/* ============================================================
   app.css — lo que solo usan las pantallas con sesion.

   La barra, el fondo con particulas, el mazo de tarjetas, el
   puente y el presupuesto. saldo.html NO carga esta hoja: es la
   pantalla de los 8 segundos y no paga nada de esto.

   Depende de base.css: todos los colores salen de sus variables.
   Aca no hay ni un color escrito a mano.
   ============================================================ */

/* ============================================================
   LA MALLA DEL FONDO — tres manchas de color, detras de todo

   Elegida mirando y no imaginando, igual que la piel Indigo: se
   pusieron tres candidatos (malla sola / con granulado / con
   aurora) en una pagina desechable y Joel eligio la malla sola al
   50% de intensidad, el 2026-08-15.

   ---- POR QUE VA EN SVG Y NO EN UNA IMAGEN ----

   Un <svg> escrito dentro del documento puede leer las variables
   de CSS: stop-color="var(--acento)". Un archivo .svg suelto o un
   background-image NO pueden. O sea que esto cambia solo con el
   tema y con la piel, y una imagen habria que rehacerla a mano
   cada vez que se toque un color. Ademas pesa un par de cientos de
   bytes y no se pixela en ninguna pantalla.

   ---- POR QUE EL MARCADO SE REPITE EN LAS TRES PAGINAS ----

   Por lo mismo que el script del tema va inline en cada <head>:
   inyectarlo con JavaScript llega DESPUES del primer dibujo y la
   pantalla pega un salto de color. Un fondo que aparece de golpe
   medio segundo tarde se ve peor que no tenerlo.

   ---- POR QUE NINGUN FILTRO DE DESENFOQUE ----

   Un radialGradient que va de color a transparente YA es una
   mancha suave. Un feGaussianBlur a pantalla completa es de las
   cosas mas caras que se le pueden pedir a un telefono, y aca no
   agrega nada.

   ---- Y POR QUE saldo.html NO LA TIENE ----

   Porque esto vive en app.css. La pantalla de los 8 segundos no
   paga profundidad visual, que es justamente el corte entre las
   dos hojas.
   ============================================================ */
.fondo {
  position: fixed;
  inset: 0;
  z-index: -3;            /* debajo de la reticula (-2) y las particulas (-1) */

  /* ---- LA FUERZA DE LAS MANCHAS, EN UN SOLO NUMERO ----

     Joel dijo el 2026-08-15 que el fondo dejo de convencerlo, sin
     saber si era la reticula o los degradados. La reticula se apago
     del todo; estas se bajaron a la mitad en vez de quitarse, porque
     apagar las dos capas de golpe deja un vacio plano y no habria
     forma de saber cual de las dos molestaba.

     Va aca y no en las opacidades de los <stop> del SVG por una
     razon practica: el bloque del SVG esta escrito IDENTICO en tres
     paginas, asi que tocarlo son tres ediciones y un md5 para
     comprobar que siguen iguales. Esta linea es una. */
  opacity: .5;
  width: 100%;
  height: 100%;
  pointer-events: none;
  /* La intensidad la eligio Joel con un deslizador, mirando. A 1
     las manchas se leen como manchas; a .5 se leen como luz. */
  opacity: .5;
}

/* EL VAIVEN. Va con transform y no moviendo las manchas de sitio,
   por la misma razon que las particulas de aca abajo: transform es
   lo unico que el navegador anima sin volver a dibujar nada.

   Dura mas de dos minutos a proposito. Medido: la mancha recorre
   47px en 130 segundos, o sea 0,38 px/s, que esta POR DEBAJO del
   umbral en que el ojo detecta que algo se movio. No se ve moverse
   y no tiene que verse: lo que hace es que la pantalla no este
   identica cuando la persona vuelve. Un fondo que se nota moverse
   es un fondo compitiendo con los numeros.

   base.css lo apaga entero bajo prefers-reduced-motion. */
.soplo { transform-box: fill-box; transform-origin: center; }
.soplo-1 { animation: soplar-1 130s ease-in-out infinite alternate; }
.soplo-2 { animation: soplar-2 170s ease-in-out infinite alternate; }
.soplo-3 { animation: soplar-3 150s ease-in-out infinite alternate; }

@keyframes soplar-1 { to { transform: translate(4%, 3%)  scale(1.08); } }
@keyframes soplar-2 { to { transform: translate(-5%, 2%) scale(1.06); } }
@keyframes soplar-3 { to { transform: translate(3%, -4%) scale(1.10); } }

/* ============================================================
   LAS PARTICULAS

   Dos capas de puntos que suben lento, a distinta velocidad. La
   diferencia de velocidad es lo que da sensacion de profundidad;
   con una sola capa se ve como una calcomania moviendose.

   ---- POR QUE ASI Y NO CON JAVASCRIPT ----

   Un motor de particulas de verdad son cientos de elementos y un
   requestAnimationFrame corriendo siempre, o sea bateria. Esto son
   DOS pseudo-elementos con un patron repetido que se desplaza con
   transform, que es lo unico que el navegador puede animar sin
   volver a dibujar nada: lo resuelve la tarjeta de video. Cero
   JavaScript y cero dependencias, que es la regla del proyecto.

   ---- POR QUE EL DESPLAZAMIENTO ES UN MULTIPLO EXACTO DEL TILE ----

   El patron se repite cada 260px (y 190px la otra capa). Si la
   animacion moviera 300px, al reiniciarse el ciclo habria un salto
   visible. Moviendo exactamente un tile (o dos), el final es
   identico al principio y el bucle es invisible.
   ============================================================ */
/* ---- LAS PARTICULAS SE MUDARON A base.css el 2026-08-17 ----

   Joel: "a la página de login/signup le faltan partículas flotantes".
   Esas cuatro pantallas —entrar, recuperar, clave-nueva y
   confirmado— cargan SOLO base.css, y cargarles esta hoja entera
   para dos pseudo-elementos habria sido 48 KB de tablero por un
   adorno.

   Se MUEVE en vez de copiarse. Copiada, `.particulas` quedaria
   definida en dos hojas que la landing carga juntas, que es
   exactamente el choque de nombres que dejo la pagina de inicio
   escrita en mayusculas durante dos semanas por culpa de `.tramo`.
   Una sola definicion, en la hoja que todas cargan.

   Quien las tiene lo decide el `<div>`, no la hoja: `saldo.html` no
   lo lleva y sigue igual de quieta. */

/* ============================================================
   LA BARRA LATERAL — la cascara de las cinco secciones
   (pendiente 48, decidido el 2026-08-20)

   Reemplaza a `.barra` en las pantallas con sesion. **`.barra` NO se
   borra**: la landing la sigue usando, con su `position: static`.

   ---- POR QUE UNA SOLA PIEZA DE HTML Y NO DOS ----

   En telefono esto tiene que ser una barra ABAJO con iconos, y ahi la
   tentacion es escribir dos bloques —uno de escritorio y otro de
   telefono— y esconder uno. **No se puede**, y no por prolijidad: el
   boton del tema se busca con `document.querySelector`, en singular,
   asi que un segundo boton en el DOM quedaria muerto **en silencio**.
   Es la clase de bug que no da error y solo se nota el dia que
   alguien toca el que no funciona.

   Entonces es UNA sola pieza y lo que se mueve es el CSS: en telefono
   el contenedor se va arriba con la marca y el tema, y el menu se
   descuelga solo al borde de abajo con `position: fixed`.

   ---- EL COSTO DEL TELEFONO, ESCRITO PARA NO OLVIDARLO ----

   La barra de abajo se come ~56px de alto en todas las pantallas, y
   con cinco destinos los iconos quedan justos. **El dia que entren la
   campanita y el calendario, esos dos NO caben abajo**: van en la
   franja de arriba, no como un sexto y septimo icono.
   ============================================================ */

.armazon {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: start;
}

.lateral {
  position: sticky;
  top: 0;
  z-index: 20;
  height: 100vh;
  width: 15rem;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  padding: 1.1rem .9rem;
  background: color-mix(in srgb, var(--fondo) 82%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-right: 1px solid var(--linea);
  /* El ancho cambia al contraer, y con el la posicion de todo lo de
     al lado. Se anima solo el ancho: animar el grid entero hace
     reflow del contenido en cada cuadro. */
  transition: width .18s ease;
}

/* La marca y el boton de plegar comparten renglon: el plegar vive
   arriba, pegado al logo, que es donde lo ponen Slack y Claude. */
.lat-cabeza {
  display: flex;
  align-items: center;
  gap: .4rem;
}
.lateral .marca { padding: .3rem .45rem; }

/* ---- LA MARCA NO SE RECORTA, Y COSTO ENCONTRARLO ----

   Aca habia un `min-width: 0` en la marca y un `overflow: hidden` +
   `text-overflow: ellipsis` en su span, puestos por precaucion. Con
   el boton de plegar al lado, el nombre salia como **"Mes bajo
   cont…"** — y la regla del proyecto es que la marca lleva
   tratamiento propio y nunca se parte.

   **Lo caro fue el diagnostico:** `scrollWidth` y `clientWidth` daban
   los dos 124 y el span "no estaba truncado" segun ese numero, asi
   que por un rato le crei al numero en vez de a la pantalla. No
   sirve para esto: **cuando el elemento es un flex item que ya se
   encogio, las dos medidas se reportan DESPUES del encogimiento y
   salen iguales aunque el ellipsis este puesto.** La prueba que si
   distingue es apagar la propiedad y volver a mirar.

   Es la leccion de siempre —medir muy bien la cosa equivocada— con
   un corolario que vale anotar: cuando el ojo y el numero se
   contradicen, el sospechoso tambien es el numero. */
.lat-cabeza .lat-plegar { margin-left: auto; }

.lat-menu {
  display: flex;
  flex-direction: column;
  gap: .2rem;
}

.lat-menu a {
  display: flex;
  align-items: center;
  gap: .7rem;
  padding: .55rem .6rem;
  border-radius: 10px;
  font-size: .92rem;
  color: var(--suave);
  text-decoration: none;
  white-space: nowrap;
  transition: background .15s ease, color .15s ease;
}
.lat-menu a:hover { background: var(--superficie-alta); color: var(--tinta); }

.lat-menu a.activa {
  background: var(--superficie-alta);
  color: var(--tinta);
  font-weight: 620;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--acento) 35%, transparent);
}

/* El icono no se encoge nunca: es lo unico que queda cuando la barra
   se contrae, asi que si cede ahi no queda nada que tocar. */
.lat-menu svg {
  width: 1.15rem;
  height: 1.15rem;
  flex: 0 0 auto;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.lat-pie {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: .6rem;
  flex-wrap: wrap;
}

/* ---- CONTRAIDA A ICONOS ----

   El estado vive en `data-lateral` sobre el `<html>` y lo escribe un
   script inline en el `<head>`, igual que el tema y por la misma
   razon: en un archivo aparte llegaria despues del primer dibujo y la
   barra pegaria un salto de ancho al cargar cada pagina.

   ---- Y VA DENTRO DE UN `min-width`, QUE NO ES PROLIJIDAD ----

   **Una media query NO agrega especificidad.** `:root[data-lateral=
   "iconos"] .lateral` pesa 0-2-1 y la regla de telefono que la tenia
   que anular pesaba 0-1-0, asi que **le ganaba dentro de la media
   query**: con la barra contraida, un telefono mostraba los cinco
   iconos apilados en una columna de 62px encima del contenido, y la
   barra de abajo no aparecia nunca.

   Se arregla acotando el estado al escritorio, que ademas es lo
   correcto: en telefono no hay nada que contraer —`.lat-plegar` va
   oculto— asi que estas reglas no tienen por que existir ahi.

   Es la cuarta vez que la especificidad muerde en este proyecto
   (`.descargo`, `.plan-nota`, `.plan-o`) y la primera con una media
   query de por medio. Las tres anteriores solo cambiaban un tamano de
   letra; esta rompio una pantalla entera. */
@media (min-width: 768px) {
  /* ---- EL ANCHO CONTRAIDO SALE DE UNA CUENTA, NO DE UN OJO ----

     El interruptor de tema mide `3.6rem` (57,6px) y lleva
     `flex-shrink: 0`, asi que no cede. Con la barra en 3.9rem y
     .9rem de relleno a cada lado quedaban **33,6px de contenido** y
     el interruptor se salia por el borde — se veia colgando fuera de
     la barra.

     Se arregla por los dos lados: la barra pasa a 4.4rem con menos
     relleno (52,8px utiles) y el interruptor se achica a 2.9rem
     (46,4px), que deja 6,4px de aire.

     Se achica con `width`/`height` y **no con `transform: scale`**:
     un transform le daria su propia capa al elemento, que es
     exactamente la familia de problemas que costo el
     `backdrop-filter` de la barra de telefono. No hace falta
     arriesgarse por dos propiedades. */
  :root[data-lateral="iconos"] .lateral { width: 4.4rem; padding-inline: .55rem; }
  :root[data-lateral="iconos"] .lateral .marca span,
  :root[data-lateral="iconos"] .lat-menu a span,
  :root[data-lateral="iconos"] .lat-salir span { display: none; }
  :root[data-lateral="iconos"] .lat-menu a,
  :root[data-lateral="iconos"] .lat-salir { justify-content: center; padding-inline: 0; }

  /* La marca y el plegar se apilan: en 52,8px no entran a lo ancho el
     punto de la marca y el boton. */
  :root[data-lateral="iconos"] .lat-cabeza { flex-direction: column; gap: .5rem; }
  :root[data-lateral="iconos"] .lat-cabeza .lat-plegar { margin-left: 0; }
  :root[data-lateral="iconos"] .lat-plegar svg { transform: scaleX(-1); }

  :root[data-lateral="iconos"] .lat-pie { flex-direction: column; gap: .5rem; align-items: center; }
  /* Se achica redefiniendo las variables que la pildora publica, NO
     su `width` y su `height`: tocando esos dos, la perilla se queda
     con el desplazamiento del tamano grande y deja de caer sobre los
     iconos. El porque completo esta en `base.css`. */
  :root[data-lateral="iconos"] .lat-pie .tema {
    --tema-ancho: 2.9rem;
    --tema-alto: 1.7rem;
    --tema-perilla: 1.2rem;
  }
  :root[data-lateral="iconos"] .lat-pie .tema-icono svg { width: .8rem; height: .8rem; }
}

.lat-plegar {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 1.9rem;
  height: 1.9rem;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--suave);
  cursor: pointer;
}
.lat-plegar:hover { background: var(--superficie-alta); color: var(--tinta); }
.lat-plegar svg { width: 1.05rem; height: 1.05rem; stroke: currentColor; fill: none; stroke-width: 2; }

/* ---- CERRAR SESION ----

   Se dibuja como un destino mas del menu y no como un enlace
   subrayado: con un icono al lado, el subrayado de `.enlace` lo
   dejaba a medio camino entre las dos cosas. */
.lat-salir {
  display: flex;
  align-items: center;
  gap: .7rem;
  width: 100%;
  padding: .5rem .6rem;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--suave);
  font: inherit;
  font-size: .88rem;
  text-align: left;
  cursor: pointer;
}
.lat-salir:hover { background: var(--superficie-alta); color: var(--tinta); }
.lat-salir svg {
  width: 1.15rem; height: 1.15rem; flex: 0 0 auto;
  stroke: currentColor; fill: none;
  stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round;
}

/* Dentro del armazon el lienzo se centra en la columna que le queda,
   no en la ventana: sin esto quedaria corrido a la derecha por el
   ancho de la barra. */
.armazon .lienzo { margin-inline: auto; width: 100%; }


/* ---- TELEFONO: la barra se parte en dos ----

   Arriba la identidad (marca, tema, salir) y abajo la navegacion, que
   es donde llega el pulgar. Las dos van `fixed`, asi que el lienzo
   tiene que reservarles el alto o el contenido se les mete debajo. */
@media (max-width: 767px) {
  .armazon { display: block; }

  .lateral {
    position: fixed;
    inset: 0 0 auto 0;
    height: auto;
    width: auto;
    flex-direction: row;
    align-items: center;
    gap: .75rem;
    padding: .55rem 1rem;
    border-right: 0;
    border-bottom: 1px solid var(--linea);

    /* ---- SIN `backdrop-filter`, Y ES OBLIGATORIO ----

       **`backdrop-filter` crea un containing block para los
       descendientes `position: fixed`.** Con el puesto, el
       `.lat-menu` de abajo dejaba de anclarse a la ventana y se
       anclaba a ESTA barra: `inset: auto 0 0 0` lo mandaba al borde
       inferior de una franja de 90px, o sea que los cinco iconos
       aparecian ARRIBA y la barra de abajo no existia nunca.

       Es la misma propiedad que en la semana 5 aplano el contexto 3D
       de la tarjeta del heroe. La lista de lo que rompe cosas gana
       una entrada: **`filter`, `backdrop-filter`, `transform`,
       `perspective`, `will-change` y `contain` tambien secuestran a
       los hijos `fixed`**, no solo al 3D.

       El blur se le da al `.lat-menu`, que no tiene ningun
       descendiente fijo, y aca el fondo va mas opaco para compensar
       que ya no difumina lo que pasa por debajo. */
    background: color-mix(in srgb, var(--fondo) 94%, transparent);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  .lat-pie { margin-left: auto; margin-top: 0; flex-wrap: nowrap; }

  /* En telefono no hay nada que contraer: la barra ya esta partida en
     dos franjas y el menu vive abajo. */
  .lat-plegar { display: none; }

  /* Y "Cerrar sesion" se queda en su icono. Medido a 375px: la franja
     da 343px utiles y entre la marca, el interruptor y el texto
     completo se pasaba. El nombre no se pierde —va en `aria-label` y
     en `title`— y el icono de salida es el mismo que en escritorio,
     donde si se lee entero. */
  .lat-salir { width: auto; padding: .4rem; }
  .lat-salir span { display: none; }

  .lat-menu {
    position: fixed;
    inset: auto 0 0 0;
    flex-direction: row;
    gap: 0;
    padding: .35rem .4rem calc(.35rem + env(safe-area-inset-bottom));
    background: color-mix(in srgb, var(--fondo) 92%, transparent);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-top: 1px solid var(--linea);
  }

  /* Cinco columnas iguales: el destino no puede ser mas facil de
     tocar por tener el nombre mas corto. */
  .lat-menu a {
    flex: 1 1 0;
    min-width: 0;
    flex-direction: column;
    gap: .18rem;
    padding: .35rem .1rem;
    font-size: .66rem;
    text-align: center;
  }
  /* El nombre se queda: un icono solo, sin etiqueta, obliga a
     adivinar — y "Fondos" y "Tasas" no tienen icono evidente. */
  .lat-menu a span {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
  }
  .lat-menu a.activa { box-shadow: none; background: none; color: var(--acento); }

  .armazon .lienzo { padding-top: 4.2rem; padding-bottom: 5.5rem; }
}


/* ============================================================
   LA BARRA — pegada arriba, ancho completo
   ============================================================ */
.barra {
  position: sticky;
  /* Ancla del menu, que va centrado en absoluto. */
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  padding: .85rem 1.5rem;
  background: color-mix(in srgb, var(--fondo) 82%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--linea);
}

/* El menu va centrado en la BARRA entera, no en el hueco que dejan
   la marca y el boton de salir. Por eso se posiciona en absoluto:
   en el flujo normal quedaria corrido a un lado, porque los dos
   extremos no miden lo mismo —y encima cambian, "Hola, Joel" no
   ocupa lo que "Hola, Maria Fernanda"—. Asi el eje del menu cae
   siempre en el centro de la pantalla, que es donde el ojo lo
   busca y donde el pulgar llega. */
.menu {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: .3rem;
}

.menu a {
  padding: .45rem .9rem;
  border-radius: 9px;
  font-size: .9rem;
  color: var(--suave);
  text-decoration: none;
  transition: background .15s ease, color .15s ease;
}
.menu a:hover { background: var(--superficie-alta); color: var(--tinta); }

.menu a.activa {
  background: var(--superficie-alta);
  color: var(--tinta);
  font-weight: 620;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--acento) 35%, transparent);
}

.barra-fin { margin-left: auto; display: flex; align-items: center; gap: 1rem; }

/* ============================================================
   EL LIENZO — el ancho de verdad
   ============================================================ */
.lienzo {
  position: relative;
  max-width: 76rem;
  margin: 0 auto;
  padding: 2rem 1.5rem 5rem;
}

.saludo { font-size: 1.8rem; font-weight: 660; }
.saludo-pie { color: var(--suave); font-size: .95rem; margin-top: .3rem; }

/* Dos columnas en escritorio, una en telefono, sin media query:
   auto-fit se encarga solo. */
.rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(19rem, 100%), 1fr));
  gap: 1.25rem;
  margin-top: 1.75rem;
}

.seccion-cabeza {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; margin: 2.5rem 0 1.1rem;
}
.seccion-cabeza .secundario, .seccion-cabeza .principal { margin-top: 0; width: auto; }

/* Cada bloque del presupuesto separado del anterior: son pasos
   distintos y sin la linea se leen como uno solo muy largo. */
.seccion { margin-top: 2.5rem; padding-top: 1.5rem; border-top: 1px solid var(--linea); }

/* El lienzo mide 76rem, y eso esta bien para un mazo de tarjetas y
   muy mal para un formulario: a ese ancho el ojo pierde el renglon
   entre la etiqueta de la izquierda y el campo de la derecha.
   Pero una sola columna angosta deja media pantalla vacia a la
   derecha y se ve desbalanceado. La salida es poner los bloques de
   a dos: cada uno conserva su ancho legible y entre los dos llenan
   el lienzo.
   En telefono auto-fit los apila solo, sin media query. */
.angosta { max-width: 38rem; }

.dos-columnas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(24rem, 100%), 1fr));
  gap: 0 2.5rem;
  align-items: start;
}
/* La primera fila de la rejilla no necesita su linea de arriba: ya
   la separa del puente el borde de la seccion anterior. */
.dos-columnas > .seccion:nth-child(-n+2) { margin-top: 1.5rem; }

/* ---- LOS FONDOS OCUPAN LA FILA ENTERA ----

   Llegaron a esta pantalla el 2026-08-16, desde app.html. Van en su
   propia fila y no en una de las dos columnas por dos razones:

   - Los recuadros del capital son una rejilla propia, y una rejilla
     de recuadros dentro de media pantalla deja uno por fila. Ancha
     caben tres o cuatro, que es como se disenaron.
   - Los quiero DEBAJO de "Tus ingresos", no al lado de otra cosa.
     Primero lo que se mueve este mes —lo que entra y lo que sale— y
     despues lo que ya esta guardado.

   `grid-column: 1 / -1` es lo que hace que un hijo de la rejilla
   ocupe de la primera columna a la ultima, sea cual sea el numero
   de columnas que decida auto-fit. */
/* La regla de `#seccion-capital` que vivia aca murio el 2026-08-18: los
   fondos se mudaron a app.html (pendiente 47, etapa 1) y alli la seccion
   es hija directa del lienzo, no de una rejilla de dos columnas. Un
   selector que no aplica a nada es peor que uno feo: el dia que alguien
   escriba esa clase creyendo que hace algo, se lleva un estilo que nadie
   diseño para su caso. */

/* ============================================================
   EL PANEL — la caja del numero grande
   ============================================================ */
/* El hover es el MISMO que el de las columnas de la landing, y eso
   es a propósito: es la misma app y una caja no puede reaccionar de
   dos maneras distintas según la pantalla en que esté. */
.panel {
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-radius: var(--curva);
  padding: 1.4rem;
  box-shadow: var(--sombra);
  transition: border-color .2s ease, box-shadow .25s ease, transform .2s ease;
}
.panel:hover {
  border-color: color-mix(in srgb, var(--acento) 55%, var(--linea));
  box-shadow: var(--sombra-alta);
  transform: translateY(-3px);
}

