/* Hornero — estilos del front. Hasta el 4/9/2026 vivía inline en Index.html; salió
   cuando el front dejó de servirse desde Apps Script (hoja de ruta técnica, paso 2).
   Los tokens están documentados en DESIGN-TOKENS.md. Regla 4: los componentes usan
   solo tokens semánticos, nunca primitivos --c-*. */
:root{
  /* ================================================================
     DESIGN TOKENS
     Tier 1 = primitives (raw values). Tier 2 = semantic roles that
     reference primitives. Then scales: type, space, radius, shadow,
     z-index, motion. Everything is CSS-var based so un futuro front
     en React puede consumirlo tal cual (CSS vars) o espejarlo en un
     theme object en JS. Cambiar un tema = redefinir esta capa.
     ================================================================ */

  /* ---------- Primitives · palette ---------- */
  --c-bg-1:#201d17; --c-bg-2:#2a261e; --c-bg-3:#2f2b22;
  --c-paper:#e9ecd9; --c-paper-2:#dfe3cd; --c-paper-line:#b7bf9e;
  --c-ink:#23281f; --c-ink-soft:#52594a;
  --c-cream-1:#f3f1e6; --c-cream-2:#e7e3d4; --c-cream-3:#c9c4b3; --c-cream-4:#8a8574; --c-cream-5:#6f6a5b;
  --c-gaston:#2c4a63; --c-gaston-soft:#dfe6ea;
  --c-abi:#863c30;    --c-abi-soft:#f0e0dc;
  --c-brass:#8a6d1d;
  --c-danger:#a23328;
  --c-positive:#6f8f5a;
  --c-white:#fff; --c-black:#000;
  /* rgb tuples para overlays con alpha */
  --rgb-white:255,255,255; --rgb-ink:35,40,31; --rgb-danger:162,51,40; --rgb-brass:138,109,29; --rgb-black:0,0,0;

  /* ---------- Semantic · surfaces / backgrounds ---------- */
  --bg-page-top:var(--c-bg-2);
  --bg-page-bottom:var(--c-bg-1);
  --surface:rgba(var(--rgb-white),0.05);
  --surface-raised:rgba(var(--rgb-white),0.06);
  --scrim-top:rgba(32,29,23,0.82);
  --scrim-bottom:rgba(38,34,27,0.94);
  --scrim:rgba(var(--rgb-black),0.5);
  --toast-bg:var(--c-bg-3);
  --toast-text:var(--c-cream-1);

  /* ---------- Semantic · text (shell oscuro) ---------- */
  --text-strong:var(--c-cream-1);
  --text:var(--c-cream-2);
  --text-muted:var(--c-cream-3);
  --text-faint:var(--c-cream-4);
  --text-fainter:var(--c-cream-5);
  --text-on-accent:var(--c-white);
  --focus-ring:var(--c-white);

  /* ---------- Semantic · paper world (ticket + sheets) ---------- */
  --paper:var(--c-paper);
  --paper-2:var(--c-paper-2);
  --line:var(--c-paper-line);
  --ink:var(--c-ink);
  --ink-soft:var(--c-ink-soft);
  --paper-tint:rgba(var(--rgb-ink),0.05);
  --paper-tint-2:rgba(var(--rgb-ink),0.06);
  --paper-hairline:rgba(var(--rgb-ink),0.15);
  --paper-border:rgba(var(--rgb-ink),0.14);
  --paper-border-strong:rgba(var(--rgb-ink),0.22);
  --paper-border-payer:rgba(var(--rgb-ink),0.28);
  --paper-border-ghost:rgba(var(--rgb-ink),0.35);
  --on-paper-hover:rgba(var(--rgb-ink),0.08);
  --handle:rgba(var(--rgb-ink),0.22);

  /* ---------- Semantic · borders + states (shell) ---------- */
  --border-subtle:rgba(var(--rgb-white),0.10);
  --border-chip:rgba(var(--rgb-white),0.12);
  --border-strong:rgba(var(--rgb-white),0.18);
  --border-field:rgba(var(--rgb-white),0.20);
  --border-ghost:rgba(var(--rgb-white),0.22);
  --hairline:rgba(var(--rgb-white),0.08);
  --state-hover:rgba(var(--rgb-white),0.08);
  --state-press:rgba(var(--rgb-white),0.14);
  --state-press-soft:rgba(var(--rgb-white),0.10);
  --field-bg:rgba(var(--rgb-white),0.95);
  --field-placeholder:rgba(var(--rgb-ink),0.45);

  /* ---------- Semantic · accents + status ---------- */
  --accent:var(--c-brass);
  --accent-tint:rgba(var(--rgb-brass),0.34);
  --payer-a:var(--c-gaston); --payer-a-soft:var(--c-gaston-soft); --payer-a-ink:var(--c-gaston);
  --payer-b:var(--c-abi);    --payer-b-soft:var(--c-abi-soft);    --payer-b-ink:var(--c-abi);
  --gaston:var(--c-gaston); --gaston-soft:var(--c-gaston-soft);
  --abi:var(--c-abi);       --abi-soft:var(--c-abi-soft);
  --brass:var(--c-brass);
  --danger:var(--c-danger);
  --stamp:var(--c-danger);
  --danger-tint:rgba(var(--rgb-danger),0.08);
  --danger-tint-strong:rgba(var(--rgb-danger),0.16);
  --danger-border:rgba(var(--rgb-danger),0.5);
  --positive:var(--c-positive);

  /* ---------- Shadows ---------- */
  --shadow-receipt:0 18px 40px rgba(var(--rgb-black),0.35);
  --shadow-sheet:0 -12px 40px rgba(var(--rgb-black),0.4);
  --shadow-toast:0 6px 18px rgba(var(--rgb-black),0.4);

  /* ---------- Typography ---------- */
  --font-mono:'JetBrains Mono', ui-monospace, monospace;
  --font-sans:'Inter', system-ui, sans-serif;
  --fw-regular:400; --fw-medium:500; --fw-semibold:600; --fw-bold:700;
  --text-2xs:0.7rem;  --text-xs:0.78rem; --text-sm:0.85rem;
  /* --text-2xl es el paso "número hero": el monto más grande de cada pantalla
     (total del mes, saldo del detalle). Está lejos del resto de la escala a
     propósito — no es un tamaño de texto, es el número que se lee de lejos. */
  --text-md:0.9rem;   --text-base:0.95rem; --text-lg:1rem; --text-xl:1.05rem; --text-2xl:1.25rem;
  --lh-tight:1.2; --lh-snug:1.4; --lh-base:1.5;

  /* ---------- Radius ---------- */
  --radius-xs:2px; --radius-sm:8px; --radius-md:10px; --radius-lg:12px;
  --radius-xl:18px; --radius-2xl:22px; --radius-pill:999px;
  --radius:var(--radius-md); /* alias legacy */

  /* ---------- Spacing scale (disponible para adoptar) ---------- */
  --space-1:4px; --space-2:6px; --space-3:8px; --space-4:10px; --space-5:12px;
  --space-6:14px; --space-7:16px; --space-8:18px; --space-9:20px; --space-10:22px; --space-11:24px;

  /* ---------- Z-index layers ---------- */
  --z-tabbar:40; --z-sheet:70; --z-sheet-top:80; --z-toast:100;

  /* ---------- Motion ---------- */
  --dur-1:0.12s; --dur-2:0.18s; --dur-3:0.22s; --dur-4:0.26s;
  --ease-standard:ease; --ease-out:ease-out; --ease-sheet:cubic-bezier(.32,.72,0,1);

  font-size: 16px;
}

/* ================================================================
   THEME · DARK (Gastón)
   Solo redefine la CAPA SEMÁNTICA. Primitivos y componentes intactos.
   Clásico (Abi) = valores base de :root.
   ================================================================ */
