/* ==========================================================================
   UNKNOWNWORLD — AOS / GEO
   Hoja de estilo única del archivo de señales.
   Base oscura tipo archivo/consola; cada señal cambia --accent.
   ========================================================================== */

:root{
  --void:#060608;
  --ink:#0c0c11;
  --paper:#eceaf0;
  --dim:#8b8b98;
  --line:rgba(255,255,255,.14);
  --line-soft:rgba(255,255,255,.07);
  --accent:#d9a8ff;
  --bad:#ff6b86;
  --mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  --display:'Anton',Impact,'Arial Narrow',sans-serif;
  --pad:clamp(1rem,4vw,2rem);
  --maxw:1140px;
}

*,*::before,*::after{box-sizing:border-box}

html{-webkit-text-size-adjust:100%}

body{
  margin:0;
  min-height:100vh;
  background:var(--void);
  color:var(--paper);
  font-family:var(--mono);
  font-size:15px;
  font-weight:400;
  line-height:1.65;
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
}

/* halo de color de la señal ------------------------------------------------ */
body::before{
  content:'';
  position:fixed;
  inset:0;
  z-index:0;
  pointer-events:none;
  animation:halo-breathe 15s ease-in-out infinite;
  background:
    radial-gradient(58vw 44vh at 50% -8%, color-mix(in oklab, var(--accent) 26%, transparent), transparent 72%),
    radial-gradient(46vw 36vh at 50% 112%, color-mix(in oklab, var(--accent) 13%, transparent), transparent 74%);
}

img{max-width:100%}
a{color:var(--paper)}
::selection{background:var(--accent);color:var(--void)}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
*{scrollbar-color:#2b2b35 var(--void)}

.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;
}

/* --- capas de textura (las inyecta app.js) -------------------------------- */
.fx{position:fixed;inset:0;z-index:60;pointer-events:none}
.fx-grain,.fx-scan,.fx-sweep{position:absolute;inset:0;display:block}
.fx-grain{
  opacity:.16;
  animation:grain-live 6.5s steps(1,end) infinite;
  mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
.fx-scan{
  opacity:.5;
  background:repeating-linear-gradient(180deg,rgba(255,255,255,.05) 0 1px,transparent 1px 3px);
  animation:scan-live 9s steps(1,end) infinite;
}
.fx-sweep{
  inset:0;
  opacity:.2;
  background:linear-gradient(180deg,transparent,color-mix(in oklab,var(--accent) 90%,transparent),transparent);
  height:20vh;
  animation:sweep 8.5s linear infinite;
  will-change:transform;
}

/* pared repetida de una imagen (AOS · JENN) -------------------------------- */
.tiles{
  position:fixed;
  inset:0;
  z-index:1;
  pointer-events:none;
  opacity:.17;
  background-repeat:repeat;
  background-size:clamp(92px,13vw,168px) auto;
  filter:invert(1) hue-rotate(180deg) saturate(1.15);
  animation:drift 120s linear infinite;
}
.tiles::after{
  content:'';
  position:absolute;
  inset:0;
  background:radial-gradient(circle at 50% 42%,rgba(6,6,8,.5),rgba(6,6,8,.9) 62%,var(--void) 86%);
}
/* La pared que manda (FORTNITE): aquí la imagen repetida no es una textura
   de fondo, es la señal entera. Se enseña tal cual —sin invertir, más grande
   y con poca penumbra— y sólo los bordes se cierran a negro para que la
   barra de arriba, el buscador y el pie sigan leyéndose. Se activa con
   tileLoud:true en codes.js. */
.tiles.is-loud{
  opacity:.94;
  background-size:clamp(150px,19vw,250px) auto;
  filter:saturate(1.08) brightness(.88) contrast(1.04);
  animation-duration:220s;
}
/* la pared se ve en el centro; arriba y abajo el lienzo se cierra a negro
   para que la barra, la línea del pie y el buscador no compitan con las
   caras */
.tiles.is-loud::after{
  background:
    linear-gradient(180deg,rgba(6,6,8,.9),rgba(6,6,8,.12) 12%,rgba(6,6,8,0) 20%,rgba(6,6,8,0) 58%,rgba(6,6,8,.9)),
    radial-gradient(circle at 50% 46%,rgba(6,6,8,.34),rgba(6,6,8,.3) 58%,rgba(6,6,8,.5) 96%);
}
/* el contenido va encima: paneles oscuros para que no se pierda en la pared */
body.has-loud-tiles .sitecard{
  background:rgba(8,8,12,.72);
  -webkit-backdrop-filter:blur(3px);
  backdrop-filter:blur(3px);
}
body.has-loud-tiles .sitecard:hover,
body.has-loud-tiles .sitecard:focus-visible{background:rgba(8,8,12,.88)}
body.has-loud-tiles .vault{
  background:rgba(6,6,8,.78);
  -webkit-backdrop-filter:blur(3px);
  backdrop-filter:blur(3px);
}
body.has-loud-tiles .code{
  text-shadow:0 0 70px color-mix(in oklab,var(--accent) 60%,transparent),0 3px 30px rgba(0,0,0,.9);
}
body.has-loud-tiles .signal-no,
body.has-loud-tiles .meta-line,
body.has-loud-tiles .vmsg{text-shadow:0 1px 12px rgba(0,0,0,.95)}

/* --- barra superior ------------------------------------------------------- */
.topbar{
  position:relative;
  z-index:3;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:1rem;
  padding:.9rem var(--pad);
  border-bottom:1px solid var(--line-soft);
  font-size:.66rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--dim);
}
.brand{
  display:inline-flex;
  align-items:center;
  gap:.6rem;
  color:var(--paper);
  text-decoration:none;
  letter-spacing:.22em;
}
.brand .mark{
  font-size:.92rem;
  letter-spacing:.02em;
  text-transform:none;
  color:var(--paper);
  text-shadow:0 0 16px color-mix(in oklab,var(--accent) 65%,transparent);
  transition:color .18s,text-shadow .18s;
}
.brand:hover .mark{color:var(--accent)}
.brand:hover{color:var(--accent)}
.tb-mid{color:#5d5d6a}
.tb-right{display:inline-flex;align-items:center;gap:.45rem}
.tb-sound,.tb-share,.tb-cta{
  font:inherit;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--dim);
  background:none;
  border:1px solid var(--line-soft);
  padding:.45rem .7rem;
  cursor:pointer;
  text-decoration:none;
  transition:color .18s,border-color .18s;
}
.tb-share:hover,.tb-cta:hover,.tb-sound:hover{color:var(--accent);border-color:var(--accent)}

/* --- hilo sonoro de fondo ------------------------------------------------ */
.tb-sound{display:inline-flex;align-items:center;gap:.5rem}
.tb-sound .ico{--i:url(/icons/sound-on.svg);width:13px;height:13px;flex:0 0 13px}
html[data-sound="off"] .tb-sound .ico{--i:url(/icons/sound-off.svg)}
html[data-sound="off"] .tb-sound{color:#4b4b57;border-color:var(--line-soft)}
html[data-sound="off"] .tb-sound:hover{color:var(--accent)}
.tb-sound.is-waiting{
  color:var(--accent);
  border-color:color-mix(in oklab,var(--accent) 55%,transparent);
  box-shadow:0 0 0 1px color-mix(in oklab,var(--accent) 22%,transparent),0 0 22px -6px var(--accent);
  animation:sound-pulse 2.6s ease-in-out infinite;
}
.no-ambient .tb-sound{display:none}

.sound-hint{
  position:absolute;
  top:calc(100% + .5rem);
  right:var(--pad);
  z-index:2;
  display:inline-flex;
  align-items:center;
  gap:.55rem;
  padding:.5rem .75rem;
  font:500 .6rem/1 var(--mono);
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--paper);
  background:rgba(9,9,14,.86);
  border:1px solid color-mix(in oklab,var(--accent) 42%,var(--line));
  cursor:pointer;
  animation:rise .4s ease both;
}
.sound-hint:hover{color:var(--accent)}
.sh-dot{
  width:6px;
  height:6px;
  flex:0 0 6px;
  border-radius:50%;
  background:var(--accent);
  box-shadow:0 0 10px var(--accent);
  animation:ping 1.8s ease-in-out infinite;
}
@keyframes sound-pulse{
  0%,100%{box-shadow:0 0 0 1px color-mix(in oklab,var(--accent) 22%,transparent),0 0 22px -6px var(--accent)}
  50%{box-shadow:0 0 0 1px color-mix(in oklab,var(--accent) 40%,transparent),0 0 30px -2px var(--accent)}
}