.panel-titulo {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; margin-bottom: .9rem;
}
.panel-titulo h2 {
  font-size: .8rem; font-weight: 620; letter-spacing: .09em;
  text-transform: uppercase; color: var(--suave);
}
.moneda { font-size: .72rem; letter-spacing: .1em; color: var(--suave); }

/* El nombre del tramo, debajo del número grande. Un porcentaje solo
   no le dice nada a quien no sabe de crédito: "45%" es un dato,
   "45%, Alto" es una lectura. Va del mismo color que el número para
   que se lean como una sola cosa y no como dos datos distintos. */
.tramo {
  /* Pegado al número pero no encima: con -.35rem las mayúsculas del
     tramo casi tocaban la base de las cifras. */
  margin-top: -.05rem;
  font-size: .82rem; font-weight: 640;
  letter-spacing: .06em; text-transform: uppercase;
}

/* El numero grande. Es lo unico que mucha gente va a mirar. */
.numeron {
  font-size: 3.2rem; font-weight: 700; letter-spacing: -.03em; line-height: 1;
  font-variant-numeric: tabular-nums;
}

/* ============================================================
   EL NUMERO GRANDE EN TEMA CLARO: COLOR VIVO CON CONTORNO

   La idea es de Joel: "si dejas el mismo amarillo semaforo en el
   tema claro y bordeas ese numero con un borde negro para separarlo
   del fondo". Se probo mirandolo y funciona: el 44% vuelve a ser
   amarillo de semaforo y se lee perfectamente.

   ---- POR QUE ESTO NO ES UNA TRAMPA DE CONTRASTE ----

   El amarillo solo da 1,4 sobre blanco, o sea invisible. Lo que lo
   hace legible no es el relleno sino el CONTORNO, que es tinta
   sobre blanco: la forma de la letra queda definida por una linea
   con contraste de sobra y el color pasa a ser lo de adentro. Es lo
   mismo que hace un subtitulo de television amarillo sobre
   cualquier imagen.

   `paint-order: stroke fill` pinta el trazo DEBAJO del relleno. Sin
   eso el contorno se dibuja centrado en el borde del glifo y se
   come la mitad del grosor de la letra hacia adentro, que en una
   cifra de 3,2rem se ve como si hubiera adelgazado.

   ---- SOLO ACA, Y POR QUE ----

   Solo en el numero grande y solo en los cuatro tramos:

   - No en el nombre del tramo ("ALTO"): a .7rem un contorno de
     1,2px es mas grueso que los palos de la letra y queda una
     mancha. Ahi el color apagado se lee bien y no hace falta.
   - No en las cifras de "Tu plata", que llevan .numeron sin ningun
     nivel-*: un contorno oscuro sobre una letra ya oscura solo la
     ensucia. Por eso se listan las cuatro clases en vez de escribir
     `.numeron` a secas.
   - No en el tema oscuro, donde los colores ya son los vivos y
     brillan solos.
   ============================================================ */
:root[data-tema="claro"] .numeron.nivel-excelente,
:root[data-tema="claro"] .numeron.nivel-bien,
:root[data-tema="claro"] .numeron.nivel-alto,
:root[data-tema="claro"] .numeron.nivel-critico {
  color: var(--vivo);
  /* ---- EL GROSOR: .047em, o sea 2,4px sobre 3,2rem ----

     Empezo en 1,2px y Joel dijo que se veia "como mal hecho", sin
     poder explicar por que. Se compararon cuatro grosores uno al
     lado del otro y se ve de una: a 1,2 el contorno no es un
     contorno, es un hilo irregular que sigue el borde de la letra y
     parece un defecto de dibujo. Un trazo tiene que verse
     deliberado o no verse; el punto medio es el que se lee como un
     error.

     A 2,4 la letra se sostiene y el contorno se lee como una
     decision. A 3 empiezan a cerrarse los huecos del 4 y de los dos
     circulos del %, y ahi la cifra pierde legibilidad, que es lo
     contrario de lo que el contorno vino a hacer.

     Va en em y no en px para que acompanie a la letra si algun dia
     el numero grande cambia de tamano en telefono. */
  -webkit-text-stroke: .047em var(--tinta);
  paint-order: stroke fill;
}

/* EL NÚMERO GRANDE CUANDO ES PLATA Y NO UN PORCENTAJE.

   Los paneles de país nunca tuvieron este problema: ahí el número
   grande es una utilización, y "100%" es lo más largo que existe. Una
   cifra de dinero no tiene techo — "ARS 125.400.000" se sale del
   panel a 3.2rem, y eso no es un caso raro sino un sueldo argentino
   de dos meses.

   Se encoge por tramos según cuántos caracteres trae, y lo decide
   pintar-capital.js porque el largo del texto es un dato que el CSS
   no puede leer. Tres tramos y no un ajuste continuo: así dos
   recuadros con cifras parecidas se ven del mismo tamaño, y una
   columna de números que cambian de tamaño uno a uno se lee como si
   unos importaran más que otros.

   El último tramo además deja partir el número si aún así no cabe:
   mejor dos renglones que una cifra cortada por la mitad. */
.numeron.plata-larga  { font-size: 2.4rem; }
.numeron.plata-huge   { font-size: 1.8rem; overflow-wrap: anywhere; }

/* ============================================================
   LOS RECUADROS DE "TU PLATA", ALINEADOS ENTRE SI

   Joel: «el texto "En un solo lugar" persigue el tamaño del monto
   cuando son muchas cifras, entonces queda desalineado de los otros
   saldos. El nombre de la moneda y ese texto siempre deberían estar
   alineados en cada caja, y lo único que cambie de tamaño (y siempre
   centrado en vertical) sea el monto.»

   ---- POR QUE PASABA ----

   Las tres cosas estan una debajo de otra en el flujo normal, y la
   del medio cambia de tamano: tamanoCifra() la baja de 3,2rem a 2,4
   o a 1,8 segun cuantos digitos tenga. Un peso argentino ocupa mas
   renglones que un dolar, asi que lo de abajo arranca mas abajo. No
   era un error de nadie: es lo que hace el flujo normal.

   ---- LA SOLUCION ----

   El recuadro pasa a ser una columna de tres piezas donde la del
   medio ES la que estira. El nombre queda pegado arriba, la pista
   pegada abajo —y como la rejilla estira todos los recuadros al alto
   del mas alto, quedan en la misma linea de una caja a la otra— y el
   monto flota en el medio, centrado en vertical, cambiando de tamano
   sin arrastrar a nadie.

   El min-height es lo que evita que un recuadro con una cifra corta
   se encoja tanto que la rejilla deje de estirar. Sale de la cifra
   mas alta posible: 3,2rem de letra con su interlineado.

   Solo aplica a .panel-capital y no a .panel: los paneles de pais
   tienen barra, escalera y una caja de datos abajo, y ahi el numero
   grande NO debe flotar en el medio.
   ============================================================ */
.panel-capital {
  display: flex;
  flex-direction: column;
}

.panel-capital .numeron {
  flex: 1;
  min-height: 3.6rem;
  /* El texto suelto adentro de un flex se vuelve un item anonimo, y
     por eso align-items lo centra sin necesidad de envolverlo. */
  display: flex;
  align-items: center;
  margin: .55rem 0;
}

/* DOS FAMILIAS, y la diferencia importa.

   Las de abajo llevan el nombre del TRAMO y son el semáforo de
   utilización: las escribe nivel(), y si mañana cambian los cortes
   cambian con ellas.

   Las de arriba llevan el nombre del COLOR y son decorativas: los
   baldes del reparto y los ejemplos de la landing las usan para
   pedir "verde" o "ámbar" sin estar hablando de ninguna
   utilización. Si les hubiera puesto nombre de tramo, un balde de
   ahorro pintado "nivel-excelente" diría algo que no es. */
.nivel-bueno { color: var(--bueno); }
.nivel-medio { color: var(--medio); }
.nivel-malo  { color: var(--malo); }
.nivel-desconocido { color: var(--suave); }

/* Cada clase pone DOS cosas: el color de la letra, que se apaga en
   el tema claro para poder leerse, y --vivo, que es el mismo color
   de semaforo en los dos temas y lo usan las formas —la barra, la
   escalera, la franja del puente—. Van juntas en un solo sitio a
   proposito: repartidas por regla, un dia alguien cambia una y no
   la otra, y la barra deja de coincidir con su numero. */
.nivel-excelente { color: var(--bueno); --vivo: var(--bueno-vivo); }
.nivel-bien      { color: var(--bien);  --vivo: var(--bien-vivo); }
.nivel-alto      { color: var(--medio); --vivo: var(--medio-vivo); }
.nivel-critico   { color: var(--malo);  --vivo: var(--malo-vivo); }

/* ============================================================
   EL RIEL — la barra de progreso

   El relleno hereda el color con currentColor, asi que la clase
   nivel-* se pone en el relleno y no hace falta un color por
   franja aca.
   ============================================================ */
.riel {
  position: relative;
  height: .55rem;
  margin: 1.1rem 0 .4rem;
  background: var(--fondo);
  border-radius: 999px;
  overflow: hidden;

  /* ---- EL CONTORNO, y por que es un border y no un box-shadow ----

     Un inset box-shadow se pinta encima del fondo pero DEBAJO de los
     hijos, asi que el relleno lo taparia justo en la parte llena, y
     el marco solo se veria en el pedazo vacio. Un borde de verdad
     queda fuera de la caja de contenido: el relleno no puede
     alcanzarlo y el aro se ve entero.

     El alto subio de .5 a .55rem para compensar el pixel que se
     lleva el borde por arriba y por abajo — sin eso la barra
     adelgaza y el cambio se nota mas que el marco. */
  border: 1px solid var(--borde-riel);
}

/* El relleno usa --vivo y no currentColor: es una forma, no una
   letra, asi que puede llevar el color de semaforo entero tambien
   en el tema claro. El resplandor tambien, y ahi se nota mas: un
   halo del color apagado no es un halo. */
.riel-relleno {
  height: 100%;
  border-radius: 999px;
  background: var(--vivo, currentColor);
  box-shadow: 0 0 12px var(--vivo, currentColor);
}

/* ---- SIN USAR desde el 2026-08-15 ----
   El <div class="riel-meta"> salio de js/pintar.js cuando entro la
   escalera: la meta del mes siempre cae en un borde de tramo, asi
   que la marca repetia una separacion que ya esta tres pixeles mas
   abajo, y encima se leia como "estas aqui" en vez de "apunta
   aqui". El porque completo esta en pintar.js, donde iba el div.
   La regla se queda porque el sandwich de tres franjas costo
   encontrarlo y sin git rehacerlo es escribirlo de nuevo. Para
   volver a usarla, se devuelve el div.

   La marca de la meta: una linea vertical sobre el riel, para que
   se vea de un golpe si el relleno la paso o no.

   NO es una linea sola: son tres franjas de 1px, oscura-clara-oscura.
   Con una linea clara al 60% de opacidad desaparecia sobre el ambar
   del tramo Alto en tema oscuro —el color de fondo y el de la marca
   quedaban casi igual de claros— y justo ahi es donde mas hace falta
   verla, porque es el tramo desde el que hay que salir. Con el
   sandwich, el nucleo claro se ve contra el ambar y los bordes
   oscuros se ven contra el riel vacio. Funciona sobre los cuatro
   tramos y en los dos temas, sin una regla por color.

   Va con el ancho en el gradiente y no con un border, porque el
   riel tiene overflow hidden y un borde se recortaria. */
.riel-meta {
  position: absolute; top: 0;
  width: 4px; height: 100%;
  margin-left: -1px;
  background: linear-gradient(90deg,
    var(--fondo) 0 1px, var(--tinta) 1px 3px, var(--fondo) 3px 4px);
}

/* ============================================================
   LA ESCALERA — los cuatro tramos debajo del riel

   Cada peldano mide lo que mide su tramo en el riel (10, 20, 20 y
   50 de flex-grow), asi que cae justo debajo del pedazo de barra
   que le toca y el relleno de arriba senala solo en cual esta la
   persona. El HTML lo arma escalera() en js/pintar.js, leyendo
   TRAMOS: aca no hay ni un limite ni un color escrito a mano.

   ---- CADA UNO DE SU COLOR, PERO BAJITO ----

   Los cuatro se dibujan siempre —es la regla 4: una escalera para
   subir, no un permiso para quedarse— y cada uno lleva SU color,
   porque si no dejaria de ser una leyenda de colores. Lo que los
   separa no es el tono sino la intensidad: los ajenos van al 40% y
   con la barrita fina, el propio va entero, mas grueso y con la
   cifra encendida. Asi se ve la escala completa sin que cinco cosas
   de color compitan con el numero grande.

   El propio lleva TRES senales y no una: color pleno, barra mas
   gruesa y el numero en --tinta. Un color solo no es un dato — es
   la misma regla por la que la tarjeta cerrada lleva una insignia
   ademas del gris.

   ---- SOLO EL RANGO ----

   El nombre de cada tramo no cabe: la celda de 0–9 mide el 10% del
   panel. Y no hace falta, porque el nombre del tramo propio ya esta
   arriba en grande. El porque completo esta en escalera(), en
   js/pintar.js.
   ============================================================ */
.escalera {
  display: flex;
  gap: 3px;
  margin: 0 0 .5rem;
  padding: 0;
  list-style: none;
}

.peldano {
  /* El flex-basis en 0 es lo que hace que mande el flex-grow: sin
     el, cada celda arranca del ancho de su texto y las
     proporciones del riel se pierden. */
  flex-basis: 0;
  min-width: 0;
  padding-top: .28rem;
  /* La barrita de arriba es el peldano; el numero lo nombra. Va con
     --vivo —el color de semaforo, igual en los dos temas— bajado con
     color-mix y no con opacity, porque opacity sobre el <li> se
     llevaria tambien el texto. */
  border-top: 2px solid color-mix(in srgb, var(--vivo, currentColor) 40%, transparent);
  font-size: .62rem;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
}

/* ---- POR QUE EL NUMERO VA EN UN <span> ----
   El <li> NO puede llevar `color`: ese color es el del tramo y es de
   donde el borde saca el suyo con currentColor. Si se le escribiera
   encima para apagar el texto, el borde se apagaria con el y la
   escalera perderia los colores. El span separa las dos cosas: el
   borde toma el color del tramo del padre, el numero pone el suyo. */
.peldano > span { color: var(--suave); }

/* El tuyo. El color viene de la clase nivel-* que le puso
   escalera(), o sea la misma que pinta el numero grande: no se
   pueden contradecir. */
.peldano.aqui {
  border-top-width: 3px;
  border-top-color: var(--vivo, currentColor);
  font-weight: 680;
}
.peldano.aqui > span { color: var(--tinta); }

.riel-pie { color: var(--suave); font-size: .78rem; }

/* ============================================================
   EL MAZO — las tarjetas dibujadas

   Se GENERAN, nunca se usa el logo del banco: un logo ajeno es
   marca registrada y obligaria a mantener una lista de bancos por
   pais, que rompe la regla de que agregar un pais sea insertar una
   fila. El tono sale de la columna tarjetas.tono (sql/27), asi que
   esto funciona con cualquier banco del mundo desde el primer dia.
   ============================================================ */
.mazo {
  display: grid;
  /* 21rem y no 19: la cara de atras es un formulario y a 19rem los
     campos quedan en un canal demasiado angosto para escribir. */
  grid-template-columns: repeat(auto-fill, minmax(min(21rem, 100%), 1fr));
  gap: 1.5rem;
  align-items: start;
}

/* El aire que deja el scrollIntoView de mazo.js al abrir una tarjeta
   nueva. Sin esto, 'start' pega el borde de arriba de la tarjeta al
   borde de la ventana y la barra pegajosa —que mide unos 4rem y esta
   por encima de todo— le tapa la primera fila del formulario.
   Va como scroll-margin y no como un numero dentro del JavaScript
   porque el alto de la barra lo decide esta hoja: si algun dia
   crece, el que tiene que enterarse es el CSS y no un renglon
   perdido en mazo.js. */
.mazo-item {
  display: flex; flex-direction: column; gap: .7rem; scroll-margin-top: 5.5rem;
  /* ---- EL APILADO, DESDE QUE LA ESCENA NO RECORTA ----
     Sin recorte, el zoom de un boton y la panza del giro salen de
     la caja — y sin z-index saldrian POR DEBAJO de la tarjeta
     siguiente, que en el DOM va despues. Se veria como que la
     vecina le muerde la esquina, que es el mismo sintoma que
     veniamos de arreglar.

     `:focus-within` y no solo `:hover` porque girar() enfoca un
     campo del reverso: si el mouse se va a mitad de la vuelta, el
     hover se apaga y la tarjeta caeria de capa EN MEDIO de la
     animacion. El foco dura lo que dura el formulario abierto.

     Un z-index en un ancestro de `.escena` NO aplana el 3D: la
     cadena empieza en la escena y sigue hacia adentro. */
  position: relative;
  z-index: 0;
}
.mazo-item:hover,
.mazo-item:focus-within { z-index: 2; }

/* El contenedor da la perspectiva; sin ella el giro se ve plano.
   Va acá y no en .tarjeta a proposito: la perspectiva tiene que
   vivir en el PADRE del elemento que rota. */

/* ---- SIN `border-radius`, QUE RECORTABA LOS BOTONES ----
   La curva iba aca porque la escena SOLO contenia el plastico, que
   tiene esa misma curva. Desde el 2026-08-22 contiene tambien la
   fila de botones, y los de las puntas llegan al borde: la curva de
   la escena les comia la esquina de afuera. Lo vio Joel.

   ---- Y SIN `overflow: clip`, QUE HACIA LO MISMO UN DIA DESPUES ----

   Quitarle la curva no alcanzo: el recorte seguia puesto, y un
   recorte recto corta igual que uno curvo. Joel lo vio el
   2026-08-23, por DOS caminos que resultaron ser el mismo:

     1. "al poner el mouse sobre Editar y Borrar, al tener un leve
        zoom, quedan por fuera del recuadro y se ven cortados".
        Los botones crecen `scale(1.03)` y encienden `--neon` al
        pasar el mouse —eso es de base.css y es de toda la app—, y
        los de las puntas arrancan pegados al borde de la escena.

     2. "al girar se pierde un pedacito en la parte superior
        derecha, como detras de una linea negra invisible".
        Esa linea negra ES este recorte. Con `perspective`, la mitad
        de la tarjeta que se acerca al ojo se proyecta MAS GRANDE, y
        lo que crece por arriba y por abajo caia fuera de la caja.

   ---- POR QUE SE PUEDE QUITAR, Y POR QUE HABIA QUE QUITARLO ----

   Estaba aca para "recortar el formulario mientras la caja todavia
   no termino de crecer". **La caja dejo de crecer el 2026-08-22**,
   cuando las dos caras pasaron a compartir celda de grid y a medir
   lo mismo: en reposo ya no hay nada que sobresalga.

   Es la regla escrita del proyecto: una precaucion escrita para un
   comportamiento que ya no existe se convierte en un defecto. Van
   dos en dos dias sobre esta misma regla —primero la curva, ahora
   el recorte— y las dos las encontro Joel mirando la pantalla.

   Lo que ahora sobresale es lo que TIENE que verse: el zoom de un
   boton y la panza del giro. Por eso la escena no recorta y el
   apilado lo resuelve el z-index de `.mazo-item`, abajo. */
.escena { perspective: 1600px; }

.tarjeta {
  position: relative;
  /* ---- LAS DOS CARAS SUPERPUESTAS EN UNA CELDA ----
     Las dos ocupan `grid-area: 1/1`, asi que la tarjeta mide **la
     mas alta de las dos** y las dos miden eso. Ningun calculo y
     ninguna altura escrita: girar no puede cambiar el alto porque
     las dos caras ya comparten celda.
     Con `position: absolute` no servia —un absoluto no aporta
     altura— y habia que elegir a mano cual iba en el flujo, que es
     lo que hacia falta cuando el reverso crecia. */
  display: grid;
  transform-style: preserve-3d;
  /* ---- SOLO EL GIRO, DESDE EL 2026-08-22 ----
     Aca vivia una coreografia de dos tiempos: la tarjeta giraba en
     600 ms y la ALTURA arrancaba a los 250 y tardaba 350, porque el
     reverso era un formulario largo y un plastico convirtiendose de
     golpe en una columna se veia barato.
     **Las dos caras miden lo mismo**, asi que no hay altura que
     animar. Con ella se fueron la medicion en JavaScript, el
     `height` inline y el temporizador de 640ms que lo liberaba. */
  transition: transform .6s cubic-bezier(.2,.7,.3,1);
}
.tarjeta.girada { transform: rotateY(180deg); }


.cara {
  grid-area: 1 / 1;
  display: flex; flex-direction: column;
  padding: 1.15rem;
  border-radius: var(--curva);
  backface-visibility: hidden;
  /* ---- POR QUE ADEMAS DEL backface-visibility ----
     backface-visibility se cae en cuanto algo adentro del contexto
     3D crea su propia capa: un backdrop-filter, un filter, un
     overflow. Cuando eso pasa, las dos caras se dibujan encima y
     la de atras se ve al reves. Paso de verdad, con el
     backdrop-filter del boton de girar.
     La visibilidad es el cinturon: la cara que no toca desaparece a
     media vuelta y el efecto sale bien aunque el 3D se aplane.

     ---- EL RETRASO ES .12s Y NO .3s, Y EL .3 ERA UN ERROR ----

     Decia .3s con este argumento: "la mitad de los .6s del giro".
     **La mitad del TIEMPO no es la mitad del RECORRIDO**: la curva
     `cubic-bezier(.2,.7,.3,1)` arranca rapidisimo, asi que la tarjeta
     cruza los 90 grados mucho antes de la mitad del reloj.

     Medido en el navegador, no calculado: **cruza a los 119 ms** y el
     visibility cambiaba a los 338. En el medio la cara de adelante ya
     estaba oculta por `backface-visibility` y la de atras todavia por
     `visibility` — **219 ms sin ver nada**. Joel lo describio exacto:
     "desaparece antes de los 90 y vuelve a aparecer despues".

     No se veia hasta ahora porque en Safari el backface no funcionaba
     y la cara de adelante seguia dibujandose, tapando el hueco. Al
     arreglar el backface, el hueco quedo al descubierto: **un arreglo
     puede destapar un bug que otro bug estaba escondiendo.**

     ---- Y VA UN PELO ANTES DEL CRUCE, NO JUSTO ENCIMA ----

     Con .12s —el cruce medido— quedaban 2 cuadros ciegos: entre que
     se aplica la clase y el primer repintado hay latencia, asi que el
     visibility llegaba ~35ms tarde.

     El error no es simetrico y por eso la salida es adelantarse:
     si el visibility se ADELANTA, la cara de atras ya esta "visible"
     unos milisegundos antes de los 90 grados y **el backface la sigue
     tapando** hasta el cruce, asi que no se ve nada raro. Si se
     ATRASA, no hay nada que tape el hueco. Ante la duda, antes.

     Si algun dia se toca la curva o la duracion del giro, hay que
     volver a medir este numero. No se deduce leyendo. */
  transition: visibility 0s linear .09s;
}
.tarjeta:not(.girada) .cara-detras { visibility: hidden; }
.tarjeta.girada       .cara-frente { visibility: hidden; }

