/* ================================================================
   FONDEO LEDGER — hoja de estilos
   ================================================================
   Dirección de diseño: "libro de cuentas / cuaderno de bitácora de
   trading", no un dashboard SaaS genérico. Tinta casi negra en vez
   de gris-azulado plano, un serif con carácter para titulares
   (Fraunces) en vez del palo-seco que usa cualquier app, y latón
   (brass) como color de firma en vez de un dorado plano — es la
   misma familia de "dinero/logro" que ya tenías, pero más metálico y
   menos genérico. El elemento firma es el SELLO: los badges de
   estado (activa/quemada/pendiente) llevan un pequeño giro y un
   anillo, como un sello estampado sobre un libro de cuentas, en vez
   de una píldora plana como en cualquier admin panel.

   IMPORTANTE PARA QUIEN TOQUE ESTO: los nombres de clase/ID de aquí
   abajo son EXACTAMENTE los mismos que usa app.js e index.html. No
   renombres selectores sin buscar también sus usos en app.js. Los
   colores viven en las variables de :root — para retocar la paleta,
   cambia solo ahí arriba.
   ================================================================ */

:root{
  /* Igual que env(safe-area-inset-top), pero con un mínimo garantizado:
     esa variable del sistema solo reserva hueco cuando detecta una
     muesca/isla física — en bastantes Android (y algún iPhone) devuelve
     0px aunque la barra de estado siga ocupando sitio, y entonces
     cualquier calc(Npx + env(...)) se queda corto y el título/botón
     choca con la hora/batería. Con max(), si el sistema no avisa de
     nada, se usa igualmente este suelo de 24px en vez de 0. Usar SIEMPRE
     esta variable (no env(safe-area-inset-top) directo) en cualquier
     padding/top nuevo que toque el borde superior de la pantalla. */
  --safe-top:max(env(safe-area-inset-top), 24px);
  /* Tinta (fondos) — casi negro, con un pelín de azul frío, no gris plano */
  --bg:#0b0e15;
  --bg-2:#070911;
  --panel:#12161f;
  --panel-2:#181d29;
  --line:#262c3b;
  --line-soft:#1d2230;

  --text:#e9ecf3;
  --muted:#8b93a6;
  --muted-2:#6b7690; /* antes #5c6478 — subido un pelín de luz para que las labels en mayúscula (10-11px) no queden por debajo de contraste legible sobre --panel-2 */

  /* Easing "caro": arranque rápido, freno suave — para hovers/transform,
     en vez del ease-lineal-de-fábrica que usa cualquier panel */
  --ease:cubic-bezier(.16,1,.3,1);

  /* Latón (firma de marca — sustituye al "gold" plano) */
  --gold:#c9a24e;
  --gold-dim:#3f331c;
  --gold-light:#f0d38f; /* tono claro del latón, usado en degradados de marca */
  --gold-dark:#8a6a2c;  /* tono oscuro del mismo degradado */
  --on-gold:#221a08;    /* texto oscuro legible sobre fondos dorados (btn.gold, pills activas...) */

  --gain:#3ecf8e;
  --gain-dim:#173b2c;
  --gain-bright:#59e0a8; /* verde más vivo, solo para el extremo de degradados de progreso */
  --gain-text:#adf0cf;   /* texto verde claro sobre fondos --gain-dim (auth-msg.ok, pill.on) */
  --on-gain-bright:#0b1f16; /* texto oscuro sobre celdas de calendario muy verdes (fcal-lvl3/4) */
  --loss:#e2584f;
  --loss-dim:#3d201e;
  --loss-text:#ffb3ae;   /* texto rojo claro sobre fondos --loss-dim (auth-msg.err) */

  /* Degradados que se repetían literalmente en más de una regla */
  --grad-brand:linear-gradient(135deg, var(--gold-light), var(--gold) 55%, var(--gold-dark));
  --grad-gain:linear-gradient(90deg, var(--gain), var(--gain-bright));

  /* Azul-acero: acento de información/enlaces, distinto del latón */
  --accent:#6f8fe8;

  /* Sombras — antes cada componente inventaba su propia rgba a ojo;
     ahora las que eran (casi) iguales comparten token */
  --shadow-resting:0 1px 3px rgba(0,0,0,0.35);      /* tarjetas en reposo: acc-card, meta-row, chart-card */
  --shadow-hover:0 8px 18px rgba(0,0,0,0.4);        /* hover de elevación media: stat-card, meta-row */
  --shadow-hover-lg:0 14px 28px rgba(0,0,0,0.42);   /* hover de elevación grande: acc-card */
  --shadow-dropdown:0 8px 24px rgba(0,0,0,0.35);    /* listas flotantes: admin-suggest-list */
  --shadow-panel-float:0 10px 24px rgba(0,0,0,0.4); /* paneles flotantes puntuales */
  --shadow-modal:0 24px 60px rgba(0,0,0,0.45);      /* overlays grandes: modal, auth-card */

  /* Duraciones — antes mezcladas (.12/.15/.2/.25s) sin un criterio claro */
  --dur-fast:.12s;   /* micro-feedback: active/press */
  --dur-base:.15s;   /* color/borde en hover normal */
  --dur-med:.2s;     /* transform/elevación estándar */
  --dur-slow:.25s;   /* transform/elevación que quiere notarse más (acc-card) */

  --radius:10px;
  --font-display:'Fraunces', serif;
  --font-body:'Inter', sans-serif;
  --font-mono:'IBM Plex Mono', monospace;
}

/* ================================================================
   TEMA CLARO (Roadmap #14, 30/07/26) — "papel de cuentas" a la luz
   del día en vez de tinta. Mismas variables de :root, mismos nombres
   de familia de color (gold/gain/loss), solo con los valores
   invertidos para contraste sobre fondo claro. Se activa poniendo
   la clase .theme-light en <body> (ver toggleTheme() en index.html,
   junto al toggle del sidebar/topbar del gestor) y se recuerda en
   localStorage (fl_theme). Nada de esto toca la lógica de negocio —
   es solo la hoja de estilos, ningún archivo .js de negocio sabe ni
   le importa qué tema está activo.
   ================================================================ */
body.theme-light{
  --bg:#f2ede0;
  --bg-2:#e8e1cd;
  --panel:#fffcf5;
  --panel-2:#f6f0e2;
  --line:#ddd2b4;
  --line-soft:#ecdfc2;

  --text:#221d15;
  --muted:#6f6656;
  --muted-2:#87806c;

  --gold:#8a6a2c;
  --gold-dim:#f0e1bd;
  --gold-light:#a9852f;
  --gold-dark:#5f4a1f;
  --on-gold:#fffaf0;

  --gain:#1c8a5c;
  --gain-dim:#d9f0e2;
  --gain-bright:#158f60;
  --gain-text:#0d4a30;
  --on-gain-bright:#eafff5;

  --loss:#c23c33;
  --loss-dim:#f7dcd8;
  --loss-text:#7a201a;

  --accent:#3b5bc9;
}
/* La textura de fondo (repeating-linear-gradient + radiales) estaba
   calibrada para tinta oscura: los mismos rgba casi no se ven sobre
   papel claro. Se redefine aquí solo el "papel" del body, el resto
   de reglas que usan var(--bg)/var(--text)/etc. no necesitan tocarse. */
body.theme-light{
  background:
    repeating-linear-gradient(180deg, rgba(34,29,21,0.028) 0px, rgba(34,29,21,0.028) 1px, transparent 1px, transparent 27px),
    radial-gradient(circle at 12% 8%, rgba(138,106,44,0.07), transparent 42%),
    radial-gradient(circle at 88% 12%, rgba(59,91,201,0.05), transparent 45%),
    radial-gradient(circle at 50% 100%, rgba(28,138,92,0.045), transparent 55%),
    var(--bg);
}

*{box-sizing:border-box;}
html,body{margin:0;padding:0;}
body{
  /* Textura de "papel de cuentas": un ligerísimo rayado horizontal
     (como líneas de un libro mayor) superpuesto a los mismos
     radiales de marca que ya tenías, muy tenue para no restar
     legibilidad. background-attachment:fixed para que no se mueva
     al hacer scroll. */
  background:
    repeating-linear-gradient(180deg, rgba(233,236,243,0.012) 0px, rgba(233,236,243,0.012) 1px, transparent 1px, transparent 27px),
    radial-gradient(circle at 12% 8%, rgba(201,162,78,0.055), transparent 42%),
    radial-gradient(circle at 88% 12%, rgba(111,143,232,0.045), transparent 45%),
    radial-gradient(circle at 50% 100%, rgba(62,207,142,0.035), transparent 55%),
    var(--bg);
  background-attachment:fixed;
  color:var(--text);
  font-family:var(--font-body);
  min-height:100vh;
  min-height:100dvh;
  -webkit-font-smoothing:antialiased;
}
::selection{background:var(--gold); color:#1a1406;}
.num{font-family:var(--font-mono); font-variant-numeric:tabular-nums;}
h1,h2,h3,h4{font-family:var(--font-display); font-weight:600; margin:0; letter-spacing:-0.01em;}
button{font-family:var(--font-body); cursor:pointer;}
a{color:inherit;}
:focus-visible{outline:2px solid var(--gold); outline-offset:2px; border-radius:4px; box-shadow:0 0 0 5px rgba(201,162,78,0.14);}

/* Scrollbar a juego con la paleta (el gris de fábrica del navegador
   desentonaba con el resto del cuidado puesto en el resto de la hoja) */
*{scrollbar-width:thin; scrollbar-color:var(--line) var(--bg-2);}
::-webkit-scrollbar{width:10px; height:10px;}
::-webkit-scrollbar-track{background:var(--bg-2);}
::-webkit-scrollbar-thumb{background:var(--line); border-radius:20px; border:2px solid var(--bg-2);}
::-webkit-scrollbar-thumb:hover{background:var(--muted-2);}

/* ================================================================
   RED DE SEGURIDAD ANTI-OVERFLOW (repaso mobile)
   ================================================================
   Estas reglas no cambian el diseño en desktop, solo evitan que algo
   se "salga" del contenedor en pantallas estrechas. Los culpables más
   típicos de "se sale de containers" en esta app eran:
   1) inputs/selects sin width definido dentro de flex/grid — un
      <input> tiene un ancho mínimo intrínseco de fábrica (~170px)
      que el navegador respeta aunque el contenedor sea más estrecho,
      salvo que se le diga explícitamente min-width:0.
   2) tablas (.log-table) sin límite de ancho, que empujan todo el
      layout hacia la derecha si el contenido de alguna celda es largo.
   3) cualquier overflow puntual que antes provocaba scroll horizontal
      de TODA la página (no solo del elemento culpable), porque nada
      lo frenaba en html/body.
   ================================================================ */
html, body{overflow-x:hidden; max-width:100%;}
img, svg, canvas, video{max-width:100%; height:auto;}
input, select, textarea{min-width:0; max-width:100%;}
table{display:block; overflow-x:auto; -webkit-overflow-scrolling:touch; max-width:100%;}

/* 4) Texto dinámico dentro de tarjetas (nombres de firma/cuenta,
   importes, títulos de sección) generado desde JS: por defecto un
   texto largo o una palabra sin espacios (un nombre pegado, un
   importe con muchos decimales) no rompe línea y empuja la tarjeta
   hacia fuera de su columna del grid, sobre todo en pantallas
   estrechas. overflow-wrap:anywhere permite partir esa palabra si
   hace falta, sin tocar el aspecto en pantallas anchas (solo actúa
   cuando el texto no cabe). min-width:0 es necesario además porque
   estos contenedores son flex/grid items — sin esto, un hijo con
   texto largo no encoge por debajo de su ancho intrínseco aunque
   tenga overflow-wrap, y sigue reventando el layout. */
.acc-card, .stat-card, .sec-card, .chart-card, .alert-card, .meta-hero,
.meta-row, .admin-alert-box, .fcal, .br-card, .detail-top, .todaybox,
.acc-row, .stats-row .stat-card, .cal-nav, .fcal-head, .admin-header,
.staff-clock, .staff-info-row .sec-card{
  min-width:0;
}
.acc-card h3, .acc-card .firmtag, .acc-row, .acc-row b, .acc-row span,
.stat-card .val, .stat-card .lab, .detail-top h2, .detail-top .sub, .sec-card h3,
.chart-card h3, .cal-nav h3, .fcal-title, .admin-header .brand h1,
.staff-title, .staff-company, .todaybox .tp, .todaybox .sl{
  overflow-wrap:anywhere;
}

/* 5) Corrección: en .acc-row y .todaybox el contenedor YA tenía
   min-width:0 (arriba), pero eso no basta — en un flex row los que
   necesitan encoger de verdad son los HIJOS directos (los <span>/<b>
   que llevan el texto), no el propio contenedor. Sin esto, "Total
   retirado" / "TP hoy" con un importe largo seguía empujando la
   tarjeta hacia fuera aunque el texto ya pudiera romper línea. */
.acc-row > span, .acc-row > b, .todaybox > span{
  min-width:0; overflow-wrap:anywhere;
}

/* 6) accountCard() (fondeo.js) pinta la cabecera de cada tarjeta
   (nombre de firma + nombre de cuenta a la izquierda, badge de
   estado a la derecha) como un <div style="display:flex;
   justify-content:space-between"> sin clase propia — el div de texto
   de la izquierda no encogía, así que un nombre de cuenta largo
   empujaba el badge fuera de la tarjeta. renderDetail() repite el
   mismo patrón dentro de .detail-top. Se apunta por estructura
   (primer hijo directo de .acc-card / .detail-top) para no depender
   de tocar fondeo.js. */
.acc-card > div:first-child{ min-width:0; gap:8px; }
.acc-card > div:first-child > div, .detail-top > div:first-child{
  min-width:0; flex:1 1 auto;
}
.acc-card > div:first-child > .badge, .detail-top > .badge{
  flex:none;
}

/* ---------- layout ---------- */
#app{display:none; min-height:100vh; min-height:100dvh;} /* JS decide cuándo mostrarlo, ver initAuth() */
#sidebar{
  width:280px; flex-shrink:0;
  background:var(--bg-2);
  border-right:1px solid var(--line);
  padding:20px 16px;
  display:flex; flex-direction:column; gap:22px;
}
#main{flex:1; padding:26px 34px; max-width:1220px;}
.brand{display:flex; align-items:baseline; gap:9px; padding:0 4px 12px; margin-bottom:4px; border-bottom:1px solid var(--line-soft); position:relative;}
.brand::after{
  content:""; position:absolute; left:4px; bottom:-1px; width:34px; height:2px;
  background:linear-gradient(90deg, var(--gold), transparent);
}
.brand .mark{
  font-family:var(--font-display); font-weight:600; font-size:22px;
  background:var(--grad-brand);
  -webkit-background-clip:text; background-clip:text; color:transparent;
  filter:drop-shadow(0 0 5px rgba(201,162,78,0.3));
}
.brand h1{font-size:18.5px; font-weight:600;}
.brand span.tag{font-size:10.5px; color:var(--muted-2); font-family:var(--font-mono); letter-spacing:.03em;}

