/* The Map of Us: interface over the canvas. */
:root {
  --ink: #0d0b17;
  --cream: #fbf1e7;
  --cream-dim: rgba(251, 241, 231, 0.72);
  --rose: #f5a9b8;
  --rose-deep: #e07f98;
  --scrim: rgba(16, 13, 34, 0.42);
  --hand: "Caveat", "Bradley Hand", "Segoe Print", cursive;
  --serif: "Fraunces", "Iowan Old Style", Georgia, serif;
  --sans: "DM Sans", -apple-system, "Helvetica Neue", Arial, sans-serif;
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --edge: 20px;
}

* { box-sizing: border-box; }

[hidden] { display: none !important; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--ink);
  overflow: hidden;
  overscroll-behavior: none;
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}

body {
  color: var(--cream);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
}

#app {
  position: fixed;
  inset: 0;
  height: 100dvh;
  overflow: hidden;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

#gl {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  touch-action: none;
  -webkit-touch-callout: none;
  outline: none;
}

#ui {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

#ui button, #ui .interactive { pointer-events: auto; }

.layer {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

/* ---------- type ---------- */

.hand {
  font-family: var(--hand);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: 0.005em;
  color: var(--cream);
  text-shadow: 0 1px 2px rgba(10, 8, 24, 0.55), 0 0 22px rgba(10, 8, 24, 0.55);
}

.serif {
  font-family: var(--serif);
  font-weight: 380;
  font-variation-settings: "opsz" 40, "SOFT" 100;
  line-height: 1.18;
  letter-spacing: -0.005em;
}

.ui-text {
  font-family: var(--sans);
  font-weight: 450;
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: lowercase;
}

/* ---------- masked line reveal ---------- */

.rl {
  display: block;
  overflow: hidden;
  /* room for Caveat's descenders and ascenders inside the mask */
  padding: 0.08em 0.12em 0.2em;
  margin: -0.08em -0.12em -0.2em;
}

.rl > .rl-in {
  display: inline-block;
  will-change: transform;
}

/* ---------- invitation ---------- */

#invite {
  background: radial-gradient(120% 80% at 50% 45%, #171428 0%, #0d0b17 62%, #08070f 100%);
  padding: calc(var(--safe-t) + 48px) calc(var(--safe-r) + 32px) calc(var(--safe-b) + 48px) calc(var(--safe-l) + 32px);
  pointer-events: auto;
  cursor: pointer;
  z-index: 20;
  transition: opacity 1.4s ease;
}

#invite.gone { opacity: 0; pointer-events: none; }

#invite-line {
  margin: 0;
  max-width: 15.5em;
  text-align: center;
  font-size: clamp(30px, 8.4vw, 46px);
  color: #f7ece2;
  text-shadow: none;
}

#invite-tap {
  margin-top: 56px;
  min-height: 48px;
  padding: 14px 26px;
  color: var(--cream-dim);
  background: none;
  border: 0;
  font-size: 14px;
  cursor: pointer;
}

#invite-tap::after {
  content: "";
  display: block;
  width: 6px;
  height: 6px;
  margin: 14px auto 0;
  border-radius: 50%;
  background: var(--rose);
  box-shadow: 0 0 12px 3px rgba(245, 169, 184, 0.55);
  animation: breathe 2.8s ease-in-out infinite;
}

#invite-wait {
  position: absolute;
  bottom: calc(var(--safe-b) + 64px);
  left: 50%;
  width: 6px;
  height: 6px;
  margin-left: -3px;
  border-radius: 50%;
  background: rgba(245, 169, 184, 0.6);
  animation: breathe 1.6s ease-in-out infinite;
}

#invite-wait.done { display: none; }

@keyframes breathe {
  0%, 100% { opacity: 0.35; transform: scale(0.85); }
  50% { opacity: 1; transform: scale(1.1); }
}

/* ---------- lines over the street ---------- */

