/* ==========================================================================
   OBSCURA · vista-mock.css — sólo /proyectos/

   Las 3 pantallas animadas que viven dentro de `.vista__marco` (Tomo I ·
   Automatizaciones). No son fotos: son el dashboard real de cada sistema
   (claude/piezas/<proyecto>/pieza.html, hoy estático, usado para las capturas
   del home) redibujado con clases propias `vm-*` y animado en loop mientras
   dura el hover — misma técnica que css/mockups.css § 05 de la home (reveals
   por transición, cursor guionado con --cx/--cy), aplicada acá con hover en
   vez de scroll. Ver js/vista-mock.js.

   Cada pieza trae su PROPIA paleta (custom properties --vm-*, tomadas de la
   paleta real de cada pieza.css) y pinta su propio fondo opaco — .vista__marco
   (css/proyectos.css) no se toca. Necesario: taller-mecánico tiene que verse
   oscuro de verdad, y --bg-sunk del sitio es un color del SITIO, no del
   sistema que se muestra.

   Tipografía fluida: .vm-board fija un font-size en clamp(vw), y todo lo
   demás de esta hoja está en em relativo a eso — mismo idioma que ya usa
   tokens.css/proyectos.css en el resto del sitio (clamp con vw, sin
   @container en ningún lado). Reveals: sólo opacity/transform/clip-path/
   stroke-dasharray vía clase .is-in — nunca @keyframes para las
   revelaciones, igual que mockups.css. Los dos @keyframes de acá (pulso
   "en vivo", puntitos de "escribiendo") son pequeños, infinite, y están
   copiados de mockups.css tal cual.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0 · MARCO COMÚN
   -------------------------------------------------------------------------- */
.vm-board {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  overflow: hidden;
  display: flex; flex-direction: column;
  opacity: 0;
  transform: scale(1.1);
  filter: blur(10px);
  transition: opacity 500ms var(--ease-out), transform 500ms var(--ease-out), filter 500ms var(--ease-out);
  font-family: var(--font-body);
  /* Sigue el mismo eje de viewport que .vista__marco (clamp(300px,26vw,420px)),
     dividido por 36 — que es la relación del board--tall real: 360px de ancho
     con una base de ~10px, y esta hoja convirtió sus píxeles a em con esa
     misma regla. Los tres tramos coinciden: 300px→8.3, 374px→10.4, 420px→11.7.
     Medido: con 2.85vw (o sea 12.5px a 1440) todo entraba un 25 % grande y la
     leyenda de la dona se comía su propio encabezado. */
  font-size: clamp(8.3px, 0.72vw, 11.7px);
  line-height: 1.3;
  -webkit-font-smoothing: antialiased;
}
.vm-board.is-shown { opacity: 1; transform: scale(1); filter: blur(0); }

.vm-board * { box-sizing: border-box; }
.vm-board svg { display: block; }
.vm-board b, .vm-board i { font-style: normal; }

/* --------------------------------------------------------------------------
   1 · PALETA POR SISTEMA — valores reales de cada pieza.css, no los de
   Obscura (mismo criterio documentado ahí: la pieza se acerca al panel del
   cliente, no al sitio).
   -------------------------------------------------------------------------- */
