/* ============================================================
   CALLE STUDIO — hoja de estilos
   Página de una sola pantalla: el muro ocupa todo, la app
   está escondida en él y aparece al hacer clic.
   Paleta y acento se cambian en :root.
   ============================================================ */

:root{
  --bg:#06070a;
  --accent:#c9ced8;
  --accent-2:#e7bd77;
  --accent-ink:#15110a;
  --ink:#f4f3f0;
  --ink-2:#b6b9be;
  --ink-3:#7e838a;
  --panel:#0f1114;
  --line:rgba(255,255,255,.13);
  --line-soft:rgba(255,255,255,.08);
  --danger:#e07a70;
  /* identidad BlokiiMobb (del logo): plata aerosol sobre noche, ladrillo y un solo acento calido */
  --plata:#f4f4f0;
  --noche:#0a0b0d;
  --ladrillo:#3a2418;
  --ambar:#ffb65c;
  --ambar-suave:rgba(255,182,92,.32);
  /* tokens de identidad del logo: plata #f4f4f0, noche, ambar #ffb65c */
  --sans:"Inter","SF Pro Text",-apple-system,"Helvetica Neue",system-ui,"Segoe UI",Roboto,Arial,sans-serif;
  --mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,monospace;
  --r:14px;
  --shadow:0 30px 80px rgba(0,0,0,.6);
  /* encuadre del muro: apunta al objeto escondido (porcentaje de la imagen) */
  --foco-x:62.5%;
  --foco-y:34%;

  /* ------------------------------------------------------------
     VIDRIO DEL HUD — una sola pastilla para todo el interfaz que
     va sobre la imagen (rotulo de calle, avisos, minimapa, brujula,
     controles tactiles y avisos del mando).

     Es la UNICA fuente de verdad: la calle 3D se construye en
     escena3d.js y NO debe traer sus propios colores — pide estas
     clases. Antes cada elemento llevaba sus literales copiados a
     mano y los cuatro vidrios ya habian divergido (.62 / .68 / .68
     / .85 de fondo). Si hay que retocar el HUD, se retoca aqui.
     ------------------------------------------------------------ */
  --hud-fondo:rgba(8,10,14,.68);
  --hud-borde:rgba(244,244,240,.24);
  --hud-tinta:#f4f4f0;
  --hud-fuente:"Barlow Condensed","Arial Narrow","Helvetica Neue",Arial,sans-serif;
  --hud-radio:10px;
  --hud-radio-pastilla:999px;
  --hud-desenfoque:blur(6px);
  --hud-sombra:0 8px 22px rgba(0,0,0,.5);
}

*,*::before,*::after{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0; background:var(--bg); color:var(--ink);
  font-family:var(--sans); font-size:16.5px; line-height:1.6;
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
  overflow:hidden;
}
img{display:block; max-width:100%}
a{color:var(--ink); text-decoration:none}
h2{font-size:clamp(1.35rem,2.2vw,1.8rem); font-weight:600; letter-spacing:-.02em; margin:0 0 .6em}
p{margin:0 0 1em}
code{font-family:var(--mono); font-size:.85em; background:rgba(255,255,255,.08); padding:.1em .35em; border-radius:4px}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip-link{position:absolute; left:-9999px; top:0; z-index:200; background:var(--accent); color:var(--accent-ink); padding:10px 16px; font-weight:600}
.skip-link:focus{left:12px; top:12px}
:focus-visible{outline:2px solid var(--accent); outline-offset:3px; border-radius:3px}

/* ============ aviso de configuración ============ */
.cfg-warning{position:fixed; left:16px; bottom:16px; z-index:80; max-width:min(380px,72vw);
  display:flex; align-items:center; gap:10px; padding:10px 12px 10px 14px;
  background:rgba(14,12,9,.88); border:1px solid rgba(214,163,85,.28); border-radius:10px;
  color:#ddd2b9; font-size:.77rem; line-height:1.4; backdrop-filter:blur(12px);
  box-shadow:0 18px 44px rgba(0,0,0,.6)}
.cfg-warning span{max-width:32ch}
.cfg-warning__x{margin-left:auto; flex:none; border:1px solid rgba(214,163,85,.45); background:transparent; color:#e8dfcc;
  width:22px; height:22px; border-radius:50%; cursor:pointer; line-height:1; font-size:.72rem}
.cfg-warning[hidden]{display:none}   /* hidden manda aunque la regla de arriba traiga display:flex */