/* ---- QUIEN MANDA LA ALTURA, DESDE EL 2026-08-22 ----

   La manda `.cara-frente`, y las dos caras son absolutas dentro de
   ella. Antes la cara visible iba en el flujo y la otra encima, para
   que la tarjeta midiera lo que midiera cada una; ahora **miden lo
   mismo por definicion** y eso deja de hacer falta.

   El alto sale de la proporcion real del plastico MAS la fila de
   botones, porque las dos cosas giran juntas: eso es "el recuadro"
   que pidio Joel. */
.cara-frente {
  position: relative;
  color: #fff;
  display: flex;
  flex-direction: column;
  /* El plastico arriba y los botones abajo. Si el reverso pide mas
     alto que los dos juntos, el aire sobrante queda en el medio en
     vez de estirar el plastico, que tiene una proporcion que
     respetar. */
  justify-content: space-between;
  gap: .55rem;
  padding: 0;
  background: none;
  box-shadow: none;
}

/* El plastico de verdad: lo que lleva el degradado y la proporcion. */
.plastico-cara {
  position: relative;
  /* ---- CRECE SI SOBRA AIRE ----
     El recuadro mide lo que pide el reverso, que es mas que el
     plastico mas los botones. Con el plastico rigido quedaba un
     hueco de 100px en el medio, que se ve como un error de maquetado.
     Asi el aire se lo lleva el plastico: la proporcion cede —de
     1,586 a ~1,4— y eso no se nota, mientras que un agujero si. */
  /* `1 1 auto` con un tope: si el reverso pide un poco mas de alto,
     el plastico lo absorbe hasta 1,45 de proporcion y despues no
     mas. Estirado sin limite dejaba de parecer una tarjeta y pasaba
     a ser un cuadrado. */
  /* `1 0 auto`: puede CRECER si sobra aire, nunca ENCOGER. Con
     `1 1 auto` cedia por debajo de su proporcion —en escritorio
     salia a 2,13 en vez de 1,586, o sea una tarjeta aplastada—
     porque el reverso pedia menos alto que el plastico natural y el
     flex lo apretaba para igualar. */
  flex: 1 0 auto;
  aspect-ratio: 1.586;          /* la proporcion real de una tarjeta */
  min-height: 11.5rem;
  display: flex; flex-direction: column;
  padding: 1.15rem;
  border-radius: var(--curva);
  /* ---- SIN `color` PROPIO, Y ES UN BUG QUE COSTO ENCONTRAR ----
     Aca decia `color: #fff`, heredado de cuando este bloque vivia en
     `.cara-frente`. Con la tarjeta CLARA, `.cara-frente.clara` da
     vuelta la tinta a `#10142b` — y este `#fff`, al estar en un
     elemento mas adentro, la pisaba: sobre un plastico casi blanco
     el nombre del banco salia **blanco sobre blanco**.
     No se veia hasta ponerle a una tarjeta el acabado claro, que es
     uno de los dos plasticos mas comunes que existen. El blanco vive
     solo en `.cara-frente`, que es donde `.clara` puede invertirlo. */
  /* La luz cae desde arriba a la derecha.
     --k y --sat vienen de js/tonos.js y son las dos perillas del
     color: k multiplica el brillo (2 = blanco, 1 = color pleno,
     casi 0 = negro) y sat multiplica la saturacion, que cae a cero
     en los dos extremos porque un blanco con matiz no es blanco. */
  background:
    radial-gradient(125% 125% at 85% 5%,
      hsl(var(--tono, 265) calc(72% * var(--sat, 1)) calc(44% * var(--k, 1))),
      transparent 62%),
    linear-gradient(150deg,
      hsl(var(--tono, 265) calc(58% * var(--sat, 1)) calc(26% * var(--k, 1))),
      hsl(calc(var(--tono, 265) + 30)
          calc(52% * var(--sat, 1)) calc(13% * var(--k, 1))));
  box-shadow: var(--sombra);
}

/* ---- La tarjeta clara ----
   Debajo de cierto brillo la letra blanca desaparece, asi que la
   tarjeta se da vuelta entera: tinta oscura y velo claro. Es la
   unica forma de que exista una tarjeta blanca, que es uno de los
   plasticos mas comunes que hay. Quien decide cuando es clara es
   esClara() en js/tonos.js, no una regla escrita dos veces. */
.cara-frente.clara { color: #10142b; }
.cara-frente.clara .plastico-cara::before {
  background: linear-gradient(to top,
    rgba(255,255,255,.80), rgba(255,255,255,.34) 52%, rgba(255,255,255,.06));
}
.cara-frente.clara .plastico-cara::after {
  background: linear-gradient(105deg, transparent 34%,
    rgba(255,255,255,.55) 48%, transparent 62%);
}
.cara-frente.clara .riel-tarjeta { background: rgba(16,20,43,.20); }
.cara-frente.clara .insignia.nivel-desconocido {
  background: rgba(16,20,43,.14); color: #10142b;
}
.cara-frente.clara .girar {
  background: rgba(255,255,255,.7); border-color: rgba(16,20,43,.25); color: #10142b;
}
/* El chip dorado sobre un plastico blanco necesita su contorno: sin
   el se pierde contra el fondo. */
/* En un plastico casi blanco el chip necesita un contorno mas firme
   o se pierde contra el fondo. Se REPITEN las tres sombras del
   relieve y solo sube el contorno: escrito como una sombra sola
   —que es como estaba— esta regla pisaba las otras tres y dejaba el
   chip plano justo en las tarjetas claras, que son la mitad de las
   que existen. `box-shadow` es una propiedad sola: no se suma. */
.cara-frente.clara .chip-emv {
  box-shadow:
    inset 0  1px 0 rgba(255,255,255,.60),
    inset 0 -1px 0 rgba(0,0,0,.32),
    inset 0  0   0 1px rgba(0,0,0,.40),
    0 1px 2px rgba(0,0,0,.28);
}
/* ---- CADA CARA EN SU PROPIO PLANO, Y ES UN ARREGLO DE SAFARI ----

   Joel, el 2026-08-22: "al darle la vuelta se ve la cara de adelante
   al reves y despues es que desaparece". En Chromium no pasa.

   ---- LA HIPOTESIS ESTABA MAL, Y ESO SE MIDIO ----

   La sospecha era el `display: grid` de `.tarjeta`, por el bug viejo
   de Safari con `preserve-3d` en contenedores flex y grid. **Era
   falsa**: se probaron tres variantes juntas en Safari y la version
   SIN grid —caras absolutas, como estuvo siempre— fallaba igual. O
   sea que el grid no tenia nada que ver, y "arreglarlo" por ahi
   habria sido deshacer algo que funcionaba.

   ---- LO QUE SI ERA ----

   La cara de ADELANTE no tenia ningun `transform`. Safari solo pone
   un elemento en el espacio 3D cuando algo lo declara ahi, y sin
   transform la trataba como plana: `backface-visibility: hidden` no
   tiene efecto sobre algo que no esta en 3D, asi que la cara seguia
   dibujandose pasados los 90 grados, espejada.

   Con transform explicito en las DOS —y separadas 1px en Z para que
   no compitan por el mismo plano— Safari crea las dos capas y el
   backface vuelve a valer. **El `translateZ` no es un truco: declara
   que cada cara ocupa su propio plano.**

   Vale para cualquier cosa que se de vuelta: las dos caras necesitan
   transform, incluida "la que no rota". */
.cara-frente { transform: rotateY(0deg) translateZ(1px); }

.cara-detras {
  transform: rotateY(180deg) translateZ(1px);
  /* Relleno propio y mucho mas apretado que el 1.15rem de `.cara`:
     ese padding esta pensado para el plastico, donde el aire es
     parte del diseno. Aca cada milimetro decide si el recuadro tiene
     que crecer, y un recuadro que crece deja al plastico del frente
     estirado y con cara de cuadrado. */
  padding: .65rem;
  /* La rejilla se lleva el alto que sobre y los botones quedan
     pegados abajo. Sin esto el bloque entero se iba arriba. */
  justify-content: stretch;
}


.mazo-item:hover .plastico-cara { box-shadow: var(--sombra-alta); }

/* El velo oscuro de abajo. NO es decoracion: el tono lo elige la
   persona y puede ser amarillo, donde la letra blanca desaparece.
   Este degradado garantiza que la mitad de abajo —donde estan las
   cifras— siempre tenga fondo oscuro, sea cual sea el tono.
   Se recorta con su propio border-radius y no con un overflow del
   padre, porque un overflow adentro del contexto 3D es una de las
   cosas que lo aplanan. */
.plastico-cara::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(to top,
    rgba(4,5,14,.78), rgba(4,5,14,.30) 52%, rgba(4,5,14,.05));
}

/* El brillo que cruza al pasar el mouse. Es lo que hace que se
   sienta un objeto y no un rectangulo de color. */
.plastico-cara::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(105deg, transparent 34%,
    rgba(255,255,255,.15) 48%, transparent 62%);
  opacity: 0;
  transition: opacity .4s ease;
}
.mazo-item:hover .plastico-cara::after { opacity: 1; }

/* Todo el contenido va por encima del velo y del brillo. Se
   exceptua el boton de girar, que se posiciona solo en una esquina
   y quedaria clavado al flujo si esta regla lo alcanzara. */
/* (El `:not(.bandera)` se quedo sin efecto el 2026-08-23: la bandera
   dejo de ser hija de `.cara` y pasa a serlo de `.plastico-cara`. Se
   deja escrito porque quitarlo no cambia nada y el dia que algo
   vuelva a colgar de `.cara` conviene ver la excepcion.) */
.cara > *:not(.girar):not(.bandera) { position: relative; z-index: 1; }

/* ---- Y EL VELO Y EL BRILLO VAN DEBAJO DEL TEXTO ----

   Lo encontro Joel el 2026-08-23: "en las tarjetas claras se pierden
   los numeros del Debes y el dia de corte, creo que porque son
   grises".

   ---- NO ERAN GRISES, Y AHI ESTUVO LA TRAMPA ----

   El color computado del texto es `#10142b` a opacidad 1, o sea negro
   azulado pleno. Medido asi, no habia ningun problema — y Joel lo
   estaba viendo. **Cuando la medicion dice que no existe, la
   sospechosa es la medicion.** Lo que estaba mal es que yo media el
   COLOR y el defecto estaba en el ORDEN DE PINTADO.

   `.plastico-cara::before` es el velo y va `position: absolute` sin
   z-index. En el orden de pintado de una pila, los descendientes
   posicionados con z-index auto o 0 se dibujan **despues** del
   contenido en flujo — asi que el velo cae ENCIMA del texto. En una
   tarjeta clara ese velo es blanco al 80% en la parte de abajo, que
   es justo donde viven "Debes" y el dia de corte: el texto negro
   quedaba lavado hasta el gris claro. En una oscura el velo es
   oscuro sobre texto blanco y aun asi se lee, que es por lo que
   sobrevivio.

   ---- POR QUE `-1` Y NO `0` ----

   Solo el z-index NEGATIVO pinta por debajo del contenido en flujo.
   El `0` y el `auto` son el mismo escalon de arriba, asi que no
   habrian cambiado nada. Y el `-1` no se escapa hacia atras del
   plastico porque `.plastico-cara` tiene `z-index: 1` por la regla de
   arriba, o sea que es una pila propia: el velo queda encima del
   degradado del plastico y debajo del texto, que es exactamente el
   sitio que le corresponde.

   ---- ES UN BUG DE LA TANDA DEL 2026-08-22, SIN PUBLICAR ----

   La regla de arriba dice "todo el contenido va por encima del velo"
   y era cierta cuando el contenido colgaba de `.cara`. Ese dia entro
   `.plastico-cara` como envoltorio, el texto bajo un nivel, y la
   regla dejo de alcanzarlo sin que nadie lo notara. La intencion
   estaba escrita; lo que se rompio fue el selector que la sostenia. */
.plastico-cara::before,
.plastico-cara::after { z-index: -1; }

/* ---- LA ESQUINA DE ARRIBA A LA DERECHA: SOLO EL PORCENTAJE ----
   Pedido de Joel el 2026-08-22: el porcentaje "bien cuadrado con
   todos los demas elementos", alineado con el chip — el chip abre la
   fila de arriba por la izquierda y esto la cierra por la derecha.
   Eso se queda; lo que salio de aca es la bandera, el 2026-08-23:
   "que el porcentaje se vea solito en la esquina superior derecha".
   Ver `.bandera`, abajo. */
.esquina-tarjeta {
  position: absolute;
  top: 1.15rem; right: 1.15rem;
  z-index: 2;
  display: flex; align-items: center;
}

/* ---- LA BANDERA VUELVE AL BORDE DERECHO, A MEDIA ALTURA ----
   Donde estuvo hasta el 2026-08-22. Volvio el 23, por decision de
   Joel: en la esquina competia con el porcentaje, que es el dato que
   esa esquina existe para mostrar.

   Y ahi sirve mejor: es lo que se busca DE REOJO al barrer el mazo
   —de que pais es esta— y a media altura no comparte renglon con
   nada, asi que se encuentra sin leer.

   El centrado va con `top: calc(50% - .7rem)` y no con
   `translateY(-50%)` a proposito: la mitad de `font-size: 1.4rem`
   con `line-height: 1` es exactamente .7rem, y un transform menos
   dentro de una tarjeta con historial de 3D es un sospechoso menos
   el dia que algo se aplane. */
.bandera {
  position: absolute;
  right: 1.15rem; top: calc(50% - .7rem);
  z-index: 2;
  font-size: 1.4rem; line-height: 1;
  filter: drop-shadow(0 1px 3px rgba(0,0,0,.5));
}

/* ---- LAS MARCAS DE ESTADO, ARRIBA AL CENTRO ----
   Pedido de Joel el 2026-08-23: "el titulo en pausa ponlo arriba en
   el centro". Antes viajaba pegada al nombre del banco, o sea que su
   sitio dependia de cuanto midiera el nombre — que es el MISMO
   defecto que el porcentaje tuvo hasta el 22.

   Se centra con una banda de ancho completo y `text-align: center`,
   no con `left: 50%` + `translateX(-50%)`. Dos razones: un transform
   menos, y sobre todo que asi la banda no tiene ancho propio, o sea
   que una marca larga se centra igual en vez de correrse.

   `pointer-events: none` porque la banda cruza por encima del chip y
   del porcentaje: sin eso taparia el clic de lo que hay debajo. Las
   marcas no son botones, asi que no pierden nada. */
.marcas-tarjeta {
  position: absolute;
  top: 1.15rem; left: 0; right: 0;
  z-index: 2;
  display: flex; justify-content: center; gap: .4rem;
  pointer-events: none;
}

/* ---- EL CHIP, CON RELIEVE Y CONTACTOS — 2026-08-23 ----
   Pedido de Joel: "dale relieve al chip, que tenga las rayitas
   negras caracteristicas". Era un rectangulo dorado plano.

   ---- VA DIBUJADO, NUNCA UNA IMAGEN ----

   Por lo mismo que el SVG de la malla va escrito en el `<body>`: una
   imagen suelta no lee las variables del tema, cuesta una peticion y
   hay que volver a exportarla cada vez que cambie el tamanio. Aca son
   dos pseudo-elementos, cero nodos nuevos y cero bytes de red — y el
   mazo dibuja un chip por tarjeta.

   ---- EL RELIEVE SON TRES SOMBRAS Y CADA UNA HACE UNA COSA ----

   Luz arriba (el canto que da a la luz), sombra abajo (el que no), y
   una sombra corta por fuera que lo despega del plastico. Con una
   sola de las tres el chip se sigue viendo pegado encima. */
