/* ============================================================================
   V12 — Sistema de diseño
   ============================================================================
   Esta hoja es LA fuente de la estética del portal. Sale de las 7 referencias
   que eligió Mateo y de los mockups aprobados en el lienzo "Estructura del
   Portal V12". Cada componente dice de qué referencia viene.

   LA REGLA: ninguna pantalla nueva escribe estilos propios. Si algo no está
   acá, primero se agrega acá (y a /estilo, que es donde se ven todos juntos) y
   recién después se usa. Si una pantalla se sale del sistema, es un error del
   sistema, no de la pantalla.

   PALETA — la del portal, sin inventar nada:
     fondo #0d1a29 · panel #15263d · panel2 #1f3654 · acento #d6571a
   Un solo acento, como en la referencia Gofit: 20 pantallas sostenidas por un
   color. El naranja NUNCA es decoración: marca lo accionable o lo que urge.
   ============================================================================ */

:root {
  /* ── CAPA 1 · Los colores crudos ────────────────────────────────────────
     Cada color existe UNA vez, acá, y en ningún otro lado de la hoja. Van como
     canales sueltos para poder componer transparencias sin volver a escribir el
     número: el naranja estaba escrito NUEVE veces como "214, 87, 26" repartido
     por el archivo, y cambiar el acento del portal significaba encontrar las
     nueve y no equivocarse en ninguna.

     Esta capa NO se usa en un componente. Un componente usa la capa 2, que es
     la que dice para qué sirve cada color. Si escribís var(--c-…) dentro de una
     regla de componente, falta un nombre en la capa 2. */
  --c-noche: 13 26 41;
  --c-marino: 21 38 61;
  --c-marino-claro: 31 54 84;
  --c-marino-mas-claro: 36 61 94;
  --c-fuego: 214 87 26;
  --c-fuego-hondo: 166 62 12;
  --c-fuego-claro: 240 145 92;
  --c-blanco: 255 255 255;
  --c-negro: 0 0 0;
  --c-verde: 60 191 136;
  --c-verde-claro: 111 224 179;
  --c-ambar: 212 165 42;
  --c-ambar-claro: 232 200 96;
  --c-rojo: 224 88 88;
  --c-rojo-claro: 255 180 180;
  --c-hielo: 98 135 174;
  --c-hielo-claro: 156 192 230;
  --c-violeta: 139 92 246;

  /* ── CAPA 2 · Para qué sirve cada uno ───────────────────────────────────
     Estos son los nombres que usan los componentes. La regla que hace que la
     separación valga: en una regla de componente, `color:` toma un nombre de
     texto (--v12-txt / --v12-dim* / los *-claro), `background:` toma una
     superficie (--v12-bg / --v12-panel* / --v12-relleno) o un relleno de
     estado, y `border-color:` toma una línea. Un color de estado sin -claro
     NO es un color de texto: --v12-ok sobre el fondo oscuro da 3,6:1 en 12px.

     SIETE DE ESTOS SON HEX DE 6 DÍGITOS A PROPÓSITO y no pueden pasar a
     rgb(var(--c-…)): el portal del entrenador les pega el alfa al final del
     hex ("#d6571a" + "40") en unos 170 lugares, y "rgb(214 87 26)40" no es un
     color. Son --v12-o, --v12-ok, --v12-mal, --v12-frio, --v12-alerta,
     --v12-violeta y --v12-txt. Quedan al lado de su primitivo para que se vea
     que son el mismo color escrito dos veces por esa razón y no por descuido. */
  --v12-bg: rgb(var(--c-noche));
  --v12-panel: rgb(var(--c-marino));
  --v12-panel2: rgb(var(--c-marino-claro));
  --v12-panel3: rgb(var(--c-marino-mas-claro));
  --v12-o: #d6571a;                            /* = --c-fuego (ver arriba) */
  --v12-o-hondo: rgb(var(--c-fuego-hondo));
  --v12-o-suave: rgb(var(--c-fuego) / .16);
  --v12-o-borde: rgb(var(--c-fuego) / .40);

  /* Seis dígitos, no #fff: el portal del entrenador le pega el alfa al hex
     ("#ffffff" + "15") en unos 150 lugares, y "#fff15" no es un color. */
  --v12-txt: #ffffff;                         /* = --c-blanco (hex: le pegan alfa) */
  /* Un escalón entre el blanco pleno y el primer apagado: para texto corrido
     largo, donde el blanco puro cansa. */
  --v12-dim0: rgb(var(--c-blanco) / .82);
  --v12-dim: rgb(var(--c-blanco) / .62);
  /* .52 y no .38: a .38 daba 3,43:1 sobre el panel y este es el color de trece
     reglas de texto, incluida .v12-etiqueta, que es el rótulo de dato que viene
     de cuatro de las siete referencias. .52 da 5,16:1 sobre panel y 5,52:1
     sobre el fondo. El número está calculado, no elegido a ojo: .50 da 4,88:1 y
     no deja margen sobre --v12-panel2. */
  --v12-dim2: rgb(var(--c-blanco) / .52);
  /* NO es un escalón de texto: 2,03:1 no se lee. Es para marcas, hilos y
     puntos — cosas que se ven, no que se leen. Se llamaba --v12-dim3 y el
     nombre invitaba a usarlo como el cuarto gris de texto; por eso terminó
     pintando los días del calendario. */
  --v12-adorno: rgb(var(--c-blanco) / .22);

  --v12-line: rgb(var(--c-blanco) / .10);
  --v12-line-suave: rgb(var(--c-blanco) / .06);
  --v12-line-fuerte: rgb(var(--c-blanco) / .14);
  --v12-relleno: rgb(var(--c-blanco) / .05);
  /* El riel de una barra: el canal apagado sobre el que corre el relleno. Se
     escribía a mano en cuatro lugares (.v12-barra, .v12-mini, .v12-pastilla
     neutra y el riel de la regla). */
  --v12-riel: rgb(var(--c-blanco) / .07);

  /* Los dos estados que pintan la caja entera y no solo el borde. Estaban
     escritos con el rojo crudo en .v12-panel.urge y en .v12-fila.urge, que a
     propósito comparten valores: dos rojos distintos para "esto urge" serían
     dos vocabularios. */
  --v12-urge-borde: rgb(var(--c-rojo) / .35);
  --v12-urge-fondo: rgb(var(--c-rojo) / .07);
  --v12-ok-borde: rgb(var(--c-verde) / .35);
  --v12-ok-relleno: rgb(var(--c-verde) / .16);

  --v12-ok: #3cbf88;                          /* = --c-verde (hex: le pegan alfa) */
  --v12-alerta: #d4a52a;                      /* = --c-ambar (hex: le pegan alfa) */
  --v12-mal: #e05858;                         /* = --c-rojo (hex: le pegan alfa) */
  --v12-frio: #6287ae;                        /* = --c-hielo (hex: le pegan alfa) */

  /* Los mismos colores, aclarados para usarse como TEXTO. Un #3cbf88 sobre el
     fondo oscuro se lee mal en 12px; el aclarado sí. Son los que ya venían
     escritos a mano en `.v12-aviso` y en el panel del setter: acá dejan de
     estar sueltos en cada pantalla. */
  --v12-ok-claro: rgb(var(--c-verde-claro));
  --v12-alerta-claro: rgb(var(--c-ambar-claro));
  --v12-mal-claro: rgb(var(--c-rojo-claro));
  --v12-frio-claro: rgb(var(--c-hielo-claro));
  --v12-o-claro: rgb(var(--c-fuego-claro));

  --v12-r-chico: 8px;
  --v12-r: 12px;
  --v12-r-panel: 14px;
  --v12-r-pastilla: 999px;

  --v12-sombra: 0 14px 34px rgb(var(--c-negro) / .40);
  --v12-sombra-suave: 0 8px 24px rgb(var(--c-negro) / .30);
  --v12-fuente: 'Montserrat', system-ui, -apple-system, sans-serif;

  /* Nada que se toque baja de 44px: es el mínimo para un pulgar. */
  --v12-tocable: 44px;

  /* ── Piezas que el portal de entrenador ya usaba y el sistema no nombraba ──
     El SPA (dist/index.html) traía su paleta escrita tres veces adentro. Para
     que pueda leer de acá sin cambiar de aspecto, el sistema tuvo que ponerle
     nombre a lo que ese lado sí usa y este no tenía. Se agregan con el valor
     exacto que ya tenían: migrar no es rediseñar. */
  --v12-violeta: #8b5cf6;                     /* = --c-violeta (hex: le pegan alfa) */                     /* la 5ª serie de los gráficos */
  --v12-fuente-titulo: 'Varien', 'Montserrat', sans-serif;
  --v12-nav: rgb(var(--c-noche) / .82);           /* barra fija sobre contenido */
  --v12-o-brillo: 0 0 8px rgb(var(--c-fuego) / .60);
  --v12-o-degrade: linear-gradient(135deg, rgb(var(--c-fuego) / .22), rgb(var(--c-fuego) / .06));
  --v12-o-sombra: 0 10px 28px rgb(var(--c-fuego) / .32);   /* el botón principal levantado */
  --v12-r-capsula: 22px;

  /* Anillo de foco. Doble a propósito: el primer borde es del color del fondo,
     así separa el control de lo que tenga debajo, y el segundo pinta. De un
     solo color se pierde cuando el control está sobre un panel del mismo tono. */
  --v12-foco: 0 0 0 2px var(--v12-bg), 0 0 0 4px var(--v12-o-claro);
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }

body.v12 {
  background: var(--v12-bg);
  color: var(--v12-txt);
  font-family: var(--v12-fuente);
  -webkit-font-smoothing: antialiased;
  min-height: 100dvh;
}
.v12 a { color: var(--v12-o); }
/* Aclara, no oscurece: #b84813 bajaba el contraste de 4,38:1 a 3,32:1, o sea
   que el estado de foco del mouse dejaba el enlace MENOS legible. */
.v12 a:hover { color: var(--v12-o-claro); }

/* ── Contenedores ──────────────────────────────────────────────────────────
   El marco de una pantalla de celular (referencia 4 y 5): ancho acotado,
   centrado, y respetando la barra del sistema arriba y abajo. */
.v12-app {
  width: 100%; max-width: 460px; margin: 0 auto;
  min-height: 100dvh; display: flex; flex-direction: column;
  padding: max(20px, env(safe-area-inset-top)) 20px max(20px, env(safe-area-inset-bottom));
}
.v12-cuerpo { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.v12-pie { flex-shrink: 0; padding-top: 20px; }

/* Panel: la tarjeta base de todo el portal. */
.v12-panel {
  background: var(--v12-panel);
  border: 1px solid var(--v12-line);
  border-radius: var(--v12-r-panel);
  padding: 18px 20px;
}
.v12-panel.acento { border-color: var(--v12-o-borde); }
.v12-panel.urge { border-color: var(--v12-urge-borde); background: var(--v12-urge-fondo); }

/* ── Hoja de escritorio ────────────────────────────────────────────────────
   El sistema salió de las referencias de celular y su único contenedor es
   .v12-app (460px). Las dos referencias horizontales que eligió Mateo "para
   gráficos y tarjetas" son de escritorio y no tenían dónde vivir: cada pantalla
   se inventaba su ancho (1100 en /estilo, 1180 en /panel, 1080 escrito a mano
   en el portal). Tres anchos distintos y ninguno en el sistema. */
.v12-hoja { width: 100%; max-width: 1180px; margin: 0 auto; padding: 0 20px; }

/* ── Estados de bloque (vacío, cargando, error) ────────────────────────────
   Ninguna referencia los muestra, y por eso faltaban. Pero con la adherencia en
   0% en dos de cinco jugadores, el vacío NO es la excepción: es el estado que
   más se ve. El sistema ya había tomado esta decisión una vez, en .v12-kpi.vacia
   ("se marca a propósito, para que no parezca rota"); acá se generaliza. */
.v12-vacio {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 12px; padding: 26px 20px; border-radius: var(--v12-r-panel);
  border: 1px dashed var(--v12-line-fuerte); color: var(--v12-dim);
  font-size: 13px; line-height: 1.55;
}
/* Un mensaje no se estira: en escritorio queda del ancho de un párrafo legible. */
.v12-vacio > * { max-width: 420px; }
.v12-vacio svg { color: var(--v12-adorno); flex: 0 0 auto; }
.v12-vacio .v12-btn { width: auto; }
/* El mismo vacío, sin el aire de un estado de pantalla entera: es el hueco de
   un bloque sin ejercicios adentro de un formulario. */
.v12-vacio.angosta { padding: 13px 14px; font-size: 12px; gap: 7px; }

.v12-error {
  border-style: solid;
  border-color: color-mix(in srgb, var(--v12-mal) 35%, transparent);
  color: var(--v12-mal-claro);
}
/* Un error sin forma de reintentar obliga a recargar la pestaña. */

/* Esqueleto: bloques del alto de una fila. Es lo que la regla de rendimiento
   pide en vez de una ruedita cuando la espera pasa de 300ms — reserva el lugar
   y evita que la pantalla salte cuando llega el dato. */
.v12-cargando { display: flex; flex-direction: column; gap: 8px; }
.v12-cargando i {
  display: block; height: 62px; border-radius: var(--v12-r);
  background: linear-gradient(90deg, var(--v12-relleno) 25%,
              rgb(var(--c-blanco) / .09) 37%, var(--v12-relleno) 63%);
  background-size: 400% 100%;
  animation: v12-brillo 1.4s ease-in-out infinite;
}
@keyframes v12-brillo { from { background-position: 100% 0 } to { background-position: 0 0 } }

/* ── Cabecera de paso (referencia 5: título chico + puntos de avance) ────── */
.v12-top { display: flex; align-items: center; gap: 12px; padding-bottom: 18px; flex-shrink: 0; }
.v12-top-txt { font-size: 13px; font-weight: 750; }
.v12-top-sub { font-size: 11.5px; color: var(--v12-dim2); margin-top: 2px; }
.v12-volver {
  /* El chevron sale en currentColor: el color lo pone acá y no el SVG, así un
     ícono toma el color de lo que lo rodea en vez de traer el suyo. */
  color: var(--v12-dim0);
  background: none; border: 0; padding: 6px; margin: -6px; cursor: pointer;
  display: flex; align-items: center; justify-content: flex-start;
  min-width: var(--v12-tocable); min-height: var(--v12-tocable);
}
.v12-pasos { margin-left: auto; display: flex; gap: 5px; }
.v12-pasos i { display: block; width: 7px; height: 7px; border-radius: var(--v12-r-pastilla); background: var(--v12-adorno); }
.v12-pasos i.on { background: var(--v12-o); width: 20px; }
/* Lleno pero subordinado al actual: distinguía el paso en curso del resto
   apagado, y eso sirve para un formulario de 3 pasos, no para una lista donde
   importa cuántos quedaron atrás. */
.v12-pasos i.hecho { background: var(--v12-o); opacity: .45; }

/* ── Texto ─────────────────────────────────────────────────────────────── */
.v12-h1 { font-size: 23px; font-weight: 800; letter-spacing: -.4px; line-height: 1.28; }
.v12-h2 { font-size: 13px; font-weight: 750; }
.v12-ayuda { font-size: 13.5px; color: var(--v12-dim); margin-top: 8px; line-height: 1.5; }
.v12-rotulo { font-size: 15px; font-weight: 750; margin-top: 26px; }
.v12-rotulo .opc { font-size: 12px; font-weight: 600; color: var(--v12-dim2); margin-left: 8px; }
/* Rótulo de dato: mayúsculas chicas, como en las referencias 1, 3, 6 y 7. */
.v12-etiqueta {
  font-size: 10px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--v12-dim2);
}

/* ── REGLA 0-10 (referencia 5, Gofit) ───────────────────────────────────────
   El elemento distintivo de esa referencia y el que hace que el jugador
   conteste con el pulgar en vez de escribir. Marcas de verdad, no una barra:
   las pares altas, las impares bajas, y la elegida naranja y más alta todavía.
   El <input type=range> queda debajo para el teclado y los lectores de
   pantalla; el toque y el arrastre los maneja la pista, porque en iOS tocar un
   range NO mueve el pulgar y el jugador se queda mirando la pantalla. */