.vm-board--concesionaria {
  --vm-bg:#FFFFFF; --vm-bg-sunk:#F1F2F5;
  --vm-ink:#16161A; --vm-ink-mute:#52525B;
  --vm-ink-soft:rgba(22,22,26,.64); --vm-ink-faint:rgba(22,22,26,.42);
  --vm-line:rgba(22,22,26,.09); --vm-line-strong:rgba(22,22,26,.16);
  --vm-accent:#2563EB; --vm-accent-2:#EA580C; --vm-accent-2-ink:#C2410C;
  --vm-ok:#16A34A; --vm-ok-ink:#15803D; --vm-rojo:#DC2626; --vm-rojo-ink:#B91C1C;
  --vm-claro:#F4F4F6; --vm-negro:#17171A;
  background: var(--vm-bg); color: var(--vm-ink);
}
.vm-board--taller-mecanico {
  /* Paleta oscura REAL del sistema (pieza.css:33-45) — no es
     [data-theme="dark"] del sitio: --bg acá es #1B1B1F, el negro de Obscura
     es #1D1C18, y el acento vivo es --accent-ink #60A5FA, no --accent-lt. */
  --vm-bg:#1B1B1F; --vm-bg-elev:#232329; --vm-bg-sunk:#111113;
  --vm-ink:#F5F5F7; --vm-ink-mute:#A6A6AF;
  --vm-ink-soft:rgba(245,245,247,.66); --vm-ink-faint:rgba(245,245,247,.42);
  --vm-line:rgba(245,245,247,.10); --vm-line-strong:rgba(245,245,247,.18);
  --vm-accent:#2563EB; --vm-accent-ink:#60A5FA;
  --vm-accent-2:#EA580C; --vm-accent-2-ink:#FB923C;
  --vm-ok:#16A34A; --vm-ok-ink:#4ADE80; --vm-rojo:#DC2626; --vm-rojo-ink:#F87171;
  --vm-claro:#F4F4F6; --vm-negro:#0B0B0D;
  background: var(--vm-bg); color: var(--vm-ink);
}
.vm-board--inmobiliaria {
  --vm-bg:#FFFFFF; --vm-bg-sunk:#F1F2F5;
  --vm-ink:#16161A; --vm-ink-mute:#52525B;
  --vm-ink-soft:rgba(22,22,26,.64); --vm-ink-faint:rgba(22,22,26,.42);
  --vm-line:rgba(22,22,26,.09); --vm-line-strong:rgba(22,22,26,.16);
  --vm-accent:#2563EB; --vm-accent-ink:#FFFFFF;
  --vm-accent-2:#EA580C; --vm-accent-2-ink:#C2410C; --vm-accent-2-deep:#9A3412;
  --vm-ok:#16A34A; --vm-ok-ink:#166534;
  --vm-claro:#F4F4F6; --vm-negro:#17171A;
  background: var(--vm-bg); color: var(--vm-ink);
}

/* --------------------------------------------------------------------------
   2 · CHROME Y BARRA DE ESTADO — comunes a los 3 (in-app, no es bezel de
   dispositivo: ese se descartó a propósito, es "el mockup" que el cliente
   pidió sacar).
   -------------------------------------------------------------------------- */
.vm-chrome {
  flex: 0 0 auto; display: flex; align-items: center; gap: .7em;
  background: var(--vm-negro); color: var(--vm-claro);
  padding: 0 1em; height: 2.6em;
}
.vm-chrome__mark { width: 1.1em; height: 1.1em; border-radius: 50%; flex: 0 0 auto;
                    border: .13em solid var(--vm-claro); opacity: .92; position: relative; }
.vm-chrome__mark::after { content:""; position:absolute; inset: .3em; border-radius: 50%;
                           background: var(--vm-claro); opacity: .5; }