.chip-emv {
  position: relative;
  width: 2.3rem; height: 1.7rem; border-radius: 5px;
  background: linear-gradient(135deg,
    #f3e7c0 0%, #d7b976 38%, #b1904f 62%, #e6d5a2 100%);
  box-shadow:
    inset 0  1px 0 rgba(255,255,255,.60),
    inset 0 -1px 0 rgba(0,0,0,.32),
    inset 0  0   0 1px rgba(0,0,0,.22),
    0 1px 2px rgba(0,0,0,.35);
}

/* Los contactos: una linea horizontal al medio y dos verticales.
   Tres degradados de un color solido dentro de UN background, en vez
   de tres elementos. La sintaxis `linear-gradient(color 0 0)` es un
   rectangulo de ese color, y el `/ 100% 1px` le da el grosor. */
.chip-emv::before {
  content: '';
  position: absolute; inset: 0;
  border-radius: inherit;
  background:
    linear-gradient(rgba(0,0,0,.55) 0 0)   0 50% / 100% 1px no-repeat,
    linear-gradient(rgba(0,0,0,.55) 0 0) 30%  0  / 1px 100% no-repeat,
    linear-gradient(rgba(0,0,0,.55) 0 0) 70%  0  / 1px 100% no-repeat;
}

/* La almohadilla del centro, ENCIMA de las tres lineas. Eso es lo
   que hace que se lea como un chip y no como una cuadricula: la
   linea horizontal se ve entrar por los dos lados y morir contra la
   almohadilla, en vez de cruzarla de lado a lado.
   Los bordes caen sobre las verticales del ::before a proposito —30%
   y 70% en los dos— asi que las tres piezas quedan encajadas. */
.chip-emv::after {
  content: '';
  position: absolute; left: 30%; right: 30%; top: 27%; bottom: 27%;
  border: 1px solid rgba(0,0,0,.55);
  border-radius: 2px;
  background: linear-gradient(135deg, #efe1b6, #c5a55f);
}

.tarjeta-nombre {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  margin-top: auto;
  font-weight: 650; letter-spacing: -.01em;
}

.digitos {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 1.05rem; letter-spacing: .14em; opacity: .9;
}

/* La insignia de utilizacion. Fondo SOLIDO del color de la franja
   y letra oscura: sobre un plastico de color cualquiera, un chip
   translucido puede quedar ilegible, y este numero es justamente
   el que no se puede perder. */
.insignia {
  padding: .15rem .5rem;
  border-radius: 999px;
  font-size: .72rem; font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--sobre-color);
  background: var(--suave);
}
.insignia.nivel-bueno { background: var(--bueno); }
.insignia.nivel-medio { background: var(--medio); }
.insignia.nivel-malo  { background: var(--malo); }

.insignia.nivel-excelente { background: var(--bueno); }
.insignia.nivel-bien      { background: var(--bien); }
.insignia.nivel-alto      { background: var(--medio); }
.insignia.nivel-critico   { background: var(--malo); }
.insignia.nivel-desconocido { background: rgba(255,255,255,.24); color: #fff; }

.pie-tarjeta {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: .75rem; margin-top: .6rem;
}
.pie-tarjeta small {
  display: block; font-size: .66rem; text-transform: uppercase;
  letter-spacing: .1em; opacity: .7;
}
.pie-tarjeta b { font-size: .92rem; font-weight: 620; font-variant-numeric: tabular-nums; }

.riel-tarjeta {
  height: .28rem; margin-top: .75rem;
  background: rgba(255,255,255,.22);
  border-radius: 999px; overflow: hidden;
}
.riel-tarjeta div { height: 100%; border-radius: 999px; background: currentColor; }

/* El boton redondo que gira la tarjeta. Es lo UNICO que la gira:
   la tarjeta entera no puede ser un boton porque tiene botones y
   campos adentro, y eso deja a quien navega con teclado sin saber
   que esta tocando.
   Sin backdrop-filter: ese filtro fue exactamente lo que aplano el
   contexto 3D y dejo las dos caras encimadas. */
.girar {
  position: absolute; top: .9rem; right: .9rem; z-index: 2;
  width: 1.9rem; height: 1.9rem;
  display: grid; place-items: center;
  border: 1px solid rgba(255,255,255,.3);
  border-radius: 50%;
  background: rgba(4,5,14,.55);
  color: #fff; font-size: .9rem; line-height: 1;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.girar:hover { background: var(--acento-boton); border-color: var(--acento); }

/* ---- La cara de atras: el formulario ----
   Es el UNICO formulario de una tarjeta en todo el proyecto. Antes
   habia una pantalla aparte (tarjeta.html) y se borro: dos
   formularios para lo mismo terminan validando distinto. */
.cara-detras {
  background: var(--superficie-alta);
  border: 1px solid var(--linea);
  box-shadow: var(--sombra);
  /* El mismo `.3rem` que separa las filas de la rejilla: los avisos
     son los unicos hermanos que quedan, y aparecen solo cuando hay
     algo que decir. Una distancia distinta aca rompería la unica
     separacion que la cara tiene. */
  gap: .3rem;
}
/* La flecha de la cara de atras hereda el blanco de .girar, que
   esta pensado para ir sobre el plastico de color. Atras el fondo
   es una superficie de la app, o sea blanca en el tema claro: la
   flecha desaparecia. Acá el color lo manda el tema. */
.cara-detras .girar {
  background: var(--superficie);
  border-color: var(--linea);
  color: var(--tinta);
}
.cara-detras .girar:hover { background: var(--acento-boton); color: #fff; }

.titulo-detras {
  font-size: .95rem; font-weight: 640;
  padding-right: 2.4rem;
  margin-bottom: .3rem;
}

/* Campos mas apretados que los de una pantalla completa: aca el
   ancho es el de una tarjeta, no el de la ventana. El font-size de
   16px NO se toca —con menos, el telefono hace zoom solo al tocar
   el campo— y lo que cede es el relleno. */
/* ---- LOS VALORES DEL 2026-08-22 ----
   Eran `min-height: 2.5rem` con etiquetas de .76rem, y estaban bien
   cuando el reverso podia crecer todo lo que quisiera. Ahora mide lo
   mismo que el frente, asi que el alto de cada fila decide si el
   recuadro entero tiene que estirarse — y un recuadro estirado deja
   al plastico con cara de cuadrado.

   OJO CON LA ESPECIFICIDAD, que costo una vuelta: esto pesa
   **0-2-1** (`.cara-detras` + `input` + `[type]`), asi que le gana a
   `.detras-rejilla > label > input`, que pesa 0-1-2 aunque parezca
   mas especifica por tener tres partes. Por eso los valores viven
   aca y no alla: pelear con una regla existente desde una menos
   pesada es escribir codigo que no se aplica. */
.cara-detras label { font-size: .64rem; margin-top: 0; }
.cara-detras input[type="text"],
.cara-detras input[type="number"],
.cara-detras select {
  min-height: 1.75rem; height: 1.75rem;
  margin-top: 0; padding: .1rem .4rem;
  /* 16px NO se toca: con menos, iOS hace zoom solo al tocar el campo
     y la pantalla queda descuadrada. Lo que cede es el relleno. */
  font-size: 16px; line-height: 1.1;
}
.cara-detras .pista { font-size: .74rem; }
.cara-detras .aviso { font-size: .78rem; min-height: 0; }

/* Dos campos cortos en la misma fila: "dia de corte" y "dia de
   pago" uno debajo del otro estiran el formulario sin necesidad. */
.par { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; }
.par > div { display: flex; flex-direction: column; }

/* `.detras-acciones` se fue el 2026-08-23: Guardar y Cancelar pasaron
   a ser dos items mas de `.detras-rejilla`, para que compartan la
   cuadricula de los ocho campos. Ver alla el porque. */

/* ---- La rueda de color ----
   Un deslizador nativo sobre el arco iris: 360 tonos, no diez. Va
   con range y no con input[type=color] porque la base guarda el
   MATIZ, y el selector del sistema devuelve un color completo del
   que habria que descartar saturacion y brillo. Elegir "gris" y
   ver aparecer un morado es peor que no poder elegirlo. Aca lo que
   se mueve es exactamente lo que se guarda. */
.rueda {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 1.5rem; margin-top: .35rem;
  border-radius: 999px; cursor: pointer;
  border: 1px solid var(--linea);
  background: linear-gradient(to right,
    hsl(0 70% 50%), hsl(60 70% 50%), hsl(120 70% 50%), hsl(180 70% 50%),
    hsl(240 70% 50%), hsl(300 70% 50%), hsl(360 70% 50%));
}
.rueda::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 1.35rem; height: 1.35rem; border-radius: 50%;
  background: hsl(var(--tono, 265) 72% 50%);
  border: 3px solid #fff;
  /* El anillo oscuro fino es para cuando la bolita queda blanca
     sobre el extremo blanco de la barra: sin el, desaparece. */
  box-shadow: 0 0 0 1px rgba(0,0,0,.55), 0 1px 4px rgba(0,0,0,.6);
  cursor: grab;
}
.rueda::-moz-range-thumb {
  width: 1.35rem; height: 1.35rem; border-radius: 50%;
  background: hsl(var(--tono, 265) 72% 50%);
  border: 3px solid #fff;
  box-shadow: 0 0 0 1px rgba(0,0,0,.55), 0 1px 4px rgba(0,0,0,.6);
  cursor: grab;
}
.rueda:focus-visible { outline: 2px solid var(--acento); outline-offset: 3px; }

/* La muestra que acompaña a los deslizadores. Mismo degradado que
   la cara de adelante, con las mismas --tono, --k y --sat: no puede
   mostrar un color distinto del que va a quedar. */
.fila-color { display: flex; align-items: center; justify-content: space-between; gap: .6rem; }
.fila-color label { margin-top: .55rem; }

.muestra-color {
  width: 3.2rem; height: 1.6rem;
  margin-top: .55rem;
  border-radius: 6px;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.18), 0 1px 3px rgba(0,0,0,.3);
  background:
    radial-gradient(125% 125% at 80% 10%,
      hsl(var(--tono, 265) calc(72% * var(--sat, 1)) calc(44% * var(--k, 1))),
      transparent 62%),
    linear-gradient(150deg,
      hsl(var(--tono, 265) calc(58% * var(--sat, 1)) calc(26% * var(--k, 1))),
      hsl(calc(var(--tono, 265) + 30)
          calc(52% * var(--sat, 1)) calc(13% * var(--k, 1))));
}

/* El segundo deslizador: de blanco a negro pasando por el matiz que
   la persona acaba de elegir. Se pinta con SU tono y no con una
   escala de grises fija, para que el control muestre el recorrido
   real y no uno generico. */
.rueda.escala {
  background: linear-gradient(to right,
    #ffffff,
    hsl(var(--tono, 265) 62% 46%) 50%,
    #05060f);
}

/* La bolita de ESTE deslizador lleva el color de llegada —blanco en
   un extremo, negro en el otro— y no el matiz pelado. Antes se
   quedaba clavada en el color de la barra de arriba, o sea que
   arrastrarla al blanco no cambiaba nada: el control mentia sobre
   lo que estaba haciendo. Usa las mismas --k y --sat que la
   tarjeta, asi que no puede desincronizarse de ella. */
.rueda.escala::-webkit-slider-thumb {
  background: hsl(var(--tono, 265)
    calc(72% * var(--sat, 1)) calc(50% * var(--k, 1)));
}
.rueda.escala::-moz-range-thumb {
  background: hsl(var(--tono, 265)
    calc(72% * var(--sat, 1)) calc(50% * var(--k, 1)));
}

/* Tres botones iguales. Eran dos con anchos 2fr/1fr —"Actualizar
   saldo" era el principal— y desde el 2026-08-22 son Editar, Color y
   Borrar, que pesan lo mismo. */
.mazo-acciones { display: grid; grid-template-columns: repeat(3, 1fr); gap: .4rem; }
.mazo-acciones > * { margin-top: 0; }

/* Una tarjeta cerrada sigue en la lista —su historial vale— pero
   apagada, para que no compita con las que si cuentan. El filtro
   va en la CARA y no en la escena: un filter sobre el contenedor
   del contexto 3D es otra de las cosas que lo aplanan. */
.mazo-item.cerrada .plastico-cara { filter: grayscale(.7); opacity: .65; }
/* ============================================================
   EL PUENTE

   El color va en el borde izquierdo y NO en el texto. Por eso no
   reusa las clases nivel-*, que pintan la letra: un panel rojo con
   todo el cuerpo en rojo no se puede leer.

   La franja se la pregunta a nivel(), la misma funcion que pinta
   el panel de utilizacion, asi que los dos no pueden contradecirse
   en la misma pantalla.
   ============================================================ */
/* ---- LAS DOS FRANJAS ----

   Era una sola, a la izquierda. Joel pidio repetirla a la derecha
   "que ese recuadro quede como atrapado por los colores de ambos
   lados", y tiene razon por una razon que no es de gusto: con una
   sola franja el color es un adorno pegado a un borde, y el ojo lo
   lee como el principio de la caja. Con las dos, el color deja de
   estar EN la caja y pasa a CONTENERLA, que es lo que el puente
   hace con los dos numeros que compara.

   El color va en --franja y no repetido en cada regla: escrito dos
   veces por tramo son ocho declaraciones que pueden desincronizarse,
   y una franja de un color y la otra de otro seria peor que no
   tener ninguna.

   Usa la familia --vivo, la de las formas, por lo mismo que la
   barra: no hay ninguna letra encima, asi que el tema claro puede
   llevar el color de semaforo entero. */
.puente {
  --franja: var(--linea);
  margin-top: 1.25rem;
  padding: 1.3rem;
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-left: 4px solid var(--franja);
  border-right: 4px solid var(--franja);
  border-radius: var(--curva);
  box-shadow: var(--sombra);
}

.puente-bueno { --franja: var(--bueno-vivo); }
.puente-bien  { --franja: var(--bien-vivo); }
.puente-medio { --franja: var(--medio-vivo); }
.puente-malo  { --franja: var(--malo-vivo); }
.puente-flojo { --franja: var(--linea); }

/* Dentro de una rejilla el puente ya tiene su hueco: el margen de
   arriba le desalinea la fila. Y una rejilla que viene justo
   despues de un titulo de seccion tampoco necesita su propio
   margen, porque el titulo ya dejo aire abajo. */
.rejilla .puente { margin-top: 0; }
.seccion-cabeza + .rejilla { margin-top: 0; }

/* ---- El desglose por moneda ----

   De dónde sale el número del veredicto. Va dentro de un <details>
   y cerrado por defecto a propósito: quien cobra y debe en la misma
   moneda no tiene nada que desarmar, y para esa mayoría es un
   renglón y no un bloque. Quien sí convierte lo abre una vez,
   entiende la cuenta, y ya. */
.desglose { margin-top: 1.1rem; border-top: 1px solid var(--linea); padding-top: .9rem; }
.desglose-titulo {
  margin: 0 0 .2rem; color: var(--suave);
  font-size: .78rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .08em;
}

.grupo-tasa { margin-top: .85rem; }
.grupo-tasa:first-of-type { margin-top: .6rem; }

.grupo-cabeza {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: .75rem; font-size: .9rem;
}
/* La bandera y el código de moneda juntos, sin que el código se
   despegue si el sistema no dibuja la bandera (Windows muestra las
   dos letras del país, y ahí quedan cuatro letras seguidas). */
.grupo-cabeza span { letter-spacing: .01em; }
.grupo-cabeza strong { font-weight: 640; }
.grupo-tasa .pista { margin-top: .15rem; }

/* ============================================================
   PRESUPUESTO — el reparto como dona

   Reemplaza a las cuatro barras, decidido el 2026-08-15 mirando
   las dos versiones lado a lado. El cambio es por como se lee, no
   porque lo pida el dato: la proporcion entre baldes se ve de un
   vistazo en un circulo y en cuatro barras hay que compararlas.

   La geometria y las dos salvaguardas —el balde en cero y el
   reparto pasado del ingreso— viven en js/torta.js, con su porque.
   Aca solo esta como se ve.
   ============================================================ */
.torta-caja {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  flex-wrap: wrap;
  margin-top: 1rem;
}

/* 240 y no 220, y el numero sale de MEDIR: el hueco util es el 62%
   del ancho, y a 220px daban 136px contra los 138 que mide
   "COP 5.000.000". Dos pixeles, pero la cifra se partia en medio de
   los digitos. */
.torta-lienzo { position: relative; width: 240px; flex: 0 0 auto; }
.torta { display: block; width: 100%; height: auto; overflow: visible; }

/* La entrada. El estado FINAL es el natural del elemento y el
   keyframe solo describe el "desde": asi, cuando
   prefers-reduced-motion deja la animacion en 0,001ms, la dona
   aparece quieta y correcta en vez de quedarse a medio camino.
   Verificado, no supuesto. */
.torta-anillo {
  transform-box: fill-box; transform-origin: center;
  animation: torta-entrar .55s cubic-bezier(.2,.75,.3,1) both;
}
@keyframes torta-entrar { from { opacity: 0; transform: scale(.9) rotate(-10deg); } }

/* La pista vacia. Cuando sobra plata, este pedazo de anillo SIN
   pintar es el dato: es, literalmente, lo que todavia no se
   asigno. */
/* ---- LA PISTA YA NO ES EL COLOR DEL FONDO ----

   Estaba en `var(--fondo)` exacto, asi que el tramo sin asignar era
   invisible y la dona parecia cortada. Ahora es el fondo con un
   poco de tinta encima: se lee como un carril vacio, que es lo que
   es, sin competir con ningun balde. */
.torta-pista {
  fill: none;
  stroke: color-mix(in srgb, var(--tinta) 9%, var(--fondo));
}

/* Los dos contornos, con la misma variable que el riel de
   utilizacion: cambia sola con el tema. */
.torta-contorno {
  fill: none;
  stroke: var(--borde-riel);
  stroke-width: 1;
}

/* El arco hereda el color de la clase cat-*, la misma que pintaba
   la barra y la misma que lleva el borde de cada gasto. El giro de
   -90 grados arranca el reparto a las 12 en punto, que es donde el
   ojo empieza a leer un circulo. */
.torta-tramo {
  fill: none;
  stroke: currentColor;
  transform: rotate(-90deg);
  transform-box: fill-box; transform-origin: center;
}

/* La marca de donde se acaba el ingreso, solo cuando el reparto se
   paso. Son DOS lineas encimadas: la de abajo gruesa y del color
   del fondo, la de arriba fina y de tinta. Eso da el mismo
   sandwich oscura-clara-oscura de la marca de la meta en el riel,
   y por el mismo motivo: tiene que verse encima de cualquiera de
   los cuatro colores Y encima de la pista vacia, en los dos
   temas. */
.torta-marca-borde { stroke: var(--fondo); stroke-width: 6; }
.torta-marca       { stroke: var(--tinta); stroke-width: 2; }

/* El halo de "esto no cabe". Va dentro del SVG y no como un ::after
   de CSS: en CSS habria que darle un inset en pixeles atado al
   tamano de la dona, y el dia que la dona cambie de tamano el halo
   queda flotando lejos del anillo. Aca comparte coordenadas con el
   anillo y no se puede despegar. */
.torta-halo-1, .torta-halo-2 { fill: none; stroke: var(--malo); }
.torta-halo-1 { stroke-width: 1;   opacity: .55; }
.torta-halo-2 { stroke-width: 2.5; opacity: .16; }

/* ---- El centro ----
   Va en HTML encima del SVG y no en un <text>, porque la cifra
   tiene que ACHICARSE segun cuanto mida, que es el arreglo del
   numero grande de la semana 7. En SVG eso obliga a textLength, que
   aplasta las letras en vez de achicarlas. */
.torta-centro {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: .1rem;
  padding: 0 19%;
  text-align: center;
  pointer-events: none;
}
.torta-rotulo { font-size: .72rem; color: var(--suave); line-height: 1; }
.torta-cifra {
  font-weight: 700; line-height: 1.12;
  font-variant-numeric: tabular-nums;
  /* Ultimo recurso, y no deberia dispararse nunca: los cuatro
     tamanos de abajo cubren la cadena mas larga que la base acepta.

     Hace falta igual, y por algo que costo encontrar: el separador
     que mete Intl entre el codigo y el numero es un espacio DURO, o
     sea que el navegador no puede partir ahi. Sin esto, una cifra
     que no entrara se saldria de la dona en vez de acomodarse. */
  overflow-wrap: anywhere;
}

/* Los cortes estan MEDIDOS en el navegador contra el hueco real
   (149px de ancho util), con un barrido de todas las longitudes de
   5 a 22 caracteres usando digitos —que son mas anchos que los
   puntos separadores—. Ninguna se sale; la peor deja 4px de aire.

   Es la leccion del numero grande de la semana 7, donde medirlos
   con una cadena inventada dio de mas justamente por tener mas
   puntos que un numero real.

   Y los cuatro bajaron un escalon despues de mirarlo en telefono:
   entrar no alcanza. A 1,15rem la cifra ENTRABA por 11px —cinco y
   medio de cada lado— y contra el borde curvo del anillo eso se ve
   apretado, no centrado. El aire tambien es parte de que se vea
   caro.

   Si algun dia una tipografia mas ancha (Windows) desborda igual,
   el overflow-wrap de arriba lo parte en dos renglones y el hueco
   tiene alto de sobra. Se ve peor, pero nunca se sale. */
.cifra-l  { font-size: 1.05rem; }   /* hasta 13 caracteres */
.cifra-m  { font-size: .85rem; }    /* 14 y 15 */
.cifra-s  { font-size: .74rem; }    /* 16 a 18 */
.cifra-xs { font-size: .6rem; }     /* 19 a 22, el techo de numeric(14,2) */

/* ---- La leyenda ----
   Aca vive el dato de verdad. Los CUATRO baldes siempre, tengan o
   no un segmento que mostrar: esa es la salvaguarda contra un balde
   en cero desapareciendo sin avisar, y por eso la lista no se
   filtra nunca. */
.torta-leyenda {
  list-style: none; margin: 0; padding: 0;
  flex: 1 1 14rem; min-width: 0;
}

/* FILA QUE SE PARTE, y no una rejilla de cuatro columnas.

   Con rejilla, un monto largo —"ARS 125.400.000", que es un ingreso
   normal en Argentina y no un caso inventado— no cabia y algo tenia
   que ceder: o aparecia barra horizontal o el nombre se cortaba con
   puntos suspensivos. Las dos salidas son malas en una pantalla de
   plata.

   Asi, cuando no cabe, el monto BAJA a su propio renglon. El
   renglon crece y no se pierde ni un caracter. El margin-left
   automatico los deja igual alineados a la derecha, que es la unica
   alineacion que importa en una columna de cifras. */
.torta-leyenda li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .1rem .55rem;
  padding: .38rem 0;
  border-bottom: 1px solid var(--linea);
  font-size: .88rem;
}
.torta-leyenda li:last-child { border-bottom: 0; }

.torta-punto {
  width: .7rem; height: .7rem; border-radius: 50%;
  background: var(--balde, var(--linea));
  align-self: center;
}
/* Un balde en cero: el punto va HUECO. Se ve que el balde existe y
   que esta vacio, sin tener que buscar un segmento que no esta. */
.torta-punto.vacio {
  background: none;
  box-shadow: inset 0 0 0 2px var(--balde, var(--linea));
  opacity: .55;
}
.torta-punto.hueco {
  background: none;
  box-shadow: inset 0 0 0 2px var(--linea);
}
/* El mismo sandwich de la marca radial, en chiquito, para que el
   renglon de "te pasaste" se reconozca contra el dibujo.

   ---- SE LLAMABA `.marca` Y SE RENOMBRO EL 2026-08-21 ----

   `.marca` es el bloque del logo, en base.css, y esta pantalla carga
   las dos hojas: o sea que este puntito de 7px estaba recibiendo el
   display:flex, el peso y el color del NOMBRE DE LA MARCA.

   No se veia —el punto mide en rem, no en em, y no tiene hijos— pero
   era una bomba con la mecha puesta: el dia del logo se le agregaron
   a `.marca` reglas para sus hijos (`.marca b`, `.marca span`), y
   basta que alguien meta un <span> aqui para heredarlas. Es la misma
   familia que `.tramo`, que dejo la landing entera en mayusculas
   durante dos semanas sin romper nada.

   La regla que lo cubre ya estaba escrita: dos hojas que se cargan
   juntas comparten un solo espacio de nombres. */
.torta-punto.exceso {
  background: linear-gradient(90deg,
    var(--fondo) 0 2px, var(--tinta) 2px 5px, var(--fondo) 5px 7px);
  border-radius: 2px;
}

.torta-nombre { font-weight: 560; white-space: nowrap; }
.torta-parte  { color: var(--suave); font-size: .78rem;
                font-variant-numeric: tabular-nums; }
.torta-monto  { font-weight: 700; white-space: nowrap;
                margin-left: auto;
                font-variant-numeric: tabular-nums; }

.torta-leyenda li.apagado .torta-nombre,
.torta-leyenda li.apagado .torta-monto { color: var(--suave); font-weight: 500; }

.torta-leyenda li.torta-hueco { --balde: var(--linea); }
.torta-leyenda li.torta-hueco .torta-nombre,
.torta-leyenda li.torta-hueco .torta-monto { color: var(--suave); }

.torta-leyenda li.torta-paso .torta-nombre,
.torta-leyenda li.torta-paso .torta-monto { color: var(--malo); }

/* ---- Elegir estrategia ---- */
.opcion {
  display: flex; align-items: flex-start; gap: .8rem;
  margin-top: .7rem; padding: .9rem 1rem;
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-radius: 12px;
  font-weight: 400; cursor: pointer;
  transition: border-color .15s ease, box-shadow .2s ease, background .15s ease;
}
.opcion:hover { border-color: color-mix(in srgb, var(--acento) 60%, var(--linea)); }
.opcion.elegida { border-color: var(--acento); background: var(--superficie-alta); box-shadow: var(--neon); }
.opcion input { margin-top: .3rem; flex-shrink: 0; }
.opcion strong { display: block; font-size: .95rem; font-weight: 640; }
/* Las explicaciones van una debajo de otra; en linea se amontonan. */
.opcion .pista { display: block; }

/* ============================================================
   FILAS — los gastos del presupuesto
   ============================================================ */
.fila {
  padding: .95rem 1.05rem;
  margin-top: .6rem;
  background: var(--superficie);
  border: 1px solid var(--linea);
  border-radius: 12px;
}
.fila.cerrada { opacity: .55; }

.fila-cabeza {
  display: flex; align-items: baseline; justify-content: space-between; gap: .75rem;
}
.fila-nombre { font-weight: 620; }
.monto { font-size: .9rem; font-weight: 700; white-space: nowrap;
         font-variant-numeric: tabular-nums; }

.fila-datos { margin-top: .25rem; color: var(--suave); font-size: .8rem; }

/* ============================================================
   LOS BOLSILLOS, EN TARJETITAS

   Eran filas de ancho completo con el nombre pegado a la izquierda y
   el monto pegado a la derecha. Joel: "abarca casi toda la pantalla
   y no es util". El problema es de distancia: en una pantalla ancha
   el ojo tiene que cruzar veinte centimetros para juntar dos datos
   que son uno solo —cuanto hay y donde— y cada bolsillo se gasta un
   renglon entero para decir dos cosas cortas.

   ---- 15rem Y auto-fill, no un 3x3 ----

   Joel pidio "grid de 3x3". Tres columnas fijas se rompen en los dos
   extremos: en un telefono quedan tres tarjetitas de 90px con el
   monto cortado, y en un monitor ancho quedan tres columnas enormes
   con el mismo problema de distancia que veniamos de arreglar. Con
   `auto-fill` y un minimo de 15rem caben tres en un portatil normal
   —que es donde Joel lo esta viendo— cuatro o cinco en un monitor
   grande y una sola en el telefono, sin una media query.

   Es la misma decision que ya toma `.rejilla` para los paneles; lo
   unico que cambia es el minimo, porque un bolsillo es mas chico que
   un panel de pais.
   ============================================================ */
/* El encabezado que parte la seccion en dos: arriba cuanto hay, aca
   abajo donde esta. Mas chico que un <h2> de seccion a proposito —no
   abre una seccion nueva, divide una— y con una linea arriba que es
   la que de verdad hace el corte. */
.sub-cabeza {
  margin-top: 1.75rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--linea);
  font-size: .95rem;
  font-weight: 650;
  color: var(--suave);
}

.fondos-rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr));
  gap: .75rem;
  margin-top: .7rem;
}

/* La tasa, debajo del monto convertido y no pegada con un punto al
   lado: "= ARS 50.400.000 · tu tasa del 10/08/2026" en una caja de
   15rem se parte donde caiga y la fecha termina sola en un renglon.
   En dos renglones, cada cosa es una cosa. */
.fila-tasa { display: block; }

.fondo-caja {
  /* El margen de arriba lo pone ahora el gap de la rejilla; dejarlo
     agregaria un escalon entre las filas de tarjetitas. */
  margin-top: 0;
  display: flex;
  flex-direction: column;
  /* Los botones abajo del todo aunque una tarjetita tenga el aviso
     de "no sabemos a cuanto cambias" y la de al lado no: sin esto,
     en la misma fila unos botones quedan a media altura de otros. */
  justify-content: space-between;
}

/* El nombre deja de competir con el monto: pasa a ser la etiqueta y
   el monto, el dato. Al reves de como estaban, que era el problema. */
.fondo-caja .fila-nombre {
  color: var(--suave);
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .02em;
}

.fondo-caja .monto {
  /* Sin white-space: nowrap, que es lo que trae .monto de la fila
     ancha: aca la caja mide 15rem y un ARS 125.400.000 se sale. Que
     baje de renglon es mejor que que desborde. */
  white-space: normal;
  overflow-wrap: anywhere;
  margin-top: .15rem;
  font-size: 1.25rem;
  line-height: 1.15;
}

.fila-acciones { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .7rem; }
/* `flex: 1` a secas no deja encoger por debajo del contenido, asi
   que con cuatro botones —los tres de siempre mas "Activar este" de
   una fila pausada— en una tarjetita de 15rem se desbordaban y se
   metian encima de la de al lado. Con `wrap` bajan de renglon en vez
   de salirse, y `flex: 1 1 auto` deja que el ultimo ocupe lo que
   sobra en vez de estirar los cuatro a la fuerza. */
.fila-acciones > * {
  flex: 1 1 auto;
  /* `.secundario` trae `width: 100%` porque en un formulario eso es
     lo correcto. Con `wrap` puesto, ese 100% hace que cada boton
     pida el contenedor entero y se vaya solo a su renglon: los tres
     de cada gasto salieron apilados en vertical. Con `auto` piden lo
     que miden y vuelven a caber los tres en una fila, y solo se
     envuelven cuando de verdad no entran. */
  width: auto;
}

/* ============================================================
   TELEFONO

   Sigue siendo telefono-primero: la app se usa parada en la fila
   del banco, no sentado en un escritorio. La barra se parte en dos
   filas y el nombre de la marca desaparece —el punto solo ya
   identifica, y tres palabras partidas en tres renglones se ven
   rotas.
   ============================================================ */
@media (max-width: 720px) {
  .barra { flex-wrap: wrap; gap: .6rem; padding: .7rem 1rem; }
  .marca span { display: none; }
  /* En dos filas ya no hay nada a los costados que descentre el
     menu, asi que vuelve al flujo y ocupa el ancho. */
  .menu { position: static; transform: none; flex: 1; }
  .menu a { flex: 1; text-align: center; }
  .barra-fin { margin-left: auto; }

  .lienzo { padding: 1.5rem 1rem 4rem; }
  .saludo { font-size: 1.5rem; }
  .numeron { font-size: 2.7rem; }
  .mazo { grid-template-columns: 1fr; }
}