.side-section{display:flex; flex-direction:column; gap:8px;}
.side-label{
  font-size:10.5px; text-transform:uppercase; letter-spacing:0.1em;
  color:var(--muted-2); padding:0 4px; display:flex; justify-content:space-between; align-items:center;
  font-family:var(--font-mono);
}
.side-item{
  display:flex; align-items:center; justify-content:space-between;
  padding:9px 10px; border-radius:8px; font-size:13.5px;
  color:var(--muted); border:1px solid transparent; gap:8px;
  transition:background var(--dur-base) var(--ease), color var(--dur-base) var(--ease), border-color var(--dur-base) var(--ease);
}
.side-item:hover{background:var(--panel); color:var(--text); cursor:pointer;}
.side-item.active{background:var(--panel-2); border-color:var(--gold-dim); color:var(--text); box-shadow:inset 2px 0 0 var(--gold);}
.side-item .dot{width:6px;height:6px;border-radius:50%;background:var(--muted-2); flex-shrink:0;}
.side-item .row{display:flex; align-items:center; gap:8px; flex:1; min-width:0;}
.side-item .row span{overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.iconbtn{
  background:none; border:none; color:var(--muted-2); font-size:14px; padding:2px 6px; border-radius:6px;
}
.iconbtn:hover{background:var(--panel-2); color:var(--text);}
.iconbtn.danger:hover{color:var(--loss);}

.btn{
  border:1px solid var(--line); background:var(--panel); color:var(--text);
  padding:8px 13px; border-radius:8px; font-size:13px; font-weight:500;
  display:inline-flex; align-items:center; gap:6px;
  transition:border-color var(--dur-base) var(--ease), filter var(--dur-base) var(--ease), transform var(--dur-fast) var(--ease), box-shadow var(--dur-base) var(--ease);
}
.btn:hover{border-color:var(--muted-2);}
.btn:active{transform:translateY(1px);}
.btn.primary{
  background:linear-gradient(180deg, #839bec, var(--accent) 60%); border-color:var(--accent); color:#fff;
  box-shadow:0 2px 8px rgba(111,143,232,0.28);
}
.btn.primary:hover{filter:brightness(1.08); box-shadow:0 4px 14px rgba(111,143,232,0.4);}
.btn.gold{
  background:linear-gradient(180deg, #ddb768, var(--gold) 60%); border-color:var(--gold); color:var(--on-gold); font-weight:600;
  box-shadow:0 2px 8px rgba(201,162,78,0.28);
}
.btn.gold:hover{filter:brightness(1.06); box-shadow:0 4px 14px rgba(201,162,78,0.4);}
.btn.loss{background:transparent; border-color:var(--loss); color:var(--loss);}
.btn.loss:hover{background:var(--loss); color:#fff;}
.btn.ghost{background:transparent;}
.btn.small{padding:5px 10px; font-size:12px;}
.btn:disabled{opacity:0.4; cursor:not-allowed;}

/* ---------- topbar / stats ---------- */
.topbar{display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:24px; gap:20px; flex-wrap:wrap;}
.stats-row{display:flex; gap:10px; flex-wrap:wrap;}
.stat-card{
  background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
  padding:12px 16px; min-width:120px; box-shadow:var(--shadow-resting); transition:border-color var(--dur-med) var(--ease), transform var(--dur-med) var(--ease), box-shadow var(--dur-med) var(--ease);
  position:relative; overflow:hidden;
}
.stat-card:hover{transform:translateY(-2px); box-shadow:var(--shadow-hover);}
.stat-card::before{
  content:""; position:absolute; top:0; left:0; width:100%; height:2px;
  background:var(--line-soft);
}
.stat-card.highlight{border-color:var(--gold); background:linear-gradient(180deg, rgba(201,162,78,0.09), var(--panel) 70%);}
.stat-card.highlight::before{background:linear-gradient(90deg, var(--gold), transparent);}
.stat-card .lab{font-size:10.5px; color:var(--muted-2); text-transform:uppercase; letter-spacing:0.07em; margin-bottom:4px; font-family:var(--font-mono);}
.stat-card .val{font-family:var(--font-display); font-size:22px; font-weight:600; letter-spacing:-0.01em;}
.stat-card .val.gain{color:var(--gain);}
.stat-card .val.gold{color:var(--gold);}
.stat-card .val.loss{color:var(--loss);}
.stat-card .val.info{color:var(--accent);}

/* ---------- account grid ---------- */
.section-title{display:flex; align-items:center; justify-content:space-between; margin:6px 0 14px;}
.grid{display:grid; grid-template-columns:repeat(auto-fill,minmax(270px,1fr)); gap:14px; margin-bottom:30px;}
.acc-card{
  background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
  padding:16px; cursor:pointer; position:relative; transition:border-color var(--dur-med) var(--ease), transform var(--dur-slow) var(--ease), box-shadow var(--dur-slow) var(--ease);
  display:flex; flex-direction:column; gap:10px;
  box-shadow:var(--shadow-resting), 0 1px 0 rgba(255,255,255,0.025) inset;
}
.acc-card:hover{border-color:var(--muted-2); transform:translateY(-3px); box-shadow:var(--shadow-hover-lg), 0 1px 0 rgba(255,255,255,0.03) inset;}
.acc-card .firmtag{font-size:10px; color:var(--muted-2); text-transform:uppercase; letter-spacing:0.08em; font-family:var(--font-mono);}
.acc-card h3{font-size:16px; margin-top:2px; font-weight:600;}

/* Badge = el "sello" estampado sobre el libro de cuentas: ligero
   giro, borde en anillo y una sombra corta, en vez de la píldora
   plana de cualquier panel. */
.badge{
  font-size:10px; padding:3px 9px; border-radius:20px; font-weight:700; letter-spacing:.04em;
  text-transform:uppercase; display:inline-block; border:1px solid transparent;
  transform:rotate(-1.5deg); box-shadow:0 2px 4px rgba(0,0,0,0.28);
}
.badge.activa{background:var(--gain-dim); color:var(--gain); border-color:rgba(62,207,142,0.35);}
.badge.quemada{background:var(--loss-dim); color:var(--loss); border-color:rgba(226,88,79,0.35);}
.badge.pendiente{background:var(--gold-dim); color:var(--gold); border-color:rgba(201,162,78,0.35);}
.badge.sev-baja{background:var(--gain-dim); color:var(--gain); transform:none;}
.badge.sev-media{background:var(--gold-dim); color:var(--gold); transform:none;}
.badge.sev-alta{background:var(--loss-dim); color:var(--loss); transform:none;}
.badge.section-tag{background:var(--panel-2); color:var(--muted-2); transform:none;}
.badge.meta-badge.completada{background:var(--gold-dim); color:var(--gold); border-color:rgba(201,162,78,0.35);}
.badge.meta-badge.progreso{background:var(--gain-dim); color:var(--gain); border-color:rgba(62,207,142,0.35);}
.badge.meta-badge.luzverde{background:var(--gain-dim); color:var(--gain); border-color:rgba(62,207,142,0.4); transform:none;}
.badge.meta-badge.alerta{background:var(--loss-dim); color:var(--loss); border-color:rgba(226,88,79,0.4); transform:none;}

/* ---------- Metas & Recompensas: barra general de urgencia (hero) ----------
   Una única barra (no una por meta) que se llena por % de lo ahorrado
   para la meta pendiente más urgente — "lo que toca ahorrar primero". */
.meta-hero{
  display:flex; align-items:center; gap:16px;
  background:linear-gradient(135deg, rgba(201,162,78,0.10), var(--panel) 65%);
  border:1px solid rgba(201,162,78,0.35); border-radius:var(--radius);
  padding:18px 20px; margin-bottom:18px;
  box-shadow:0 4px 16px rgba(0,0,0,0.35);
}
.meta-hero-done{
  text-align:center; padding:20px; font-size:14px;
  background:var(--gold-dim); border:1px solid rgba(201,162,78,0.35); border-radius:var(--radius);
  color:var(--gold); margin-bottom:18px;
}
.meta-hero-icon{
  --glow-rgb:201,162,78; flex:none; width:54px; height:54px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:radial-gradient(circle at 32% 30%, rgba(var(--glow-rgb),0.38), rgba(var(--glow-rgb),0.08) 72%);
  box-shadow:0 0 20px 2px rgba(var(--glow-rgb),0.5), inset 0 0 0 1px rgba(var(--glow-rgb),0.45);
}
.meta-hero-icon svg{width:26px; height:26px; filter:drop-shadow(0 0 4px rgba(var(--glow-rgb),0.85));}
.meta-hero-icon img{width:100%; height:100%; object-fit:cover; border-radius:50%;}
.meta-hero-main{flex:1; min-width:0; display:flex; flex-direction:column; gap:8px;}
.meta-hero-top{display:flex; align-items:baseline; gap:8px; flex-wrap:wrap;}
.meta-hero-eyebrow{font-size:11px; text-transform:uppercase; letter-spacing:0.06em; color:var(--muted); white-space:nowrap;}
.meta-hero-top h3{font-size:17px; margin:0; font-weight:700; color:var(--gold);}
.meta-hero-bar{height:9px;}
.meta-hero-bar>div{background:linear-gradient(90deg, var(--gold), var(--gold-light));}
.meta-hero-bottom{display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; font-size:12.5px; color:var(--muted);}
.meta-hero-amounts b{color:var(--text);}
.meta-hero-pct{color:var(--gold);}
.meta-hero-fecha.vencida{color:var(--loss);}

.meta-hero.colchon{
  background:linear-gradient(135deg, rgba(62,207,142,0.10), var(--panel) 65%);
  border-color:rgba(62,207,142,0.35);
}
.meta-hero.colchon .meta-hero-top h3{color:var(--gain);}
.meta-hero.colchon.completo{border-color:rgba(62,207,142,0.55); box-shadow:0 4px 16px rgba(62,207,142,0.15);}
.colchon-bar>div{background:var(--grad-gain);}
.meta-row-fecha.alerta-text{color:var(--loss);}
@media (max-width:480px){ .meta-hero{flex-wrap:wrap;} }

/* ---------- Metas & Recompensas (lista compacta) ---------- */
.meta-list{display:flex; flex-direction:column; gap:10px; margin-bottom:30px;}
.meta-row{
  background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
  padding:12px 16px; display:flex; align-items:center; gap:14px;
  transition:border-color var(--dur-base), transform var(--dur-base), box-shadow var(--dur-base), opacity var(--dur-base);
  box-shadow:var(--shadow-resting);
}
.meta-row:hover{border-color:var(--muted-2); transform:translateY(-1px); box-shadow:var(--shadow-hover);}
.meta-row.completada{border-color:rgba(201,162,78,0.4); background:linear-gradient(180deg, rgba(201,162,78,0.07), var(--panel) 70%);}
.meta-row.dragging{opacity:0.35;}
.meta-row[draggable="true"]{cursor:grab;}
.meta-drag-handle{flex:none; color:var(--muted-2); font-size:15px; line-height:1; cursor:grab; user-select:none; padding-right:2px;}
.badge.meta-badge.prioritaria{background:rgba(201,162,78,0.16); color:var(--gold); border-color:rgba(201,162,78,0.4);}
.meta-row-fecha{font-size:11px; color:var(--muted-2); margin-top:1px;}
.meta-row-fecha.vencida{color:var(--loss);}
.progress-bar.mini{height:3px; opacity:0.8;}

/* El icono vive en un chip circular con degradado radial del color de
   su categoría (--glow-rgb, en rgb "r,g,b") y un resplandor real
   (box-shadow difuminado + drop-shadow en el propio trazo del SVG),
   para que se sienta "premium"/motivador en vez de un icono plano. */
.meta-row-icon{
  --glow-rgb:201,162,78;
  flex:none; width:42px; height:42px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:radial-gradient(circle at 32% 30%, rgba(var(--glow-rgb),0.32), rgba(var(--glow-rgb),0.06) 72%);
  box-shadow:0 0 14px 1px rgba(var(--glow-rgb),0.45), inset 0 0 0 1px rgba(var(--glow-rgb),0.4);
}
.meta-row-icon svg{width:20px; height:20px; filter:drop-shadow(0 0 3px rgba(var(--glow-rgb),0.8));}
.meta-row-icon img{width:100%; height:100%; object-fit:cover; border-radius:50%;}
.meta-row-main{flex:1; min-width:0; display:flex; flex-direction:column; gap:6px;}
.meta-row-top{display:flex; align-items:center; gap:8px; flex-wrap:wrap;}
.meta-row-top h3{font-size:14.5px; font-weight:600; margin:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
.meta-row-side{flex:none; display:flex; align-items:center; gap:12px;}
.meta-row-amounts{flex-direction:column; align-items:flex-end; gap:2px; font-size:12px; min-width:70px;}

/* Checklist táctico por meta (nuevo) */
.meta-checklist{margin-top:6px; padding-top:8px; border-top:1px dashed var(--line); display:flex; flex-direction:column; gap:5px;}
.meta-checklist-head{font-size:10.5px; text-transform:uppercase; letter-spacing:0.05em; color:var(--muted-2);}
.meta-checklist-item{display:flex; align-items:flex-start; gap:7px; font-size:12.5px; color:var(--muted); cursor:pointer;}
.meta-checklist-item input{margin-top:2px; accent-color:var(--gold); cursor:pointer;}
.meta-checklist-item.done span{color:var(--muted-2); text-decoration:line-through;}
.meta-checklist-item a{color:var(--accent);}

/* Caja destacada de control de saldo/margen NFC (vista Bitrefill) */
.crypto-box{background:var(--panel); border:1px solid var(--gain); border-radius:var(--radius); padding:16px; margin-bottom:16px;}
.crypto-box.crypto-alerta{border-color:var(--loss);}

@media (max-width:480px){
  .meta-row{flex-wrap:wrap; padding:12px;}
  .meta-row-main{flex-basis:100%; order:3;}
  .meta-row-side{margin-left:auto;}
}

/* ---------- Reparto de metas (modal) ---------- */
.reparto-row{display:flex; align-items:center; justify-content:space-between; gap:12px;}
.reparto-row-lab{display:flex; flex-direction:column; gap:2px; font-size:13px;}
.reparto-input{width:110px; flex:none;}

/* ---------- Fase F: consola de bugs ---------- */
.bug-card{
  background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
  padding:16px; display:flex; flex-direction:column; gap:10px; margin-bottom:12px;
}
.bug-card .bug-top{display:flex; justify-content:space-between; align-items:flex-start; gap:10px; flex-wrap:wrap;}
.bug-card .bug-tags{display:flex; gap:6px; flex-wrap:wrap;}
.bug-card .bug-desc{font-size:13px; color:var(--text); white-space:pre-wrap; line-height:1.5;}
.bug-card .bug-meta{font-size:11px; color:var(--muted-2);}
.bug-card .bug-check-result{font-size:11.5px; color:var(--muted); border-left:2px solid var(--gold-dim); padding-left:8px; margin-top:2px;}
.bug-card .bug-actions{display:flex; gap:8px; flex-wrap:wrap; margin-top:2px;}
.bug-status-select{
  background:var(--panel-2); color:var(--text); border:1px solid var(--line); border-radius:20px;
  font-size:11px; font-weight:600; padding:4px 10px; cursor:pointer;
}
.bug-form textarea{min-height:70px; resize:vertical;}
.bug-intro{font-size:12.5px; color:var(--muted); margin-bottom:16px; line-height:1.6; padding:12px 14px; background:var(--panel-2); border-radius:9px; border:1px solid var(--line-soft);}

/* ---------- Fase G: modo presentación ---------- */
.presentation-overlay{
  position:fixed; inset:0; z-index:900; display:none;
  flex-direction:column; align-items:center; justify-content:center; gap:36px;
  background:
    radial-gradient(circle at 20% 20%, rgba(201,162,78,0.07), transparent 45%),
    radial-gradient(circle at 80% 80%, rgba(111,143,232,0.05), transparent 45%),
    var(--bg-2);
}
.presentation-overlay.show{display:flex;}
.presentation-mark{
  font-family:var(--font-display); font-weight:600; font-size:34px;
  background:var(--grad-brand);
  -webkit-background-clip:text; background-clip:text; color:transparent;
  filter:drop-shadow(0 0 8px rgba(201,162,78,0.35));
}
.presentation-grid{display:flex; gap:56px; flex-wrap:wrap; justify-content:center; padding:0 40px;}
.presentation-stat{text-align:center;}
.presentation-stat .lab{font-size:13px; letter-spacing:.12em; text-transform:uppercase; color:var(--muted-2); margin-bottom:12px; font-family:var(--font-mono);}
.presentation-stat .val{font-family:var(--font-display); font-size:clamp(34px, 6vw, 64px); font-weight:600; letter-spacing:-0.01em;}
.presentation-exit{
  position:absolute; top:26px; right:30px; background:transparent; border:1px solid var(--line);
  color:var(--muted); padding:8px 14px; border-radius:8px; font-size:13px;
}
.presentation-exit:hover{color:var(--text); border-color:var(--muted-2);}

/* ---------- Mejora: modo reel (vertical, pensado para grabar pantalla
   tipo TikTok/Reels/Stories) — mismo overlay que el modo presentación,
   solo cambia el ancho y el layout a una columna vertical centrada. */
.presentation-overlay.reel{
  max-width:460px; margin:0 auto; left:50%; transform:translateX(-50%);
  border-left:1px solid rgba(216,180,92,0.25); border-right:1px solid rgba(216,180,92,0.25);
  gap:44px;
}
.presentation-overlay.reel .presentation-grid{flex-direction:column; gap:38px; padding:0 24px;}
.presentation-overlay.reel .presentation-stat .val{font-size:clamp(40px, 11vw, 58px);}
.presentation-overlay.reel .presentation-mark{font-size:26px;}

/* ---------- Mejora: racha (gamificación) en el dashboard ---------- */
.stat-card .val.streak{color:var(--gold); display:flex; align-items:center; gap:4px;}

/* ---------- Fase G: micro-animación al marcar TP / confirmar cobro ---------- */
.celebrate-layer{position:fixed; inset:0; pointer-events:none; z-index:1200; overflow:hidden;}
.celebrate-flash{
  position:absolute; inset:0;
  background:radial-gradient(circle at 50% 38%, rgba(201,162,78,0.32), transparent 62%);
  animation:celebrateFlash 1s ease-out forwards;
}
@keyframes celebrateFlash{0%{opacity:0;} 18%{opacity:1;} 100%{opacity:0;}}
.confetti-piece{
  position:absolute; top:-16px; width:7px; height:7px; border-radius:2px; opacity:.95;
  animation:confettiFall linear forwards;
}
@keyframes confettiFall{
  0%{transform:translateY(0) rotate(0deg); opacity:1;}
  100%{transform:translateY(105vh) rotate(360deg); opacity:0;}
}

/* ---------- Roadmap #14 parte 2 (30/07/26): confetti al completar una meta ----------
   Clases propias (no reutiliza .celebrate-layer/.confetti-piece de arriba,
   que son de la Fase G para TP/cobro) para que ambas animaciones puedan
   coexistir sin pisarse si coinciden en el tiempo (p.ej. un cobro que de
   paso completa una meta en el mismo reparto). Ver dispararConfettiMeta()
   en metas.js. */
.meta-celebrate-layer{position:fixed; inset:0; pointer-events:none; z-index:1300; overflow:hidden;}
.meta-confetti-piece{
  position:absolute; top:-16px; width:8px; height:8px; border-radius:2px; opacity:.95;
  animation:metaConfettiFall linear forwards;
}
@keyframes metaConfettiFall{
  0%{transform:translateY(0) rotate(0deg); opacity:1;}
  100%{transform:translateY(105vh) rotate(360deg); opacity:0;}
}
.acc-row{display:flex; justify-content:space-between; font-size:12.5px; color:var(--muted);}
.acc-row b{color:var(--text); font-weight:500; font-family:var(--font-mono);}
.progress-bar{height:5px; border-radius:4px; background:var(--line-soft); overflow:hidden;}
.progress-bar>div{height:100%; background:var(--grad-gain); border-radius:4px;}
.todaybox{
  margin-top:2px; border-top:1px solid var(--line-soft); padding-top:10px;
  display:flex; justify-content:space-between; font-size:12.5px;
}
.todaybox .tp{color:var(--gain);} .todaybox .sl{color:var(--loss);}

.empty{color:var(--muted-2); font-size:13.5px; border:1px dashed var(--line); border-radius:var(--radius); padding:26px; text-align:center;}

/* Lista de sugerencias tipo "buscar y elegir" (NO es un <select>): se
   usa para elegir gestor/usuario por nombre escribiendo, con filas
   pulsables en vez de un desplegable nativo. */
.admin-suggest-list{
  position:absolute; left:0; right:0; top:100%; margin-top:4px; z-index:20;
  background:var(--panel-2); border:1px solid var(--line); border-radius:var(--radius);
  max-height:220px; overflow-y:auto; box-shadow:var(--shadow-dropdown);
}
.admin-suggest-item{
  padding:9px 12px; font-size:13px; cursor:pointer; border-bottom:1px solid var(--line);
}
.admin-suggest-item:last-child{border-bottom:none;}
.admin-suggest-item:hover, .admin-suggest-item.active{background:rgba(255,255,255,0.06);}
.admin-suggest-item .uid{display:block; font-size:10.5px; color:var(--muted-2); font-family:var(--font-mono);}
.admin-suggest-empty{padding:10px 12px; font-size:12.5px; color:var(--muted-2);}

/* ---------- modal ---------- */
.overlay{
  position:fixed; inset:0; background:rgba(4,5,9,0.78); display:none;
  align-items:flex-start; justify-content:center; z-index:50; padding:40px 16px; overflow:auto;
}
.overlay.show{display:flex;}
.modal{
  background:var(--panel); border:1px solid var(--line); border-radius:14px;
  width:100%; max-width:640px; padding:22px 24px 24px; margin-bottom:40px;
  box-shadow:var(--shadow-modal);
}
.modal h2{font-size:18px; margin-bottom:4px;}
.modal .sub{font-size:12.5px; color:var(--muted-2); margin-bottom:16px;}
.modal.wide{max-width:820px;}
.modal.narrow{max-width:400px;}
.field{margin-bottom:14px;}
.field label{display:block; font-size:12px; color:var(--muted); margin-bottom:5px;}
.field input, .field select, .field textarea{
  width:100%; background:var(--bg-2); border:1px solid var(--line); color:var(--text);
  padding:9px 10px; border-radius:7px; font-size:13.5px; font-family:inherit;
  transition:border-color var(--dur-fast);
}
.field input:focus, .field select:focus, .field textarea:focus{border-color:var(--gold); outline:none; box-shadow:0 0 0 3px rgba(201,162,78,0.14);}
.field input.num-in, .field textarea.num-in{font-family:var(--font-mono);}
.field input.num-in[readonly]{color:var(--gold); background:var(--panel-2); border-style:dashed; cursor:default;}
.field-row{display:flex; gap:10px;}
.field-row .field{flex:1;}
.modal-actions{display:flex; justify-content:flex-end; gap:8px; margin-top:18px;}
.modal-actions.split{justify-content:space-between;}
.close-x{position:absolute; top:14px; right:16px; background:none; border:none; color:var(--muted-2); font-size:18px;}

/* ---------- hoja "Más" (móvil) ---------- */
.overlay.sheet-overlay{align-items:flex-end; padding:0;}
.modal.sheet{
  width:100%; max-width:600px; margin:0 auto 0; padding:10px 10px calc(14px + env(safe-area-inset-bottom));
  border-radius:20px 20px 0 0; animation:sheetUp .2s ease;
}
@keyframes sheetUp{ from{transform:translateY(30px); opacity:0;} to{transform:translateY(0); opacity:1;} }
.sheet-handle{width:36px; height:4px; border-radius:3px; background:var(--line); margin:2px auto 14px;}
.sheet-group{margin-bottom:6px;}
.sheet-group + .sheet-group{margin-top:10px; padding-top:10px; border-top:1px solid var(--line-soft);}
.sheet-label{font-size:11px; color:var(--muted-2); text-transform:uppercase; letter-spacing:.05em; font-family:var(--font-mono); padding:0 8px 8px;}
.sheet-item{
  width:100%; display:flex; align-items:center; gap:12px; background:none; border:none;
  color:var(--text); font-family:var(--font-body); font-size:14.5px; font-weight:500;
  padding:13px 8px; border-radius:10px; text-align:left;
}
.sheet-item i{font-style:normal; font-size:18px; width:22px; text-align:center;}
.sheet-item:active{background:var(--panel-2);}
.sheet-item.danger{color:var(--loss);}
.sheet-item .badge{margin-left:auto;}

/* ---------- phase builder ---------- */
.phase-block{border:1px solid var(--line); border-radius:10px; padding:14px; margin-bottom:12px; background:var(--panel-2);}
.phase-head{display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;}
.phase-head input{font-family:var(--font-display); font-weight:600; font-size:14.5px; background:transparent; border:none; color:var(--text); width:60%;}
.day-row{display:grid; grid-template-columns:24px 78px 84px 84px 1fr 28px; gap:6px; align-items:center; margin-bottom:6px;}
.day-row .idx{color:var(--muted-2); font-size:12px; text-align:right; font-family:var(--font-mono);}
.day-row input{width:100%; min-width:0; background:var(--bg-2); border:1px solid var(--line); color:var(--text); border-radius:6px; padding:6px 7px; font-size:12.5px;}
.day-row input.gain{color:var(--gain);}
.day-row input.sl{color:var(--loss);}
.day-row input.benefit{color:var(--gold);}
.day-row button{background:none; border:none; color:var(--muted-2); font-size:14px;}
.day-row button:hover{color:var(--loss);}
.target-row{display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-top:10px;}

/* ---------- detail / staircase ----------
   La escalera es el SEGUNDO elemento de firma: cada tramo ya es una
   metáfora de "subir de fase hacia el cobro", así que se refuerza en
   vez de sustituirse — el escalón actual y el de aterrizaje (cobro)
   ahora llevan un halo de color a juego para que se note de un
   vistazo dónde estás y a dónde vas. */
.detail-top{display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:18px; flex-wrap:wrap; gap:12px;}
.detail-top h2{font-size:20px; display:inline-flex; align-items:center; gap:8px;}
.detail-top .sub{color:var(--muted); font-size:13px; margin-top:3px;}
.stair-wrap{
  display:flex; align-items:flex-end; gap:10px; overflow-x:auto; padding:30px 6px 6px;
  border-bottom:1px solid var(--line); margin-bottom:20px;
}
.step{
  display:flex; flex-direction:column; align-items:center; gap:8px; flex-shrink:0; width:118px;
}
.step .card{
  width:100%; border-radius:9px; padding:9px 8px; font-size:11.5px; text-align:center;
  border:1px solid var(--line); background:var(--panel-2); color:var(--muted);
  transition:border-color var(--dur-base), box-shadow var(--dur-base);
}
.step .card .d{font-family:var(--font-mono); font-size:10px; color:var(--muted-2); margin-bottom:3px;}
.step .card .tp{color:var(--gain); font-family:var(--font-mono); font-size:12.5px;}
.step .card .sl{color:var(--loss); font-family:var(--font-mono); font-size:11.5px;}
.step .card .bf{color:var(--gold); font-family:var(--font-mono); font-size:11px;}
.step .bar{width:36px; border-radius:5px 5px 0 0; background:var(--line-soft);}
.step.done .bar{background:var(--gain-dim);}
.step.done .card{border-color:var(--gain-dim);}
.step.current .bar{background:var(--accent); box-shadow:0 0 12px rgba(111,143,232,0.55);}
.step.current .card{border-color:var(--accent); background:var(--panel); box-shadow:0 0 0 1px rgba(111,143,232,0.25);}
.step.current .card::before{content:"HOY"; display:block; font-size:9px; letter-spacing:.08em; color:var(--accent); margin-bottom:3px; font-family:var(--font-mono);}
.step.landing .bar{background:var(--gold-dim); width:44px;}
.step.landing .card{border-color:var(--gold); background:var(--gold-dim); color:var(--gold); box-shadow:0 0 16px rgba(201,162,78,0.3);}
.step.landing .card .d{color:var(--gold);}

.actions-row{display:flex; gap:10px; flex-wrap:wrap; margin-bottom:18px;}
.log-table{width:100%; border-collapse:collapse; font-size:12.5px;}
.log-table th{text-align:left; color:var(--muted-2); font-weight:500; font-size:10.5px; text-transform:uppercase; letter-spacing:.05em; padding:6px 8px; border-bottom:1px solid var(--line); font-family:var(--font-mono);}
.log-table td{padding:7px 8px; border-bottom:1px solid var(--line-soft); color:var(--muted);}
.log-table td.amt{font-family:var(--font-mono);}
.log-table td.amt.g{color:var(--gain);} .log-table td.amt.l{color:var(--loss);}

.banner{
  display:none; background:var(--panel-2); border:1px solid var(--line); border-radius:8px;
  padding:8px 12px; font-size:12px; color:var(--muted); margin-bottom:16px; align-items:center; gap:8px;
}
.banner.show{display:flex;}

.adjust-box{
  border:1px solid var(--line); border-radius:10px; padding:14px 16px; margin-bottom:20px; background:var(--panel-2);
}
.adjust-box summary{cursor:pointer; font-size:12.5px; color:var(--muted); list-style:none; display:flex; align-items:center; gap:6px;}
.adjust-box summary::-webkit-details-marker{display:none;}
.adjust-box summary::before{content:"⚙"; }
.adjust-grid{display:grid; grid-template-columns:1fr 1fr 1fr; gap:10px; margin-top:12px;}

/* ---------- stats view ---------- */
.chart-grid{display:grid; grid-template-columns:1.4fr 1fr; gap:16px; margin-bottom:16px;}
.chart-card{background:var(--panel); border:1px solid var(--line); border-radius:var(--radius); padding:16px; box-shadow:var(--shadow-resting);}
.chart-card h3{font-size:13.5px; color:var(--muted); font-weight:500; margin-bottom:12px; font-family:var(--font-body);}
.chart-card canvas{max-height:260px;}
.filter-row{display:flex; gap:8px; align-items:center; margin-bottom:16px;}
.filter-row select{min-width:0; background:var(--panel); border:1px solid var(--line); color:var(--text); padding:7px 10px; border-radius:7px; font-size:12.5px;}
@media (max-width:900px){ .chart-grid{grid-template-columns:1fr;} }

/* Roadmap #19 (30/07/26): rejilla propia para el simulador comparativo de
   N firmas — a diferencia de .chart-grid (fija a 2 columnas, la usa la
   vista de Estadísticas), esta se adapta a cuantas firmas se seleccionen. */
.sim-compare-grid{display:grid; grid-template-columns:repeat(auto-fit, minmax(320px, 1fr)); gap:16px; margin-bottom:16px;}

/* ---------- Fase H: Calendario de trading (heatmap) ---------- */
.cal-nav{display:flex; align-items:center; justify-content:space-between; margin-bottom:14px;}
.cal-nav h3{font-size:15px; font-weight:600; text-transform:capitalize;}
.cal-grid{display:grid; grid-template-columns:repeat(7,1fr); gap:6px;}
.cal-dow{font-size:10.5px; color:var(--muted-2); text-align:center; text-transform:uppercase; letter-spacing:.05em; padding-bottom:4px; font-family:var(--font-mono);}
.cal-cell{
  aspect-ratio:1; border-radius:8px; border:1px solid var(--line);
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  font-size:11px; color:var(--muted); cursor:default; gap:2px; padding:4px;
  background:var(--panel);
}
.cal-cell.pad{border:none; background:transparent;}
.cal-cell.has-data{cursor:pointer;}
.cal-cell.has-data:hover{border-color:var(--muted-2);}
.cal-cell .d{font-size:10px; color:var(--muted-2);}
.cal-cell .v{font-size:11px; font-weight:600; font-family:var(--font-mono);}
.cal-legend{display:flex; align-items:center; gap:6px; font-size:11px; color:var(--muted-2); margin-top:12px;}
.cal-legend .sw{width:12px; height:12px; border-radius:3px; display:inline-block;}
#calDayDetail{margin-top:16px;}

/* ---------- Fase H: Alertas ---------- */
.alert-card{
  background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
  padding:14px 16px; display:flex; align-items:center; justify-content:space-between; gap:12px;
  margin-bottom:10px; border-left:3px solid var(--gold);
}
.alert-card.sev-alta{border-left-color:var(--loss);}
.alert-card .txt b{color:var(--text);}
.alert-card .txt .sub{font-size:12px; color:var(--muted-2); margin-top:2px;}
.alerts-settings{display:flex; gap:18px; flex-wrap:wrap; margin-bottom:18px; background:var(--panel); border:1px solid var(--line); border-radius:var(--radius); padding:12px 16px;}
.alerts-settings .field{margin-bottom:0; flex:1; min-width:200px;}

/* ---------- Roadmap #18 (30/07/26): timeline unificada de próximos eventos ---------- */
.timeline-list{display:flex; flex-direction:column; gap:8px;}
.timeline-row{
  background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
  padding:12px 16px; display:flex; align-items:center; gap:14px; border-left:3px solid var(--gold);
}
.timeline-row.timeline-objetivo{border-left-color:var(--gain);}
.timeline-row.timeline-caducidad{border-left-color:var(--loss);}
.timeline-dias{
  font-family:'IBM Plex Mono', monospace; font-size:13px; color:var(--gold); font-weight:600;
  min-width:44px; text-align:center;
}
.timeline-row.timeline-objetivo .timeline-dias{color:var(--gain);}
.timeline-row.timeline-caducidad .timeline-dias{color:var(--loss);}
.timeline-icon{font-size:18px; flex-shrink:0;}
.timeline-body{flex:1; min-width:0;}
.timeline-titulo{font-size:13.5px; color:var(--text); font-weight:500;}

.sim-grid{display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-bottom:14px;}
.sim-grid .field{margin-bottom:0;}
.sim-toggle{display:flex; align-items:center; gap:8px; font-size:12.5px; color:var(--muted); margin-bottom:14px;}
.sim-toggle input{width:auto;}
@media (max-width:900px){ .sim-grid{grid-template-columns:1fr 1fr;} }

#toast{
  position:fixed; bottom:22px; left:50%; transform:translateX(-50%) translateY(10px); opacity:0;
  background:var(--panel-2); border:1px solid var(--line); color:var(--text); padding:10px 18px;
  border-radius:9px; font-size:13px; z-index:100; transition:all var(--dur-slow); pointer-events:none;
  box-shadow:var(--shadow-panel-float);
}
#toast.show{opacity:1; transform:translateX(-50%) translateY(0);}

/* Aviso de "hay versión nueva de la app" — flotante arriba, por
   encima de todo salvo la pantalla de login, con su propia franja de
   safe-area-inset-top para no quedar bajo la barra de notificaciones. */
#updateBanner{
  display:none; position:fixed; top:0; left:0; right:0; z-index:600;
  align-items:center; justify-content:center; gap:12px; flex-wrap:wrap;
  background:linear-gradient(180deg, rgba(201,162,78,0.16), rgba(201,162,78,0.07));
  border-bottom:1px solid var(--gold-dim);
  padding:calc(10px + var(--safe-top)) 16px 10px;
  font-size:12.5px; color:var(--text); text-align:center;
  backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
}
#updateBanner.show{display:flex;}
#updateBanner .close-x{position:static; background:none; border:none; color:var(--muted-2); cursor:pointer; font-size:13px;}

/* Fase iPhone: barra de pestañas fija abajo, estilo app nativa.
   Definida ANTES de la media query a propósito: así el display:flex
   de abajo (dentro de @media max-width:760px) gana la cascada en
   móvil. Si esta regla base se pone DESPUÉS de la media query, con
   la misma especificidad (#mobileTabBar vs #mobileTabBar) gana la
   que esté más abajo en el archivo y la barra no se ve NUNCA — este
   fue el bug real por el que no salía en el iPhone. */
#mobileTabBar{
  display:none; position:fixed; left:0; right:0; bottom:0; z-index:40;
  background:rgba(7,9,17,.92); -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px);
  border-top:1px solid var(--line);
  padding:8px 4px calc(8px + env(safe-area-inset-bottom));
  justify-content:space-around; align-items:center;
}

/* Mini-header de marca, solo visible en móvil (sustituye al sidebar).
   padding-top suma el alto de la barra de estado/notch (env(safe-area-inset-top)
   vía --safe-top) para que la marca no quede pegada o tapada por la barra
   de notificaciones. position:sticky (antes estático) — sin esto, al
   hacer scroll esta barra se iba hacia arriba y desaparecía como
   cualquier contenido normal, dejando el título propio de cada vista
   (ej. "Gastos") pegado contra el borde real de la pantalla, tapado por
   la barra de notificaciones del iPhone. El Dashboard no sufría esto
   porque #mobileQuickBar (sticky) hacía de colchón, pero el resto de
   vistas no tienen ese colchón propio. Fondo sólido + z-index para que
   tape el contenido que pasa por debajo al hacer scroll.
   IMPORTANTE — definida ANTES de la media query, mismo motivo que
   #mobileTabBar arriba: con la misma especificidad (#mobileTopBar vs
   #mobileTopBar), si esta regla base (con display:none) se queda
   DESPUÉS del "#mobileTopBar{display:flex;}" de la media query, gana
   la de aquí abajo y la barra no se muestra NUNCA en móvil — este era
   el bug real por el que el título de cada vista chocaba con la hora/
   batería en TODAS las pantallas, no solo en una vista concreta. */
#mobileTopBar{
  display:none; align-items:center; gap:8px;
  position:sticky; top:0; z-index:25; background:var(--bg-2);
  padding:calc(16px + var(--safe-top)) 18px 12px; border-bottom:1px solid var(--line);
  font-family:var(--font-display); font-weight:600; font-size:16px; color:var(--text);
}
#mobileTopBar .mark{color:var(--gold); font-size:17px;}
#mobileTopBar span:nth-child(2){flex:1;}

