.kfb-logo-wrap {
  position: relative;
  /* El color EXACTO del fondo del video, medido de sus propias
     esquinas: rgb(43,38,37). El video es vertical y el marco es un
     círculo, así que a los costados sobra lugar. Ese hueco se pinta
     de este color y el borde del video desaparece: no se ve dónde
     termina el archivo y dónde empieza el fondo.
     Antes se resolvía recortando (object-fit: cover) y eso comía
     parte del logo. No se recorta: se rellena. */
  background: #2b2625;
  border-radius: 50%;
  overflow: hidden;
  border: 1px solid rgba(201, 169, 110, .7);
  animation: kfbFloat 4.5s ease-in-out infinite alternate, kfbGlow 4s ease-in-out infinite;
}
/* La llama dibujada: se ve al instante y no depende de la red.
   Queda debajo del video, que la tapa recién cuando arranca. */
.kfb-logo-fija {
  position: absolute;
  inset: 12%;
  width: 76%;
  height: 76%;
  filter: drop-shadow(0 0 6px rgba(245, 166, 35, .55));
}

.kfb-logo-video {
  position: relative;
  z-index: 1;
  /* Arranca invisible: si el video nunca decodifica, un <video>
     vacío es un rectángulo negro tapando la llama dibujada. Se
     muestra recién cuando el evento `playing` confirma que hay
     imagen de verdad. */
  opacity: 0;
  transition: opacity .45s ease;
  width: 100%;
  height: 100%;
  /* `contain`: entra el cuadro ENTERO, sin recortar nada del logo.
     Lo que sobra a los costados lo tapa el fondo del contenedor,
     que es exactamente el color del fondo del video. */
  object-fit: contain;
  object-position: center 28%;
  transform: scale(1.02);
  -webkit-mask-image: radial-gradient(ellipse 75% 75% at 50% 50%, black 55%, transparent 100%);
  mask-image: radial-gradient(ellipse 75% 75% at 50% 50%, black 55%, transparent 100%);
}
.kfb-logo-video.viva { opacity: 1; }

/* La foto fija tiene que PARECER fuego, no una calcomanía.
   El video titila solo; la foto, si no se le hace nada, queda muerta —
   y en la barra de arriba es lo único que se ve, porque ahí abajo de
   60px no se carga el video.
   Se anima con BRILLO y COLOR, nunca con escala: una llama que crece y
   se achica se lee como un logo que late, y con brillo se lee como
   fuego. (Además la escala ya trajo problemas de repintado en el
   wordmark -- ver el 09/08.) */
/* MEDIDO el 06/09/2026, porque Canu preguntó "¿por qué no se mueve el
   logo?" mirando /kiosco/dueno: la animación CORRÍA -- moviéndole el
   currentTime a mano se leen los tres extremos -- pero el recorrido
   entero era brightness .92 -> 1.18 repartido en 2,6 segundos. Un 13%
   de brillo estirado en dos segundos y medio no se ve: se lee quieto.
   Un latido que hay que medir para saber que está no es un latido.

   Lo que cambia:
   - AMPLITUD: .78 -> 1.42 de brillo, y con saturación acompañando. El
     fuego se apaga y se aviva de verdad, no respira.
   - RITMO IRREGULAR: los pasos no están repartidos parejo (12/19/31/
     44/58/71/86). Una llama con pulsos simétricos se lee como un LED,
     que es exactamente lo que no queremos.
   - HALO: un drop-shadow naranja que crece con el brillo. Es lo que
     hace que se lea como fuego y no como una foto a la que le suben y
     le bajan la luz.
   - MÁS RÁPIDO: 2,6s -> 1,9s. El fuego titila, no late.

   Sigue siendo brillo y color, NUNCA escala: una llama que crece y se
   achica se lee como un logo latiendo, y además la escala ya trajo
   problemas de repintado en el wordmark (ver el 09/08).

   CUESTA CERO BYTES. Ésa es la gracia: en la barra de arriba no se
   carga el video (son 6 MB para 40px), así que esto es lo único que se
   ve, y tiene que alcanzar solo. */