/* --- portada -------------------------------------------------------------- */
.hero{
  position:relative;
  z-index:2;
  animation:hero-jolt 12s steps(1,end) infinite;
  max-width:920px;
  margin:clamp(2.6rem,9vh,6rem) auto 0;
  padding:0 var(--pad);
  text-align:center;
}
.kicker{
  margin:0 0 1.5rem;
  font-size:.66rem;
  letter-spacing:.34em;
  text-transform:uppercase;
  color:var(--dim);
}
.kicker b{color:var(--accent);font-weight:500}
.kicker .gl{
  position:relative;
  display:inline-block;
  color:#9a9aa8;
  animation:glitch-flick 4.2s steps(1,end) infinite;
}
/* el titileo de la cabecera: entra, se rompe medio segundo y se va */
@keyframes glitch-flick{
  0%,41%,100%{text-shadow:none;transform:none;opacity:1;color:#9a9aa8}
  42%{text-shadow:-2px 0 #ff2f6d,2px 0 #2ff0ff;transform:translateX(2px);color:#cdcdda}
  43%{text-shadow:2px 0 #ff2f6d,-2px 0 #2ff0ff;transform:translateX(-2px) skewX(-10deg);opacity:.6}
  44%{text-shadow:none;transform:none;opacity:1}
  45%{text-shadow:-3px 1px #2ff0ff,3px -1px #ff2f6d;transform:translate(2px,-1px)}
  46%{text-shadow:none;transform:none}
  47%{text-shadow:0 0 16px color-mix(in oklab,var(--accent) 80%,transparent);opacity:.45;color:#e6e6f2}
  48%,86%{text-shadow:none;opacity:1;color:#9a9aa8;transform:none}
  87%{text-shadow:-2px 0 #2ff0ff,2px 0 #ff2f6d;transform:translateX(-2px) skewX(7deg);opacity:.72}
  88%{text-shadow:2px 1px #ff2f6d,-2px -1px #2ff0ff;transform:translateY(-1px)}
  89%,100%{text-shadow:none;transform:none;opacity:1;color:#9a9aa8}
}
.hero h1{
  margin:0;
  font-family:var(--display);
  font-weight:400;
  font-size:clamp(3rem,14.5vw,8.5rem);
  line-height:.86;
  letter-spacing:.01em;
  text-transform:uppercase;
}
.hero h1 span{display:block}
.w1{color:var(--paper);animation:w1-split 5.4s steps(1,end) infinite}
.w2{
  position:relative;
  color:transparent;
  -webkit-text-stroke:1px color-mix(in oklab,var(--accent) 85%,#fff);
  animation:w2-glow 6.5s ease-in-out infinite;
}
.w2::before{
  content:'WORLD';
  position:absolute;
  inset:0;
  color:var(--accent);
  -webkit-text-stroke:1px var(--accent);
  clip-path:inset(30% 0 50% 0);
  animation:glitch 4.8s steps(1) infinite;
}
.lede{
  max-width:34rem;
  margin:1.8rem auto 0;
  color:#b9b9c6;
  font-size:.92rem;
  line-height:1.75;
  animation:lede-pulse 8.5s ease-in-out infinite;
}

/* --- buscador de códigos -------------------------------------------------- */
.vault{
  position:relative;
  display:flex;
  align-items:stretch;
  max-width:620px;
  margin:2.4rem auto 0;
  border:1px solid var(--line);
  background:rgba(255,255,255,.02);
  transition:border-color .2s,box-shadow .2s;
}
.vault:focus-within{
  border-color:var(--accent);
  box-shadow:0 0 0 1px var(--accent),0 0 48px -16px var(--accent);
}
.v-prompt{
  display:flex;
  align-items:center;
  padding-left:1rem;
  color:var(--accent);
  font-weight:700;
}
.vault input{
  flex:1;
  min-width:0;
  padding:1.05rem .75rem;
  border:0;
  outline:0;
  background:transparent;
  color:var(--paper);
  font:inherit;
  font-size:clamp(.86rem,2.5vw,1rem);
  letter-spacing:.18em;
  text-transform:uppercase;
  caret-color:var(--accent);
}
.vault input::placeholder{color:#57575f;letter-spacing:.18em}
.vault button{
  border:0;
  border-left:1px solid var(--line);
  background:transparent;
  color:var(--paper);
  font:700 .68rem/1 var(--mono);
  letter-spacing:.24em;
  text-transform:uppercase;
  padding:0 clamp(.9rem,3vw,1.5rem);
  cursor:pointer;
  transition:background .18s,color .18s;
}
.vault button:hover{background:var(--accent);color:var(--void)}
.vault.is-bad{border-color:var(--bad);animation:shake .36s ease-in-out}
.vault.is-bad .v-prompt{color:var(--bad)}
.vault.is-ok{border-color:var(--accent)}

.vmsg{
  min-height:1.5em;
  margin:1rem auto 0;
  max-width:620px;
  font-size:.66rem;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--dim);
}
.vmsg[data-state="bad"]{color:var(--bad)}
.vmsg[data-state="ok"]{color:var(--accent)}

.hints{
  display:flex;
  flex-wrap:wrap;
  gap:.5rem .9rem;
  justify-content:center;
  max-width:620px;
  margin:1.1rem auto 0;
}
.hints-label{
  flex:0 0 100%;
  margin:0;
  font-size:.6rem;
  letter-spacing:.3em;
  text-transform:uppercase;
  color:#5d5d6a;
}
.hint{
  font-size:.68rem;
  letter-spacing:.16em;
  color:#9a9aa8;
  border:1px dashed var(--line);
  padding:.28rem .55rem;
}
.hint b{color:var(--accent);font-weight:500}

.foot-note{
  max-width:620px;
  margin:1.6rem auto 0;
  font-size:.64rem;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:#5d5d6a;
}
.foot-note a{color:var(--dim);text-decoration:none;border-bottom:1px solid var(--line)}
.foot-note a:hover{color:var(--accent);border-color:var(--accent)}

/* --- rejilla de señales --------------------------------------------------- */
.signals{
  position:relative;
  z-index:2;
  max-width:var(--maxw);
  margin:clamp(3.4rem,9vh,6.5rem) auto 0;
  padding:0 var(--pad);
}
.signals-head{
  display:flex;
  align-items:baseline;
  justify-content:space-between;
  gap:1rem;
  padding-bottom:.75rem;
  border-bottom:1px solid var(--line);
  font-size:.66rem;
  letter-spacing:.3em;
  text-transform:uppercase;
  color:var(--dim);
}
.signals-head h2{margin:0;font:500 .66rem/1 var(--mono);letter-spacing:.3em}
.grid{
  list-style:none;
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(196px,1fr));
  gap:0;
  margin:.35rem 0 0;
  padding:0;
  background:transparent;
}
.slot{
  position:relative;
  display:flex;
  flex-direction:column;
  justify-content:space-between;
  aspect-ratio:5/3;
  padding:1rem;
  background:var(--void);
  outline:1px solid var(--line-soft);
  color:#4d4d59;
  text-decoration:none;
  transition:background .2s,color .2s;
  overflow:hidden;
}
.slot:hover{background:#101018}
.slot .n{
  font-size:.6rem;
  letter-spacing:.22em;
  text-transform:uppercase;
}
.slot .k{
  font-family:var(--display);
  font-size:clamp(1.15rem,3.2vw,1.7rem);
  line-height:1;
  letter-spacing:.04em;
  text-transform:uppercase;
  color:#3b3b46;
}
.blocks{display:inline-flex;gap:.16em}
.blk{
  display:inline-block;
  width:.6em;
  height:.78em;
  background:currentColor;
  opacity:.85;
}
.slot .go{
  position:absolute;
  right:.9rem;
  bottom:.85rem;
  font-size:.58rem;
  letter-spacing:.22em;
  text-transform:uppercase;
  color:var(--dim);
  opacity:0;
  transition:opacity .2s;
}
.slot.is-open{color:var(--accent)}
.slot.is-open .k{color:var(--paper)}
.slot.is-open .go{opacity:1}
.slot.is-open:hover{background:color-mix(in oklab,var(--accent) 14%,#0c0c11)}
.slot.is-open:hover .k{color:var(--accent)}
.slot:hover .blk{background:var(--dim)}

/* --- pie ------------------------------------------------------------------ */
.foot{
  position:relative;
  flex-direction:row;
  z-index:2;
  max-width:var(--maxw);
  margin:clamp(3.4rem,8vh,5.5rem) auto 0;
  padding:clamp(1.3rem,4vw,2rem) var(--pad) clamp(2rem,6vh,3.4rem);
  display:flex;
  flex-wrap:wrap;
  gap:1.2rem 1.6rem;
  align-items:center;
  justify-content:space-between;
  border-top:1px solid var(--line-soft);
  font-size:.62rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:#5d5d6a;
}

/* --- botones de redes ----------------------------------------------------- */
.socials{
  display:flex;
  flex-wrap:wrap;
  gap:.6rem;
  justify-content:center;
}
.social{
  display:inline-flex;
  align-items:center;
  gap:.6rem;
  padding:.72rem 1rem;
  border:1px solid var(--line);
  background:rgba(255,255,255,.03);
  color:var(--paper);
  font:600 .66rem/1 var(--mono);
  letter-spacing:.16em;
  text-transform:uppercase;
  text-decoration:none;
  transition:transform .18s,border-color .18s,color .18s,box-shadow .18s;
}
.social:hover{
  transform:translateY(-2px);
  border-color:var(--accent);
  color:var(--accent);
  box-shadow:0 10px 30px -18px var(--accent);
}
.ico{
  width:14px;
  height:14px;
  flex:0 0 14px;
  background-color:currentColor;
  -webkit-mask:var(--i) center/contain no-repeat;
  mask:var(--i) center/contain no-repeat;
}

/* --- sala de una señal ---------------------------------------------------- */
.room{
  position:relative;
  z-index:2;
  display:grid;
  justify-items:center;
  gap:clamp(1.3rem,3.4vh,2.2rem);
  max-width:860px;
  margin:0 auto;
  padding:clamp(1.8rem,6vh,4rem) var(--pad) clamp(2rem,7vh,4rem);
  text-align:center;
}
.room-head{display:grid;gap:.85rem;justify-items:center}
.signal-no{
  margin:0;
  font-size:.62rem;
  letter-spacing:.3em;
  text-transform:uppercase;
  color:var(--dim);
}
.signal-no b{color:var(--accent);font-weight:500}
.code{
  margin:0;
  font-family:var(--display);
  font-weight:400;
  font-size:clamp(2.6rem,12.5vw,6.6rem);
  line-height:.9;
  letter-spacing:.01em;
  text-transform:uppercase;
  text-shadow:0 0 70px color-mix(in oklab,var(--accent) 60%,transparent);
}

.frame{
  --maxh:min(56vh,560px);
  position:relative;
  width:min(100%,calc(var(--maxh) * var(--rw) / var(--rh)));
  aspect-ratio:var(--rw) / var(--rh);
  margin:0;
  background:#0b0b11;
  border:1px solid var(--line);
  box-shadow:0 40px 90px -40px #000,0 0 0 1px rgba(0,0,0,.5) inset;
  overflow:hidden;
}
.frame img{display:block;width:100%;height:100%;object-fit:cover}
.frame::after{
  content:'';
  position:absolute;
  inset:0;
  pointer-events:none;
  background:linear-gradient(180deg,rgba(6,6,8,.3),transparent 20%,transparent 76%,rgba(6,6,8,.5));
}
.frame-tag{
  position:absolute;
  left:0;
  bottom:0;
  z-index:2;
  padding:.5rem .7rem;
  background:rgba(6,6,8,.7);
  color:var(--accent);
  font-size:.58rem;
  letter-spacing:.26em;
  text-transform:uppercase;
}

.sub{
  max-width:38rem;
  margin:0;
  font-size:clamp(1rem,2.6vw,1.32rem);
  font-weight:300;
  line-height:1.6;
  color:var(--paper);
}
.sub-mark{color:var(--accent);margin-right:.35em}

.player{
  width:min(100%,720px);
  aspect-ratio:16/9;
  border:1px solid var(--line);
  background:#000;
  box-shadow:0 40px 90px -40px #000;
}
.player iframe{display:block;width:100%;height:100%;border:0}

/* --- vídeo externo: miniatura que se abre al pulsar ----------------------- */
.videocard{
  width:min(100%,var(--vmax,760px));
  border:1px solid var(--line);
  background:rgba(255,255,255,.02);
  box-shadow:0 40px 90px -50px #000;
  animation:rise .75s cubic-bezier(.2,.7,.2,1) both;
  animation-delay:.22s;
}
.vc-face{
  display:block;
  position:relative;
  width:100%;
  padding:0;
  border:0;
  background:#0b0b11;
  overflow:hidden;
  cursor:pointer;
}
.vc-face img{display:block;width:100%;height:auto;aspect-ratio:var(--vrw) / var(--vrh);object-fit:cover}
.vc-face::after{
  content:'';
  position:absolute;
  inset:0;
  background:linear-gradient(180deg,rgba(6,6,8,.04),rgba(6,6,8,.16) 55%,rgba(6,6,8,.6));
  transition:opacity .25s;
}
.vc-face:hover::after{opacity:.55}
.vc-play{
  position:absolute;
  top:50%;
  left:50%;
  width:66px;
  height:66px;
  margin:-33px 0 0 -33px;
  border:1px solid rgba(255,255,255,.45);
  border-radius:50%;
  background:rgba(6,6,8,.5);
  -webkit-backdrop-filter:blur(4px);
  backdrop-filter:blur(4px);
  transition:transform .2s,border-color .2s,background .2s,box-shadow .2s;
}
.vc-play::before{
  content:'';
  position:absolute;
  top:50%;
  left:50%;
  margin:-11px 0 0 -7px;
  border-left:17px solid var(--paper);
  border-top:11px solid transparent;
  border-bottom:11px solid transparent;
  transition:border-left-color .2s;
}
.vc-face:hover .vc-play,.vc-face:focus-visible .vc-play{
  transform:scale(1.07);
  border-color:var(--accent);
  background:rgba(6,6,8,.68);
  box-shadow:0 0 42px -8px var(--accent);
}
.vc-face:hover .vc-play::before,.vc-face:focus-visible .vc-play::before{border-left-color:var(--accent)}
.vc-tag{
  position:absolute;
  left:0;
  bottom:0;
  padding:.5rem .7rem;
  background:rgba(6,6,8,.72);
  border-top:1px solid var(--line-soft);
  border-right:1px solid var(--line-soft);
  color:var(--dim);
  font:500 .58rem/1 var(--mono);
  letter-spacing:.2em;
  text-transform:uppercase;
}
.vc-bar{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  justify-content:space-between;
  gap:.9rem;
  padding:.75rem .85rem;
  border-top:1px solid var(--line-soft);
}
.vc-title{
  margin:0;
  font:500 .72rem/1.45 var(--mono);
  color:var(--paper);
  letter-spacing:.02em;
}
.vc-by{color:var(--dim)}
.cta--sm{padding:.55rem .8rem;font-size:.6rem}
.videocard .vc-live{width:100%;aspect-ratio:var(--vrw) / var(--vrh);border:0;box-shadow:none}
/* vídeos verticales: la tarjeta se estrecha para no comerse la pantalla */
.videocard.is-tall{--vmax:380px}
.videocard.is-tall .vc-bar{flex-direction:column;align-items:stretch;gap:.7rem}
/* vídeos en cuadrado: la tarjeta se limita para que el cuadrado entre entero */
.videocard.is-square{--vmax:min(100%,520px)}
.videocard.is-square .vc-bar{flex-direction:column;align-items:stretch;gap:.7rem}

/* --- enlace externo: la tarjeta con su miniatura cuadrada ----------------- */
.sitecard{
  display:flex;
  align-items:center;
  gap:1rem;
  width:min(100%,760px);
  padding:.85rem;
  border:1px solid var(--line);
  background:rgba(255,255,255,.02);
  box-shadow:0 40px 90px -50px #000;
  color:inherit;
  text-decoration:none;
  animation:rise .75s cubic-bezier(.2,.7,.2,1) both;
  animation-delay:.24s;
  transition:border-color .2s,background .2s,box-shadow .2s;
}
.sitecard:hover,.sitecard:focus-visible{
  border-color:var(--accent);
  background:rgba(255,255,255,.05);
  box-shadow:0 40px 90px -50px #000,0 0 60px -26px var(--accent);
}
.sc-face{
  position:relative;
  flex:0 0 auto;
  width:104px;
  height:104px;
  border:1px solid var(--line-soft);
  background:#0b0b11;
  overflow:hidden;
}
.sc-face img{display:block;width:100%;height:100%;aspect-ratio:1 / 1;object-fit:cover;transition:transform .3s}
.sitecard:hover .sc-face img,.sitecard:focus-visible .sc-face img{transform:scale(1.05)}
.sc-body{display:flex;flex:1 1 auto;flex-direction:column;gap:.3rem;min-width:0;text-align:left}
.sc-tag{font:500 .56rem/1 var(--mono);letter-spacing:.2em;text-transform:uppercase;color:var(--dim)}
.sc-title{font:400 1.3rem/1.06 var(--display);text-transform:uppercase;letter-spacing:.02em;color:var(--paper)}
.sc-by{font:400 .68rem/1.3 var(--mono);color:var(--dim)}
.sc-go{
  display:inline-flex;
  align-items:center;
  gap:.6rem;
  flex:0 0 auto;
  padding:.72rem 1rem;
  border:1px solid var(--accent);
  color:var(--accent);
  font:600 .62rem/1 var(--mono);
  letter-spacing:.2em;
  text-transform:uppercase;
  transition:background .18s,color .18s;
}
.sc-go::after{
  content:'';
  width:9px;
  height:9px;
  border-top:1.5px solid currentColor;
  border-right:1.5px solid currentColor;
  transform:rotate(45deg) translate(-2px,2px);
  transition:transform .2s;
}
.sitecard:hover .sc-go,.sitecard:focus-visible .sc-go{background:var(--accent);color:var(--void)}
.sitecard:hover .sc-go::after,.sitecard:focus-visible .sc-go::after{transform:rotate(45deg) translate(1px,-1px)}
@media (max-width:720px){
  .sitecard{flex-wrap:wrap;gap:.85rem}
  .sc-face{width:76px;height:76px}
  .sc-title{font-size:1.1rem}
  .sc-go{width:100%;justify-content:center}
}

.ico--lg{width:42px;height:42px;flex:0 0 42px;opacity:.95}

.linkcard{
  display:grid;
  justify-items:center;
  gap:1rem;
  width:min(100%,620px);
  padding:clamp(1.8rem,5vw,2.8rem);
  border:1px solid var(--line);
  background:rgba(255,255,255,.02);
  box-shadow:0 40px 90px -50px #000;
}
.lc-title{
  margin:0;
  font-family:var(--display);
  font-size:clamp(1.5rem,4.4vw,2.2rem);
  line-height:1;
  text-transform:uppercase;
  letter-spacing:.02em;
}
.lc-note{
  margin:0 0 .4rem;
  font-size:.62rem;
  letter-spacing:.24em;
  text-transform:uppercase;
  color:var(--dim);
}

/* --- señal que sólo suena -------------------------------------------------- */
.track{
  position:relative;
  display:flex;
  align-items:center;
  gap:1.1rem;
  width:100%;
  max-width:660px;
  padding:1.1rem 1.2rem;
  border:1px solid var(--line);
  background:rgba(255,255,255,.02);
  box-shadow:0 40px 90px -50px #000;
}
.tk-btn{
  flex:0 0 auto;
  width:56px;
  height:56px;
  display:grid;
  place-items:center;
  border:1px solid var(--accent);
  border-radius:50%;
  background:none;
  color:var(--accent);
  cursor:pointer;
  transition:background .18s,color .18s,transform .18s;
}
.tk-btn:hover{background:var(--accent);color:var(--void)}
.tk-btn:active{transform:scale(.95)}
.tk-icon{
  width:0;
  height:0;
  margin-left:4px;
  border-style:solid;
  border-width:9px 0 9px 15px;
  border-color:transparent transparent transparent currentColor;
}
.track.is-playing .tk-icon{
  width:15px;
  height:17px;
  margin-left:0;
  border:0;
  background:currentColor;
  -webkit-mask:repeating-linear-gradient(90deg,#000 0 6px,transparent 6px 9px);
  mask:repeating-linear-gradient(90deg,#000 0 6px,transparent 6px 9px);
}
.tk-mid{flex:1 1 auto;min-width:0}
.tk-label{
  margin:0 0 .5rem;
  font-size:.58rem;
  letter-spacing:.24em;
  text-transform:uppercase;
  color:var(--dim);
}
.tk-bars{position:relative;height:28px}
.tk-bars .row{position:absolute;inset:0;display:flex;align-items:flex-end;gap:3px}
.tk-bars .row--on{clip-path:inset(0 calc(100% - var(--p,0%)) 0 0)}
.tk-bars i{
  flex:1 1 auto;
  height:18%;
  background:rgba(255,255,255,.12);
  animation:eq 1.1s ease-in-out infinite alternate;
  animation-play-state:paused;
}
.tk-bars .row--on i{background:var(--accent)}
.track.is-playing .tk-bars i{animation-play-state:running}
.tk-time{
  flex:0 0 auto;
  margin:0;
  font-family:var(--mono);
  font-size:.62rem;
  letter-spacing:.08em;
  color:#4d4d59;
}
.tk-time .tk-now{color:var(--paper)}
.track.needs-tap .tk-btn{animation:ping 2s ease-in-out infinite}

.cta{
  display:inline-flex;
  align-items:center;
  gap:.65rem;
  padding:.85rem 1.2rem;
  border:1px solid var(--accent);
  color:var(--accent);
  font:600 .68rem/1 var(--mono);
  letter-spacing:.2em;
  text-transform:uppercase;
  text-decoration:none;
  transition:background .18s,color .18s;
}
.cta:hover{background:var(--accent);color:var(--void)}

.room-nav{
  display:flex;
  flex-direction:column;
  align-items:center;
  width:100%;
  max-width:520px;
  padding-top:1.6rem;
  border-top:1px solid var(--line-soft);
}
.vault--mini{flex:1 1 auto;width:100%;max-width:none;margin:0}
.vault--mini input{padding:.8rem .7rem;font-size:.8rem}

.meta-line{
  margin:0;
  font-size:.58rem;
  letter-spacing:.26em;
  text-transform:uppercase;
  color:#4d4d59;
}
.room .vmsg{margin:0}

.noscript{
  position:relative;
  z-index:2;
  max-width:40rem;
  margin:2.5rem auto;
  padding:0 var(--pad);
  text-align:center;
}
.noscript h1{font-family:var(--display);font-size:2.6rem;margin:0 0 1rem}
.noscript a{color:var(--accent)}
.noscript ul{list-style:none;display:flex;flex-wrap:wrap;gap:.6rem 1.1rem;justify-content:center;margin:1.4rem 0;padding:0}
.foot p{margin:0}

/* --- animaciones ---------------------------------------------------------- */
@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@keyframes shake{
  0%,100%{transform:translateX(0)}
  18%{transform:translateX(-7px)}
  36%{transform:translateX(6px)}
  54%{transform:translateX(-4px)}
  72%{transform:translateX(3px)}
}
@keyframes sweep{0%{transform:translateY(-30vh)}100%{transform:translateY(115vh)}}
@keyframes eq{from{height:16%}to{height:var(--h,72%)}}
@keyframes ping{
  0%,100%{box-shadow:0 0 0 0 color-mix(in oklab,var(--accent) 55%,transparent)}
  50%{box-shadow:0 0 0 14px transparent}
}
@keyframes drift{from{background-position:0 0}to{background-position:340px 240px}}
@keyframes glitch{
  0%,88%,100%{opacity:0;transform:none}
  89%{opacity:1;transform:translate(-5px,1px) scaleY(1.1)}
  91%{opacity:0;transform:translate(5px,-2px)}
  92.5%{opacity:.85;transform:translate(-3px,2px)}
  94%{opacity:0}
  96%{opacity:.7;transform:translate(4px,1px)}
  97.5%{opacity:0;transform:none}
}

/* --- el ambiente, en marcha
   El barrido cruza la pantalla, el halo respira, el grano y las líneas de
   escaneo laten de vez en cuando, la frase de arriba se rompe medio segundo
   cada cuatro, el título se parte en rojo y cian y la portada entera da un
   tirón cada doce. Todo son animaciones cortas y espaciadas: la página está
   viva, pero en calma. Con «reducir movimiento» se apagan todas de golpe
   (la regla global de más abajo). */
@keyframes halo-breathe{
  0%,100%{opacity:.9;transform:scale(1)}
  50%{opacity:1;transform:scale(1.07)}
}
@keyframes grain-live{
  0%,100%{opacity:.16}
  23%{opacity:.22}
  24%,72%{opacity:.16}
  73%{opacity:.21}
  74%,100%{opacity:.16}
}
@keyframes scan-live{
  0%,100%{opacity:.5}
  31%{opacity:.62}
  32%,67%{opacity:.5}
  68%{opacity:.58}
  69%,100%{opacity:.5}
}
@keyframes w1-split{
  0%,63%,100%{text-shadow:none;transform:none}
  64%{text-shadow:-4px 0 #ff2f6d,4px 0 #2ff0ff;transform:translateX(2px)}
  65%{text-shadow:4px 0 #ff2f6d,-4px 0 #2ff0ff;transform:translateX(-2px) skewX(-.6deg)}
  66%{text-shadow:-2px 2px #2ff0ff;transform:none}
  67%,68%{text-shadow:none;transform:none}
  69%{text-shadow:0 0 26px color-mix(in oklab,var(--accent) 55%,transparent)}
  70%,100%{text-shadow:none;transform:none}
}
@keyframes w2-glow{
  0%,100%{opacity:.7}
  50%{opacity:1}
}
@keyframes hero-jolt{
  0%,93%,100%{transform:none;filter:none}
  94%{transform:translateX(-3px) skewX(.35deg);filter:brightness(1.14)}
  95%{transform:translateX(2px);filter:none}
  96%,100%{transform:none;filter:none}
}
@keyframes lede-pulse{
  0%,100%{text-shadow:none;color:#b9b9c6}
  45%{text-shadow:0 0 22px color-mix(in oklab,var(--accent) 45%,transparent);color:#d8d2e6}
  55%{text-shadow:0 0 14px color-mix(in oklab,var(--accent) 30%,transparent);color:#cac6d8}
}

.room-head,.frame,.player,.sub,.socials,.cta,.room-nav,.meta-line,.flip{animation:rise .75s cubic-bezier(.2,.7,.2,1) both}
.room-head{animation-delay:.04s}
.frame,.player,.flip{animation-delay:.12s}
.sub{animation-delay:.2s}
.socials,.cta{animation-delay:.26s}
.room-nav{animation-delay:.32s}
.meta-line{animation-delay:.38s}

/* --- adaptación a móvil --------------------------------------------------- */
@media (max-width:720px){
  .topbar{font-size:.58rem;letter-spacing:.14em;padding:.8rem var(--pad)}
  .tb-mid{display:none}
  .tb-sound,.tb-share,.tb-cta{padding:.42rem .58rem}
  .vc-play{width:56px;height:56px;margin:-28px 0 0 -28px}
  .vc-play::before{margin:-9px 0 0 -6px;border-left:14px solid var(--paper);border-top:9px solid transparent;border-bottom:9px solid transparent}
  .vc-bar{padding:.7rem .75rem}
  .vc-title{width:100%}
  .tb-word{display:none}
  .sound-hint{max-width:min(78vw,320px);letter-spacing:.12em}
  .frame{--maxh:min(46vh,430px)}
  .grid{grid-template-columns:repeat(auto-fill,minmax(146px,1fr))}
  .slot{aspect-ratio:3/2;padding:.8rem}
  .meta-line{letter-spacing:.18em}
}

/* --- respeto por quien prefiere menos movimiento -------------------------- */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important}
}

/* ==========================================================================
   SEÑAL QUE SACA DEL ARCHIVO (HOMERO) — entra y te manda fuera
   --------------------------------------------------------------------------
   La sala no tiene imagen ni frase: el código de la señal, una línea que dice
   que se sale, una barra que se llena y el enlace por si alguien no quiere
   esperar. A los 1,2 s (0,4 s con «reducir movimiento») el archivo redirige
   solo. Se declara con exit:'https://…' en codes.js.
   ========================================================================== */
body.is-exit .room--exit{
  display:grid;
  place-content:center;
  justify-items:center;
  gap:1.1rem;
  max-width:none;
  min-height:calc(100vh - 46px);
  padding:clamp(1.2rem,5vh,3rem) var(--pad);
  text-align:center;
}
body.is-exit .room--exit .sub{max-width:30rem;color:var(--dim);font-size:clamp(.95rem,2.2vw,1.1rem)}
.exit-bar{
  position:relative;
  width:min(260px,60vw);
  height:2px;
  overflow:hidden;
  background:color-mix(in oklab,var(--paper) 14%,transparent);
}
.exit-bar::after{
  content:'';
  position:absolute;
  inset:0;
  background:var(--accent);
  transform:scaleX(0);
  transform-origin:left center;
  animation:exit-fill 1.2s linear forwards;
}
@keyframes exit-fill{to{transform:scaleX(1)}}
.exit-link a{
  font-size:.58rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--dim);
  border-bottom:1px solid transparent;
}
.exit-link a:hover{color:var(--accent);border-color:currentColor}
@media (prefers-reduced-motion:reduce){
  .exit-bar::after{animation:none;transform:scaleX(1)}
}

/* ==========================================================================
   SEÑALES QUE SUENAN (MIKU · TETO) — sólo su imagen, y suena al pulsarla
   --------------------------------------------------------------------------
   Sin número, sin código y sin frase: la sala ES la ilustración. Cada clic
   lanza una copia nueva del audio, así que las copias se solapan sin cortarse.
   Se declaran con bare:true y sound:'/audio/…' en codes.js; la figura se
   recorta sola (los dibujos vienen con fondo transparente).
   El ancho se limita por la altura de la pantalla (--ar, la proporción de cada
   dibujo): así una figura alta y una cuadrada caben enteras, sin recortes ni
   barra de desplazamiento.
   ========================================================================== */
body.is-bare .room--bare{
  display:grid;
  place-items:center;
  gap:clamp(.9rem,2.6vh,1.5rem);
  max-width:none;
  min-height:calc(100vh - 46px);
  padding:clamp(1rem,4vh,2.5rem) var(--pad);
}
/* con frase debajo, la figura cede un poco de altura para que quepan las dos */
body.is-bare.has-sub .bare img{
  width:min(86vw,540px,calc(64vh * var(--ar,1)));
  max-height:64vh;
}
.bare-sub{
  max-width:34rem;
  text-align:center;
  font-size:clamp(1rem,2.4vw,1.22rem);
}
.bare{
  display:block;
  padding:0;
  border:0;
  background:none;
  cursor:pointer;
  -webkit-tap-highlight-color:transparent;
  animation:bare-bob 6.5s ease-in-out infinite;
}
.bare img{
  display:block;
  width:min(86vw,540px,calc(76vh * var(--ar,1)));
  max-height:76vh;
  height:auto;
  filter:drop-shadow(0 26px 60px rgba(0,0,0,.7));
  transition:transform .3s cubic-bezier(.2,.7,.3,1),filter .3s;
}
.bare:hover img,
.bare:focus-visible img{
  transform:translateY(-8px) scale(1.035);
  filter:drop-shadow(0 34px 74px color-mix(in oklab,var(--accent) 45%,transparent));
}
.bare:active img{transform:translateY(-2px) scale(.985)}
@keyframes bare-bob{50%{transform:translateY(-7px)}}
@media (prefers-reduced-motion:reduce){
  .bare{animation:none}
  .bare img{transition:none}
  .bare:hover img,
  .bare:focus-visible img,
  .bare:active img{transform:none}
}

/* ==========================================================================
   LA PUERTA (ROOM) — la sala de un solo golpe
   --------------------------------------------------------------------------
   No hay número, ni código, ni frase, ni nada más: sólo una puerta cerrada.
   El lienzo se pinta EXACTAMENTE del negro de la imagen (#020202, el mismo
   píxel que rodea la puerta), así que no hay marco ni borde que la delate: la
   puerta no está puesta en la página, está en la habitación. Encima cae una
   penumbra que cierra las esquinas a negro, de modo que el borde de la foto no
   asoma nunca, y respira muy despacio para que la puerta parezca estar viva.
   Al pulsarla suena el golpe —una copia nueva por clic, así que los golpes se
   encadenan— y la puerta cede un instante, como si la empujaran desde dentro.
   La barra superior se apaga casi del todo: sólo vuelve si el visitante la
   busca con el ratón o con el tabulador (sigue siendo la salida a la portada).
   Se declara con door:true en codes.js.
   ========================================================================== */
html.is-room-bg{background:#020202}
body.is-room{background:#020202;overflow:hidden}
/* sin halo de acento: aquí el negro es negro */
body.is-room::before{background:none}
/* el grano y las líneas de barrido se quedan (le dan el aire de cinta),
   pero el barrido de color que recorre las otras salas se apaga */
body.is-room .fx-sweep{display:none}
body.is-room .fx-scan{opacity:.22}
body.is-room .fx-grain{opacity:.1}

/* la barra se apaga y vuelve cuando se la busca */
body.is-room .topbar{border-bottom-color:transparent}
body.is-room .topbar>*{opacity:.14;transition:opacity .7s ease}
body.is-room .topbar:hover>*,
body.is-room .topbar:focus-within>*{opacity:1}
/* aquí el gesto es el propio golpe: el aviso de audio sobra */
body.is-room .sound-hint{display:none}

body.is-room .room--door{
  position:fixed;
  inset:0;
  z-index:2;
  display:block;
  max-width:none;
  margin:0;
  padding:0;
  text-align:center;
}
.door{
  display:block;
  width:100%;
  height:100%;
  padding:0;
  border:0;
  background:none;
  cursor:pointer;
  touch-action:manipulation;
  -webkit-tap-highlight-color:transparent;
  animation:door-breathe 13s ease-in-out infinite;
}
.door img{
  display:block;
  width:100%;
  height:100%;
  object-fit:contain;
  user-select:none;
  -webkit-user-drag:none;
  filter:brightness(1);
  transition:filter .55s ease;
}
/* quien se acerca a la puerta, la enciende un poco */
.door:hover img,
.door:focus-visible img{filter:brightness(1.16)}
.door:active img{filter:brightness(1.3)}
body.is-room .door:focus-visible{outline:2px solid var(--accent);outline-offset:-6px}

/* En vertical (móvil) la puerta se acerca: se llena la pantalla y sólo se
   recorta negro de los lados —la puerta queda entera, con su marco—, así que
   la habitación sigue sin bordes visibles. */
@media (max-aspect-ratio:1/1) and (min-aspect-ratio:9/20){
  .door img{object-fit:cover}
}

/* respira: se acerca y se aleja muy despacio */
@keyframes door-breathe{
  0%,100%{transform:scale(1)}
  50%{transform:scale(1.022)}
}
/* el golpe: la puerta cede hacia dentro y vuelve */
.door.is-hit{animation:door-hit .52s cubic-bezier(.2,.7,.3,1)}
@keyframes door-hit{
  0%{transform:translateX(0)}
  12%{transform:translateX(-10px)}
  28%{transform:translateX(7px)}
  45%{transform:translateX(-4px)}
  63%{transform:translateX(3px)}
  81%{transform:translateX(-1px)}
  100%{transform:translateX(0)}
}

/* El subtexto escondido. Va escrito bajo la puerta con casi el mismo negro que
   la habitación —la opacidad exacta la pone app.js según los golpes—, así que
   no se lee: aparece si alguien selecciona el texto (el resaltado lo enciende)
   o si insiste en llamar. No recibe clics: los golpes siguen siendo golpes. */
.door-sub{
  position:absolute;
  left:clamp(1rem,4vw,3rem);
  right:clamp(1rem,4vw,3rem);
  bottom:clamp(1rem,4.5vh,2.6rem);
  margin:0;
  font-size:clamp(.6rem,1.6vw,.72rem);
  letter-spacing:.34em;
  text-indent:.34em;
  text-align:center;
  color:rgb(168 182 200 / var(--sub-a,.055));
  pointer-events:none;
  transition:color .6s linear;
}
.door-sub::selection{background:rgb(168 182 200 / .9);color:#05070a}

/* Y la puerta que cede: la habitación se queda en sombra y sale el subtexto. */
body.is-gate .door{animation:none}
body.is-gate .door img{filter:brightness(.28) saturate(.6);transition:filter 1.2s ease}
body.is-gate .door-sub{color:rgb(232 240 250 / .97);text-shadow:0 0 22px rgb(190 214 255 / .35);transition:color 1s ease}
body.is-gate .door-vig{
  opacity:1;
  animation:none;
  background:radial-gradient(ellipse 78% 86% at 50% 50%,rgba(0,0,0,.34) 34%,rgba(0,0,0,.97) 100%);
}
body.is-gate .topbar>*{opacity:.05}

/* la penumbra: entra de las esquinas y aprieta */
.door-vig{
  position:fixed;
  inset:0;
  z-index:2;
  pointer-events:none;
  background:radial-gradient(ellipse 74% 82% at 50% 50%,rgba(0,0,0,0) 40%,rgba(0,0,0,.42) 76%,rgba(0,0,0,.92) 100%);
  animation:door-dark 16s ease-in-out infinite;
}
@keyframes door-dark{50%{opacity:.66}}

@media (prefers-reduced-motion:reduce){
  .door{animation:none}
  .door img{transition:none}
  .door:hover img,
  .door:focus-visible img,
  .door:active img{filter:none}
  .door.is-hit{animation:none}
  .door-vig{animation:none}
}

/* ==========================================================================
   SEÑAL PLANA (TGSWIIWAGAA) — la página de un solo color
   --------------------------------------------------------------------------
   La única sala sin penumbra: todo el lienzo es el color de la señal y todo lo
   que en el resto del archivo es blanco, aquí es tinta oscura. Se pone con
   flat:'#B2F802' en codes.js (y el acento oscuro que la acompaña); la tinta
   vive aquí. Se reescriben los colores base para que los componentes ya
   hechos (marco, tarjeta de vídeo, buscador, botones) se pinten solos.
   ========================================================================== */
html.is-flat-bg{background:var(--flat)}
body.is-flat{
  --ink-flat:#0e1500;
  --paper:var(--ink-flat);
  --dim:rgba(14,21,0,.62);
  --line:rgba(14,21,0,.45);
  --line-soft:rgba(14,21,0,.24);
  --void:var(--flat);
  --bad:#8f1200;
  background:var(--flat);
  color:var(--ink-flat);
  scrollbar-color:rgba(14,21,0,.5) var(--flat);
}
body.is-flat::before{display:none}
body.is-flat ::selection{background:var(--ink-flat);color:var(--flat)}
body.is-flat :focus-visible{outline:2px solid var(--ink-flat);outline-offset:3px}
/* la textura sigue, pero en tinta: grano multiplicado y líneas oscuras */
body.is-flat .fx-grain{opacity:.18;mix-blend-mode:multiply;filter:invert(1) contrast(1.5)}
body.is-flat .fx-scan{opacity:.55;background:repeating-linear-gradient(180deg,rgba(14,21,0,.09) 0 1px,transparent 1px 4px)}
body.is-flat .fx-sweep{display:none}

/* barra de arriba en tinta (sigue llevando a casa) ------------------------- */
body.is-flat .topbar{color:var(--dim);border-bottom-color:var(--line-soft)}
body.is-flat .brand,
body.is-flat .brand .mark{color:var(--ink-flat);text-shadow:none}
body.is-flat .brand:hover,
body.is-flat .brand:hover .mark{color:var(--ink-flat);opacity:.65}
body.is-flat .tb-mid{color:rgba(14,21,0,.4)}
body.is-flat .tb-sound,
body.is-flat .tb-share,
body.is-flat .tb-cta{color:var(--ink-flat);border-color:rgba(14,21,0,.4)}
body.is-flat .tb-sound:hover,
body.is-flat .tb-share:hover,
body.is-flat .tb-cta:hover{background:var(--ink-flat);color:var(--flat);border-color:var(--ink-flat)}
body.is-flat .tb-sound.is-waiting{color:var(--ink-flat);border-color:var(--ink-flat);box-shadow:0 0 0 1px rgba(14,21,0,.35);animation:none}
html[data-sound="off"] body.is-flat .tb-sound{color:rgba(14,21,0,.5);border-color:rgba(14,21,0,.3)}
body.is-flat .sound-hint{color:var(--flat);background:var(--ink-flat);border-color:var(--ink-flat)}
body.is-flat .sound-hint:hover{color:var(--ink-flat);background:var(--flat)}
body.is-flat .sh-dot{background:var(--flat);box-shadow:none}

/* la señal: un código largo, su frase y el vídeo de abajo ------------------ */
body.is-flat .signal-no{color:rgba(14,21,0,.6)}
body.is-flat .signal-no b{color:var(--ink-flat)}
body.is-flat .code{color:var(--ink-flat);text-shadow:none;font-size:clamp(2rem,9.4vw,5.2rem)}
body.is-flat .sub{color:var(--ink-flat)}
body.is-flat .sub-mark{color:var(--ink-flat);opacity:.5}

body.is-flat .videocard{
  background:rgba(14,21,0,.06);
  border-color:var(--ink-flat);
  box-shadow:7px 7px 0 rgba(14,21,0,.9);
}
body.is-flat .vc-face::after{background:linear-gradient(180deg,rgba(14,21,0,.04),rgba(14,21,0,.1) 58%,rgba(14,21,0,.45))}
body.is-flat .vc-face:hover::after{opacity:.6}
body.is-flat .vc-play{
  border-color:var(--ink-flat);
  background:rgba(178,248,2,.75);
  box-shadow:none;
  -webkit-backdrop-filter:none;
  backdrop-filter:none;
}
body.is-flat .vc-play::before{border-left-color:var(--ink-flat)}
body.is-flat .vc-face:hover .vc-play,
body.is-flat .vc-face:focus-visible .vc-play{background:var(--ink-flat);border-color:var(--ink-flat);transform:scale(1.06);box-shadow:none}
body.is-flat .vc-face:hover .vc-play::before,
body.is-flat .vc-face:focus-visible .vc-play::before{border-left-color:var(--flat)}
body.is-flat .vc-tag{background:rgba(178,248,2,.88);border-color:var(--ink-flat);color:var(--ink-flat)}
body.is-flat .vc-bar{border-top-color:rgba(14,21,0,.35)}
body.is-flat .vc-title{color:var(--ink-flat)}
body.is-flat .vc-by{color:rgba(14,21,0,.62)}
body.is-flat .player{border-color:var(--ink-flat);background:var(--ink-flat);box-shadow:7px 7px 0 rgba(14,21,0,.9)}

/* el buscador y el pie de la sala ----------------------------------------- */
body.is-flat .vault{background:rgba(14,21,0,.05);border-color:rgba(14,21,0,.45)}
body.is-flat .vault input{color:var(--ink-flat)}
body.is-flat .vault input::placeholder{color:rgba(14,21,0,.42)}
body.is-flat .vault button{border-left-color:rgba(14,21,0,.35);color:var(--ink-flat)}
body.is-flat .vault button:hover{background:var(--ink-flat);color:var(--flat)}
body.is-flat .room-nav{border-top-color:rgba(14,21,0,.3)}
body.is-flat .meta-line{color:rgba(14,21,0,.55)}
body.is-flat .vmsg[data-state="ok"]{color:var(--ink-flat)}

/* ==========================================================================
   SEÑAL LOG — la grabación recuperada (001)
   --------------------------------------------------------------------------
   Sin imagen y sin frase: lo que hay es una cinta. Un registro de audio con su
   contador, su onda —una sola forma, que no baila: es una grabación y se lee
   entera— y tres líneas de registro. El punto rojo late como un REC y el
   cabezal se mueve con lo que suena. Arranca sola al entrar.
   ========================================================================== */
.room--log{max-width:640px}
.log{
  display:grid;
  gap:1.05rem;
  width:min(100%,540px);
  padding:clamp(1.1rem,3.4vw,1.55rem);
  border:1px solid var(--line);
  background:rgba(255,255,255,.02);
  box-shadow:0 40px 90px -50px #000,0 0 70px -42px var(--accent);
  text-align:left;
  animation:rise .75s cubic-bezier(.2,.7,.2,1) both;
}
.log audio{display:none}
.log-top{
  display:flex;
  align-items:center;
  gap:.55rem;
  margin:0;
  color:var(--dim);
  font:500 .58rem/1 var(--mono);
  letter-spacing:.24em;
  text-transform:uppercase;
}
.log-rec{
  flex:0 0 8px;
  width:8px;
  height:8px;
  border-radius:50%;
  background:#ff3b3b;
  box-shadow:0 0 12px #ff3b3b;
  animation:rec 2.6s steps(1,end) infinite;
}
.log-reel{position:relative;height:clamp(52px,12vw,66px)}
.log-reel .row{position:absolute;inset:0;display:flex;align-items:center;gap:2px}
.log-reel .row--on{clip-path:inset(0 calc(100% - var(--p,0%)) 0 0)}
.log-reel i{flex:1 1 auto;height:var(--h,30%);background:rgba(255,255,255,.13)}
.log-reel .row--on i{background:var(--accent)}
.log-head{
  position:absolute;
  top:0;
  bottom:0;
  left:var(--p,0%);
  width:1px;
  background:var(--accent);
  opacity:0;
  transition:opacity .2s;
}
body.is-log-playing .log-head{opacity:.85;box-shadow:0 0 14px var(--accent)}
.log-face{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  justify-content:space-between;
  gap:.9rem;
  padding-top:.9rem;
  border-top:1px solid var(--line-soft);
}
.log-time{margin:0;font-family:var(--mono);font-size:.78rem;letter-spacing:.1em;color:#4d4d59}
.log-time b{color:var(--paper);font-weight:500}
.log-ctl{display:flex;align-items:center;gap:.65rem}
.log-btn{
  display:inline-flex;
  align-items:center;
  justify-content:center;
  width:46px;
  height:46px;
  padding:0;
  border:1px solid var(--accent);
  border-radius:50%;
  background:none;
  color:var(--accent);
  cursor:pointer;
  transition:background .18s,color .18s,transform .18s;
}
.log-btn:hover{background:var(--accent);color:var(--void)}
.log-btn:active{transform:scale(.94)}
.log-icon{
  width:0;
  height:0;
  margin-left:4px;
  border-style:solid;
  border-width:8px 0 8px 13px;
  border-color:transparent transparent transparent currentColor;
}
body.is-log-playing .log-icon{
  width:13px;
  height:15px;
  margin-left:0;
  border:0;
  background:currentColor;
  -webkit-mask:repeating-linear-gradient(90deg,#000 0 5px,transparent 5px 8px);
  mask:repeating-linear-gradient(90deg,#000 0 5px,transparent 5px 8px);
}
.log-again{
  padding:.6rem .8rem;
  border:1px solid var(--line-soft);
  background:none;
  color:var(--dim);
  font:500 .56rem/1 var(--mono);
  letter-spacing:.2em;
  text-transform:uppercase;
  cursor:pointer;
  transition:border-color .18s,color .18s;
}
.log-again:hover{border-color:var(--accent);color:var(--paper)}
.log-notes{display:grid;gap:.45rem;margin:0;padding:0;list-style:none;font-family:var(--mono);font-size:.68rem;color:var(--dim)}
.log-notes li{display:grid;grid-template-columns:8.6rem 1fr;gap:.6rem}
.log-notes span{color:var(--accent);font-size:.56rem;letter-spacing:.2em;text-transform:uppercase}
body.log-needs-tap .log-btn{animation:ping 2s ease-in-out infinite}

/* ==========================================================================
   SEÑALES DE SPOTIFY — PORTER y MADEON
   --------------------------------------------------------------------------
   El par. La misma tarjeta para las dos: la portada real de la lista, su
   nombre y quién la hizo. De Spotify no se carga nada hasta que el visitante
   la pulsa; entonces el reproductor de Spotify se abre dentro de la página.
   El enlace para abrirla en su aplicación está siempre a la vista.
   ========================================================================== */
.spotcard{
  display:flex;
  align-items:center;
  gap:1rem;
  width:min(100%,760px);
  padding:.85rem;
  border:1px solid var(--line);
  background:rgba(255,255,255,.02);
  box-shadow:0 40px 90px -50px #000;
  text-align:left;
  animation:rise .75s cubic-bezier(.2,.7,.2,1) both;
  animation-delay:.16s;
}
.sp-face{
  position:relative;
  flex:0 0 auto;
  width:118px;
  height:118px;
  padding:0;
  border:1px solid var(--line-soft);
  background:#0b0b11;
  overflow:hidden;
  cursor:pointer;
}
.sp-face img{display:block;width:100%;height:100%;aspect-ratio:1 / 1;object-fit:cover;transition:transform .35s}
.sp-face::after{
  content:'';
  position:absolute;
  inset:0;
  background:linear-gradient(180deg,rgba(6,6,8,.08),rgba(6,6,8,.55));
  transition:opacity .25s;
}
.sp-face:hover::after,.sp-face:focus-visible::after{opacity:.5}
.sp-face:hover img,.sp-face:focus-visible img{transform:scale(1.04)}
.sp-play{
  position:absolute;
  top:50%;
  left:50%;
  z-index:2;
  width:54px;
  height:54px;
  margin:-27px 0 0 -27px;
  border:1px solid rgba(255,255,255,.5);
  border-radius:50%;
  background:rgba(6,6,8,.5);
  -webkit-backdrop-filter:blur(4px);
  backdrop-filter:blur(4px);
  transition:transform .2s,border-color .2s,background .2s,box-shadow .2s;
}
.sp-play::before{
  content:'';
  position:absolute;
  top:50%;
  left:50%;
  margin:-9px 0 0 -5px;
  border-left:14px solid var(--paper);
  border-top:9px solid transparent;
  border-bottom:9px solid transparent;
  transition:border-left-color .2s;
}
.sp-face:hover .sp-play,.sp-face:focus-visible .sp-play{
  transform:scale(1.07);
  border-color:var(--accent);
  background:rgba(6,6,8,.7);
  box-shadow:0 0 42px -8px var(--accent);
}
.sp-face:hover .sp-play::before,.sp-face:focus-visible .sp-play::before{border-left-color:var(--accent)}
.sp-tag{
  position:absolute;
  left:0;
  bottom:0;
  z-index:2;
  padding:.4rem .55rem;
  background:rgba(6,6,8,.78);
  border-top:1px solid var(--line-soft);
  border-right:1px solid var(--line-soft);
  color:var(--dim);
  font:500 .48rem/1 var(--mono);
  letter-spacing:.14em;
  text-transform:uppercase;
  white-space:nowrap;
}
.sp-body{display:flex;flex:1 1 auto;flex-direction:column;gap:.35rem;min-width:0}
.sp-title{margin:0;font-family:var(--display);font-size:1.3rem;line-height:1.06;letter-spacing:.02em;text-transform:uppercase;color:var(--paper)}
.sp-by{margin:0;font:400 .68rem/1.3 var(--mono);color:var(--dim)}
.sp-live{width:100%;border:1px solid var(--line);background:#000;box-shadow:0 40px 90px -50px #000}
.sp-live iframe{display:block;width:100%;height:clamp(352px,44vh,460px);border:0}
.spotcard.is-live{display:grid;gap:.85rem}
.sp-bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.8rem}
@media (max-width:720px){
  .spotcard{flex-wrap:wrap;gap:.85rem}
  .sp-face{width:88px;height:88px}
  .sp-title{font-size:1.08rem}
  .sp-tag{font-size:.42rem;letter-spacing:.06em;padding:.35rem .45rem}
  .sp-play{width:44px;height:44px;margin:-22px 0 0 -22px}
  .sp-play::before{margin:-7px 0 0 -4px;border-left-width:11px;border-top-width:7px;border-bottom-width:7px}
  .sp-open{width:100%;justify-content:center}
  .log-notes li{grid-template-columns:1fr;gap:.12rem}
}
@media (prefers-reduced-motion:reduce){
  .log-rec{animation:none;box-shadow:none}
}

/* ==========================================================================
   SEÑAL ALBUM — la página rota
   --------------------------------------------------------------------------
   La única señal sin imagen y sin texto. Aquí no hay nada que leer: piezas de
   basura superpuestas sobre blanco, moviéndose a tirones (steps) y cambiando
   de letras desde app.js. Rompe la norma del archivo a propósito.
   ========================================================================== */
html.is-broken-bg{background:#fff}
body.is-broken{background:#fff;color:#000}
body.is-broken::before{display:none}
body.is-broken ::selection{background:#000;color:#fff}
body.is-broken :focus-visible{outline:2px solid #000;outline-offset:3px}
body.is-broken .fx-grain{opacity:.22;mix-blend-mode:multiply;filter:invert(1) contrast(1.6) brightness(1.12)}
body.is-broken .fx-scan{opacity:1;background:repeating-linear-gradient(180deg,rgba(0,0,0,.17) 0 1px,transparent 1px 4px)}
body.is-broken .fx-sweep{opacity:.5;height:20vh;background:linear-gradient(180deg,transparent,rgba(0,0,0,.3),transparent);animation-duration:3.4s}

/* la barra de arriba tiembla y se ensucia, pero sigue llevando a casa ------- */
html.is-broken-runs .topbar{animation:brk-jit 1.15s steps(1,end) infinite}
body.is-broken .topbar{color:#000;border-bottom-color:rgba(0,0,0,.28)}
body.is-broken .brand,
body.is-broken .brand .mark,
body.is-broken .brand:hover,
body.is-broken .brand:hover .mark{color:#000;text-shadow:1.5px 0 #ff0037,-1.5px 0 #00d5ff}
body.is-broken .tb-mid{color:#000;opacity:.4}
body.is-broken .tb-sound,
body.is-broken .tb-share,
body.is-broken .tb-cta{color:#000;border-color:rgba(0,0,0,.32)}
body.is-broken .tb-sound:hover,
body.is-broken .tb-share:hover,
body.is-broken .tb-cta:hover{background:#000;color:#fff;border-color:#000}
body.is-broken .tb-sound.is-waiting{box-shadow:none;border-color:#000}
body.is-broken .sound-hint{background:#fff;color:#000;border-color:#000}
body.is-broken .sound-hint:hover{background:#000;color:#fff}
body.is-broken .sh-dot{background:#000;box-shadow:none}

/* la sala deja de ser una sala -------------------------------------------- */
body.is-broken .room{display:block;max-width:none;margin:0;padding:0;text-align:left}
.brk{position:relative;min-height:calc(100vh - 3rem);overflow:clip;background:#fff}

/* piezas de basura: cada una con su sitio, su giro y su temblor ------------ */
.brk-bit{
  position:absolute;
  left:var(--x);
  top:var(--y);
  z-index:1;
  margin:0;
  white-space:nowrap;
  font-size:calc(var(--s) * 1vw);
  line-height:1;
  opacity:var(--o,1);
  rotate:var(--r);
  transform-origin:left center;
  animation:brk-jit var(--d,1s) steps(1,end) var(--dl,0s) infinite;
  will-change:transform,opacity;
}
.brk-bit[data-face="display"]{font-family:var(--display);text-transform:uppercase;letter-spacing:-.01em}
.brk-bit[data-face="mono"]{font-family:var(--mono);font-weight:700;letter-spacing:.04em}
.brk-bit[data-tone="red"]{color:#ff0037;text-shadow:2px 0 rgba(0,213,255,.75)}
.brk-bit[data-tone="cyan"]{color:#00b8e6;text-shadow:-2px 0 rgba(255,0,55,.7)}
.brk-bit[data-tone="gray"]{color:#8c8c94}
.brk-bit[data-tone="outline"]{color:transparent;-webkit-text-stroke:2px #000}
.brk-bit[data-tone="blur"]{color:#000;filter:blur(1.7px);mix-blend-mode:multiply}
.brk-bit.is-off{visibility:hidden}

/* franjas negras que se arrastran por encima ------------------------------- */
.brk-bar{
  position:absolute;
  left:-2%;
  right:-2%;
  z-index:3;
  height:var(--h,8px);
  background:#000;
  opacity:var(--o,.12);
  animation:brk-bar var(--d,2.4s) steps(1,end) var(--dl,0s) infinite;
  will-change:transform;
}

/* el recuadro de imagen que no cargó ------------------------------------- */
.brk-img{
  position:absolute;
  left:58%;
  top:20%;
  z-index:4;
  width:clamp(120px,17vw,220px);
  aspect-ratio:16/10;
  display:grid;
  place-items:center;
  border:3px solid #000;
  background:repeating-linear-gradient(115deg,#000 0 4px,#fff 4px 11px);
  rotate:6deg;
  animation:brk-jit 1.6s steps(1,end) -.4s infinite;
}
.brk-img::after{
  content:'IMG 0 · ✕';
  padding:.25rem .4rem;
  background:#fff;
  border:1px solid #000;
  color:#000;
  font:700 .6rem/1 var(--mono);
  letter-spacing:.14em;
}

/* el título, partido en tres capas desfasadas ----------------------------- */
.brk-head{
  position:absolute;
  left:-1.5vw;
  top:2vh;
  z-index:2;
  margin:0;
  font-family:var(--display);
  font-size:25vw;
  line-height:.82;
  letter-spacing:-.03em;
  text-transform:uppercase;
  color:#000;
  rotate:-2deg;
  animation:brk-jit 2.1s steps(1,end) -.7s infinite;
}
.brk-head::before,
.brk-head::after{content:attr(data-t);position:absolute;inset:0;pointer-events:none}
.brk-head::before{color:#ff0037;mix-blend-mode:multiply;animation:brk-slice-a 2.6s steps(1,end) infinite}
.brk-head::after{color:#00d5ff;mix-blend-mode:multiply;animation:brk-slice-b 3.3s steps(1,end) -.9s infinite}

/* y una nota al pie igual de rota ---------------------------------------- */
.brk-tag{
  position:absolute;
  left:6%;
  bottom:4%;
  z-index:5;
  margin:0;
  color:#000;
  font:700 clamp(.55rem,1vw,.72rem)/1.6 var(--mono);
  letter-spacing:.28em;
  text-transform:uppercase;
  text-shadow:1.5px 0 #ff0037,-1.5px 0 #00d5ff;
  animation:brk-jit .85s steps(1,end) -.2s infinite;
}

/* las piezas dan tirones y de vez en cuando se les corta un trozo --------- */
@keyframes brk-jit{
  0%,100%{transform:translate(0,0);opacity:var(--o,1);clip-path:none}
  7%{transform:translate(var(--j1,-3px),1px)}
  9%{transform:translate(0,0);opacity:calc(var(--o,1) * .35)}
  11%{transform:translate(0,0);opacity:var(--o,1)}
  27%{transform:translate(2px,-2px);clip-path:inset(0 0 42% 0)}
  29%{transform:translate(0,0);clip-path:none}
  58%{transform:translate(var(--j2,4px),2px);opacity:calc(var(--o,1) * .6)}
  60%{transform:translate(0,0);opacity:var(--o,1)}
  81%{transform:translate(-2px,-3px);clip-path:inset(46% 0 0 0)}
  83%{transform:translate(0,0);clip-path:none}
}
@keyframes brk-bar{
  0%,100%{transform:translateY(0) scaleY(1)}
  22%{transform:translateY(9vh) scaleY(2.6)}
  48%{transform:translateY(-5vh) scaleY(.4)}
  63%{transform:translateY(3vh) scaleY(1.8)}
}
@keyframes brk-slice-a{
  0%,100%{transform:translate(-5px,3px);clip-path:inset(0 0 61% 0)}
  38%{transform:translate(7px,-4px);clip-path:inset(34% 0 14% 0)}
  64%{transform:translate(-3px,5px);clip-path:inset(72% 0 0 0)}
}
@keyframes brk-slice-b{
  0%,100%{transform:translate(5px,-3px);clip-path:inset(46% 0 8% 0)}
  29%{transform:translate(-8px,4px);clip-path:inset(0 0 70% 0)}
  71%{transform:translate(4px,6px);clip-path:inset(76% 0 0 0)}
}

@media (max-width:720px){
  .brk{min-height:86vh}
  .brk-head{font-size:29vw;left:-2vw}
  .brk-bit[data-tone="red"],.brk-bit[data-tone="cyan"]{text-shadow:1px 0 rgba(0,0,0,.5)}
  .brk-tag{left:5%;bottom:5%;letter-spacing:.18em}
}

/* ==========================================================================
   SEÑAL FREDDY — la que avisa
   --------------------------------------------------------------------------
   Un jumpscare a pantalla completa, después estática, y la página se cierra
   sola para volver a la portada. Sin chrome: ni barra ni halo ni ruido de
   fondo. Todo negro, todo vacío, hasta el grito.
   ========================================================================== */
body.is-freddy{background:#000;color:#000;overflow:hidden;cursor:none}
body.is-freddy::before,
body.is-freddy .fx,
body.is-freddy .topbar,
body.is-broken .topbar .tb-sound.is-waiting,
body.is-freddy .sound-hint{display:none!important}

body.is-freddy .room--freddy{position:fixed;inset:0;display:block;max-width:none;margin:0;padding:0;text-align:left;z-index:120}
.frd{position:fixed;inset:0;background:#000;overflow:hidden}

/* "monitor" que parpadea antes del grito ------------------------------- */
.frd-noise{position:absolute;inset:0;pointer-events:none;
  background:repeating-linear-gradient(0deg,rgba(255,255,255,.06) 0 1px,transparent 1px 3px);
  animation:frd-idle .4s steps(1,end) infinite;opacity:.5}
@keyframes frd-idle{0%,100%{opacity:.25}50%{opacity:.6}}
.frd-id{position:absolute;left:2.5vw;bottom:2.5vh;margin:0;
  font:500 .62rem/1.6 var(--mono);color:#3a3a3a;letter-spacing:.32em;text-transform:uppercase}

/* el vídeo del jumpscare ----------------------------------------------- */
.frd-clip{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;background:#000;opacity:0;visibility:hidden;z-index:2}
.frd-clip.is-armed{visibility:visible}
.frd-clip.is-fired{opacity:1}

/* estática analógica tras el grito ------------------------------------- */
.frd-static{position:absolute;inset:0;background:#000;opacity:0;z-index:3;pointer-events:none}
.frd-static.is-on{opacity:1}
.frd-canvas{position:absolute;inset:0;width:100%;height:100%;display:block;image-rendering:pixelated}

/* si el navegador bloqueó el sonido, un toque lo destapa --------------- */
.frd-tap{position:absolute;inset:0;display:grid;place-items:center;
  background:transparent;border:0;color:#fff;cursor:none;
  font:500 .8rem/1 var(--mono);letter-spacing:.32em;text-transform:uppercase;opacity:0;z-index:4}
.frd-tap.is-shown{opacity:.85;animation:frd-tap 1.6s ease-in-out infinite}
@keyframes frd-tap{0%,100%{opacity:.25}50%{opacity:.9}}

@media (max-width:720px){
  .frd-id{font-size:.55rem;letter-spacing:.24em}
  .frd-tap{font-size:.7rem;letter-spacing:.24em}
}

/* ==========================================================================
   LA ÚLTIMA SEÑAL — la tarjeta que se gira (señal 2)
   --------------------------------------------------------------------------
   La imagen por delante, con su frase debajo como cualquier otra señal. Lo que
   cambia es que la imagen es una tarjeta: al pulsarla se gira y deja ver lo que
   llevaba detrás — lo que la sala trae grabado en Morse. El audio es ese mismo
   Morse, y su transcripción se escribe letra a letra al compás de la cinta; las
   letras ya dichas quedan legibles y la que suena se enciende. Cuando la cinta
   acaba, la traducción sale a la luz: estuvo ahí desde el principio, pero no se
   leía. Con «reducir movimiento» la tarjeta no gira: cambia de cara de golpe.
   ========================================================================== */
.flip{
  --maxh:min(58vh,560px);
  position:relative;
  width:min(100%,calc(var(--maxh) * var(--rw) / var(--rh)));
  aspect-ratio:var(--rw) / var(--rh);
  perspective:1500px;
}
.flip audio{display:none}
.flip-btn{
  display:block;
  width:100%;
  height:100%;
  padding:0;
  border:0;
  background:none;
  color:inherit;
  cursor:pointer;
  touch-action:manipulation;
  -webkit-tap-highlight-color:transparent;
  text-align:left;
}
.flip-inner{
  position:relative;
  display:block;
  width:100%;
  height:100%;
  transform-style:preserve-3d;
  transition:transform .9s cubic-bezier(.36,.06,.18,1);
}
.flip.is-flipped .flip-inner{transform:rotateY(180deg)}
.flip-face{
  position:absolute;
  inset:0;
  display:block;
  overflow:hidden;
  border:1px solid var(--line);
  background:#0b0b11;
  backface-visibility:hidden;
  -webkit-backface-visibility:hidden;
}

/* la foto: la piscina, con su puerta al fondo ----------------------------- */
.flip-front{box-shadow:0 40px 90px -40px #000,0 0 0 1px rgba(0,0,0,.5) inset}
.flip-front img{
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
  user-select:none;
  -webkit-user-drag:none;
  transition:transform .6s ease,filter .45s ease;
}
/* quien se acerca a la tarjeta la enciende un poco */
.flip-btn:hover .flip-front img,
.flip-btn:focus-visible .flip-front img{filter:brightness(1.06);transform:scale(1.018)}
.flip-btn:active .flip-front img{transform:scale(.996)}
.ff-tag{
  position:absolute;
  left:0;
  bottom:0;
  z-index:2;
  padding:.5rem .7rem;
  background:rgba(6,6,8,.74);
  color:var(--accent);
  font:500 .56rem/1 var(--mono);
  letter-spacing:.26em;
  text-transform:uppercase;
}

/* la cara de atrás: el mensaje, escrito según suena ---------------------- */
.flip-back{
  display:grid;
  grid-template-rows:auto 1fr auto auto;
  gap:clamp(.5rem,1.4vh,.9rem);
  align-content:start;
  padding:clamp(.85rem,3vh,1.4rem);
  text-align:left;
  transform:rotateY(180deg);
  background:
    radial-gradient(120% 90% at 50% -12%,color-mix(in oklab,var(--accent) 18%,transparent),transparent 72%),
    #07070c;
}
.fb-top{display:flex;align-items:center;gap:.55rem}
.fb-dot{
  width:7px;
  height:7px;
  background:var(--dim);
  transition:background .3s,box-shadow .3s;
}
.flip.is-playing .fb-dot{
  background:var(--accent);
  box-shadow:0 0 12px var(--accent);
  animation:fb-rec 1.7s ease-in-out infinite;
}
@keyframes fb-rec{0%,100%{opacity:.35}50%{opacity:1}}
.fb-label{
  color:var(--dim);
  font:500 .54rem/1 var(--mono);
  letter-spacing:.24em;
  text-transform:uppercase;
}
.fb-clock{color:var(--paper);font-weight:500}

/* la transcripción: cada letra en su sitio y a su tiempo ----------------- */
.fb-rail{
  display:block;
  font:400 clamp(.6rem,1.5vw,.78rem)/2 var(--mono);
  letter-spacing:.16em;
  color:rgb(236 234 240 / .17);
}
.fm-mark{display:inline-block;transition:color .22s ease,text-shadow .22s ease}
.fm-mark.is-said{color:rgb(236 234 240 / .74)}
.fm-mark.is-now{color:var(--accent);text-shadow:0 0 12px color-mix(in oklab,var(--accent) 75%,transparent)}
.fm-gap{display:inline-block;width:.75em}

/* la traducción, que sale a la luz cuando la cinta termina ---------------- */
.fb-text{
  display:block;
  font:400 clamp(.74rem,1.9vw,.98rem)/1.6 var(--mono);
  color:var(--paper);
  opacity:.16;
  filter:blur(2.6px);
  transition:opacity .9s ease,filter .9s ease;
}
.flip.is-heard .fb-text{opacity:.96;filter:none}
.fb-foot{
  display:block;
  color:var(--dim);
  font:500 .5rem/1.4 var(--mono);
  letter-spacing:.2em;
  text-transform:uppercase;
  opacity:.7;
  transition:opacity .5s ease;
}
.flip.is-heard .fb-foot{opacity:.25}

@media (max-width:720px){
  .flip{--maxh:min(52vh,460px)}
  .fb-rail{line-height:1.85;letter-spacing:.1em}
  .fb-foot{font-size:.46rem;letter-spacing:.14em}
}
/* ==========================================================================
   LA REJILLA — casillas tapadas y casillas abiertas
   --------------------------------------------------------------------------
   Una señal sin descifrar no tiene puerta: su casilla no lleva enlace, así que
   no se puede pulsar, ni tabular hasta ella, ni copiar su dirección, ni
   abrirla en otra pestaña. Sólo dice su número y sus bloques. La casilla se
   abre escribiendo el código, y entonces se descifra ahí mismo (revealSlot):
   los bloques se asientan, el nombre toma su sitio y a partir de ese momento
   sí es una puerta, con su «Abrir →».
   ========================================================================== */
.slot.is-locked{cursor:default}
.slot.is-locked:hover{background:var(--void)}
.slot.is-locked .blk{background:#3b3b46}
.slot.is-locked .go{display:none}

/* el descifrado, a la vista */
.slot.is-decoding .blk{animation:blk-settle .43s cubic-bezier(.2,.7,.2,1) both}
@keyframes blk-settle{
  0%{transform:translateY(-3px) scaleY(.6);opacity:.35}
  70%{transform:translateY(1px) scaleY(1.06);opacity:1}
  100%{transform:none;opacity:.85}
}
.slot.is-open .k{animation:k-decode .5s cubic-bezier(.2,.7,.2,1) both;animation-delay:calc(var(--i,0) * 22ms)}
@keyframes k-decode{
  from{opacity:0;filter:blur(6px);transform:translateY(5px)}
  to{opacity:1;filter:none;transform:none}
}

/* la señal recién encontrada: se anuncia una sola vez, y luego se calla */
.slot.is-new{animation:slot-new 1.9s ease-in-out both}
@keyframes slot-new{
  0%,100%{box-shadow:0 0 0 0 transparent}
  12%{box-shadow:0 0 0 1px var(--accent),0 0 34px -6px var(--accent)}
  45%{box-shadow:0 0 0 1px color-mix(in oklab,var(--accent) 55%,transparent),0 0 22px -10px var(--accent)}
  70%{box-shadow:0 0 0 1px var(--accent),0 0 30px -8px var(--accent)}
}
.slot .nv{
  position:absolute;
  top:.75rem;
  right:.9rem;
  font:500 .52rem/1 var(--mono);
  letter-spacing:.22em;
  text-transform:uppercase;
  color:var(--accent);
}

@media (prefers-reduced-motion:reduce){
  .slot.is-decoding .blk,
  .slot.is-open .k,
  .slot.is-new{animation:none}
}

@media (prefers-reduced-motion:reduce){
  .flip{animation:none}
  .flip-inner{transition:none}
  .flip-front img{transition:none}
  .flip-btn:hover .flip-front img,
  .flip-btn:focus-visible .flip-front img,
  .flip-btn:active .flip-front img{transform:none}
  .fm-mark,.fb-dot,.fb-text,.fb-foot{transition:none}
  .flip.is-playing .fb-dot{animation:none;opacity:1}
}