.v12-regla { text-align: center; margin-top: 26px; }
/* Sin tocar: el numero es un guion apagado, para que se vea que falta
   responder y no un valor de verdad. */
.v12-regla.sin-tocar .v12-regla-n { color: var(--v12-dim2); }
.v12-regla.sin-tocar .v12-regla-de { opacity: .4; }
.v12-regla-n {
  font-size: 62px; font-weight: 800; line-height: 1; letter-spacing: -2px;
  color: var(--v12-o); font-variant-numeric: tabular-nums;
}
.v12-regla-de { font-size: 19px; font-weight: 700; color: var(--v12-dim2); margin-left: 5px; }
.v12-regla-que { font-size: 13px; color: var(--v12-dim); margin-top: 9px; font-weight: 650; min-height: 20px; }

.v12-regla-pista {
  position: relative; margin-top: 22px; height: 62px;
  touch-action: none; cursor: pointer; user-select: none; -webkit-user-select: none;
}
.v12-regla-marcas {
  position: absolute; inset: 0 0 24px 0;
  display: flex; align-items: center; justify-content: space-between;
}
.v12-regla-marcas i {
  display: block; width: 2px; height: 14px; border-radius: 2px;
  background: var(--v12-adorno); flex: 0 0 auto;
}
.v12-regla-marcas i.par { height: 20px; background: rgb(var(--c-blanco) / .28); }
.v12-regla-marcas i.sel { width: 3.5px; height: 34px; background: var(--v12-o); }
.v12-regla-nums {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; justify-content: space-between;
  font-size: 11.5px; color: var(--v12-dim2); font-variant-numeric: tabular-nums;
}
.v12-regla-nums span { flex: 0 0 auto; width: 2px; display: flex; justify-content: center; }
.v12-regla-pista input[type=range] {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; margin: 0; cursor: pointer;
}

/* ── Fichas (referencia 4: chips de filtro / referencia 5: objetivos) ────── */
.v12-fichas { display: flex; flex-wrap: wrap; gap: 9px; margin-top: 14px; }
.v12-ficha {
  min-height: 46px; padding: 12px 17px; border-radius: var(--v12-r-pastilla);
  background: var(--v12-relleno); border: 1px solid var(--v12-line);
  color: var(--v12-dim0); font: inherit; font-size: 13.5px; font-weight: 650;
  cursor: pointer; display: inline-flex; align-items: center;
}
.v12-ficha[aria-pressed=true] {
  background: var(--v12-o); border-color: var(--v12-o); color: var(--v12-bg); font-weight: 800;
}
/* Variante chica, para filtros de una lista (no para respuestas). Chica es la
   tipografía y el padding horizontal; la ALTURA no baja. Tenía min-height:34px
   diez líneas después de que este archivo declarara --v12-tocable con el
   comentario "nada que se toque baja de 44px": la excepción estaba mal, no la
   regla. */
.v12-fichas.chicas .v12-ficha { padding: 6px 13px; font-size: 12px; }

/* ── Botones ───────────────────────────────────────────────────────────── */
.v12-btn {
  width: 100%; min-height: 54px; border: 0; border-radius: var(--v12-r);
  background: var(--v12-o); color: var(--v12-bg);
  font: inherit; font-size: 15.5px; font-weight: 800; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 9px;
}
/* .55 y no .4: a .4 el texto del botón quedaba por debajo de 2:1 y no se leía
   qué era lo que estaba deshabilitado. El cursor lo dice sin depender de la
   vista. */
.v12-btn[disabled] { opacity: .55; cursor: not-allowed; }
.v12-btn.suave {
  background: transparent; color: var(--v12-dim);
  font-weight: 650; min-height: 46px; font-size: 13.5px;
}
.v12-btn.linea {
  background: transparent; color: var(--v12-dim0);
  border: 1px solid var(--v12-line); font-weight: 700;
}
.v12-btn.angosto { width: auto; padding: 0 20px; min-height: 44px; font-size: 13px; }
/* La fila de acciones de un pie: la principal ocupa el resto y las angostas se
   quedan del ancho de su texto. Cada pantalla lo resolvía con un flex a mano. */
.v12-pie .acciones { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.v12-pie .acciones .v12-btn { flex: 1 1 160px; }
.v12-pie .acciones .v12-btn.angosto { flex: 0 0 auto; }

/* ── Estados ───────────────────────────────────────────────────────────────
   El sistema definía el estado por defecto de cada pieza y nada más: el único
   :focus en 403 líneas era el del campo de texto. Sin esto, la regla 0-10 y las
   filas de ejercicio —que se escribieron a propósito para andar con teclado— no
   muestran dónde estás parado.

   :focus-visible y no :focus: el anillo aparece cuando se navega con teclado y
   no cuando se toca con el dedo, que es donde molesta. */
.v12 :focus-visible {
  outline: none;
  box-shadow: var(--v12-foco);
  border-radius: inherit;
}

/* Hover: un escalón de relleno y el borde que ya existía sin usar
   (--v12-line-fuerte). No cambia el tamaño: mover el layout en hover hace
   saltar lo que está al lado. */
@media (hover: hover) {
  .v12-btn:not([disabled]):hover { filter: brightness(1.08); }
  .v12-ficha:not([aria-pressed=true]):hover,
  .v12-fila-cabeza:hover,
  .v12-stepper button:hover {
    background: var(--v12-relleno); border-color: var(--v12-line-fuerte);
  }
  .v12-fila:hover { border-color: var(--v12-line-fuerte); }
}
/* Apretado: 1px hacia abajo. Es la confirmación táctil que pide la regla 2
   cuando no hay vibración. */
.v12-btn:not([disabled]):active,
.v12-ficha:active,
.v12-stepper button:active { transform: translateY(1px); }

/* ── Campos ────────────────────────────────────────────────────────────── */
.v12-campo {
  width: 100%; margin-top: 12px; padding: 14px; border-radius: var(--v12-r);
  background: var(--v12-relleno); border: 1px solid var(--v12-line);
  color: var(--v12-txt); font: inherit; font-size: 16px; line-height: 1.5; outline: none;
}
textarea.v12-campo { min-height: 110px; resize: none; }
input.v12-campo.corto { width: 130px; }
/* El borde solo daba 2,10:1 contra el panel. El anillo del sistema lo cubre;
   acá queda el borde para que el campo se vea activo también sin teclado. */
.v12-campo:focus { border-color: var(--v12-o-borde); }
.v12-campo::placeholder { color: var(--v12-dim2); }
/* El desplegable es un campo más. No estaba en el sistema y por eso cada
   pantalla lo pintaba sola: en el planificador era una caja de 58px con las
   letras A B C D peladas, cuando el jugador del otro lado ya lee "B · Fuerza".
   La flecha va en background y no en un ::after, porque un <select> no admite
   pseudoelementos. */
select.v12-campo {
  appearance: none; -webkit-appearance: none;
  padding-right: 34px; cursor: pointer;
  /* El color de la flecha va literal y es el ÚNICO de la hoja que no sale de un
     token: adentro de un data: URI el SVG es una cadena de texto y las variables
     CSS no se resuelven. Es el valor de --v12-dim; si ese cambia, este también,
     a mano. */
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='rgba(255,255,255,.62)' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center;
}
/* El desplegable abierto lo pinta el sistema operativo y hereda el fondo de la
   página: sin esto, en Windows sale texto blanco sobre blanco. */
select.v12-campo option { background: var(--v12-panel); color: var(--v12-txt); }

/* ── Avisos ────────────────────────────────────────────────────────────── */
.v12-aviso {
  background: color-mix(in srgb, var(--v12-mal) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--v12-mal) 35%, transparent);
  color: var(--v12-mal-claro); border-radius: var(--v12-r-chico);
  padding: 12px 14px; font-size: 13px; line-height: 1.5; margin-top: 14px;
}
.v12-nota { font-size: 11.5px; color: var(--v12-dim2); text-align: center; margin-top: 13px; line-height: 1.5; }

