/* Copiado de docs/modelo-visual.html, que es la fuente de verdad del diseno.
   Si hace falta un componente nuevo, se agrega alla primero.
   Solo se sacan los selectores del conmutador y la ventana falsa. */
/* ═══ TOKENS ═══════════════════════════════════════════════════════
     Claro por defecto. El oscuro se redefine dos veces: por preferencia
     del sistema, y por eleccion explicita. Ningun color se define solo
     adentro de un bloque de tema.                                      */
  :root {
    --canvas:  #fbfbfa;
    --surface: #ffffff;
    --hueco:   #f7f6f3;
    --borde:   #eaeaea;
    --borde-f: #c9c8c4;
    --ink:     #2f3437;
    --muted:   #787774;
    --tenue:   #9b9a97;
    --cero:    #c2c1be;
    --fila:    #fcfcfb;
    --calido:  #fbf7ed;

    --solido-f: #111111;
    --solido-t: #ffffff;
    --solido-h: #333333;

    --verde-f: #edf3ec;  --verde-t: #346538;  --verde-p: #7fae82;
    --ambar-f: #fbf3db;  --ambar-t: #956400;  --ambar-p: #d4ad57;
    --rojo-f:  #fdebec;  --rojo-t:  #9f2f2d;  --rojo-p:  #c97b76;
    --azul-f:  #e1f3fe;  --azul-t:  #1f6c9f;
    --serie-tarjeta: #3b73b8;  --serie-prestamo: #2a9d6e;  --grilla: #f0efec;
    --esqueleto: #f0efec;  --brillo: #f8f7f5;

    --luz: rgba(180,150,110,.05);
    --sombra: rgba(0,0,0,.04);

    --sans:  "Geist", "SF Pro Display", "Helvetica Neue", sans-serif;
    --serif: "Newsreader", "Lyon Text", Georgia, serif;
    --mono:  "Geist Mono", "SF Mono", ui-monospace, monospace;
  }

  @media (prefers-color-scheme: dark) {
    :root:not([data-tema="claro"]) {
      --canvas:  #1b1b19;
      --surface: #222220;
      --hueco:   #282826;
      --borde:   #343432;
      --borde-f: #4a4a46;
      --ink:     #e9e8e4;
      --muted:   #a1a09b;
      --tenue:   #7c7b76;
      --cero:    #55544f;
      --fila:    #272725;
      --calido:  #2a2519;

      --solido-f: #e9e8e4;
      --solido-t: #1b1b19;
      --solido-h: #ffffff;

      --verde-f: #1e2a1f;  --verde-t: #8fc293;  --verde-p: #6f9c73;
      --ambar-f: #2e2717;  --ambar-t: #ddb469;  --ambar-p: #b3903f;
      --rojo-f:  #2e1c1c;  --rojo-t:  #e2918c;  --rojo-p:  #b06b66;
      --azul-f:  #17242e;  --azul-t:  #85bcdd;
      --serie-tarjeta: #4f8ad0;  --serie-prestamo: #2e9e70;  --grilla: #2b2b29;
      --esqueleto: #2b2b29;  --brillo: #343431;

      --luz: rgba(190,160,115,.045);
      --sombra: rgba(0,0,0,.3);
    }
  }

  :root[data-tema="oscuro"] {
    --canvas:  #1b1b19;
    --surface: #222220;
    --hueco:   #282826;
    --borde:   #343432;
    --borde-f: #4a4a46;
    --ink:     #e9e8e4;
    --muted:   #a1a09b;
    --tenue:   #7c7b76;
    --cero:    #55544f;
    --fila:    #272725;
    --calido:  #2a2519;

    --solido-f: #e9e8e4;
    --solido-t: #1b1b19;
    --solido-h: #ffffff;

    --verde-f: #1e2a1f;  --verde-t: #8fc293;  --verde-p: #6f9c73;
    --ambar-f: #2e2717;  --ambar-t: #ddb469;  --ambar-p: #b3903f;
    --rojo-f:  #2e1c1c;  --rojo-t:  #e2918c;  --rojo-p:  #b06b66;
    --azul-f:  #17242e;  --azul-t:  #85bcdd;
    --serie-tarjeta: #4f8ad0;  --serie-prestamo: #2e9e70;  --grilla: #2b2b29;
    --esqueleto: #2b2b29;  --brillo: #343431;

    --luz: rgba(190,160,115,.045);
    --sombra: rgba(0,0,0,.3);
  }

  * { box-sizing: border-box; }

  html { background: var(--canvas); }
  body {
    margin: 0;
    background: var(--canvas);
    color: var(--ink);
    font: 400 15px/1.6 var(--sans);
    -webkit-font-smoothing: antialiased;
    padding: 2.5rem 1.5rem 4rem;
    transition: background .25s, color .25s;
  }
  body::before {
    content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
    background: radial-gradient(60rem 40rem at 50% -10%, var(--luz), transparent 70%);
  }

  .envoltorio { max-width: 84rem; margin: 0 auto; }

  

  /* ── ventana ───────────────────────────────────────────────────── */
  .ventana {
    background: var(--surface); border: 1px solid var(--borde);
    /* clip y no hidden: hidden haría que el pie de la barra se pegue a la
       ventana en vez de a la pantalla (ver .pie-lateral). */
    border-radius: 12px; overflow: clip;
    transition: background .25s, border-color .25s;
  }

  /* minmax(0, 1fr) y no 1fr: un track 1fr tiene min-width auto, asi que una
     tabla ancha lo empuja mas alla de la pantalla en vez de scrollear adentro. */
  .app { display: grid; grid-template-columns: 13.5rem minmax(0, 1fr); min-height: 36rem; }

  /* ── barra lateral ─────────────────────────────────────────────── */
  aside {
    border-right: 1px solid var(--borde); background: var(--hueco);
    padding: 1.35rem 0; display: flex; flex-direction: column;
  }
  /* El logo (25/09): la cara del jefe de equipo, rulos, ojos cerrados y bigote.
     Sin cuadrado y en el gris de los textos secundarios (28/09): acompaña, no grita. */
  .marca { padding: 0 1.25rem 1.35rem; display: flex; align-items: center; gap: .65rem; }
  .marca svg { flex: none; display: block; }
  .marca b { display: block; font: 500 .95rem/1.2 var(--sans); letter-spacing: -.01em; }
  /* En bloque y con interlineado justo: si no, sobra aire debajo y el logo se
     centra contra ese aire en vez de contra las letras. */
  .marca span { display: block; font-size: .78rem; line-height: 1.3; color: var(--tenue); }

  aside nav { display: flex; flex-direction: column; gap: 1px; padding: 0 .6rem; }
  aside nav a {
    display: flex; align-items: center; gap: .6rem;
    padding: .45rem .65rem; border-radius: 6px;
    font-size: .88rem; color: var(--muted); text-decoration: none;
    transition: background .18s, color .18s;
  }
  aside nav a:hover { background: var(--surface); color: var(--ink); }
  aside nav a.activo {
    background: var(--surface); color: var(--ink); font-weight: 500;
    border: 1px solid var(--borde); padding-block: calc(.45rem - 1px);
  }
  aside nav a .punto { width: 6px; height: 6px; border-radius: 9999px; background: var(--tenue); flex: none; }
  aside nav a .punto.ok { background: var(--verde-p); }
  aside nav a .punto.espera { background: var(--ambar-p); }
  aside nav a .punto.mal { background: var(--rojo-p); }
  aside nav a .globo {
    margin-left: auto; font: 500 .68rem var(--mono);
    background: var(--rojo-f); color: var(--rojo-t);
    padding: .1rem .35rem; border-radius: 9999px;
  }
  aside nav .titulo {
    font: 500 .67rem/1 var(--mono); letter-spacing: .09em; text-transform: uppercase;
    color: var(--tenue); padding: 1.1rem .65rem .5rem;
  }

  /* El selector de tema (05/10, opción B): abajo de la barra como siempre, pero
     fijo al pie de la pantalla, así no hay que bajar hasta el final para verlo.
     Tiene fondo propio de lado a lado para que el menú no se vea por detrás. */
  .pie-lateral {
    position: sticky; bottom: 0; margin-top: auto;
    padding: 1.1rem 1.85rem 1.1rem; background: var(--hueco);
  }
  .pie-lateral::before { content: ""; position: absolute; top: 0; left: .6rem; right: .6rem; border-top: 1px solid var(--borde); }
  .tema { display: flex; gap: .2rem; background: var(--surface); border: 1px solid var(--borde); border-radius: 7px; padding: 2px; }
  .tema button {
    flex: 1; font: 500 .72rem var(--sans); color: var(--muted);
    background: transparent; border: 0; border-radius: 5px; padding: .28rem .2rem; cursor: pointer;
    transition: background .18s, color .18s;
  }
  .tema button:hover { color: var(--ink); }
  .tema button[aria-pressed="true"] { background: var(--hueco); color: var(--ink); }
  .tema button:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }

  /* ── contenido ─────────────────────────────────────────────────── */
  main { padding: 2.25rem 2.25rem 2.75rem; }
  .vista[hidden] { display: none; }

  .titular {
    margin-bottom: 1.75rem;
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap;
  }
  .titular h1 { margin: 0 0 .2rem; font: 400 1.95rem/1.1 var(--serif); letter-spacing: -.025em; }
  .titular p { margin: 0; color: var(--muted); font-size: .92rem; }

  .etiqueta {
    display: inline-flex; align-items: center;
    font: 500 .65rem/1 var(--sans); letter-spacing: .06em; text-transform: uppercase;
    padding: .32rem .55rem; border-radius: 9999px;
  }
  .etiqueta.ok    { background: var(--verde-f); color: var(--verde-t); }
  .etiqueta.espera{ background: var(--ambar-f); color: var(--ambar-t); }
  .etiqueta.mal   { background: var(--rojo-f);  color: var(--rojo-t); }
  .etiqueta.info  { background: var(--azul-f);  color: var(--azul-t); }

  .tarjetas { display: grid; gap: .9rem; }
  .tarjeta {
    border: 1px solid var(--borde); border-radius: 10px; background: var(--surface);
    padding: 1.4rem 1.5rem;
    transition: box-shadow .2s, border-color .25s, background .25s;
    animation: entrar .6s cubic-bezier(.16,1,.3,1) backwards;
    animation-delay: calc(var(--i, 0) * 70ms);
  }
  .tarjeta:hover { box-shadow: 0 2px 8px var(--sombra); }
  @keyframes entrar { from { opacity: 0; transform: translateY(12px); } }

  .tarjeta-alto { display: flex; align-items: center; gap: .7rem; margin-bottom: .55rem; flex-wrap: wrap; }
  .tarjeta-alto h2 { margin: 0; font: 500 1.02rem/1.3 var(--sans); letter-spacing: -.01em; }
  .tarjeta-alto .hora { margin-left: auto; font: 400 .78rem var(--mono); color: var(--tenue); }

  .tarjeta p { margin: 0; color: var(--muted); font-size: .9rem; max-width: 60ch; }
  .tarjeta p code, .celdilla code {
    font: 400 .86em var(--mono); background: var(--hueco);
    padding: .1em .35em; border-radius: 4px; color: var(--ink);
  }
  .tarjeta p b { color: var(--ink); font-weight: 500; }

  .metricas {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
    gap: 1.5rem; margin: 1.15rem 0 0;
  }
  .metrica dt {
    font: 500 .67rem/1 var(--mono); letter-spacing: .08em; text-transform: uppercase;
    color: var(--tenue); margin-bottom: .35rem;
  }
  .metrica dd {
    margin: 0; font: 400 1.22rem/1.15 var(--mono);
    font-variant-numeric: tabular-nums; letter-spacing: -.02em;
  }
  .metrica dd.alerta { color: var(--rojo-t); }
  .metrica dd.bien { color: var(--verde-t); }

  .acciones { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: 1.2rem; }
  .btn {
    font: 500 .84rem var(--sans); text-decoration: none; cursor: pointer;
    padding: .46rem .85rem; border-radius: 6px;
    border: 1px solid var(--borde); background: var(--surface); color: var(--ink);
    transition: background .18s, transform .1s, border-color .25s;
  }
  .btn:hover { background: var(--hueco); }
  .btn:active { transform: scale(.98); }
  .btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
  .btn.solido { background: var(--solido-f); border-color: var(--solido-f); color: var(--solido-t); }
  .btn.solido:hover { background: var(--solido-h); border-color: var(--solido-h); }
  .btn.chico { padding: .3rem .6rem; font-size: .78rem; }
  .btn:disabled { color: var(--cero); pointer-events: none; }

  /* ── buscador ──────────────────────────────────────────────────── */
  .campo { display: flex; gap: .5rem; margin-bottom: 1.4rem; }
  .campo input {
    flex: 1; font: 400 1rem var(--mono); font-variant-numeric: tabular-nums;
    letter-spacing: .02em;
    padding: .62rem .8rem; border-radius: 8px;
    border: 1px solid var(--borde); background: var(--surface); color: var(--ink);
    transition: border-color .18s, background .25s;
  }
  .campo input::placeholder { color: var(--tenue); }
  .campo input:focus { outline: none; border-color: var(--borde-f); }
  .campo input:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }

  .persona { border: 1px solid var(--borde); border-radius: 10px; overflow: hidden; }
  .persona-alto {
    padding: 1.25rem 1.5rem; border-bottom: 1px solid var(--borde);
    display: flex; align-items: baseline; gap: .8rem; flex-wrap: wrap;
  }
  .persona-alto .dni { font: 400 1.5rem/1 var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
  .persona-alto .nombre { font: 400 1.05rem var(--serif); color: var(--muted); }
  .persona-alto .gestor { margin-left: auto; font: 400 .78rem var(--mono); color: var(--tenue); }

  /* Solapas de la persona (elegidas el 25/09): la misma persona en las otras
     pantallas, marcada la que se está mirando. En las tablas, el DNI lleva a su
     ficha. */
  .solapas { display: flex; gap: .15rem; background: var(--hueco); border: 1px solid var(--borde); border-radius: 8px; padding: 3px; }
  .solapas a {
    font: 500 .8rem var(--sans); color: var(--muted); text-decoration: none; white-space: nowrap;
    padding: .28rem .7rem; border-radius: 6px; transition: color .18s, background .18s;
  }
  .solapas a:hover { color: var(--ink); }
  .solapas a[aria-current="page"] { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px var(--sombra); }
  .solapas a:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
  .persona-alto .solapas { margin-left: auto; align-self: center; }
  .persona-alto .periodo + .solapas, .persona-alto .gestor + .solapas { margin-left: .8rem; }
  .persona > .persona-alto:last-child { border-bottom: 0; }
  a.dni-enlace { color: inherit; text-decoration: none; border-bottom: 1px solid var(--borde-f); transition: border-color .18s; }
  a.dni-enlace:hover { border-color: var(--ink); }

  .desglose { display: grid; grid-template-columns: repeat(3, 1fr); }
  .desglose > div { padding: 0; border-right: 1px solid var(--borde); }
  .desglose > div:last-child { border-right: 0; background: var(--hueco); }
  .desglose dt {
    font: 500 .67rem/1 var(--mono); letter-spacing: .08em; text-transform: uppercase;
    color: var(--tenue); margin-bottom: .4rem;
  }
  .desglose dd { margin: 0; font: 400 1.32rem/1.15 var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
  .desglose > div:last-child dd { font-weight: 500; }

  /* Cada monto de la ficha es un botón: un click lo copia con el signo pesos.
     Por teléfono se dicta el número, y equivocarse una cifra es mandar a pagar
     cualquier cosa. */
  .monto {
    display: block; width: 100%; text-align: left; background: none; border: 0;
    font: inherit; color: inherit; cursor: pointer; position: relative;
    transition: background .15s;
  }
  .desglose .monto { padding: 1.25rem 1.5rem; }
  .compuesta .monto { padding: .8rem 1.5rem; }
  .monto:hover:not(:disabled) { background: var(--fila); }
  .monto:focus-visible { outline: 2px solid var(--ink); outline-offset: -3px; }
  /* Un guión no es un monto: ahí no hay nada que copiar. */
  .monto:disabled { cursor: default; }

  /* Un bloque por producto, debajo de la ficha: separados se ve de un vistazo
     qué deuda es cuál, que es lo primero para poder ofrecer algo. */
  .persona.bloque { margin-top: .8rem; }
  .persona.bloque .persona-alto { gap: .6rem; }

  /* El total a pagar hoy va en el encabezado de la ficha: es un solo número y
     en una grilla de tres quedaban dos casilleros vacíos al lado. */
  .total-hoy { margin: 0 0 0 auto; }
  .total-hoy .monto { padding: 0; text-align: right; }
  .total-hoy .monto:hover:not(:disabled) { background: none; color: var(--ink); }
  .total-hoy dt { margin-bottom: .25rem; }
  .total-hoy dd { font-size: 1.32rem; font-weight: 500; }
  .total-hoy .copiado { top: -.9rem; right: 0; }

  .total-hoy .de-donde { display: block; text-align: right; margin-top: .2rem;
    font: 400 .72rem var(--sans); color: var(--tenue); }

  /* La suma de lo exigible hoy, con la cuenta escrita: mínimo TDC + vencida
     del préstamo = total a pagar. Es la primera pregunta que se contesta por
     teléfono, y antes había que deducirla de dos números en dos bloques. */
  .suma { display: grid; grid-template-columns: 1fr auto 1fr auto 1fr;
    align-items: stretch; background: var(--calido); margin: 0; }
  /* El + y el = van sueltos entre los montos, sin líneas: son la cuenta, no
     una columna más. */
  .suma .signo { display: flex; align-items: center; justify-content: center;
    padding: 0 .2rem; font: 400 1.2rem var(--mono); color: var(--tenue); }
  .suma .monto { padding: 1rem 1.4rem; }
  .suma dt { font: 500 .66rem/1 var(--mono); letter-spacing: .08em; text-transform: uppercase;
    color: var(--tenue); margin-bottom: .4rem; }
  .suma dd { margin: 0; font: 400 1.22rem/1.15 var(--mono); font-variant-numeric: tabular-nums;
    letter-spacing: -.02em; }
  .suma .monto.igual dd { font-size: 1.42rem; font-weight: 500; }
  /* Con un solo producto no hay suma: la caja ocupa todo el ancho. */
  .suma:not(:has(.signo)) { grid-template-columns: 1fr; }

  .pie-nota { margin-top: 1.1rem; font-size: .85rem; color: var(--tenue); max-width: 62ch; }

  /* Capital e intereses van aparte, mas chicos: describen de que esta hecha
     la deuda entera, no lo que hay que pagar hoy. Mezclarlos con el total
     haria pensar que se suman. */
  .compuesta {
    display: grid; grid-template-columns: repeat(3, 1fr);
    border-top: 1px solid var(--borde); background: var(--hueco);
  }
  .compuesta > div { padding: 0; border-right: 1px solid var(--borde); }
  .compuesta > div:last-child { border-right: 0; }
  .compuesta dt {
    font: 500 .66rem/1 var(--mono); letter-spacing: .08em; text-transform: uppercase;
    color: var(--tenue); margin-bottom: .3rem;
  }
  .compuesta dd { margin: 0; font: 400 1rem/1.15 var(--mono); font-variant-numeric: tabular-nums; color: var(--muted); }
  .compuesta .aclara { grid-column: 1 / -1; padding: .55rem 1.5rem; border-top: 1px solid var(--borde); border-right: 0; }
  .compuesta .aclara span { font-size: .8rem; color: var(--tenue); }

  /* ── tabla ─────────────────────────────────────────────────────── */
  .caja-tabla { border: 1px solid var(--borde); border-radius: 10px; overflow: hidden; }
  .tabla-scroll { overflow-x: auto; }
  table { width: 100%; border-collapse: collapse; }
  thead th {
    text-align: left; white-space: nowrap; background: var(--hueco);
    padding: .55rem .9rem; border-bottom: 1px solid var(--borde);
    font: 500 .67rem/1 var(--mono); letter-spacing: .08em; text-transform: uppercase;
    color: var(--muted);
  }
  thead th.der { text-align: right; }
  /* Fila de grupo: dice de que mitad de la tabla es cada bloque, y asi los
     encabezados de abajo no tienen que repetir "prestamo" en cada uno. */
  thead tr.grupos th {
    text-align: center; padding-block: .4rem; color: var(--ink);
    border-bottom: 1px solid var(--borde);
  }
  /* El DNI ocupa las dos filas del encabezado: si no, queda un hueco blanco
     arriba de la columna, al lado del primer grupo. */
  thead tr.grupos th.dni-doble { vertical-align: bottom; }
  thead tr.grupos th.separa { border-left: 1px solid var(--borde); }
  tbody td.separa, thead th.separa { border-left: 1px solid var(--borde); }
  tbody td {
    padding: .5rem .9rem; border-bottom: 1px solid var(--borde); white-space: nowrap;
    font: 400 .87rem var(--mono); font-variant-numeric: tabular-nums;
  }
  tbody tr:last-child td { border-bottom: 0; }
  /* Los botones de una fila (05/10): si no entran uno al lado del otro, el
     segundo baja de renglón en vez de quedar cortado contra el borde. */
  .botones-fila { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: .4rem; min-width: 7rem; }
  /* La tabla de envíos tiene nueve columnas y botones por fila: con el aire de
     siempre no entra en una notebook. */
  .envios thead th, .envios tbody td { padding-left: .6rem; padding-right: .6rem; }
  tbody td.der { text-align: right; }
  tbody td.cero { color: var(--cero); }
  tbody td.total { font-weight: 500; }
  tbody td.texto { font-family: var(--sans); }
  /* Dentro de una celda: la hora del envío, un dato que falta, uno que salió mal. */
  tbody td .hora { font: 400 .78rem var(--mono); color: var(--tenue); }
  tbody td .apagado { color: var(--cero); }
  tbody td .alerta { color: var(--rojo-t); }
  tbody tr:hover td { background: var(--fila); }

  /* ── Triaje: el filtro ES el resumen ────────────────────────────────────
     Cuatro montones con su número adelante. El elegido se levanta en vez de
     pintarse de negro: con cuatro cajas grandes, el negro pleno pesa demasiado
     en el tema claro. */
  .triaje {
    display: grid; grid-template-columns: repeat(4, 1fr); gap: 3px;
    background: var(--hueco); border: 1px solid var(--borde);
    border-radius: 10px; padding: 3px; margin-bottom: 1.1rem;
  }
  .lote {
    display: grid; gap: .15rem; padding: .8rem .9rem; border: 0; border-radius: 7px;
    background: transparent; color: var(--muted); text-align: left;
    text-decoration: none; cursor: pointer; transition: background .16s, color .16s;
  }
  .lote:hover { background: var(--surface); color: var(--ink); }
  .lote:focus-visible { outline: 2px solid var(--ink); outline-offset: -2px; }
  .lote .cuantas {
    font: 500 1.5rem/1 var(--mono); letter-spacing: -.03em; font-variant-numeric: tabular-nums;
  }
  .lote .que { font: 400 .78rem var(--sans); }
  .lote .pista { font: 400 .7rem var(--sans); color: var(--tenue); }
  .lote[aria-current="page"] {
    background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px var(--sombra);
    outline: 1px solid var(--borde-f); outline-offset: -1px;
  }
  .lote[aria-current="page"] .pista { color: var(--muted); }
  .lote[aria-current="page"] .cuantas { color: var(--ink); }
  .lote .punto { display: inline-block; width: 6px; height: 6px; border-radius: 9999px;
                 background: var(--tenue); margin-right: .4rem; vertical-align: .1em; }
  .lote.rota .punto  { background: var(--rojo-p); }
  .lote.hoy .punto   { background: var(--ambar-p); }
  .lote.viene .punto { background: var(--azul-t); }
  .lote.cumplida .punto  { background: var(--verde-p); }

  /* El carril de la izquierda dice el estado sin gastar una columna. */
  tbody td:first-child { border-left: 3px solid transparent; padding-left: calc(1.1rem - 3px); }
  tr.rota  td:first-child { border-left-color: var(--rojo-p); }
  tr.hoy   td:first-child { border-left-color: var(--ambar-p); }
  tr.viene td:first-child { border-left-color: var(--azul-t); }
  tr.cumplida td:first-child { border-left-color: var(--verde-p); }

  /* Dos líneas adentro de una celda: quién es, y para cuándo prometió. */
  .quien, .cuando { display: grid; gap: .1rem; }
  .quien b { font: 500 .92rem var(--sans); letter-spacing: -.01em; }
  .quien span { font: 400 .75rem var(--mono); color: var(--tenue); }
  .cuando b { font: 400 .88rem var(--mono); }
  .cuando span { font: 400 .72rem var(--sans); color: var(--tenue); }

  /* Cuánto pagó de lo prometido (28/09): lo que entró, y abajo qué parte y cuándo.
     En verde si cubrió la promesa; apagado si no entró nada. */
  .lo-pagado { display: grid; gap: .1rem; justify-items: end; }
  .lo-pagado b { font: 400 .88rem var(--mono); font-variant-numeric: tabular-nums; }
  .lo-pagado span { font: 400 .72rem var(--sans); color: var(--tenue); white-space: nowrap; }
  .lo-pagado.todo span { color: var(--verde-t); }
  .lo-pagado.nada b, .lo-pagado.sin-dato b { color: var(--cero); }

  /* Copiar un dato suelto de una celda: el monto para pasarlo, el teléfono
     para marcarlo. No parece un botón hasta que se le pasa el mouse. */
  .copiar {
    background: none; border: 0; padding: .2rem .35rem; margin: -.2rem -.35rem;
    border-radius: 5px; font: inherit; color: inherit; cursor: pointer; position: relative;
  }
  .copiar:hover { background: var(--hueco); color: var(--ink); }
  .copiar:focus-visible { outline: 2px solid var(--ink); outline-offset: 0; }

  @media (max-width: 58rem) { .triaje { grid-template-columns: repeat(2, 1fr); } }

  /* ── Historial del deudor ──────────────────────────────────────────────
     El mes de una persona: arriba el resumen y el gráfico, después lo que pasó
     escrito, abajo la tabla día por día. */
  .persona-alto .btn { margin-left: auto; }
  .persona-alto .periodo { margin-left: auto; font: 400 .8rem var(--mono); color: var(--tenue); }
  .meses { display: flex; gap: .35rem; flex-wrap: wrap; margin: -.4rem 0 1.1rem; }

  .resumen-mes { display: grid; grid-template-columns: repeat(4, 1fr); background: var(--calido); margin: 0; }
  .resumen-mes > div { padding: .95rem 1.5rem; display: grid; gap: .3rem; align-content: start;
    border-right: 1px solid var(--borde); }
  .resumen-mes > div:last-child { border-right: 0; }
  .resumen-mes dt { font: 500 .64rem/1 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--tenue); }
  .resumen-mes dd { margin: 0; font: 500 1.15rem/1.1 var(--mono); font-variant-numeric: tabular-nums; }
  .resumen-mes dd.verde { color: var(--verde-t); }
  .resumen-mes dd small { display: block; font: 400 .72rem var(--sans); color: var(--tenue); margin-top: .2rem; }
  .resumen-mes dd + dd { margin-top: .35rem; }
  .resumen-mes .hacia { color: var(--tenue); font-weight: 400; }

  .grafico { padding: 1.2rem 1.5rem .6rem; border-top: 1px solid var(--borde); position: relative; }
  .grafico-alto { display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap; margin-bottom: .6rem; }
  .grafico-alto h2 { margin: 0; font: 500 .92rem var(--sans); }
  .grafico-alto p { margin: 0; font-size: .8rem; color: var(--tenue); }
  .leyenda { display: flex; gap: 1rem; margin-left: auto; font-size: .8rem; color: var(--muted); }
  .leyenda span::before { content: ""; display: inline-block; width: 10px; height: 10px; border-radius: 2px;
    margin-right: .4rem; vertical-align: -.05em; }
  .leyenda .p::before { background: var(--serie-prestamo); }
  .leyenda .t::before { background: var(--serie-tarjeta); }
  #lienzo { width: 100%; height: 240px; display: block; }
  #lienzo text { font: 400 11px var(--mono); fill: var(--tenue); }
  #lienzo .etiq { font: 500 11px var(--sans); fill: var(--ink); }
  .globo { position: absolute; pointer-events: none; background: var(--surface); border: 1px solid var(--borde-f);
    border-radius: 8px; padding: .55rem .7rem; font: 400 .78rem var(--sans); box-shadow: 0 2px 8px var(--sombra);
    min-width: 13rem; display: none; z-index: 2; }
  .globo b { display: block; font: 500 .8rem var(--mono); margin-bottom: .3rem; }
  .globo div { display: flex; justify-content: space-between; gap: 1rem; color: var(--muted); }
  .globo div span:last-child { font-family: var(--mono); color: var(--ink); }
  .globo .suma-dia { border-top: 1px solid var(--borde); margin-top: .3rem; padding-top: .3rem; }
  .globo i { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: .35rem; }

  h2.seccion { margin: 2rem 0 .8rem; font: 400 1.3rem var(--serif); letter-spacing: -.02em; }
  .hechos { list-style: none; margin: 0; padding: 0; border: 1px solid var(--borde); border-radius: 10px;
    overflow: hidden; background: var(--surface); }
  .hechos li { display: grid; grid-template-columns: 4.5rem 1fr auto; gap: 1rem; align-items: baseline;
    padding: .75rem 1.1rem; border-bottom: 1px solid var(--borde); border-left: 3px solid transparent; }
  .hechos li:last-child { border-bottom: 0; }
  .hechos .fecha-hecho { font: 500 .88rem var(--mono); }
  .hechos .que { font-size: .92rem; }
  .hechos .que small { display: block; color: var(--tenue); font-size: .78rem; }
  .hechos .cuanto { font: 400 .88rem var(--mono); font-variant-numeric: tabular-nums; text-align: right; }
  .hechos li.pago { border-left-color: var(--verde-p); }
  .hechos li.pago .cuanto { color: var(--verde-t); }
  .hechos li.cumplida { border-left-color: var(--verde-p); }
  .hechos li.promesa { border-left-color: var(--ambar-p); }
  .hechos li.rota { border-left-color: var(--rojo-p); }
  .hechos li.cuota { border-left-color: var(--azul-t); }
  .hechos li.fuera { border-left-color: var(--cero); }

  /* Dos filas de encabezado: el producto arriba, subrayado con su color. */
  thead tr.grupos th { padding-bottom: .35rem; border-bottom: 0; }
  thead tr.grupos th.g { border-bottom: 2px solid var(--borde-f); }
  thead tr.grupos th.g.t { border-bottom-color: var(--serie-tarjeta); }
  thead tr.grupos th.g.p { border-bottom-color: var(--serie-prestamo); }
  tr.pago td:first-child, tr.cumplida td:first-child { border-left-color: var(--verde-p); }
  tr.promesa td:first-child { border-left-color: var(--ambar-p); }
  tr.rota td:first-child { border-left-color: var(--rojo-p); }
  tr.cuota td:first-child { border-left-color: var(--azul-t); }
  tr.finde td { color: var(--tenue); }
  /* Lo que no cambió desde el día anterior se apaga: así lo que sí cambió salta solo. */
  tbody td.igual { color: var(--cero); }
  td .dif { display: block; font-size: .7rem; }
  td .dif.baja { color: var(--verde-t); }
  td .dif.suba { color: var(--rojo-t); }
  td .semana { color: var(--tenue); font-size: .75rem; }

  @media (max-width: 52rem) {
    .resumen-mes { grid-template-columns: repeat(2, 1fr); }
    .resumen-mes > div:nth-child(2) { border-right: 0; }
    .resumen-mes > div:nth-child(-n+2) { border-bottom: 1px solid var(--borde); }
    .leyenda { margin-left: 0; }
  }

  .pie-tabla {
    display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
    padding: .75rem 1.1rem; border-top: 1px solid var(--borde); background: var(--hueco);
    font: 400 .8rem var(--mono); color: var(--muted);
  }
  .paginas { margin-left: auto; display: flex; gap: .25rem; }
  .paginas button {
    font: 400 .8rem var(--mono); min-width: 1.9rem; padding: .22rem .4rem;
    border: 1px solid transparent; background: transparent; color: var(--muted);
    border-radius: 5px; cursor: pointer; transition: background .18s;
  }
  .paginas button:hover { background: var(--fila); color: var(--ink); }
  .paginas button[aria-current="page"] { background: var(--surface); border-color: var(--borde); color: var(--ink); }
  .paginas button:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }

  .dias { margin-top: 1.4rem; font-size: .85rem; color: var(--tenue); }
  .dias a { color: var(--muted); text-decoration: none; border-bottom: 1px solid var(--borde); }
  .dias a:hover { color: var(--ink); }

  /* ── bocas de cobro ────────────────────────────────────────────── */
  .aviso {
    border: 1px solid var(--borde); border-left: 3px solid var(--rojo-p);
    background: var(--surface); border-radius: 8px;
    padding: 1.1rem 1.35rem; margin-bottom: 1.5rem;
  }
  .aviso h2 { margin: 0 0 .35rem; font: 500 .98rem var(--sans); }
  .aviso p { margin: 0; color: var(--muted); font-size: .89rem; max-width: 62ch; }
  .aviso a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--borde-f); }
  /* En Hoy, mientras el de hoy no llega: el último que hay. */
  .tarjeta p.anterior { margin-top: .45rem; font-size: .84rem; color: var(--tenue); }
  /* El de "esto no es lo de hoy": es una espera, no un error. */
  .aviso.espera { border-left-color: var(--ambar-p); }

  /* Entrar (06/10): una tarjeta sola al medio, con el logo y el nombre. */
  .entrar { min-height: 100vh; display: grid; place-items: center; padding: 2rem 1rem; }
  /* minmax(0, 1fr): la tarjeta no se estira por lo que tiene adentro. Safari dibujaba el
     campo del código más ancho que la tarjeta y corría todo hacia la derecha. */
  .entrar .tarjeta { width: min(23rem, 100%); display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; padding: 1.9rem 1.8rem; }
  .entrar .marca { padding: 0 0 .4rem; }
  .entrar label, .formulario label { display: grid; gap: .35rem; font: 500 .76rem var(--sans); color: var(--muted); }
  .entrar input, .formulario input, .formulario select, input.chico {
    font: 400 .92rem var(--sans); color: var(--ink); background: var(--surface);
    border: 1px solid var(--borde); border-radius: 8px; padding: .55rem .7rem;
    min-width: 0; box-sizing: border-box;
  }
  .entrar input { width: 100%; }
  input.chico { font-size: .8rem; padding: .3rem .55rem; width: 9rem; }
  .entrar input:focus-visible, .formulario input:focus-visible, .formulario select:focus-visible, input.chico:focus-visible {
    outline: 2px solid var(--ink); outline-offset: 1px;
  }
  .entrar .error { margin: 0; padding: .55rem .75rem; border-radius: 8px; font-size: .85rem;
    background: var(--rojo-f); color: var(--rojo-t); }
  .entrar .pista-entrar { margin: 0; font-size: .78rem; color: var(--tenue); }

  /* Dos pasos (08/10): la misma tarjeta de entrar; más ancha para el QR y los códigos. */
  .entrar .tarjeta.ancha { width: min(27rem, 100%); }
  .entrar h1 { margin: 0; font: 400 1.45rem/1.15 var(--serif); letter-spacing: -.02em; color: var(--ink); }
  .entrar .explica { margin: 0; font-size: .86rem; line-height: 1.55; color: var(--muted); }
  .entrar .explica b, .pasos-vincular b { color: var(--ink); font-weight: 500; }
  .pasos-vincular { margin: 0; padding-left: 1.1rem; display: grid; gap: .3rem; font-size: .86rem; color: var(--muted); }
  /* El QR va siempre oscuro sobre blanco, también en el tema oscuro: la cámara lo lee mejor. */
  .qr { justify-self: center; background: #fff; border: 1px solid var(--borde); border-radius: 10px; padding: .55rem; line-height: 0; }
  .qr svg { display: block; width: 10.5rem; height: 10.5rem; }
  .clave-manual { margin: 0; text-align: center; font-size: .78rem; color: var(--tenue); }
  .clave-manual code { font: 500 .8rem var(--mono); letter-spacing: .04em; color: var(--ink); word-break: break-word; }
  .entrar input.codigo { font: 500 1.35rem var(--mono); letter-spacing: .32em; text-align: center; padding: .55rem .7rem; }
  .entrar input.codigo::placeholder { color: var(--cero); }
  .entrar label.casilla { display: flex; align-items: center; gap: .55rem; font: 400 .84rem var(--sans); color: var(--muted); cursor: pointer; }
  .entrar .casilla input { width: 1rem; height: 1rem; margin: 0; padding: 0; accent-color: var(--ink); }
  .codigos-repuesto { margin: 0; padding: .9rem 1.1rem; list-style: none; display: grid; grid-template-columns: 1fr 1fr;
    gap: .5rem 1.4rem; background: var(--hueco); border: 1px solid var(--borde); border-radius: 10px;
    font: 500 .92rem var(--mono); letter-spacing: .04em; color: var(--ink); }

  /* Quién entró, al pie de la barra, con el botón para salir. */
  .quien-soy { display: grid; gap: .45rem; margin-bottom: .8rem; }
  .quien-soy b { display: block; font: 500 .82rem/1.25 var(--sans); color: var(--ink); }
  .quien-soy .rol { display: block; margin-top: .1rem; font-size: .72rem; color: var(--tenue); }
  /* Las dos acciones, alineadas con el nombre: el -.4rem compensa el relleno del botón. */
  .quien-soy .cuenta { display: flex; gap: .15rem; margin-left: -.4rem; }
  .quien-soy .cuenta form { margin: 0; }
  .quien-soy button { font: 500 .74rem var(--sans); color: var(--muted); background: none; border: 0;
    padding: .22rem .4rem; border-radius: 5px; cursor: pointer; transition: background .18s, color .18s; }
  .quien-soy button:hover { color: var(--ink); background: var(--surface); }
  .quien-soy button:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }

  /* Usuarios: el alta en una fila, y los formularios chicos dentro de la tabla. */
  .alta-usuario { margin-top: 1.4rem; }
  .alta-usuario h2 { margin: 0 0 .9rem; font: 500 .98rem var(--sans); }
  .formulario { display: flex; flex-wrap: wrap; gap: .7rem; align-items: flex-end; }
  form.en-linea { display: inline-flex; align-items: center; gap: .45rem; margin: 0; }

  /* ── calculadora de quitas ─────────────────────────────────── */
  details.calc { margin-top: 1.1rem; border: 1px solid var(--borde); border-radius: 10px;
    background: var(--surface); overflow: hidden; }
  details.calc > summary { padding: 1rem 1.4rem; cursor: pointer; display: flex;
    align-items: center; gap: .65rem; font: 500 1rem var(--sans);
    letter-spacing: -.01em; list-style: none; }
  details.calc > summary::-webkit-details-marker { display: none; }
  details.calc > summary:hover { background: var(--fila); }
  details.calc > summary:focus-visible { outline: 2px solid var(--ink); outline-offset: -3px; }
  details.calc > summary .pista { margin-left: auto; font: 400 .82rem var(--sans); color: var(--tenue); }
  details.calc[open] > summary { border-bottom: 1px solid var(--borde); }
  .flecha { width: 9px; height: 9px; border-right: 1.6px solid var(--muted);
    border-bottom: 1.6px solid var(--muted); transform: rotate(-45deg);
    transition: transform .2s; flex: none; margin-left: -.1rem; }
  details.calc[open] > summary .flecha { transform: rotate(45deg); }

  .cuerpo-calc { padding: 1.25rem 1.4rem; display: grid; gap: 1.25rem; }
  .etiqueta { display: block; font: 500 .66rem/1 var(--mono); letter-spacing: .08em;
    text-transform: uppercase; color: var(--tenue); margin-bottom: .55rem; }

  .tramos { display: flex; gap: 3px; background: var(--hueco);
    border: 1px solid var(--borde); border-radius: 9px; padding: 3px; }
  .tramo { flex: 1 1 0; background: transparent; border: 0; border-radius: 6px;
    padding: .42rem .3rem; cursor: pointer; text-align: center; color: var(--muted);
    transition: background .16s, color .16s; }
  .tramo:hover { background: var(--surface); color: var(--ink); }
  .tramo:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
  .tramo b { display: block; font: 500 .95rem var(--mono); letter-spacing: -.02em; }
  .tramo span { display: block; font: 400 .64rem var(--sans); color: var(--tenue); margin-top: .05rem; }
  .tramo[aria-pressed="true"] { background: var(--solido-f); color: var(--solido-t); }
  .tramo[aria-pressed="true"] span { color: var(--solido-t); opacity: .68; }
  /* Los de producto son anchos: ahí el negro pleno pesa demasiado en claro, así
     que el elegido se levanta en vez de pintarse. Los tramos, que son chicos,
     se quedan en negro. */
  #productos .tramo[aria-pressed="true"] {
    background: var(--surface); color: var(--ink);
    box-shadow: 0 1px 2px var(--sombra);
    outline: 1px solid var(--borde-f); outline-offset: -1px;
  }
  #productos .tramo[aria-pressed="true"] span { color: var(--muted); }
  .tramo.sugerido b::after { content: ""; display: inline-block; width: 5px; height: 5px;
    border-radius: 99px; background: var(--azul-t); margin-left: .28rem; vertical-align: .22em; }
  .tramo[aria-pressed="true"].sugerido b::after { background: var(--solido-t); opacity: .6; }

  .regla { font-size: .88rem; color: var(--muted); padding: .75rem .95rem;
    border-radius: 8px; background: var(--hueco); border: 1px solid var(--borde); }
  .regla b { color: var(--ink); font-weight: 500; }

  .ofertas { display: grid; gap: .8rem; }
  .oferta { border: 1px solid var(--borde); border-radius: 9px; overflow: hidden; }
  .oferta-alto { padding: .75rem 1.1rem; background: var(--hueco);
    border-bottom: 1px solid var(--borde); display: flex; align-items: center;
    gap: .6rem; flex-wrap: wrap; }
  .oferta-alto h3 { margin: 0; font: 500 .92rem var(--sans); }
  .oferta-alto .via { font: 400 .78rem var(--sans); color: var(--tenue); }
  .oferta-cuerpo { padding: 1.05rem 1.1rem; display: grid; gap: .9rem; }

  .mandos { display: grid; grid-template-columns: auto 1fr auto; gap: .9rem; align-items: end; }
  .mando label { display: block; font: 500 .64rem/1 var(--mono); letter-spacing: .08em;
    text-transform: uppercase; color: var(--tenue); margin-bottom: .35rem; }
  .mando input[type=text] { width: 5.5rem; font: 400 1rem var(--mono);
    font-variant-numeric: tabular-nums; padding: .45rem .6rem; border-radius: 7px;
    border: 1px solid var(--borde); background: var(--surface); color: var(--ink); }
  .mando input[type=range] { width: 100%; accent-color: var(--ink); height: 1.6rem; }
  .mando input:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
  .paga { text-align: right; }
  .paga dt { font: 500 .64rem/1 var(--mono); letter-spacing: .08em; text-transform: uppercase;
    color: var(--tenue); margin-bottom: .3rem; }
  .paga dd { margin: 0; font: 600 1.45rem/1 var(--mono); font-variant-numeric: tabular-nums;
    letter-spacing: -.025em; white-space: nowrap; }

  .pie-calc { font-size: .82rem; color: var(--tenue); display: flex;
    justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-top: -.25rem; }
  .pie-calc b { color: var(--muted); font-weight: 500; }
  .acciones-calc { display: flex; gap: .45rem; flex-wrap: wrap; }

  @media (max-width: 46rem) {
    .mandos { grid-template-columns: 1fr; align-items: stretch; }
    .paga { text-align: left; }
  }

  /* Subir un archivo: el control nativo del navegador, pero que no desentone. */
  input[type=file] {
    font: 400 .82rem var(--sans); color: var(--muted); max-width: 17rem;
  }
  input[type=file]::file-selector-button {
    font: 500 .8rem var(--sans); color: var(--ink); cursor: pointer;
    background: var(--surface); border: 1px solid var(--borde); border-radius: 6px;
    padding: .34rem .7rem; margin-right: .6rem;
  }
  input[type=file]::file-selector-button:hover { background: var(--hueco); }
  .celdilla .acciones { margin-top: 0; align-items: center; }

  .celdillas { display: grid; gap: .7rem; }
  .celdilla {
    border: 1px solid var(--borde); border-radius: 9px; background: var(--surface);
    padding: 1rem 1.2rem;
    display: grid; grid-template-columns: 1fr auto; gap: 1rem; align-items: center;
  }
  .celdilla .que { display: grid; gap: .3rem; }
  .celdilla .nombre-boca { font: 500 .93rem var(--mono); letter-spacing: -.01em; }
  .celdilla .cuanto { font-size: .82rem; color: var(--tenue); }
  .celdilla .elegir { display: flex; gap: .4rem; }

  .lista-conocidas { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .9rem; }
  .pastilla {
    font: 400 .78rem var(--mono); padding: .25rem .55rem; border-radius: 9999px;
    background: var(--verde-f); color: var(--verde-t);
  }
  .pastilla.no { background: var(--hueco); color: var(--tenue); text-decoration: line-through; }

  /* ── archivo ───────────────────────────────────────────────────── */
  .grilla-dias { display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); gap: .7rem; }
  .dia {
    border: 1px solid var(--borde); border-radius: 9px; background: var(--surface);
    padding: .9rem 1rem; display: grid; gap: .45rem;
    text-decoration: none; color: inherit;
    transition: box-shadow .2s, border-color .18s;
  }
  .dia:hover { box-shadow: 0 2px 8px var(--sombra); border-color: var(--borde-f); }
  .dia .fecha { font: 500 .95rem var(--mono); font-variant-numeric: tabular-nums; }
  .dia .cuantos { font-size: .8rem; color: var(--tenue); }

  @media (max-width: 54rem) {
    body { padding: 1.25rem .75rem 3rem; }
    .app { grid-template-columns: 1fr; }
    aside { border-right: 0; border-bottom: 1px solid var(--borde); padding-bottom: 1rem; }
    aside nav { flex-direction: row; flex-wrap: wrap; }
    aside nav .titulo { display: none; }
    .pie-lateral { margin-top: 1rem; position: static; }
    main { padding: 1.5rem 1.25rem 2rem; }
    .desglose { grid-template-columns: 1fr; }
    .desglose > div { border-right: 0; border-bottom: 1px solid var(--borde); }
    .celdilla { grid-template-columns: 1fr; }
    /* Angosto, la cuenta va de arriba a abajo y los signos sobran. */
    .suma { grid-template-columns: 1fr; }
    .suma .signo { display: none; }
  }
  /* ── Movimiento ─────────────────────────────────────────────────────────
     Elegido por Giuliano en el muestrario, una opción por momento. Todo con la
     misma curva, y solo opacidad y desplazamiento: nada que mueva el layout. */
  :root { --curva: cubic-bezier(.16,1,.3,1); }

  /* 3B · Al abrir una pantalla, los bloques entran en cascada. Solo al llegar
     desde otra pantalla: buscar o paginar en la misma no la repite, si no cada
     búsqueda sería una espera. `misma-pantalla` la pone base.html. */
  main > :not(.tarjetas) { animation: entrar .6s var(--curva) backwards; }
  main > :nth-child(2) { animation-delay: 70ms; }
  main > :nth-child(3) { animation-delay: 140ms; }
  main > :nth-child(4) { animation-delay: 210ms; }
  main > :nth-child(n+5) { animation-delay: 280ms; }
  .misma-pantalla main > *, .misma-pantalla .tarjeta { animation: none; }

  /* 2C · Al buscar, primero la forma de lo que viene; después, eso mismo fundido. */
  .misma-pantalla #resultado { animation: aparecer .3s ease-out both; }
  @keyframes aparecer { from { opacity: 0; } }
  .hueso {
    display: block; border-radius: 6px;
    background: linear-gradient(90deg, var(--esqueleto) 30%, var(--brillo) 50%, var(--esqueleto) 70%);
    background-size: 300% 100%; animation: brillar 1.2s linear infinite;
  }
  @keyframes brillar { from { background-position: 100% 0; } to { background-position: 0 0; } }
  .esqueleto { border: 1px solid var(--borde); border-radius: 10px; overflow: hidden; }
  .esqueleto .alto { padding: 1.25rem 1.5rem; border-bottom: 1px solid var(--borde); }
  .esqueleto .cuerpo { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; padding: 1.25rem 1.5rem; }
  .esqueleto .filas { display: grid; gap: .9rem; padding: 1.1rem 1.5rem; }

  /* 1B · Mientras la app trabaja, la tarjeta entera lo dice: la etiqueta late,
     una línea recorre el borde de arriba y se cuentan los segundos. La línea no
     sabe cuánto falta, y no lo finge. */
  .trabajando { position: relative; overflow: hidden; }
  .barra { position: absolute; left: 0; right: 0; top: 0; height: 2px; overflow: hidden; background: var(--hueco); }
  .barra::after {
    content: ""; position: absolute; inset: 0; width: 35%; background: var(--ambar-p);
    animation: barrer 1.2s var(--curva) infinite;
  }
  @keyframes barrer { from { transform: translateX(-100%); } to { transform: translateX(290%); } }
  .latido {
    display: inline-block; width: 6px; height: 6px; border-radius: 99px; background: currentColor;
    margin-right: .35rem; vertical-align: .1em; animation: latido 1.1s ease-in-out infinite;
  }
  @keyframes latido { 50% { opacity: .25; } }

  /* 1B en Hoy · El proceso corre aparte y la tarjeta muestra sus pasos de verdad:
     los hechos con lo que tardaron, el que se está haciendo con el latido y su
     segundero, los que faltan apagados. */
  .pasos { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; max-width: 30rem; font-size: .9rem; }
  .pasos li { display: grid; grid-template-columns: .9rem auto 1fr auto; column-gap: .55rem; align-items: baseline; }
  .pasos li::before { content: ""; justify-self: center; align-self: center; width: 6px; height: 6px; border-radius: 99px; }
  .pasos .hecho { color: var(--muted); }
  .pasos .hecho::before { content: "✓"; width: auto; height: auto; border-radius: 0; font-size: .8rem; line-height: 1; color: var(--verde-t); }
  .pasos .ahora::before { background: var(--ambar-t); animation: latido 1.1s ease-in-out infinite; }
  .pasos .falta { color: var(--cero); }
  .pasos .falta::before { box-shadow: inset 0 0 0 1px currentColor; }
  .pasos .detalle, .pasos .segundos { font: 400 .8rem var(--mono); font-variant-numeric: tabular-nums; color: var(--tenue); }
  .pasos .detalle:not(:empty)::before { content: "· "; }

  /* 5C+B · Al copiar: abajo dice qué quedó copiado, y el número se pone verde. */
  .aviso-copia {
    position: fixed; left: 50%; bottom: 1.5rem; z-index: 10; max-width: min(36rem, 90vw);
    transform: translate(-50%, 8px); opacity: 0; pointer-events: none;
    background: var(--solido-f); color: var(--solido-t); font: 400 .82rem var(--sans);
    padding: .5rem .85rem; border-radius: 8px; box-shadow: 0 2px 8px var(--sombra);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    transition: opacity .25s var(--curva), transform .35s var(--curva);
  }
  .aviso-copia.visible { opacity: 1; transform: translate(-50%, 0); }
  .aviso-copia span { font-family: var(--mono); }
  .recien-copiado, .recien-copiado dd { color: var(--verde-t) !important; }
  .monto dd, .copiar, .paga dd { transition: color .35s; }

  /* 6C · En la calculadora, el elegido se desliza. La corredera va detrás de
     los botones; el texto cambia de color cuando llega. */
  .tramos { position: relative; }
  .tramos .corredera {
    position: absolute; top: 3px; bottom: 3px; left: 0; border-radius: 6px;
    background: var(--solido-f); transition: transform .32s var(--curva);
  }
  #productos .tramos .corredera {
    background: var(--surface); box-shadow: 0 1px 2px var(--sombra);
    outline: 1px solid var(--borde-f); outline-offset: -1px;
  }
  .tramos.con-corredera .tramo { position: relative; z-index: 1; transition: color .25s var(--curva); }
  .tramos.con-corredera .tramo[aria-pressed="true"],
  #productos .tramos.con-corredera .tramo[aria-pressed="true"] { background: transparent; box-shadow: none; outline: 0; }
  .cruce { animation: cruce .22s ease-out; }
  @keyframes cruce { from { opacity: .15; } }

  /* 6C · En promesas, entre página y página: el montón elegido se desliza y
     la lista se funde. El @view-transition que lo prende está en la plantilla. */
  .lote[aria-current="page"] { view-transition-name: lote-elegido; }
  #resultado .caja-tabla { view-transition-name: lista-promesas; }
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
  ::view-transition-group(*) { animation-duration: .32s; animation-timing-function: var(--curva); }
  /* La transición ya funde la lista: una segunda entrada encima sería doble. */
  .misma-pantalla #resultado.con-transicion { animation: none; }

  /* 8C · Lo que se aprieta se hunde; las tarjetas que llevan a otro lado se
     levantan al pasar el mouse. */
  .tramo:active, .copiar:active, .lote:active { transform: scale(.98); }
  .lote, .dia { transition: background .16s, color .16s, box-shadow .2s, transform .2s var(--curva); }
  .lote:hover, .dia:hover { box-shadow: 0 2px 8px var(--sombra); transform: translateY(-1px); }

  @media (prefers-reduced-motion: reduce) {
    * { animation: none !important; transition: none !important; }
    ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
  }