:root[data-theme="dark"]{
  color-scheme: dark;

  /* Shell: cálido más profundo */
  --bg-page-top:#1b1710;
  --bg-page-bottom:#100d08;
  --scrim-top:rgba(20,17,12,0.82);
  --scrim-bottom:rgba(26,22,15,0.94);
  --toast-bg:#2a251b;

  /* Mundo papel → tarjeta oscura cálida (tinta clara) */
  --paper:#221e16;
  --paper-2:#2a251b;
  --line:rgba(var(--rgb-white),0.14);
  --ink:#ece8dd;
  --ink-soft:#a8a294;
  --paper-tint:rgba(var(--rgb-white),0.05);
  --paper-tint-2:rgba(var(--rgb-white),0.06);
  --paper-hairline:rgba(var(--rgb-white),0.10);
  --paper-border:rgba(var(--rgb-white),0.14);
  --paper-border-strong:rgba(var(--rgb-white),0.20);
  --paper-border-payer:rgba(var(--rgb-white),0.24);
  --paper-border-ghost:rgba(var(--rgb-white),0.30);
  --on-paper-hover:rgba(var(--rgb-white),0.08);
  --handle:rgba(var(--rgb-white),0.24);

  /* Fields oscuros */
  --field-bg:#2b271e;
  --field-placeholder:rgba(var(--rgb-white),0.40);

  /* Acentos: más brillantes para resaltar sobre casi-negro */
  --rgb-brass:195,154,58;
  --accent:#c39a3a;
  --payer-a:#4a7aa5; --payer-a-soft:rgba(74,122,165,0.22); --payer-a-ink:#9cc4e6;
  --payer-b:#c06a51; --payer-b-soft:rgba(192,106,81,0.22); --payer-b-ink:#e8a892;
  --rgb-danger:208,80,63;
  --danger:#d0503f;
  --stamp:#d0503f;
  --positive:#86a86b;
}

/* ================================================================
   THEME · POESÍA (claro — rosa/lavanda + púrpura)
   Primer tema light. Invierte shell (fondo claro, texto oscuro) y
   paper (papel casi blanco, tinta púrpura). Solo capa semántica.
   ================================================================ */
:root[data-theme="poesia"]{
  color-scheme: light;

  /* Shell: degradé rosa → lavanda */
  --bg-page-top:#f7d6f3;
  --bg-page-bottom:#d7b6ea;
  --surface:rgba(255,255,255,0.42);
  --surface-raised:rgba(255,255,255,0.62);
  --scrim-top:rgba(247,214,243,0.82);
  --scrim-bottom:rgba(233,196,235,0.92);
  --scrim:rgba(58,35,82,0.42);
  --toast-bg:#3a2352;
  --toast-text:#f4ecfa;

  /* Texto: púrpuras oscuros sobre claro */
  --text-strong:#4a2382;
  --text:#4f3d66;
  --text-muted:#715f88;
  --text-faint:#8f7ea6;
  --text-fainter:#a99bbe;
  --text-on-accent:#ffffff;
  --focus-ring:#4a2382;

  /* Paper: casi blanco lavanda, tinta púrpura */
  --paper:#fbf7fc;
  --paper-2:#f1e8f6;
  --line:#d9c8e6;
  --ink:#33254a;
  --ink-soft:#6c5d82;
  --paper-tint:rgba(51,37,74,0.05);
  --paper-tint-2:rgba(51,37,74,0.06);
  --paper-hairline:rgba(51,37,74,0.12);
  --paper-border:rgba(51,37,74,0.14);
  --paper-border-strong:rgba(51,37,74,0.20);
  --paper-border-payer:rgba(51,37,74,0.28);
  --paper-border-ghost:rgba(51,37,74,0.34);
  --on-paper-hover:rgba(51,37,74,0.06);
  --handle:rgba(51,37,74,0.22);

  /* Bordes + estados sobre claro (alpha púrpura) */
  --border-subtle:rgba(90,64,130,0.16);
  --border-chip:rgba(90,64,130,0.22);
  --border-strong:rgba(90,64,130,0.30);
  --border-field:rgba(90,64,130,0.26);
  --border-ghost:rgba(90,64,130,0.34);
  --hairline:rgba(90,64,130,0.14);
  --state-hover:rgba(90,64,130,0.10);
  --state-press:rgba(90,64,130,0.18);
  --state-press-soft:rgba(90,64,130,0.12);
  --field-bg:rgba(255,255,255,0.85);
  --field-placeholder:rgba(74,50,110,0.45);

  /* Acentos */
  --rgb-brass:122,63,176;
  --accent:#7a3fb0;
  --payer-a:#5b62d6; --payer-a-soft:#e2e3fb; --payer-a-ink:#4147bf;
  --payer-b:#c2477e; --payer-b-soft:#f9dcec; --payer-b-ink:#ab3568;
  --rgb-danger:200,56,74;
  --danger:#c8384a;
  --stamp:#c8384a;
  --positive:#4f9e6d;
}

/* ================================================================
   THEME · NAVE (oscuro — consola/terminal alien, verde neón)
   Basado en gast.design. Verde casi-negro con grilla, headings en
   verde neón, cuerpo blanco, acento verde con texto negro (+ ámbar).
   ================================================================ */
:root[data-theme="nave"]{
  color-scheme: dark;
  --grid-line:rgba(59,240,122,0.06);

  /* Shell: verde casi-negro */
  --bg-page-top:#0a2313;
  --bg-page-bottom:#030c06;
  --surface:rgba(255,255,255,0.04);
  --surface-raised:rgba(255,255,255,0.06);
  --scrim-top:rgba(6,20,11,0.82);
  --scrim-bottom:rgba(8,26,14,0.94);
  --scrim:rgba(2,10,5,0.55);
  --toast-bg:#0d2b18;
  --toast-text:#e6fff0;

  /* Texto: headings verde neón, cuerpo blanco */
  --text-strong:#3bf07a;
  --text:#e8f0ea;
  --text-muted:#8fb89e;
  --text-faint:#5f7d68;
  --text-fainter:#43584a;
  --text-on-accent:#04140a;

  /* Paper: tarjeta verde oscura, tinta clara */
  --paper:#0c2113;
  --paper-2:#123018;
  --line:rgba(255,255,255,0.12);
  --ink:#e8f3ea;
  --ink-soft:#8fb89e;
  --paper-tint:rgba(255,255,255,0.05);
  --paper-tint-2:rgba(255,255,255,0.06);
  --paper-hairline:rgba(255,255,255,0.10);
  --paper-border:rgba(255,255,255,0.14);
  --paper-border-strong:rgba(255,255,255,0.20);
  --paper-border-payer:rgba(255,255,255,0.24);
  --paper-border-ghost:rgba(255,255,255,0.30);
  --on-paper-hover:rgba(255,255,255,0.08);
  --handle:rgba(255,255,255,0.24);

  /* Bordes + estados sobre verde-negro (alpha neón) */
  --border-subtle:rgba(59,240,122,0.12);
  --border-chip:rgba(59,240,122,0.16);
  --border-strong:rgba(59,240,122,0.22);
  --border-field:rgba(59,240,122,0.20);
  --border-ghost:rgba(59,240,122,0.28);
  --hairline:rgba(59,240,122,0.12);
  --state-hover:rgba(59,240,122,0.10);
  --state-press:rgba(59,240,122,0.18);
  --state-press-soft:rgba(59,240,122,0.12);
  --field-bg:#10291a;
  --field-placeholder:rgba(255,255,255,0.40);

  /* Acentos: verde neón + ámbar */
  --rgb-brass:59,240,122;
  --accent:#3bf07a;
  --payer-a:#3bf07a; --payer-a-soft:rgba(59,240,122,0.16); --payer-a-ink:#6bf59a;
  --payer-b:#f0b23c; --payer-b-soft:rgba(240,178,60,0.16); --payer-b-ink:#f0c661;
  --rgb-danger:255,90,77;
  --danger:#ff5a4d;
  --stamp:#ff5a4d;
  --positive:#5cff8f;
}
/* Grilla de consola en el fondo (solo Nave) */
:root[data-theme="nave"] body{
  background:
    linear-gradient(var(--grid-line) 1px, transparent 1px) 0 0 / 48px 48px,
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px) 0 0 / 48px 48px,
    radial-gradient(ellipse at top, var(--bg-page-top), var(--bg-page-bottom));
}
/* Botón primario con sombra dura 3D (guiño al sitio) */
:root[data-theme="nave"] #submitBtn{ box-shadow: 5px 5px 0 #0b7d3f; }
:root[data-theme="nave"] #submitBtn:active{ transform: translate(2px,2px); box-shadow: 3px 3px 0 #0b7d3f; }

*{ box-sizing: border-box; }
/* ───── App shell ─────
   El documento NO scrollea: <main> es el único contenedor de scroll, y la tabbar
   es lo único fijo. Así el rebote elástico pasa adentro del contenido, la nav de
   abajo nunca se mueve, y no hay canvas del navegador que se pueda descubrir.
   No hay nada fijo arriba: el encabezado de cada pantalla scrollea con su
   contenido, que es lo que devuelve esos píxeles a la lista. */
