/* ==========================================================
   Linit — Design system CSS
   Variables de diseño propias (NO Cyprivi)
   ========================================================== */

:root {
  /* Tema claro fijo: evita el force-dark de Chrome Android (se veía oscura). */
  color-scheme: light;
  --bg:       #f3faf6;
  --surface:  #ffffff;
  --ink:      #13241c;

  /* ── Tokens de TINTA (siempre se usan como color de texto o de un icono
     sobre fondo claro: --surface, --bg o su propio par "-s").
     Los valores originales (--muted #6f8279, --brand2 #059669, --sky
     #0ea5e9, --amber #f59e0b, --coral #f43f5e, --plum #8b5cf6, --teal
     #0d9488, --green #22c55e) daban entre 1.9:1 y 4.1:1 sobre esos fondos:
     TODOS por debajo del 4.5:1 que WCAG 2.1 AA exige para texto normal, y
     --green ni siquiera llegaba al 3:1 de componente de interfaz que necesita
     el check ✓ blanco de .check.on. Se bajó cada tono a su equivalente ~700
     de la misma familia — mismo hue, misma lectura de color, ya en AA. Los
     pares "-s" NO cambian: son fondos suaves y su contraste lo aporta la
     tinta. Si tocas uno de estos siete, ContrasteTokensAaTest lo verifica.
     ── */
  --line:     #e6efe9;
  --muted:    #5f7169;   /* 5.18:1 sobre blanco · 4.89:1 sobre --bg */
  --brand:    #10b981;   /* fondo/identidad, no se usa como tinta */
  --brand2:   #047857;   /* 5.48:1 sobre blanco · 4.76:1 sobre --brand-s */
  --brand-s:  #d7f6e6;
  --teal:     #0f766e;   /* 5.47:1 sobre blanco · 4.65:1 sobre --teal-s */
  --teal-s:   #d3f3ef;
  --sky:      #0369a1;   /* 5.93:1 sobre blanco · 5.13:1 sobre --sky-s */
  --sky-s:    #dcf2fd;
  --amber:    #96560a;   /* 5.78:1 sobre blanco · 5.12:1 sobre --amber-s */
  --amber-s:  #fdf0d5;
  --coral:    #be123c;   /* 6.29:1 sobre blanco · 5.19:1 sobre --coral-s */
  --coral-s:  #fde3e8;
  --plum:     #6d28d9;   /* 7.10:1 sobre blanco · 5.94:1 sobre --plum-s */
  --plum-s:   #ede8fc;
  --green:    #15803d;   /* 5.02:1 sobre blanco (check ✓ blanco de .check.on) */
  --radius:   22px;
  --shadow:   0 2px 6px rgba(20,80,50,.05), 0 14px 30px rgba(20,80,50,.07);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

body {
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}

svg { display: block; }

/* ——— Layout app ——— */
.app {
  max-width: 480px;
  margin: 0 auto;
  min-height: 100vh;
  padding-bottom: 96px;
  position: relative;
}

/* ——— Header ——— */
.top {
  padding: 24px 20px 6px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
/* El nombre del hogar es lo único elástico del header: es texto y se puede
   recortar sin perder función. min-width:0 le permite encogerse por debajo
   de su contenido dentro del flex. */
.greet    { min-width: 0; }
.greet h1 { font-size: 21px; font-weight: 720; letter-spacing: -.4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.greet p  { font-size: 13px; color: var(--muted); margin-top: 2px; }
.who      { display: flex; align-items: center; }
/* Botón real que envuelve moneda + avatares (ver _header.php): el disparador
   de Perfil accesible con teclado. Sin caja propia — hereda el aire del
   header — pero con 44px de alto para cumplir el mínimo táctil. */
.who-perfil {
  display: flex; align-items: center;
  min-height: 44px; padding: 0; margin: 0;
  background: none; border: none; cursor: pointer;
  font: inherit; color: inherit;
}
.av {
  width: 38px; height: 38px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 13px; font-weight: 700; color: #fff;
  border: 2.5px solid var(--bg);
  cursor: default;
  /* Sin esto, a 320px el header reparte el recorte entre sus hijos y los
     avatares se aplastan a 35x38: círculos convertidos en elipses justo
     donde el usuario reconoce quién es quién. Que se recorte el nombre del
     hogar, que para eso lleva ellipsis. */
  flex-shrink: 0;
}
.curchip {
  font-size: 11px; font-weight: 800;
  background: var(--brand-s); color: var(--brand2);
  padding: 6px 9px; border-radius: 9px; margin-right: 6px;
  flex-shrink: 0;
}

/* ——— Month nav ——— */
.gmonth {
  display: flex; align-items: center; justify-content: center;
  gap: 18px; padding: 8px 20px 2px;
}
.gmonth button {
  /* 44x44 es el mínimo táctil (WCAG 2.5.5 / HIG). Estaba en 40x40 y son los
     dos botones que más se pulsan del header: cambiar de mes es el gesto de
     entrada a media app. */
  width: 44px; height: 44px;
  border: none; background: var(--surface);
  border-radius: 12px; box-shadow: var(--shadow);
  color: var(--brand2); font-size: 17px; cursor: pointer;
  display: grid; place-items: center;
}
.gm { font-size: 14px; font-weight: 740; min-width: 110px; text-align: center; }
.gm small { display: block; font-size: 10px; color: var(--muted); font-weight: 600; }

/* ——— Vistas ——— */
.view { display: none; padding: 8px 16px 16px; animation: fade .28s ease; }
.view.active { display: block; }
@keyframes fade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; } }

/* ——— Section title ——— */
.section-title {
  font-size: 12px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .7px;
  margin: 22px 6px 12px;
  display: flex; justify-content: space-between; align-items: center;
}

/* ——— Hero ——— */
.hero {
  position: relative; overflow: hidden;
  background: linear-gradient(140deg, #22c55e 0%, #10b981 55%, #0d9488 100%);
  color: #fff; border-radius: 26px; padding: 24px;
  box-shadow: 0 16px 36px rgba(16,185,129,.32);
}
.hero::after  { content:""; position:absolute; top:-40px; right:-30px; width:160px; height:160px; border-radius:50%; background:rgba(255,255,255,.13); }
.hero::before { content:""; position:absolute; bottom:-50px; left:-20px; width:120px; height:120px; border-radius:50%; background:rgba(255,255,255,.08); }
.hero .label { font-size: 13px; opacity: .92; font-weight: 500; position: relative; text-align: center; }
.hero .autoupdate { font-size: 10.5px; opacity: .72; font-weight: 500; position: relative; text-align: center; margin-top: 1px; }
.hero .big   { font-size: 38px; font-weight: 760; letter-spacing: -1.1px; margin: 6px 0 2px; position: relative; text-align: center; }
.hero .sub   { font-size: 13px; opacity: .92; position: relative; text-align: center; }
.heroduo { display: flex; gap: 10px; margin-top: 16px; position: relative; }
.heroduo > div { flex: 1; background: rgba(255,255,255,.16); border-radius: 14px; padding: 10px 12px; cursor: pointer; }
.heroduo .hk  { font-size: 11px; opacity: .9; }
.heroduo .hv  { font-size: 17px; font-weight: 740; margin-top: 2px; }


/* ——— hduo2 (score + checklist) ——— */
.hduo2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 16px; }
.htile {
  background: var(--surface); border-radius: 18px; padding: 14px 8px 13px;
  box-shadow: var(--shadow); text-align: center; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
.htile.dark { background: linear-gradient(135deg,#0b1a15,#0a2a23); color: #fff; position: relative; overflow: hidden; }
.htlabel { font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .6px; color: var(--muted); }
.htile.dark .htlabel { color: #79a99a; }
.hgauge  { width: 98px; margin: 4px auto 0; }
.hbig    { font-size: 25px; font-weight: 800; letter-spacing: -1px; line-height: 1; margin-top: 2px; }
.hzone   { font-size: 11px; font-weight: 740; margin-top: 3px; }
.hring   { position: relative; width: 70px; height: 70px; margin: 8px auto 6px; }
.hring .num { position: absolute; inset: 0; display: grid; place-items: center; font-size: 17px; font-weight: 760; }

/* ——— Executive cards ——— */
.exec { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 14px; }
.ecard {
  background: var(--surface); border-radius: 16px; padding: 13px 12px;
  box-shadow: var(--shadow); cursor: pointer; transition: .12s; text-align: center;
}
.ecard:active { transform: scale(.98); }
.ecard .eic  { width: 30px; height: 30px; border-radius: 9px; display: grid; place-items: center; margin: 0 auto 8px; }
.ecard .ek   { font-size: 11px; color: var(--muted); font-weight: 650; }
.ecard .ev   { font-size: 17px; font-weight: 780; letter-spacing: -.4px; margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ecard .es   { font-size: 10.5px; color: var(--brand2); font-weight: 650; margin-top: 4px; }

/* ——— Card y List ——— */
.card { background: var(--surface); border-radius: var(--radius); padding: 16px; box-shadow: var(--shadow); }
.list { background: var(--surface); border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; }

/* ——— Checklist items ——— */
.item { display: flex; align-items: center; gap: 12px; padding: 11px 16px; border-bottom: 1px solid var(--line); }
.item:last-child { border-bottom: none; }
.check {
  width: 26px; height: 26px; border-radius: 9px;
  border: 2px solid var(--line); flex-shrink: 0;
  display: grid; place-items: center; cursor: pointer; transition: .15s;
}
.check.on { background: var(--green); border-color: var(--green); }
.check svg { width: 15px; height: 15px; opacity: 0; transition: .15s; }
.check.on svg { opacity: 1; }
.item .body { flex: 1; min-width: 0; }
.item .t    { font-size: 14.5px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.item.done .lbl { color: var(--muted); text-decoration: line-through; }
.item .s    { font-size: 11.5px; color: var(--muted); margin-top: 2px; display: flex; align-items: center; gap: 6px; }
.item .amt  { font-size: 14px; font-weight: 680; white-space: nowrap; text-align: right; }
/* Editar y eliminar directamente en la fila del gasto (pedido por Daniel,
   2026-08-30). Antes solo se llegaba abriendo el detalle, o sea dos toques y
   una pantalla de por medio para algo que se hace a diario.

   Área de toque de 30px aunque el icono mida 15: en el móvil, un botón de
   borrar más pequeño que el dedo es un borrado por accidente esperando a
   pasar. Y el de eliminar va SEGUNDO y en rojo, lejos del pulgar que viene
   de tocar la fila. */
.item-acciones { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
.item-accion {
  width: 30px; height: 30px; border: none; background: transparent;
  border-radius: 8px; cursor: pointer; padding: 0;
  display: grid; place-items: center;
  color: var(--muted); opacity: .55; transition: opacity .15s, background .15s, color .15s;
}
.item-accion:hover  { opacity: 1; background: rgba(125,211,252,.10); color: var(--brand2); }
.item-accion.danger:hover { background: var(--coral-s); color: var(--coral); }
.item-accion:focus-visible { outline: 2px solid var(--brand2); outline-offset: 1px; opacity: 1; }
/* En pantallas táctiles no hay hover: si dependieran de él, se verían
   apagados para siempre justo donde más se usan. */
@media (hover: none) { .item-accion { opacity: .75; } }

.due  { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 7px; }
.due.ok   { background: var(--sky-s); color: var(--sky); }
.due.late { background: var(--coral-s); color: var(--coral); }
.due.soft { background: var(--plum-s); color: var(--plum); }
.rec  { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 7px; background: var(--brand-s); color: var(--brand2); }
/* Cuota diferida que no se pagó en su mes: ni se esconde ni se pinta de rojo.
   Es un aviso, no una alarma — el dinero sigue debiéndose, no ha pasado nada
   malo todavía. Usa --amber, que ya es el ámbar accesible del tema. */
.arrastre { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 7px; background: var(--amber-s); color: var(--amber); }

/* ——— Bolsillos ——— */
.pcarousel {
  display: flex; gap: 12px; overflow-x: auto; scroll-snap-type: x mandatory;
  padding: 2px 0 8px; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; margin: 0 -16px; padding-left: 16px; padding-right: 16px;
}
.pcarousel::-webkit-scrollbar { display: none; }
.pocket {
  border-radius: 16px; padding: 13px 15px; color: #fff;
  position: relative; overflow: hidden; box-shadow: var(--shadow);
  scroll-snap-align: start; flex: 0 0 76%; min-width: 76%;
}
.pocket::after { content:""; position:absolute; top:-20px; right:-20px; width:90px; height:90px; border-radius:50%; background:rgba(255,255,255,.14); }
.pocket .pk   { font-size: 13px; font-weight: 600; opacity: .92; position: relative; }
.pocket .pv   { font-size: 19px; font-weight: 760; letter-spacing: -.5px; margin-top: 3px; position: relative; }
.pocket .pb   { height: 5px; border-radius: 5px; background: rgba(255,255,255,.28); margin-top: 9px; position: relative; overflow: hidden; }
.pocket .pb i { display: block; height: 100%; background: #fff; border-radius: 6px; }
.pocket .pmeta { font-size: 10.5px; opacity: .9; margin-top: 6px; position: relative; }

/* ——— Modales ——— */
.mscrim {
  position: fixed; inset: 0; background: rgba(19,36,28,.5);
  z-index: 55; display: none; align-items: center; justify-content: center; padding: 18px;
}
.mscrim.open { display: flex; }
.modal {
  width: 100%; max-width: 420px; background: var(--surface);
  border-radius: 24px; box-shadow: 0 20px 50px rgba(0,0,0,.25);
  max-height: 84vh; display: flex; flex-direction: column;
  animation: pop .2s ease;
  /* Bug real (Daniel, 2026-08-24): al crear un bolsillo, los conceptos
     sugeridos se salían del cuadro y no se podía hacer scroll.
     
     La causa era estructural, no de ese modal: .modal es un flex column con
     max-height, y en un flex column el contenido DESBORDA salvo que alguien
     tenga overflow. Solo 2 de los 11 modales traían un contenedor interno con
     overflow-y:auto; los otros 9 clipaban en silencio en cuanto su contenido
     pasaba de 84vh. Se arregla aquí y no en cada vista: el fallo estaba en el
     contenedor, y parchear nueve ficheros dejaría al décimo repitiéndolo. */
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* Contraste AA dentro del modal Y del bottom sheet.

     Medido en la app real con Playwright, calculando el ratio de cada texto
     contra su fondo EFECTIVO (el primer ancestro con color opaco), no contra
     blanco: dentro de un modal estos colores caen tanto sobre --surface
     (#fff) como sobre --bg (#f3faf6 — el botón × de .mhead, las .tcard) y
     sobre los tintes --brand-s / --coral-s / --teal-s / --sky-s (chips,
     .delbtn, .btn-add-passkey, .activos-nav-link). Contra ESOS fondos, y no
     contra blanco, es donde fallaban:

       --muted  #687a72  4.29:1 sobre --bg      (el × de los 10 modales)
       --brand2 #05875e  3.93:1 sobre --brand-s (chips, "Gestionar en Bolsillos")
       --coral  #d93854  4.27:1 sobre --bg / 3.73:1 sobre --coral-s (.delbtn)
       --teal   #0d9488  3.18:1 sobre --teal-s  (.btn-add-passkey)
       --sky    #0ea5e9  2.40:1 sobre --sky-s   (chip "Super Admin")
       --amber  #f59e0b  2.15:1 sobre --surface (título "PUNTUALES")
       --plum   #8b5cf6  4.00:1 sobre --bg      (etiqueta de plantilla)

     Todos por debajo del 4.5:1 que exige WCAG 2.2 AA para texto normal.

     El bottom sheet (.sheet) entra en la misma regla y no como una copia:
     comparte las mismas piezas (el × de cerrar sobre --bg, los labels en
     --muted, las pistas de formato sobre #f0f8f4) y medía lo mismo — 3.85:1
     el × y 4.08:1 cada etiqueta de campo de TODOS los formularios, que es
     donde el usuario pasa más tiempo leyendo.

     Redefinidos SOLO en este ámbito: los tokens globales de :root no se
     tocan porque los comparten pantallas de otro ámbito (login, admin,
     secciones del dashboard). Mismo tono, un punto más oscuros. Ninguno de
     estos se usa como fondo dentro de un modal o un sheet, así que
     oscurecerlos no invierte ningún par texto/fondo. */
.modal, .sheet {
  --muted:  #62746a;
  --brand2: #05764f;
  --coral:  #c52741;
  --teal:   #0d7168;
  --sky:    #0369a1;
  --amber:  #b45309;
  --plum:   #6d28d9;
}
/* La cabecera se queda fija al hacer scroll: sin esto el botón de cerrar se va
   hacia arriba y el usuario se queda dentro de un modal largo sin salida
   visible. */
.modal > .mhead {
  position: sticky; top: 0; z-index: 2;
  background: var(--surface);
}
@keyframes pop { from { transform: scale(.96); opacity: .6; } to { transform: none; opacity: 1; } }
.mhead { display: flex; align-items: center; justify-content: space-between; padding: 18px 18px 4px; }
.mhead h3 { font-size: 18px; font-weight: 740; flex: 1; text-align: center; padding-left: 44px; /* compensa el ancho del botón × para centrado óptico */ }
/* Área táctil mínima 44×44 (defecto medido: 38×38, bajo el mínimo — es el
   botón de cierre de los 10 modales, el más usado de toda la vista). */
.mhead .x { border: none; background: var(--bg); width: 44px; height: 44px; border-radius: 50%; font-size: 16px; cursor: pointer; color: var(--muted); flex-shrink: 0; }
.mtot { margin: 8px 18px 4px; background: var(--brand-s); border-radius: 14px; padding: 12px 14px; display: flex; justify-content: space-between; align-items: center; font-weight: 740; }
.mtot.red { background: var(--coral-s); }
.mtot b   { font-size: 19px; letter-spacing: -.4px; }
.mnote    { font-size: 11.5px; color: var(--muted); margin: 8px 20px 0; }
.mscroll  { overflow: auto; padding: 6px 6px 10px; }
/* Defecto real medido (audit 2026-09-03, 320-390px): en filas con icono +
   nombre + importe + 2-3 botones de acción (pasivos/activos/tarjetas), la
   suma de anchos fijos ya supera el ancho disponible ANTES de darle nada al
   nombre. Con min-width:0 flexbox no desborda: en vez de eso reduce .mb a
   0px — el nombre de la deuda/bien queda invisible, no truncado. Medido con
   getBoundingClientRect(): "Tarjeta de crédito" en m-pasivos daba .mb=0px
   a 320px con datos reales de seed.
   Fix: flex-wrap permite que el grupo de botones (.mrow-acciones) caiga a
   una 2ª línea cuando no cabe, así el nombre conserva un ancho mínimo
   legible en vez de desaparecer. En anchos donde todo cabe en una línea
   (la mayoría), el wrap nunca se activa y el layout es idéntico al actual. */
.mrow     { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; row-gap: 6px; padding: 11px 14px; border-bottom: 1px solid var(--line); }
.mrow:last-child { border-bottom: none; }
.mrow .mb { flex: 1; min-width: 72px; /* piso legible: nunca colapsa a 0px */ }
.mrow .mt { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mrow .msu { font-size: 11px; color: var(--muted); margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mrow .ma { font-size: 14px; font-weight: 700; white-space: nowrap; display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.mrow .ma.neg { color: var(--coral); }
.mrow .ma .ma-sec { font-size: 11px; font-weight: 400; opacity: .6; white-space: nowrap; }
/* Grupo de botones de acción (editar/eliminar/resumen) — si no cabe junto al
   importe, cae a su propia línea alineado a la derecha (ver .mrow arriba).
   El display/gap viven aquí y no en un style= de cada vista: con el
   `margin-left:8px` que traían en línea, el `margin-left:auto` de esta clase
   no llegaba a aplicarse nunca (el inline gana), y al caer a la segunda
   línea el grupo quedaba pegado a la izquierda, debajo del icono, en vez de
   alineado con el importe. */
.mrow-acciones { display: flex; gap: 4px; margin-left: auto; }

/* Área táctil mínima 44×44 para los controles que sólo viven dentro de un
   modal (medido con getBoundingClientRect() a 390px, con la animación `pop`
   ya terminada — antes de que acabe, el scale(.96) hace medir 42.2 donde en
   realidad hay 44):

     .item-accion (m-perfil, "sacar del hogar")   30×30  ← destructivo
     .btn-add-passkey (m-perfil)                 322×39
     .delbtn (m-perfil, "cerrar sesión")         322×43
     .activos-nav-link (m-activos)               318×40
     #form-invitar input / botón (m-perfil)      247×37 y 67×37
     input[type=file] y enviar (m-bug-report)    322×21 y 322×40

   `.item-accion` se limita con `.modal` delante porque la misma clase se usa
   en la sección de gastos, que es de otro ámbito; el círculo VISIBLE sigue
   midiendo 30px vía ::before, así que el aspecto no cambia — sólo el área
   que responde al toque. */
.modal .item-accion { position: relative; width: 44px; height: 44px; }
.modal .item-accion::before {
  content: ""; position: absolute; width: 30px; height: 30px;
  border-radius: 8px; background: transparent; transition: background .15s; z-index: 0;
}
.modal .item-accion svg { position: relative; z-index: 1; }
.modal .item-accion:hover,
.modal .item-accion.danger:hover { background: transparent; }
.modal .item-accion:hover::before { background: rgba(125,211,252,.10); }
.modal .item-accion.danger:hover::before { background: var(--coral-s); }

.modal .btn-add-passkey,
.modal .delbtn,
.modal .activos-nav-link,
#form-invitar input,
#form-invitar button,
#m-bug-report input[type="file"],
#m-bug-report #btn-bug-report-enviar { min-height: 44px; }

/* ——— FAB ——— */
.fab {
  position: fixed; bottom: 108px; right: calc(50% - 240px + 20px);
  width: 56px; height: 56px; border-radius: 18px;
  background: linear-gradient(135deg,#15803d,#065f46); color: #fff;
  border: none; display: grid; place-items: center;
  box-shadow: 0 8px 22px rgba(16,185,129,.5); cursor: pointer; z-index: 40;
}
@media (max-width: 520px) { .fab { right: 18px; } }

/* ——— Nav bottom ——— */
nav {
  position: fixed; bottom: 0; left: 50%; transform: translateX(-50%);
  width: 100%; max-width: 480px;
  background: rgba(255,255,255,.96); backdrop-filter: blur(14px);
  border-top: 1px solid var(--line); display: flex; justify-content: space-around;
  padding: 10px 2px 24px; z-index: 30;
}
nav button {
  background: none; border: none; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 4px;
  color: var(--muted); font-size: 10px;
  font-weight: 650; cursor: pointer; padding: 4px; flex: 1; transition: .15s;
  /* La barra inferior es el control más pulsado de la app y medía 38px de
     alto (33px por debajo de 420px): por debajo del mínimo táctil de 44px,
     con el dedo cayendo a medias entre dos pestañas. El ancho ya lo da
     flex:1; lo que faltaba era altura. */
  min-height: 44px;
}
nav button svg { width: 22px; height: 22px; flex-shrink: 0; }
nav button.on { color: var(--brand2); }

/* Con 6 tabs a 390px reducir SVG y texto para que quepa */
@media (max-width: 420px) {
  nav button      { font-size: 9px; padding: 3px 2px; gap: 3px; }
  nav button svg  { width: 19px; height: 19px; }
}

/* ——— Hint ——— */
.hint {
  font-size: 12px; color: var(--muted); background: #eef7f2;
  border-radius: 12px; padding: 10px 13px; margin-top: 12px;
  display: flex; align-items: center; gap: 8px;
}

/* ——— Flash messages ——— */
.flash {
  position: fixed; top: 16px; left: 50%; transform: translateX(-50%);
  min-width: 280px; max-width: 90%;
  padding: 12px 16px; border-radius: 14px; font-size: 14px; font-weight: 600;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  z-index: 100; box-shadow: 0 8px 24px rgba(0,0,0,.15);
  animation: slidedown .25s ease;
}
@keyframes slidedown { from { transform: translateX(-50%) translateY(-20px); opacity: 0; } to { transform: translateX(-50%); opacity: 1; } }
@keyframes slideInRight { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
.flash-success { background: #d7f6e6; color: #065f46; }
.flash-error   { background: var(--coral-s); color: #9f1239; }
.flash-warning { background: var(--amber-s); color: #92400e; }
.flash-info    { background: var(--sky-s); color: #0369a1; }
.flash-close   { background: none; border: none; font-size: 18px; cursor: pointer; color: inherit; opacity: .6; flex-shrink: 0; }

/* ——— Alerts inline ——— */
.alert {
  border-radius: 12px; padding: 12px 16px; font-size: 14px;
  font-weight: 600; margin-bottom: 16px;
  display: flex; align-items: center; justify-content: space-between;
}
.alert button { background: none; border: none; font-size: 18px; cursor: pointer; opacity: .6; }
.alert-success { background: #d7f6e6; color: #065f46; }
.alert-error   { background: var(--coral-s); color: #9f1239; }
.alert-warning { background: var(--amber-s); color: #92400e; }
.alert-info    { background: var(--sky-s); color: #0369a1; }

/* ——— Botones ——— */
.btn-primary {
  background: linear-gradient(135deg,#15803d,#065f46); color: #fff;
  border: none; border-radius: 14px; padding: 14px 24px;
  font-size: 15px; font-weight: 700; cursor: pointer; display: inline-block;
  box-shadow: 0 6px 16px rgba(16,185,129,.3); transition: .15s;
}
.btn-primary:hover { box-shadow: 0 8px 20px rgba(16,185,129,.45); }
.btn-primary:active { transform: scale(.97); }

.btn-outline {
  background: var(--surface); color: var(--brand2);
  border: 1.5px solid var(--line); border-radius: 14px;
  padding: 13px 22px; font-size: 14px; font-weight: 650;
  cursor: pointer; display: inline-flex; align-items: center; gap: 8px; transition: .15s;
}
.btn-outline:hover { border-color: var(--brand); }
.delbtn {
  width: 100%; border: none; background: var(--coral-s); color: var(--coral);
  font-size: 15px; font-weight: 700; padding: 13px; border-radius: 14px; cursor: pointer;
}

/* ——— Forms ——— */
.fld { margin-bottom: 14px; }
.fld label { font-size: 12px; font-weight: 700; color: var(--muted); display: block; margin-bottom: 6px; }
.fld input, .fld select, .fld textarea {
  width: 100%; border: 1.5px solid var(--line); border-radius: 13px;
  padding: 13px 14px; font-size: 16px; font-family: inherit;
  background: #f8fbf9; color: var(--ink);
}
.fld input:focus, .fld select:focus, .fld textarea:focus {
  outline: none; border-color: var(--brand);
}
/* Error de validación por campo (ver submitForm en core.js): resalta el
   input exacto que falló en vez de dejar solo un toast genérico sin decir
   cuál. */
.fld input.fld-invalid, .fld select.fld-invalid, .fld textarea.fld-invalid {
  border-color: #f43f5e;
}
/* #f43f5e (rojo de marca) sobre blanco da 3.67:1 — no llega al 4.5:1 que
   exige texto normal (12px no cuenta como "texto grande" aunque sea bold).
   #9f1239 ya es el tono que usa .alert-error/.flash-error para el mismo
   propósito (8:1 sobre blanco): reusarlo evita introducir un rojo nuevo. */
.fld-error-msg { font-size: 12px; color: #9f1239; font-weight: 600; margin-top: 5px; }

/* ——— Login page ——— */
.login-body { display: flex; align-items: center; justify-content: center; min-height: 100vh; background: var(--bg); }
.login-wrap { width: 100%; max-width: 380px; padding: 20px; }
.login-card {
  background: var(--surface); border-radius: 24px; padding: 32px 28px;
  box-shadow: 0 20px 60px rgba(20,80,50,.12);
}
.login-logo { text-align: center; margin-bottom: 28px; }
.login-logo-icon { display: flex; align-items: center; justify-content: center; margin-bottom: 12px; }
.login-title { font-size: 28px; font-weight: 800; letter-spacing: -1px; color: var(--ink); }
.login-subtitle { font-size: 13px; color: var(--muted); margin-top: 4px; }
.login-btn { width: 100%; margin-top: 8px; }
.login-passkey { margin-top: 20px; text-align: center; }
.login-passkey-divider { font-size: 12px; color: var(--muted); display: block; margin-bottom: 12px; }
.login-footer { text-align: center; color: var(--muted); font-size: 12px; margin-top: 20px; }
.fld-password { position: relative; }
.input-icon-wrap { position: relative; }
.input-icon-wrap input { padding-right: 44px; }
/* Área de toque 44x44 (antes 18x18 = solo el icono): en un input de ~45px de
   alto, un botón flush al borde derecho cabe entero dentro del padding-right
   ya reservado arriba, así que el icono queda visualmente en el mismo sitio. */
.toggle-pw {
  position: absolute; right: 0; top: 50%; transform: translateY(-50%);
  width: 44px; height: 44px;
  background: none; border: none; cursor: pointer; color: var(--muted);
  display: flex; align-items: center; justify-content: center;
}
.badge-soon {
  font-size: 9px; font-weight: 800; background: var(--brand-s); color: var(--brand2);
  padding: 2px 6px; border-radius: 6px; text-transform: uppercase; letter-spacing: .5px;
}

/* ==========================================================
   Puertas de entrada — login, registro, recuperación, reset,
   invitación y "cambiar contraseña".
   Ajustes de contraste AA acotados a estas pantallas mediante la
   clase .auth-form-page, que se pone a mano en cada vista del
   alcance. NO cuelgan de .login-body: esa clase la comparten
   también /otp, sin_hogar y las páginas de error 403/404/500, que
   pertenecen a otro lote — un override ahí las cambiaría de aspecto
   sin que nadie lo hubiera revisado.
   Tampoco tocan --muted ni .btn-primary/.btn-outline globales, que
   se usan en dashboard, admin y modales.
   Ratios medidos con Playwright a 320/390/768/1280 px.
   ========================================================== */
.auth-form-page {
  /* #6f8279 global da 4.08:1 sobre blanco y 3.85:1 sobre --bg — bajo el
     4.5:1 de texto normal. Mismo tono, ~25% más oscuro (misma familia, no
     un color nuevo): 6.43:1 sobre blanco / 6.07:1 sobre --bg. */
  --muted: #53625b;
}

/* .btn-primary es una clase compartida con 15+ vistas fuera de este alcance
   (admin, errores, otp, presupuesto). Su degradado #22c55e→#059669 con texto
   blanco da 2.28:1 en el extremo claro y 3.77:1 en el oscuro — falla 4.5:1 en
   todo el recorrido. Se recalibra SOLO dentro de las puertas de entrada:
   misma familia de verde, mismo ángulo 135deg, solo más oscuro →
   5.02:1 (#15803d) a 7.68:1 (#065f46). */
.auth-form-page .btn-primary {
  background: linear-gradient(135deg, #15803d, #065f46);
}

/* El botón de passkey y el de Google son .btn-outline, compartida con
   dashboard/admin: su color var(--brand2) #059669 da 3.77:1 sobre el blanco
   de la tarjeta. Se sobreescribe SOLO dentro de .login-passkey (que solo
   existe en login.php): #047857 = 5.48:1. */
.login-passkey .btn-outline,
.login-passkey .btn-outline svg { color: #047857; }

/* Foco visible (WCAG 2.2 SC 2.4.11 / 1.4.11).
   `.fld input:focus` global hace `outline: none` y deja como única señal el
   borde en var(--brand) #10b981: 2.54:1 contra el blanco del input y 2.16:1
   contra el borde en reposo #e6efe9 — por debajo del 3:1 exigido a un
   indicador no textual. Con el zoom de un lector de pantalla o en una
   pantalla con brillo bajo, el campo enfocado no se distingue del resto.
   Se restituye un anillo real en las puertas de entrada (#047857 = 5.48:1
   sobre blanco, 5.17:1 sobre --bg). :focus-visible, no :focus: el ratón no
   dispara el anillo, el teclado sí. */
.auth-form-page .fld input:focus-visible,
.auth-form-page .fld select:focus-visible,
.auth-form-page .fld textarea:focus-visible,
.auth-form-page a:focus-visible,
.auth-form-page button:focus-visible {
  outline: 2px solid #047857;
  outline-offset: 2px;
}

/* ——— OTP page ——— */
.otp-info {
  font-size: 14px; color: var(--muted); text-align: center;
  margin: 0 0 20px; line-height: 1.5;
}
.otp-input {
  text-align: center; font-size: 28px; font-weight: 700;
  letter-spacing: 8px; font-variant-numeric: tabular-nums;
}
.btn-link {
  background: none; border: none; color: var(--brand); font-size: 13px;
  cursor: pointer; text-decoration: underline; padding: 0;
}
.btn-link:disabled { color: var(--muted); cursor: not-allowed; text-decoration: none; }

/* ——— Badge ——— */
.badge {
  font-size: 10px; font-weight: 800; width: 19px; height: 19px;
  border-radius: 50%; display: inline-grid; place-items: center; color: #fff; flex-shrink: 0;
}

/* ——— Boton pequeño ——— */
.btn-sm {
  background: var(--brand-s); color: var(--brand2);
  border: none; border-radius: 9px; padding: 5px 12px;
  font-size: 12px; font-weight: 700; cursor: pointer; transition: .12s;
}
/* var(--brand) con texto blanco da 2.54:1; el mismo verde un escalón más
   oscuro, 5.02:1. */
.btn-sm:hover { background: #15803d; color: #fff; }

/* ——— Botón grande (checklist) ——— */
.bigbtn {
  width: 100%; background: linear-gradient(135deg,#15803d,#065f46); color: #fff;
  border: none; border-radius: 14px; padding: 14px;
  font-size: 15px; font-weight: 700; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  margin-top: 8px; box-shadow: 0 6px 16px rgba(16,185,129,.3);
}

/* ——— Gastos: grp header ——— */
.grp {
  font-size: 12px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .6px;
  padding: 16px 6px 8px;
  display: flex; justify-content: space-between; align-items: center;
}
.tot { color: var(--ink); font-size: 13px; text-transform: none; letter-spacing: 0; font-weight: 740; }
.eqnote { font-size: 11px; color: var(--muted); font-weight: 500; }

/* ——— Acciones en filas ——— */
.row-actions {
  display: flex; gap: 4px; margin-left: 8px; flex-shrink: 0;
}
/* Área táctil mínima 44×44 (defecto medido: 28×28, y en pasivos hay hasta 3
   pegados uno junto al otro — "editar" al lado de "eliminar", que es
   destructivo). El botón crece a 44×44 pero el círculo VISIBLE sigue siendo
   de 28px vía ::before, así el aspecto no cambia — solo el área que
   responde al toque. */
.icon-btn {
  position: relative;
  width: 44px; height: 44px; border: none; background: transparent;
  border-radius: 8px; display: grid; place-items: center;
  cursor: pointer; color: var(--muted); transition: .12s;
}
.icon-btn::before {
  content: ""; position: absolute; width: 28px; height: 28px;
  background: var(--bg); border-radius: 8px; transition: inherit; z-index: 0;
}
.icon-btn svg { position: relative; z-index: 1; }
.icon-btn:hover::before { background: var(--line); }
.icon-btn:hover { color: var(--ink); }
.icon-btn.danger:hover::before { background: var(--coral-s); }
.icon-btn.danger:hover { color: var(--coral); }

/* ——— Botones iconos sobre bolsillos ——— */
.icon-btn-inv {
  width: 26px; height: 26px; border: none;
  background: rgba(255,255,255,.22); border-radius: 7px;
  display: grid; place-items: center; cursor: pointer; transition: .12s;
}
.icon-btn-inv:hover { background: rgba(255,255,255,.4); }
.icon-btn-inv.danger-inv:hover { background: rgba(244,63,94,.5); }

/* ——— Modales madd footer ——— */
.madd {
  border-top: 1px solid var(--line); padding: 14px 18px;
  font-size: 14px; font-weight: 700; color: var(--brand2);
  cursor: pointer; text-align: center;
  border-bottom-left-radius: 24px; border-bottom-right-radius: 24px;
}
.madd:hover { background: var(--brand-s); }

/* ——— Futuro ——— */
.fcard { background: var(--surface); border-radius: 18px; padding: 16px; box-shadow: var(--shadow); margin-bottom: 12px; }
.ftitle { font-size: 13px; color: var(--muted); margin-bottom: 12px; }
.frow { display: flex; align-items: center; gap: 12px; }
.fl { flex: 1; }
.fmeta { font-size: 11px; color: var(--muted); margin-top: 2px; }
.fbar { height: 5px; background: var(--line); border-radius: 5px; margin-top: 6px; overflow: hidden; }
.fbar i { display: block; height: 100%; border-radius: 6px; }
.ftag { font-size: 10px; font-weight: 800; background: var(--coral-s); color: var(--coral); padding: 2px 7px; border-radius: 6px; margin-left: 4px; }
.ftag.g { background: var(--brand-s); color: var(--brand2); }

/* ——— Futuro hero proyeccion ——— */
.scoremini {
  background: linear-gradient(135deg,#06231c,#0a3a2e);
  border-radius: 18px; padding: 16px; display: flex; gap: 14px;
  align-items: center; cursor: pointer; margin-top: 4px; color: #fff;
  box-shadow: 0 8px 20px rgba(6,35,28,.3);
}
.scoremini .si { flex: 1; }
.scoremini .sl { font-size: 11px; opacity: .7; }
.scoremini .sv { font-size: 22px; font-weight: 780; color: #34d399; letter-spacing: -.5px; margin-top: 2px; }
.scoremini .sd { font-size: 11px; opacity: .8; margin-top: 2px; }

/* ——— Chips de anos en futuro ——— */
.ychip {
  background: rgba(255,255,255,.15); color: rgba(255,255,255,.8);
  border: none; border-radius: 9px; padding: 6px 12px;
  font-size: 12px; font-weight: 650; cursor: pointer; transition: .15s;
}
.ychip.on { background: rgba(255,255,255,.9); color: #06231c; }

/* ——— Filter tabs ——— */
.filter {
  display: flex; gap: 6px; background: var(--line); border-radius: 12px; padding: 4px;
}
.filter button {
  flex: 1; background: none; border: none; border-radius: 9px; padding: 8px;
  font-size: 13px; font-weight: 650; cursor: pointer; color: var(--muted); transition: .15s;
}
.filter button.on { background: var(--surface); color: var(--ink); box-shadow: var(--shadow); }

/* ——— Drawer (formularios CRUD) ——— */
.scrim {
  position: fixed; inset: 0; background: rgba(19,36,28,.45);
  z-index: 50; display: none;
}
.scrim.open { display: block; }
.drawer {
  position: fixed; bottom: 0; left: 50%; transform: translateX(-50%) translateY(100%);
  width: 100%; max-width: 480px;
  background: var(--surface); border-radius: 24px 24px 0 0;
  box-shadow: 0 -8px 40px rgba(0,0,0,.18);
  z-index: 51; transition: transform .3s cubic-bezier(.25,.8,.25,1);
  display: flex; flex-direction: column; max-height: 88vh;
  padding-bottom: env(safe-area-inset-bottom, 0);
}
.drawer.open { transform: translateX(-50%) translateY(0); }
.drawer-handle { width: 40px; height: 4px; background: var(--line); border-radius: 2px; margin: 12px auto 0; flex-shrink: 0; }
.drawer-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 18px 10px; flex-shrink: 0; }
.drawer-head h3 { font-size: 17px; font-weight: 740; }

/* ——— Responsive ——— */
@media (min-width: 640px) {
  .app { box-shadow: 0 0 0 1px var(--line); margin-top: 20px; border-radius: 24px; min-height: auto; }
}

/* ================================================================
   Banner de impersonación — Modo admin soporte
   Visible en TODAS las vistas cuando super_admin impersona un hogar.
   Diseñado para ser imposible de ignorar.
   ================================================================ */
.imp-banner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 9999;
  background: #1c3a4a;
  color: #e0f2fe;
  border-bottom: 3px solid #0ea5e9;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
  box-shadow: 0 2px 12px rgba(0,0,0,.3);
}

/* Modo edicion activa — color más alarmante */
.imp-banner--edit {
  background: #3b1a1a;
  border-bottom-color: #f43f5e;
  color: #fecdd3;
}
.imp-banner--edit .imp-banner__mode {
  color: #f87171;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .04em;
}

.imp-banner__inner {
  max-width: 860px;
  margin: 0 auto;
  padding: 8px 14px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.imp-banner__icon {
  flex-shrink: 0;
  opacity: .85;
}

.imp-banner__text {
  flex: 1;
  min-width: 0;
}

.imp-banner__mode {
  font-style: italic;
  opacity: .85;
}

.imp-banner__actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
  flex-wrap: wrap;
  width: 100%; /* en mobile ocupa fila propia */
}

.imp-btn {
  border: none;
  border-radius: 8px;
  cursor: pointer;
  font-size: 12px;
  font-weight: 700;
  padding: 8px 14px;
  transition: opacity .15s;
  min-height: 36px;
  flex: 1; /* en mobile cada botón se expande */
  white-space: nowrap;
}
.imp-btn:hover { opacity: .82; }

.imp-btn--edit {
  background: #0ea5e9;
  color: #fff;
}
.imp-btn--readonly {
  background: rgba(255,255,255,.15);
  color: #e0f2fe;
}
.imp-btn--exit {
  background: #f43f5e;
  color: #fff;
}

/* Cuando hay banner, empujar el contenido principal hacia abajo.
   En mobile el banner puede ocupar ~80px (wrappea). */
body.has-imp-banner .app,
body.has-imp-banner .admin-body .admin-main {
  margin-top: 80px;
}
body.has-imp-banner .admin-nav {
  top: 80px;
}
body.has-imp-banner .admin-nav-drawer {
  top: calc(80px + 52px); /* banner + nav */
}

/* Desktop: banner más compacto */
@media (min-width: 700px) {
  .imp-banner__actions {
    width: auto;
  }
  .imp-btn {
    flex: none;
  }
  body.has-imp-banner .app,
  body.has-imp-banner .admin-body .admin-main {
    margin-top: 52px;
  }
  body.has-imp-banner .admin-nav {
    top: 52px;
  }
  body.has-imp-banner .admin-nav-drawer {
    top: calc(52px + 60px);
  }
}

/* ──────────────────────────────────────────────────────────────
   Bolsillo con propósito — migración 010
   Barra de progreso enriquecida + coaching inline
   ────────────────────────────────────────────────────────────── */

/* Motivo del bolsillo */
.pocket .pmotivo {
  font-size: 10.5px;
  opacity: .78;
  margin-top: 2px;
  position: relative;
  font-style: italic;
}

/* Barra de progreso con propósito (reemplaza .pb cuando hay meta) */
.pocket .pb-proposito {
  margin-top: 9px;
  position: relative;
}

.pocket .pb-bar {
  height: 5px;
  border-radius: 5px;
  background: rgba(255,255,255,.28);
  overflow: hidden;
}

.pocket .pb-fill {
  height: 100%;
  background: #fff;
  border-radius: 6px;
  transition: width .4s ease;
}

.pocket .pb-info {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 4px;
  font-size: 10.5px;
  opacity: .9;
  flex-wrap: wrap;
}

.pocket .pb-pct  { font-weight: 700; }
.pocket .pb-meta { opacity: .85; }
.pocket .pb-faltante { opacity: .8; }

/* Coaching inline: aporte sugerido + frase */
.pocket .pcoach {
  margin-top: 8px;
  padding: 7px 10px;
  background: rgba(255,255,255,.15);
  border-radius: 9px;
  position: relative;
}

.pocket .pcoach-amt {
  font-size: 13px;
  font-weight: 760;
  letter-spacing: -.3px;
}

.pocket .pcoach-fecha {
  font-size: 10.5px;
  opacity: .8;
  margin-left: 2px;
}

.pocket .pcoach-frase {
  font-size: 10.5px;
  opacity: .85;
  margin-top: 3px;
  font-style: italic;
  line-height: 1.4;
}

/* ── F-A: barra dual de contribuciones por miembro ──────────── */
.pb-contribs {
  margin-top: 6px;
  border-radius: 4px;
  overflow: hidden;
  position: relative;
  height: 6px;
  display: flex;
}
.pb-contrib-bar {
  height: 100%;
  transition: width .3s;
}
.pb-contrib-labels {
  position: absolute;
  bottom: -16px;
  left: 0;
  right: 0;
  display: flex;
  justify-content: space-between;
  font-size: 9.5px;
  font-weight: 700;
  color: #fff;
  letter-spacing: .03em;
}

/* ── NLM-26: badge inicial usuario en movimientos ────────────── */
.mv-usr-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--brand2);
  color: #fff;
  font-size: 9px;
  font-weight: 700;
  flex-shrink: 0;
  vertical-align: middle;
}

/* ── NLM-04: indicador Morgan Housel ─────────────────────────── */
.nlm04-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-radius: 10px;
  font-size: 13px;
  margin: 12px 0 4px;
}
.nlm04-bar.ok   { background: #f0fdf4; color: #166534; }
/* #dc2626 sobre #fef2f2 daba 4.41:1 — se quedaba a un pelo del 4.5:1 de AA
   justo en la barra que avisa de déficit, el mensaje que más importa que se
   lea. #b91c1c (red-700) sube a 5.91:1 con el mismo rojo de alarma. */
.nlm04-bar.over { background: #fef2f2; color: #b91c1c; }
.nlm04-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.nlm04-bar.ok   .nlm04-dot { background: #22c55e; }
.nlm04-bar.over .nlm04-dot { background: #ef4444; }

/* ── NLM-24: sesión financiera mensual de pareja ─────────────── */
.sesion-fin-card {
  background: #f0fdf4;
  border: 1px solid #bbf7d0;
  border-radius: 14px;
  overflow: hidden;
  margin-top: 10px;
}
.sesion-fin-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 16px 10px;
  font-size: 13px;
  font-weight: 600;
  color: #166534;
}
.sesion-fin-reset {
  margin-left: auto;
  background: none;
  border: none;
  font-size: 16px;
  cursor: pointer;
  color: #6ee7b7;
  line-height: 1;
  padding: 0 2px;
}
.sesion-fin-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 16px;
  border-top: 1px solid #d1fae5;
  cursor: pointer;
  transition: background .12s;
}
.sesion-fin-item:active { background: #dcfce7; }
.sesion-fin-item.done .sesion-fin-label { color: var(--muted); text-decoration: line-through; }
.sesion-fin-check {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid #86efac;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background .15s, border-color .15s;
  color: transparent;
}
.sesion-fin-item.done .sesion-fin-check {
  background: #059669;
  border-color: #059669;
  color: #fff;
}
.sesion-fin-label {
  font-size: 13.5px;
  color: #14532d;
  line-height: 1.4;
}
.sesion-fin-footer {
  padding: 0 16px 14px;
  font-size: 12px;
  color: #166534;
  font-weight: 600;
  min-height: 0;
}

/* F-C: Timeline de metas */
.fc-timeline {
  background: var(--card-bg, #fff);
  border: 1px solid var(--border, #e5e7eb);
  border-radius: 12px;
  padding: 16px 18px 10px;
  margin-bottom: 16px;
}
.fc-axis { display: flex; flex-direction: column; gap: 14px; }
.fc-axis-line { display: none; }
.fc-meta-row { display: flex; flex-direction: column; gap: 4px; }
.fc-meta-label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}
.fc-meta-nombre {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text, #111);
}
.fc-meta-fecha {
  font-size: 11.5px;
  color: var(--muted, #6b7280);
}
.fc-meta-track {
  position: relative;
  height: 8px;
  background: #f3f4f6;
  border-radius: 4px;
  overflow: visible;
}
.fc-meta-fill {
  position: absolute;
  left: 0; top: 0;
  height: 100%;
  border-radius: 4px;
  transition: width .3s;
}
.fc-meta-dot {
  position: absolute;
  top: -4px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px rgba(0,0,0,.12);
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
}
.fc-meta-pct {
  position: absolute;
  top: -18px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 10px;
  font-weight: 700;
  white-space: nowrap;
  color: var(--text, #111);
}
.fc-meta-aporte {
  font-size: 11.5px;
  color: var(--muted, #6b7280);
  text-align: right;
}

/* F-B: Liquidación mensual */
.fb-card {
  background: #f0fdf4;
  border: 1px solid #bbf7d0;
  border-radius: 12px;
  padding: 14px 16px 12px;
  margin-top: 12px;
}
.fb-header {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13.5px;
  font-weight: 700;
  color: #14532d;
  margin-bottom: 3px;
}
.fb-sub {
  font-size: 12.5px;
  color: #166534;
  margin-bottom: 10px;
}
.fb-list { display: flex; flex-direction: column; gap: 5px; margin-bottom: 10px; }
.fb-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 13px;
  color: #15803d;
}
.fb-nombre { font-weight: 500; }
.fb-aporte { font-weight: 700; color: #166534; }
.fb-alerta {
  font-size: 11.5px;
  color: #92400e;
  background: #fffbeb;
  border: 1px solid #fde68a;
  border-radius: 6px;
  padding: 5px 8px;
  margin-top: 4px;
}
.fb-btn {
  width: 100%;
  padding: 9px;
  background: #15803d;
  color: #fff;
  border: none;
  border-radius: 8px;
  font-size: 13.5px;
  font-weight: 700;
  cursor: pointer;
  transition: background .15s;
}
/* El verde claro daba 2.28:1 con el texto blanco: el botón se leía a medias.
   Mismo verde, dos escalones más oscuro (5.02:1); el hover, uno más. */
.fb-btn:hover { background: #166534; }

/* ===================================================================
   TOUR GUIADO — Colkee onboarding
   Sin emojis. Celeste #7DD3FC + near-black #0d1117 (brand Linit).
   z-index: overlay 9000 | ring 9001 | tooltip 9100 | toast 9200
   =================================================================== */

/* ── Overlay (4 rectángulos oscuros alrededor del elemento) ───────── */
.tour-overlay-piece {
  position: fixed;
  background: rgba(0, 0, 0, 0.76);
  z-index: 9000;
  pointer-events: all;
}

/* ── Anillo de resalte celeste ────────────────────────────────────── */
.tour-ring {
  position: fixed;
  border: 2.5px solid #7DD3FC;
  border-radius: 14px;
  z-index: 9001;
  pointer-events: none;
  box-shadow: 0 0 0 3px rgba(125, 211, 252, 0.18),
              0 0 28px rgba(125, 211, 252, 0.32);
  animation: tour-pulse 2.2s ease-in-out infinite;
}
@keyframes tour-pulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(125,211,252,.18), 0 0 28px rgba(125,211,252,.32); }
  50%       { box-shadow: 0 0 0 5px rgba(125,211,252,.28), 0 0 40px rgba(125,211,252,.48); }
}

/* ── Tooltip principal ────────────────────────────────────────────── */
.tour-tooltip {
  position: fixed;
  z-index: 9100;
  max-width: calc(100vw - 32px);
  background: #0d1117;
  border: 1.5px solid #7DD3FC;
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.55), 0 2px 8px rgba(0, 0, 0, 0.3);
  display: none;
  will-change: opacity, transform;
}

/* ── Flecha del tooltip ───────────────────────────────────────────── */
.tour-arrow {
  position: absolute;
  width: 0;
  height: 0;
  overflow: visible;
}

/* Tooltip DEBAJO del elemento → flecha apunta ARRIBA (borde superior) */
.tour-tt-below .tour-arrow {
  top: -9px;
}
.tour-tt-below .tour-arrow::before,
.tour-tt-below .tour-arrow::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  border-style: solid;
}
.tour-tt-below .tour-arrow::before {
  border-width: 0 9px 9px 9px;
  border-color: transparent transparent #7DD3FC transparent;
}
.tour-tt-below .tour-arrow::after {
  top: 2.5px;
  left: 1.5px;
  border-width: 0 7.5px 7.5px 7.5px;
  border-color: transparent transparent #0d1117 transparent;
}

/* Tooltip ENCIMA del elemento → flecha apunta ABAJO (borde inferior) */
.tour-tt-above .tour-arrow {
  top: 100%;
}
.tour-tt-above .tour-arrow::before,
.tour-tt-above .tour-arrow::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  border-style: solid;
}
.tour-tt-above .tour-arrow::before {
  border-width: 9px 9px 0 9px;
  border-color: #7DD3FC transparent transparent transparent;
}
.tour-tt-above .tour-arrow::after {
  top: 0;
  left: 1.5px;
  border-width: 7.5px 7.5px 0 7.5px;
  border-color: #0d1117 transparent transparent transparent;
}

/* ── Contenido interno ────────────────────────────────────────────── */
.tour-inner {
  padding: 18px 16px 14px;
}

.tour-count {
  font-size: 11px;
  font-weight: 700;
  color: #7DD3FC;
  letter-spacing: 0.4px;
  margin-bottom: 6px;
  text-transform: uppercase;
}

.tour-title {
  font-size: 15px;
  font-weight: 720;
  color: #f1f5f9;
  margin: 0 0 8px;
  line-height: 1.3;
}

.tour-desc {
  font-size: 13.5px;
  color: #94a3b8;
  line-height: 1.55;
  margin: 0 0 16px;
}

/* ── Acciones del tooltip ─────────────────────────────────────────── */
.tour-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.tour-navbtns {
  display: flex;
  gap: 8px;
}

.tour-skip {
  font-size: 12px;
  font-weight: 500;
  color: #4e657a;
  background: none;
  border: none;
  cursor: pointer;
  padding: 2px 0;
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color .15s;
  white-space: nowrap;
}
.tour-skip:hover { color: #7DD3FC; }

.tour-prev {
  padding: 8px 14px;
  font-size: 12.5px;
  font-weight: 650;
  background: transparent;
  border: 1.5px solid #7DD3FC;
  color: #7DD3FC;
  border-radius: 7px;
  cursor: pointer;
  transition: background .15s;
  white-space: nowrap;
}
.tour-prev:hover { background: rgba(125, 211, 252, 0.1); }

.tour-next {
  padding: 8px 18px;
  font-size: 13px;
  font-weight: 720;
  background: #7DD3FC;
  color: #0d1117;
  border: none;
  border-radius: 7px;
  cursor: pointer;
  transition: background .15s, transform .1s;
  white-space: nowrap;
}
.tour-next:hover  { background: #93dcfa; }
.tour-next:active { transform: scale(0.97); }

/* Focus visible accesible en los botones del tour */
.tour-next:focus-visible,
.tour-prev:focus-visible,
.tour-skip:focus-visible {
  outline: 2px solid #7DD3FC;
  outline-offset: 3px;
}

/* ── Botón "Guía" en el nav ───────────────────────────────────────── */
/* Hereda estilos de nav button (flex-col, gap, font-size, cursor) */
#tour-help-btn { transition: color .15s; }
#tour-help-btn:hover       { color: #7DD3FC; }
#tour-help-btn:focus-visible {
  outline: 2px solid #7DD3FC;
  outline-offset: 2px;
  border-radius: 6px;
}

/* ── Toast de bienvenida al finalizar ─────────────────────────────── */
.tour-welcome {
  position: fixed;
  bottom: 110px;
  left: 50%;
  transform: translateX(-50%) translateY(18px);
  z-index: 9200;
  opacity: 0;
  transition: opacity .3s ease, transform .3s cubic-bezier(.16, 1, .3, 1);
  pointer-events: none;
  width: min(340px, calc(100vw - 40px));
  /* Visual — los hijos son flex items directos */
  display: flex;
  align-items: center;
  gap: 12px;
  background: #0d1117;
  border: 1.5px solid #7DD3FC;
  border-radius: 12px;
  padding: 14px 16px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
}
.tour-welcome-in {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: all;
}
.tour-welcome-txt {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.tour-welcome-txt strong {
  font-size: 13.5px;
  font-weight: 720;
  color: #f1f5f9;
}
.tour-welcome-txt span {
  font-size: 12px;
  color: #64748b;
}
.tour-welcome-x {
  background: none;
  border: none;
  cursor: pointer;
  color: #4e657a;
  padding: 4px;
  display: grid;
  place-items: center;
  border-radius: 5px;
  flex-shrink: 0;
  transition: color .15s;
}
.tour-welcome-x:hover { color: #94a3b8; }
.tour-welcome-x:focus-visible {
  outline: 2px solid #7DD3FC;
  outline-offset: 2px;
}

/* ── Mobile: ajuste en pantallas muy pequeñas (<380px) ───────────── */
@media (max-width: 380px) {
  .tour-inner  { padding: 14px 12px 12px; }
  .tour-title  { font-size: 14px; }
  .tour-desc   { font-size: 13px; }
  .tour-next   { padding: 8px 13px; font-size: 12.5px; }
  .tour-prev   { padding: 8px 10px; font-size: 12px; }
}

/* Modal score — variables breakdown */
.ms-var {
  padding: 12px 18px 10px;
  border-top: 1px solid var(--border, #e5e7eb);
}
.ms-var:first-child { border-top: none; }
.ms-var-head {
  display: flex;
  justify-content: space-between;
  /* Nombre y valor son una línea cada uno desde que el modal se simplificó
     (ya no hay pregunta debajo del nombre): centrados se leen mejor. */
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
}
.ms-var-nombre {
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text, #111);
  margin-bottom: 2px;
}
.ms-var-sub {
  font-size: 11.5px;
  color: var(--muted, #6b7280);
  line-height: 1.4;
}
.ms-var-val {
  font-size: 15px;
  font-weight: 800;
  white-space: nowrap;
  flex-shrink: 0;
}
.ms-bar-bg {
  height: 6px;
  background: #f3f4f6;
  border-radius: 3px;
  overflow: hidden;
  margin-bottom: 4px;
}
.ms-bar-fill {
  height: 100%;
  border-radius: 3px;
  transition: width .4s;
}
.ms-var-pts {
  font-size: 11px;
  color: var(--muted, #6b7280);
}
.ms-tip {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin-top: 6px;
  font-size: 11.5px;
  color: #64748b;
  background: rgba(100,116,139,.07);
  border-left: 2px solid #94a3b8;
  border-radius: 0 4px 4px 0;
  padding: 5px 8px;
  line-height: 1.45;
}
.ms-tip.warn {
  color: #92400e;
  background: rgba(245,158,11,.07);
  border-left-color: #f59e0b;
}
.ms-tip.crit {
  color: #9f1239;
  background: rgba(244,63,94,.07);
  border-left-color: #f43f5e;
}
.ms-tip-icon { flex-shrink: 0; margin-top: 1px; }

/* ——— Reconciliación de excedente mensual ——— */
.reconciliacion-cat-btn {
  width: 100%; text-align: left; background: var(--surface); color: var(--ink);
  border: 1.5px solid var(--line); border-radius: 12px; padding: 12px 14px;
  font-size: 13.5px; font-weight: 600; cursor: pointer; transition: .15s;
}
.reconciliacion-cat-btn:hover { border-color: var(--brand2); }
.reconciliacion-cat-btn.sel { border-color: var(--brand2); background: var(--brand-s); color: var(--brand2); }

/* ——— Ocultar saldos (Daniel, CEO, 2026-08-11) ———
   Cubre los displays de dinero MÁS visibles (hero patrimonio, KPIs de Hoy,
   saldo de bolsillos, filas de gastos/ingresos/movimientos). No es 100%
   exhaustivo — hay montos generados por JS con estilos inline en popups
   puntuales (ej. resumen de un pasivo) que no pasan por estas clases; cubrir
   eso requeriría tocar cada template JS individualmente, desproporcionado
   para una feature de "que no vea el saldo quien mira por encima del
   hombro" — el objetivo es la vista normal del dashboard, no cada popup. */
html.saldos-ocultos .amt,
html.saldos-ocultos .big,
html.saldos-ocultos .hv,
html.saldos-ocultos .ev,
html.saldos-ocultos .pv,
html.saldos-ocultos .ma,
html.saldos-ocultos .tv,
html.saldos-ocultos .sim-big,
html.saldos-ocultos .pocket-subitem-valor,
html.saldos-ocultos .coach-meta-saldo,
html.saldos-ocultos .coach-meta-meta,
html.saldos-ocultos .coach-meta-aporte,
html.saldos-ocultos .div-clase-monto,
html.saldos-ocultos .div-horizonte-total,
html.saldos-ocultos .insight-dato-val,
html.saldos-ocultos .fb-aporte,
html.saldos-ocultos .pcoach-amt {
  color: transparent !important;
  position: relative;
}
html.saldos-ocultos .amt::after,
html.saldos-ocultos .big::after,
html.saldos-ocultos .hv::after,
html.saldos-ocultos .ev::after,
html.saldos-ocultos .pv::after,
html.saldos-ocultos .ma::after,
html.saldos-ocultos .tv::after,
html.saldos-ocultos .sim-big::after,
html.saldos-ocultos .pocket-subitem-valor::after,
html.saldos-ocultos .coach-meta-saldo::after,
html.saldos-ocultos .coach-meta-meta::after,
html.saldos-ocultos .coach-meta-aporte::after,
html.saldos-ocultos .div-clase-monto::after,
html.saldos-ocultos .div-horizonte-total::after,
html.saldos-ocultos .insight-dato-val::after,
html.saldos-ocultos .fb-aporte::after,
html.saldos-ocultos .pcoach-amt::after {
  content: "••••";
  position: absolute;
  inset: 0;
  color: var(--ink);
  letter-spacing: 2px;
  display: flex;
  align-items: center;
}
/* Iconos discretos del header (ojo de saldos, reportar problema). Vivían con
   width/height:32px en el atributo style del propio <button> en _header.php:
   32x32 es un blanco táctil demasiado pequeño (mínimo 44px) y, al estar
   inline, ninguna hoja de estilos podía corregirlo. El círculo VISIBLE sigue
   siendo de 32px — lo pinta el :hover sobre el área interior — pero la caja
   pulsable llega a 44x44 y los márgenes negativos absorben los 12px extra
   para que el header no se ensanche ni se separe de los avatares. */
.btn-privacy {
  width: 44px; height: 44px;
  margin: -6px -6px -6px -6px;
  border-radius: 50%; border: none; background: transparent;
  cursor: pointer; padding: 0; color: var(--muted);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.btn-privacy:hover { color: var(--brand2); }

/* ==========================================================
   FOCO VISIBLE — capa final, a propósito
   ==========================================================
   La app no tenía indicador de foco propio: solo tres reglas sueltas (las
   del tour y .item-accion). Todo lo demás quedaba en manos del anillo por
   defecto del navegador, que sobre estas tarjetas redondeadas y de bajo
   contraste apenas se distingue — y en los controles con `border: none`
   (la nav inferior, .fab, .btn-privacy, .icon-btn: casi todos los botones
   de aquí) no se ve en absoluto. Quien navega con teclado o con un lector
   de pantalla no sabía qué iba a activar al pulsar Enter.

   Va al FINAL del archivo por orden de cascada, no por descuido: hay
   reglas anteriores que apagan el contorno (`.fld input:focus { outline:
   none }`, `.sim-input:focus` en dashboard.css) con la misma especificidad;
   si esta capa fuera antes, la ganarían y el foco volvería a ser invisible
   justo en los formularios.

   :focus-visible y no :focus — el anillo aparece al navegar con teclado y
   no al hacer clic con el ratón. Color --brand2, que ya cumple AA (5.48:1
   sobre blanco) y de paso es la marca. Global a propósito: cualquier
   control que se añada mañana lo hereda sin acordarse de nada. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible,
[role="button"]:focus-visible {
  outline: 3px solid var(--brand2);
  outline-offset: 2px;
}

/* Sobre superficies oscuras el verde de marca se pierde contra el fondo:
   ahí el anillo se pinta en blanco. */
.hero :focus-visible,
.htile.dark :focus-visible,
.tile-dark :focus-visible {
  outline-color: #ffffff;
}