@media (max-width:760px){
  #app{flex-direction:column;}
  /* Antes el sidebar se reflow-eaba como fila horizontal deslizable
     con firmas/exportar/cerrar sesión — quedaba feo y con cosas que
     en el móvil no hacen falta (exportar, modo edición...). Ahora en
     móvil el sidebar entero se oculta: la navegación principal la
     cubre #mobileTabBar de abajo, el resto de opciones (firmas,
     seguridad, cerrar sesión...) vive agrupado en la hoja "Más"
     (#moreOverlay), y la marca/título se muestra en #mobileTopBar. */
  #sidebar{display:none;}
  #mobileTopBar{display:flex;}
  #main{padding:18px; padding-bottom:calc(78px + env(safe-area-inset-bottom));}
  #mobileQuickBar{display:flex;}
  #mobileTabBar{display:flex;}
}

.refresh-btn{
  background:none; border:1px solid var(--line); color:var(--muted); border-radius:8px;
  width:30px; height:30px; font-size:15px; line-height:1; cursor:pointer; flex:none;
  display:inline-flex; align-items:center; justify-content:center; transition:color var(--dur-base), border-color var(--dur-base);
}
.refresh-btn:active{color:var(--gold); border-color:var(--gold);}
.refresh-btn.spin{animation:refreshSpin .6s linear infinite; color:var(--gold); border-color:var(--gold);}
@keyframes refreshSpin{ to{transform:rotate(360deg);} }