html, body{ height:100%; max-width:100%; overflow:hidden; }
html{
  /* Red de seguridad: si algún navegador igual deja descubrir el canvas, que sea
     del color del tema y no blanco. Sigue al tema porque el token se redefine. */
  background-color: var(--bg-page-bottom);
}
body{
  margin:0;
  background: radial-gradient(ellipse at top, var(--bg-page-top), var(--bg-page-bottom));
  color: var(--ink);
  font-family: var(--font-sans);
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
}
.app{
  height:100%; max-width: 460px; margin: 0 auto;
  display:flex; flex-direction:column;
}
main{
  flex:1 1 auto; min-height:0;          /* min-height:0 o el flex no deja encoger */
  overflow-y:auto; -webkit-overflow-scrolling:touch;
  overscroll-behavior-y:contain;         /* rebota acá adentro, sin propagar */
  /* El notch. Esto lo despejaba la topbar; al sacarla quedó acá, que además es
     el lugar correcto: es una sola declaración para todas las pantallas. */
  padding-top: env(safe-area-inset-top);
  /* Despeja la tabbar, que sigue siendo fixed para ocupar todo el ancho. */
  padding-bottom: calc(66px + env(safe-area-inset-bottom));
}
input, button, textarea, select{ font-family: inherit; }

/* No hay barra superior. La marca "CUENTAS · CASA" se repetía en todas las
   pantallas sin aportar nada —el tab activo ya dice dónde estás— y encima de
   las sub-pantallas quedaban dos encabezados apilados. El punto de sincronización
   que vivía ahí se mudó a Ajustes. */

.screen{ padding: 16px 16px 10px; }
.screen[hidden]{ display:none; }
.screen-title{ font-family:var(--font-mono); color:var(--text-strong); font-size:var(--text-xl); margin:4px 0 16px; font-weight:var(--fw-bold); letter-spacing:0.02em; }

/* ───── Sub-pantallas ─────
   Una <section class="screen"> con data-parent="X" cuelga de X: no tiene tab
   propio, deja marcado el tab de X, y esta flecha vuelve ahí. El destino sale
   del atributo, no de nada cableado acá. */
.subhead{ display:flex; align-items:center; gap:4px; margin:4px 0 16px; }
.subhead .screen-title{ margin:0; }
.back-btn{
  flex:0 0 auto; width:48px; height:48px; margin-left:-14px;
  display:flex; align-items:center; justify-content:center;
  border:none; background:none; cursor:pointer;
  color:var(--text-muted); border-radius:var(--radius-pill);
}
.back-btn svg{ width:24px; height:24px; display:block; }
.back-btn:active{ background: var(--state-press-soft); }
.back-btn:focus-visible{ outline:2px solid var(--focus-ring); outline-offset:-4px; }

/* ───── Índice de Casa ─────
   Agregar un módulo nuevo a la app es agregar una fila acá. La misma fila se
   reusa suelta al final de Cuenta para entrar al historial. */
.hub{ display:flex; flex-direction:column; gap:10px; }
.hub-row{
  width:100%; min-height:60px; display:flex; align-items:center; gap:14px;
  text-align:left; padding:12px 14px; cursor:pointer;
  background: var(--surface); border:1px solid var(--border-subtle);
  border-radius: var(--radius-lg); color:var(--text);
  transition: background var(--dur-2) var(--ease-standard);
}
.hub-row:active{ background: var(--state-press-soft); }
.hub-row:focus-visible{ outline:2px solid var(--focus-ring); outline-offset:2px; }
.hub-ico{
  flex:0 0 auto; display:flex; align-items:center; justify-content:center;
  width:38px; height:38px; border-radius:var(--radius-pill);
  background: var(--accent-tint); color:var(--text-strong);
}
.hub-ico svg{ width:20px; height:20px; display:block; }
.hub-txt{ flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:2px; }
.hub-name{ color:var(--text-strong); font-weight:var(--fw-semibold); font-size:var(--text-base); }
.hub-desc{ color:var(--text-muted); font-size:var(--text-xs); line-height:var(--lh-snug); }
.hub-chev{ flex:0 0 auto; width:18px; height:18px; color:var(--text-faint); }
.hub-row-inline{ margin-top:14px; }

/* Ajustes */
.setting{ background: var(--surface); border:1px solid var(--border-subtle); border-radius:var(--radius-lg); padding:16px; margin-bottom:16px; }
.setting-label{ color:var(--text-strong); font-weight:var(--fw-semibold); font-size:var(--text-base); margin-bottom:3px; }
.setting-desc{ color:var(--text-muted); font-size:var(--text-xs); margin-bottom:14px; line-height:var(--lh-snug); }
/* ───── PIN de casa (solo front remoto) ─────
   No es un sheet: no se cierra, no se registra, no tiene Escape. Tapa todo hasta
   que la API acepte el PIN, y vuelve solo si la API lo rechaza (lo cambiaron en la
   planilla). Mundo shell, como la tarjeta de carga. */
.pin-gate{
  position:fixed; inset:0; z-index:var(--z-toast); background:var(--bg-page-bottom);
  display:flex; align-items:center; justify-content:center; padding:24px;
}
.pin-gate[hidden]{ display:none; }
.pin-card{
  width:100%; max-width:380px; background:var(--surface); border:1px solid var(--border-subtle);
  border-radius:var(--radius-md); padding:22px 18px; display:flex; flex-direction:column; gap:12px;
}
.pin-brand{ font-family:var(--font-mono); font-size:var(--text-xs); letter-spacing:0.12em; text-transform:uppercase; color:var(--accent); }
.pin-title{ margin:0; color:var(--text-strong); font-size:var(--text-xl); font-weight:var(--fw-semibold); }
.pin-desc{ margin:0; color:var(--text-muted); font-size:var(--text-sm); line-height:var(--lh-base); min-height:1.4em; }
.pin-desc.is-error{ color:var(--danger); }
.pin-card label{ display:flex; flex-direction:column; gap:6px; font-size:var(--text-xs); color:var(--text-muted); }

.about{ text-align:center; color:var(--text-fainter); font-size:var(--text-xs); margin-top:22px; font-family:var(--font-mono); }
.theme-row{ display:flex; align-items:center; justify-content:space-between; gap:12px; padding:10px 0; }
.theme-row + .theme-row{ border-top:1px solid var(--hairline); }
.theme-name{ font-family:var(--font-mono); font-size:var(--text-sm); color:var(--text); }
.theme-select{
  font-family:var(--font-sans); font-size:var(--text-sm); font-weight:var(--fw-semibold);
  color:var(--text-strong); background:var(--surface-raised);
  border:1px solid var(--border-strong); border-radius:var(--radius-sm);
  padding:8px 12px; min-height:40px; cursor:pointer;
}
.theme-select:focus-visible{ outline:2px solid var(--focus-ring); outline-offset:2px; }

/* Bottom nav */
.tabbar{
  position: fixed; left:0; right:0; bottom:0; z-index:var(--z-tabbar);
  background: var(--scrim-bottom);
  -webkit-backdrop-filter: saturate(1.2) blur(12px); backdrop-filter: saturate(1.2) blur(12px);
  border-top: 1px solid var(--hairline);
  padding-bottom: env(safe-area-inset-bottom);
}
.tabbar-inner{ max-width:460px; margin:0 auto; display:flex; }
.tab{
  flex:1; display:flex; flex-direction:column; align-items:center; gap:4px;
  min-height:56px; padding:8px 4px 6px; border:none; background:none; cursor:pointer; color:var(--text-faint);
}
.tab-ico{ display:flex; align-items:center; justify-content:center; width:54px; height:28px; border-radius:var(--radius-pill); transition: background var(--dur-2) var(--ease-standard); }
.tab-ico svg{ width:22px; height:22px; display:block; }
.tab-lbl{ font-size:var(--text-2xs); font-weight:var(--fw-semibold); letter-spacing:0.01em; }
.tab.active{ color:var(--text-strong); }
.tab.active .tab-ico{ background: var(--accent-tint); }
.tab:active .tab-ico{ background: var(--state-press-soft); }
.tab:focus-visible{ outline:2px solid var(--focus-ring); outline-offset:-3px; border-radius:var(--radius-md); }

