/* node 060806 · the room, and what is on the other side of it
   ---------------------------------------------------------------------------
   Two worlds in one document. The room is her locked room: dark, red-lit,
   the keyboard is the only light in it. Barzakh is the same room overexposed
   all the way through to paper, which is where you end up when a door opens
   and you still cannot leave.

   Colour discipline. The room is her ground (#131111) with one of her own
   red-lit photographs under it, held near black. Barzakh is her paper
   (#F3F4F3) falling to mist at the edges. The blue is 3.4 percent of her
   photographs and it does exactly two things here, one per view: a 6px tick
   beside the sign in the mirror, and a 6px tick on the destination you are
   currently picturing. It is never a field, never a fill, never type.

   Motion. Only transform and opacity. The darkness is a canvas, painted from
   javascript, and it stops painting the moment nothing is decaying. Under
   prefers-reduced-motion the light does not decay at all: what you reveal
   stays revealed, and the whole room is static.
*/

html, body { height: 100%; }
body { background: var(--ob-ground); overflow: hidden; }
[hidden] { display: none !important; }

.vh {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

:root {
  --fa: "Vazirmatn", "Noto Naskh Arabic", "Geeza Pro", Tahoma, sans-serif;
  /* how far below the top of the viewport the room's field of holes begins,
     and how far above the console it ends. the lattice in game.js uses the
     same two numbers. */
  --field-top: 11%;
  --field-bottom: 63%;
}

/* ---------------------------------------------------------------- the room */

#room { position: fixed; inset: 0; }

#wall {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  /* static filter, never animated */
  filter: brightness(0.62) saturate(0.72) contrast(1.04);
}

#dark { position: absolute; inset: 0; }

#threads {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  overflow: visible;
}
#threads line {
  stroke: rgba(243, 244, 243, 0.16);
  stroke-width: 1;
  stroke-dasharray: 1 5;
}

#field { position: absolute; inset: 0; }

/* an aperture: a hole you can see but have not reached.
   revealed when its pair is found. three pairs of holes like a burrow. */
.aperture {
  position: absolute;
  width: 26px; height: 16px;
  margin: -8px 0 0 -13px;
  border-radius: 50%;
  background: radial-gradient(ellipse at 50% 42%, #000 40%, rgba(0, 0, 0, 0) 100%);
  box-shadow: 0 0 0 1px rgba(243, 244, 243, 0.20), 0 0 16px rgba(0, 0, 0, 0.9);
  opacity: 0;
}
.aperture.shown { opacity: 1; transition: opacity 1.1s ease; }

/* a print: developed, and from then on it makes its own light */
.print {
  position: absolute;
  width: clamp(88px, 13vw, 152px);
  margin: 0;
  transform: translate(-50%, -50%) rotate(var(--tilt, 0deg));
  opacity: 0;
}
.print.developed { opacity: 1; transition: opacity 1.5s ease; }
.print img {
  width: 100%; height: auto;
  box-shadow: 0 0 40px rgba(243, 244, 243, 0.13);
}
.print figcaption {
  position: absolute; right: -30px; bottom: -12px;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
}
.print .digit {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 300;
  font-size: clamp(26px, 3vw, 40px);
  line-height: 1;
  color: var(--ob-paper);
  text-shadow: 0 0 20px rgba(0, 0, 0, 0.95);
}
.print .slot {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.16em;
  color: var(--ob-mid);
  text-shadow: 0 0 10px rgba(0, 0, 0, 0.95);
}
/* bleached by the burn: it goes to paper and back to the wall */
.print.bleached { opacity: 0; transition: opacity 0.9s ease; }

/* ------------------------------------------------------------- the mirror */
/* غزاله signalled with her hands from the mirror of her own world and she
   saw it in the mirror on this side. it is the room's only hint, and it is
   the only place in this view where the blue is allowed to appear. */

#mirror {
  position: absolute;
  left: 76%; top: 17%;
  width: clamp(74px, 9vw, 116px);
  margin: 0;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  outline: 1px solid rgba(243, 244, 243, 0.14);
  outline-offset: 3px;
}
#mirror img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 24%;
  filter: brightness(0.34) saturate(0.5);
}
#mirror figcaption {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center; gap: 7px;
  background: rgba(6, 5, 5, 0.72);
  opacity: 0;
}
#mirror.signing figcaption { opacity: 1; transition: opacity 0.7s ease; }
#mirror .sign {
  font-family: var(--mono);
  font-size: clamp(20px, 2.4vw, 30px);
  font-weight: 300;
  color: var(--ob-paper);
  transform: scaleX(-1);           /* you are reading it in the glass */
}
#mirror .tick { width: 6px; height: 6px; background: var(--ob-blue); }