/* ============ la calle en 3D ============ */
/* El vidrio del HUD vive en el :root de arriba (--hud-*). Aqui abajo van
   los elementos que lo usan; ninguno define sus propios colores ni su
   propia tipografia: todos leen los tokens. */

/* ===== interfaz propia de la calle 3D ===== */
.brujula{
  position:fixed; left:50%; bottom:26px; transform:translateX(-50%); z-index:16;
  width:58px; height:58px; border-radius:50%; display:none; place-items:center;
  border:1px solid var(--hud-borde); background:var(--hud-fondo); backdrop-filter:var(--hud-desenfoque);
  opacity:0; transition:opacity .4s ease;
}
body.modo3d .brujula{display:grid}
.brujula.moviendo{opacity:.95}
.brujula__aro{position:absolute; inset:9px; border-radius:50%; border:1px dashed rgba(244,244,240,.32)}
.brujula__punto{width:9px; height:9px; border-radius:50%; background:var(--ambar); box-shadow:0 0 12px rgba(255,182,92,.85); transition:transform .25s ease}
body.modo3d .marker--web .marker__dot,body.modo3d .marker--solicitud .marker__dot{background:rgba(244,244,240,.55)}
.sin3d{
  position:fixed; left:50%; bottom:26px; transform:translateX(-50%); z-index:18; margin:0; display:none;
  padding:9px 14px; border-radius:var(--hud-radio-pastilla); border:1px solid var(--ambar-suave);
  background:var(--hud-fondo); color:var(--plata); font-family:var(--hud-fuente);
  font-size:.78rem; letter-spacing:.14em; text-transform:uppercase; backdrop-filter:var(--hud-desenfoque);
}
body.modo2d .sin3d[data-visible="1"]{display:block}

/* ------------------------------------------------------------
   Piezas del HUD que arma escena3d.js.
   Antes vivian como style.cssText o <style> inyectado desde el JS,
   con los colores copiados a mano en cada una. Ahora son clases de
   aqui y el JS solo las asigna: un solo sitio donde retocar el HUD.
   Los ids y los data-* se conservan (el QA los consulta).
   ------------------------------------------------------------ */

/* Rotulo del nombre de la calle, arriba al centro. */
#rotuloCalle{
  position:fixed; top:16px; left:50%; transform:translateX(-50%); z-index:35;
  font:600 15px/1 var(--hud-fuente); color:var(--hud-tinta); letter-spacing:.14em; text-transform:uppercase;
  background:var(--hud-fondo); border:1px solid var(--hud-borde); border-radius:var(--hud-radio-pastilla);
  padding:8px 16px; opacity:0; transition:opacity .45s ease; pointer-events:none;
  backdrop-filter:var(--hud-desenfoque); -webkit-backdrop-filter:var(--hud-desenfoque);
}
#rotuloCalle.visible{opacity:.95}

/* Avisos de la escena ("pulsa E", etc.), abajo al centro. */
#avisoEscena{
  position:fixed; left:50%; bottom:86px; transform:translateX(-50%); z-index:65;
  background:var(--hud-fondo); border:1px solid var(--hud-borde); color:var(--hud-tinta);
  padding:8px 16px; border-radius:var(--hud-radio);
  font:600 14px/1.2 var(--hud-fuente); letter-spacing:.06em; text-transform:uppercase;
  display:none; pointer-events:none;
}

/* Mini mapa: mismo vidrio que el resto del HUD. */
#minimapaWrap{
  position:fixed; right:14px; bottom:14px; z-index:40; pointer-events:none;
  border:1px solid var(--hud-borde); border-radius:var(--hud-radio); overflow:hidden;
  background:var(--hud-fondo); box-shadow:var(--hud-sombra); opacity:.94;
  backdrop-filter:blur(4px); -webkit-backdrop-filter:blur(4px);
}
#minimapa{display:block; width:200px; height:150px}
@media (max-width:600px){#minimapa{width:142px; height:106px}}

/* Aviso del mando (conectar/desconectar), arriba al centro. */
#avisoMando{
  position:fixed; left:50%; top:14px; transform:translateX(-50%); z-index:70;
  background:var(--hud-fondo); border:1px solid var(--hud-borde); color:var(--hud-tinta);
  padding:7px 14px; border-radius:var(--hud-radio);
  font:600 13px/1.2 var(--hud-fuente); letter-spacing:.08em; text-transform:uppercase;
  pointer-events:none; opacity:0; transition:opacity .35s;
}

