.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;
}
/* Las dos capas del logo: la foto abajo, el video encima. Ninguna se
   ve hasta que tiene imagen de verdad -- la foto con `onload`, el video
   con `playing` (un <video> sin decodificar es un rectángulo negro).
   Hasta ahí el círculo queda vacío, con su fondo y su borde: NO hay
   ninguna llama dibujada de respaldo. Canu la sacó el 13/09/2026 ("de
   última si tarda en cargar el logo, que tarde"). */
.kfb-logo-video,
.kfb-logo-foto {
  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 { position: relative; z-index: 2; }
.kfb-logo-foto  { position: absolute; inset: 0; z-index: 1; }
.kfb-logo-video.viva,
.kfb-logo-foto.viva { opacity: 1; }
/* Llegó el video: la foto de abajo ya no hace falta. Van en ese orden en
   el DOM (video, foto) justamente para que este `~` alcance. */
.kfb-logo-video.viva ~ .kfb-logo-foto { opacity: 0; }

/* 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 hasta que el video decodifica (6 MB) es lo único que se ve.
   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. Y desde el 13/09 es lo único que se ve mientras
   el video baja (6 MB): la foto titila hasta que el video la tapa. */
@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)); }
}
.kfb-logo-foto { animation: kfbBrasa 1.9s ease-in-out infinite; }

@media (prefers-reduced-motion: reduce) {
  .kfb-logo-foto { 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;
  /* En el monograma las tres letras tienen que medir lo mismo. La F va en
     itálica a 400 (el «Fire» liviano es de marca) y así, al lado de la K y
     la B a 600, se veía más baja: Canu, 13/09, con zoom en el teléfono.
     Se compensa con tamaño, no con peso: la itálica sólo está pedida a
     400 y un 600 sería peso falseado. El factor no está medido en
     pantalla (sin navegador en la sesión): es el que iguala la altura de
     capitular de Playfair itálica con la redonda a ojo; si sobra o falta,
     es este número. */
  font-size: 1.12em;
  line-height: 1;
  vertical-align: baseline;
}
@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; }
}
/* EXCEPTO en la pantalla del token y del PIN: ahí el nombre va solo, en
   su renglón, centrado -- hay lugar en cualquier teléfono (medido a 375:
   1.4rem, 236px de 375) y es la puerta de entrada de la marca. Canu,
   14/09, con captura del celular: «tiene que decir Knife, Fire & Brain
   completo y Kiosco, no KFB». La barra de arriba de la app sigue con KFB. */
.wordmark .kfb-marca .kfb-largo { display: inline; }
.wordmark .kfb-marca .kfb-corto { display: none; }

/* 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; }
}