/* ============================================================
   LEVANTAR AL PASAR EL MOUSE

   El destello del borde ya existía; faltaba que el objeto se
   moviera. Es lo mismo que hace el mazo de la landing y lo que
   ahora hacen los paneles: una app que no responde al mouse se
   siente muerta aunque todo lo demás esté bien.

   ---- POR QUE EN .escena Y NO EN .tarjeta ----

   .tarjeta es la que tiene preserve-3d y la que rota para el giro.
   Ponerle otro transform encima le pisa el rotateY y la deja
   plana a mitad de vuelta: es primo del bug de las dos caras
   encimadas de la semana 5. .escena es el contenedor y puede
   moverse sin tocar el contexto 3D de adentro.

   ---- Y POR QUE SE APAGA CUANDO ESTA GIRADA ----

   Girada, la cara de adelante es un formulario. Que la caja crezca
   y se mueva mientras alguien escribe adentro es mareante y hace
   saltar el campo bajo el cursor.
   ============================================================ */
.mazo-item .escena {
  transition: transform .25s cubic-bezier(.2,.7,.3,1);
}
.mazo-item:hover .escena { transform: translateY(-4px) scale(1.012); }
/* ---- LA EXCEPCION SE QUITO EL 2026-08-22 ----
   Decia `transform: none` con la tarjeta girada, y tenia razon
   cuando el reverso CRECIA: que la caja se agrandara mientras
   alguien escribe hacia saltar el campo bajo el cursor.
   Desde que las dos caras miden lo mismo eso no pasa, y la
   excepcion pasó a ser el problema: al girar la tarjeta perdia el
   zoom del hover y al volver lo recuperaba, o sea un salto en cada
   vuelta. Lo vio Joel en Safari. */

/* base.css ya apaga las transiciones con prefers-reduced-motion,
   pero eso solo las vuelve instantaneas: el salto seguiria ahi, y
   para quien pidio no ver movimiento un salto es peor que una
   animacion suave. Aca se quita el movimiento entero y queda solo
   el cambio de borde y sombra, que no se mueve. */
@media (prefers-reduced-motion: reduce) {
  .panel:hover,
  .mazo-item:hover .escena { transform: none; }
}


/* ============================================================
   LOS CUATRO BALDES — el mismo color en la barra y en el gasto

   El borde de color a la izquierda de cada gasto no es para que la
   lista "no se vea plana": es para que se lea sin leerla. Con
   quince renglones del mismo gris hay que ir palabra por palabra
   para saber cuánto se va en necesidades; con el borde, la
   proporción se ve de un vistazo y coincide con la barra de arriba.

   Por eso NO son colores alternados: alternar dos tonos es
   decoración y no dice nada. Acá el color ES el dato.

   ---- POR QUE DOS FAMILIAS DE CLASES ----

   .cat-* pinta el COLOR DEL TEXTO, y la usa la barra del reparto,
   que hereda con currentColor.

   .balde-* solo define la variable --balde y no toca ningún color.
   La usa la fila del gasto, donde el color va en el borde y el
   texto tiene que seguir siendo legible. Con una sola familia había
   que devolverle el color a cada hijo, y esa pelea de
   especificidades la termina ganando cualquiera menos el que uno
   quiere.
   ============================================================ */
.cat-necesidad { color: var(--cat-necesidad); }
.cat-gusto     { color: var(--cat-gusto); }
.cat-ahorro    { color: var(--cat-ahorro); }
.cat-deuda     { color: var(--cat-deuda); }

.balde-necesidad { --balde: var(--cat-necesidad); }
.balde-gusto     { --balde: var(--cat-gusto); }
.balde-ahorro    { --balde: var(--cat-ahorro); }
.balde-deuda     { --balde: var(--cat-deuda); }

/* El borde de color MAS un tinte que se desvanece hacia la derecha.
   Solo con el borde de 3px el color casi no se notaba: en una lista
   de diez gastos hay que buscarlo, y un color que hay que buscar no
   sirve para leer de un vistazo, que es para lo que está.

   El degradado es el mismo recurso que el de las tarjetas, pero muy
   por debajo: 12% del color contra el fondo, y apagándose antes de
   la mitad del ancho. Tiene que alcanzar para reconocer el balde de
   reojo y no tanto como para pelear con el monto, que es el dato
   que la persona vino a leer. El nombre del gasto sigue en tinta
   normal: acá el color es del fondo, no de las letras.

   El valor de reserva no es adorno: si algún día entrara una
   categoría fuera de la lista, sin él el borde desaparece entero y
   la fila se descuadra contra las de al lado. */
.fila.con-balde {
  border-left: 3px solid var(--balde, var(--linea));
  background:
    linear-gradient(100deg,
      color-mix(in srgb, var(--balde, transparent) 12%, transparent) 0%,
      transparent 55%),
    var(--superficie);
}

/* ---- EN CLARO EL DEGRADADO LLEGA MAS LEJOS ----

   Sube al 16% por lo de siempre: sobre blanco un color claro tiene
   menos con que contrastar. Pero eso solo no alcanzaba — Joel:
   "en el modo claro el degradado de cada categoria casi no se ve".

   Lo que faltaba no era mas opacidad sino mas RECORRIDO. Con el
   corte en 55% el color moria antes de la mitad del recuadro, y en
   una tarjetita de la rejilla —mucho mas angosta que la fila de
   ancho completo para la que se calibro— eso son cuatro
   centimetros de nada. Llevandolo al 75% el color cruza casi todo
   el ancho y se lee como un fondo teñido en vez de una mancha en la
   esquina. Subir la opacidad en cambio habria empezado a competir
   con el texto. */
:root[data-tema="claro"] .fila.con-balde {
  background:
    linear-gradient(100deg,
      color-mix(in srgb, var(--balde, transparent) 16%, transparent) 0%,
      transparent 75%),
    var(--superficie);
}

/* La única palabra coloreada del renglón: es la que conecta el
   borde de la izquierda con la barra del reparto. */
.fila-datos .balde-nombre { color: var(--balde); font-weight: 640; }

/* La regla de la estrategia elegida, arriba del reparto. */
.regla-elegida { margin-bottom: .2rem; }

/* ============================================================
   LO QUE EL PLAN TIENE EN PAUSA — 2026-08-16

   La regla: "no se borra nada, nunca. Una tarjeta en pausa esta a
   la vista con todo su historial. La diferencia es que esta a la
   vista Y NO FUNCIONANDO, y eso ademas de cerrar el hueco es el
   mejor argumento de venta que tiene la app: se ve exactamente lo
   que uno se esta perdiendo."

   Por eso lo pausado NO se esconde ni se pinta de gris muerto: se
   atenua lo justo para que se lea como apagado, y lleva una
   insignia que lo dice con palabras. Un color no es un dato — la
   misma regla por la que la tarjeta cerrada tambien lleva la suya.
   ============================================================ */

.en-pausa { opacity: .55; }

/* La tarjeta pausada no se atenua entera: el plastico se queda como
   esta —es un objeto y sigue siendo suyo— y lo que baja es todo lo
   demas. Asi se distingue de la cerrada, que si va en gris. */
.mazo-item.en-pausa .escena { opacity: .5; filter: saturate(.7); }

/* La insignia usa el mismo componente que "cerrada" para no inventar
   una pieza nueva, con su propio color: `--suave` y no un color del
   semaforo, porque la pausa NO es un estado de la deuda. Pintarla de
   ambar o de rojo diria algo sobre la plata de la persona que no es
   cierto. */
.insignia.en-pausa {
  background: var(--suave);
  color: var(--sobre-color);
  opacity: 1;
}

/* ---- EL AVISO ARRIBA DE CADA LISTA ---- */
/* ============================================================
   LO IRREVERSIBLE — 2026-08-17

   Hoy solo lo usa "cerrar mi cuenta". Va como variante y no como un
   botón nuevo porque la forma, el tamaño y el foco son los mismos: lo
   único que cambia es el color, que es lo que dice "esto no se
   deshace".

   ---- POR QUE USA `--malo` Y NO UN ROJO PROPIO ----

   `--malo` es el rojo del semáforo y ya está medido en los dos temas
   —entre 5,16 y 12,93 de contraste—. Un rojo nuevo habría que medirlo
   otra vez, y la regla dice que ninguna regla de más abajo escribe un
   color a mano.

   Y no rompe la regla de que el color del semáforo es un DATO: acá no
   pinta una cifra ni un estado de la plata de nadie. Pinta un
   control, igual que el naranja de la landing pinta botones. */
.secundario.peligro {
  color: var(--malo);
  border-color: color-mix(in srgb, var(--malo) 42%, transparent);
}
.secundario.peligro:hover {
  background: color-mix(in srgb, var(--malo) 12%, transparent);
  border-color: var(--malo);
}

/* El de dentro del diálogo, que es el que de verdad borra: relleno
   sólido, porque ahí ya no es una salida entre otras sino LA acción.
   Letra clara sobre el rojo, que es el par que ya usa el semáforo. */
.principal.peligro {
  background: var(--malo);
  color: var(--sobre-color);
}
.principal.peligro:hover {
  background: color-mix(in srgb, var(--malo) 88%, #000);
}

/* El diálogo de confirmación escrita. Hereda todo de `.dialogo-pausa`
   —ancho, curva, sombra— y solo marca el borde: es lo que lo
   distingue de un diálogo de elegir a simple vista. */
.dialogo-peligro { border-top: 3px solid var(--malo); }

/* ============================================================
   EL BANNER DE REACTIVACION — 2026-08-17

   Va arriba del todo, antes de los paneles, y solo aparece cuando
   hay algo en pausa.

   ---- POR QUE PESA MAS QUE `.aviso-plan` Y NO ES LO MISMO ----

   `.aviso-plan` es contextual: vive encima de una lista y explica
   esa lista. Este es la foto de la cuenta entera —tarjetas, ingresos
   y fondos juntos— y es el unico sitio donde aparece el precio. Si
   los dos se vieran igual, el de arriba se leeria como una
   repeticion del de abajo y el ojo lo saltaria.

   La barra de acento a la izquierda es la misma de `.aviso-plan.pausa`
   a proposito: dicen cosas del mismo tema. Lo que cambia es el
   cuerpo, no el codigo de color. */
.banner-plan {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .8rem 1.2rem;
  margin: 0 0 var(--aire-bloque);
  padding: 1rem 1.15rem;
  background: var(--superficie-alta);
  border: 1px solid var(--linea);
  border-left: 3px solid var(--acento);
  border-radius: var(--curva);
  box-shadow: var(--sombra);
}

.banner-plan .crece { flex: 1; min-width: 15rem; }

.banner-plan-titulo {
  margin: 0;
  font-size: 1rem;
  font-weight: 640;
  color: var(--tinta);
}

.banner-plan-nota {
  margin: .3rem 0 0;
  font-size: .84rem;
  line-height: 1.5;
  color: var(--suave);
}

/* El boton no crece. `.como-boton` viene con ancho completo porque en
   un formulario eso es lo correcto; aca lo convertiria en una barra
   que pesa mas que el texto que la explica. */
.banner-plan a.como-boton {
  flex: 0 0 auto;
  width: auto;
}

/* En telefono el boton si ocupa el ancho: al lado de un texto de dos
   o tres renglones, un boton corto a la derecha queda flotando solo
   en una esquina. */
@media (max-width: 560px) {
  .banner-plan a.como-boton { width: 100%; }
}

.aviso-plan {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem .9rem;
  margin: 0 0 1rem;
  padding: .7rem .9rem;
  font-size: .84rem;
  line-height: 1.45;
  color: var(--suave);
  background: var(--superficie-alta);
  border: 1px solid var(--linea);
  border-radius: calc(var(--curva) - 6px);
}
.aviso-plan b { color: var(--tinta); font-weight: 620; }

/* El de "tienes cosas en pausa" lleva una barra al costado. No es
   una alerta —no hay nada roto— pero si algo que la persona puede
   accionar, y sin ninguna marca se leia como una nota al pie. */
.aviso-plan.pausa { border-left: 3px solid var(--acento); }

.aviso-plan .crece { flex: 1; min-width: 12rem; }

/* El enlace no crece. `.como-boton` viene con ancho completo porque
   en un formulario eso es lo correcto; dentro de un aviso lo
   convertia en una barra que pesaba mas que el texto que la
   explica. Es una salida, no la accion principal de la pantalla. */
.aviso-plan a.como-boton {
  flex: 0 0 auto;
  width: auto;
  padding: .4rem .8rem;
  font-size: .8rem;
}

/* ---- EL AVISO DE DESPUES DE PAGAR ----

   Lo pone js/pagar.js cuando Paddle avisa que el checkout termino, y
   vive mientras se espera a que llegue el webhook. Va FIJO abajo y
   no dentro del flujo de la pagina por una razon concreta: el
   recuadro de Paddle se cierra dejando el scroll donde estaba, que
   puede ser cualquier parte, y un aviso insertado arriba del todo
   quedaria fuera de la pantalla justo en el momento en que hay algo
   que decir.

   ---- NO SE CENTRA CON `left: 50%` Y `translateX`, Y COSTÓ
        MEDIRLO ----

   Esa receta es la que uno escribe de memoria, y aquí encoge la
   caja: con `left: 50%` el ancho disponible para un elemento fijo
   pasa a ser la MITAD DERECHA de la ventana, y como la caja se
   ajusta a su contenido, en un teléfono de 375 px quedaba de 188 y
   el texto salía en cuatro renglones. En escritorio no se veía,
   porque media pantalla ahí todavía sobra.

   Con `left` y `right` puestos, el ancho disponible vuelve a ser la
   ventana entera menos los márgenes, y `margin-inline: auto` centra
   sin mover nada. */
.aviso-pago {
  position: fixed;
  z-index: 60;
  left: 1rem;
  right: 1rem;
  bottom: 1.5rem;
  width: fit-content;
  margin-inline: auto;
  max-width: min(30rem, 100%);
  padding: .8rem 1.1rem;
  font-size: .88rem;
  line-height: 1.45;
  text-align: center;
  color: var(--tinta);
  background: var(--superficie-alta);
  border: 1px solid var(--linea);
  border-left: 3px solid var(--acento);
  border-radius: calc(var(--curva) - 6px);
  box-shadow: var(--sombra-alta);
}

.aviso-pago a { color: var(--acento); }

/* El boton de "conservar esta" que aparece en cada fila pausada. */
/* ---- "Activar este" VA SOLO, EN SU PROPIO RENGLON ----

   Joel: "que el botón que queda solo abajo sea el de Activar este,
   y así todos los botones siempre quedan en el mismo orden: Editar,
   apagar, borrar".

   Tiene razón y el motivo es de lectura, no de gusto: con cuatro
   botones envolviéndose libremente, cuál caía abajo dependía del
   ancho de la tarjetita, así que la misma lista mostraba el trío en
   un orden distinto en cada columna. Con `flex-basis: 100%` este
   siempre ocupa su renglón y los otros tres quedan siempre juntos y
   siempre iguales.

   Y de paso queda donde corresponde: es la acción propia de una
   fila pausada, no una más del trío que tienen todas. */
.boton-conservar {
  flex-basis: 100%;
  font-size: .78rem;
  padding: .35rem .7rem;
  white-space: nowrap;
}

/* La insignia de pausa dentro de una fila va pegada al nombre y con
   su tamaño propio. Sin esto heredaba el alto de los botones de
   `.fila-acciones` —donde estuvo al principio— y salía como una
   píldora enorme con "en pausa" partido en dos renglones. */
.fila-nombre .insignia.en-pausa {
  margin-left: .45rem;
  padding: .1rem .45rem;
  font-size: .68rem;
  white-space: nowrap;
  vertical-align: middle;
}

/* ============================================================
   LAS LISTAS EN REJILLA — 2026-08-16

   Joel, viendo los fondos: "fíjate cómo quedaron los saldos, que
   caben hasta cuatro ahora en la página. Quiero que así queden tus
   ingresos y tus gastos. Dos columnas para tus ingresos y dos para
   tus gastos [...] Igualmente tus tasas de cambio."

   Antes eran filas de ancho completo: un ingreso ocupaba un renglón
   entero para decir un nombre y un monto, y con tres o cuatro la
   pantalla se volvía una tira larga. En rejilla se leen de un
   vistazo, que es lo mismo que ganaron los fondos.

   ---- POR QUE `auto-fill` Y NO UN NUMERO DE COLUMNAS ----

   Dos columnas fijas se rompen en los dos extremos: en un teléfono
   quedan dos tarjetitas de 90 px y en un monitor dos columnas
   enormes. Con `auto-fill` y un mínimo, el número de columnas sale
   del ancho que haya — es la misma decisión que ya se tomó con los
   bolsillos, y por eso caben dos dentro de la media pantalla de
   ingresos y cuatro en la fila entera de las tasas, sin una sola
   media query.

   Y el orden es el que pidió: la rejilla llena izquierda, derecha,
   y baja. Es el flujo natural de `grid`, no hay nada que escribir.
   ============================================================ */
.rejilla-fina {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(13.5rem, 100%), 1fr));
  gap: 1rem;

  /* ---- TODAS DEL MISMO ALTO ----

     Joel, viendo el gasto "Fondo de emergencia": tiene el título en
     dos renglones y además la línea de la tasa, así que era mucho
     más alto que "Arriendo", que estaba a su lado. Pidió ese tamaño
     como estándar.

     `1fr` en las filas automáticas reparte el alto por igual, así
     que TODAS las filas —no solo las tarjetitas de una misma fila—
     toman el de la más alta. Con `align-items: start`, que es lo que
     había, cada una se encogía a su contenido y quedaban los
     escalones.

     No lleva una altura escrita a mano: el estándar sale del
     contenido real, así que si algún día un nombre ocupa tres
     renglones, las demás lo siguen solas. */
  grid-auto-rows: 1fr;
}

/* Las filas de la rejilla no heredan el margen que tenían cuando
   iban apiladas: ese margen ahora lo pone el `gap`, y dejarlo
   sumaría un escalón entre renglones. */
/* El margen ahora lo pone el `gap`; dejarlo sumaría un escalón.
   Y cada tarjetita se vuelve una columna para que los botones caigan
   abajo del todo: sin esto, en una tarjeta más corta que la fila los
   botones quedaban a media altura y no se alineaban con los de al
   lado. Es lo mismo que ya hacía `.fondo-caja`. */
.rejilla-fina > .fila {
  margin-top: 0;
  display: flex;
  flex-direction: column;
}
/* Empuja las acciones al pie, sea cual sea el alto que le tocó.

   El `padding-top` no es redundante con el `margin-top: auto`: el
   auto reparte lo que SOBRA, y en la tarjetita más alta de la
   rejilla no sobra nada, así que ahí valía cero y la fecha de la
   tasa quedaba pegada a los botones. Joel: "esa fecha de la tasa
   está muy pegada de los botones". El padding es el aire mínimo
   garantizado, sobre o no sobre espacio. */
.rejilla-fina > .fila > .fila-acciones {
  margin-top: auto;
  padding-top: .95rem;
}

/* Las tasas ocupan la fila entera, no media pantalla, así que con el
   mínimo de arriba entraban CINCO y Joel pidió hasta cuatro. Se les
   sube el mínimo en vez de fijarles `repeat(4, 1fr)`: así en un
   portátil angosto bajan a tres y a dos solas, en vez de dejar
   cuatro columnas apretadas. Medido sobre los 1168 px de contenido
   del lienzo: con 17rem entran 4 y la quinta necesitaría 1424. */
.rejilla-fina.hasta-4 {
  grid-template-columns: repeat(auto-fill, minmax(min(17rem, 100%), 1fr));
}

/* El diálogo de "¿cuál pauso?". Hereda casi todo de `dialog` en
   base.css; lo único propio es la lista de opciones. */
.opciones-pausa { display: grid; gap: .5rem; margin: 1rem 0 1.4rem; }

.opcion-pausa {
  display: flex; align-items: center; gap: .6rem;
  padding: .7rem .85rem;
  background: var(--superficie-alta);
  border: 1px solid var(--linea);
  border-radius: calc(var(--curva) - 6px);
  cursor: pointer;
}
/* El seleccionado se marca con el acento: sin esto, con el radio
   nativo chico había que mirar dos veces para saber cuál estaba. */
.opcion-pausa:has(input:checked) {
  border-color: var(--acento);
  box-shadow: var(--neon);
}
.opcion-pausa input { width: auto; margin: 0; }

/* ============================================================
   EL RITMO VERTICAL DE UNA SECCION — 2026-08-16

   Una regla sola pone el ritmo por defecto y tres excepciones
   marcan lo que va junto. Se escribe así, y no poniéndole un margen
   a cada componente, justamente por el problema que vino a
   arreglar: con el margen repartido en veinte reglas, cada una
   elige su número y el conjunto pierde la jerarquía.

   `> * + *` solo toca a los hijos DIRECTOS de la sección, así que
   nada de lo que pase dentro de una tarjetita o un formulario se
   ve afectado.
   ============================================================ */
.seccion > * + *,
.lienzo > section > * + * { margin-top: var(--aire-bloque); }

/* Un título y su bajada son UNA idea, no dos bloques. */
.seccion > h2 + .pista,
.seccion > .seccion-cabeza + .pista,
.lienzo > section > h2 + .pista,
.lienzo > section > .seccion-cabeza + .pista { margin-top: var(--aire-par); }

/* Una etiqueta y su campo, lo mismo. */
.seccion > label + *,
.lienzo > section > label + * { margin-top: var(--aire-par); }

/* Y la pista que explica un campo pertenece al campo de arriba, no
   al bloque de abajo. */
.seccion > select + .pista,
.seccion > input + .pista,
.lienzo > section > select + .pista,
.lienzo > section > input + .pista { margin-top: var(--aire-par); }

/* Entre secciones, el escalón más grande. Ya estaba en 2.5rem por
   casualidad; ahora lo dice el token. */
.seccion { margin-top: var(--aire-seccion); }

/* ============================================================
   UN NOMBRE LARGO NO PUEDE DEFORMAR LA REJILLA — 2026-08-16

   Joel probó un gasto con 58 caracteres sin un solo espacio y la
   tarjetita se estiró hasta romper la columna de al lado.

   ---- POR QUE EL `maxlength` NO ERA LA SOLUCION ----

   Ya había un `maxlength="60"` en los tres formularios, y aun así
   pasó. El límite acota cuánto se escribe, pero no dice nada sobre
   si eso CABE: 58 caracteres sin espacios no tienen dónde partirse,
   así que la palabra empuja la caja por ancha que sea. Con el
   límite en 40 pasaría lo mismo, solo que un poco más tarde.

   Lo que de verdad lo impide son tres cosas, y ninguna depende de
   cuánto escriba nadie:

   1. `min-width: 0` en la tarjetita. Un elemento de grid trae
      `min-width: auto`, que le PROHIBE encogerse por debajo de su
      contenido — esa es la causa real del estirón, y es la misma
      trampa del `minmax(21rem, 1fr)` del héroe en la semana 9.
   2. `overflow-wrap: anywhere` en el nombre, para que una palabra
      sin espacios se parta en vez de empujar.
   3. Un tope de dos renglones. Sin él la palabra se parte pero
      ocupa cinco líneas, y como la rejilla iguala alturas, UNA
      tarjeta mal nombrada estiraba las demás.

   El nombre completo queda en el `title`, y al editar se ve entero:
   no se pierde nada, solo se deja de dibujar.
   ============================================================ */
.rejilla-fina > .fila { min-width: 0; }