/* Controles tactiles: mismo vidrio y acento de marca (antes azul ajeno). */
#toquePalanca{
  position:fixed; left:16px; bottom:20px; width:124px; height:124px; border-radius:50%;
  background:var(--hud-fondo); border:1.5px solid var(--hud-borde);
  z-index:60; touch-action:none; pointer-events:auto; backdrop-filter:var(--hud-desenfoque);
}
#toquePalanca .toque-perilla{
  position:absolute; left:50%; top:50%; width:56px; height:56px; margin:-28px 0 0 -28px; border-radius:50%;
  background:rgba(244,244,240,.42); box-shadow:0 0 12px rgba(255,182,92,.4); pointer-events:none;
}
.toque-boton{
  position:fixed; min-width:58px; height:58px; border-radius:50%;
  background:var(--hud-fondo); border:1.5px solid var(--hud-borde); color:var(--hud-tinta);
  font:600 12px/58px var(--hud-fuente); text-align:center; padding:0 6px; box-sizing:border-box;
  z-index:60; touch-action:none; pointer-events:auto; user-select:none; -webkit-user-select:none;
  backdrop-filter:var(--hud-desenfoque);
}
.toque-boton.pulsado{background:var(--ambar-suave); color:var(--noche)}

#escena3d{position:fixed; inset:0; width:100%; height:100%; display:none; background:#05070c; cursor:crosshair}
#escena3d.mano{cursor:pointer}
#escena3d.arrastrando{cursor:grabbing}
body.modo3d #escena3d{display:block}
body.modo3d .capa,
body.modo3d .stage__img{display:none}
body.modo3d .stage{transform:none}
/* Un solo bloque para el modo 3D: antes eran dos reglas `body.modo3d{}`
   seguidas (los acentos por un lado y el vidrio por otro), que es como se
   cuelan los tokens duplicados. Se conservan los dos valores. */
body.modo3d{ --accent:#f4f4f0; --accent-2:#ffb65c; --hud-fondo:rgba(8,10,14,.78) }

/* ============ el muro ============ */
.stage{
  position:fixed; inset:0; overflow:hidden; background:#05060a;
  transform:perspective(1600px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg)) scale(1.05);
  transition:transform .7s cubic-bezier(.2,.7,.2,1); will-change:transform;
}
.stage__img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  object-position:var(--foco-x,62.5%) var(--foco-y,34%)}

/* capas de profundidad: cada una se mueve a distinta velocidad (--tx/--ty las maneja el JS) */
.capa{position:absolute; inset:0; width:100%; height:100%; pointer-events:none; will-change:transform;
  /* 1.06 en vez de 1.12: cuanto menos se agrande la foto, mas nitida se ve
     (con el muro a 2848 px el margen sobra para el recorrido) */
  transform:translate3d(var(--tx,0px), var(--ty,0px), 0) scale(1.06)}
.capa--fondo{overflow:hidden; pointer-events:auto; z-index:2}
.capa--fondo .stage__img{transform:none}
.capa--luz{mix-blend-mode:screen; opacity:.5; z-index:3; object-fit:cover}
.capa--pintura{mix-blend-mode:screen; opacity:.4; z-index:4; object-fit:cover}
.capa--marco{z-index:5; inset:-22%; width:144%; height:144%;
  background:radial-gradient(58% 52% at 50% 46%, rgba(3,4,6,0) 42%, rgba(3,4,6,.72) 100%)}
/* el plano mas cercano: el canto del muro y el piso que se nos vienen encima.
   Es la capa que mas se mueve (data-p=2.7), asi que da la profundidad de
   estar parado junto al muro, no frente a una foto. Sin desenfoque a proposito:
   los degradados ya son suaves y un filtro sobre una capa que se mueve se paga
   en cada cuadro. */
.capa--frente{z-index:7; inset:-26%; width:152%; height:152%;
  background:
    radial-gradient(30% 58% at 4% 58%, rgba(3,4,7,.92), rgba(3,4,7,0) 70%),
    radial-gradient(62% 30% at 42% 106%, rgba(3,5,8,.88), rgba(3,5,8,0) 74%)}

/* el plano MAS lejano: el resplandor de la ciudad detras de la niebla. Se mueve
   menos que el muro (0.12), asi que se lee como distancia, no como pintura. */
.capa--lejos{z-index:3; inset:-10%; width:120%; height:120%;
  mix-blend-mode:screen; opacity:.9;
  background:
    radial-gradient(30% 22% at 16% 34%, rgba(116,150,205,.10), rgba(116,150,205,0) 70%),
    radial-gradient(40% 20% at 60% 30%, rgba(255,186,110,.13), rgba(255,186,110,0) 72%),
    radial-gradient(26% 16% at 86% 38%, rgba(168,120,255,.09), rgba(168,120,255,0) 70%)}