/* ---------------------------------------------------------------- chrome */
/* fixed chrome has to stay legible over a photograph, so it carries its own
   ground. #9BA0A5 on #131111 is 7.1:1 and stays 7.1:1. */

.sector-line { left: 12px; top: 12px; padding: 18px 26px 8px 22px; }

#log {
  position: fixed; left: 12px; top: 46px;
  z-index: 70;
  max-width: min(52ch, 62vw);
  padding: 6px 26px 18px 22px;
  color: var(--ob-mid);
}
.sector-line, #log {
  background: radial-gradient(120% 200% at 18% 50%, rgba(19, 17, 17, 0.94), rgba(19, 17, 17, 0));
}

#meter {
  position: fixed; right: 22px; top: 58px;
  z-index: 70;
  display: flex; align-items: center; gap: 10px;
  padding: 12px 14px 12px 22px;
  background: radial-gradient(120% 200% at 82% 50%, rgba(19, 17, 17, 0.94), rgba(19, 17, 17, 0));
}
#meter .bar {
  display: block;
  width: 74px; height: 1px;
  background: rgba(243, 244, 243, 0.22);
  overflow: hidden;
}
#meter .bar i {
  display: block; width: 100%; height: 1px;
  background: var(--ob-paper);
  transform-origin: left;
  transform: scaleX(0);
}
#meter.hot .cap { color: var(--ob-blood); }
#meter.hot .bar i { background: var(--ob-blood); }

/* her line about the cost, in her own register, once the room has taken
   something from you */
#cost {
  position: fixed; right: 22px; bottom: 34px;
  z-index: 70;
  max-width: 34ch;
  padding: 20px 16px 20px 34px;
  text-align: right;
  font-family: var(--serif);
  font-weight: 200;
  font-size: clamp(14px, 1.35vw, 19px);
  line-height: 1.62;
  color: rgba(243, 244, 243, 0.86);
  background: radial-gradient(120% 160% at 78% 50%, rgba(19, 17, 17, 0.93), rgba(19, 17, 17, 0));
}

/* --------------------------------------------------------------- console */

#console {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 72;
  display: flex; flex-direction: column; align-items: center;
  gap: 10px;
  padding: 0 12px 16px;
  background: linear-gradient(to top, rgba(19, 17, 17, 0.96) 46%, rgba(19, 17, 17, 0));
  padding-top: 46px;
}

#door {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  align-items: center;
  gap: 2px 16px;
  padding: 12px 20px;
  border: 1px solid rgba(243, 244, 243, 0.34);
  background: rgba(5, 5, 5, 0.72);
}
#door.refused { border-color: var(--ob-blood); }
#door.open { border-color: var(--ob-paper); }
#door .rmz {
  grid-row: 1 / 3;
  font-family: var(--fa);
  font-weight: 300;
  font-size: 21px;
  line-height: 1;
  color: rgba(243, 244, 243, 0.72);
}
#held { color: var(--ob-mid); letter-spacing: 0.42em; font-size: 10.5px; }
#slots { color: var(--ob-paper); letter-spacing: 0.42em; font-size: 15px; }

#locked {
  font-family: var(--fa);
  font-weight: 300;
  font-size: clamp(12px, 1.25vw, 15px);
  line-height: 1.9;
  color: rgba(243, 244, 243, 0.56);
  text-align: center;
  max-width: 46ch;
}

/* the keys. she played with her hands and a keyboard, which meant she didn't
   know which key to press. these are real buttons: the game is the same
   whether you use them or the keyboard under your hands. */
.pad {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 3px;
  max-width: 470px;
}
.pad .row { display: flex; gap: 3px; justify-content: center; width: 100%; }
.k {
  width: clamp(24px, 7.6vw, 32px);
  height: clamp(24px, 7.6vw, 32px);
  border: 1px solid rgba(243, 244, 243, 0.16);
  background: rgba(5, 5, 5, 0.5);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 300;
  color: var(--ob-mid);
  padding: 0;
  transition: border-color 0.25s ease, color 0.25s ease;
}
.k:hover { border-color: rgba(243, 244, 243, 0.5); color: var(--ob-paper); }
.k:focus-visible { outline: 1px solid var(--ob-paper); outline-offset: 2px; }
/* a key you have already thrown light with */
.k.spent { color: rgba(155, 160, 165, 0.45); border-color: rgba(243, 244, 243, 0.07); }
.k.spent::after {
  content: ""; position: absolute;
}
.k.hit { color: var(--ob-paper); border-color: rgba(243, 244, 243, 0.55); }
.k.lit { transform: translateY(1px); }

#digits .k { width: clamp(22px, 6.4vw, 28px); height: clamp(22px, 6.4vw, 28px); }

/* --------------------------------------------------------------- barzakh */
/* the burn taken all the way. her paper, not her ground. dark type on light,
   which is the one real inversion in the whole site, because this is the one
   place in the site you are not supposed to be. */