@keyframes kfbBrasa {
  0%   { filter: brightness(1)    saturate(1)    drop-shadow(0 0 3px rgba(245,166,35,.30)); }
  12%  { filter: brightness(1.30) saturate(1.22) drop-shadow(0 0 9px rgba(245,166,35,.60)); }
  19%  { filter: brightness(1.04) saturate(1.04) drop-shadow(0 0 4px rgba(245,166,35,.34)); }
  31%  { filter: brightness(1.42) saturate(1.30) drop-shadow(0 0 12px rgba(255,190,80,.68)); }
  44%  { filter: brightness(.86)  saturate(.92)  drop-shadow(0 0 2px rgba(245,166,35,.22)); }
  58%  { filter: brightness(1.24) saturate(1.18) drop-shadow(0 0 8px rgba(245,166,35,.55)); }
  71%  { filter: brightness(.78)  saturate(.88)  drop-shadow(0 0 2px rgba(196,52,27,.20)); }
  86%  { filter: brightness(1.16) saturate(1.12) drop-shadow(0 0 7px rgba(245,166,35,.48)); }
  100% { filter: brightness(1)    saturate(1)    drop-shadow(0 0 3px rgba(245,166,35,.30)); }
}
img.kfb-logo-video { animation: kfbBrasa 1.9s ease-in-out infinite; }

@media (prefers-reduced-motion: reduce) {
  img.kfb-logo-video { animation: none; }
}

@keyframes kfbFloat {
  from { transform: translateY(0); }
  to   { transform: translateY(-5px); }
}
@keyframes kfbGlow {
  0%, 100% { box-shadow: 0 0 6px rgba(201,169,110,.25); }
  50%      { box-shadow: 0 0 16px rgba(201,169,110,.55); }
}

.theme-switcher {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border-radius: var(--r-full);
  border: 1px solid var(--border);
  background: var(--bg-card);
}

/* En el login flota fija arriba a la derecha; en el topbar vive en el flujo normal. */
body > .theme-switcher {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 40;
}