.hint {
  position: absolute;
  left: 0;
  right: 0;
  margin: 0 auto;
  padding: 0 calc(var(--edge) + var(--safe-l));
  max-width: 22em;
  text-align: center;
  font-size: clamp(28px, 7.4vw, 38px);
  bottom: calc(var(--safe-b) + 21dvh);
}

.ui-hint {
  position: absolute;
  left: 0;
  right: 0;
  margin: 0 auto;
  text-align: center;
  bottom: calc(var(--safe-b) + 124px); /* clear of the keepsake album */
  padding: 0 var(--edge);
  color: var(--cream);
  font-size: 13px;
  text-shadow: 0 1px 3px rgba(10, 8, 24, 0.9);
}

.voice {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--safe-t) + 7dvh);
  margin: 0 auto;
  max-width: 17em;
  padding: 0 var(--edge);
  text-align: center;
  font-size: clamp(25px, 6.6vw, 34px);
}

.voice .voice-mark {
  display: block;
  margin: 0 auto 10px;
  width: 30px;
  height: 14px;
}

.caption {
  position: absolute;
  left: 0;
  right: 0;
  margin: 0 auto;
  max-width: 16em;
  padding: 0 var(--edge);
  text-align: center;
  font-size: clamp(27px, 7vw, 36px);
  bottom: calc(var(--safe-b) + 12dvh);
}

/* a soft dark backing behind every line that sits on the scene, strong enough
   that the text keeps at least 4.5:1 against whatever is behind it */
.hint::before, .voice::before, .caption::before, .ui-hint::before {
  content: "";
  position: absolute;
  z-index: -1;
  left: 50%;
  top: 50%;
  width: var(--back-w, 100%);
  height: var(--back-h, 100%);
  transform: translate(-50%, -50%);
  border-radius: 999px;
  background: rgba(15, 11, 30, var(--back-a, 0.78));
  filter: blur(var(--back-blur, 14px));
  opacity: var(--scrim-o, 0);
  transition: opacity 0.9s ease;
}

/* each line is its own stacking context, so its backing sits behind its text, not behind the canvas */
.hint, .voice, .caption, .ui-hint { z-index: 1; }
.hint { --back-w: min(var(--line-w, 6em), 92%); --back-h: 1.45em; --back-blur: 10px; }
.voice, .caption { --back-w: 104%; --back-h: calc(100% + 0.9em); }
/* a frame's caption sits over the bright film: balanced lines (no orphan word), and a
   deeper plum-black plate that hugs the text (visit.js sets --back-w / --back-h from the
   laid-out lines), so the film dims only behind the words */
.caption {
  text-wrap: balance;
  --back-a: 0.9;
  --back-blur: 16px;
  --back-w: calc(104% + 1em);
  --back-h: calc(100% + 1.3em);
}
@supports not (text-wrap: balance) {
  .caption { max-width: 11.5em; }
}
.caption::before { border-radius: 2.4em; }
.ui-hint.top { bottom: auto; top: calc(var(--safe-t) + 74px); }
.ui-hint { --back-w: min(29em, 100%); --back-h: 4.2em; --back-blur: 7px; --back-a: 0.92; }

.has-text { --scrim-o: 1; }

/* ---------- the question, on the booth's ivory card ---------- */

.question {
  position: absolute;
  left: 50%;
  bottom: calc(var(--safe-b) + 96px);
  width: min(calc(100% - 40px), 420px);
  padding: 26px 22px 20px;
  text-align: center;
  pointer-events: auto;
  color: #2c2640;
  background:
    radial-gradient(120% 90% at 30% 10%, rgba(255, 255, 250, 0.7), rgba(255, 255, 250, 0) 60%),
    linear-gradient(170deg, #f6efe1, #ebe1cd);
  border-radius: 4px;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.6),
    0 0 0 3px #efe6d4,
    0 0 0 4.5px #b08442,
    0 24px 60px rgba(6, 4, 16, 0.55),
    0 4px 12px rgba(6, 4, 16, 0.35);
  opacity: 0;
  transform: translate(-50%, 18px);
  transition: opacity 0.9s ease, transform 1.1s cubic-bezier(.16,.84,.24,1);
}