.vm-chrome__name { font-family: var(--font-ui); font-weight: 700; font-size: 1em; }
.vm-chrome__sep { width: 1px; height: 1.1em; background: rgba(244,244,246,.22); }
.vm-chrome__crumb { font-family: var(--font-ui); font-weight: 500; font-size: .92em;
                     color: rgba(244,244,246,.68); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vm-chrome__right { margin-left: auto; display: flex; align-items: center; gap: 1em; flex: 0 0 auto; }
.vm-chrome__live { display: inline-flex; align-items: center; gap: .4em;
                    font-family: var(--font-ui); font-weight: 600; font-size: .75em;
                    letter-spacing: .1em; text-transform: uppercase; color: rgba(244,244,246,.72);
                    white-space: nowrap; }
.vm-chrome__live i { width: .45em; height: .45em; border-radius: 50%; background: #22C55E;
                      animation: vm-pulse 2s var(--ease-inout) infinite; }

/* NO HAY BARRA DE ESTADO, y no es un olvido: adentro de `.vista__marco` esa
   franja de abajo ya tiene dueño — `.vista__pie` (css/proyectos.css), que dice
   "Ver proyecto · Tomo I · i" sobre un degradado oscuro. Las piezas del home
   sí la llevan porque ahí no hay pie que las tape; acá las dos cosas se pisaban
   texto contra texto. El `padding-bottom` de .vm-main mantiene el contenido
   fuera de la zona oscura del degradado. */

@keyframes vm-pulse { 0%,100% { opacity: .4; transform: scale(.85); } 50% { opacity: 1; transform: scale(1); } }

/* --------------------------------------------------------------------------
   3 · CUERPO COMÚN — cabecera de página, fila de KPIs
   -------------------------------------------------------------------------- */
/* El relleno de abajo es la zona de sacrificio del pie: `.vista__pie` pinta un
   degradado que arriba es transparente y abajo casi opaco, así que el
   contenido tiene que terminar antes de esa parte oscura. Medido a 374px de
   marco: con 2em la última fila quedaba tapada por "VER PROYECTO". */
.vm-main { flex: 1; min-height: 0; display: flex; flex-direction: column;
           gap: .85em; padding: 1.1em 1.15em 3em; overflow: hidden; }

.vm-eyebrow { display: inline-flex; align-items: center; gap: .4em;
              font-family: var(--font-ui); font-weight: 600; font-size: .78em;
              letter-spacing: .13em; text-transform: uppercase; color: var(--vm-ink-soft); }
.vm-eyebrow svg { width: .9em; height: .9em; }

.vm-phead { flex: 0 0 auto; display: flex; align-items: center; gap: 1em; }
.vm-phead h1 { font-family: var(--font-display); font-weight: 400; font-size: 1.85em;
               line-height: 1.05; color: var(--vm-ink); }

.vm-krow { flex: 0 0 auto; display: grid; grid-template-columns: repeat(2, 1fr); gap: .8em; }
.vm-k { background: var(--vm-bg); border-radius: .7em;
        box-shadow: inset 0 0 0 1px var(--vm-line);
        padding: .7em .85em .8em; display: flex; flex-direction: column; min-width: 0;
        transition: box-shadow 200ms var(--ease-out); }
.vm-k__rot { display: flex; align-items: center; gap: .4em;
             font-family: var(--font-ui); font-weight: 600; font-size: .72em;
             letter-spacing: .08em; text-transform: uppercase; color: var(--vm-ink-soft);
             white-space: nowrap; overflow: hidden; }
.vm-k__ico { margin-left: auto; width: 1.05em; height: 1.05em; flex: 0 0 auto; color: var(--vm-ink-faint); }
.vm-k__ico svg { width: 100%; height: 100%; }
.vm-k__v { margin-top: auto; font-family: var(--font-display); font-size: 2.05em; line-height: 1;
           color: var(--vm-ink); font-variant-numeric: tabular-nums; white-space: nowrap;
           /* se revela por barrido, no por contador animado */
           clip-path: inset(0 100% 0 0);
           transition: clip-path 700ms var(--ease-expo); }
.vm-k.is-in .vm-k__v { clip-path: inset(0 -2% 0 0); }
.vm-k__v u { text-decoration: none; font-family: var(--font-ui); font-weight: 600; font-size: .5em; color: var(--vm-ink-soft); }
.vm-k__sub { margin-top: .35em; font-family: var(--font-ui); font-weight: 500; font-size: .74em;
             color: var(--vm-ink-soft); line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
             opacity: 0; transform: translate3d(0, .3em, 0);
             transition: opacity 320ms var(--ease-out), transform 320ms var(--ease-out); }
.vm-k.is-in .vm-k__sub { opacity: 1; transform: none; }
.vm-k__pie { margin-top: .4em; display: flex; align-items: baseline; gap: .35em;
             font-family: var(--font-ui); font-weight: 700; font-size: .85em; white-space: nowrap;
             opacity: 0; transform: translate3d(0, .3em, 0);
             transition: opacity 320ms var(--ease-out) 120ms, transform 320ms var(--ease-out) 120ms; }
.vm-k.is-in .vm-k__pie { opacity: 1; transform: none; }
.vm-k--up { color: var(--vm-ok-ink); }
.vm-k--urg { background: color-mix(in srgb, var(--vm-rojo) 12%, var(--vm-bg));
             box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--vm-rojo) 30%, transparent); }
.vm-k--urg .vm-k__v, .vm-k--urg .vm-k__sub, .vm-k--urg .vm-k__ico { color: var(--vm-rojo-ink); }
.vm-k--med { background: color-mix(in srgb, var(--vm-accent-2) 12%, var(--vm-bg));
             box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--vm-accent-2) 30%, transparent); }
.vm-k--med .vm-k__v, .vm-k--med .vm-k__ico { color: var(--vm-accent-2-ink); }

/* --------------------------------------------------------------------------
   4 · CONCESIONARIA — donut "Leads por estado", draw-in real por segmento
   -------------------------------------------------------------------------- */
.vm-dona { flex: 1; min-height: 0; background: var(--vm-bg); border-radius: .7em;
           box-shadow: inset 0 0 0 1px var(--vm-line);
           padding: .75em .85em .8em; display: flex; flex-direction: column; overflow: hidden; }