.fila-nombre {
  min-width: 0;
  overflow-wrap: anywhere;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* El monto nunca se parte ni se encoge: es el dato, y un número
   cortado a la mitad es peor que un nombre cortado. */
.fila-cabeza .monto { flex: 0 0 auto; }

/* ============================================================
   LA INSIGNIA DE PAUSA EN LA TARJETITA DE UN FONDO — 2026-08-16

   Salía como una barra gris de ancho completo debajo del nombre:
   `.fondo-caja` es una columna flex, así que la insignia, siendo un
   hijo más, se estiraba como todos. Joel: "no sale muy bonito que
   se diga".

   Va a la esquina superior derecha, que es donde no le quita el
   sitio a nada: el nombre manda a la izquierda y el monto va abajo,
   en grande.

   ---- Y LO QUE JOEL PREGUNTO: UN TITULO LARGO ----

   Es el riesgo real de sacar algo del flujo — un elemento absoluto
   deja de empujar, así que un nombre largo le pasaría por debajo.

   Se resuelve reservándole el hueco: cuando la tarjetita está en
   pausa, el nombre lleva un `padding-right` del ancho de la
   insignia. El padding va SOLO en ese caso; si fuera fijo, todas
   las tarjetitas perderían cinco centímetros de nombre para dejar
   sitio a una insignia que casi nunca está.

   Y el nombre ya no puede desbordar por su cuenta: tiene el tope de
   dos renglones y el corte con puntos suspensivos de más arriba.
   ============================================================ */
.fondo-caja { position: relative; }

.fondo-caja > .insignia.en-pausa {
  position: absolute;
  top: .7rem;
  right: .7rem;
  margin: 0;
  z-index: 1;
}

/* El hueco reservado, solo cuando hay insignia que esquivar. */
.fondo-caja.en-pausa > .fila-nombre { padding-right: 5rem; }

/* ============================================================
   LA BALANZA DEL PUENTE — maqueta del pendiente 35h, 2026-08-17

   Todavia NO la usa ninguna pantalla: la ejercita
   `herramientas/puente.html`. Vive aca y no en la herramienta a
   proposito, para que la maqueta NO tenga hoja propia — que es
   exactamente lo que convirtio a `maqueta.html` en un dibujo de la app
   en vez de la app, y escondio el bug de las cuotas en la semana 5.

   ---- QUE DIBUJA ----

   Un bullet chart. Una sola escala horizontal, de 0 al mayor entre lo
   que piden y lo que dejas:

     - EL FONDO son las dos cosas que piden las tarjetas, y son DOS
       ZONAS distintas porque son dos cosas distintas: `cuotas_del_mes`
       va solida —si no se paga hay mora— y de ahi hasta el objetivo va
       rayada, porque es una meta propia y no una deuda exigible.
       **Esa diferencia de textura ES la regla del puente**: macizo lo
       obligatorio, poroso lo deseable, sin depender de que nadie lea
       el rotulo.

     - LA BARRA DE ENCIMA es lo que el presupuesto deja. Va mas fina
       —60% del alto— para que las zonas se sigan viendo arriba y
       abajo. Si fuera del mismo alto taparia justo lo que hay que
       comparar.

     - LA MARCA del final es el objetivo del mes.

   Y con eso el veredicto se lee sin una palabra: si la barra pasa la
   marca alcanza; si termina en la zona rayada, se paga sin mora pero
   no se llega a la meta; si termina en la solida, hay mora en camino.

   ---- EL COLOR NO SALE DEL VEREDICTO ----

   Sale de `--vivo`, o sea de las clases `nivel-*`, que las pone
   `nivel(utilizacion_peor)` — la MISMA funcion que pinta el panel de
   utilizacion de arriba. No puede haber dos colores para la misma
   deuda en una pantalla, y eso ya costo un arreglo en la semana 4.
   Por eso aca no hay ni un color escrito.
   ============================================================ */

.balanza { display: grid; gap: var(--aire-dentro); }

/* La pista. Mismo borde que `.riel`, por lo mismo: si no se ve donde
   TERMINA, el relleno deja de ser una proporcion. */
.balanza-pista {
  position: relative;
  height: 2.6rem;
  border-radius: 10px;
  border: 1px solid var(--borde-riel);
  background: var(--fondo);
  overflow: hidden;
}

/* Zona 1: lo obligatorio. Solida.

   Y lleva una LINEA en su borde derecho, dibujada por encima de la
   barra de "lo que dejas" (z-index 3 contra 2). Sin ella, cuando el
   presupuesto cubre las cuotas la barra tapa justo el limite entre lo
   exigible y lo deseable — que es el dato que hay que leer. Medido en
   la maqueta: con 154,07 de cuotas y 229,13 de presupuesto, el corte
   quedaba escondido debajo. */
.balanza-cuotas {
  position: absolute; inset: 0 auto 0 0; z-index: 1;
  background: color-mix(in srgb, var(--vivo, currentColor) 26%, transparent);
}
.balanza-cuotas::after {
  content: ''; position: absolute; z-index: 3;
  right: 0; top: 0; bottom: 0; width: 2px;
  background: var(--fondo);
}

/* Zona 2: de las cuotas al objetivo. Rayada.
   El rayado se dibuja con un gradiente repetido y no con una imagen:
   asi toma el color del semaforo y cambia solo con el tema. */
.balanza-abono {
  position: absolute; top: 0; bottom: 0;
  background: repeating-linear-gradient(
    -45deg,
    color-mix(in srgb, var(--vivo, currentColor) 22%, transparent) 0 5px,
    transparent 5px 11px);
}

/* Lo que el presupuesto deja. Mas fina y centrada. */
.balanza-deja {
  position: absolute; z-index: 2; left: 0; top: 50%; transform: translateY(-50%);
  height: 60%;
  border-radius: 8px;
  background: var(--vivo, currentColor);
  box-shadow: 0 0 14px color-mix(in srgb, var(--vivo, currentColor) 45%, transparent);
}

/* La marca del objetivo. Es el sandwich oscura-clara-oscura del
   `.riel-meta`, por la misma razon: tiene que verse encima de la zona
   de color Y de la pista vacia, en los dos temas, sin una regla por
   color. */
.balanza-meta {
  position: absolute; top: -2px; bottom: -2px; width: 3px;
  background: linear-gradient(90deg,
    rgba(0,0,0,.55) 0 1px, var(--tinta) 1px 2px, rgba(0,0,0,.55) 2px 3px);
}

/* Las etiquetas, debajo y ancladas a su tramo. */
.balanza-pies {
  position: relative; height: 1.2rem;
  color: var(--suave); font-size: .74rem;
}
.balanza-pies span { position: absolute; white-space: nowrap; transform: translateX(-50%); }
.balanza-pies span.der { transform: translateX(-100%); }
.balanza-pies b { color: var(--tinta); font-weight: 620; font-variant-numeric: tabular-nums; }

/* El desglose: la misma figura en chiquito, una por grupo. Se aprende
   la forma una vez arriba y despues se leen tres sin releer nada. */
.balanza-grupo { display: grid; grid-template-columns: auto 1fr auto; gap: .7rem;
                 align-items: center; padding: .5rem 0; }
.balanza-grupo + .balanza-grupo { border-top: 1px solid var(--linea); }
.balanza-grupo .balanza-pista { height: 1.1rem; border-radius: 6px; }
.balanza-grupo .nombre { font-size: .82rem; min-width: 5.5rem; }
.balanza-grupo .cifra  { font-size: .82rem; font-variant-numeric: tabular-nums;
                         color: var(--suave); }

/* ---- LOS CORCHETES, debajo de la barra (2026-08-17, pedido de Joel)

   Reemplazan a las etiquetas sueltas que flotaban debajo. Un corchete
   del ancho exacto del tramo dice "esto de aca es esto" sin ninguna
   frase; con la etiqueta suelta habia que adivinar a que tramo se
   referia, y por eso hacia falta un parrafo explicandolo. Ese parrafo
   se fue.

   Van en DOS FILAS y no en una: `obligatorio` y `puedes pagar`
   empiezan los dos en cero, asi que en la misma fila se pisarian. */
.balanza-corchetes { position: relative; }
.balanza-fila { position: relative; height: 2.1rem; }
.balanza-corchete { position: absolute; top: 0; }
.balanza-corchete::before {
  content: ''; display: block; height: 6px;
  border: 1px solid var(--borde-riel); border-bottom: 0;
  border-radius: 4px 4px 0 0;
}
.balanza-corchete span {
  display: block; text-align: center; margin-top: .2rem;
  color: var(--suave); font-size: .74rem; white-space: nowrap;
}
.balanza-corchete b { color: var(--tinta); font-weight: 620;
                      font-variant-numeric: tabular-nums; }

/* La banderita a cuadros del objetivo. Va ARRIBA de la barra para no
   chocar con los corchetes, y es CSS y no el emoji: el emoji lo dibuja
   el sistema operativo y en Windows no siempre esta —es la misma razon
   por la que la app no apoya nada importante en las banderas de pais—. */
.balanza-bandera {
  position: absolute; bottom: calc(100% + 4px); width: 14px; height: 10px;
  transform: translateX(-50%);
  background:
    conic-gradient(var(--tinta) 90deg, transparent 90deg 180deg,
                   var(--tinta) 180deg 270deg, transparent 270deg)
    0 0 / 5px 5px;
  outline: 1px solid var(--borde-riel);
}
.balanza-bandera::after {
  content: ''; position: absolute; left: -1px; top: 0; bottom: -6px;
  border-left: 1px solid var(--tinta);
}

/* ---- CORCHETES QUE ABRAZAN LA BARRA (2026-08-17, 2a vuelta de Joel)

   Las punticas apuntan HACIA la barra, no hacia afuera: un corchete
   que abre en direccion contraria al tramo que nombra obliga a
   decidir a cual se refiere, que era el problema que los corchetes
   venian a resolver.

   Por eso hay dos variantes y su posicion no es intercambiable:
   `.arriba` va encima de la barra con las punticas bajando, y
   `.abajo` va debajo con las punticas subiendo. */
.balanza-corchete.arriba::before {
  border: 1px solid var(--borde-riel); border-bottom: 0;
  border-radius: 4px 4px 0 0;
}
.balanza-corchete.arriba span { margin: 0 0 .2rem; }
.balanza-corchete.arriba { display: flex; flex-direction: column-reverse; }

.balanza-corchete.abajo::before {
  border: 1px solid var(--borde-riel); border-top: 0;
  border-radius: 0 0 4px 4px;
}

/* El texto de "puedes pagar" va DENTRO de su barra. Es el unico tramo
   que puede llevarlo adentro: es la barra solida y tiene fondo propio,
   asi que no compite con el rayado. Va en `--sobre-color`, la tinta
   que la piel ya tiene definida para escribir encima de un color de
   semaforo. */
.balanza-deja { display: flex; align-items: center; }
.balanza-deja span {
  padding: 0 .7rem; font-size: .74rem; white-space: nowrap;
  color: var(--sobre-color); font-weight: 600;
}
.balanza-deja b { font-variant-numeric: tabular-nums; font-weight: 700; }

/* ---- LA BANDERITA: mastil desde el final de la barra, ondeando a la
   izquierda y POR FUERA de la pista. Antes era un cuadrado pegado
   arriba y no se leia como bandera. El mastil nace exactamente en el
   final de la escala, que es donde esta el objetivo. */
.balanza-bandera {
  position: absolute; bottom: 100%; width: 1px; height: 1.35rem;
  background: var(--tinta); transform: none; outline: 0;
}
.balanza-bandera::after {
  content: ''; position: absolute; left: -17px; top: 0;
  width: 17px; height: 11px;
  background:
    conic-gradient(var(--tinta) 90deg, var(--fondo) 90deg 180deg,
                   var(--tinta) 180deg 270deg, var(--fondo) 270deg)
    0 0 / 5.6px 5.6px;
  outline: 1px solid var(--borde-riel);
}

/* La banderita vive FUERA de `.balanza-pista` y no dentro: esa pista
   lleva `overflow: hidden` para recortar las zonas contra sus esquinas
   redondeadas, y se comia el mastil entero. Costo una vuelta. */
.balanza-marco { position: relative; }

/* ---- 3a vuelta de Joel: jerarquia y color (2026-08-17) ----

   1. El corchete de arriba quedaba MAS LEJOS de la barra que el de
      abajo. La causa: `.balanza-fila` tiene alto fijo y el contenido de
      arriba no lo llena, asi que el sobrante caia entre el corchete y
      la barra. Se ancla al fondo de su fila y los dos quedan a la misma
      distancia. Dos separaciones distintas para dos cosas del mismo
      rango se leen como jerarquia donde no la hay. */
.balanza-corchete.arriba { top: auto; bottom: 0; }

/* 2. El texto va CENTRADO en su barra y no pegado a la izquierda. */
.balanza-deja { justify-content: center; }

/* 3. La banderita, mas presente. */
.balanza-bandera { height: 1.75rem; width: 2px; }
.balanza-bandera::after {
  left: -25px; width: 25px; height: 16px;
  background:
    conic-gradient(var(--tinta) 90deg, var(--fondo) 90deg 180deg,
                   var(--tinta) 180deg 270deg, var(--fondo) 270deg)
    0 0 / 8.34px 8px;
}

/* 4. LA BANDERA Y EL CODIGO DE LA MONEDA, mas grandes. Son la unica
      forma de saber de que grupo habla cada barra. */
.balanza-grupo .nombre { font-size: .95rem; min-width: 6.5rem; letter-spacing: .01em; }
.balanza-grupo .cifra  { font-size: .88rem; }

/* 5. EL COLOR DEL SEMAFORO SE GUARDA PARA LA CIFRA.

   El titulo y el nombre del estado pasan a tinta normal: pintados los
   tres del mismo color de alerta, el color deja de senialar y se vuelve
   el fondo del bloque. Queda en la cifra, que es el dato. Es la misma
   razon por la que el naranja no puede tocar un chip ni un estado. */
.balanza-titulo { color: var(--tinta); }
.balanza-estado { color: var(--suave); }

/* ---- 4a vuelta (2026-08-17): fuera la banderita, prominencia por
   problema, y la lista por moneda rehecha ----

   1. SE FUE LA BANDERITA A CUADROS. No hace falta un simbolo para el
      objetivo: **el final de la pista ES el objetivo**, porque la
      escala va de cero a el. Un adorno que marca algo que la forma ya
      dice es ruido, y ademas era el unico elemento ilustrativo en una
      pantalla puramente geometrica.

   2. LA PROMINENCIA SIGUE AL PROBLEMA.

      Si la barra ya cubre lo obligatorio, ese numero esta resuelto —no
      va a haber mora— y no tiene por que competir con el que si esta
      abierto. Se apaga a gris fino. Cuando NO esta cubierto se pone en
      primer plano y en el color de alerta, porque ese mes es lo unico
      que importa.

      Es la misma correccion que Joel hizo con el titulo: si algo grita
      siempre, deja de avisar. */
.balanza-corchete.resuelto span { opacity: .55; font-size: .7rem; }
.balanza-corchete.resuelto b { color: var(--suave); font-weight: 500; }
.balanza-corchete.resuelto::before { opacity: .5; }

.balanza-corchete.abierto span { color: var(--tinta); }
.balanza-corchete.abierto b { color: var(--vivo, currentColor); }
.balanza-corchete.abierto::before { border-color: var(--vivo, currentColor); }

/* 3. LA LISTA POR MONEDA: EL LARGO ES EL DATO.

   Antes las cuatro barras eran de ancho completo, asi que la unica
   diferencia entre ellas era donde caia el rayado — y el dato que
   alguien de verdad busca ahi es CUAL LE ESTA PIDIENDO MAS. Con todas
   del mismo largo, ese orden habia que leerlo en las cifras.

   Ahora el largo de cada barra es su objetivo contra el del grupo que
   mas pide, asi que el ranking se ve sin leer un numero. Es la misma
   idea que la escalera de tramos: que la distancia signifique algo. */
.balanza-grupo .carril { display: block; }
.balanza-grupo .balanza-pista { height: 1.25rem; }
.balanza-grupo.vacio .nombre,
.balanza-grupo.vacio .cifra { opacity: .5; }
.balanza-grupo.vacio .carril { border-bottom: 1px dashed var(--borde-riel); }

/* ---- CUANDO LA ETIQUETA NO CABE EN SU BARRA (2026-08-17) ----

   "Puedes pagar USD 229,13" vive dentro de la barra solida, y esa
   barra mide lo que midan los datos: con el presupuesto chico contra
   el objetivo, o en un telefono, el texto se sale.

   ---- POR QUE NO ES UNA MEDIA QUERY ----

   El ancho que decide NO es el de la pantalla sino el de la BARRA, y
   ese es un valor de los datos. En un monitor de 27 pulgadas la barra
   puede medir 60 px si la persona tiene poco presupuesto. Una media
   query mediria la ventana, que es justo lo que no informa.

   La container query pregunta por el ancho del propio elemento, que es
   la unica medida que aca significa algo.

   ---- Y EL RESPALDO NO INVENTA UN SITIO NUEVO ----

   Cuando no cabe, la etiqueta baja al renglon de abajo como un
   corchete igual a los otros dos. Ese renglon esta libre desde 0 hasta
   donde empieza "Te falta", asi que no se pisan. Se prefirio eso a
   encogerle la letra —seria el unico texto de la pantalla fuera de la
   escala— o a recortar el numero, que es un dato. */
.balanza-deja { container-type: inline-size; }

/* Por defecto manda la de adentro y la de respaldo no existe. */
.balanza-respaldo { display: none; }

@container (max-width: 175px) {
  .balanza-deja > span { display: none; }
}
/* El respaldo se prende con el mismo umbral, desde el contenedor de
   la barra. `:has()` deja preguntarlo desde afuera sin una linea de
   JavaScript. */
.balanza:has(.balanza-deja) .balanza-respaldo { display: none; }
@container (max-width: 175px) {
  .balanza-deja::after {
    content: attr(data-corto);
    position: absolute; left: calc(100% + .5rem); top: 50%;
    transform: translateY(-50%);
    color: var(--tinta); font-size: .74rem; font-weight: 600;
    white-space: nowrap;
  }
}

/* El respaldo cae encima de la zona rayada, y texto sobre rayas se lee
   sucio. Lleva su propia pastilla del color de la superficie. */
@container (max-width: 175px) {
  .balanza-deja::after {
    background: var(--superficie);
    padding: .1rem .45rem; border-radius: 6px;
    box-shadow: 0 0 0 1px var(--borde-riel);
  }
}

/* ---- LA ETIQUETA DE AFUERA, CENTRADA EN EL HUECO ----

   El respaldo estaba pegado al borde de la barra solida, invadiendo el
   rayado desde su misma orilla. Ahora va CENTRADO en lo que queda de
   pista.

   Vive DENTRO de `.balanza-deja` aunque se dibuje afuera, y eso no es
   un capricho: la container query que lo prende mide esa barra, y una
   container query solo puede estilar descendientes de su contenedor.
   Como hermano no habria forma de prenderlo sin JavaScript.

   Su `width` es el hueco expresado en veces la barra —hueco% / barra%—
   y lo calcula quien dibuja, igual que los demas anchos. */
.balanza-fuera {
  display: none;
  position: absolute; left: 100%; top: 0; bottom: 0;
  align-items: center; justify-content: center;
  pointer-events: none;
}
.balanza-fuera span {
  color: var(--tinta); font-size: .74rem; font-weight: 600;
  white-space: nowrap;
  background: var(--superficie);
  padding: .1rem .5rem; border-radius: 6px;
  box-shadow: 0 0 0 1px var(--borde-riel);
}
@container (max-width: 175px) {
  .balanza-fuera { display: flex; }
  /* Se apaga la pastilla del ::after: la reemplaza este elemento. */
  .balanza-deja::after { content: none; }
}

/* ---- EL RESPALDO SE QUEDA AL LADO, Y NO CUMPLE DEL TODO ----

   Joel pidio que no tocara el borde del rayado. Se intento bajarlo
   debajo de su barra y NO SE PUEDE desde aqui: `.balanza-fuera` vive
   dentro de `.balanza-deja`, que vive dentro de `.balanza-pista`, y esa
   pista lleva `overflow: hidden` para recortar las zonas contra sus
   esquinas. Cualquier cosa que intente salir hacia abajo se recorta.

   Y no puede vivir fuera de esa cadena, porque la container query que
   lo prende mide el ancho de la barra y una container query solo
   estila descendientes de su contenedor.

   O sea que el arreglo de verdad es de MARCADO, no de CSS: el respaldo
   tiene que ser hermano de la pista y recibir su posicion de quien
   dibuja, que ya conoce los porcentajes. Se hace al montarlo en
   app.html, donde ese renderer se escribe de todos modos.

   Mientras tanto queda al lado y centrado en el hueco: legible, pero
   con la barra muy corta llena ese hueco y lo toca por los dos lados.
   Queda dicho para que nadie lo de por resuelto. */

/* ---- LA FILA DE MONEDA, PEGADA (2026-08-17, pedido de Joel) ----

   Dos cosas separaban la barra de su bandera:

   1. `.nombre` tenia `min-width: 6.5rem` = 104 px, y el texto real
      —bandera + tres letras— mide bastante menos. La barra arrancaba
      despues de esa caja, no despues del texto, asi que sobraba aire
      muerto. El ancho pasa a ser el justo para el codigo mas largo, que
      son tres letras en todas las monedas ISO.

   2. EL MONTO VIVIA EN UNA COLUMNA FIJA A LA DERECHA. Con las barras
      proporcionales —el largo ES el dato— el borde derecho de cada
      barra cae en un sitio distinto, asi que ese hueco iba de 11 px a
      316 px segun la fila. Medido.

      Ahora el monto va DENTRO del carril, pegado al final de su barra,
      asi que la distancia es la misma a los dos lados y en las tres
      filas. El efecto de lado: los montos ya no alinean en columna,
      forman una escalera descendente — que refuerza el ranking en vez
      de pelearse con el.  */
.balanza-grupo { grid-template-columns: auto 1fr; gap: .7rem; }
.balanza-grupo .nombre { min-width: 0; width: 4.4rem; }

.balanza-grupo .carril { display: flex; align-items: center; gap: .7rem; }
.balanza-grupo .carril .balanza-pista { flex: 0 0 auto; }
.balanza-grupo .cifra { flex: 0 0 auto; white-space: nowrap; }

/* ---- Y EL CODIGO SE ALINEA A LA DERECHA ----

   Aunque su caja tenga ancho fijo —hace falta para que las barras de
   todas las filas arranquen en el mismo x, que es lo que permite
   compararlas— el TEXTO puede pegarse a la derecha. Asi el hueco que
   se ve es exactamente el `gap` y no el sobrante de la caja, sin
   depender de cuanto mida la bandera en cada sistema operativo.
   Medido antes: 33 px de aire contra 11 del otro lado. */
.balanza-grupo .nombre { text-align: right; }

/* La barra mide un % del hueco QUE QUEDA despues del monto, no del
   carril entero. Sin esta zona intermedia, una barra al 100% mas el
   monto suman mas que la fila y la pagina se puede arrastrar de lado
   — que es justo el desborde invisible que este proyecto ya persiguio
   dos veces. */
.balanza-grupo .riel-zona { flex: 1 1 auto; min-width: 0; }

/* ---- LA ZONA LLEVA EL PORCENTAJE, NO LA BARRA ----

   Con la zona flexible y el % en la barra, el borde derecho de la
   barra volvia a moverse y el hueco hasta el monto iba de 11 a 333 px.
   Medido en las tres filas.

   Poniendo el % en la ZONA y la barra al 100% de ella, la zona mide
   exactamente lo que mide la barra, el monto va pegado a su borde y la
   distancia es la misma en todas las filas — que es lo que se pidio.

   ---- Y LA ESCALA NO LLEGA A 100 ----

   El grupo que mas pide se dibuja al 78% y no al 100%, para que el
   monto de esa fila —la mas larga— tenga donde caer sin empujar la
   pagina. El 100% era arbitrario: esto es un ranking relativo, no una
   medida absoluta, asi que reservar ese margen no pierde ninguna
   informacion. Quien dibuja aplica el mismo factor a las tres. */
.balanza-grupo .riel-zona { flex: 0 1 auto; }
.balanza-grupo .riel-zona .balanza-pista { width: 100%; }

/* ---- LA PISTA DEJA DE RECORTAR (2026-08-17, al montar en app.html)

   Llevaba `overflow: hidden` solo para que las zonas no se salieran de
   sus esquinas redondeadas — y de paso se comia cualquier etiqueta que
   quisiera escapar hacia abajo, que es por lo que "Puedes pagar" no
   podia salir de la barra cuando no cabia.

   Se cambia el recorte por darle a cada zona SU curva: la de las
   cuotas redondea a la izquierda y la del abono a la derecha. Mismo
   resultado visual, sin encerrar nada. */
.balanza-marco .balanza-pista { overflow: visible; }
.balanza-marco .balanza-cuotas { border-radius: 9px 0 0 9px; }
.balanza-marco .balanza-abono  { border-radius: 0 9px 9px 0; }

/* Y con la pista sin recortar, el respaldo por fin puede bajar. Cae
   debajo de SU barra, en la mitad del renglon que "Te falta" deja
   libre, asi que no invade el rayado ni se pisa con el otro corchete. */
.balanza-fuera {
  left: 0; top: calc(100% + .5rem); bottom: auto; width: 100%; height: 1.3rem;
}

/* ---- LAS CLASES DEL PUENTE PONEN TAMBIEN `--vivo` ----

   Montando la balanza en app.html salio que las barras se dibujaban
   GRISES: usan `var(--vivo, currentColor)` y dentro de `.puente` esa
   variable no existia, asi que caian al color del texto.

   Se resuelve igual que las `nivel-*`, y por la misma razon: esas
   clases ponen `color` y `--vivo` DE UNA VEZ porque repartido en dos
   reglas un dia alguien cambia una y no la otra, y la barra deja de
   coincidir con su numero. La franja del borde y el relleno de la
   balanza son el mismo color por definicion — se declaran juntos. */
.puente-bueno { --vivo: var(--bueno-vivo); }
.puente-bien  { --vivo: var(--bien-vivo); }
.puente-medio { --vivo: var(--medio-vivo); }
.puente-malo  { --vivo: var(--malo-vivo); }
.puente-flojo { --vivo: var(--suave); }

/* La fila sin barra ponia su texto en una tercera columna que no
   existe —la rejilla es `auto 1fr`— y se caia de renglon. El texto va
   dentro del carril, que es donde iria la barra si la hubiera. */
.balanza-grupo.vacio .carril { display: flex; align-items: center; }
.balanza-grupo.vacio .carril::before {
  content: ''; flex: 0 0 auto; width: 1.2rem;
  border-bottom: 1px dashed var(--borde-riel);
}

/* ---- AJUSTES DE LA BALANZA MONTADA (2026-08-17, mirando la pantalla)

   1. El gris del corchete resuelto estaba demasiado apagado. Se
      apaga para que no compita con lo que si esta abierto, pero tiene
      que seguir siendo legible: es una cifra de dinero, no un adorno.
      De .55 de opacidad a .8, y el numero recupera la tinta normal. */
.balanza-corchete.resuelto span { opacity: .8; font-size: .72rem; }
.balanza-corchete.resuelto b { color: var(--tinta); font-weight: 600; }

/* 2. LA NOTA DE LAS TASAS ES UN PIE DE PAGINA, y tiene que verse
      como tal. Estaba pegada a la ultima fila —"no pide nada" y la
      nota casi se tocaban— asi que se leia como un renglon mas de la
      lista en vez de como una aclaracion al margen. */
.desglose .riel-pie {
  margin-top: 1.6rem; padding-top: .9rem;
  border-top: 1px solid var(--linea);
}

/* 3. UNA TASA POR LINEA. Encadenadas con puntos medios, tres tasas
      eran un parrafo que hay que leer entero para encontrar la que
      uno busca. En lineas separadas se barre con la vista. */
.desglose .riel-pie { display: grid; gap: .3rem; }

/* ---- AIRE ALREDEDOR DE LA CIFRA Y LA BALANZA (2026-08-18) ----

   Joel: "esa barra esta totalmente pegada al titulo grande. Que
   respire, es el importante". Tenia razon y era de las seis medidas a
   ojo que la escala de aire vino a arreglar: la cifra, su estado y la
   balanza estaban los tres a distancia de parrafo, asi que se leian
   como un bloque en vez de como tres cosas.

   Se usan los escalones de `base.css` y no numeros nuevos: la cifra y
   su estado son UNA sola idea —van a `--aire-par`— y la balanza es
   otra cosa, asi que va a `--aire-seccion`. Y los corchetes necesitan
   su propio respiro abajo para que no choquen con lo que siga. */
/* ============================================================
   EL PUENTE AL VENCIMIENTO — lo que agrega la etapa 4

   La caja, la franja de color y la balanza ya estaban: esto solo
   suma la cabeza, la cadena de la cuenta y la version compacta de
   las fechas que no son la proxima.
   ============================================================ */

.puente-cabeza {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}
.puente-moneda {
  font-size: var(--t-etiqueta, .72rem);
  color: var(--suave);
  white-space: nowrap;
}

/* ---- LA CADENA DE LA CUENTA ----

   Los montos alineados a la derecha y en columna, que es lo unico
   que deja seguir una suma con el ojo: con las cifras empezando
   donde termine cada texto no se pueden comparar dos renglones. */
.puente-cuenta {
  list-style: none;
  margin: var(--aire-bloque) 0 0;
  padding: 0;
  font-size: .92rem;
}
.puente-cuenta li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: .3rem 0;
  color: var(--suave);
}
.puente-cuenta li b {
  color: var(--tinta);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* La suposicion del goteo, en el renglon que la usa y no al pie:
   al pie se lee como letra chica legal y acá se lee como parte del
   numero, que es lo que es. */
.puente-cuenta em {
  display: block;
  font-style: normal;
  font-size: .78rem;
  opacity: .75;
}
.puente-cuenta-total {
  border-top: 1px solid var(--linea);
  margin-top: .35rem;
  padding-top: .55rem;
}
.puente-cuenta-total span,
.puente-cuenta-total b { color: var(--tinta); font-weight: 640; }

/* ---- LAS FECHAS QUE NO SON LA PROXIMA ----

   Mas compactas y con la cifra grande a la mitad, porque la urgente
   es la de arriba. **No se esconden**: la mala noticia puede ser la
   tercera, y plegarlas obligaria a abrir una por una para
   encontrarla. */
.puente-secundario { margin-top: .7rem; padding: 1rem 1.3rem; }
.puente-secundario .numeron { font-size: 1.6rem; }
.puente-secundario .puente-cuenta { font-size: .86rem; }

.puente .numeron { margin-bottom: var(--aire-par); }
.puente .balanza-estado { margin-bottom: 0; }
.puente .balanza { margin-top: var(--aire-seccion); }
.puente .balanza + * { margin-top: var(--aire-bloque); }
.balanza-fila { height: 2.4rem; }


/* ============================================================
   EL CARRUSEL DE TELEFONO — pedido de Joel el 2026-08-21

   "En vez de ver todas las tarjetas y los recuadros de utilizacion
   hacia abajo, verlos hacia los lados... de esa manera la pantalla
   no se hace eterna."

   ---- SOLO EN TELEFONO, Y ESO ES UNA DECISION ----

   En escritorio la rejilla ya pone dos o tres por fila, o sea que no
   hay pantalla eterna que arreglar, y arrastrar de lado con un mouse
   es incomodo: no hay dedo. Ademas, en un monitor ancho el carrusel
   MUESTRA MENOS que la rejilla — donde caben tres, se veria una.

   ---- LA PIEZA SIGUIENTE ASOMA, Y NO ES DECORACION ----

   `grid-auto-columns` va por debajo del 100% justamente para que se
   vea el canto de la que sigue. Sin eso, un carrusel a pantalla
   completa es indistinguible de una lista de un solo elemento y
   nadie descubre que hay mas. La otra mitad de la señal son los
   puntos de abajo, que los dibuja js/carrusel.js.

   ---- POR QUE SANGRA HASTA EL BORDE ----

   Los margenes negativos llevan el carrusel a los cantos de la
   pantalla y el padding devuelve la primera pieza a su sitio. Con
   eso la que asoma se corta contra el borde del telefono —que es
   como se lee "hay mas de lo que cabe"— en vez de cortarse contra
   un margen blanco, que se lee como un error de maquetado.
   No genera desplazamiento horizontal de pagina: el elemento mide
   exactamente el ancho de la ventana y lo que sobra vive DENTRO de
   su propio overflow.

   ---- EL OVERFLOW NO APLANA NINGUN 3D ----

   `overflow` esta en la lista de lo que aplana un contexto 3D, asi
   que hay que decir por que aca no: el contexto 3D del mazo empieza
   en `.escena` (perspective) y `.tarjeta` (preserve-3d), que son
   DESCENDIENTES de esto. La lista alcanza a los ancestros que estan
   DENTRO de la cadena 3D, y `.mazo` esta fuera. Verificado en vivo:
   la tarjeta sigue girando y el reverso sigue apareciendo pasados
   los 90 grados.
   ============================================================ */
@media (max-width: 720px) {
  .carrusel {
    grid-auto-flow: column;
    grid-auto-columns: 86%;
    grid-template-columns: none;
    overflow-x: auto;
    /* Que llegar al final del carrusel no arrastre la pagina de
       atras, que es lo que hace que un carrusel se sienta pegajoso. */
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;

    margin-inline: -1rem;
    padding-inline: 1rem;
    /* El iman tiene que dejar la pieza donde empieza el contenido,
       no pegada al canto de la pantalla. */
    scroll-padding-inline-start: 1rem;
    /* Aire para que la sombra de la tarjeta no se recorte arriba y
       abajo contra el propio overflow.

       ---- SUBIO DE .4 A .8 EL 2026-08-23, Y NO ES POR LA SOMBRA ----

       Ese dia `.escena` dejo de recortar, asi que la PANZA DEL GIRO
       —la mitad de la tarjeta que se acerca al ojo y se proyecta mas
       grande— pasa a salirse de la caja. En escritorio no molesta
       porque nada recorta; aca si, porque el carrusel tiene su propio
       `overflow-x: auto` y eso arrastra el eje vertical.

       Medido, no estimado: la panza llega a **11,4px por lado, a los
       90 grados**, barriendo la vuelta de 5 en 5. Con los 6,4px que
       habia se recortaban 5. Estos 12,8 la cubren con holgura.

       Si algun dia cambia el alto de la tarjeta o la perspectiva, hay
       que volver a medirlo: sale de las dos cosas y no se deduce. */
    padding-block: .8rem;

    scrollbar-width: none;
  }
  .carrusel::-webkit-scrollbar { display: none; }
  .carrusel > * { scroll-snap-align: start; }

  /* Con una sola pieza no hay carrusel: ocupa el ancho entero y no
     asoma nada, porque no hay nada que asomar. */
  .carrusel:has(> :only-child) { grid-auto-columns: 100%; }

  .carrusel-guia:not([hidden]) {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: .3rem;
    margin-top: .5rem;
  }

  /* El punto se ve de .5rem y el boton mide 30x38: lo que se toca
     con el pulgar no puede medir ocho pixeles. Por eso el color va
     en el ::before y no en el boton.

     Alto y ancho distintos a proposito: el alto es gratis —no hay
     nada arriba ni abajo— y el ancho no se puede subir mas sin
     separar los puntos entre si, que es lo que los convierte en
     cuatro cosas sueltas en vez de una escala. */
  .carrusel-punto {
    appearance: none; -webkit-appearance: none;
    border: 0; background: none; padding: 0; margin: 0;
    width: 1.9rem; height: 2.4rem;
    display: grid; place-items: center;
    cursor: pointer;
  }
  .carrusel-punto::before {
    content: '';
    display: block;
    width: .5rem; height: .5rem;
    border-radius: 999px;
    background: var(--borde-riel);
    transition: width .22s ease, background-color .22s ease;
  }
  /* Se alarga ademas de cambiar de color: el color solo deja fuera a
     quien no lo distingue, y es el mismo motivo por el que la
     tarjeta cerrada lleva insignia ademas del gris. */
  .carrusel-punto[aria-current="true"]::before {
    width: 1.4rem;
    background: var(--acento);
  }

  .carrusel-cuenta {
    margin: 0;
    color: var(--suave);
    font-size: .8rem;
    font-variant-numeric: tabular-nums;
  }
}

/* En escritorio la guia no existe. Va fuera de la media query para
   que este apagada tambien mientras el JavaScript todavia no la
   marco con [hidden]. */
@media (min-width: 721px) {
  .carrusel-guia { display: none; }
}


/* ============================================================
   CENTRADO EN TELEFONO — pedido de Joel el 2026-08-21

   Acota el pendiente 38, que decia "en telefono todo centrado" sin
   decir que era "todo". Lo que se centra es lo que ENCABEZA una
   pantalla o un bloque: el saludo y su bajada en las cinco, el
   titulo del reparto con su frase, y la dona.

   ---- LO QUE NO SE CENTRA, Y POR QUE ----

   Las listas de montos se quedan alineadas a la izquierda. Una
   columna de cifras se compara por su borde, y centrada cada renglon
   empieza en un sitio distinto: el ojo pierde la columna y hay que
   leer numero por numero. Eso incluye la leyenda de la dona, los
   gastos, los ingresos, las tasas y los bolsillos.

   ---- SOLO EN TELEFONO ----

   En escritorio el lienzo mide 76rem. Un titulo centrado ahi flota
   solo, porque nada mas comparte ese eje: el contenido de abajo
   arranca pegado al borde izquierdo. En 375px el titulo ocupa casi
   todo el ancho y centrarlo se lee como portada, que es lo que pidio
   Joel.
   ============================================================ */
@media (max-width: 720px) {
  .saludo, .saludo-pie { text-align: center; }
  /* La bajada acotada y centrada: a lo ancho completo, un parrafo
     centrado de tres renglones parece descuadrado porque el ultimo
     queda muy corto. */
  .saludo-pie { max-width: 30ch; margin-inline: auto; }

  /* El bloque del reparto: su titulo y la frase que evita el
     malentendido de los montos planeados. Van juntos porque son un
     par —titulo y su bajada— igual que el saludo. */
  #seccion-reparto > h2,
  #seccion-reparto > .pista { text-align: center; }
  #seccion-reparto > .pista { max-width: 34ch; margin-inline: auto; }

  /* La dona centrada. `justify-content` y no `margin: auto`: la caja
     es flex y en telefono la dona y su leyenda se apilan, asi que lo
     que hay que centrar es la fila. La LEYENDA no se centra —ver
     arriba— y por eso el centrado va en el contenedor y no en el
     texto. */
  .torta-caja { justify-content: center; }

  /* ---- LOS DOS PARRAFOS DE LA ESTRATEGIA ----

     Quedaban alineados a la izquierda ENTRE el titulo centrado y la
     dona centrada, y el corte se notaba. Joel los mando centrar el
     2026-08-22: "igual si mas adelante quiero cambiarlo te lo diré".

     Se habian dejado a la izquierda porque el segundo tiene tres
     renglones y un parrafo largo centrado se lee peor. Eso sigue
     siendo cierto y es lo que compensa el `max-width`: acotado a 34
     caracteres el ultimo renglon no queda tan corto como para que se
     vea descuadrado, que es lo unico que de verdad afea un parrafo
     centrado.

     NO alcanza a la leyenda de la dona, que va en `.torta-leyenda` y
     es una columna de cifras. */
  #reparto > .pista { text-align: center; max-width: 34ch; margin-inline: auto; }
}


/* ============================================================
   EL ACORDEON DE AJUSTES — pedido de Joel el 2026-08-21

   Cinco renglones cerrados en vez de cuarenta campos a la vista.
   El mecanismo entero es `<details name>` del HTML; esto es solo
   como se ve. El porque de usar <details> esta en ajustes.html.

   Va en app.css y no en base.css a proposito: `saldo.html` carga
   UNA sola hoja y no tiene acordeon. Es el corte de la semana 5.
   ============================================================ */
.acordeon-lista {
  display: flex;
  flex-direction: column;
  gap: .7rem;
  margin-top: 1.5rem;
  /* El ancho de un FORMULARIO y no el del lienzo. A 76rem el ojo
     pierde el renglon entre la etiqueta de la izquierda y el campo
     de la derecha, que es el mismo motivo por el que el presupuesto
     va en dos columnas. Acá no puede ir en dos: el acordeon es una
     lista vertical de renglones y partirla en dos columnas
     desordena el orden de lectura al abrir uno. */
  max-width: 44rem;
}

.acordeon {
  background: var(--superficie-alta);
  border: 1px solid var(--linea);
  border-radius: 12px;
  /* Recorta el cuerpo contra las esquinas curvas al abrirse. Acá no
     hay ningun contexto 3D que aplanar: el acordeon no gira nada. */
  overflow: hidden;
}

.acordeon summary {
  display: flex;
  align-items: center;
  gap: .85rem;
  padding: 1rem 1.15rem;
  cursor: pointer;
  /* El triangulito nativo se quita: ya hay una flecha propia que
     gira, y con los dos se ven dos marcas para lo mismo. */
  list-style: none;
  transition: background-color .18s ease;
}
.acordeon summary::-webkit-details-marker { display: none; }
.acordeon summary:hover { background: var(--superficie); }

/* El foco se marca sobre el renglon entero, que es lo que se
   activa. Sin esto, quien navegue con teclado no ve donde esta. */
.acordeon summary:focus-visible {
  outline: 2px solid var(--acento);
  outline-offset: -2px;
}

.acordeon summary > svg {
  width: 1.25rem; height: 1.25rem; flex: 0 0 auto;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
  color: var(--acento);
}

.acordeon-texto { flex: 1; min-width: 0; }
.acordeon-texto b {
  display: block;
  font-family: var(--titulares);
  font-size: 1.02rem; font-weight: 620;
  color: var(--tinta);
}
/* La linea de abajo es lo que hace que "ir exactamente a donde
   quiere" funcione: sin ella, "Tus datos" no dice si la zona
   horaria esta ahi adentro o en otra seccion. */
.acordeon-texto small {
  display: block;
  color: var(--suave);
  font-size: .82rem;
  margin-top: .12rem;
}

.acordeon-flecha {
  color: var(--suave) !important;
  transition: transform .22s ease;
}
.acordeon[open] > summary .acordeon-flecha { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .acordeon-flecha, .acordeon summary { transition: none; }
}

.acordeon-cuerpo {
  padding: .25rem 1.15rem 1.25rem;
  border-top: 1px solid var(--linea);
}
/* El primer elemento del cuerpo no necesita su margen de arriba: ya
   lo pone el padding, y sumados quedaba el doble de aire que entre
   los campos de adentro. */
.acordeon-cuerpo > :first-child { margin-top: .9rem; }
.acordeon-cuerpo .forma { margin-top: 0; }

/* El rojo va SOLO en el icono, y solo con la seccion cerrada.
   Abierta ya esta el boton rojo abajo, y dos marcas de peligro en
   la misma caja convierten la pantalla en una advertencia — que es
   justo lo que el comentario de esa seccion decia evitar. */
/* Separado del grupo, que es el unico lugar donde el aire dice algo:
   "esto no es un ajuste mas". Es lo mismo que ya hacia el bloque de
   cerrar cuenta yendo al final. */
.acordeon-peligro { margin-top: 1.4rem; }
.acordeon-peligro:not([open]) > summary > svg:first-child { color: var(--malo); }

/* Los enlaces legales: renglones tocables, no una linea de enlaces
   separados por puntos. En telefono tres enlaces seguidos en una
   linea son imposibles de acertar con el pulgar. */
.ajustes-legal { display: flex; flex-direction: column; }
.ajustes-legal a {
  padding: .7rem 0;
  border-bottom: 1px solid var(--linea);
  color: var(--tinta);
  text-decoration: none;
  font-size: .92rem;
}
.ajustes-legal a:last-child { border-bottom: 0; }
.ajustes-legal a:hover { color: var(--acento); }

@media (max-width: 720px) {
  .acordeon summary { padding: .95rem 1rem; }
  .acordeon-cuerpo { padding: .25rem 1rem 1.15rem; }
}


/* ============================================================
   "LO QUE VIENE" — lo que quedo del puente el 2026-08-22

   La caja dejo de dar un veredicto y pasa a decir que se paga y
   cuando. Eso cambia dos cosas de como se ve, y las dos son
   consecuencia y no gusto:

   1. **LA CIFRA NO LLEVA COLOR DE SEMAFORO.** Iba en `--vivo`, que
      es el color del veredicto, y sin veredicto esa variable ya no
      significa nada — de hecho en `.puente-flojo` resuelve a gris,
      asi que el numero mas importante de la caja salia apagado.
      Va en `--tinta`: es un dato, no un juicio.

      Lo unico que si se pinta es la URGENCIA, y es un hecho: si
      vence hoy o manana la caja lleva `puente-malo` y la cifra se
      va al rojo. No hay ningun umbral inventado en el medio.

   2. **LA FECHA DEJA DE IR EN MAYUSCULAS.** Usaba `.tramo`, que es
      la clase del nombre del tramo del semaforo —"ALTO", "CRITICO"—
      y lleva `text-transform: uppercase`. Una etiqueta de tres
      letras en mayuscula se lee de un golpe; "10 DE SEPTIEMBRE DE
      2026 · EN 20 DIAS" ocupa dos renglones y se lee gritando.
      Es la familia de `.tramo` contra `.banda`, otra vez: una clase
      que describe un ESTADO reusada para un DATO.
   ============================================================ */
.cifra-neutra { color: var(--tinta); }
.puente-malo .cifra-neutra { color: var(--malo-vivo); }

.viene-cuando {
  color: var(--suave);
  font-size: .92rem;
  margin-top: .2rem;
}


/* ============================================================
   EL RECUADRO DE LA TARJETA — rehecho el 2026-08-22

   Joel: "ese menú desplegable al voltearse me parece excesivo; mi
   idea al principio era que se volteara la tarjeta y justo detrás
   estuvieran las casillas, pero sin expandirse, que estuvieran en
   el mismo tamaño de la tarjeta al voltear".

   ---- EL ALTO NO CAMBIA NUNCA, Y ESA ES LA REGLA ----

   El recuadro son el plástico Y la fila de botones, girando juntos.
   Las dos caras miden exactamente eso, así que girar no mueve nada
   de la página. Con esto se fue toda la coreografía de altura, que
   era la pieza más frágil del mazo.

   ---- CUÁNTO ESPACIO HAY, MEDIDO ----

     escritorio (2 columnas) .... 477 x 300 + 38 de botones = 346 px
     teléfono (carrusel) ........ 295 x 186 + 38 de botones = 232 px

   Ocho campos en 232 px obligan a filas de ~46 px. Por eso el
   reverso usa campos compactos y la etiqueta ENCIMA en letra chica:
   una etiqueta al lado comería el ancho que necesitan las cifras.
   ============================================================ */

/* La rejilla de atrás: cuatro filas de dos. Los pares no son
   casuales —cada fila son dos datos del mismo hecho— así que leer
   de a filas no obliga a saltar de tema. */
/* ---- LAS FILAS SE REPARTEN EL ALTO, NO SE APELOTONAN ARRIBA ----

   Joel, el 2026-08-22: "en la parte de atras queda un espacio muy
   grande entre la ultima linea y los botones. Podrias repartir mejor
   esas 8 casillas, con una jerarquia de separacion igual entre todos
   los elementos y aprovechando al maximo esa parte de atras".

   Tenia `align-content: start`, o sea que las cuatro filas se pegaban
   arriba y TODO el aire sobrante caia de golpe antes de los botones.
   Con las filas en `1fr` el alto se reparte parejo entre las cuatro y
   el hueco desaparece: cada fila crece un poco en vez de que sobre un
   hueco grande al final.

   Es la misma idea de la escala de aire de `base.css`: la distancia
   tiene que significar algo, y un hueco de 40px que aparece solo
   porque sobro sitio no significa nada. */
/* ---- Y DESDE EL 2026-08-23 LOS BOTONES SON DOS FILAS MAS ----

   Joel: "que el espaciado entre todas las casillas sea igual, incluso
   contando las casillas de Guardar y Cancelar en relacion a las de
   arriba. Que las 8 casillas y los 2 botones queden todos simetricos
   perfectos en todo el recuadro".

   Guardar y Cancelar dejaron de vivir en su propia fila flex y pasan
   a ser DOS ITEMS MAS de esta cuadricula. Con eso caen solos en la
   quinta fila, uno por columna, alineados con los ocho campos de
   arriba. No hay forma de que se desalineen porque no hay dos
   sistemas que sincronizar: es la misma cuadricula.

   ---- `space-between` Y NO FILAS DE `1fr` ----

   Tenia `grid-auto-rows: 1fr`, o sea filas de altura IGUAL. Eso
   reparte el aire DENTRO de cada fila, no entre ellas — y como cada
   campo esta pegado abajo de la suya (`justify-content: end`), el
   aire caia arriba de la etiqueta. Con la fila de botones, que no
   tiene etiqueta, ese aire habria quedado como un hueco grande justo
   antes de Guardar: exactamente el hueco que Joel mando quitar el
   2026-08-22, de vuelta un escalon mas abajo.

   Con filas de altura natural y `align-content: space-between`, el
   aire sobrante se reparte EN PARTES IGUALES entre todas las
   junturas, la de los botones incluida. Eso es, literalmente, lo que
   se pidio: una sola distancia en toda la cara.

   Y aguanta que falte una fila: sin ciclo conocido no se dibujan
   pago minimo ni pago total, quedan cuatro filas en vez de cinco, y
   el reparto sigue siendo parejo sin tocar nada. */
.detras-rejilla {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: auto;
  gap: .3rem .45rem;
  align-content: space-between;
  flex: 1 1 auto;
  min-height: 0;
}

/* Los dos botones, exactamente del alto de un campo. Ese numero no
   es decorativo: es el mismo `1.75rem` de los inputs, y por eso la
   quinta fila se lee como una fila mas y no como un pie. */
.detras-rejilla > button {
  margin-top: 0;
  width: 100%; min-width: 0;
  height: 1.75rem; min-height: 1.75rem;
  padding: .1rem .4rem;
}
.detras-rejilla > label {
  display: flex;
  flex-direction: column;
  /* El campo pegado ABAJO: las etiquetas del pais son de largo
     variable —"corte" mide una linea y "fecha limite de pago" dos—
     y sin esto la fila se descuadraba, con un campo mas arriba que
     el otro. Asi los dos campos de una fila quedan alineados pase
     lo que pase con el texto de arriba. */
  justify-content: end;
  gap: .1rem;
  font-size: .64rem;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: .02em;
  color: var(--suave);
  margin: 0;
  min-width: 0;
}
/* El alto, el relleno y la fuente NO van aca: los pone la regla de
   `.cara-detras input[type=...]`, que pesa mas. Ver alla. */
.detras-rejilla > label > input,
.detras-rejilla > label > select {
  width: 100%;
  font-variant-numeric: tabular-nums;
}
/* La casilla "Abierta" se quito el 2026-08-23 —decision de Joel, ver
   mazo.js— y con ella `.detras-acciones .casilla`. No queda ningun
   marcado que las pida. */

.cara-detras .aviso { min-height: 0; margin: 0; font-size: .74rem; }
.cara-detras .aviso:empty { display: none; }

/* ============================================================
   LO ESTÉTICO SE ESCRIBE SOBRE EL PLÁSTICO

   El banco y los últimos cuatro son campos de texto encima de la
   tarjeta, no filas de un formulario. Se escriben donde se ven.

   ---- SIN RECUADRO HASTA QUE SE TOCAN ----

   En una tarjeta de verdad el nombre del banco tampoco lleva un
   rótulo que diga "banco". El campo se ve como texto y solo al
   enfocarlo aparece el marco — así el plástico sigue pareciendo un
   plástico y no un formulario pintado de colores.

   ---- EL COLOR LO HEREDA, Y ESO ES LO QUE LO HACE FUNCIONAR ----

   `color: inherit` y fondo transparente: sobre una tarjeta negra el
   texto es blanco y sobre una blanca es tinta oscura, porque
   `.cara-frente.clara` ya da vuelta la tinta de toda la cara. Un
   color propio habría que definirlo dos veces y se rompería en uno
   de los dos extremos.
   ============================================================ */
input.escrito-encima {
  border: 1px solid transparent;
  background: transparent;
  color: inherit;
  font: inherit;
  padding: .05rem .25rem;
  margin: 0;
  min-height: 0;
  border-radius: 6px;
  width: 100%;
  transition: background-color .15s ease, border-color .15s ease;
}
input.escrito-encima::placeholder { color: currentColor; opacity: .5; }
input.escrito-encima:hover { border-color: rgba(255,255,255,.22); }
.cara-frente.clara input.escrito-encima:hover { border-color: rgba(16,20,43,.22); }
input.escrito-encima:focus {
  outline: none;
  background: rgba(0,0,0,.35);
  border-color: rgba(255,255,255,.55);
}
.cara-frente.clara input.escrito-encima:focus {
  background: rgba(255,255,255,.55);
  border-color: rgba(16,20,43,.45);
}

input.nombre-banco {
  font-weight: 640;
  /* .95 y no 1rem: medido, "Banco de la Cordillera" pedia 175px y el
     hueco es de 169. Un input siempre se desplaza si el texto no
     cabe —eso es normal y no es un bug— pero un nombre de banco
     corriente tiene que entrar entero sin tocarlo. */
  font-size: .95rem;
  /* Que no empuje a la insignia a otro renglon: la fila es flex y
     sin esto un banco de nombre largo se lleva todo el ancho. */
  flex: 1 1 6rem; min-width: 0;
}
/* Los cuatro dígitos viven dentro de la fila de puntos, así que el
   campo mide lo que miden cuatro cifras y ni un píxel más. */
.digitos input.cuatro {
  width: 4.2em;
  letter-spacing: .18em;
  font-variant-numeric: tabular-nums;
}

/* ---- EL PANEL DEL COLOR ----
   Ocupa el sitio de los botones, no el de la tarjeta: lo que hay
   que estar mirando mientras se arrastra es el plástico. */
/* Los tres botones en UNA fila, siempre. A 295px se envolvian en
   dos y eso hacia que el recuadro de una tarjeta activa midiera 51px
   mas que el de una pausada. Con `min-width: 0` y texto corto caben
   los tres. */
.mazo-acciones > button { min-width: 0; padding-inline: .5rem; }

/* ---- POR QUE EL BOTON SE COMIA EL PANEL ----
   `.secundario` trae `width: 100%` de base.css, y con `flex: 0 0 auto`
   el flex-basis es ese width: el boton "Listo" pedia el contenedor
   entero y los dos deslizadores quedaban en cero. Joel lo vio en
   Safari: "solo se ve el boton de listo larguisimo y no se ven los
   colores".
   Hay que anular el width ADEMAS de fijar el flex — con uno solo no
   alcanza, que es justo lo que fallaba. */
.panel-color {
  display: flex; align-items: center; gap: .5rem;
}
.panel-color[hidden] { display: none; }
.panel-color .rueda {
  flex: 1 1 0;
  min-width: 0;          /* si no, el `width: 100%` de la rueda no deja encoger */
  width: auto;
  margin: 0;
}
.panel-color > button {
  flex: 0 0 auto;
  width: auto;           /* <- lo que faltaba */
  margin: 0;
  padding: .45rem .8rem;
  min-height: 0;
}
.mazo-acciones[hidden] { display: none; }

/* El eco del disponible, dentro de su etiqueta: "Disponible hoy ·
   debes COP 1.700.000". Ver el porqué en mazo.js. */
.detras-rejilla [data-eco] { font-weight: 500; opacity: .85; }
.detras-rejilla [data-eco].eco-malo { color: var(--malo); opacity: 1; font-weight: 700; }


/* ============================================================
   LA MÁQUINA DE GASTOS

   Sale de `herramientas/maquina2.html` el 2026-08-23, al montarla en
   `presupuesto.html`. La dibuja `js/maquina.js`, que construye el
   marcado entero: aquí no hay nada que buscar en el HTML de la
   pantalla.

   ---- TODAS LAS CLASES VAN PREFIJADAS, Y NO ES PROLIJIDAD ----

   En la herramienta se llamaban `.escena`, `.consola`, `.tecla`… y
   **`.escena` YA EXISTE en esta misma hoja**: es la escena 3D del
   mazo de tarjetas, con su `perspective`. Montada con ese nombre, la
   máquina habría heredado reglas que no son suyas — que es
   exactamente lo que `.tramo` le hizo a la landing, dejándola escrita
   en mayúsculas dos semanas sin que nadie lo notara.

   Se comprobaron los diecinueve nombres contra `base.css`, `app.css`
   e `inicio.css` antes de mover una línea. Chocaban dos.

   ---- Y NO ESTÁN LAS VARIANTES ----

   El panel de la herramienta montaba cuatro tipografías del total,
   tres colores, cinco formas de tecla y cuatro del rótulo del frasco.
   Existían para elegir mirando; Joel eligió el 2026-08-23 y aquí solo
   está lo elegido. Un mecanismo sin consumidor invita a que alguien
   lo toque creyendo que hace algo.
   ============================================================ */

/* La escena, con la proporción del render. Todo lo de adentro se
   estira con ella. `--ue` es la centésima parte de su ancho REAL, y
   lo escribe el JavaScript con un ResizeObserver: no se usa `cqw`
   porque en Safari no sigue al zoom, y el arreglo no depende de
   acertar por qué. El valor de aquí es solo el de arranque. */
.maquina {
  position: relative;
  aspect-ratio: 4 / 3;
  width: 100%;
  --ue: 11.2px;
}
/* `picture` también se posiciona: es un elemento más en el flujo, y
   sin esto el `<img>` de adentro se ancla a él y no a la escena. */
.maquina picture, .maquina img, .maquina canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block;
}
/* ---- EL CANVAS VA ENCIMA, Y NO ERA LO PREVISTO ----
   La idea era ponerlo debajo para que la bola se viera a través del
   vidrio. No funciona: el vidrio del render está pintado con mucha
   opacidad y tapaba las bolas por completo. Lo que se pierde es el
   vidrio POR DELANTE de la bola, y eso se recupera el día que haga
   falta exportando una segunda imagen solo con los reflejos. */