/* ---------- Skeleton loader genérico (pantallas completas tipo
   #staffApp mientras cargan datos de Supabase). Bloques grises con un
   barrido de luz, en vez de dejar solo un texto suelto o la pantalla
   en blanco. Reutiliza --panel-2/--line, no --gold, para no competir
   visualmente con el contenido real cuando termine de cargar. */
/* Sin padding/max-width propios a propósito: el skeleton se pinta
   DENTRO de #staffApp (wrap.innerHTML), que ya aplica su propio
   padding con safe-area — duplicarlo aquí dejaría doble margen arriba. */
.skeleton-wrap{display:block;}
.skel{
  position:relative; overflow:hidden; background:var(--panel-2);
  border-radius:8px; display:block;
}
.skel::after{
  content:''; position:absolute; inset:0; transform:translateX(-100%);
  background:linear-gradient(90deg, transparent, rgba(233,236,243,0.06), transparent);
  animation:skelShimmer 1.4s ease-in-out infinite;
}
@keyframes skelShimmer{ to{transform:translateX(100%);} }
.skel-topbar{height:52px; border-radius:10px; margin-bottom:22px;}
.skel-tabs{height:44px; border-radius:11px; margin-bottom:22px;}
.skel-card{height:88px; border-radius:var(--radius); margin-bottom:14px;}
.skel-row{display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:14px; margin-bottom:22px;}
@media (prefers-reduced-motion: reduce){ .skel::after{animation:none;} }