.theme-switch-btn {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: none;
  background: none;
  color: var(--text-muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background .12s ease, color .12s ease;
}
.theme-switch-btn:hover { background: var(--bg-hover); color: var(--text-sub); }
.theme-switch-btn.active { background: var(--gold); color: #1a1a1a; }

/* ══════════════════════════════════════════════════════════════
   EL WORDMARK — una sola definición para toda la marca.

   Estaba escrito cuatro veces (login.css, app.css, la calculadora,
   la página de modelos) y una de las copias se desvió: mostraba
   "KFB" en vez del nombre, y "Kiosco" salió en ROJO porque quedó
   adentro de un <em>, que es la etiqueta del Fire. Por eso vive acá
   ahora: la marca no puede depender de que cuatro copias digan lo
   mismo.

   Reglas, y no se negocian:
     · Dice «Knife, Fire & Brain». No «KFB», salvo que no entre.
     · El dorado PASA de un lado al otro sobre las letras.
     · «Fire» va en rojo, en cursiva, latiendo.
     · «Kiosco» va gris y arriba, chiquita, como volada.
   ══════════════════════════════════════════════════════════════ */

.kfb-marca {
  display: inline-block;
  line-height: 1.15;
}
.kfb-marca .kfb-nombre {
  font-family: var(--serif);
  font-weight: 600;
  letter-spacing: .01em;
  white-space: nowrap;
  /* El dorado no está quieto: viaja sobre las letras. */
  background: linear-gradient(115deg, var(--text) 20%, var(--gold) 46%, #e8d5b0 54%, var(--text) 78%);
  background-size: 220% auto;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: kfbShimmer 5s linear infinite;
}
.kfb-marca .fire {
  display: inline-block;
  font-style: italic;
  font-weight: 400;
  background: none;
  -webkit-text-fill-color: var(--fire);
  color: var(--fire);
  animation: fireBurn 1.8s ease-in-out infinite;
}

/* «Kiosco»: gris y arriba, como volada. Es como estaba y así queda
   -- se probó dorada y abajo, y el usuario la devolvió a esto. */
.kfb-marca .kfb-chapa {
  display: inline-block;
  font-family: var(--sans);
  font-style: normal;
  font-size: .6rem;
  font-weight: 600;
  letter-spacing: .1em;
  vertical-align: super;
  margin-left: 3px;
  background: none;
  color: var(--text-muted);
  -webkit-text-fill-color: var(--text-muted);
}

/* ── Cuando no entra el nombre entero ─────────────────────────
   Autorizado para pantallas angostas. Va «KFB»: la K y la B en
   blanco con el mismo dorado pasando por encima, y la F en rojo,
   parpadeando. Es el nombre comprimido, no otro logo. */
.kfb-marca .kfb-corto { display: none; }
.kfb-marca .kfb-corto .fire {
  animation: fireBlink 1.25s steps(1, end) infinite;
}
@keyframes fireBlink {
  0%, 62%  { opacity: 1;  text-shadow: 0 0 14px rgba(255,122,69,.75); }
  63%, 78% { opacity: .28; text-shadow: none; }
  79%      { opacity: 1;  text-shadow: 0 0 14px rgba(255,122,69,.75); }
}

/* Hasta 1024 va la marca corta ("KFB"). El nombre entero se lleva 170px
   --medido a 915, el teléfono acostado-- y ahí la barra se caía al segundo
   renglón. Canu, viendo la horizontal en dos: *"achicale, que aparezca acá
   KFB nomás"*. El nombre completo vuelve en pantalla grande, que es donde
   se lo puede leer sin sacarle lugar a nada. */
@media (max-width: 1024px) {
  .kfb-marca .kfb-largo { display: none; }
  .kfb-marca .kfb-corto { display: inline; letter-spacing: .04em; }
}

/* Los dos movimientos de la marca. Estaban sólo en login.css, así que
   en las pantallas que no lo cargan el dorado quedaba quieto y el
   Fire no latía. */
@keyframes kfbShimmer {
  from { background-position: -220% center; }
  to   { background-position: 220% center; }
}
/* El Fire late con COLOR y BRILLO, no con escala.
   Por que: el nombre lleva el dorado con background-clip:text, y si un
   HIJO de ese elemento tiene transform, Chrome pinta el degradado del
   padre recortado sobre ese hijo en una posicion equivocada. Se veia
   la palabra "Fire" dibujada dos veces: una roja en su lugar y otra
   BLANCA arriba a la izquierda, encima de la K de Knife.
   Medido y confirmado sacando el transform: la copia desaparece. */
@keyframes fireBurn {
  0%, 100% { color: var(--fire); -webkit-text-fill-color: var(--fire);
             text-shadow: 0 0 8px rgba(232,83,79,.35); }
  50%      { color: #ff7a45; -webkit-text-fill-color: #ff7a45;
             text-shadow: 0 0 22px rgba(255,122,69,.85), 0 0 6px rgba(255,160,90,.6); }
}

/* Los dos selectores de preferencia --tema e idioma-- en una sola tira.
   Envolverlos en vez de darle al de idioma un `right` calculado a mano:
   ese numero dependeria del ancho del de tema, que cambia con el
   breakpoint, y quedarian dos reglas que hay que sincronizar. */
/* La tira SIEMPRE es una fila: viaja de la barra de la landing al body del
   login, y adentro de la barra se apilaba en dos renglones porque el flex
   estaba pegado al `body >`. Lo que depende de donde este es la posicion
   fija, no la forma. */
.kfb-preferencias {
  display: flex;
  align-items: center;
  gap: 10px;
}
body > .kfb-preferencias {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 40;
}

/* El selector de idioma. VIVE ACA, no en app.css.

   Estuvo en app.css con un comentario que decia "que cargan TODAS las
   paginas". No es cierto, y se midio: `ayuda.html` y `catalogo.html` NO la
   cargan. El manual quedo con el selector sin un solo estilo -- dos botones
   pelados, pintados por el navegador.

   Es la segunda vez que este control se muda por el mismo motivo (antes
   estaba en pos.css, que es de las tres del operador). El de tema ya vivia
   aca: que dos controles gemelos vivieran en hojas distintas es lo que hizo
   que uno se rompiera y el otro no.

   `una-clase-estilada-en-una-hoja-que-esa-pagina-no-carga.py` NO lo agarra,
   y conviene saber por que: `.idioma-btn` la escribe `idioma.js`, asi que
   no esta en ningun HTML. Un barrido que mira el HTML no puede ver una
   clase que nace en el JS.

   Va al lado del de tema y con el mismo tamaño:
   son la misma clase de control --preferencia del que mira, no accion
   sobre el negocio-- y si uno es mas grande que el otro se lee como si
   fuera mas importante. */
.idioma-switcher { display: flex; gap: 2px; }
.idioma-btn {
  min-width: 30px; height: 28px; padding: 0 6px;
  border: 1px solid var(--border); border-radius: 7px;
  background: transparent; color: var(--text-sub);
  font-size: .64rem; font-weight: 700; letter-spacing: .06em; cursor: pointer;
}
.idioma-btn:hover { color: var(--text); border-color: var(--border-accent); }
.idioma-btn.active {
  color: var(--on-gold); background: var(--gold); border-color: var(--gold);
}
/* En un celular se ve SOLO el puesto, igual que el tema: los dos juntos se
   comian 60px de los 412 de ancho. Tocarlo pasa al siguiente. */
@media (max-width: 700px) {
  .idioma-btn:not(.active) { display: none; }
}