.vm-dona__h { flex: 0 0 auto; margin-bottom: .5em; }
.vm-dona__b { flex: 1; min-height: 0; display: flex; align-items: center; gap: .8em; overflow: hidden; }
.vm-dona__r { position: relative; flex: 0 0 auto; width: 5.8em; height: 5.8em; }
.vm-dona__g { width: 100%; height: 100%; }
.vm-dona__seg {
  fill: none;
  stroke-dasharray: 0 238.76;
  stroke-dashoffset: var(--vm-off, 0);
  transition: stroke-dasharray 650ms var(--ease-expo);
}
.vm-dona__seg.is-in { stroke-dasharray: var(--vm-arc) 238.76; }
.vm-dona__c { position: absolute; inset: 0; display: flex; flex-direction: column;
              align-items: center; justify-content: center; }
.vm-dona__c b { font-family: var(--font-display); font-size: 1.55em; line-height: 1;
                font-weight: 400; color: var(--vm-ink); font-variant-numeric: tabular-nums; }
.vm-dona__c i { font-family: var(--font-ui); font-weight: 600; font-size: .55em;
                letter-spacing: .12em; text-transform: uppercase; color: var(--vm-ink-soft); margin-top: .2em; }
.vm-dona__l { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column;
              justify-content: center; overflow: hidden; }
.vm-lg { display: flex; align-items: center; gap: .45em; padding: .1em 0; min-width: 0; flex: 0 0 auto;
         opacity: 0; transform: translate3d(-.4em, 0, 0);
         transition: opacity 320ms var(--ease-out), transform 320ms var(--ease-out); }