/* ── Pantalla completa (cargando, listo, error) ────────────────────────── */
.v12-centro {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  justify-content: center; text-align: center; gap: 14px;
}
.v12-centro .v12-h1 { font-size: 24px; }
.v12-centro p { font-size: 14px; color: var(--v12-dim); line-height: 1.6; max-width: 330px; }
.v12-tilde {
  width: 62px; height: 62px; border-radius: var(--v12-r-pastilla);
  background: var(--v12-ok-relleno); color: var(--v12-ok);
  display: flex; align-items: center; justify-content: center; margin-bottom: 4px;
}

/* ── Tira de datos de la sesión (referencia 4: duración / calorías / nivel) ─ */
.v12-tira { display: flex; gap: 8px; margin-top: 14px; }
.v12-tira > div {
  flex: 1; background: var(--v12-panel); border: 1px solid var(--v12-line);
  border-radius: var(--v12-r); padding: 12px 10px; text-align: center;
}
.v12-tira .n { font-size: 17px; font-weight: 800; font-variant-numeric: tabular-nums; }
.v12-tira .u { font-size: 10px; color: var(--v12-dim2); margin-top: 3px; font-weight: 650; }

/* ── Nota del entrenador ───────────────────────────────────────────────── */
.v12-nota-coach {
  background: rgb(var(--c-fuego) / .09); border: 1px solid rgb(var(--c-fuego) / .32);
  border-radius: var(--v12-r); padding: 13px 14px; margin-top: 14px;
}
.v12-nota-coach .quien { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; }
/* Era .ini y sólo existía adentro de la nota del entrenador. Es la misma pieza
   que necesitan la fila de triage y la línea de tiempo, así que sale a la luz
   como .v12-inicial y la nota se queda con su variante naranja. */
.v12-inicial {
  width: 32px; height: 32px; flex: 0 0 auto; border-radius: var(--v12-r-pastilla);
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 800; letter-spacing: .02em;
  /* Neutro a propósito: NO lleva el color del riesgo. La severidad ya la dicen
     el borde de la fila y la pastilla; que el avatar la repita es codificar el
     mismo dato tres veces. */
  background: var(--v12-relleno); color: var(--v12-dim0);
}
.v12-inicial.chica  { width: 24px; height: 24px; font-size: 9.5px; }
.v12-inicial.grande { width: 40px; height: 40px; font-size: 13px; }
.v12-nota-coach .quien .v12-inicial { background: var(--v12-o); color: var(--v12-bg); }
.v12-nota-coach .quien span { font-size: 11.5px; font-weight: 750; color: var(--v12-o); }
.v12-nota-coach p { font-size: 13px; line-height: 1.55; color: var(--v12-dim0); }

/* ── Rótulo de bloque dentro de una sesión ─────────────────────────────── */
.v12-bloque {
  font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--v12-dim2); margin: 20px 0 9px;
}

/* ── Fila de ejercicio (referencia 4: lista de la rutina) ──────────────── */
.v12-fila {
  display: flex; align-items: center; gap: 12px;
  background: var(--v12-panel); border: 1px solid var(--v12-line);
  border-radius: var(--v12-r); padding: 10px 14px; margin-bottom: 8px;
}
.v12-fila.acento { border-color: var(--v12-o-borde); }
/* El escalón alto. Son los mismos valores que .v12-panel.urge a propósito: dos
   rojos distintos para "esto urge" serían dos vocabularios. Con .acento (medio)
   y la fila pelada (bajo) quedan tres escalones, que es lo que le faltaba a la
   pantalla Hoy para que un dolor de tres semanas no se vea igual que una carga
   estancada. */
.v12-fila.urge { border-color: var(--v12-urge-borde); background: var(--v12-urge-fondo); }
/* El ordinal, en el mismo slot donde va el tilde. Saca el ranking de las manos
   del color: "ordenado por urgencia" deja de ser una promesa escrita al costado
   y pasa a leerse. Cifras tabulares para que el 1 y el 10 ocupen lo mismo. */
.v12-fila-orden {
  width: 24px; flex: 0 0 auto; text-align: center;
  font-size: 13px; font-weight: 800; color: var(--v12-dim);
  font-variant-numeric: tabular-nums;
}
.v12-fila.hecha { border-color: var(--v12-ok-borde); }
/* Abierta: la fila se vuelve columna para que entre el contador debajo. */
.v12-fila.abierta { flex-direction: column; align-items: stretch; border-color: var(--v12-o-borde); }
/* La cabecera ocupa TODA la fila. Si solo ocupa el ancho del texto —que es lo
   que pasa por defecto dentro de un flex— el jugador toca a la derecha del
   nombre y no se abre nada. Es un botón de verdad para que ande con teclado. */
.v12-fila-cabeza {
  display: flex; align-items: center; gap: 12px;
  width: 100%; min-height: var(--v12-tocable); cursor: pointer; text-align: left;
  background: none; border: 0; padding: 0; color: inherit; font: inherit;
}
/* La fila de lista con severidad: dos renglones de texto con dos ranuras fijas
   a la izquierda. En grilla y no en flex porque el orden y la inicial tienen que
   ocupar las DOS líneas, y el detalle tiene que poder usar el ancho completo.
   Con flex, la pastilla le come el ancho al nombre y en un teléfono "Brian
   Plessen" se parte en dos renglones. */
.v12-fila.lista > .v12-fila-cabeza {
  display: grid; align-items: center; column-gap: 12px; row-gap: 2px;
  grid-template-columns: 24px 32px minmax(0, 1fr) auto;
  grid-template-areas:
    "orden inicial nombre  pastilla"
    "orden inicial detalle detalle";
}
.v12-fila.lista .v12-fila-orden   { grid-area: orden; }
.v12-fila.lista .v12-inicial      { grid-area: inicial; }
.v12-fila.lista .v12-fila-nombre  { grid-area: nombre; }
.v12-fila.lista .v12-fila-detalle { grid-area: detalle; margin-top: 0; }
.v12-fila.lista .v12-pastilla     { grid-area: pastilla; justify-self: end; }
/* Con lugar de sobra la pastilla se corre al costado y el texto respira: el
   detalle deja de tener que competir por el ancho. */
@media (min-width: 720px) {
  .v12-fila.lista > .v12-fila-cabeza {
    grid-template-columns: 24px 32px minmax(0, 1fr) auto;
    grid-template-areas:
      "orden inicial nombre  pastilla"
      "orden inicial detalle pastilla";
  }
  .v12-fila.lista .v12-pastilla { align-self: center; }
}
.v12-fila-tilde { width: 24px; height: 24px; flex-shrink: 0; }
.v12-fila-txt { flex: 1; min-width: 0; }
.v12-fila-nombre { font-size: 13.5px; font-weight: 650; line-height: 1.35; }
.v12-fila-detalle { font-size: 11.5px; color: var(--v12-dim2); margin-top: 4px; }
.v12-fila-detalle b { color: var(--v12-o); font-weight: 700; }
/* Modificador, no cambio de raíz: /sesion usa .v12-fila-detalle para la
   prescripción de una línea y tocarla ahí movería una pantalla que anda.
   Recorta por LÍNEAS y no por caracteres, así "rodilla izq · desde 06/07,
   último 08/07" entra entero en el teléfono en vez de morir en "desde 06/…". */
.v12-fila-detalle.dos {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; line-height: 1.4;
}