#barzakh {
  position: fixed; inset: 0;
  z-index: 88;
  overflow-y: auto;
  overscroll-behavior: contain;
  background:
    radial-gradient(ellipse 90% 70% at 50% 26%, var(--ob-paper), var(--ob-mist) 78%, var(--ob-mid) 118%);
  color: var(--ob-ground);
}
.bz-inner {
  max-width: 760px;
  margin: 0 auto;
  padding: clamp(46px, 9vh, 110px) 22px clamp(60px, 12vh, 140px);
  text-align: center;
}
#barzakh .b-log { color: var(--ob-clay); }          /* 7.5:1 on paper */
#barzakh .fa {
  margin-top: 26px;
  font-family: var(--fa);
  font-weight: 300;
  font-size: clamp(14px, 1.6vw, 19px);
  line-height: 2.1;
  color: var(--ob-deep);
}
#barzakh .fa.long { max-width: 46ch; margin-left: auto; margin-right: auto; }
#kept {
  margin: clamp(30px, 5vh, 54px) auto;
  width: min(240px, 56vw);
}
#kept img { width: 100%; height: auto; }
#barzakh .her {
  margin: clamp(26px, 4vh, 44px) auto 0;
  max-width: 26ch;
  font-family: var(--serif);
  font-weight: 200;
  font-size: clamp(22px, 3.2vw, 38px);
  line-height: 1.42;
  color: var(--ob-ground);
  text-wrap: balance;
}
#barzakh .her.lose {
  margin-top: clamp(36px, 6vh, 62px);
  font-size: clamp(14px, 1.5vw, 18px);
  font-style: italic;
  color: var(--ob-clay);
}

/* the destinations. location and time, which is what she said you need. */
#dests {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  gap: clamp(14px, 2.4vw, 30px);
  margin-top: clamp(22px, 3.5vh, 38px);
  text-align: left;
}
.dest {
  --p: 0;
  display: block;
  position: relative;
  padding-bottom: 14px;
  color: var(--ob-ground);
  -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none;
  touch-action: manipulation;
}
.dest .plate { overflow: hidden; background: var(--ob-mid); }
.dest img {
  width: 100%; height: auto;
  opacity: calc(0.4 + var(--p) * 0.6);
  transform: scale(calc(1 + var(--p) * 0.05));
  transform-origin: 50% 50%;
}
.dest .addr, .dest .when {
  display: block;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: lowercase;
}
.dest .addr { margin-top: 10px; color: var(--ob-deep); }
.dest .when { margin-top: 3px; color: var(--ob-clay); }
.dest .rule {
  position: absolute; left: 0; right: 0; bottom: 6px;
  height: 1px;
  background: rgba(48, 43, 46, 0.22);
  overflow: hidden;
}
.dest .rule i {
  display: block; height: 1px; width: 100%;
  background: var(--ob-deep);
  transform-origin: left;
  transform: scaleX(var(--p));
}
/* the one live mark in this view */
.dest .tick {
  position: absolute; right: 0; top: 0;
  width: 6px; height: 6px;
  background: var(--ob-blue);
  opacity: 0;
}
.dest.pictured .tick { opacity: 1; }
.dest:focus-visible { outline: 1px solid var(--ob-ground); outline-offset: 6px; }
.dest:hover .addr { color: var(--ob-ground); }

/* the room is gone once you are through. no tabbing back into it. */
body.through #room,
body.through #console,
body.through #meter,
body.through #log,
body.through #cost,
body.through .sector-line { display: none; }
body.through { overflow: auto; }

/* ------------------------------------------------------------ small rooms */

@media (max-width: 620px) {
  #mirror { left: 70%; top: 13%; }
  #log { max-width: 66vw; font-size: 10.5px; }
  #meter { top: 52px; right: 12px; }
  #meter .bar { width: 52px; }
  #cost { font-size: 13px; bottom: auto; top: 108px; max-width: 24ch; }
  .print { width: clamp(74px, 22vw, 110px); }
  #locked { font-size: 11.5px; line-height: 1.8; }
  :root { --field-bottom: 56%; }
}
@media (max-height: 620px) {
  #kept { width: min(180px, 40vw); }
  #cost { display: none; }
}

/* ---------------------------------------------------------- reduced motion */
/* the site's spine already flattens durations to nothing under this query.
   what matters here is that the room stops decaying: light you throw stays
   thrown, the mirror does not flicker, and nothing loops. game.js reads the
   same query and changes the rules to match. */

@media (prefers-reduced-motion: reduce) {
  .aperture.shown, .print.developed, #mirror.signing figcaption { transition: none; }
  .dest img { transform: none; opacity: 1; }
  .dest .rule { display: none; }
}