.mtab{
  background:none; border:none; display:flex; flex-direction:column; align-items:center; gap:2px;
  color:var(--muted-2); font-family:var(--font-body); font-size:10px; font-weight:600;
  padding:4px 8px; border-radius:10px; transition:color var(--dur-base);
}
.mtab i{ font-style:normal; font-size:19px; line-height:1; }
.mtab.active{ color:var(--gold); }
.mtab:active{ transform:scale(0.94); }
/* Fase I: barra fija de "vista rápida" solo para móvil — el
   beneficio neto siempre visible arriba aunque hagas scroll por
   las cuentas, sin tener que abrir el menú lateral. Oculta por
   defecto (display:none), la media query de arriba la muestra
   solo bajo 760px. */
#mobileQuickBar{
  display:none; position:sticky; top:var(--safe-top); z-index:20; align-items:center; justify-content:space-between;
  background:var(--bg-2); border:1px solid var(--line); border-radius:9px;
  padding:9px 14px; margin-bottom:14px; font-size:13px;
}
#mobileQuickBar .lab{color:var(--muted-2); font-size:11px; text-transform:uppercase; letter-spacing:.05em; font-family:var(--font-mono);}
#mobileQuickBar .val{font-family:var(--font-mono); font-weight:700; font-size:16px;}