/* ── Contador de carga: el valor viene puesto, confirmar es un toque ───── */
.v12-stepper { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.v12-stepper button {
  width: var(--v12-tocable); height: var(--v12-tocable); flex-shrink: 0;
  border-radius: var(--v12-r-chico); background: var(--v12-relleno);
  border: 1px solid var(--v12-line); color: var(--v12-txt);
  font: inherit; font-size: 20px; font-weight: 700; cursor: pointer;
  display: flex; align-items: center; justify-content: center; line-height: 1;
}
.v12-stepper .valor {
  flex: 1; text-align: center; font-size: 22px; font-weight: 800;
  font-variant-numeric: tabular-nums; min-width: 0;
}
.v12-stepper .valor small { font-size: 12px; color: var(--v12-dim2); font-weight: 650; margin-left: 4px; }

/* ── Número con variación (referencias 3, 6 y 7) ───────────────────────── */
.v12-kpi { background: var(--v12-panel); border: 1px solid var(--v12-line); border-radius: var(--v12-r-panel); padding: 15px 16px; }
.v12-kpi.destaca { border-color: var(--v12-o-borde); }
.v12-kpi .n { font-size: 30px; font-weight: 800; line-height: 1.05; letter-spacing: -.6px; font-variant-numeric: tabular-nums; }
.v12-kpi.destaca .n { color: var(--v12-o); }
.v12-kpi .u { font-size: 12px; color: var(--v12-dim2); margin-left: 4px; font-weight: 600; }
.v12-kpi .d { font-size: 12.5px; font-weight: 750; margin-top: 9px; display: flex; align-items: center; gap: 5px; }
.v12-kpi .d.sube { color: var(--v12-ok); }
.v12-kpi .d.baja { color: var(--v12-mal); }
/* El rótulo debajo del número y la frase que lo explica. `.u` es la unidad que
   va PEGADA al número ("12 sesiones") y `.d` es el delta con peso y color
   ("+12% ↑"): ninguno de los dos sirve para una oración. El panel de entrevistas
   los tenía escritos aparte por eso. */
.v12-kpi .v12-etiqueta { display: block; margin-top: 8px; }
.v12-kpi .p { font-size: 11.5px; color: var(--v12-dim2); margin-top: 6px; line-height: 1.45; }
/* Tarjeta sin datos: se marca a propósito, para que no parezca rota.
   Es el estado que ninguna referencia muestra y el que más se va a ver. */
.v12-kpi.vacia { border-style: dashed; border-color: var(--v12-line-fuerte); }
.v12-kpi.vacia .n { font-size: 13.5px; font-weight: 700; color: var(--v12-dim); line-height: 1.4; }

/* ── Pastillas de estado (referencia 7) ────────────────────────────────── */
.v12-pastilla {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px; border-radius: var(--v12-r-pastilla);
  font-size: 11.5px; font-weight: 750; white-space: nowrap;
  background: var(--v12-riel); color: var(--v12-dim);
}
/* Los tres semánticos salen del token, no de un rgba() escrito a mano: cambiar
   --v12-ok cambia el fondo y el texto de una. (color-mix al 15% da exactamente
   el mismo color que el rgba que había antes.) */
.v12-pastilla.ok     { --v12-p: var(--v12-ok);     --v12-p-txt: var(--v12-ok-claro); }
.v12-pastilla.alerta { --v12-p: var(--v12-alerta); --v12-p-txt: var(--v12-alerta-claro); }
.v12-pastilla.mal    { --v12-p: var(--v12-mal);    --v12-p-txt: var(--v12-mal-claro); }
.v12-pastilla.frio   { --v12-p: var(--v12-frio);   --v12-p-txt: var(--v12-frio-claro); }
.v12-pastilla.acento { --v12-p: var(--v12-o);      --v12-p-txt: var(--v12-o-claro); }
.v12-pastilla.ok, .v12-pastilla.alerta, .v12-pastilla.mal,
.v12-pastilla.frio, .v12-pastilla.acento {
  background: color-mix(in srgb, var(--v12-p) 15%, transparent);
  /* El tono claro, no el pleno: el pleno da 3,3-4,1:1 a 11,5px. El relleno al
     15% ya aporta el color; el texto no tiene por qué repetirlo y perder
     legibilidad. --v12-p-txt ya estaba declarado en cada estado y sólo lo
     usaba la variante .contorno. */
  color: var(--v12-p-txt);
  padding-left: 9px;
}
/* La FORMA cambia con el estado, no sólo el color. Es la regla 1 de
   accesibilidad: la información no puede viajar únicamente en el color, y un
   entrenador daltónico tiene que poder separar "subió" de "duele". Va como
   ::before para que no se pueda olvidar — antes era un <span class="punto">
   opcional y cuatro de las seis pastillas de /estilo no lo llevaban. */
.v12-pastilla.ok::before, .v12-pastilla.alerta::before, .v12-pastilla.mal::before,
.v12-pastilla.frio::before, .v12-pastilla.acento::before {
  content: ""; width: 7px; height: 7px; flex: 0 0 auto; background: currentColor;
}
.v12-pastilla.ok::before     { border-radius: var(--v12-r-pastilla); }                    /* círculo */
.v12-pastilla.alerta::before { clip-path: polygon(50% 0, 100% 100%, 0 100%); }            /* triángulo */
.v12-pastilla.mal::before    { transform: rotate(45deg); }                                /* rombo */
.v12-pastilla.acento::before { width: 3px; height: 10px; border-radius: 2px; }            /* barra */
.v12-pastilla.frio::before   {
  border-radius: var(--v12-r-pastilla);
  background: none; box-shadow: inset 0 0 0 1.5px currentColor;                           /* anillo */
}

/* Con contorno: la misma pastilla cuando tiene que sostenerse sola sobre un
   fondo que cambia —una fila de lista, una tarjeta— y el relleno al 15% no
   alcanza para separarla. El texto sube al tono claro porque el borde ya
   aporta el color y así se lee a 11px. */
.v12-pastilla.contorno {
  border: 1px solid color-mix(in srgb, var(--v12-p, #fff) 38%, transparent);
  color: var(--v12-p-txt, var(--v12-dim));
}

/* ── Barra etiquetada (referencia 6) ───────────────────────────────────── */
.v12-barra-fila { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 5px; }
.v12-barra-fila .t { font-size: 12.5px; color: var(--v12-dim0); }
.v12-barra-fila .n { font-size: 12.5px; font-weight: 700; font-variant-numeric: tabular-nums; }
.v12-barra { height: 7px; background: var(--v12-riel); border-radius: 4px; overflow: hidden; margin-bottom: 13px; }
.v12-barra i { display: block; height: 100%; background: var(--v12-panel2); border-radius: 4px; }
.v12-barra i.acento { background: var(--v12-o); }

/* ── Línea de tiempo (referencia 7) ────────────────────────────────────── */
.v12-linea { display: flex; gap: 13px; padding-bottom: 15px; }
.v12-linea-eje { display: flex; flex-direction: column; align-items: center; flex-shrink: 0; }
.v12-linea-eje .punto { width: 10px; height: 10px; border-radius: var(--v12-r-pastilla); background: var(--v12-adorno); margin-top: 4px; }
.v12-linea-eje .punto.mal { background: var(--v12-mal); }
.v12-linea-eje .punto.acento { background: var(--v12-o); }
.v12-linea-eje .hilo { width: 1.5px; flex: 1; background: var(--v12-line-suave); margin-top: 4px; }
.v12-linea-txt { flex: 1; }
.v12-linea-fecha { font-size: 12px; font-weight: 700; color: var(--v12-dim); }
.v12-linea-detalle { font-size: 12.5px; color: var(--v12-dim0); margin-top: 4px; line-height: 1.5; }

/* ── Calendario de adherencia (referencia 2 y 3) ───────────────────────── */
.v12-cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 5px; text-align: center; }
.v12-cal .dia { font-size: 11px; padding: 6px 0; border-radius: 6px; color: var(--v12-dim2); }
.v12-cal .dia.fuera { color: var(--v12-dim2); }   /* es texto: 2,03:1 no alcanzaba */
.v12-cal .dia.hecha { background: rgb(var(--c-verde) / .22); color: var(--v12-ok); font-weight: 700; }
.v12-cal .dia.perdida { background: rgb(var(--c-rojo) / .20); color: var(--v12-mal); font-weight: 700; }
.v12-cal .dia.hoy { border: 1px solid var(--v12-o-borde); color: var(--v12-o); font-weight: 800; }
.v12-cal-cab { font-size: 9.5px; color: var(--v12-dim2); }   /* idem */

/* ── Delta: la variación con forma ─────────────────────────────────────────
   Ref 6 (barras etiquetadas) cruzada con 3 y 7 (números con variación). Es lo
   que Mateo pidió de las dos referencias horizontales: "más para gráficos y
   tarjetas".

   El cero queda SIEMPRE en la misma x, así las filas se comparan entre sí de un
   vistazo: hoy "+8,3%" y "+33,3%" son dos textos grises del mismo largo y
   llevan la misma pastilla "Subió", cuando uno subió cuatro veces más que el
   otro. La escala la fija la tabla en --pct (normalizado contra el máximo
   absoluto de la columna), no cada fila por su cuenta. */
.v12-delta { display: flex; align-items: center; gap: 9px; }
.v12-delta .pista {
  position: relative; flex: 1; min-width: 70px; height: 7px;
  border-radius: 4px; background: var(--v12-riel);
}
/* El hilo del cero. Sin él la barra flota y no se sabe desde dónde crece. */
.v12-delta .pista::before {
  content: ""; position: absolute; left: 50%; top: -2px; bottom: -2px;
  width: 1px; background: var(--v12-adorno);
}
.v12-delta i {
  position: absolute; top: 0; height: 7px; border-radius: 4px;
  width: calc(var(--pct, 0) * 50%);
}
.v12-delta i.sube { left: 50%; background: var(--v12-ok); }
.v12-delta i.baja { right: 50%; background: var(--v12-o); }
.v12-delta span {
  flex: 0 0 auto; min-width: 52px; text-align: right;
  font-size: 11.5px; font-weight: 700; color: var(--v12-dim0);
  font-variant-numeric: tabular-nums;
}

/* ── Selector de ámbito ────────────────────────────────────────────────────
   Ref 4 (chips de filtro) llevada al lado del entrenador. Ya estaba diseñada
   fuera del sistema: es `.periodo` del panel de entrevistas. Esto es mudanza,
   no diseño nuevo.
   El activo NO va en naranja: el acento se reserva para lo accionable, y un
   filtro puesto es un estado, no una acción. */
.v12-segmentado {
  display: inline-flex; max-width: 100%; overflow-x: auto;
  background: var(--v12-panel); border: 1px solid var(--v12-line);
  border-radius: var(--v12-r); overflow-y: hidden;
}
.v12-segmentado button {
  flex: 1 0 auto; min-height: var(--v12-tocable); padding: 0 16px;
  background: none; border: 0; color: var(--v12-dim);
  font: inherit; font-size: 12.5px; font-weight: 650; cursor: pointer;
  white-space: nowrap;
}
.v12-segmentado button[aria-pressed=true] {
  background: var(--v12-panel2); color: var(--v12-txt); font-weight: 800;
}

/* ── Pestañas (referencia 1: la de fondo negro con detalles violetas) ──────
   Es la pieza que Mateo señaló primero de esa referencia: "tiene todas las
   pestañas para poder usar de base y mejorar la vista del deportista". Estaba
   escrita a mano en la barra de la ficha y en ningún otro lado, así que la
   referencia que él eligió como base no existía en el sistema.

   Se distingue de .v12-segmentado por el trabajo, no por el gusto: un
   segmentado filtra la lista que ya estás mirando, una pestaña cambia lo que
   estás mirando. Por eso una se rellena y la otra se subraya. */
.v12-pestanas {
  display: flex; gap: 2px; overflow-x: auto; -webkit-overflow-scrolling: touch;
  border-bottom: 1px solid var(--v12-line); scrollbar-width: none;
}
.v12-pestanas::-webkit-scrollbar { display: none; }
.v12-pestanas button {
  flex: 0 0 auto; min-height: var(--v12-tocable); padding: 0 14px;
  /* Pisa el borde del contenedor: sin esto el subrayado de la activa queda
     flotando un pixel arriba de la línea. */
  margin-bottom: -1px;
  background: none; border: 0; border-bottom: 2px solid transparent;
  color: var(--v12-dim); font: inherit; font-size: 13px; font-weight: 700;
  white-space: nowrap; cursor: pointer;
}
.v12-pestanas button[aria-pressed=true] {
  color: var(--v12-txt); border-bottom-color: var(--v12-o);
}
@media (hover: hover) {
  .v12-pestanas button:not([aria-pressed=true]):hover { color: var(--v12-dim0); }
}

/* ── Tablas que no rompen el celular ───────────────────────────────────── */
.v12-tabla { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.v12-tabla table { width: 100%; border-collapse: collapse; min-width: 460px; }
.v12-tabla th {
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em;
  color: var(--v12-dim2); text-align: left; padding: 0 10px 10px 0;
}
.v12-tabla td { padding: 12px 10px; border-top: 1px solid var(--v12-line); font-size: 12.5px; vertical-align: middle; }
.v12-tabla td:first-child, .v12-tabla th:first-child { padding-left: 0; }
/* Cifras a la derecha y tabulares. Como clase y no en `td` a secas, para no
   forzar tabular en las columnas de texto: era el único componente de datos del
   sistema sin cifras tabulares, y sin eso las columnas de números bailan. */
.v12-tabla td.num, .v12-tabla th.num { text-align: right; font-variant-numeric: tabular-nums; }
/* Cabecera ordenable: el <th> lleva aria-sort y adentro va un botón de ancho
   completo, porque lo que se toca tiene que ser un botón y medir 44px. */
.v12-tabla th.orden { padding: 0; }
.v12-tabla th.orden button {
  display: flex; align-items: center; gap: 5px; width: 100%;
  min-height: var(--v12-tocable); padding: 0 10px 0 0;
  background: none; border: 0; cursor: pointer; color: inherit;
  font: inherit; font-size: 10.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .07em;
}
.v12-tabla th.orden.num button { justify-content: flex-end; }
.v12-tabla th.orden:first-child button { padding-left: 0; }
.v12-tabla th.orden button:hover { color: var(--v12-txt); }
.v12-tabla th[aria-sort]:not([aria-sort=none]) button { color: var(--v12-txt); }
.v12-tabla th.orden .flecha { opacity: 0; flex: 0 0 auto; }
.v12-tabla th[aria-sort]:not([aria-sort=none]) .flecha { opacity: 1; color: var(--v12-o); }
.v12-tabla th[aria-sort=descending] .flecha { transform: rotate(180deg); }


/* ── Semana (refs 2 y 3: calendario de adherencia · ref 4: objetivos tocables) ─
   La unidad del planificador deja de ser la fecha suelta y pasa a ser la
   semana. Mateo planifica por día de semana ("el martes va fuerza"), no por
   número, y hasta ahora la pantalla mostraba dos fechas sueltas sin decir
   cuántos días de esa semana quedaban vacíos.

   Esta pieza sola mata tres problemas: el <input type=date> pintado por el
   navegador en formato de Estados Unidos (08/26/2026) desaparece porque el día
   se elige acá; aparece el contexto de semana; y el choque de guardar sobre una
   fecha ya ocupada se ve ANTES de tocar, porque el día cargado ya viene marcado.

   Una pieza con dos densidades, no dos piezas: mismo modelo de datos (7 días
   con estado), misma semántica, distinta caja. `.grilla` es la de escritorio.

   NO la cubre .v12-cal: esa es de sólo lectura, su .dia es un div de 11px sin
   semántica de botón, y sus estados describen el pasado en vez de ofrecer
   elegir un día futuro. Acá se reusan sus tokens de estado y su grilla de 7. */
.v12-semana {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
  gap: 8px 10px; margin-bottom: 16px;
}
.v12-semana-nav {
  width: var(--v12-tocable); height: var(--v12-tocable);
  display: grid; place-items: center;
  background: var(--v12-panel); border: 1px solid var(--v12-line);
  border-radius: var(--v12-r-chico); color: var(--v12-txt);
  font: inherit; font-size: 17px; line-height: 1; cursor: pointer;
}
.v12-semana-nav[disabled] { opacity: .55; cursor: not-allowed; }
.v12-semana-txt {
  text-align: center; font-size: 13.5px; font-weight: 750;
  font-variant-numeric: tabular-nums;
}
.v12-semana-txt small {
  display: block; font-size: 11.5px; font-weight: 600; color: var(--v12-dim2);
  margin-top: 2px; text-transform: none; letter-spacing: 0;
}
.v12-semana-dias {
  grid-column: 1 / -1;
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 5px;
}
/* 7 × 44 = 308px: entra en los 350 de contenido de un celular de 390. */
.v12-semana .dia {
  min-height: 56px; min-width: var(--v12-tocable);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  background: var(--v12-panel); border: 1px solid var(--v12-line);
  border-radius: var(--v12-r-chico); color: var(--v12-dim);
  font: inherit; cursor: pointer; padding: 6px 2px;
}
.v12-semana .dia em {
  font-style: normal; font-size: 9.5px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--v12-dim2);
}
.v12-semana .dia b {
  font-size: 15px; font-weight: 750; color: var(--v12-txt);
  font-variant-numeric: tabular-nums; line-height: 1.1;
}
/* La marca de estado. Reserva su lugar siempre para que el número no salte
   cuando un día pasa de vacío a cargado. */
.v12-semana .dia i {
  width: 6px; height: 6px; border-radius: 50%; background: none; flex: 0 0 auto;
}
.v12-semana .dia.cargada i { background: var(--v12-o); }
/* Verde Y tilde: el color solo no alcanza, y "cargada" contra "hecha" es
   justamente la distinción que Mateo mira de un vistazo. */
.v12-semana .dia.hecha i {
  width: 9px; height: 9px; border-radius: 0; background: none;
  border-bottom: 2px solid var(--v12-ok); border-right: 2px solid var(--v12-ok);
  transform: rotate(45deg) translate(-1px, -1px);
}
.v12-semana .dia.hoy { border-color: var(--v12-o-borde); }
.v12-semana .dia.hoy em { color: var(--v12-o); }
.v12-semana .dia[aria-pressed=true] {
  background: var(--v12-panel2); border-color: var(--v12-line-fuerte);
}
.v12-semana .dia[aria-pressed=true] b { color: var(--v12-txt); }

/* ── Bloque con su cuenta (ref 4: la rutina agrupada, cada grupo con su estado) ─
   "B · FUERZA … 2/2". El rótulo solo decía el nombre; el conteo al lado es lo
   que dice si el bloque está completo sin abrirlo. Va la palabra además del
   tono, porque el verde solo no es información. */
.v12-bloque { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.v12-bloque .cuenta {
  font-variant-numeric: tabular-nums; color: var(--v12-dim2);
  letter-spacing: 0; text-transform: none; font-size: 10.5px;
}
.v12-bloque .cuenta.completo { color: var(--v12-ok-claro); }

/* ── Tarjeta del día (referencia 4: la lista de la rutina · ref 7: pastillas) ─
   Lo que hay en un día y NO es la sesión: la nota de Mateo, el formulario, el
   test de salto, el pedido de video. Sale de la plantilla.

   El ícono dice de qué se trata ANTES de leer, y el borde izquierdo lo repite
   con forma: una nota y un test no se confunden de reojo. Las cuatro comparten
   caja porque son la misma cosa —algo que hacer hoy que no es entrenar— y lo
   que cambia es qué. */
.v12-tarjeta {
  display: flex; gap: 12px; align-items: flex-start;
  background: var(--v12-panel); border: 1px solid var(--v12-line);
  border-left: 3px solid var(--v12-adorno);
  border-radius: var(--v12-r); padding: 14px 16px; margin-bottom: 8px;
}
.v12-tarjeta .ico { flex: 0 0 auto; color: var(--v12-dim); margin-top: 1px; }
.v12-tarjeta .txt { flex: 1; min-width: 0; }
.v12-tarjeta h3 { font-size: 13.5px; font-weight: 750; }
.v12-tarjeta p { font-size: 12.5px; color: var(--v12-dim0); line-height: 1.55; margin-top: 5px; }
.v12-tarjeta .v12-btn { margin-top: 12px; }
/* Cada tipo con su color y su ícono. El test y el video son pedidos con fecha,
   así que van en el acento; la nota es contexto y queda neutra. */
.v12-tarjeta.test  { border-left-color: var(--v12-o); }
.v12-tarjeta.test .ico  { color: var(--v12-o); }
.v12-tarjeta.video { border-left-color: var(--v12-o); }
.v12-tarjeta.video .ico { color: var(--v12-o); }
.v12-tarjeta.formulario { border-left-color: var(--v12-frio); }
.v12-tarjeta.formulario .ico { color: var(--v12-frio-claro); }
.v12-tarjeta.nota .ico { color: var(--v12-dim2); }
/* Hecha: el verde Y el tilde, nunca el color solo. */
.v12-tarjeta.hecha { border-left-color: var(--v12-ok); opacity: .72; }
.v12-tarjeta.hecha .ico { color: var(--v12-ok); }

/* ── Series de un ejercicio ────────────────────────────────────────────────
   Una fila por serie, para cuando la pauta NO es la misma en todas: "15 seg,
   30, 45, 60" es una rampa, no cuatro veces 15. Sale del export real de
   TeamBuildr, donde la mitad de las prescripciones son así.

   Es una tabla y no cuatro campos sueltos porque lo que importa es leer la
   columna: si las cuatro series de reps se leen una debajo de la otra, la
   progresión se ve; en línea, no. */
.v12-series { margin-top: 10px; }
/* Las columnas se declaran, no se asumen: un ejercicio sin carga tiene dos
   (volumen y RPE) y uno que pide dos alturas tiene cuatro. Con las tres fijas
   que había, el que pedía caída Y cajón se salía de la grilla. */
.v12-series { --v12-series-cols: 3; }
.v12-series .cab,
.v12-series .fila {
  display: grid;
  grid-template-columns: 34px repeat(var(--v12-series-cols), minmax(0, 1fr));
  gap: 8px;
  align-items: center;
}
.v12-series .cab { margin-bottom: 5px; }
.v12-series .cab span {
  font-size: 10px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--v12-dim2);
}
.v12-series .fila { margin-bottom: 6px; }
.v12-series .nro {
  font-size: 12px; font-weight: 750; color: var(--v12-dim);
  font-variant-numeric: tabular-nums; text-align: center;
}
/* Más apretados que un campo suelto: son doce en la misma tarjeta y con el alto
   de siempre la tarjeta mide media pantalla. El toque sigue en 44. */
.v12-series .v12-campo { margin-top: 0; padding: 10px 12px; font-size: 15px; min-height: var(--v12-tocable); }

/* ── Grilla de semanas (referencia 2 y 3: el calendario) ──────────────────
   La plantilla entera de un vistazo: una fila por semana, siete columnas de
   días, y adentro lo que hay ese día. Es el pedido textual de Mateo —
   "poder planificar plazos de varias semanas" — y lo que hace que un programa
   de 13 semanas se lea sin abrir semana por semana.

   Siete columnas no entran en 390px y no se achican sin volverse ilegibles:
   la grilla se desliza sola adentro de su caja, como .v12-tabla. La columna de
   la semana queda pegada, porque perder de vista en qué semana estás mientras
   scrolleás al costado es perder la única referencia. */
.v12-grilla { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.v12-grilla > * { min-width: 760px; }
.v12-grilla .cab,
.v12-grilla .fila {
  display: grid; grid-template-columns: 74px repeat(7, minmax(0, 1fr)); gap: 8px;
}
.v12-grilla .cab { margin-bottom: 8px; }
.v12-grilla .cab span {
  font-size: 9.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--v12-dim2); padding-left: 2px;
}
.v12-grilla .fila { margin-bottom: 8px; align-items: stretch; }
.v12-grilla .sem {
  position: sticky; left: 0; z-index: 2;
  background: var(--v12-bg); padding: 10px 8px 0 0;
  font-size: 11.5px; font-weight: 750; color: var(--v12-dim0);
  font-variant-numeric: tabular-nums;
}
.v12-grilla .sem small { display: block; font-size: 10px; font-weight: 600; color: var(--v12-dim2); margin-top: 2px; }
.v12-grilla .dia {
  background: var(--v12-relleno); border: 1px solid var(--v12-line-suave);
  border-radius: var(--v12-r-chico); padding: 6px; min-height: 62px;
  display: flex; flex-direction: column; gap: 5px;
}
.v12-grilla .dia.hoy { border-color: var(--v12-o-borde); }
/* El botón de agregar ocupa lo que sobra de la celda, así que tocar el vacío
   de un día es agregarle algo. Con celdas de 62px, un + de 44 no entraba. */
.v12-grilla .dia .mas {
  flex: 1 0 auto; min-height: 28px; width: 100%;
  background: none; border: 0; border-radius: 6px;
  color: var(--v12-dim2); font: inherit; font-size: 15px; cursor: pointer;
}
@media (hover: hover) { .v12-grilla .dia .mas:hover { background: var(--v12-relleno); color: var(--v12-txt); } }

/* La tarjeta chica de la grilla. Es la misma tarjeta del día, apretada: mismo
   vocabulario de color y de ícono, para que lo que Mateo ve en la plantilla y
   lo que el jugador ve en su pantalla se lean igual. */
.v12-tarjeta.mini {
  display: block; width: 100%; text-align: left;
  padding: 7px 8px; margin: 0; border-radius: 6px;
  font: inherit; font-size: 11px; font-weight: 650; line-height: 1.3;
  color: var(--v12-dim0); cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── Ejercicios unidos ─────────────────────────────────────────────────────
   La letra que une: A1 y A2 se hacen seguidos, sin descanso en el medio. Es lo
   que en la planilla de Mateo queda pegado, y lo que el bloque con nombre
   liberó — antes la letra estaba ocupada diciendo de qué sección era el
   ejercicio, así que no se podía unir nada.

   Va el hilo Y la frase. El hilo solo diría "estos dos tienen algo que ver";
   lo que el jugador necesita saber es que no descansa en el medio, y eso hay
   que escribirlo. */
.v12-unidos {
  display: flex; align-items: center; gap: 7px;
  margin: 15px 0 7px; font-size: 11.5px; font-weight: 700; color: var(--v12-o-claro);
}
.v12-unidos::before {
  content: ""; flex: 0 0 auto; width: 3px; height: 13px;
  border-radius: 2px; background: var(--v12-o);
}
/* El hilo a la izquierda de cada fila del grupo. Sobre la fila y sobre la
   tarjeta del editor, que son las dos caras del mismo ejercicio: el jugador lo
   ve en /sesion y Mateo lo arma en el planificador. */
.v12-fila.unido, .v12-arrastrable.unido { border-left: 3px solid var(--v12-o-borde); }

/* ── Pie fijo (ref 4: barra de acción fija) ────────────────────────────────
   --v12-nav estaba declarado desde el primer día con el comentario "barra fija
   sobre contenido" y NINGUNA clase lo usaba: la decisión estaba tomada y
   faltaba la pieza. La necesitan /sesion (con 9 ejercicios la CTA queda en
   y=1250 de una página de 1371px) y el editor del planificador a 390px. */
.v12-pie.fija {
  position: sticky; bottom: 0; z-index: 20;
  background: var(--v12-nav); backdrop-filter: blur(12px);
  border-top: 1px solid var(--v12-line);
  margin: 16px -20px 0; padding: 14px 20px max(14px, env(safe-area-inset-bottom));
}

/* ── Arrastrar (pedido textual de Mateo: "afinamos bien lo que es drag and drop") ─
   No sale de una referencia visual. Es la tarjeta que se agarra, la manija de
   44px —que es lo que evita que arrastrar y hacer scroll se peleen en el
   celular—, el hueco punteado que muestra dónde va a caer, y la tarjeta
   levantada mientras viaja.

   ES MUDANZA Y BAUTISMO, NO DISEÑO NUEVO: el comportamiento ya existía y
   andaba, pero su CSS vivía dentro de una cadena de texto en src/app.js con
   nombres `tdnd-*` y el naranja escrito a mano tres veces.
   Acá pasa a ser una pieza del sistema con los tokens del sistema. */
.v12-arrastrable {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--v12-panel); border: 1px solid var(--v12-line);
  border-radius: var(--v12-r); padding: 10px 12px; margin-bottom: 8px;
}
/* Botón de ícono: 44×44 sin caja. El sistema no tenía ninguno y por eso cada
   pantalla resolvía la × y las flechas con un .v12-btn achicado (que trae ancho
   completo y fondo naranja) o con un <span> con onClick. El agarre y las
   flechas de mover son dos casos del mismo botón. */
.v12-icono, .v12-agarre, .v12-mover button {
  flex: 0 0 auto;
  width: var(--v12-tocable); height: var(--v12-tocable);
  display: grid; place-items: center;
  background: none; border: 0; border-radius: var(--v12-r-chico);
  color: var(--v12-dim2); cursor: pointer; font: inherit; font-size: 17px; line-height: 1;
}
@media (hover: hover) {
  .v12-icono:not([disabled]):hover, .v12-agarre:hover, .v12-mover button:not([disabled]):hover {
    color: var(--v12-txt); background: var(--v12-relleno);
  }
  .v12-icono.peligro:not([disabled]):hover { color: var(--v12-mal-claro); }
}
.v12-icono[disabled] { opacity: .3; cursor: not-allowed; }
.v12-agarre {
  cursor: grab;
  /* Sin esto el navegador se queda el gesto para hacer scroll y el arrastre
     nunca arranca en el celular. */
  touch-action: none;
}
.v12-agarre:active { cursor: grabbing; }
/* El hueco: dónde va a caer. Punteado y no relleno, porque no es contenido. */
.v12-hueco {
  pointer-events: none; flex-shrink: 0;
  border-radius: var(--v12-r);
  border: 2px dashed var(--v12-o-borde);
  background: repeating-linear-gradient(135deg,
    var(--v12-o-suave) 0 10px, rgb(var(--c-fuego) / .05) 10px 20px);
  animation: v12Latir 1.1s ease-in-out infinite;
}
@keyframes v12Latir { 0%, 100% { opacity: .9 } 50% { opacity: .55 } }
/* La tarjeta mientras viaja. Acá es donde --v12-sombra y --v12-r-capsula, que
   estaban declarados y sin usar, encuentran su uso real. */
.v12-arrastrando {
  position: fixed; left: 0; top: 0; margin: 0 !important; z-index: 9999;
  pointer-events: none; border-radius: var(--v12-r);
  box-shadow: var(--v12-sombra), 0 4px 14px rgb(var(--c-negro) / .4);
  will-change: transform, left, top;
}
.v12-viajando { display: none !important; }
.v12-reacomodando { transition: transform 260ms cubic-bezier(.2, .85, .25, 1) !important; }
body.v12-arrastre { cursor: grabbing !important; user-select: none !important; -webkit-user-select: none !important; }
.v12-zona-activa { outline: 2px dashed var(--v12-o); outline-offset: -2px; }

/* ── Mover sin puntero ─────────────────────────────────────────────────────
   Toda interacción de arrastre necesita una alternativa que no dependa del
   puntero, o la pantalla no se puede usar con teclado ni con lector. Son dos
   botones de 44px en la tarjeta, no un menú: un menú sería la primera pieza de
   superposición del sistema y esa decisión define cómo se ven todas las que
   vengan después — no se toma de costado para resolver un reordenamiento. */
.v12-mover { display: flex; flex-direction: column; flex: 0 0 auto; }
/* 44 CADA UNO, no 22 y 22 sumando 44: el mínimo es por objetivo, no por par.
   La primera versión los apiló a 22px y la prueba de /estilo la agarró. */
.v12-mover button { font-size: 11px; }
.v12-mover button[disabled] { opacity: .3; cursor: not-allowed; }

/* ── Sólo para lectores de pantalla ────────────────────────────────────────
   Donde cae el anuncio de cada movimiento ("Peso Muerto, 2 de 6"). Sin esto la
   alternativa por teclado es muda: el foco se mueve y nada dice qué pasó. El
   portal no tenía ni la clase ni una sola región viva. */
.v12-solo-lectores {
  position: absolute; width: 1px; height: 1px;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

/* ── Nada de esto se anima si la persona pidió que no ──────────────────── */
@media (prefers-reduced-motion: reduce) {
  .v12 *, .v12 *::before, .v12 *::after { animation: none !important; transition: none !important; }
}