.maquina picture { z-index: 1; pointer-events: none; }
.maquina canvas  { z-index: 2; cursor: pointer; }

/* ---- LA CONSOLA VA SOBRE LA PANTALLA DEL RENDER ----
   Los límites están MEDIDOS contra la imagen —corridas contiguas de
   píxeles oscuros, no a ojo—: la pantalla va de x .4183 a .5800 y de
   y .2967 a .7378, centrada en .4992. Por eso el `left` no es un 50%
   redondo: la diferencia son 0,9 px y se veía al medir los dos
   márgenes. */
.maq-consola {
  position: absolute; z-index: 3;
  left: 42.72%; top: 30.9%; width: 14.4%; height: 41.7%;
  --u: 1.6px;
}
.maq-pila {
  height: 100%;
  display: flex; flex-direction: column; gap: calc(2.6 * var(--u));
}
/* Nada se encoge: si algún día el contenido no cabe, tiene que verse
   desbordando la pantalla y no achatándose. Un item flex que se
   encoge en silencio se ve como un campo mal diseñado, no como un
   bug. */
.maq-pila > * { flex-shrink: 0; }

.maq-consola input {
  width: 100%; min-height: 0; margin: 0;
  padding: calc(2.6 * var(--u)) calc(3 * var(--u));
  font-size: calc(8.6 * var(--u)); line-height: 1.15;
  border-radius: calc(2.5 * var(--u));
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.18);
  color: #fff;
  /* ---- ESTA LÍNEA ARREGLA UN BUG DE SAFARI ----
     Joel veía el cursor titilando en el MEDIO del campo vacío, y al
     escribir el texto se iba a la izquierda. En el Mac. No se
     reproducía en Chromium —`text-align` computa `start` en el campo
     y en sus seis ancestros— así que no se aplicó una hipótesis: se
     montaron tres interruptores y él confirmó que el que lo arregla
     es éste. Safari no trata igual el `start` HEREDADO que el `left`
     ESCRITO. */
  text-align: left;
}
.maq-consola input:focus { border-color: rgba(255,255,255,.5); outline: none; }
/* El campo que falta, en un rojo que NO flipea con el tema: la
   pantalla de la máquina es una fotografía y no lo tiene. Va DESPUÉS
   de la regla del foco, o tocar el campo apagaría el aviso justo
   cuando la persona va a leerlo. */
