/* ==========================================================================
   fs-componentes.css · Librería de componentes base del rediseño (2026-11-08)
   Fuente: docs/diseno/Manual de marca.dc.html §09 + CRM Prototipo.dc.html.
   Prefijo fs- (convive con Tailwind sin choques). Solo usa tokens de
   assets/fuerza-tokens.css: funciona igual en claro y en Noche.
   JS (vanilla, opcional salvo donde se indica): assets/fs-ui.js.
   Se carga en app_head() DESPUÉS de tailwind.css (gana al plugin forms).
   Reglas: objetivo táctil ≥ 44 px · solo transform/opacity en movimiento ·
   ningún estado depende solo del color (ícono o texto siempre).
   ========================================================================== */

/* Caja: las páginas del CRM ya traen el preflight de Tailwind; esto cubre
   los usos fuera de él (páginas públicas, láminas). */
:where([class^="fs-"], [class*=" fs-"]) { box-sizing: border-box; }

/* ── Botón ─────────────────────────────────────────────────────────────────
   <button class="fs-btn fs-btn--accion">Ingresar</button>
   Variantes: --accion (UNA por vista) · --secundario (por defecto) ·
   --fantasma · --borde · --peligro · --inverso. Tamaños: --sm (40) · --lg (56)
   · --icono (cuadrado) · --bloque (ancho completo). Cargando: fsBtnCargando(btn, true). */
.fs-btn {
  --fs-btn-bg: var(--c-superficie-alta); --fs-btn-fg: var(--c-texto); --fs-btn-bg-h: var(--c-neutro-300);
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 48px; min-height: var(--toque); padding: 0 18px; border: 0; border-radius: var(--radius-md);
  background: var(--fs-btn-bg); color: var(--fs-btn-fg);
  font: 700 15px/1 var(--font-ui); letter-spacing: 0; white-space: nowrap; text-decoration: none; cursor: pointer;
  -webkit-tap-highlight-color: transparent; user-select: none;
  transition: transform var(--dur-instante) var(--ease-salida), background-color var(--dur-rapida) ease, color var(--dur-rapida) ease, box-shadow var(--dur-rapida) ease;
}
.fs-btn .material-symbols-outlined, .fs-btn .im-ico { font-size: 20px; width: 20px; height: 20px; }
.fs-btn:active:not(:disabled):not([aria-disabled="true"]) { transform: scale(var(--escala-presion)); }
@media (hover: hover) and (pointer: fine) { .fs-btn:hover:not(:disabled):not([aria-disabled="true"]) { background: var(--fs-btn-bg-h); } }
.fs-btn:disabled, .fs-btn[aria-disabled="true"] { --fs-btn-bg: var(--c-superficie-alta); --fs-btn-fg: var(--c-texto-3); cursor: not-allowed; opacity: .7; }
.fs-btn--accion { --fs-btn-bg: var(--c-accion); --fs-btn-fg: var(--c-sobre-accion); --fs-btn-bg-h: var(--c-accion-hover); }
.fs-btn--secundario { --fs-btn-bg: var(--c-superficie-alta); --fs-btn-fg: var(--c-texto); }
.fs-btn--fantasma { --fs-btn-bg: transparent; --fs-btn-fg: var(--c-accion); --fs-btn-bg-h: var(--c-accion-suave); padding: 0 14px; }
.fs-btn--borde { --fs-btn-bg: transparent; --fs-btn-fg: var(--c-texto); --fs-btn-bg-h: var(--c-superficie-alta); box-shadow: inset 0 0 0 1px var(--c-borde); }
.fs-btn--peligro { --fs-btn-bg: var(--c-error); --fs-btn-fg: var(--c-sobre-error); --fs-btn-bg-h: var(--c-error-hover); }
.fs-btn--inverso { --fs-btn-bg: var(--c-texto); --fs-btn-fg: var(--c-fondo); --fs-btn-bg-h: var(--c-neutro-800); }
.fs-btn--sm { height: 40px; padding: 0 14px; font-size: 14px; border-radius: var(--radius-md); }
.fs-btn--lg { height: 56px; padding: 0 22px; font-size: 17px; border-radius: 14px; }
.fs-btn--icono { width: 48px; padding: 0; }
.fs-btn--icono.fs-btn--sm { width: 40px; }
.fs-btn--bloque { display: flex; width: 100%; }
/* Cargando: el texto se vuelve transparente (el ancho NO cambia) y encima
   aparece el loader de marca. */
.fs-btn--cargando { color: transparent !important; pointer-events: none; }
.fs-btn--cargando > :not(.fs-btn-loader) { visibility: hidden; }
.fs-btn-loader { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: var(--fs-btn-fg); }
.fs-btn-loader .app-loader-marca { color: var(--fs-btn-fg); }
.fs-btn-loader .alm-cruz { stroke: currentColor; opacity: .35; }
@media (pointer: coarse) { .fs-btn--sm { height: var(--toque); } }

/* ── Campos ────────────────────────────────────────────────────────────────
   <label class="fs-campo"><span class="fs-etiqueta">DNI</span>
     <input class="fs-input" ...><span class="fs-ayuda">8 dígitos</span></label>
   Error: aria-invalid="true" en el control + <span class="fs-error">…</span>
   (con ícono) + fsTemblar(control). El error NUNCA borra lo escrito.
   Con ícono: <span class="fs-input-grupo"><span class="material-symbols-outlined">badge</span><input class="fs-input"></span> */