/* ---------- Fase C: pantalla de login / registro ---------- */
#authScreen{
  display:none; align-items:center; justify-content:center;
  background:radial-gradient(circle at 50% 0%, rgba(201,162,78,0.07), transparent 55%), var(--bg);
  /* padding suma la barra de notificaciones/notch arriba y la barra de
     gestos abajo, para que la tarjeta de login nunca quede pegada a
     ninguna de las dos. position:fixed + z-index alto asegura que, si
     por lo que sea la barra de pestañas inferior (#mobileTabBar) queda
     visible, la pantalla de login siempre se dibuja por encima y la tapa
     por completo (además del arreglo real, que es ocultar la barra con
     JS mientras se ve el login, ver body.auth-mode más abajo). */
  padding:calc(20px + var(--safe-top)) 20px calc(20px + env(safe-area-inset-bottom));
  position:fixed; inset:0; z-index:500;
}
#authScreen.show{display:flex;}

/* Mientras se muestra login/registro o el panel admin de aprobación de
   dispositivos, la barra de pestañas inferior no debe verse — antes se
   veía porque #mobileTabBar vive fuera de #app en el HTML y por tanto
   no se ocultaba junto con el resto de la app. app.js añade/quita esta
   clase en <body> exactamente cuando corresponde. */
body.auth-mode #mobileTabBar{display:none !important;}
.auth-card{
  width:100%; max-width:380px; background:var(--panel); border:1px solid var(--line);
  border-radius:16px; padding:34px 28px 30px; box-shadow:var(--shadow-modal);
  position:relative; overflow:hidden;
}
/* Filo dorado superior, mismo lenguaje visual que .stat-card.highlight::before,
   para que la tarjeta de login no parezca un componente aparte del resto de la app. */
.auth-card::before{
  content:''; position:absolute; top:0; left:0; right:0; height:3px;
  background:var(--grad-brand);
}
.auth-card .brand{
  flex-direction:column; justify-content:center; align-items:center; gap:13px;
  margin-bottom:26px; border-bottom:none; padding-bottom:0; text-align:center;
}
.auth-card .brand::after{display:none;}
/* Insignia circular en vez del rombo suelto: le da peso al primer
   impacto visual sin depender de ningún nombre de marca (ver nota en
   index.html — esta tarjeta la comparten dueño y gestores). */
.auth-card .brand .mark{
  display:flex; align-items:center; justify-content:center;
  width:54px; height:54px; border-radius:50%; font-size:22px;
  background:radial-gradient(circle at 35% 30%, rgba(240,211,143,0.3), rgba(201,162,78,0.05) 72%);
  border:1px solid rgba(201,162,78,0.4);
  box-shadow:0 0 0 6px rgba(201,162,78,0.06), 0 10px 22px rgba(0,0,0,0.35);
  /* .brand .mark (arriba) usa background-clip:text para pintar el rombo
     con el degradado dorado como si fuera texto — aquí el fondo es el
     círculo, así que hay que anular ese recorte o el círculo desaparece
     y el rombo queda casi transparente. */
  -webkit-background-clip:border-box; background-clip:border-box;
  color:var(--gold);
}
.auth-card .brand h1{font-size:20px; font-family:var(--font-display); font-weight:600; letter-spacing:.01em;}
.auth-tabs{display:flex; border:1px solid var(--line); border-radius:10px; overflow:hidden; margin-bottom:22px; background:var(--bg-2);}
.auth-tab{flex:1; text-align:center; padding:10px 6px; font-size:12.5px; color:var(--muted); cursor:pointer; transition:var(--dur-base);}
.auth-tab.active{background:var(--panel-2); color:var(--gold); font-weight:600; box-shadow:inset 0 0 0 1px rgba(201,162,78,0.22);}
.auth-msg{font-size:12.5px; padding:9px 11px; border-radius:8px; margin-bottom:14px; display:none; line-height:1.4;}
.auth-card .field input{padding:10px 12px; font-size:14px;}
/* Entrada suave al cambiar entre login/registro/2FA/dispositivo — se
   retriggerea sola cada vez que el panel pasa de display:none a block. */
#authPaneLogin, #authPaneRegister, #authPaneMfa, #authPaneDevice{animation:authFadeIn .28s var(--ease);}
@keyframes authFadeIn{from{opacity:0; transform:translateY(5px);} to{opacity:1; transform:translateY(0);}}

/* ---------- Panel dedicado del rol admin (candado de navegador) ---------- */
#adminApp{display:none; min-height:100vh; min-height:100dvh; background:var(--bg); padding:calc(30px + var(--safe-top)) 20px calc(30px + env(safe-area-inset-bottom));}
.admin-wrap{max-width:640px; margin:0 auto;}
.admin-wrap .brand{margin-bottom:4px;}

/* ---- Rediseño panel admin (más intuitivo: cabecera + resumen + pestañas) ---- */
.admin-header{display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;}
.admin-header .brand{margin-bottom:0;}

.admin-stat-grid{display:grid; grid-template-columns:repeat(3, 1fr); gap:12px; margin-bottom:20px;}
@media (max-width:560px){ .admin-stat-grid{grid-template-columns:1fr 1fr;} }

.admin-tabs{
  display:flex; gap:6px; border:1px solid var(--line); border-radius:11px;
  padding:4px; margin-bottom:22px; background:var(--bg-2);
}
.admin-tab{
  flex:1; display:flex; align-items:center; justify-content:center; gap:6px;
  text-align:center; padding:10px 8px; font-size:13px; color:var(--muted);
  border-radius:8px; cursor:pointer; transition:var(--dur-base); font-weight:500;
}
.admin-tab:hover{color:var(--text);}
.admin-tab.active{background:var(--panel-2); color:var(--gold); box-shadow:0 1px 0 var(--gold-dim) inset;}
.admin-tab .tab-badge{
  background:var(--loss); color:#fff; font-size:10.5px; font-weight:700;
  border-radius:10px; padding:1px 6px; line-height:1.5; min-width:16px;
}

.admin-pane{animation:adminFade .15s ease;}
@keyframes adminFade{from{opacity:0; transform:translateY(2px);} to{opacity:1; transform:none;}}

.admin-collapse{
  border:1px solid var(--line); border-radius:var(--radius); margin-top:14px;
  background:var(--panel); overflow:hidden;
}
.admin-collapse summary{
  list-style:none; cursor:pointer; padding:14px 16px; font-size:14.5px; font-weight:600;
  display:flex; align-items:center; justify-content:space-between; color:var(--text);
}
.admin-collapse summary::-webkit-details-marker{display:none;}
.admin-collapse .admin-collapse-arrow{color:var(--muted-2); transition:transform var(--dur-base);}
.admin-collapse[open] .admin-collapse-arrow{transform:rotate(180deg);}
.admin-collapse-body{padding:0 16px 16px;}
.admin-collapse summary:hover{color:var(--gold);}

/* Caja de "Solicitudes de corrección pendientes": dos estados según
   si hay algo que revisar o no, para que solo ocupe sitio y llame la
   atención cuando de verdad hace falta.
   - .has-pending: se convierte en una alerta visible (borde y fondo
     en tono de aviso), con la descripción larga y la lista completa.
   - .quiet: no hay nada pendiente — se reduce a una línea pequeña y
     discreta (sin borde, sin descripción larga, sin caja de "vacío"
     grande), solo el título y el botón de refrescar.
   Nunca deja de estar ahí ni hay que desplegar nada para verla: el
   propio JS decide qué clase aplicar cada vez que recarga los datos. */
.admin-alert-box{ border-radius:var(--radius); margin:26px 0 0; padding:16px; transition:var(--dur-base); }
.admin-alert-box.has-pending{
  border:1px solid rgba(226,88,79,0.35);
  background:linear-gradient(180deg, var(--loss-dim), var(--panel) 65%);
}
.admin-alert-box.quiet{ padding:2px 0 0; }
.admin-alert-box.quiet .admin-solicitudes-desc{ display:none; }
.admin-alert-box.quiet .section-title{ margin-bottom:2px; }
.admin-alert-box.quiet #adminSolicitudesPendientes .empty{
  border:none; padding:0; text-align:left; font-size:11.5px; color:var(--muted-2);
}
#adminDeviceList .alert-card{align-items:flex-start; flex-wrap:wrap;}
#adminDeviceList .field{margin-bottom:0; min-width:160px;}
#adminDeviceList .field input{text-transform:uppercase; letter-spacing:2px; font-family:var(--font-mono);}
.auth-msg.show{display:block;}
.auth-msg.err{background:var(--loss-dim); color:var(--loss-text); border:1px solid var(--loss);}
.auth-msg.ok{background:var(--gain-dim); color:var(--gain-text); border:1px solid var(--gain);}
.auth-sub{font-size:12px; color:var(--muted-2); text-align:center; margin-top:14px; line-height:1.5;}
.auth-sub a{color:var(--gold); cursor:pointer; text-decoration:underline;}
#authNoBackend{font-size:11.5px; color:var(--muted-2); text-align:center; margin-top:16px; border-top:1px dashed var(--line); padding-top:14px;}

/* ---------- Fase C: vista Seguridad / 2FA ---------- */
.sec-card{background:var(--panel); border:1px solid var(--line); border-radius:var(--radius); padding:20px; max-width:480px; margin-bottom:16px;}
.sec-card h3{font-size:14.5px; margin-bottom:4px;}
.sec-card .sub{font-size:12.5px; color:var(--muted-2); margin-bottom:14px;}
.sec-row{display:flex; justify-content:space-between; align-items:center; padding:10px 0; border-bottom:1px solid var(--line-soft);}
.sec-row:last-child{border-bottom:none;}
.pill{font-size:11px; padding:3px 9px; border-radius:20px; font-weight:600;}
.pill.on{background:var(--gain-dim); color:var(--gain-text);}
.pill.off{background:var(--panel-2); color:var(--muted-2);}
.mfa-qr{background:#fff; padding:10px; border-radius:8px; display:inline-block; margin:12px 0;}
.mfa-qr svg{display:block; width:170px; height:170px;}
.mfa-secret{font-family:var(--font-mono); font-size:12px; color:var(--muted); background:var(--bg-2); border:1px solid var(--line); border-radius:6px; padding:8px 10px; word-break:break-all; margin-bottom:14px;}

/* ---------- Fase E: interruptor modo edición / modo uso ---------- */
.edit-toggle{
  display:flex; align-items:center; justify-content:space-between; gap:8px;
  padding:9px 11px; margin:0 4px 10px; border:1px solid var(--line); border-radius:9px;
  font-size:12px; color:var(--muted); cursor:pointer; background:var(--panel); user-select:none;
}
.edit-toggle:hover{border-color:var(--muted-2); color:var(--text);}
.edit-toggle.on{border-color:var(--gold); color:var(--gold);}
.switch{width:34px; height:19px; border-radius:20px; background:var(--panel-2); border:1px solid var(--line); position:relative; flex-shrink:0; transition:var(--dur-base);}
.switch .knob{position:absolute; top:1px; left:1px; width:15px; height:15px; border-radius:50%; background:var(--muted-2); transition:var(--dur-base);}
.switch.on{background:var(--gold-dim); border-color:var(--gold);}
.switch.on .knob{left:16px; background:var(--gold);}
.edit-hint{font-size:11.5px; color:var(--muted-2); padding:2px 6px 10px; line-height:1.5;}
.field.locked input{color:var(--muted); background:var(--bg-2); border-style:dashed; cursor:not-allowed;}

/* ---------- accesibilidad: respeta "reducir movimiento" ---------- */
@media (prefers-reduced-motion: reduce){
  *{animation-duration:0.001ms !important; animation-iteration-count:1 !important; transition-duration:0.001ms !important;}
}

/* ---------- Portal del gestor/administrativo (rol 'consultant') ----------
   Reutiliza .stat-card, .log-table, .btn, .section-title y .empty ya
   definidos arriba, para que visualmente encaje con el resto de la app. */
#staffApp{
  min-height:100vh; background:var(--bg); color:var(--text);
  /* Antes tenía padding-top fijo (28px) sin contar la barra de
     notificaciones/notch — era el único wrapper de pantalla completa
     (junto a #adminApp y #authScreen, que ya lo tenían bien) que se
     olvidaba de var(--safe-top), así que en modo standalone
     de iPhone el título quedaba pegado o tapado por el notch. */
  padding:calc(28px + var(--safe-top)) 20px 60px; max-width:820px; margin:0 auto;
}
.staff-topbar{
  display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:10px;
  margin-bottom:22px; padding-bottom:14px; border-bottom:1px solid var(--line);
}
.staff-title{
  font-family:var(--font-display); font-weight:600; font-size:19px; color:var(--text);
}
.staff-company{font-size:11px; color:var(--gold); text-transform:uppercase; letter-spacing:.08em; font-family:var(--font-mono); margin-bottom:2px;}
.staff-sub{font-size:12.5px; color:var(--muted-2); margin-top:3px; text-transform:capitalize;}
#staffApp .stat-grid{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
  gap:14px; margin-bottom:26px;
}
.staff-progress{height:5px; border-radius:4px; background:var(--panel-2); margin-top:9px; overflow:hidden;}
.staff-progress-fill{height:100%; background:var(--grad-gain); border-radius:4px; transition:width var(--dur-med);}
.staff-announce{
  background:var(--gold-dim); border:1px solid rgba(201,162,78,0.35); color:var(--gold);
  border-radius:9px; padding:10px 14px; font-size:12.5px; margin-bottom:18px; line-height:1.5;
}
.staff-clock{
  display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap;
}
.staff-clock-left .sub{margin-bottom:2px;}
.staff-live-timer{
  font-family:var(--font-mono); font-size:26px; font-weight:600; color:var(--gain);
  letter-spacing:0.02em; margin:4px 0 2px;
}
.staff-info-row{display:flex; gap:14px; flex-wrap:wrap; margin-bottom:22px;}
.staff-info-row .sec-card{margin-bottom:0;}