.maq-consola input.maq-falta,
.maq-consola input.maq-falta:focus {
  border-color: var(--malo-vivo);
  box-shadow: 0 0 0 1px var(--malo-vivo),
              0 0 calc(3 * var(--u)) rgba(255,59,71,.45);
}

.maq-consola .maq-rotulo {
  font-size: calc(6 * var(--u)); margin-bottom: calc(-1.6 * var(--u));
  letter-spacing: .08em; text-transform: uppercase;
  color: rgba(255,255,255,.5);
}
/* La moneda del gasto, dentro del propio rótulo. Un botón y no un
   `<select>`: en 161 px no cabe un selector de 155 opciones, así que
   cicla entre las que la persona ya usa. Va como `<button>` de verdad
   para que reciba el foco y un lector de pantalla lo anuncie. */
.maq-consola .maq-moneda {
  font: inherit; letter-spacing: inherit; text-transform: inherit;
  color: rgba(255,255,255,.72);
  background: none; border: 0; padding: 0; margin: 0;
  width: auto; min-height: 0; cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: calc(.6 * var(--u));
}
.maq-consola .maq-moneda:hover { color: #fff; }
.maq-consola .maq-moneda:focus-visible { outline: 1px solid #fff; outline-offset: 2px; }
/* Con una sola moneda no puede hacer nada, y un control que no hace
   nada se lee como que está roto. */
.maq-consola .maq-moneda[disabled] {
  color: rgba(255,255,255,.5); cursor: default; text-decoration: none;
}

/* ---- LAS CUATRO TECLAS, EN EL ORDEN DE LOS FRASCOS ----
   Tocar la categoría ES guardar: un toque menos, y el destino de la
   bola y la acción son la misma cosa. El orden no está escrito en
   ningún sitio — las teclas se construyen recorriendo los frascos, así
   que si algún día se mueve uno, su tecla se mueve sola.
   El aire sobrante se reparte a los DOS lados: con `margin-top: auto`
   todo caía encima y las teclas quedaban pegadas al total. */
.maq-teclas {
  margin-block: auto;
  display: grid; grid-template-columns: 1fr 1fr;
  padding-inline: calc(6 * var(--u));
  gap: calc(9 * var(--u)) calc(8 * var(--u));
}
/* Cada tecla es un bloque entero, con su rótulo dentro. El relleno va
   con el color rebajado sobre el negro y el filo con un anillo del
   color pleno: así el rótulo puede seguir siendo blanco —sobre
   `--cat-ahorro` puro, un verde clarísimo, no se leería—. */
.maq-tecla {
  min-width: 0;
  display: flex; flex-direction: column; gap: calc(1.8 * var(--u));
  border: 0; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  background: color-mix(in srgb, var(--c) 22%, transparent);
  border-radius: calc(3.4 * var(--u));
  padding: calc(3.6 * var(--u)) calc(1.6 * var(--u));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c) 72%, transparent);
  transition: transform .14s ease, background-color .14s ease;
}
.maq-tecla i {
  font-size: calc(19 * var(--u)); line-height: 1; font-style: normal;
  text-align: center;
}
/* 4,9 y no más: medido con un `Range` sobre el texto de verdad,
   «NECESIDAD» es la palabra más larga de las cuatro y se salía del
   botón. La caja del elemento mide la celda y no las letras, así que
   mirar el ancho del elemento no lo delata — hay que medir el TEXTO.
   Con `overflow: hidden` de red, por si algún día entra una categoría
   con un nombre más largo. */
.maq-tecla b {
  font-size: calc(4.9 * var(--u)); font-weight: 700; letter-spacing: .03em;
  text-transform: uppercase; line-height: 1; text-align: center;
  color: color-mix(in srgb, var(--c) 55%, #fff);
  white-space: nowrap; max-width: 100%; overflow: hidden;
}
.maq-tecla:hover {
  transform: translateY(-3%);
  background: color-mix(in srgb, var(--c) 34%, transparent);
}
.maq-tecla:active { transform: scale(.96); transition-duration: .06s; }
.maq-tecla:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* ---- LA BARRA DE LO SELECCIONADO, CON LA X DE BORRAR ----
   El sitio está SIEMPRE reservado (`visibility` y no `display`): si
   apareciera y desapareciera, tocar una bola movería los campos y las
   teclas hacia abajo justo cuando la persona va a leerlos. */
.maq-sel {
  display: flex; align-items: center; gap: calc(2 * var(--u));
  min-height: calc(11 * var(--u)); visibility: hidden;
}
.maq-sel.visible { visibility: visible; }
.maq-sel-nombre {
  flex: 1; min-width: 0;
  font-size: calc(6 * var(--u));
  letter-spacing: .05em; text-transform: uppercase;
  color: rgba(255,255,255,.5);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* La X va DIBUJADA en SVG y no como emoji ni como el carácter ✕:
   cuánto aire trae un glifo y dónde queda su centro depende de la
   tipografía de cada persona, que es por lo que el interruptor de
   tema dejó de usar ☀ y ☾. */
.maq-equis {
  flex: 0 0 auto;
  width: calc(11 * var(--u)); height: calc(11 * var(--u)); padding: 0;
  border: 0; border-radius: 50%; cursor: pointer;
  background: var(--malo-vivo);
  display: grid; place-items: center;
  box-shadow: 0 calc(.6 * var(--u)) calc(1.8 * var(--u)) rgba(0,0,0,.5);
  transition: transform .14s ease;
}
.maq-equis:hover { transform: scale(1.12); }
.maq-equis:active { transform: scale(.9); transition-duration: .06s; }
.maq-equis svg { width: 62%; height: 62%; display: block; }
.maq-equis path { stroke: #fff; stroke-width: 3.4; stroke-linecap: round; fill: none; }

/* ---- EL RÓTULO DE CADA FRASCO ----
   Fuera de la imagen, para que se pueda traducir y siga al tema. Sale
   de `--ue` y no de `clamp(rem, vw, rem)`: con el clamp, al hacer zoom
   el piso en `rem` congelaba la letra mientras el frasco seguía
   encogiendo, y el monto acababa ocupando 1,046 veces el ancho
   interior. `clamp(rem, vw, rem)` está bien para texto que solo tiene
   que ser legible, y es un bug para texto que tiene que CABER dentro
   de algo que escala distinto.

   Blancos y con contorno, y sin el nombre: el vidrio del frasco es un
   gris fijo (81,81,83) porque es una fotografía, y ahí `--tinta` y
   `--cat-*` daban entre 1,19 y 2,39 de contraste. Así pasan 4,5 en
   los dos temas. */
.maq-frasco {
  position: absolute; z-index: 3;
  transform: translate(-50%, 0);
  text-align: center; pointer-events: none;
}
.maq-frasco b { display: none; }
.maq-frasco span {
  display: block;
  font-size: calc(1.23 * var(--ue));
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: #fff;
  text-shadow: 0 0 calc(.18 * var(--ue)) rgba(0,0,0,.95),
               0 calc(.06 * var(--ue)) calc(.1 * var(--ue)) rgba(0,0,0,.9);
}

/* ---- EL MARCADOR ----
   Blanco fijo y no `var(--acento)`: la pantalla es una fotografía y no
   tiene tema, mientras que el acento sí — en tema claro daba 2,26 de
   contraste, por debajo del mínimo. Y no puede ser ninguno de los
   cuatro colores de categoría: sus teclas están tres centímetros más
   arriba y un total verde se leería «ahorro». */
.maq-marcador {
  --tinta-total: #fff;
  padding-top: calc(2.4 * var(--u));
  border-top: 1px solid rgba(255,255,255,.14);
  display: flex; flex-direction: column; gap: calc(3.6 * var(--u));
}
.maq-marcador-rot {
  font-size: calc(5.4 * var(--u));
  letter-spacing: .1em; text-transform: uppercase;
  color: rgba(255,255,255,.45);
}
/* ---- LA CIFRA VIVE EN UNA VENTANA DE ALTO FIJO ----
   Antes el alto salía de la proporción de la cifra, así que al pasar
   de 7 a 8 dígitos el bloque encogía y TODO lo de arriba se movía: las
   teclas reparten lo que sobra, y lo que sobraba acababa de cambiar.
   Lo vio Joel. `--alto-cifra` lo escribe el JavaScript desde su propia
   proporción — copiado aquí se desincronizaría. */
.maq-ventana {
  height: calc(var(--alto-cifra, 18.5) * var(--u));
  display: flex; align-items: center;
}
.maq-ventana > * { width: 100%; }
.maq-marcador svg { width: 100%; height: auto; display: block; }

/* La cifra también va como texto, escondida a la vista pero legible
   para un lector de pantalla: unos puntos no se leen. */
.maq-oculto {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%);
}

/* ---- MÁQUINA EN ESCRITORIO, LISTA EN TELÉFONO ----
   Decidido por Joel el 2026-08-23. La forma de teléfono de la máquina
   —la máquina en el medio con la pantalla que se corre— es el
   pendiente 53d y no está construida: medido, a 375 px de escena la
   letra de la consola queda en 4,2 px. La lista ya funciona ahí, así
   que se publica sin esperarla.
   El corte es el mismo de la barra lateral, para no inventar un
   tercer sitio donde la app decide qué es un teléfono. */
@media (max-width: 767px) { .maquina { display: none; } }
@media (min-width: 768px) { .gastos-en-lista { display: none; } }

/* ---- LOS GASTOS OCUPAN LA FILA ENTERA, Y NO ES ESTÉTICA ----

   Con la máquina montada, `#seccion-lineas` en una de las dos columnas
   deja la consola en **79 px**: medido, el rótulo de las teclas cae a
   3,87 px y el campo del monto a 6,8. O sea el mismo problema que en
   teléfono, pero en escritorio — y la máquina ya está pensada para
   161 px, que es lo que da la fila completa.

   Va también «Tus ingresos», porque si no queda un hueco enorme a su
   derecha: con los gastos ocupando toda la fila, ingresos se quedaría
   solo en la primera columna. Y ancha se ve mejor, que es lo mismo que
   se dijo de los fondos el 2026-08-16 — una rejilla de recuadros
   dentro de media pantalla deja uno por fila.

   Solo de 768 para arriba: por debajo la máquina no se dibuja y la
   lista de gastos vive mejor en una columna. */
@media (min-width: 768px) {
  .dos-columnas > #seccion-ingreso,
  .dos-columnas > #seccion-lineas { grid-column: 1 / -1; }
}