/* los cables de la colonia, cruzando arriba. Van por encima de todo y se mueven
   MAS que el muro (3.2): es la sombra de estar parado debajo de ellos. */
.capa--cables{z-index:9; inset:-14%; width:128%; height:128%; opacity:.92;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1600 900' preserveAspectRatio='none'%3E%3Cdefs%3E%3Cfilter id='b' x='-12%25' y='-12%25' width='124%25' height='124%25'%3E%3CfeGaussianBlur stdDeviation='2.4'/%3E%3C/filter%3E%3C/defs%3E%3Cg fill='none' stroke='%23070a0e' stroke-linecap='round' filter='url(%23b)'%3E%3Cpath d='M-40 96 C 300 168 700 150 1640 70' stroke-width='6' opacity='.92'/%3E%3Cpath d='M-40 150 C 340 214 820 196 1640 120' stroke-width='3.6' opacity='.82'/%3E%3Cpath d='M-40 196 C 420 250 900 240 1640 176' stroke-width='2.4' opacity='.7'/%3E%3Cpath d='M 420 232 C 470 300 470 340 466 372' stroke-width='1.8' opacity='.55'/%3E%3C/g%3E%3C/svg%3E");
  background-size:100% 100%; background-repeat:no-repeat}

/* el poste de la esquina, con su caja y su luz de borde: el plano MAS cercano
   de todos (3.8). Va por el borde DERECHO, recortado contra el resplandor de la
   lampara: un primer plano oscuro solo se lee contra una zona clara (probado en
   el borde izquierdo: se perdia en la pintura oscura).
   Ojo al recolocarlo: la capa es 136% de ancho y empieza en -18%, asi que una x
   del SVG NO cae en la misma x de la pantalla (x_svg = (x_pantalla+18)/136 * 1600). */
.capa--poste{z-index:10; inset:-18%; width:136%; height:136%; opacity:.95;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1600 900' preserveAspectRatio='none'%3E%3Cdefs%3E%3Cfilter id='b' x='-12%25' y='-12%25' width='124%25' height='124%25'%3E%3CfeGaussianBlur stdDeviation='2.8'/%3E%3C/filter%3E%3C/defs%3E%3Cg filter='url(%23b)'%3E%3Crect x='1228' y='-40' width='96' height='740' fill='%2303050a' opacity='.35'/%3E%3Crect x='1252' y='-40' width='52' height='740' fill='%23020408' opacity='.96'/%3E%3Crect x='1253' y='-40' width='7' height='740' fill='%23ffc47e' opacity='.3'/%3E%3Crect x='1222' y='120' width='118' height='40' rx='8' fill='%2303050a' opacity='.94'/%3E%3Crect x='1232' y='130' width='98' height='7' rx='3' fill='%231a1f28' opacity='.5'/%3E%3C/g%3E%3C/svg%3E");
  background-size:100% 100%; background-repeat:no-repeat}
.stage__glow{position:absolute; inset:0; mix-blend-mode:screen; pointer-events:none;
  background:radial-gradient(34% 44% at var(--gx,66%) var(--gy,34%), rgba(214,163,85,.20), transparent 72%);
  transition:background .35s linear}

/* El parpadeo de la luz: cada ~11 s la lampara de la calle FALLA (tres golpes
   cortos) y la calle se apaga ese instante. Va como animacion de CSS a proposito:
   corre en el compositor, asi que se ve aunque el JavaScript este ocupado o el
   navegador recorte cuadros, y se puede comprobar sin depender del reloj.
   El lienzo del clima acompana bajando su resplandor ambar (muro-fx.js). */
.stage__parpadeo{position:absolute; inset:0; z-index:8; pointer-events:none; background:#020306;
  opacity:0; animation:parpadeo 11s linear infinite}
@keyframes parpadeo{
  0%, 60%   {opacity:0}
  60.6%     {opacity:.34}
  61.4%     {opacity:0}
  61.9%     {opacity:.30}
  62.7%     {opacity:0}
  63.2%     {opacity:.22}
  63.9%     {opacity:.06}
  64.6%     {opacity:0}
  100%      {opacity:0}
}
.stage__scrim{position:absolute; inset:0; pointer-events:none;
  background:
    radial-gradient(120% 90% at 50% 45%, rgba(4,5,8,0) 45%, rgba(4,5,8,.55) 100%),
    linear-gradient(180deg, rgba(4,5,8,.42) 0%, rgba(4,5,8,0) 22%, rgba(4,5,8,0) 74%, rgba(4,5,8,.5) 100%)}