.split-row{
  display:inline-flex; align-items:center; justify-content:center; gap:8px; flex-wrap:wrap;
  max-width:100%; background: var(--surface-raised); border: 1px solid var(--border-chip);
  border-radius: var(--radius-2xl); padding: 8px 16px; color:var(--text);
  font-size:var(--text-sm); font-family:var(--font-mono);
}
.split-row button{
  background:none;border:none;color:var(--text-muted);
  display:inline-flex; align-items:center; gap:6px;
  font-family:var(--font-sans); font-size:var(--text-sm); cursor:pointer; padding:6px 8px; min-height:34px;
}
/* El subrayado va en el texto, no en el botón: sobre un contenedor flex
   también alcanzaría al hueco del icono y quedaría un rayón suelto. */
.split-row button .split-txt{ text-decoration:underline; }
.split-row button svg{ flex:0 0 auto; width:14px; height:14px; }
.split-row button.split-save{ color:var(--text-strong); font-weight:var(--fw-bold); }
.split-row button:hover{ color:var(--text-strong); }
.split-row button:active{ color:var(--text-strong); }
.split-edit{ display:flex; align-items:center; justify-content:center; flex-wrap:wrap; gap:8px; }
.split-row .split-edit input[type="number"]{
  width: 68px; min-height:40px; padding:8px 10px; border-radius:var(--radius-sm); border:1px solid var(--paper-border-strong);
  font-family:var(--font-mono); font-size:16px; text-align:center;
}

.add-card{
  background: var(--surface); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md); padding: 16px; margin-bottom: 22px;
}
.add-title{ color:var(--text-strong); font-size:var(--text-base); margin:0 0 12px; font-weight:var(--fw-semibold); }
.payer-toggle{ display:flex; gap:8px; margin-bottom:12px; }
.payer-btn{
  flex:1; min-height:52px; padding:12px 8px; border-radius:var(--radius-md); border:1.5px solid var(--border-strong);
  background: transparent; color:var(--text); font-family:var(--font-sans); font-weight:var(--fw-semibold);
  font-size:var(--text-lg); cursor:pointer; transition: all var(--dur-1) var(--ease-standard);
}
.payer-btn:active{ transform: scale(0.98); }
.payer-btn[data-payer="gaston"].active{ background: var(--payer-a); border-color: var(--payer-a); color:var(--text-on-accent); }
.payer-btn[data-payer="abi"].active{ background: var(--payer-b); border-color: var(--payer-b); color:var(--text-on-accent); }
.payer-btn:focus-visible{ outline: 2px solid var(--focus-ring); outline-offset:2px; }

.field-stack{ display:flex; flex-direction:column; gap:12px; margin-bottom:12px; }
.field-stack label, .concepto-label{
  display:flex; flex-direction:column; gap:6px; font-size:var(--text-xs); color:var(--text-muted); width:100%;
}
input[type="number"], input[type="date"], input[type="text"], input[type="tel"], input[type="url"], input[type="password"], .field-textarea{
  width:100%;
  font-family:var(--font-mono); font-size:16px; padding:13px 14px;
  min-height:50px; border-radius:var(--radius-md); border:1px solid var(--border-field);
  background: var(--field-bg); color:var(--ink); -webkit-appearance:none; appearance:none;
}
input:focus-visible, .field-textarea:focus-visible{ outline:2px solid var(--accent); outline-offset:1px; }
input::placeholder, .field-textarea::placeholder{ color:var(--field-placeholder); opacity:1; }

/* ───── Campo multilínea (Notas) ─────
   Hereda todo el bloque de campos de arriba; acá sólo la parte multilínea.
   Arranca en 2 líneas (26px de padding + 2 de borde + 2×22 de texto = 72) y
   autoGrow() lo estira con el contenido hasta 6 líneas; de ahí en más scrollea.
   Sin resize manual: el alto lo maneja el JS y la manija rompe el sheet. */
.field-textarea{
  display:block; line-height:22px;
  min-height:72px; max-height:160px;
  resize:none; overflow-y:auto;
}
.concepto-label{ margin-bottom:16px; }

/* ───── Campo de monto (toggle de moneda) ─────
   Mismo idiom que .cat-field: el input queda intacto —hereda el bloque de campos
   de arriba, incluido el 16px anti-zoom— y el adorno va absoluto encima.

   Pero el prefijo dejó de ser adorno: ES el selector de moneda. Se convirtió el
   $ que ya estaba en vez de sumar un control al lado porque cargar un gasto es
   la pantalla más usada de la app, y agregarle chrome permanente para un caso
   que pasa una vez al año le cobra el costo al 99% de las cargas. La hairline de
   la derecha es lo único que se agregó, y no es decoración: sin ninguna señal de
   que se toca, el toggle es indescubrible y la feature no existe.

   El ancho es explícito y por estado, no auto: "US$" mide casi el doble que "$"
   y el padding-left del input tiene que despejarlo exactamente. Con ancho auto
   el CSS no tiene forma de saber cuánto padding poner. */
.amount-field{ position:relative; display:block; width:100%; }
/* Con `.amount-input` solo no alcanza: el padding shorthand de input[type="text"]
   tiene más especificidad y el prefijo termina encima del número. */
/* El padding es el ancho del botón (left:1px + width) MÁS los 14px que separan del
   borde a todos los demás campos del formulario. Si es sólo el ancho del botón, el
   número queda pegado a la divisoria y el campo pierde el ritmo de los de al lado. */
.amount-field .amount-input{ padding-left:59px; }   /*  1 + 44 + 14 */
.amount-field.is-usd .amount-input{ padding-left:77px; }   /*  1 + 62 + 14 */
.amount-cur{
  position:absolute; left:1px; top:1px; bottom:1px; width:44px;
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font-mono); font-size:16px; line-height:1;
  color:var(--field-placeholder); background:transparent;
  /* --paper-border-strong y no --border-field: en `classic` el campo es blanco y
     --border-field es blanco al 20%, o sea que la divisoria desaparecía y el
     toggle volvía a parecer el $ decorativo de antes. Este token contrasta contra
     el fondo del campo en los 4 temas, y es el que ya usan los inputs de sheet. */
  border:0; border-right:1px solid var(--paper-border-strong);
  border-radius:var(--radius-md) 0 0 var(--radius-md);
  padding:0; cursor:pointer; -webkit-appearance:none; appearance:none;
}
/* En dólares toma el acento: es la señal de que este gasto NO va al saldo en
   pesos, visible sin leer, en el momento de cargarlo y no después. */
.amount-field.is-usd .amount-cur{ width:62px; color:var(--accent); }
.amount-cur:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px; }

/* ───── Campo de categoría (trigger del sheet) ─────
   Sigue siendo un input[type=text] readonly: hereda todo el bloque de campos
   de arriba (tamaño, fondo, borde, 16px anti-zoom de iOS) en los 4 temas y en
   los 2 mundos, y input.value sigue siendo el transporte al guardar. */
.cat-field{ position:relative; display:block; width:100%; }
.cat-trigger{ cursor:pointer; padding-right:40px; text-overflow:ellipsis; }
.cat-trigger.has-emo{ padding-left:44px; }
.cat-emo-badge{
  position:absolute; top:50%; left:14px; transform:translateY(-50%);
  font-size:19px; line-height:1; pointer-events:none;  /* el click va al input */
}
.cat-chevron{
  position:absolute; top:50%; right:14px; transform:translateY(-50%);
  width:18px; height:18px; pointer-events:none;
  color:var(--field-placeholder);
}

/* ───── Sheet de categorías ───── */
.sheet-overlay-top{ z-index:var(--z-sheet-top); }  /* se apila sobre el sheet de edición */
.cat-search{ margin-bottom:8px; }
.cat-list{
  list-style:none; margin:0; padding:0;
  max-height:58vh; overflow-y:auto; overscroll-behavior:contain;
  /* Explícito: con overflow-y:auto, un overflow-x:visible se computa como auto y
     cualquier fila más ancha que la lista genera scroll horizontal. */
  overflow-x:hidden;
  -webkit-overflow-scrolling:touch;
}
/* Filas altas: se tocan con el pulgar, a una mano. 60px queda por encima de los
   56px de la tab bar, que es el target más grande que ya usa la app. */