/* Calendario visual de fichajes (fcal-*) */
.fcal{
  background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
  padding:16px; margin-bottom:16px;
}
.fcal-head{display:flex; align-items:center; justify-content:space-between; margin-bottom:12px; flex-wrap:wrap; gap:8px;}
.fcal-title{font-family:var(--font-display); font-size:14px; font-weight:600; text-transform:capitalize; color:var(--text);}
.fcal-legend{display:flex; align-items:center; gap:4px; font-size:10.5px; color:var(--muted-2); font-family:var(--font-mono);}
.fcal-swatch{width:11px; height:11px; border-radius:3px; display:inline-block;}
.fcal-grid{display:grid; grid-template-columns:repeat(7, 1fr); gap:5px;}
.fcal-dow{margin-bottom:5px;}
.fcal-dow-cell{font-size:10px; text-align:center; color:var(--muted-2); font-family:var(--font-mono); text-transform:uppercase; letter-spacing:.04em;}
.fcal-cell{
  position:relative; aspect-ratio:1/1; border-radius:7px; border:1px solid var(--line-soft);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px;
  background:var(--bg-2);
}
.fcal-cell.fcal-admin{aspect-ratio:auto; min-height:56px;}
.fcal-empty{border:none; background:transparent;}
.fcal-daynum{font-size:10.5px; color:var(--muted-2); font-family:var(--font-mono); position:absolute; top:3px; left:5px;}
.fcal-hours{font-size:11px; font-weight:600; color:var(--text); font-family:var(--font-mono);}
.fcal-weekend .fcal-daynum{color:var(--muted-2); opacity:.7;}
/* Fin de semana sin fichajes (Mejora, 29/07/26): fondo tenue para
   distinguirlo de un día laborable vacío — normalmente no se trabaja
   findes, pero no es una ausencia como un cierre o una vacación, así
   que el tono es mucho más discreto. Selector de dos clases a
   propósito: solo tiene que ganarle a .fcal-lvl0 (mismo nivel de
   especificidad que un selector de una clase + una clase, sin usar
   !important), no a los niveles con horas trabajadas (fcal-lvl1-4),
   que deben seguir viéndose en verde si alguna vez se trabaja un finde.*/
.fcal-lvl0.fcal-weekend{background:rgba(148,163,184,0.1); border-color:rgba(148,163,184,0.18);}
.fcal-today{border-color:var(--gold); box-shadow:0 0 0 1px var(--gold) inset;}
.fcal-clickable{cursor:pointer; transition:transform var(--dur-fast);}
.fcal-clickable:hover{transform:translateY(-1px); border-color:var(--muted-2);}
.fcal-open .fcal-dot{
  position:absolute; top:4px; right:5px; width:6px; height:6px; border-radius:50%;
  background:var(--gain); box-shadow:0 0 0 2px var(--gain-dim);
  animation:fcal-pulse 1.6s ease-in-out infinite;
}
@keyframes fcal-pulse{0%,100%{opacity:1;} 50%{opacity:.35;}}
.fcal-lvl0{background:var(--bg-2);}
.fcal-lvl1{background:var(--gain-dim); border-color:rgba(62,207,142,0.18);}
.fcal-lvl2{background:rgba(62,207,142,0.22); border-color:rgba(62,207,142,0.3);}
.fcal-lvl3{background:rgba(62,207,142,0.38); border-color:rgba(62,207,142,0.45);}
.fcal-lvl4{background:rgba(62,207,142,0.6); border-color:var(--gain);}
.fcal-lvl3 .fcal-hours, .fcal-lvl4 .fcal-hours{color:var(--on-gain-bright);}
.fcal-lvl3 .fcal-daynum, .fcal-lvl4 .fcal-daynum{color:rgba(11,31,22,0.65);}

/* Días de vacaciones (Mejora): fondo distinto según estado (aprobada
   / pendiente), para que se note de un vistazo en el calendario en
   vez de parecer un día cualquiera sin fichar. Se superpone al color
   normal de "nivel de horas" — !important porque en la práctica casi
   nunca hay horas fichadas ese día, pero si las hubiera (medio día
   trabajado + medio de vacaciones) que siga ganando el aviso de
   vacaciones, que es la información más relevante ese día. */
.fcal-vacation-aprobada{background:rgba(62,207,142,0.3) !important; border-color:rgba(62,207,142,0.45) !important;}
.fcal-vacation-pendiente{background:rgba(201,162,78,0.24) !important; border-color:rgba(201,162,78,0.4) !important;}
.fcal-vacation-icon{font-size:13px;}

/* Día cerrado por la empresa (Mejora, 29/07/26): el admin lo marca
   con el botón ✕ del calendario (ver .fcal-btn-close más abajo) — sin
   motivo, solo la fecha. Máxima prioridad visual (!important, mismo
   criterio que las vacaciones): en la práctica nunca hay fichajes ese
   día porque staffClockIn lo bloquea, pero si los hubiera (p.ej. un
   día cerrado a posteriori que ya tenía fichaje) que siga ganando el
   aviso de cierre, que es la información más relevante. Toda la
   celda se pone en rojo y se sustituye lo que hubiera dentro (horas,
   🏖, marca de admin...) por una única ✕ grande — no un simple punto
   o badge — para que se note de un vistazo incluso en la miniatura
   del calendario. */
.fcal-closed{background:rgba(226,88,79,0.22) !important; border-color:rgba(226,88,79,0.5) !important;}
.fcal-closed .fcal-daynum{color:var(--loss); opacity:.9;}
.fcal-closed-mark{font-size:20px; line-height:1; color:var(--loss); font-weight:700;}
@media (max-width: 520px){
  .fcal-closed-mark{font-size:16px;}
}

/* Botón admin para abrir/cerrar un día entero de la empresa. Vive
   dentro de .fcal-actions (mismo sitio que ＋/✎/🗑), así que hereda el
   tamaño de .fcal-btn — solo cambia de color para que ✕ (cerrar)
   resalte en rojo desde el principio, y ↺ (reabrir) quede marcado en
   rojo relleno mientras el día siga cerrado. */
.fcal-btn-close{color:var(--loss); border-color:rgba(226,88,79,0.35);}
.fcal-btn-close:hover{background:var(--loss-dim); border-color:var(--loss);}
.fcal-btn-close.is-closed{background:var(--loss-dim); border-color:var(--loss);}

@media (max-width: 520px){
  .fcal-hours{font-size:9.5px;}
  .fcal-daynum{font-size:9px;}
}

.fcal-nav{display:flex; align-items:center; gap:6px;}
.fcal-nav-btn{
  position:relative;
  background:var(--panel-2); border:1px solid var(--line); color:var(--muted);
  font-size:13px; line-height:1; border-radius:6px; padding:4px 9px; cursor:pointer;
  font-family:var(--font-mono);
}
.fcal-nav-btn:hover:not(:disabled){border-color:var(--gold); color:var(--gold);}
.fcal-nav-btn:disabled{opacity:.3; cursor:default;}
.fcal-nav-dot{
  position:absolute; top:-3px; right:-3px; width:7px; height:7px; border-radius:50%;
  background:var(--loss); box-shadow:0 0 0 2px var(--panel);
}

/* Aviso de "algo pendiente de que el admin lo revise" (corrección de
   fichaje o vacaciones) en el propio día del calendario del gestor.
   Puramente informativo — no es clicable ni editable desde aquí. */
.fcal-aviso-mark{
  position:absolute; top:3px; right:5px; width:13px; height:13px; border-radius:50%;
  background:var(--loss-dim); color:var(--loss); border:1px solid rgba(226,88,79,0.5);
  font-size:9px; font-weight:700; line-height:11px; text-align:center; font-family:var(--font-mono);
}

.fcal-actions{
  position:absolute; bottom:3px; left:0; right:0;
  display:flex; align-items:center; justify-content:center; gap:4px;
}
.fcal-btn{
  background:var(--panel-2); border:1px solid var(--line); color:var(--muted);
  font-size:10px; line-height:1; border-radius:5px; padding:3px 5px; cursor:pointer;
}
.fcal-btn:hover{border-color:var(--gold); color:var(--gold);}
.fcal-btn-add{color:var(--gain); border-color:rgba(62,207,142,0.35);}
.fcal-btn-add:hover{background:var(--gain-dim);}
.fcal-btn-del:hover{border-color:var(--loss); color:var(--loss);}

/* Marca "A" (relleno por admin) — SOLO se pinta cuando el calendario
   se renderiza con adminMode:true (panel admin). El propio gestor
   nunca recibe esta clase en su portal, así que su vista es idéntica
   tenga el día el origen que tenga. */
.fcal-admin-mark{
  position:absolute; top:3px; right:5px; width:13px; height:13px; border-radius:50%;
  background:var(--gold-dim); color:var(--gold); border:1px solid rgba(201,162,78,0.5);
  font-size:9px; font-weight:700; line-height:11px; text-align:center; font-family:var(--font-mono);
}

/* ================================================================
   MEJORA (punto 8): selector visual en tarjetas/pills para el modal
   "Editar gestor" (modo de cálculo, campo de origen del sueldo, cómo
   se usa ese valor) — sustituye a los <select> planos de textos
   largos, que había que leer entero para saber qué opción era cada
   una. Los <select> reales siguen en el HTML (ocultos), esto es solo
   la capa visual de encima; ver staffEditSyncCardSelectors() en app.js.
   ================================================================ */