.vm-lg.is-in { opacity: 1; transform: none; }
.vm-lg__p { width: .5em; height: .5em; border-radius: .12em; flex: 0 0 auto; }
.vm-lg__n { flex: 1; min-width: 0; font-family: var(--font-ui); font-weight: 500; font-size: .7em;
            color: var(--vm-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vm-lg__v { flex: 0 0 auto; font-family: var(--font-ui); font-weight: 700; font-size: .74em;
            color: var(--vm-ink); font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   5 · TALLER MECÁNICO — cola de turnos + recordatorio con transición de
   estado real (pendiente → aprobado), disparada por el cursor "clickeando".
   -------------------------------------------------------------------------- */
.vm-lower { flex: 1; min-height: 0; display: grid; grid-template-columns: 1.05fr 1fr; gap: .7em; }
.vm-cola, .vm-avisos { background: var(--vm-bg); border-radius: .7em;
                        box-shadow: inset 0 0 0 1px var(--vm-line);
                        padding: .7em .8em .75em; display: flex; flex-direction: column;
                        min-width: 0; min-height: 0; overflow: hidden; }
.vm-cola__h, .vm-avisos__h { flex: 0 0 auto; display: flex; align-items: baseline; gap: .5em;
                              margin-bottom: .5em; min-width: 0; }
.vm-cola__c, .vm-avisos__c { margin-left: auto; flex: 0 0 auto;
                              font-family: var(--font-ui); font-weight: 600; font-size: .64em;
                              color: var(--vm-ink-soft); white-space: nowrap; }

.vm-dia__h { display: flex; align-items: center; gap: .4em; padding-bottom: .35em;
             min-width: 0; white-space: nowrap; }
.vm-dia__f { font-family: var(--font-ui); font-weight: 700; font-size: .78em; color: var(--vm-ink); flex: 0 0 auto; }
.vm-dia__cupo { font-family: var(--font-ui); font-weight: 600; font-size: .64em; color: var(--vm-ink-soft);
                flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; }
.vm-dia__alerta { margin-left: auto; display: inline-flex; align-items: center; gap: .3em;
                  padding: .18em .55em; border-radius: 999px;
                  background: color-mix(in srgb, var(--vm-rojo) 20%, transparent);
                  font-family: var(--font-ui); font-weight: 700; font-size: .6em;
                  letter-spacing: .05em; text-transform: uppercase; color: var(--vm-rojo-ink);
                  white-space: nowrap;
                  opacity: 0; transform: scale(.85);
                  transition: opacity 260ms var(--ease-out), transform 260ms var(--ease-spring); }
.vm-dia__alerta.is-in { opacity: 1; transform: none; }
.vm-dia__alerta svg { width: .7em; height: .7em; }

.vm-dia__filas { display: flex; flex-direction: column; }
.vm-turno { display: flex; align-items: center; gap: .6em; padding: .32em 0;
            border-top: 1px solid color-mix(in srgb, var(--vm-line) 65%, transparent);
            opacity: 0; transform: translate3d(0, .3em, 0);
            transition: opacity 340ms var(--ease-out), transform 340ms var(--ease-out); }
.vm-turno.is-in { opacity: 1; transform: none; }
.vm-dia__filas .vm-turno:first-child { border-top: 0; }
.vm-turno__n { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.vm-turno__n b { font-family: var(--font-ui); font-weight: 600; font-size: .78em; color: var(--vm-ink);
                  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vm-turno__n i { font-family: var(--font-body); font-size: .66em; color: var(--vm-ink-faint);
                  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vm-turno__pill { flex: 0 0 auto; padding: .18em .6em; border-radius: 999px;
                   font-family: var(--font-ui); font-weight: 700; font-size: .58em;
                   letter-spacing: .04em; text-transform: uppercase; white-space: nowrap;
                   color: var(--vm-ok-ink); background: color-mix(in srgb, var(--vm-ok) 18%, transparent); }
.vm-turno--pend .vm-turno__pill { color: var(--vm-accent-2-ink); background: color-mix(in srgb, var(--vm-accent-2) 18%, transparent); }
.vm-turno--pend .vm-turno__n b { color: var(--vm-accent-2-ink); }

.vm-rec { border-radius: .5em; padding: .6em .7em .65em;
          background: var(--vm-bg-elev, var(--vm-bg-sunk)); box-shadow: inset 0 0 0 1px var(--vm-line);
          display: flex; flex-direction: column; gap: .3em; }
.vm-rec__top { display: flex; align-items: center; gap: .5em; }
.vm-rec__n { min-width: 0; display: flex; flex-direction: column; }
.vm-rec__n b { font-family: var(--font-ui); font-weight: 600; font-size: .78em; color: var(--vm-ink);
               white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vm-rec__n i { font-family: var(--font-ui); font-weight: 500; font-size: .62em; color: var(--vm-ink-faint); }
.vm-rec__chip { margin-left: auto; flex: 0 0 auto; padding: .18em .55em; border-radius: 999px;
                font-family: var(--font-ui); font-weight: 700; font-size: .56em;
                letter-spacing: .04em; text-transform: uppercase; white-space: nowrap;
                transition: color 200ms var(--ease-out), background-color 200ms var(--ease-out); }
.vm-rec--pend .vm-rec__chip { color: var(--vm-accent-2-ink); background: color-mix(in srgb, var(--vm-accent-2) 20%, transparent); }
.vm-rec--sinenviar .vm-rec__chip { color: var(--vm-accent-ink, var(--vm-accent)); background: color-mix(in srgb, var(--vm-accent) 22%, transparent); }
.vm-rec__msg { font-family: var(--font-body); font-size: .68em; line-height: 1.4; color: var(--vm-ink-soft);
               display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.vm-rec__meta { font-family: var(--font-ui); font-weight: 500; font-size: .62em; color: var(--vm-ink-faint);
                opacity: 0; transform: translateY(.3em); height: 0; overflow: hidden;
                transition: opacity 220ms var(--ease-out), transform 220ms var(--ease-out); }
.vm-rec__meta b { font-weight: 700; color: var(--vm-ink-mute); }
.vm-rec--sinenviar .vm-rec__meta { opacity: 1; transform: none; height: auto; }
.vm-rec__acts { display: flex; align-items: center; gap: .5em; margin-top: .1em;
                transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out); }
.vm-rec--sinenviar .vm-rec__acts { opacity: 0; transform: translateY(-.3em); pointer-events: none; height: 0; overflow: hidden; margin: 0; }
.vm-rec__go { padding: .3em .7em; border-radius: .4em;
              font-family: var(--font-ui); font-weight: 700; font-size: .62em; letter-spacing: .01em; white-space: nowrap; }
.vm-rec__go--ok { color: #FFFFFF; background: var(--vm-accent); }
.vm-rec__go--no { color: var(--vm-ink-soft); background: color-mix(in srgb, var(--vm-ink) 8%, transparent); }

/* --------------------------------------------------------------------------
   6 · INMOBILIARIA — hilo de WhatsApp (burbujas + "escribiendo") y ficha con
   el campo reservado.
   -------------------------------------------------------------------------- */
.vm-wa { flex: 1; min-height: 0; background: var(--vm-bg); border-radius: .7em;
         box-shadow: inset 0 0 0 1px var(--vm-line); display: flex; flex-direction: column; overflow: hidden; }
.vm-wa__head { flex: 0 0 auto; display: flex; align-items: center; gap: .5em;
               padding: .5em .65em; border-bottom: 1px solid var(--vm-line); }
.vm-wa__ava { width: 1.5em; height: 1.5em; border-radius: 50%; flex: 0 0 auto;
              background: linear-gradient(140deg, #E7E7EB, #C6C7CF);
              font-family: var(--font-ui); font-weight: 700; font-size: .6em; color: var(--vm-ink);
              display: flex; align-items: center; justify-content: center; }
.vm-wa__who { min-width: 0; display: flex; flex-direction: column; }
.vm-wa__name { font-family: var(--font-ui); font-weight: 600; font-size: .78em; color: var(--vm-ink);
               white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-height: 1.2; }
.vm-wa__tel { font-family: var(--font-ui); font-weight: 500; font-size: .6em; color: var(--vm-ink-soft); }
.vm-wa__mode { margin-left: auto; flex: 0 0 auto; }
.vm-chip { display: inline-flex; align-items: center; gap: .3em; padding: .18em .55em; border-radius: 999px;
           font-family: var(--font-ui); font-weight: 600; font-size: .58em; letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; }
.vm-chip i { width: .3em; height: .3em; border-radius: 50%; background: currentColor; }
.vm-chip--hold { color: var(--vm-accent-2-deep, var(--vm-accent-2-ink)); background: color-mix(in srgb, var(--vm-accent-2) 16%, transparent); }

.vm-wa__body { flex: 1; min-height: 0; display: flex; flex-direction: column;
               justify-content: flex-end; gap: .4em; padding: .6em .65em; overflow: hidden; }
.vm-msg { display: flex; max-width: 86%; }
.vm-msg--in { align-self: flex-start; }
.vm-msg--out { align-self: flex-end; }
.vm-bubble { padding: .4em .55em; border-radius: .8em; font-size: .72em; line-height: 1.35;
             font-family: var(--font-body);
             opacity: 0; transform: translate3d(0, .5em, 0) scale(.96);
             transition: opacity 380ms var(--ease-out), transform 380ms var(--ease-spring); }
.vm-msg.is-in .vm-bubble { opacity: 1; transform: none; }
.vm-msg--in .vm-bubble { background: color-mix(in srgb, var(--vm-ink) 8%, transparent); color: var(--vm-ink);
                          border-bottom-left-radius: .2em; }
.vm-msg--out .vm-bubble { background: var(--vm-accent); color: var(--vm-accent-ink); border-bottom-right-radius: .2em; }

.vm-typing { align-self: flex-end; display: flex; align-items: center; gap: .2em;
             padding: .4em .55em; border-radius: .8em; border-bottom-right-radius: .2em;
             background: color-mix(in srgb, var(--vm-accent) 22%, transparent);
             opacity: 0; transform: translate3d(0, .4em, 0) scale(.94);
             transition: opacity 240ms var(--ease-out), transform 240ms var(--ease-spring); }
.vm-typing.is-in { opacity: 1; transform: none; }
.vm-typing i { width: .3em; height: .3em; border-radius: 50%; background: var(--vm-ink); opacity: .5; }
.vm-typing.is-in i { animation: vm-typing 1.25s var(--ease-inout) infinite; }
.vm-typing i:nth-child(2) { animation-delay: .16s; }
.vm-typing i:nth-child(3) { animation-delay: .32s; }
@keyframes vm-typing { 0%, 60%, 100% { transform: translateY(0); opacity: .35; } 30% { transform: translateY(-.2em); opacity: 1; } }

.vm-sysmark { align-self: center; display: inline-flex; align-items: center; gap: .3em;
              margin-top: .1em; padding: .22em .6em; border-radius: 999px;
              border: 1px dashed color-mix(in srgb, var(--vm-accent-2) 48%, transparent);
              background: color-mix(in srgb, var(--vm-accent-2) 8%, transparent);
              font-family: var(--font-ui); font-weight: 600; font-size: .58em;
              letter-spacing: .06em; text-transform: uppercase; color: var(--vm-accent-2-deep, var(--vm-accent-2-ink));
              white-space: nowrap;
              opacity: 0; transform: translate3d(0, .3em, 0);
              transition: opacity 380ms var(--ease-out), transform 380ms var(--ease-out); }
.vm-sysmark.is-in { opacity: 1; transform: none; }

.vm-fstrip { flex: 0 0 auto; display: flex; align-items: center; gap: .6em;
             background: var(--vm-bg); border-radius: .7em; box-shadow: inset 0 0 0 1px var(--vm-line);
             padding: .55em .7em;
             opacity: 0; transform: translate3d(0, .4em, 0);
             transition: opacity 420ms var(--ease-out), transform 420ms var(--ease-out); }
.vm-fstrip.is-in { opacity: 1; transform: none; }
.vm-fstrip__t { min-width: 0; }
.vm-fstrip__code { display: block; font-family: var(--font-ui); font-weight: 700; font-size: .58em;
                    letter-spacing: .1em; color: var(--vm-accent-2-ink); }
.vm-fstrip__name { display: block; font-family: var(--font-display); font-size: .95em; line-height: 1.15;
                    color: var(--vm-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vm-fstrip__held { margin-left: auto; display: flex; align-items: center; gap: .35em; flex: 0 0 auto;
                    border-radius: .4em; padding: .1em .3em; transition: background-color 200ms var(--ease-out); }
.vm-fstrip__held svg { width: .85em; height: .85em; flex: 0 0 auto; color: var(--vm-accent-2-ink); }
.vm-fstrip__held span { font-family: var(--font-ui); font-weight: 600; font-size: .58em;
                         letter-spacing: .05em; text-transform: uppercase; color: var(--vm-accent-2-ink); }
.vm-fstrip__held.is-hit { background: color-mix(in srgb, var(--vm-accent-2) 14%, transparent); }

/* --------------------------------------------------------------------------
   7 · CURSOR FALSO — mismo mecanismo que .mk-cursor (mockups.css): un punto
   absoluto movido por --cx/--cy, JS sólo cambia las custom properties.
   -------------------------------------------------------------------------- */
/* ⚠ EL PUNTO NO SE TRASLADA A SÍ MISMO. Un `transform: translate(50%)` sobre
   un punto de .6em resuelve el porcentaje contra SUS PROPIOS 6px, no contra el
   tablero: el cursor se movía tres píxeles en una esquina y parecía apagado.
   (Es el mismo defecto latente que tiene .mk-cursor en css/mockups.css.)
   Así que el que se mueve es una CAPA del tamaño del tablero —ahí el 50% sí
   es la mitad del tablero— y el punto va dibujado en su origen. Sigue siendo
   transform puro: no dispara layout. */
.vm-cursor {
  position: absolute; inset: 0; z-index: 5;
  pointer-events: none;
  opacity: 0;
  transform: translate3d(var(--cx, 50%), var(--cy, 50%), 0);
  transition: transform 900ms var(--ease-inout), opacity 400ms var(--ease-out);
}
.vm-cursor::before {
  content: ""; position: absolute; left: 0; top: 0;
  width: .6em; height: .6em; margin: -.3em 0 0 -.3em; border-radius: 50%;
  background: var(--vm-ink);
  box-shadow: 0 0 0 .3em color-mix(in srgb, var(--vm-ink) 16%, transparent);
  transition: transform 160ms var(--ease-out);
}
.vm-cursor.is-in { opacity: .85; }
.vm-cursor.is-click::before { transform: scale(.6); }

/* --------------------------------------------------------------------------
   8 · Reduced motion — defensa en profundidad. `.vista` entero ya se
   esconde con display:none antes de que nada de esto llegue a montarse
   (initVista() corta en coarse||reduceMotion), así que este bloque no
   debería ejecutarse nunca en la práctica — se deja igual, mismo criterio
   que el resto de los componentes animados del sitio.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .vm-cursor, .vm-typing { display: none; }
  .vm-k__v { clip-path: none !important; }
  .vm-k__sub, .vm-k__pie, .vm-dia__alerta, .vm-turno, .vm-lg,
  .vm-bubble, .vm-sysmark, .vm-fstrip { opacity: 1 !important; transform: none !important; }
  .vm-dona__seg { stroke-dasharray: var(--vm-arc) 238.76 !important; }
  .vm-rec__meta { height: auto !important; }
}