.question.on { opacity: 1; transform: translate(-50%, 0); }

#question-text {
  margin: 0 0 18px;
  font-size: clamp(23px, 6vw, 29px);
  color: #2c2640;
  text-shadow: none;
}

#answers {
  display: flex;
  flex-direction: column;
  gap: 9px;
  align-items: stretch;
}

.answer {
  position: relative;
  min-height: 50px;
  padding: 12px 18px;
  border-radius: 25px;
  border: 1px solid rgba(44, 38, 64, 0.32);
  background: rgba(255, 252, 244, 0.55);
  color: #2c2640;
  font-family: var(--sans);
  font-size: 17px;
  font-weight: 450;
  letter-spacing: 0.01em;
  cursor: pointer;
  overflow: hidden;
  transition: background 0.6s ease, border-color 0.6s ease, opacity 0.8s ease, transform 0.8s cubic-bezier(.2,.7,.1,1);
}

.answer .rl { padding-top: 0; padding-bottom: 0.06em; margin-top: 0; margin-bottom: -0.06em; }

.answer.chosen {
  background: rgba(214, 120, 146, 0.22);
  border-color: rgba(176, 70, 104, 0.7);
}

.answer.faded { opacity: 0; transform: translateY(6px); pointer-events: none; }

#reply {
  margin: 14px 0 0;
  font-size: clamp(25px, 6.6vw, 31px);
  min-height: 1.2em;
  color: #6a2f4c;
  text-shadow: none;
}

/* the flash is light, not paint: added to the scene (screen blend), so the camera
   wall still shows through it. A brief white veil over everything, and a hot
   bloom centred on the glass that lasts a little longer. */
#flash {
  position: absolute;
  inset: 0;
  pointer-events: none;
  mix-blend-mode: screen;
}

#flash::before, #flash::after {
  content: "";
  position: absolute;
  inset: 0;
}

#flash::before {
  background: rgb(255, 251, 244);
  opacity: var(--veil, 0);
}

#flash::after {
  opacity: var(--core, 0);
  background:
    radial-gradient(circle at var(--fx, 50%) var(--fy, 45%),
      rgba(255, 254, 250, 1) 0%,
      rgba(255, 250, 240, 0.85) 5%,
      rgba(255, 240, 222, 0.4) 15%,
      rgba(255, 230, 205, 0.13) 34%,
      rgba(255, 224, 196, 0.03) 60%,
      rgba(255, 224, 196, 0) 80%);
}

/* ---------- keepsakes ---------- */

#keepsakes {
  position: absolute;
  left: 50%;
  bottom: calc(var(--safe-b) + 10px);
  transform: translateX(-50%);
  display: flex;
  gap: 10px;
  align-items: flex-end;
  height: 90px;
  padding: 0 4px;
}

.keepsake {
  width: 22px;
  height: auto;
  display: block;
  border-radius: 2px;
  box-shadow: 0 6px 14px rgba(8, 6, 20, 0.45), 0 1px 2px rgba(8, 6, 20, 0.5);
  transform-origin: 50% 0;
}

.keepsake.waiting { visibility: hidden; }

#keepsakes { transition: opacity 1.4s ease; }
#keepsakes.away { opacity: 0; pointer-events: none; }

.keepsake-fly {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 30;
  pointer-events: none;
  transform-origin: 0 0;
  box-shadow: 0 18px 40px rgba(8, 6, 20, 0.45);
  border-radius: 2px;
}