.cat-opt{
  display:flex; align-items:center; gap:13px;
  min-height:60px; padding:14px 12px;
  border-radius:var(--radius-sm); cursor:pointer; user-select:none;
  font-family:var(--font-mono); font-size:var(--text-lg); color:var(--ink);
}
.cat-opt + .cat-opt{ border-top:1px dashed var(--paper-hairline); }
.cat-emo{
  flex:0 0 26px; width:26px; text-align:center;
  font-size:21px; line-height:1;
}
.cat-opt-txt{ flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cat-hit{ font-weight:var(--fw-bold); }
.cat-check{ flex:0 0 auto; width:18px; height:18px; color:var(--accent); }
.cat-opt[data-active="1"]{ background:var(--accent-tint); }
.cat-opt:hover{ background:var(--on-paper-hover); }
.cat-opt[data-active="1"]:hover{ background:var(--accent-tint); }
/* Footer del picker: las dos salidas quedan fuera de la lista, separadas por una línea
   sólida (la punteada es la de entre categorías). "Crear" es más chico y más callado que
   el primario a propósito — es la acción permanente, y la jerarquía visual tiene que
   seguir la frecuencia real de uso, no la importancia del dato. */
.cat-foot{ border-top:1px solid var(--paper-border); padding-top:16px; display:flex; flex-direction:column; gap:10px; }
.cat-foot[hidden]{ display:none; }
.cat-create[hidden]{ display:none; }
/* Aun cuando los dos son ghost, "Crear" queda un escalón más abajo: es el permanente. */
.cat-create{ min-height:48px; font-size:var(--text-base); font-weight:var(--fw-semibold); }
.ghost-btn:disabled{ opacity:0.5; cursor:not-allowed; }
.cat-create .btn-ico{ width:16px; height:16px; color:var(--accent); }
/* El nombre puede medir hasta 40 caracteres: que se recorte antes de desbordar. */
.cat-create .btn-txt{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cat-msg{
  padding:16px 12px; text-align:center;
  font-family:var(--font-sans); font-size:var(--text-xs); color:var(--ink-soft);
}
/* ───── Iconos en botones ─────
   Los tres botones de acción pasan a flex para poder centrar icono + texto
   como un bloque. El icono hereda el color con `currentColor`, así que no hace
   falta una regla por variante (acento, peligro, ghost) ni por tema. */
.submit-btn, .danger-btn, .ghost-btn{
  display:flex; align-items:center; justify-content:center; gap:9px;
}
.btn-ico{ flex:0 0 auto; width:19px; height:19px; display:block; }

.submit-btn{
  width:100%; min-height:52px; padding:14px; border-radius:var(--radius-md); border:none;
  background: var(--accent); color:var(--text-on-accent); font-weight:var(--fw-bold); font-size:var(--text-lg);
  cursor:pointer; font-family:var(--font-sans); letter-spacing:0.01em;
}
.submit-btn:hover{ filter: brightness(1.08); }
.submit-btn:active{ transform: scale(0.99); filter: brightness(0.96); }
.submit-btn:focus-visible{ outline: 2px solid var(--focus-ring); outline-offset:2px; }
.submit-btn:disabled{ opacity:0.5; cursor:not-allowed; }

.receipt-wrap{ margin-bottom: 18px; }
.zigzag{ height:11px; background-color: var(--paper); }
.zigzag-top{
  -webkit-mask-image:
    linear-gradient(135deg, transparent 8px, #000 0),
    linear-gradient(-135deg, transparent 8px, #000 0);
  mask-image:
    linear-gradient(135deg, transparent 8px, #000 0),
    linear-gradient(-135deg, transparent 8px, #000 0);
  -webkit-mask-position: left top; mask-position: left top;
  -webkit-mask-size: 16px 16px; mask-size: 16px 16px;
  -webkit-mask-repeat: repeat-x; mask-repeat: repeat-x;
  -webkit-mask-composite: source-in, source-in;
  mask-composite: intersect, intersect;
}
.zigzag-bottom{
  -webkit-mask-image:
    linear-gradient(45deg, transparent 8px, #000 0),
    linear-gradient(-45deg, transparent 8px, #000 0);
  mask-image:
    linear-gradient(45deg, transparent 8px, #000 0),
    linear-gradient(-45deg, transparent 8px, #000 0);
  -webkit-mask-position: left bottom; mask-position: left bottom;
  -webkit-mask-size: 16px 16px; mask-size: 16px 16px;
  -webkit-mask-repeat: repeat-x; mask-repeat: repeat-x;
  -webkit-mask-composite: source-in, source-in;
  mask-composite: intersect, intersect;
}
.receipt{ background: var(--paper); padding: 20px 18px 24px; box-shadow: var(--shadow-receipt); }
/* padding y no margin: contra .divider.rule los márgenes verticales de hermanos
   colapsan (14 y 4 dan 14, no 18) y la regla queda pegada al header. */
.receipt-header{ display:flex; align-items:center; justify-content:space-between; gap:10px; padding-bottom:14px; }
.receipt-store{ font-family:var(--font-mono); font-weight:var(--fw-bold); letter-spacing:0.06em; font-size:var(--text-md); white-space:nowrap; }
.receipt-period{
  display:inline-flex; align-items:center; gap:5px; flex-shrink:0; white-space:nowrap;
  font-family:var(--font-mono); font-size:var(--text-2xs); color:var(--ink);
  font-variant-numeric:tabular-nums;
  background: var(--paper-tint-2); border:1px solid var(--paper-border);
  padding:4px 10px; border-radius:var(--radius-pill);
}
.receipt-period svg{ width:12px; height:12px; opacity:0.65; flex-shrink:0; }

.divider{ border:none; border-top: 1.5px dashed var(--line); margin: 10px 0; }
.divider.dotted{ border-top: 1.5px dashed var(--line); height:0; }
/* Regla estructural del ticket: separa bloques (header ↔ items ↔ totales), no
   filas. Va a sangre con el mismo -18px que usa .entry, así corta el papel de
   lado a lado en vez de leerse como una separación más adentro de un bloque.
   Sólida a propósito: lo punteado queda reservado para separar ítems entre sí.

   El margen es 4px y no 18 porque el aire de este lado ya lo pone el vecino con
   su propio padding (14px: el header, la fila, los totales). La regla sólo paga
   la diferencia hasta 18. Si se toca uno de esos cuatro paddings hay que tocar
   este margen, o la línea queda descentrada — que es justo lo que pasaba antes:
   12px de un lado y 23 del otro. */
.divider.rule{ border-top: 1px solid var(--line); height:0; margin: 4px -18px; }

.entries{ display:flex; flex-direction:column; min-height: 20px; }
.entry{
  padding: 14px 18px; margin: 0 -18px; cursor:pointer;
  font-family:var(--font-mono); font-variant-numeric: tabular-nums;
  animation: printIn .25s var(--ease-out); transition: background var(--dur-1) var(--ease-standard);
}
.entry + .entry{ border-top: 1px dashed var(--paper-hairline); }
.entry:active{ background: var(--paper-tint); }
.entry:focus-visible{ outline:2px solid var(--accent); outline-offset:-3px; }
@media (prefers-reduced-motion: reduce){ .entry{ animation:none; } }
@keyframes printIn{ from{ opacity:0; transform: translateY(-6px);} to{opacity:1; transform:translateY(0);} }

.e-top{ display:flex; align-items:baseline; justify-content:space-between; gap:12px; }
.e-top .concept{ font-size:var(--text-base); color:var(--ink); min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.e-top .amount{ font-size:var(--text-base); font-weight:var(--fw-bold); color:var(--ink); white-space:nowrap; }

/* Dos columnas: concepto/pagador a la izquierda, monto/fecha a la derecha. La
   línea de abajo es toda info secundaria, así que se trata pareja. Antes el
   pagador era una pastilla rellena que competía con el monto en cada fila; como
   se repiten siempre los mismos dos nombres, esa tinta era ruido y no señal.
   El punto de color es el mismo idiom que ya usan las filas del detalle (.dg-dot). */
.e-bot{ display:flex; align-items:center; justify-content:space-between; gap:10px; margin-top:6px; }
.e-bot .date{ color:var(--ink-soft); font-size:var(--text-xs); flex:0 0 auto; }
/* El nombre acompaña al punto a propósito: el color solo no puede ser el único
   portador del dato (y los dos temas oscuros los tienen bastante cerca). */
.e-payer{
  display:inline-flex; align-items:center; gap:7px; min-width:0;
  color:var(--ink-soft); font-size:var(--text-xs);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.e-payer .dot{ flex:0 0 auto; width:7px; height:7px; border-radius:var(--radius-pill); }
.entry[data-payer="gaston"] .dot{ background:var(--payer-a); }
.entry[data-payer="abi"] .dot{ background:var(--payer-b); }
/* ───── Skeletons de carga ─────
   Sobre papel, así que usan los tokens del mundo papel. Imitan la silueta de
   una fila del ticket para que no salte el layout cuando llega la data. */
.sk{
  display:block; border-radius:var(--radius-xs);
  background: var(--paper-hairline);
  animation: skPulse 1.3s var(--ease-standard) infinite;
}
@keyframes skPulse{ 0%,100%{ opacity:.55; } 50%{ opacity:1; } }
@media (prefers-reduced-motion: reduce){
  .sk{ animation:none; opacity:.7; }
}
/* Mismo padding que .entry: si no, el ticket salta de alto cuando llega la data. */
.sk-entry{ padding:14px 0; }
.sk-entry + .sk-entry{ border-top:1px dashed var(--paper-hairline); }
.sk-top{ display:flex; align-items:center; justify-content:space-between; gap:12px; }
.sk-bot{ display:flex; align-items:center; justify-content:space-between; gap:10px; margin-top:8px; }
.sk-concept{ height:12px; width:42%; }
.sk-amount{ height:12px; width:22%; }
.sk-date{ height:9px; width:38px; }
/* Imita al pagador, no a la vieja pastilla: mismo alto de texto, no de chip. */
.sk-payer{ height:9px; width:62px; }
.sk-card{ height:64px; border-radius:var(--radius-md); margin-bottom:10px; background:var(--surface); }
.sk-split{ height:16px; width:60%; background:var(--surface); }

/* ───── Error de carga (distinto de "no hay nada") ───── */
.load-error{
  display:flex; flex-direction:column; align-items:center; gap:12px;
  text-align:center; padding:20px 4px 12px;
  color:var(--ink-soft); font-size:var(--text-sm);
}
.load-error .ghost-btn{ width:auto; padding:10px 20px; min-height:44px; }
/* Más marcado que el icono de vacío: es lo que separa "falló" de "no hay nada". */
.load-error-ico{ width:32px; height:32px; opacity:0.55; }
#historialSection .load-error{ color:var(--text-muted); }

.empty-msg{ display:flex; flex-direction:column; align-items:center; gap:12px; text-align:center; color:var(--ink-soft); font-size:var(--text-sm); padding: 22px 4px 12px; font-style:italic; }
.empty-ico{ width:42px; height:42px; opacity:0.38; }

.totals{ font-family:var(--font-mono); font-size:var(--text-sm); font-variant-numeric: tabular-nums; display:flex; flex-direction:column; gap:5px; }
/* Los totales del ticket son el bloque de abajo de una .divider.rule, así que
   ponen su parte del aire (14px) igual que las filas. En el sheet de detalle
   .totals no lleva este padding: ahí la separación la da el divider punteado. */
#receiptResults .totals{ padding-top:14px; gap:8px; }
.totals .row{ display:flex; justify-content:space-between; }
.totals .row.grand{ font-weight:var(--fw-bold); font-size:var(--text-md); padding-top:4px; }

/* ───── Totales del ticket: desglose vs resultado ─────
   Los subtotales por persona son el desglose, no la respuesta: van en el tono
   secundario, del mismo tamaño que el pagador de cada fila. El nombre siempre
   acompaña al punto — el color solo no puede ser el único portador del dato. */
#receiptResults .totals .row.sub{ color:var(--ink-soft); font-size:var(--text-xs); }
.t-who{ display:inline-flex; align-items:center; gap:7px; }
.t-dot{ flex:0 0 auto; width:7px; height:7px; border-radius:var(--radius-pill); }
.t-dot[data-payer="gaston"]{ background:var(--payer-a); }
.t-dot[data-payer="abi"]{ background:var(--payer-b); }
/* El total del mes venía perdiendo contra el monto de un gasto cualquiera
   (md bold vs base bold): la fila más importante del ticket era la más chica de
   las que compiten. Gana por tamaño, que es lo único que se lee de lejos; el
   sello sigue ganando por tratamiento, no hace falta que gane por cuerpo.
   El padding-top da 14px con el gap de arriba: adentro del bloque se usa el
   ritmo de las filas, los 18px quedan para los cortes entre bloques. */
#receiptResults .totals .row.grand{ align-items:baseline; font-size:var(--text-sm); padding-top:6px; }
#receiptResults .totals .row.grand .amount{ font-size:var(--text-2xl); letter-spacing:-0.01em; }

/* Sin regla arriba: acá el corte entre bloques lo hace sólo el aire, así que
   tiene que ser más que los 18px que separan del resto a una línea dibujada.
   Con 18 el sello se leería como una fila más de los totales. */
/* En columna porque puede haber DOS sellos: uno por moneda en deuda, cuando el
   mes tuvo gastos en pesos y en dólares. Con uno solo se ve igual que siempre. */
.stamp-zone{ display:flex; flex-direction:column; align-items:center; gap:12px; padding-top: 32px; }
.stamp{
  border: 3px solid var(--stamp); color: var(--stamp); border-radius: var(--radius-sm); padding: 10px 18px;
  transform: rotate(-3deg); text-align:center; font-family:var(--font-mono);
  font-weight:var(--fw-bold); text-transform:uppercase; letter-spacing:0.06em; font-size:var(--text-sm); opacity:0.9;
}
.stamp .who{ font-size:var(--text-base); margin-bottom:2px; }
.stamp.neutral{ border-color: var(--ink-soft); color:var(--ink-soft); }

.actions-row{ display:flex; gap:10px; margin-bottom:14px; }
.ghost-btn{
  flex:1; min-height:52px; padding:14px; border-radius:var(--radius-md); border:1.5px solid var(--border-ghost);
  background:transparent; color:var(--text); font-family:var(--font-sans); font-weight:var(--fw-semibold);
  font-size:var(--text-lg); cursor:pointer;
}
.ghost-btn:hover{ background: var(--state-hover); }
.ghost-btn:active{ background: var(--state-press); transform: scale(0.99); }
.ghost-btn:focus-visible{ outline:2px solid var(--focus-ring); outline-offset:2px; }

.historial{ margin-bottom: 16px; }
.historial-item{
  background: var(--surface); border:1px solid var(--border-subtle);
  border-radius:var(--radius-lg); padding:14px; margin-bottom:10px; color:var(--text);
  cursor:pointer; transition: background var(--dur-1) var(--ease-standard);
}
.historial-item:active{ background: var(--surface-raised); }
.historial-item:focus-visible{ outline:2px solid var(--focus-ring); outline-offset:2px; }
.hi-top{ display:flex; justify-content:space-between; align-items:center; font-family:var(--font-mono); font-size:var(--text-xs); color:var(--text-muted); font-variant-numeric:tabular-nums; margin-bottom:9px; }
/* block porque puede haber dos (uno por moneda): inline se pegarían en un renglón. */
.hi-saldo{ display:block; font-family:var(--font-mono); font-size:var(--text-md); color:var(--text); }
.hi-saldo strong{ color:var(--text-strong); font-weight:var(--fw-bold); }
.hi-saldo.ok{ color:var(--text-muted); }
.hi-meta{ font-size:var(--text-xs); color:var(--text-faint); margin-top:7px; font-variant-numeric:tabular-nums; }
.historial-empty{ color:var(--text-muted); font-size:var(--text-sm); text-align:center; padding:10px; }

/* ───── Contactos ───── */
.contactos{ margin-top:18px; margin-bottom:16px; }
.contacto{
  background: var(--surface); border:1px solid var(--border-subtle);
  border-radius:var(--radius-lg); padding:14px; margin-bottom:10px; color:var(--text);
}
.co-head{
  display:flex; align-items:center; gap:11px;
  cursor:pointer; border-radius:var(--radius-sm);
  transition: background var(--dur-1) var(--ease-standard);
}
.co-head:active{ background: var(--state-hover); }
.co-head:focus-visible{ outline:2px solid var(--focus-ring); outline-offset:2px; }
.co-emo{ flex:0 0 26px; width:26px; text-align:center; font-size:21px; line-height:1; }
.co-id{ flex:1 1 auto; min-width:0; }
.co-name{
  font-family:var(--font-mono); font-size:var(--text-lg); color:var(--text-strong);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.co-trade{ font-size:var(--text-xs); color:var(--text-muted); margin-top:2px; }
.co-chev{ flex:0 0 auto; width:16px; height:16px; color:var(--text-faint); }
.co-notes{
  font-size:var(--text-sm); color:var(--text-muted); line-height:var(--lh-snug);
  margin-top:10px; padding-top:10px; border-top:1px dashed var(--hairline);
  overflow-wrap:anywhere;
}
.co-actions{ display:flex; gap:8px; margin-top:11px; }
.co-btn{
  flex:1 1 0; min-height:44px;
  display:flex; align-items:center; justify-content:center; gap:7px;
  border:1px solid var(--border-ghost); border-radius:var(--radius-md);
  background:none; color:var(--text-strong); text-decoration:none;
  font-family:var(--font-sans); font-size:var(--text-sm); font-weight:var(--fw-semibold);
  cursor:pointer;
}
.co-btn:hover{ background: var(--state-hover); }
.co-btn:active{ background: var(--state-press); }
.co-btn:focus-visible{ outline:2px solid var(--focus-ring); outline-offset:2px; }
.co-btn svg{ width:16px; height:16px; flex-shrink:0; }
.co-btn.wa{ border-color: var(--accent-tint); color: var(--accent); }
.contactos-empty{
  display:flex; flex-direction:column; align-items:center; gap:8px;
  text-align:center; color:var(--text-muted); font-size:var(--text-sm);
  padding:24px 8px 8px; line-height:var(--lh-snug);
}
.contactos-empty strong{ color:var(--text-strong); font-weight:var(--fw-semibold); }

/* ───── Bitácora ─────
   Archivo de hitos de la casa. Mundo shell (--text-*), como Contactos: el
   detalle y el formulario viven en sheets, que sí son mundo papel. */
.hito-year{
  font-family:var(--font-mono); font-size:var(--text-xs); font-weight:var(--fw-bold);
  color:var(--text-faint); letter-spacing:0.08em;
  margin:18px 0 8px; padding-bottom:6px; border-bottom:1px solid var(--hairline);
}
.hito-year:first-child{ margin-top:4px; }
.hito{
  width:100%; min-height:60px; display:flex; align-items:flex-start; gap:12px;
  text-align:left; padding:12px 14px; margin-bottom:8px; cursor:pointer;
  background: var(--surface); border:1px solid var(--border-subtle);
  border-radius: var(--radius-lg); color:var(--text);
  transition: background var(--dur-2) var(--ease-standard);
}
.hito:active{ background: var(--state-press-soft); }
.hito:focus-visible{ outline:2px solid var(--focus-ring); outline-offset:2px; }
.hi-date{
  flex:0 0 auto; width:52px; padding-top:2px;
  font-family:var(--font-mono); font-size:var(--text-2xs); font-weight:var(--fw-bold);
  color:var(--text-faint); letter-spacing:0.04em; line-height:var(--lh-snug);
}
.hi-emo{ flex:0 0 auto; font-size:19px; line-height:1.2; }
.hi-id{ flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:3px; }
.hi-title{ color:var(--text-strong); font-weight:var(--fw-semibold); font-size:var(--text-base); line-height:var(--lh-snug); }
.hi-sub{ color:var(--text-muted); font-size:var(--text-xs); line-height:var(--lh-snug); }
/* La pastilla de garantía es lo único "activo" de un archivo pasivo: aparece
   solo si el hito tiene vencimiento cargado, y se apaga cuando ya venció. */
.hi-warranty{
  align-self:flex-start; margin-top:2px;
  font-family:var(--font-mono); font-size:var(--text-2xs); letter-spacing:0.02em;
  padding:3px 8px; border-radius:var(--radius-pill);
  background: var(--accent-tint); color:var(--text-strong);
}
.hi-warranty.vencida{ background: var(--state-press-soft); color:var(--text-faint); }
.hi-chev{ flex:0 0 auto; width:18px; height:18px; color:var(--text-faint); align-self:center; }
.bitacora-empty{
  display:flex; flex-direction:column; align-items:center; gap:8px;
  text-align:center; color:var(--text-muted); font-size:var(--text-sm);
  padding:24px 8px 8px; line-height:var(--lh-snug);
}
.bitacora-empty strong{ color:var(--text-strong); font-weight:var(--fw-semibold); }

/* Detalle del hito, adentro del sheet: mundo papel. */
.hito-detail{ display:flex; flex-direction:column; gap:14px; }
.hd-when{ font-family:var(--font-mono); font-size:var(--text-sm); color:var(--ink-soft); }
.hd-notes{ color:var(--ink); font-size:var(--text-base); line-height:var(--lh-base); white-space:pre-wrap; }
.hd-rows{ display:flex; flex-direction:column; gap:0; }
.hd-row{ display:flex; justify-content:space-between; gap:14px; padding:10px 0; border-top:1px solid var(--paper-hairline); }
.hd-key{ color:var(--ink-soft); font-size:var(--text-sm); flex:0 0 auto; }
.hd-val{ color:var(--ink); font-size:var(--text-sm); font-weight:var(--fw-semibold); text-align:right; min-width:0; overflow-wrap:anywhere; }
.hd-val.vencida{ color:var(--ink-soft); font-weight:var(--fw-regular); }
.hd-actions{ display:flex; flex-direction:column; gap:10px; margin-top:2px; }

/* Formulario: "+ Más detalles" mantiene el alta de un hito en 3 campos. */
.more-toggle{
  width:100%; min-height:44px; display:flex; align-items:center; justify-content:center; gap:8px;
  margin-top:12px; padding:10px; cursor:pointer;
  background:none; border:1px dashed var(--paper-border-strong); border-radius:var(--radius-md);
  color:var(--ink-soft); font-size:var(--text-sm); font-weight:var(--fw-semibold);
}
.more-toggle:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
.more-toggle[hidden]{ display:none; }
#hitoMore[hidden]{ display:none; }
#hitoMore{ margin-top:14px; display:flex; flex-direction:column; gap:14px; }
/* Select del sheet: mundo papel. NO reusa .theme-select, que es del shell —
   mezclarlos metía texto de shell sobre fondo de papel. Copia el bloque de
   campos (mismos tokens que un <input>) y sólo pisa el borde, igual que hace
   `.sheet input`. Sin appearance:none, para no perder la flecha nativa. */
.paper-select{
  width:100%; font-family:var(--font-mono); font-size:16px; padding:13px 14px;
  min-height:50px; border-radius:var(--radius-md);
  border:1px solid var(--paper-border-strong);
  background: var(--field-bg); color:var(--ink); cursor:pointer;
}
.paper-select:focus-visible{ outline:2px solid var(--accent); outline-offset:1px; }

.chip-row{ display:flex; flex-wrap:wrap; gap:8px; margin-top:8px; }
.chip{
  min-height:38px; padding:8px 14px; cursor:pointer;
  background: var(--field-bg); border:1px solid var(--paper-border-strong);
  border-radius: var(--radius-pill); color:var(--ink);
  font-family:var(--font-mono); font-size:var(--text-xs);
}
.chip:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
.chip.on{ background: var(--accent-tint); border-color: var(--accent); color:var(--ink); font-weight:var(--fw-bold); }

.confirm-text{ margin:0; font-size:var(--text-base); line-height:var(--lh-base); color:var(--ink); }

/* Bottom sheet (editar / eliminar gasto) */
.sheet-overlay{
  /* inset:0 a secas, SIN esquivar el teclado: acá no se puede medir dónde está
     (ver el comentario de kb-typing, más abajo). Del teclado se ocupan openSheet()
     —lo baja antes de abrir— y kb-typing —pantalla completa mientras se tipea—,
     y ninguno de los dos necesita un número. Hubo un `bottom: var(--kb)` medido
     con visualViewport: se borró, porque adentro del iframe de /exec la medición
     es basura y un valor inventado ACHICA el overlay — el sheet terminaba corto,
     flotando arriba de un hueco. No reintroducir medidas del teclado. */
  position:fixed; inset:0; z-index:var(--z-sheet);
  background: var(--scrim);
  display:flex; align-items:flex-end; justify-content:center;
  opacity:0; visibility:hidden; transition: opacity var(--dur-3) var(--ease-standard), visibility var(--dur-3) var(--ease-standard);
}
.sheet-overlay.open{ opacity:1; visibility:visible; }
.sheet{
  /* 90% del overlay (que es el viewport entero): igual que 90vh, pero en % para
     que si el overlay alguna vez cambia de alto, el sheet lo siga. */
  width:100%; max-width:460px; max-height:90%; overflow-y:auto;
  background: var(--paper); border-radius:var(--radius-xl) var(--radius-xl) 0 0;
  padding: 10px 18px calc(20px + env(safe-area-inset-bottom));
  box-shadow: var(--shadow-sheet);
  transform: translateY(100%); transition: transform var(--dur-4) var(--ease-sheet);
}
.sheet-overlay.open .sheet{ transform: translateY(0); }
@media (prefers-reduced-motion: reduce){
  .sheet-overlay, .sheet{ transition: opacity .01s; }
}
/* Mientras se tipea, el sheet se ancla ARRIBA.
   Anclar arriba no necesita saber cuánto mide el teclado — y de paso evita que iOS
   empuje la página para dejar el campo a la vista, porque ya está arriba.
   Sólo en pantallas táctiles: en escritorio no hay teclado que esquivar y el salto
   se leería como un bug. En el preview se prueba con el modo mobile del navegador,
   que emula pointer:coarse. */
@media (hover: none) and (pointer: coarse){
  html.kb-typing .sheet-overlay{ align-items: flex-start; }
  /* PANTALLA COMPLETA, sin números. Se probó recortar el sheet a un alto fijo
     (46vh, después 52vh) y las dos veces cayó mal: adentro del iframe de /exec no
     hay NINGUNA medida confiable — visualViewport no reporta el teclado y hasta vh
     miente, porque el iframe no mide lo que la pantalla (arriba está el wrapper de
     Google). Cualquier número elegido a mano deja una franja muerta en un teléfono
     y queda tapado en otro. El único alto que no es una apuesta es "todo el
     iframe": el sheet lo llena, el campo queda arriba a la vista, y lo que caiga
     atrás del teclado se alcanza con el único scroll, el del sheet. Es además el
     patrón nativo: el share sheet de iOS también se va a pantalla completa cuando
     escribís en su buscador. */
  html.kb-typing .sheet{
    height:100%; max-height:none; border-radius:0;
    /* La cola de 65vh es lo que permite traer el FINAL del contenido (el footer
       del picker, el botón Guardar) por arriba del teclado arrastrando. Generosa a
       propósito: sobrar deja vacío al final del scroll y no molesta; faltar deja
       botones inalcanzables. Sólo existe mientras se tipea. */
    padding: calc(20px + env(safe-area-inset-top)) 18px 65vh;
    overscroll-behavior: contain;
  }
  /* El agarre es la marca de algo que sube desde abajo; acá miente. */
  html.kb-typing .sheet-handle{ display:none; }
  /* UN SOLO scroll, el del sheet. Con la lista scrolleando aparte (su max-height de
     58vh), arrastrar sobre las categorías movía la lista y nunca el sheet, y el
     footer con las dos salidas quedaba inalcanzable: no cortado, inalcanzable. */
  html.kb-typing .cat-list{ max-height:none; overflow-y:visible; }
}
.sheet-handle{ width:38px; height:4px; border-radius:var(--radius-xs); background: var(--handle); margin:2px auto 12px; }
.sheet-head{ display:flex; align-items:center; justify-content:space-between; margin-bottom:16px; }
.sheet-title{ font-family:var(--font-mono); font-size:var(--text-lg); font-weight:var(--fw-bold); color:var(--ink); margin:0; letter-spacing:0.02em; }
.sheet-close{
  width:36px; height:36px; display:flex; align-items:center; justify-content:center;
  border:none; background:none; color:var(--ink-soft); cursor:pointer; border-radius:var(--radius-sm);
}
.sheet-close svg{ width:18px; height:18px; display:block; }
.sheet-close:hover{ background: var(--on-paper-hover); }
.sheet-close:focus-visible{ outline:2px solid var(--accent); outline-offset:-2px; }
/* Campos del sheet sobre papel claro: texto/bordes oscuros */
.sheet label{ color: var(--ink-soft); }
.sheet input[type="text"], .sheet input[type="date"], .sheet input[type="tel"], .sheet input[type="url"], .sheet .field-textarea{ border-color: var(--paper-border-strong); }
.sheet .payer-btn{ color: var(--ink); border-color: var(--paper-border-payer); }

.sheet-foot{ margin-top:20px; }
.foot-main{ display:flex; flex-direction:column; gap:10px; }
.foot-main[hidden], .foot-confirm[hidden]{ display:none; }
.foot-confirm .confirm-q{ text-align:center; color:var(--ink); font-size:var(--text-base); font-weight:var(--fw-semibold); margin:0 0 12px; }
.foot-confirm .confirm-row{ display:flex; flex-direction:column; gap:10px; }
.danger-btn{
  width:100%; min-height:52px; padding:14px; border-radius:var(--radius-md);
  border:1.5px solid var(--danger-border); background:transparent; color:var(--danger);
  font-family:var(--font-sans); font-weight:var(--fw-bold); font-size:var(--text-lg); cursor:pointer;
}
.danger-btn:hover{ background: var(--danger-tint); }
.danger-btn:active{ background: var(--danger-tint-strong); }
.danger-btn:focus-visible{ outline:2px solid var(--danger); outline-offset:2px; }
.danger-btn.solid{ background: var(--danger); color:var(--text-on-accent); border-color: var(--danger); }
.danger-btn.solid:hover{ filter: brightness(1.06); background: var(--danger); }
.sheet .ghost-btn{ color: var(--ink); border-color: var(--paper-border-ghost); }
.sheet .ghost-btn:hover{ background: var(--on-paper-hover); }

/* Detalle de un período (dentro del sheet, sobre papel) */
.detail-range{ display:flex; justify-content:space-between; font-family:var(--font-mono); font-size:var(--text-xs); color:var(--ink-soft); font-variant-numeric:tabular-nums; margin-bottom:12px; }
/* Un .detail-saldo-item por moneda en deuda; con uno solo se ve igual que antes. */
.detail-saldo{ display:flex; flex-direction:column; gap:14px; margin-bottom:4px; }
.detail-saldo-item{ display:flex; flex-direction:column; gap:3px; }
.detail-saldo-label{ font-size:var(--text-sm); color:var(--ink-soft); }
.detail-saldo-amount{ font-family:var(--font-mono); font-size:var(--text-2xl); font-weight:var(--fw-bold); color:var(--ink); font-variant-numeric:tabular-nums; line-height:1.1; }
.detail-gastos{ display:flex; flex-direction:column; }
.dg-row{
  display:grid; grid-template-columns:9px auto minmax(0,1fr) auto; align-items:center; gap:9px;
  padding:9px 0; font-family:var(--font-mono); font-variant-numeric:tabular-nums;
}
.dg-row + .dg-row{ border-top:1px dashed var(--paper-hairline); }
.dg-dot{ width:9px; height:9px; border-radius:var(--radius-pill); }
.dg-dot[data-payer="gaston"]{ background:var(--payer-a); }
.dg-dot[data-payer="abi"]{ background:var(--payer-b); }
.dg-date{ color:var(--ink-soft); font-size:var(--text-xs); }
.dg-concept{ color:var(--ink); font-size:var(--text-sm); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.dg-amount{ color:var(--ink); font-weight:var(--fw-bold); font-size:var(--text-sm); white-space:nowrap; }

.note{ text-align:center; color:var(--text-faint); font-size:var(--text-xs); margin-top:10px; }
.sync-dot{ display:inline-block; width:7px; height:7px; border-radius:var(--radius-pill); background:var(--positive); margin-right:5px; vertical-align:middle; }
.sync-dot.off{ background:var(--danger); }
.sync-row{ display:flex; align-items:center; gap:2px; }
.sync-label{ font-family:var(--font-mono); font-size:var(--text-sm); color:var(--text); }
.toast{
  position:fixed; bottom:18px; left:50%; transform:translateX(-50%);
  background:var(--toast-bg); color:var(--toast-text); padding:9px 16px; border-radius:var(--radius-2xl);
  font-size:var(--text-xs); box-shadow:var(--shadow-toast); z-index:var(--z-toast); animation: toastIn .2s var(--ease-out);
}
@keyframes toastIn{ from{opacity:0; transform:translate(-50%,8px);} to{opacity:1; transform:translate(-50%,0);} }