.fs-campo { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.fs-etiqueta { font: 700 14px/18px var(--font-ui); color: var(--c-texto); }
.fs-ayuda { font: 500 13px/18px var(--font-ui); color: var(--c-texto-2); }
.fs-error { display: flex; align-items: center; gap: 6px; font: 600 13.5px/18px var(--font-ui); color: var(--c-error); }
.fs-error .material-symbols-outlined { font-size: 17px; font-variation-settings: 'FILL' 1; }
.fs-input, .fs-select, .fs-textarea {
  width: 100%; min-height: 48px; padding: 0 14px; border: 0; border-radius: var(--radius-md);
  background-color: var(--c-superficie); color: var(--c-texto); font: 400 16px/22px var(--font-ui);
  box-shadow: inset 0 0 0 1.5px var(--c-borde-input); outline: none; appearance: none; -webkit-appearance: none;
  transition: box-shadow var(--dur-rapida) ease, background-color var(--dur-rapida) ease;
}
.fs-textarea { min-height: 96px; padding: 12px 14px; resize: vertical; }
.fs-select { padding-right: 40px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath fill='%2356635C' d='M480-361q-8 0-15-2.5t-13-8.5L268-556q-11-11-11-28t11-28q11-11 28-11t28 11l156 156 156-156q11-11 28-11t28 11q11 11 11 28t-11 28L508-372q-6 6-13 8.5t-15 2.5Z'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 22px; }
:root[data-tema="oscuro"] .fs-select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath fill='%239FB2A8' d='M480-361q-8 0-15-2.5t-13-8.5L268-556q-11-11-11-28t11-28q11-11 28-11t28 11l156 156 156-156q11-11 28-11t28 11q11 11 11 28t-11 28L508-372q-6 6-13 8.5t-15 2.5Z'/%3E%3C/svg%3E"); }
.fs-input::placeholder, .fs-textarea::placeholder { color: var(--c-texto-3); opacity: 1; }
.fs-input:hover, .fs-select:hover, .fs-textarea:hover { box-shadow: inset 0 0 0 1.5px var(--c-texto-3); }
.fs-input:focus, .fs-select:focus, .fs-textarea:focus { box-shadow: inset 0 0 0 2px var(--c-accion); }
.fs-input[aria-invalid="true"], .fs-select[aria-invalid="true"], .fs-textarea[aria-invalid="true"], .fs-input-grupo:has([aria-invalid="true"]) { box-shadow: inset 0 0 0 1.5px var(--c-error); }
.fs-input:disabled, .fs-select:disabled, .fs-textarea:disabled { background-color: var(--c-superficie-baja); color: var(--c-texto-3); cursor: not-allowed; box-shadow: inset 0 0 0 1px var(--c-borde); }
.fs-input-grupo { display: flex; align-items: center; gap: 10px; min-height: 48px; padding: 0 6px 0 14px; border-radius: 14px;
  background: var(--c-superficie); box-shadow: inset 0 0 0 1.5px var(--c-borde-input); transition: box-shadow var(--dur-rapida) ease; }
.fs-input-grupo:focus-within { box-shadow: inset 0 0 0 2px var(--c-accion); }
.fs-input-grupo > .material-symbols-outlined { font-size: 22px; color: var(--c-texto-3); }
.fs-input-grupo > .fs-input { flex: 1; min-width: 0; padding: 0; box-shadow: none !important; background: transparent; }

/* Temblor de error (manual: 3 ciclos, 320 ms, una vez). fsTemblar(el). */
@keyframes fs-temblor { 0%, 100% { transform: none; } 16% { transform: translateX(-6px); } 33% { transform: translateX(5px); } 50% { transform: translateX(-4px); } 66% { transform: translateX(3px); } 83% { transform: translateX(-1px); } }
@keyframes fs-temblor-rm { 0%, 100% { box-shadow: inset 0 0 0 1.5px var(--c-error); } 50% { box-shadow: inset 0 0 0 3px var(--c-error); } }
.fs-temblar { animation: fs-temblor 320ms var(--ease-salida) 1; }

/* ── Switch (toggle accesible) ─────────────────────────────────────────────
   <button type="button" class="fs-switch" role="switch" aria-checked="true" aria-label="Asistente IA"></button>
   Solo CSS para el dibujo (pista 52×32, perilla 26 con check / x: el estado
   se lee sin color). fs-ui.js alterna aria-checked al tocar y emite
   'fs:switch' {detail:{activo}} — data-fs-manual = la página lo controla. */
.fs-switch {
  --fs-sw-pista: var(--c-neutro-400); --fs-sw-perilla: #fff;
  --fs-sw-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath fill='%238F9892' d='M480-416 299-235q-14 14-32 14t-32-14q-14-14-14-32t14-32l181-181-181-181q-14-14-14-32t14-32q14-14 32-14t32 14l181 181 181-181q14-14 32-14t32 14q14 14 14 32t-14 32L544-480l181 181q14 14 14 32t-14 32q-14 14-32 14t-32-14L480-416Z'/%3E%3C/svg%3E");
  position: relative; flex-shrink: 0; width: 60px; height: var(--toque); padding: 0; border: 0; background: transparent; cursor: pointer;
  -webkit-tap-highlight-color: transparent; border-radius: var(--radius-full);
}
.fs-switch::before { content: ''; position: absolute; left: 4px; top: 6px; width: 52px; height: 32px; border-radius: var(--radius-full);
  background: var(--fs-sw-pista); transition: background-color var(--dur-base) ease; }
.fs-switch::after { content: ''; position: absolute; left: 7px; top: 9px; width: 26px; height: 26px; border-radius: var(--radius-full);
  background: var(--fs-sw-ico) center / 16px no-repeat, var(--fs-sw-perilla); box-shadow: 0 1px 3px rgba(0,0,0,.25);
  transition: transform 340ms var(--ease-rebote); }
.fs-switch[aria-checked="true"] {
  --fs-sw-pista: var(--c-accion);
  --fs-sw-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath fill='%2300784A' d='m382-354 339-339q12-12 28-12t28 12q12 12 12 28.5T777-636L410-268q-12 12-28 12t-28-12L182-440q-12-12-11.5-28.5T183-497q12-12 28.5-12t28.5 12l142 143Z'/%3E%3C/svg%3E");
}
.fs-switch[aria-checked="true"]::after { transform: translateX(20px); }
.fs-switch.fs-switch--aplasta::after { animation: fs-sw-aplasta 340ms var(--ease-salida); }
@keyframes fs-sw-aplasta { 35% { scale: 1.25 .85; } }
.fs-switch:disabled { cursor: not-allowed; opacity: .4; }
:root[data-tema="oscuro"] .fs-switch { --fs-sw-pista: var(--c-noche-500); --fs-sw-perilla: #7F948A;
  --fs-sw-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath fill='%2324302C' d='M480-416 299-235q-14 14-32 14t-32-14q-14-14-14-32t14-32l181-181-181-181q-14-14-14-32t14-32q14-14 32-14t32 14l181 181 181-181q14-14 32-14t32 14q14 14 14 32t-14 32L544-480l181 181q14 14 14 32t-14 32q-14 14-32 14t-32-14L480-416Z'/%3E%3C/svg%3E"); }
:root[data-tema="oscuro"] .fs-switch[aria-checked="true"] { --fs-sw-pista: var(--c-senal); --fs-sw-perilla: #04140D;
  --fs-sw-ico: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath fill='%233EE6A0' d='m382-354 339-339q12-12 28-12t28 12q12 12 12 28.5T777-636L410-268q-12 12-28 12t-28-12L182-440q-12-12-11.5-28.5T183-497q12-12 28.5-12t28.5 12l142 143Z'/%3E%3C/svg%3E"); }
/* Fila de ajuste: texto + switch, toda la fila cliqueable por el switch. */
.fs-ajuste { display: flex; align-items: center; gap: 12px; padding: 14px 0; box-shadow: inset 0 -1px 0 var(--c-borde); }
.fs-ajuste:last-child { box-shadow: none; }
.fs-ajuste-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.fs-ajuste-txt b { font: 700 15px/20px var(--font-ui); }
.fs-ajuste-txt span { font: 400 13.5px/19px var(--font-ui); color: var(--c-texto-2); }

/* ── Chips de estado, píldoras de filtro e insignias ───────────────────────
   <span class="fs-chip fs-chip--agendado"><span class="material-symbols-outlined">event</span>Agendado</span>
   Estados: --nuevo --cotizado --agendado --cerrado --sin-respuesta --ia
   --neutro --logro. Ícono + texto + color (se entienden en escala de grises).
   Filtro: <button class="fs-pill" aria-pressed="true">Todas <span class="fs-pill-n">12</span></button> */
.fs-chip { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 12px; border-radius: var(--radius-full);
  background: var(--c-superficie-alta); color: var(--c-texto); font: 700 13.5px/1 var(--font-ui); white-space: nowrap; }
.fs-chip .material-symbols-outlined, .fs-chip .im-ico { font-size: 17px; width: 17px; height: 17px; font-variation-settings: 'FILL' 1; }
.fs-chip--sm { height: 24px; padding: 0 8px; font-size: 12px; gap: 4px; }
.fs-chip--sm .material-symbols-outlined { font-size: 14px; }
.fs-chip--nuevo { background: var(--c-info-suave); color: var(--c-info); }
.fs-chip--cotizado { background: var(--c-alerta-suave); color: var(--c-alerta); }
.fs-chip--agendado, .fs-chip--cerrado, .fs-chip--ia { background: var(--c-accion-suave); color: var(--c-sobre-accion-suave); }
.fs-chip--sin-respuesta, .fs-chip--error { background: var(--c-error-suave); color: var(--c-error); }
.fs-chip--logro { background: var(--c-logro); color: var(--c-sobre-logro); }
.fs-chip--neutro { background: var(--c-superficie-baja); color: var(--c-texto-2); box-shadow: inset 0 0 0 1px var(--c-borde); }
.fs-pill { display: inline-flex; align-items: center; gap: 6px; height: 36px; padding: 0 14px; border: 0; border-radius: var(--radius-full);
  background: transparent; color: var(--c-texto-2); box-shadow: inset 0 0 0 1px var(--c-borde); font: 600 14px/1 var(--font-ui);
  cursor: pointer; white-space: nowrap; transition: background-color var(--dur-rapida) ease, color var(--dur-rapida) ease, transform var(--dur-instante) var(--ease-salida); }
.fs-pill:active { transform: scale(var(--escala-presion)); }
.fs-pill-n { color: var(--c-texto-3); font-variant-numeric: tabular-nums; }
.fs-pill[aria-pressed="true"], .fs-pill[aria-selected="true"] { background: var(--c-texto); color: var(--c-fondo); box-shadow: none; font-weight: 700; }
.fs-pill[aria-pressed="true"] .fs-pill-n, .fs-pill[aria-selected="true"] .fs-pill-n { color: inherit; opacity: .6; }
@media (pointer: coarse) { .fs-pill { min-height: var(--toque); } }
/* <span class="fs-badge">3</span> · --punto = "llegó algo nuevo" (chispa
   con anillo de 2.5 px; siempre acompañado de una cifra en otro lugar). */
.fs-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 22px; height: 22px; padding: 0 6px;
  border-radius: var(--radius-full); background: var(--c-accion); color: var(--c-sobre-accion); font: 700 12px/1 var(--font-ui);
  font-variant-numeric: tabular-nums; flex-shrink: 0; }
.fs-badge--logro { background: var(--c-logro); color: var(--c-sobre-logro); }
.fs-badge--neutro { background: var(--c-superficie); color: var(--c-texto); box-shadow: inset 0 0 0 1px var(--c-borde); }
.fs-badge--punto { min-width: 0; width: 10px; height: 10px; padding: 0; background: var(--c-chispa); box-shadow: 0 0 0 2.5px var(--c-superficie); }
.fs-badge--salta { animation: fs-salta 360ms var(--ease-rebote); }
@keyframes fs-salta { 40% { transform: scale(1.3); } }

/* ── Tarjeta y KPI ─────────────────────────────────────────────────────────
   <div class="fs-card">…</div> (--interactiva = reacciona al puntero; --plana = sin sombra)
   KPI: <div class="fs-card fs-kpi"><div class="fs-kpi-cab"><span class="fs-rotulo">Ventas del mes</span>
     <span class="fs-kpi-ico"><span class="material-symbols-outlined">paid</span></span></div>
     <b class="fs-kpi-valor" data-fs-contar="17918" data-fs-formato="soles">S/ 17,918.00</b>
     <div class="fs-kpi-pie"><span class="fs-kpi-delta">+12 % vs. octubre</span><svg class="fs-kpi-spark" viewBox="0 0 100 32"><path d="M0 30 L…"/></svg></div></div> */
.fs-card { background: var(--c-superficie); border-radius: var(--radius-xl); padding: 20px; box-shadow: var(--shadow-card); color: var(--c-texto); }
.fs-card--plana { box-shadow: inset 0 0 0 1px var(--c-borde); }
.fs-card--interactiva { cursor: pointer; transition: box-shadow var(--dur-base) ease, transform var(--dur-instante) var(--ease-salida); }
@media (hover: hover) and (pointer: fine) { .fs-card--interactiva:hover { box-shadow: var(--shadow-lg); } }
.fs-card--interactiva:active { transform: scale(.99); }
.fs-rotulo { font: var(--t-rotulo); letter-spacing: .04em; text-transform: uppercase; color: var(--c-texto-2); }
.fs-kpi { display: flex; flex-direction: column; gap: 8px; padding: 18px 20px; }
.fs-kpi-cab { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.fs-kpi-ico { width: 32px; height: 32px; border-radius: 10px; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
  background: var(--c-accion-suave); color: var(--c-sobre-accion-suave); }
.fs-kpi-ico .material-symbols-outlined { font-size: 18px; }
.fs-kpi-valor { font: 800 clamp(26px, 2.5vw, 34px)/1.1 var(--font-ui); letter-spacing: -.02em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.fs-kpi-pie { display: flex; align-items: flex-end; justify-content: space-between; gap: 10px; }
.fs-kpi-delta { display: inline-flex; align-items: center; gap: 4px; font: 500 13px/18px var(--font-ui); color: var(--c-texto-2); }
.fs-kpi-delta .material-symbols-outlined { font-size: 16px; color: var(--c-accion); }
.fs-kpi-spark { width: 96px; height: 32px; overflow: visible; }
.fs-kpi-spark path { fill: none; stroke: var(--c-accion); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.fs-kpi--logro { background: var(--c-logro-suave); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c-logro) 30%, transparent); }

/* ── Pestañas (control segmentado con "pulgar" que se desliza) ─────────────
   <div class="fs-tabs" role="tablist" data-fs-tabs>
     <button class="fs-tab" role="tab" aria-selected="true">General</button>
     <button class="fs-tab" role="tab" aria-selected="false">Por asesor</button></div>
   fs-ui.js agrega el pulgar, lo mueve (280 ms, --ease-salida), maneja ←/→ y
   emite 'fs:tab' {detail:{indice, tab}}. --suave = pulgar blanco (filtros). */
.fs-tabs { position: relative; display: inline-grid; grid-auto-flow: column; grid-auto-columns: 1fr; padding: 3px; border-radius: var(--radius-md);
  background: var(--c-superficie); box-shadow: inset 0 0 0 1px var(--c-borde); isolation: isolate; max-width: 100%; }
.fs-tabs-pulgar { position: absolute; top: 3px; bottom: 3px; left: 0; z-index: -1; border-radius: 9px; background: var(--c-texto);
  transition: transform var(--dur-media) var(--ease-salida), width var(--dur-media) var(--ease-salida); }
.fs-tab { position: relative; min-width: 0; height: 38px; padding: 0 16px; border: 0; border-radius: 9px; background: transparent;
  color: var(--c-texto-2); font: 700 14.5px/1 var(--font-ui); cursor: pointer; white-space: nowrap; transition: color var(--dur-base) ease; }
.fs-tab[aria-selected="true"] { color: var(--c-fondo); }
.fs-tabs:not(.fs-tabs--listo) .fs-tab[aria-selected="true"] { background: var(--c-texto); }
.fs-tabs--suave { background: var(--c-superficie-baja); }
.fs-tabs--suave .fs-tabs-pulgar { background: var(--c-superficie); box-shadow: var(--shadow-sm); }
.fs-tabs--suave .fs-tab[aria-selected="true"] { color: var(--c-texto); }
.fs-tabs--suave:not(.fs-tabs--listo) .fs-tab[aria-selected="true"] { background: var(--c-superficie); }
@media (pointer: coarse) { .fs-tab { min-height: var(--toque); } }

/* ── Capas: modal, hoja inferior, drawer ───────────────────────────────────
   <div class="fs-capa" id="miModal" hidden>
     <div class="fs-velo" data-fs-cerrar></div>
     <div class="fs-modal" role="dialog" aria-modal="true" aria-labelledby="miModalTit">
       <h2 class="fs-modal-tit" id="miModalTit">…</h2> … <button data-fs-cerrar>Cancelar</button></div></div>
   Cambia .fs-modal por .fs-hoja (sube desde el pulgar; en escritorio se
   centra como modal) o .fs-drawer (entra desde la derecha; --izq).
   fsAbrir('#miModal') / fsCerrar('#miModal'): foco atrapado, Esc cierra la
   de arriba, el foco vuelve al disparador, el fondo no se desplaza. */
.fs-capa { position: fixed; inset: 0; z-index: var(--z-modal); display: flex; align-items: center; justify-content: center; padding: 16px; }
.fs-capa[hidden] { display: none; }
.fs-velo { position: absolute; inset: 0; background: var(--c-velo); animation: fs-fundir var(--dur-base) ease both; }
.fs-capa.fs-saliendo .fs-velo { animation: fs-fundir-sale var(--dur-base) var(--ease-entrada) both; }
@keyframes fs-fundir { from { opacity: 0; } }
@keyframes fs-fundir-sale { to { opacity: 0; } }
.fs-modal, .fs-hoja, .fs-drawer { position: relative; background: var(--c-superficie); color: var(--c-texto); box-shadow: var(--shadow-xl); outline: none; overflow-y: auto; overscroll-behavior: contain; }
.fs-modal { width: min(480px, 100%); max-height: calc(100dvh - 32px); border-radius: var(--radius-xl); padding: 22px;
  animation: fs-modal-entra var(--dur-media) cubic-bezier(.34,1.3,.64,1) both; }
@keyframes fs-modal-entra { from { opacity: 0; transform: translateY(18px) scale(.94); } }
.fs-capa.fs-saliendo .fs-modal { animation: fs-modal-sale var(--dur-base) var(--ease-entrada) both; }
@keyframes fs-modal-sale { to { opacity: 0; transform: translateY(8px) scale(.98); } }
.fs-modal-tit { margin: 0 0 6px; font: var(--t-h3); }
.fs-modal-txt { margin: 0; font: var(--t-cuerpo); color: var(--c-texto-2); }
.fs-modal-acciones { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; margin-top: 22px; }
.fs-capa--hoja { align-items: flex-end; padding: 0; }
.fs-hoja { width: 100%; max-height: 92dvh; border-radius: var(--radius-2xl) var(--radius-2xl) 0 0; padding: 10px 16px calc(20px + env(safe-area-inset-bottom, 0px));
  animation: fs-hoja-entra var(--dur-media) var(--ease-hoja) both; }
.fs-hoja::before { content: ''; display: block; width: 40px; height: 5px; margin: 0 auto 12px; border-radius: 9px; background: var(--c-borde-fuerte); }
@keyframes fs-hoja-entra { from { transform: translateY(100%); } }
.fs-capa.fs-saliendo .fs-hoja { animation: fs-hoja-sale var(--dur-base) var(--ease-entrada) both; }
@keyframes fs-hoja-sale { to { transform: translateY(100%); } }
@media (min-width: 768px) {
  .fs-capa--hoja { align-items: center; padding: 16px; }
  .fs-hoja { width: min(480px, 100%); border-radius: var(--radius-xl); padding: 22px; animation-name: fs-modal-entra; }
  .fs-hoja::before { display: none; }
  .fs-capa.fs-saliendo .fs-hoja { animation-name: fs-modal-sale; }
}
.fs-capa--drawer { justify-content: flex-end; align-items: stretch; padding: 0; }
.fs-capa--drawer.fs-capa--izq { justify-content: flex-start; }
.fs-drawer { width: min(420px, 100%); height: 100%; padding: 22px; animation: fs-drawer-entra var(--dur-lenta) var(--ease-hoja) both; }
.fs-capa--izq .fs-drawer { animation-name: fs-drawer-entra-izq; }
@keyframes fs-drawer-entra { from { transform: translateX(105%); } }
@keyframes fs-drawer-entra-izq { from { transform: translateX(-105%); } }
.fs-capa.fs-saliendo .fs-drawer { animation: fs-drawer-sale var(--dur-base) var(--ease-entrada) both; }
.fs-capa.fs-saliendo.fs-capa--izq .fs-drawer { animation-name: fs-drawer-sale-izq; }
@keyframes fs-drawer-sale { to { transform: translateX(105%); } }
@keyframes fs-drawer-sale-izq { to { transform: translateX(-105%); } }
html.fs-capa-abierta { overflow: hidden; }

/* ── Toast (fsToast) ───────────────────────────────────────────────────────
   Uno a la vez (el nuevo reemplaza al anterior), abajo al centro, encima de
   la barra inferior en móvil. Entra con resorte desde abajo; se va sola a
   los 3.2 s (manual §09). */
.fs-toast { position: fixed; left: 50%; bottom: 24px; z-index: var(--z-toast); max-width: calc(100vw - 32px); width: max-content;
  display: flex; align-items: center; gap: 12px; padding: 14px 18px; border-radius: var(--radius-lg);
  background: var(--c-inverso); color: var(--c-sobre-inverso); box-shadow: var(--shadow-xl);
  font: 600 15px/20px var(--font-ui); transform: translateX(-50%);
  animation: fs-toast-entra var(--dur-media) var(--ease-rebote) both; }
.fs-toast-ico { font-size: 22px; flex-shrink: 0; color: var(--c-chispa); font-variation-settings: 'FILL' 1; }
:root[data-tema="oscuro"] .fs-toast-ico { color: var(--c-verde-600); }
.fs-toast--error .fs-toast-ico { color: #FF8F80; }
:root[data-tema="oscuro"] .fs-toast--error .fs-toast-ico { color: var(--c-error); filter: brightness(.8); }
.fs-toast--logro .fs-toast-ico { color: var(--c-logro); }
.fs-toast-accion { margin-left: 4px; height: 36px; padding: 0 10px; border: 0; border-radius: 10px; background: transparent; color: var(--c-chispa);
  font: 700 14px/1 var(--font-ui); cursor: pointer; }
:root[data-tema="oscuro"] .fs-toast-accion { color: var(--c-verde-700); }
.fs-toast.fs-saliendo { animation: fs-toast-sale var(--dur-base) var(--ease-entrada) both; }
@keyframes fs-toast-entra { from { opacity: 0; transform: translate(-50%, 28px) scale(.9); } }
@keyframes fs-toast-sale { to { opacity: 0; transform: translate(-50%, 8px); } }
@media (max-width: 767.98px) {
  .fs-toast { bottom: calc(57px + env(safe-area-inset-bottom, 0px) + 12px); width: auto; white-space: normal; }
}

/* ── Skeleton ──────────────────────────────────────────────────────────────
   <span class="fs-skeleton fs-skeleton--texto" style="width:60%"></span>
   --texto (12 px) · --titulo (20 px) · --circulo · --bloque (alto libre). */
.fs-skeleton { position: relative; display: block; overflow: hidden; border-radius: var(--radius-sm); background: var(--c-superficie-alta); color: transparent !important; }
.fs-skeleton::after { content: ''; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.55), transparent); animation: fs-barrido 1.2s ease-in-out infinite; }
:root[data-tema="oscuro"] .fs-skeleton::after { background: linear-gradient(90deg, transparent, rgba(255,255,255,.06), transparent); }
@keyframes fs-barrido { to { transform: translateX(100%); } }
.fs-skeleton--texto { height: 12px; border-radius: 6px; }
.fs-skeleton--titulo { height: 20px; border-radius: 8px; }
.fs-skeleton--circulo { border-radius: var(--radius-full); }
@media (prefers-reduced-motion: reduce) { .fs-skeleton::after { display: none; } .fs-skeleton { animation: fs-respira 1600ms ease-in-out infinite !important; } }
html.fs-sin-movimiento .fs-skeleton::after { display: none; }

/* ── Estado vacío (manual §12: baldosa + ícono + punto + frase) ────────────
   <div class="fs-vacio">< ?= app_icono_marca('vacio_chats', 'im-80 im-entra') ?>
     <span class="fs-rotulo">Vacío</span><b class="fs-vacio-tit">Aún no tienes chats</b>
     <p class="fs-vacio-txt">Cuando llegue un lead de tus anuncios, aparecerá aquí.</p>
     <div class="fs-vacio-acciones">…</div></div> */
.fs-vacio { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 10px; padding: 32px 16px;
  animation: fs-entra var(--dur-lenta) var(--ease-salida) both; }
.fs-vacio .im-ilustra { margin-bottom: 6px; }
.fs-vacio-tit { font: 700 17px/24px var(--font-ui); color: var(--c-texto); text-wrap: balance; }
.fs-vacio-txt { margin: 0; max-width: 38ch; font: 400 14px/21px var(--font-ui); color: var(--c-texto-2); text-wrap: pretty; }
.fs-vacio-acciones { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 6px; }
@keyframes fs-entra { from { opacity: 0; transform: translateY(var(--dist-entrada)); } }
.fs-entra { animation: fs-entra var(--dur-lenta) var(--ease-salida) both; }

/* ── Burbujas de chat ──────────────────────────────────────────────────────
   <div class="fs-hilo">  (columna con gap)
     <div class="fs-burbuja fs-burbuja--prospecto">Hola…<span class="fs-burbuja-meta">10:41</span></div>
     <div class="fs-burbuja fs-burbuja--ia"><span class="fs-burbuja-rotulo">Asistente IA</span>¿Para cuántas…</div>
     <div class="fs-burbuja fs-burbuja--asesor">Te llamo…<span class="fs-burbuja-meta">10:41
        <span class="fs-entrega" data-estado="leido" title="Leído"></span></span></div>
     <div class="fs-burbuja fs-burbuja--sistema">Diego tomó el chat · 10:41</div></div>
   Estado de entrega: data-estado = enviando | enviado | leido | error.
   .fs-burbuja--nueva = entrada de resorte (solo en la burbuja que llegó). */
.fs-hilo { display: flex; flex-direction: column; gap: 6px; }
.fs-burbuja { position: relative; max-width: min(520px, 78%); padding: 9px 14px 6px; border-radius: var(--radius-burbuja);
  font: 400 15.5px/1.45 var(--font-ui); color: var(--c-texto); overflow-wrap: anywhere; white-space: pre-line; }
.fs-burbuja--prospecto { align-self: flex-start; background: var(--c-superficie); box-shadow: var(--shadow-card);
  border-bottom-left-radius: var(--radius-cola); transform-origin: 0 100%; }
.fs-burbuja--asesor { align-self: flex-end; background: var(--c-accion); color: var(--c-sobre-accion);
  border-bottom-right-radius: var(--radius-cola); transform-origin: 100% 100%; }
.fs-burbuja--ia { align-self: flex-end; background: var(--c-ia-suave); color: var(--c-texto);
  border-bottom-right-radius: var(--radius-cola); transform-origin: 100% 100%; }
.fs-burbuja--sistema { align-self: center; max-width: 92%; display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px; margin: 4px 0;
  border-radius: var(--radius-full); background: var(--c-superficie); box-shadow: inset 0 0 0 1px var(--c-borde);
  font: 500 13px/18px var(--font-ui); color: var(--c-texto-2); white-space: normal; }
.fs-burbuja--sistema .material-symbols-outlined { font-size: 16px; color: var(--c-accion); }
.fs-burbuja-rotulo { display: flex; align-items: center; gap: 4px; margin-bottom: 2px; font: 700 12px/16px var(--font-ui); color: var(--c-ia); white-space: normal; }
.fs-burbuja-rotulo::before { content: ''; width: 14px; height: 14px; background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M17.8 3.2l.9 2.2 2.2.9-2.2.9-.9 2.2-.9-2.2-2.2-.9 2.2-.9zM10 6l1.6 4.4L16 12l-4.4 1.6L10 18l-1.6-4.4L4 12l4.4-1.6z'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M17.8 3.2l.9 2.2 2.2.9-2.2.9-.9 2.2-.9-2.2-2.2-.9 2.2-.9zM10 6l1.6 4.4L16 12l-4.4 1.6L10 18l-1.6-4.4L4 12l4.4-1.6z'/%3E%3C/svg%3E") center / contain no-repeat; }
.fs-burbuja-meta { display: flex; justify-content: flex-end; align-items: center; gap: 4px; margin-top: 1px;
  font: 500 11.5px/16px var(--font-ui); color: var(--c-texto-3); font-variant-numeric: tabular-nums; white-space: nowrap; }
.fs-burbuja--asesor .fs-burbuja-meta { color: inherit; opacity: .9; }
.fs-burbuja--ia .fs-burbuja-meta { color: var(--c-texto-2); }
.fs-entrega { display: inline-block; width: 16px; height: 16px; background: currentColor; flex-shrink: 0;
  -webkit-mask: var(--fs-ent) center / contain no-repeat; mask: var(--fs-ent) center / contain no-repeat;
  --fs-ent: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath d='m382-354 339-339q12-12 28-12t28 12q12 12 12 28.5T777-636L410-268q-12 12-28 12t-28-12L182-440q-12-12-11.5-28.5T183-497q12-12 28.5-12t28.5 12l142 143Z'/%3E%3C/svg%3E"); }
.fs-entrega[data-estado="enviando"] { --fs-ent: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath d='M520-496v-144q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640v159q0 8 3 15.5t9 13.5l132 132q11 11 28 11t28-11q11-11 11-28t-11-28L520-496ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Z'/%3E%3C/svg%3E"); opacity: .8; }
.fs-entrega[data-estado="leido"] { --fs-ent: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath d='M268-240 42-466l57-56 170 170 56 56-57 56Zm226 0L268-466l56-57 170 170 368-368 56 57-424 424Zm0-226-57-56 198-198 57 56-198 198Z'/%3E%3C/svg%3E"); }
.fs-burbuja--asesor .fs-entrega[data-estado="leido"] { color: var(--c-chispa); }
:root[data-tema="oscuro"] .fs-burbuja--asesor .fs-entrega[data-estado="leido"] { color: var(--c-verde-700); }
.fs-entrega[data-estado="error"] { --fs-ent: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 -960 960 960'%3E%3Cpath d='M480-280q17 0 28.5-11.5T520-320q0-17-11.5-28.5T480-360q-17 0-28.5 11.5T440-320q0 17 11.5 28.5T480-280Zm0-160q17 0 28.5-11.5T520-480v-160q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640v160q0 17 11.5 28.5T480-440Zm0 360q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Z'/%3E%3C/svg%3E"); color: var(--c-error); }
.fs-burbuja--asesor .fs-entrega[data-estado="error"] { color: #FFD3CD; }
.fs-burbuja--nueva { animation: fs-burbuja-entra 420ms var(--ease-rebote) both; }
@keyframes fs-burbuja-entra { from { opacity: 0; transform: translateY(14px) scale(.9); } }

/* ── Tarjeta del kanban (solo estilos; arrastre y "avanzar" los pone la
   página, fase 6). Columna: .fs-kcol (+ --sobre = destino de arrastre).
   <div class="fs-kcard" draggable="true"><div class="fs-kcard-cab">avatar + nombre/plan</div>
     <div class="fs-kcard-chips">chips</div><div class="fs-kcard-pie"><b class="fs-kcard-monto">S/ 289.00</b>
     <span class="fs-kcard-cuando">hoy 4:00 p. m.</span><button class="fs-kcard-avanzar" aria-label="Avanzar a Cotizado">→</button></div></div> */
.fs-kcol { display: flex; flex-direction: column; min-height: 0; border-radius: var(--radius-xl); background: var(--c-superficie-baja);
  box-shadow: inset 0 0 0 1px var(--c-borde); transition: background-color 180ms ease, box-shadow 180ms ease; }
.fs-kcol--sobre { background: var(--c-accion-suave); box-shadow: inset 0 0 0 2px var(--c-accion); }
.fs-kcard { display: flex; flex-direction: column; gap: 8px; padding: 12px; border-radius: 14px; background: var(--c-superficie);
  box-shadow: var(--shadow-card); cursor: grab; transition: box-shadow var(--dur-base) ease, opacity var(--dur-base) ease; }
@media (hover: hover) and (pointer: fine) { .fs-kcard:hover { box-shadow: var(--shadow-lg); } }
.fs-kcard:active { cursor: grabbing; }
.fs-kcard--arrastrando { opacity: .5; }
.fs-kcard-cab { display: flex; align-items: center; gap: 10px; min-width: 0; }
.fs-kcard-nombre { font: 700 14.5px/20px var(--font-ui); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fs-kcard-sub { font: 500 12.5px/16px var(--font-ui); color: var(--c-texto-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fs-kcard-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.fs-kcard-pie { display: flex; align-items: center; gap: 8px; }
.fs-kcard-monto { font: 700 15px/20px var(--font-ui); font-variant-numeric: tabular-nums; white-space: nowrap; }
.fs-kcard-cuando { min-width: 0; font: 600 12.5px/16px var(--font-ui); color: var(--c-texto-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fs-kcard-avanzar { flex-shrink: 0; margin-left: auto; width: 36px; height: 36px; border: 0; border-radius: 10px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--c-superficie-baja); color: var(--c-texto-2); cursor: pointer; transition: background-color var(--dur-rapida) ease, color var(--dur-rapida) ease; }
@media (hover: hover) and (pointer: fine) { .fs-kcard-avanzar:hover { background: var(--c-accion-suave); color: var(--c-sobre-accion-suave); } }

/* ── Celebración (fsCelebrar) y realce ─────────────────────────────────── */
.fs-celebra-capa { position: fixed; inset: 0; z-index: var(--z-toast); pointer-events: none; overflow: hidden; }
.fs-celebra-capa > span { position: absolute; display: block; will-change: transform, opacity; }
/* Fila que cambió (p. ej. mensaje nuevo en la lista): halo menta 1.2 s. */
@keyframes fs-realce { from { background-color: var(--c-accion-suave); } }
.fs-realce { animation: fs-realce var(--dur-momento) var(--ease-salida); }
.fs-respira { animation: fs-respira 1600ms ease-in-out infinite; }
.fs-tabular { font-variant-numeric: tabular-nums; }

/* Movimiento reducido: sin desplazamientos (los fundidos de ≤160 ms los deja
   la regla global de fuerza-tokens.css). */
@media (prefers-reduced-motion: reduce) {
  .fs-temblar { animation-name: fs-temblor-rm; }
  .fs-modal, .fs-hoja, .fs-drawer, .fs-toast, .fs-burbuja--nueva, .fs-vacio, .fs-entra { animation-name: fs-fundir !important; }
  .fs-capa.fs-saliendo .fs-modal, .fs-capa.fs-saliendo .fs-hoja, .fs-capa.fs-saliendo .fs-drawer, .fs-toast.fs-saliendo { animation-name: fs-fundir-sale !important; }
  .fs-toast { transform: translateX(-50%); }
}