.walk-on {
  position: absolute;
  left: 50%;
  bottom: calc(var(--safe-b) + 96px);
  transform: translateX(-50%);
  min-height: 48px;
  padding: 14px 28px;
  border: 1px solid rgba(251, 241, 231, 0.42);
  border-radius: 24px;
  background: rgba(22, 18, 44, 0.42);
  color: var(--cream);
  font-size: 14px;
  cursor: pointer;
  overflow: hidden;
}

.walk-on[hidden] { display: none; }

/* ---------- sound chip ---------- */

.chip {
  position: absolute;
  top: calc(var(--safe-t) + 14px);
  right: calc(var(--safe-r) + 14px);
  min-height: 44px;
  min-width: 44px;
  padding: 12px 14px;
  border: 0;
  border-radius: 22px;
  background: rgba(15, 11, 30, 0.72);
  -webkit-backdrop-filter: blur(8px) brightness(0.75);
  backdrop-filter: blur(8px) brightness(0.75);
  color: var(--cream);
  font-size: 12px;
  cursor: pointer;
  text-shadow: none;
  opacity: 0;
  transition: opacity 1.2s ease, color 0.4s ease;
}

.chip.on { opacity: 1; }
.chip[aria-pressed="false"] { color: rgba(251, 241, 231, 0.82); }

#resume {
  background: rgba(10, 8, 22, 0.55);
  pointer-events: auto;
  z-index: 25;
}

/* ---------- debug door ---------- */

#debug {
  position: absolute;
  left: calc(var(--safe-l) + 6px);
  top: calc(var(--safe-t) + 6px);
  z-index: 50;
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  max-width: 260px;
  pointer-events: auto;
  font: 10px/1 ui-monospace, Menlo, monospace;
  opacity: 0.5;
}

#debug:hover { opacity: 1; }

#debug button {
  font: inherit;
  padding: 4px 5px;
  border: 0;
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.55);
  color: #e7e2ff;
  cursor: pointer;
}

#debug .stat {
  width: 100%;
  color: #e7e2ff;
  background: rgba(0, 0, 0, 0.45);
  padding: 3px 5px;
  white-space: pre;
}

html.shots #debug { display: none; }

@media (min-width: 900px) {
  /* on a wide screen the print sits right of centre: keep the hint clear of the slot */
  .ui-hint.top { right: auto; left: calc(var(--safe-l) + 48px); margin: 0; }
  .hint { bottom: calc(var(--safe-b) + 18dvh); }
  .caption { bottom: calc(var(--safe-b) + 7dvh); }
  .voice { top: calc(var(--safe-t) + 3.5dvh); }
  .keepsake { width: 26px; }
  #keepsakes { height: 104px; }
}

@media (prefers-reduced-motion: reduce) {
  #invite-tap::after, #invite-wait { animation: none; }
}

/* ---------- the title card of a chapter, hanging in the air ahead ---------- */

#title-card {
  position: absolute;
  left: 0;
  top: 0;
  width: min(86vw, 22em);
  text-align: center;
  pointer-events: none;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.6s ease;
  will-change: transform;
}
#title-card.on { opacity: 1; }
#title-card p { margin: 0; position: relative; }
#title-card .tc-count {
  font-size: clamp(40px, 11vw, 58px);
  letter-spacing: 0.02em;
  color: #fbf1e7;
}
#title-card .tc-line {
  margin-top: 0.15em;
  font-size: clamp(26px, 6.8vw, 34px);
  color: #f6e6dc;
}
/* the same soft dark backing the street's lines have, hugging each line */
#title-card .tc-count::before, #title-card .tc-line::before {
  content: "";
  position: absolute;
  z-index: -1;
  left: 50%;
  top: 50%;
  width: calc(100% + 1em);
  height: calc(100% + 0.5em);
  transform: translate(-50%, -50%);
  border-radius: 999px;
  background: rgba(15, 11, 30, 0.62);
  filter: blur(16px);
  opacity: 0;
  transition: opacity 0.9s ease;
}
#title-card .has-text::before { opacity: 1; }