.stage__grain{position:absolute; inset:0; opacity:.06; mix-blend-mode:overlay; pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E")}

.mark{position:fixed; top:18px; left:20px; z-index:20; width:32px; height:32px; color:var(--accent); opacity:.9}
.mark svg{width:100%; height:100%}

/* ============ la app, escondida en el muro ============ */
.marker{
  position:absolute; transform:translate(-50%,-50%); z-index:12;
  width:52px; height:52px; padding:0; border:0; background:transparent; cursor:pointer;
  display:grid; place-items:center; border-radius:50%;
}
.marker__dot{width:13px; height:13px; border-radius:50%; background:rgba(255,255,255,.9);
  box-shadow:0 0 0 1.5px rgba(0,0,0,.55), 0 3px 16px rgba(0,0,0,.6);
  transition:transform .2s ease, background .2s ease}
.marker__pulse{position:absolute; width:34px; height:34px; border-radius:50%;
  border:1px solid rgba(255,255,255,.6); animation:ring 3.2s cubic-bezier(.3,.6,.4,1) infinite; pointer-events:none}
@keyframes ring{0%{transform:scale(.5); opacity:.75} 65%{transform:scale(1.35); opacity:0} 100%{opacity:0}}
.marker:hover .marker__dot,.marker:focus-visible .marker__dot{background:var(--accent); transform:scale(1.35)}

/* ============ el logo de la marca, pintado como grafiti animado ============ */
.logo-sombra{
  position:absolute; z-index:2; width:clamp(320px, 40vw, 700px); aspect-ratio:1;
  transform:translate(-50%,-50%); pointer-events:none;
  display:none;   /* fuera la burbuja oscura */
}
.logo-grafiti{
  position:absolute; z-index:3; padding:0; border:0; background:transparent; cursor:pointer;
  width:clamp(210px, 25vw, 430px); aspect-ratio:16/9;
  transform:translate(-50%,-50%) rotate(-1.8deg) skewY(-1.3deg);
  mix-blend-mode:screen;                      /* el negro del video desaparece: queda solo la pintura */
  /* borde suave arriba y abajo: se ve aerosol, no un circulo de video */
  -webkit-mask-image:linear-gradient(180deg, transparent 0, #000 12%, #000 88%, transparent 100%);
  mask-image:linear-gradient(180deg, transparent 0, #000 12%, #000 88%, transparent 100%);
  filter:contrast(1.12) brightness(.96) blur(.4px);   /* textura de pintura, no de pantalla */
  opacity:.96;
  transition:filter .35s ease, opacity .35s ease;
  will-change:transform; backface-visibility:hidden;
}
.logo-grafiti video{width:100%; height:100%; object-fit:contain; display:block; pointer-events:none; transform:translateZ(0)}
.logo-grafiti:hover video,.logo-grafiti:focus-visible video{filter:brightness(1.28) contrast(1.05)}
.logo-grafiti__onda{ display:none }   /* el anillo con zoom ya no va */

.logo-grafiti:hover 
.marker__onda{position:absolute; width:34px; height:34px; border-radius:50%; border:1px solid var(--accent);
  opacity:0; transform:scale(.35); pointer-events:none}
.marker:hover .marker__onda,.marker:focus-visible .marker__onda{animation:onda 1.15s ease-out infinite}
@keyframes onda{0%{opacity:.7; transform:scale(.35)} 100%{opacity:0; transform:scale(1.7)}}

/* la solicitud va escondida en la pintura: casi invisible hasta que la encuentras */
.marker--solicitud .marker__dot{width:9px; height:9px; background:rgba(255,255,255,.5);
  box-shadow:0 0 0 1px rgba(0,0,0,.45), 0 2px 10px rgba(0,0,0,.5)}
.marker--solicitud .marker__pulse{width:24px; height:24px; border-color:rgba(214,163,85,.45);
  animation-duration:6s; opacity:.7}
.marker--solicitud:hover .marker__dot,.marker--solicitud:focus-visible .marker__dot{background:var(--accent); transform:scale(1.7)}
/* El punto escondido del muro (la aplicacion): mismo lenguaje discreto que los
   otros puntos, con el ambar de la marca al pasar el puntero o con el teclado */
.marker--app .marker__dot{width:11px; height:11px; background:rgba(255,255,255,.72);
  box-shadow:0 0 0 1.5px rgba(4,6,10,.6), 0 3px 14px rgba(0,0,0,.55)}
.marker--app .marker__pulse{width:30px; height:30px; border-color:rgba(255,182,92,.5);
  animation-duration:5.2s; opacity:.75}
.marker--app:hover .marker__dot,.marker--app:focus-visible .marker__dot{background:var(--ambar); transform:scale(1.6)}
.marker--app .marker__onda{border-color:rgba(255,182,92,.7)}

/* texto de apoyo de los cuadros (el candado, la app, el aviso del tope) */
.note{color:var(--ink-2); font-size:.86rem; line-height:1.5}

/* ============ los cuadros de la app ============
   Hablan el mismo idioma que el HUD de la calle (la condensada) y el tono de
   cartel de la escena underground que el cliente mando de referencia
   (abse.life): titulos y etiquetas en mayusculas con aire entre letras, y el
   texto de apoyo en la tipografia normal para que se lea comodo. */
#modal-app h2{font-family:var(--hud-fuente); font-weight:700; text-transform:uppercase;
  letter-spacing:.06em; font-size:clamp(1.35rem,2.2vw,1.85rem)}
.pago__marca,.pago__precio,#demoAccesos{font-family:var(--hud-fuente); text-transform:uppercase}
.pago__marca{letter-spacing:.18em}
.pago__precio{letter-spacing:.03em; font-size:clamp(1.5rem,2.4vw,1.9rem)}
#demoAccesos{letter-spacing:.12em; font-size:.82rem}

/* el menu de pago del panel: el nombre, el precio y el boton de PayPal */
.pago{margin-top:6px; padding:14px 16px; border:1px solid var(--line-soft); border-radius:10px;
  background:rgba(255,255,255,.02); display:grid; gap:6px}
.pago__marca{margin:0; font-size:.76rem; color:var(--ink-3)}
.pago__precio{margin:0 0 10px; font-weight:600; color:var(--accent-2)}
.pago__nota{margin:-4px 0 10px; font-size:.7rem; letter-spacing:.2em; text-transform:uppercase; color:var(--ink-3)}

.stage{cursor:grab}
.stage--arrastrando{cursor:grabbing}

/* ============ animaciones ambientales ============ */
.capa--bruma{z-index:6; mix-blend-mode:screen; pointer-events:none;
  background:
    radial-gradient(58% 42% at 22% 62%, rgba(190,215,255,.07), transparent 72%),
    radial-gradient(46% 34% at 72% 32%, rgba(255,208,150,.06), transparent 72%);
  animation:bruma 44s ease-in-out infinite alternate}
@keyframes bruma{0%{transform:translate3d(-2.6%,1.2%,0) scale(1.04)} 100%{transform:translate3d(2.6%,-1.2%,0) scale(1.09)}}
.stage__glow{animation:lampara 11s ease-in-out infinite}
@keyframes lampara{0%,100%{opacity:.88} 42%{opacity:1} 68%{opacity:.84}}

/* ============ botones ============ */
.btn{display:inline-flex; align-items:center; justify-content:center; gap:8px;
  font-family:inherit; font-size:.87rem; font-weight:600; padding:13px 21px; border-radius:8px;
  border:1px solid transparent; cursor:pointer; text-decoration:none !important; background:transparent; color:var(--ink);
  transition:background .18s ease, border-color .18s ease, color .18s ease, transform .18s ease}
.btn--primary{background:linear-gradient(180deg,var(--accent-2),var(--accent)); color:var(--accent-ink);
  box-shadow:0 10px 28px rgba(214,163,85,.22)}
.btn--primary:hover{transform:translateY(-1px)}
.btn--ghost{border-color:var(--line); color:var(--ink); background:rgba(255,255,255,.02)}
.btn--ghost:hover{border-color:var(--ink-2)}
.btn--block{width:100%}

/* ============ modales ============ */
.modal{position:fixed; inset:0; z-index:90; display:grid; place-items:center; padding:clamp(12px,3vw,28px)}
.modal[hidden]{display:none}
.modal__backdrop{position:absolute; inset:0; background:rgba(4,5,7,.78); backdrop-filter:blur(5px); border:0}
.modal__panel{position:relative; z-index:1; width:100%; max-width:640px; max-height:92vh; overflow:auto;
  background:var(--panel); border:1px solid var(--line); border-radius:var(--r);
  padding:clamp(22px,3vw,34px); box-shadow:0 40px 100px rgba(0,0,0,.72);
  animation:subir .26s cubic-bezier(.2,.7,.2,1)}
@keyframes subir{from{opacity:0; transform:translateY(16px) scale(.985)} to{opacity:1; transform:none}}
.modal__panel--app{max-width:min(560px,92vw); padding:clamp(16px,2vw,26px)}
.candado h2{margin-bottom:.25em}
.candado .field{margin-top:14px}
.candado-listo .modal__img{margin-bottom:14px}
/* En el panel (al entrar con el codigo) la muestra no puede empujar el pago fuera de la
   pantalla: el precio y el boton de PayPal tienen que verse sin bajar
   (el QA lo comprueba en los tres tamanos). */
.candado-listo .modal__img{max-height:min(34vh, 320px); object-fit:contain; background:#0b0d10}
.candado-agotado h2{margin-bottom:.3em}
.modal__panel--web{max-width:min(1100px,94vw); padding:clamp(10px,1.6vw,18px)}
.modal__iframe{width:100%; height:min(70vh,720px); border:1px solid var(--line-soft); border-radius:10px; background:#0b0d10}
/* el objeto de la pagina: mismo lenguaje discreto que la solicitud */
.marker--web .marker__dot{width:10px; height:10px; background:rgba(255,255,255,.55);
  box-shadow:0 0 0 1px rgba(0,0,0,.45), 0 2px 10px rgba(0,0,0,.5)}
.marker--web .marker__pulse{width:26px; height:26px; border-color:rgba(140,220,255,.45); animation-duration:5.5s; opacity:.7}
.marker--web:hover .marker__dot,.marker--web:focus-visible .marker__dot{background:#8fe3ff; transform:scale(1.6)}
.modal__img{width:100%; max-height:62vh; object-fit:cover; border-radius:10px; border:1px solid var(--line-soft)}
.modal__row{display:flex; flex-wrap:wrap; gap:10px; justify-content:flex-end; margin-top:16px}
.modal__x{position:absolute; top:12px; right:12px; z-index:3; width:32px; height:32px; border-radius:50%;
  border:1px solid var(--line); background:rgba(10,11,13,.6); color:var(--ink-2); cursor:pointer; line-height:1}
.modal__x:hover{border-color:var(--ink-2); color:var(--ink)}
.modal__actions{display:grid; gap:10px; margin-top:20px}
#solicitudForm .modal__actions{position:sticky; bottom:-2px; z-index:3; padding:16px 0 4px;
  background:var(--panel); border-top:1px solid var(--line-soft); box-shadow:0 -18px 22px -14px rgba(0,0,0,.8)}

.fields{display:grid; grid-template-columns:1fr 1fr; gap:14px}
.field{display:flex; flex-direction:column; gap:6px; font-size:.79rem; color:var(--ink-2)}
.field--full{grid-column:1/-1}
.field input,.field select,.field textarea{width:100%; background:#0b0d10; border:1px solid var(--line); border-radius:8px;
  color:var(--ink); padding:11px 12px; font:inherit; font-size:.92rem; transition:border-color .16s ease}
.field textarea{resize:vertical; min-height:96px}
.field input::placeholder,.field textarea::placeholder{color:#666b72}
.field input:focus,.field select:focus,.field textarea:focus{outline:none; border-color:var(--accent)}
.field input[aria-invalid="true"],.field textarea[aria-invalid="true"]{border-color:var(--danger)}
.field-err{color:var(--danger); font-size:.75rem; font-style:normal; margin:6px 0 0}
.check{display:flex; gap:10px; align-items:flex-start; font-size:.81rem; color:var(--ink-2); margin-top:16px; cursor:pointer}
.check input{margin-top:3px; accent-color:var(--accent); width:16px; height:16px; flex:none}

.ok{text-align:center}
.ok p{color:var(--ink-2)}
.ok__sum{margin-top:18px; text-align:left}
.ok__sum summary{cursor:pointer; color:var(--accent); font-size:.83rem}
.ok__sum pre{white-space:pre-wrap; word-break:break-word; background:#0b0d10; border:1px solid var(--line-soft);
  border-radius:8px; padding:12px; font-size:.75rem; font-family:var(--mono); color:var(--ink-2); max-height:220px; overflow:auto}

/* ============ aviso flotante ============ */
.toast{position:fixed; left:50%; bottom:78px; transform:translate(-50%,14px); z-index:120;
  background:rgba(14,16,19,.94); border:1px solid var(--line); border-left:2px solid var(--accent);
  color:var(--ink); padding:12px 18px; border-radius:8px; font-size:.85rem; backdrop-filter:blur(10px);
  box-shadow:var(--shadow); opacity:0; pointer-events:none; transition:opacity .2s ease, transform .2s ease; max-width:88vw}
.toast.is-on{opacity:1; transform:translate(-50%,0)}

@media (max-width:640px){
  .fields{grid-template-columns:1fr}
}
@media (hover:none){
  .stage{transform:none}
  .capa{--tx:0px; --ty:0px}
}
/* ============ el muro ya no es la puerta a la 3D ============
   Vuelta del 12 oct: el puente salio de la pagina. El muro es LA pagina
   (index.html) y la calle 3D quedo archivada en mapa3d.html, asi que
   .marker--portal, .portal--abriendo y .paso3d se fueron con el.
   Lo que SI sigue es la llegada: la usa mapa3d.html al entrar a la escena. */
.llegada3d{position:fixed; inset:0; z-index:80; pointer-events:none; overflow:hidden}
.llegada3d[hidden]{display:none}
.llegada3d img{width:100%; height:100%; object-fit:cover; display:block;
  object-position:var(--foco-x,62.5%) var(--foco-y,34%)}

/* llegada a la calle 3D: el mismo muro se abre y aguanta hasta que la escena ya pinta.
   Quien avisa es escena3d.js (data-escena-lista / evento escena:lista). */
.llegada3d{opacity:1; transition:opacity .65s ease}
.llegada3d img{transform:scale(1.5); filter:blur(7px) brightness(.55)}
.llegada3d--activo img{animation:llegada3dAbre 1.5s cubic-bezier(.23,.62,.36,1) forwards}
@keyframes llegada3dAbre{0%{transform:scale(1.5); filter:blur(7px) brightness(.55)}
  100%{transform:scale(1.02); filter:blur(0) brightness(1)}}
.llegada3d--fuera{opacity:0}
.llegada3d--fuera img{animation:none; transform:scale(1.06); transition:transform .65s ease}

/* fluidez: en 3D la escena se mueve todo el tiempo y el lienzo esta debajo.
   Un backdrop-filter ahi obliga al navegador a re-desenfocar en cada cuadro.
   .sin3d es el aviso real (antes aqui habia un .aviso3d que no existia). */
body.modo3d .brujula,
body.modo3d .sin3d,
body.modo3d #rotuloCalle,
body.modo3d #minimapaWrap,
body.modo3d .marker__label,
body.modo3d .modal__panel,
body.modo3d .toast{ backdrop-filter:none; -webkit-backdrop-filter:none }
body.modo3d #brujulaPunto{ will-change:transform }
body.modo3d .capa,body.modo3d .stage__img{ contain:strict }

@media (prefers-reduced-transparency: reduce){
  .glass, .candado, .modal__panel, .cfg-warning, .toast{ backdrop-filter:none; background:#12151a }
}

/* La capa del poste tapa un cacho del borde: en pantallas tactiles no hay
   inclinacion (el muro queda quieto), asi que se asoma menos para no estorbar. */
@media (hover:none){
  .capa--poste{opacity:.75}
  .capa--cables{opacity:.7}
}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms !important; transition-duration:.001ms !important}
  .marker__pulse{display:none}
}


/* ============ vida del muro: el clima y la luz ============
.fx-muro{position:absolute; inset:0; width:100%; height:100%; z-index:1; pointer-events:none}
/* Los covers del catalogo (.poster, .muro-panel, #posterBadge) se retiraron
   a peticion del cliente. Y el 12 oct salio del muro el grafiti ViirtualMobb
   (era el logo que habia que quitar): al muro le quedan la pintura, el logo de
   BlokiiMobb —que es el video del cuadro de la marca— y el punto escondido de
   la aplicación. Los estilos del grafiti (.grafiti-viirtual) se fueron con el; su
   codigo quedo guardado en muro-fx.js.bak-20261012-0810. */
.objeto--fuera{opacity:0 !important; pointer-events:none !important; visibility:hidden}


/* candado: código, cuenta o invitado */
.candado__o{display:flex;align-items:center;gap:10px;margin:12px 0;opacity:.55;font-size:.72rem;letter-spacing:.14em;text-transform:uppercase}
.candado__o::before,.candado__o::after{content:'';flex:1;height:1px;background:var(--line, rgba(255,255,255,.16))}
.candado__sub{margin:2px 0 6px;font-size:1rem}