.card-select-grid{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(160px,1fr)); gap:8px; margin-top:2px;
}
.card-select-option{
  display:flex; flex-direction:column; gap:3px; text-align:left; cursor:pointer;
  background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
  padding:10px 12px; transition:border-color var(--dur-base), background var(--dur-base);
}
.card-select-option:hover{border-color:var(--muted-2);}
.card-select-option .cso-title{display:flex; align-items:center; gap:6px; font-size:12.5px; font-weight:600; color:var(--text);}
.card-select-option .cso-sub{font-size:10.5px; color:var(--muted-2); line-height:1.4; margin-top:1px;}
.card-select-option.active{border-color:var(--gold); background:linear-gradient(180deg, rgba(201,162,78,0.10), var(--panel) 75%);}
.card-select-option.active .cso-title{color:var(--gold);}

/* Versión en lista vertical (para opciones con más texto, como el
   "campo de origen del sueldo") — misma tarjeta, pero en fila, con
   el icono+título a la izquierda y el subtítulo alineado a la derecha
   del título en vez de debajo. */
.card-select-list{display:flex; flex-direction:column; gap:6px; margin-top:2px;}
.card-select-list .card-select-option{flex-direction:row; align-items:center; padding:9px 12px;}
.card-select-list .cso-sub{margin-top:0;}

/* Segmented control de 2 opciones ("Tal cual" / "Un %") */
.pill-toggle{display:flex; border:1px solid var(--line); border-radius:999px; overflow:hidden; width:fit-content; margin-top:2px;}
.pill-toggle .pill-option{padding:7px 16px; font-size:12px; cursor:pointer; color:var(--muted-2); background:var(--panel); white-space:nowrap;}
.pill-toggle .pill-option:not(:last-child){border-right:1px solid var(--line);}
.pill-toggle .pill-option:hover{color:var(--text);}
.pill-toggle .pill-option.active{background:var(--gold); color:var(--on-gold); font-weight:600;}

/* ---------- Gestor Bitrefill & Crypto ---------- */
.br-sim-result{margin-top:14px;}
.br-sim-bar-track{height:8px; border-radius:999px; background:var(--panel-2); overflow:hidden; margin-bottom:12px;}
.br-sim-bar-fill{height:100%; background:linear-gradient(90deg, var(--gold), var(--gain)); transition:width var(--dur-slow) ease;}
.br-sim-row{display:flex; justify-content:space-between; align-items:center; padding:6px 0; font-size:13.5px; border-bottom:1px solid var(--line);}
.br-sim-row:last-child{border-bottom:none;}
.br-sim-row.highlight b{color:var(--gain); font-size:16px;}
.br-sim-row.loss b{color:var(--loss);}

.br-filters{display:flex; gap:8px; flex-wrap:wrap; margin-bottom:14px;}
.br-filter-btn.active{background:var(--gold); color:var(--on-gold); border-color:var(--gold); font-weight:600;}

.br-cards-grid{display:grid; grid-template-columns:repeat(auto-fill, minmax(220px, 1fr)); gap:14px;}
/* min-width:0 hace falta porque dentro de grid/flex los hijos no
   encogen por debajo de su contenido por defecto (min-width:auto) —
   sin esto, un nombre de tienda o un código largo empuja la tarjeta
   entera y se sale del grid en vez de hacer wrap. */
.br-card{border:1px solid var(--line); border-radius:12px; background:var(--panel); padding:12px; display:flex; flex-direction:column; gap:10px; min-width:0;}
.br-card.caduca-pronto{border-color:var(--gold); box-shadow:0 0 0 1px rgba(201,162,78,0.35);}
.br-card.caducada{border-color:var(--loss); box-shadow:0 0 0 1px rgba(226,88,79,0.4);}
.br-card-top{display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:6px;}
.br-card-actions{display:flex; gap:4px; flex:none;}
.br-card-preview{height:110px; border-radius:8px; background:var(--panel-2); display:flex; align-items:center; justify-content:center; overflow:hidden;}
.br-card-preview img{width:100%; height:100%; object-fit:cover;}
.br-pdf-link{color:var(--gold); font-size:13px; text-decoration:none;}
.br-card-body{display:flex; flex-direction:column; gap:4px; min-width:0;}
.br-card-tienda{font-weight:600; font-size:15px; overflow-wrap:anywhere;}
.br-card-saldo{font-size:13px; color:var(--muted-2); overflow-wrap:anywhere;}
.br-card-codigo{display:flex; justify-content:space-between; align-items:center; gap:8px; background:var(--panel-2); border:1px dashed var(--line); border-radius:8px; padding:6px 10px; font-family:monospace; font-size:13px; cursor:pointer; margin-top:4px;}
.br-card-codigo span{overflow-wrap:anywhere; min-width:0;}
.br-card-codigo i{flex:none;}
.br-card-codigo:hover{border-color:var(--gold);}
@media (max-width:420px){ .br-cards-grid{grid-template-columns:1fr 1fr;} }

/* Modificador nuevo para el sistema de skeleton ya existente (ver arriba,
   ~línea 886: .skel/.skel-topbar/.skel-tabs/.skel-card/.skel-row) — línea
   de texto placeholder, para listas cortas (ej. historial de movimientos
   de Bitrefill) donde una .skel-card entera (88px) sería demasiado alta.
   Uso: <div class="skel skel-line" style="width:70%"></div> */
.skel-line{ height:12px; border-radius:5px; margin-bottom:8px; }

/* ================================================================
   MEJORA (repaso mobile general): breakpoints que faltaban.
   Todo lo de aquí abajo va DESPUÉS a propósito, para ganar la cascada
   sobre las reglas grid-template-columns definidas más arriba en el
   archivo (misma especificidad → gana la que está más abajo).
   ================================================================ */

/* Tarjetas de cuentas (.grid): con 1 sola columna forzada en pantallas
   muy estrechas no dependemos de que el minmax(270px,1fr) siga
   cabiendo por los pelos en un iPhone SE (320px de ancho). */
@media (max-width:400px){
  .grid{grid-template-columns:1fr;}
  .br-cards-grid{grid-template-columns:1fr;}
}

/* Filas de 2 campos (.field-row): en vez de apretujar 2 inputs uno
   junto al otro en 300px de ancho, se apilan en columna — mismo
   patrón que ya usa el resto de la app (p.ej. .meta-row en 480px). */
@media (max-width:480px){
  .field-row{flex-wrap:wrap;}
  .field-row .field{flex:1 1 100%; min-width:0;}
}

/* Constructor de fases (.day-row): las 3 columnas de números fijas
   (78/84/84px) son las primeras en pantalla completa, pero en un
   móvil estrecho sobran — se reparten a partes iguales (1fr cada
   una) para que quepan sin que el input tenga que encogerse más
   de lo legible. */
@media (max-width:480px){
  .day-row{grid-template-columns:16px 1fr 1fr 1fr 22px; gap:4px;}
  .day-row input{font-size:11.5px; padding:6px 4px;}
}

/* Panel de ajuste manual (.adjust-grid, 3 columnas fijas) y simulador
   (.sim-grid) — 2 y 1 columna respectivamente en pantalla pequeña. */
@media (max-width:480px){
  .adjust-grid{grid-template-columns:1fr 1fr;}
}
@media (max-width:400px){
  .sim-grid{grid-template-columns:1fr;}
}

/* Reparto de metas (.reparto-row): el input de importe fijo en
   110px no deja sitio a la etiqueta en pantallas muy estrechas. */
@media (max-width:380px){
  .reparto-row{flex-wrap:wrap;}
  .reparto-input{width:90px;}
}

/* Modal/overlay: el padding superior fijo de 40px sobra en un móvil
   con poca altura de viewport visible (teclado, barra de URL...);
   se reduce y se recorta el padding lateral del modal para dejar más
   aire al contenido real en pantallas estrechas.
   IMPORTANTE: se suma var(--safe-top) al padding — si no,
   en modo standalone (pantalla completa) en iPhone el título y el
   botón "✕" del modal quedan pegados o tapados por la barra de
   notificaciones/notch, porque los 20px fijos no la tienen en cuenta. */
@media (max-width:480px){
  .overlay{padding:calc(20px + var(--safe-top)) 10px calc(20px + env(safe-area-inset-bottom));}
  .modal{padding:18px 16px 20px;}
  .modal-actions{flex-wrap:wrap;}
}

/* ================================================================
   Vista Stakeholder/Demo — MODO EDICIÓN (03/08/26, scenario.js)
   ------------------------------------------------------------------
   Solo se pinta cuando stakeholderEditMode es true (dueño
   previsualizando/editando un link concreto). Un stakeholder real
   nunca ve estas clases porque nunca pone esa variable a true.
   ================================================================ */

.so-editable-el{
  outline: 1px dashed transparent;
  outline-offset: 2px;
  transition: outline-color .15s ease, opacity .15s ease, filter .15s ease;
}
.so-editable-el:hover{ outline-color: rgba(245,166,35,.55); }

.so-hidden-preview{
  opacity: .32;
  filter: grayscale(.6);
}

.so-x-btn{
  position: absolute;
  top: -9px;
  right: -9px;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid var(--bg, #1a1a1a);
  background: #e5484d;
  color: #fff;
  font-size: 12px;
  line-height: 1;
  font-weight: 700;
  cursor: pointer;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  box-shadow: 0 1px 4px rgba(0,0,0,.4);
}
.so-x-btn:hover{ transform: scale(1.1); }

/* Caso especial <tr>: la ❌ va dentro de su propia celda al principio
   de la fila (un <tr> no admite un botón suelto como hijo directo). */
td.so-x-cell{
  width: 34px;
  text-align: center;
  padding: 4px !important;
}
td.so-x-cell .so-x-btn{
  position: static;
  margin: 0 auto;
}

#stakeholderEditBanner{
  position: sticky;
  top: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
  background: #2b6cb0;
  color: #fff;
  font-weight: 600;
  font-size: .85rem;
  text-align: center;
  padding: 8px 14px;
}
#stakeholderEditBanner button{
  background: #fff;
  color: #2b6cb0;
  border: none;
  border-radius: 6px;
  padding: 4px 12px;
  font-weight: 700;
  font-size: .8rem;
  cursor: pointer;
}
#stakeholderEditBanner button:hover{ opacity: .85; }

/* Selector genérico "marca lo que quieras" (04/08/26, scenario.js) */
body.so-picker-active{ cursor: crosshair; }
body.so-picker-active *:hover{ outline: 2px solid #f5a623 !important; outline-offset: 1px; }

.so-popover{
  position: fixed;
  z-index: 2000;
  background: #1f1f1f;
  border: 1px solid rgba(255,255,255,.15);
  border-radius: 10px;
  padding: 12px;
  width: 260px;
  box-shadow: 0 8px 24px rgba(0,0,0,.5);
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: .82rem;
  color: #eee;
}
.so-pop-title{ font-weight: 700; }
.so-pop-current{ opacity: .7; font-size: .75rem; word-break: break-word; }
.so-pop-label{ display:flex; flex-direction:column; gap:4px; font-size:.75rem; opacity:.85; }
.so-pop-label input{
  background:#111; border:1px solid rgba(255,255,255,.15); border-radius:6px;
  color:#fff; padding:5px 7px; font-size:.82rem;
}
.so-pop-check{ display:flex; align-items:center; gap:6px; font-size:.72rem; opacity:.85; }
.so-popover button{
  background:#2b6cb0; color:#fff; border:none; border-radius:6px;
  padding:6px 8px; font-size:.78rem; font-weight:600; cursor:pointer;
}
.so-popover .so-pop-hide{ background:#e5484d; }
.so-popover .so-pop-close{ background:transparent; color:#aaa; text-decoration:underline; padding:2px; }

.so-value-overridden{ text-decoration: underline dotted; text-decoration-color: #f5a623; }