/* a zone's small word: a month going by, low and small, in the owner's hand */
#zone-word {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(var(--safe-b) + 31dvh);
  margin: 0 auto;
  max-width: 12em;
  text-align: center;
  font-size: clamp(24px, 6.2vw, 30px);
  color: #f6ebe2;
  z-index: 1;
}
#zone-word::before {
  content: "";
  position: absolute;
  z-index: -1;
  left: 50%;
  top: 50%;
  width: 5.5em;
  height: 1.5em;
  transform: translate(-50%, -50%);
  border-radius: 999px;
  background: rgba(15, 11, 30, 0.6);
  filter: blur(12px);
  opacity: 0;
  transition: opacity 0.7s ease;
}
#zone-word.has-text::before { opacity: 1; }

/* ---------- afterwards: "the town" chip, and the pins on the town from above ---------- */

/* the mirror of the sound chip: top-left, same style and size, clear of the notch */
.chip-town {
  right: auto;
  left: calc(var(--safe-l) + 14px);
}
#ui .chip-town:not(.on) { pointer-events: none; }

#veil {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  z-index: 5;
  background: radial-gradient(ellipse at 50% 45%, rgb(255, 250, 240) 0%, rgb(255, 236, 214) 55%, rgb(246, 214, 196) 100%);
}

#pins {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
}

/* a pin: a 48 px target round a rose dot; its label is placed beside it by pins.js */
.pin {
  position: absolute;
  left: 0;
  top: 0;
  width: 48px;
  height: 48px;
  margin: -24px 0 0 -24px;
  padding: 0;
  border: 0;
  background: none;
  overflow: visible;
  cursor: pointer;
  color: var(--cream);
  opacity: 0;
  transition: opacity 1.1s ease;
  transition-delay: calc(var(--i, 0) * 0.3s);
  will-change: transform;
}
#pins.on .pin { opacity: 1; }
#pins.leaving .pin { opacity: 0; transition: opacity 0.5s ease; transition-delay: 0s; pointer-events: none; }

.pin-dot {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 14px;
  height: 14px;
  margin: -7px 0 0 -7px;
  border-radius: 50%;
  background: #ee7f9d;
  box-shadow: 0 0 0 2px rgba(255, 242, 246, 0.85), 0 0 12px 3px rgba(245, 150, 176, 0.9);
}

/* the halo breathes, slowly, each pin on its own beat */
.pin-halo {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 40px;
  height: 40px;
  margin: -20px 0 0 -20px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(245, 169, 184, 0.62) 0%, rgba(245, 169, 184, 0.28) 38%, rgba(245, 169, 184, 0) 70%);
  opacity: 0.8;
  animation: pin-breathe 5.2s ease-in-out infinite;
  animation-delay: calc(var(--i, 0) * -1.3s);
}
@keyframes pin-breathe {
  0%, 100% { transform: scale(0.8); opacity: 0.55; }
  50% { transform: scale(1.25); opacity: 1; }
}

.pin-label {
  position: absolute;
  left: 24px;
  top: 24px;
  white-space: nowrap;
  font-size: 26px;
  text-transform: lowercase;
  isolation: isolate;
  pointer-events: none;
}
.pin-label::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -0.08em -0.45em;
  border-radius: 999px;
  background: rgba(15, 11, 30, 0.46);
  filter: blur(10px);
}

/* "walk it again", small, near the top of the town from above */
#wayback-line {
  position: absolute;
  left: 50%;
  top: calc(var(--safe-t) + 22px);
  transform: translateX(-50%);
  margin: 0;
  max-width: 11em;
  text-align: center;
  font-size: clamp(26px, 6.6vw, 32px);
  color: #f6ebe2;
  z-index: 2;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .pin-halo { animation: none; opacity: 0.8; transform: none; }
  .pin { transition-delay: 0s; }
}
