:root {
  --door-size: min(94vw, 94vh);
  --steel-1: #b8bec6;
  --steel-2: #7d858f;
  --steel-3: #4a5059;
  --steel-4: #2a2e34;
  --ok: #2bff88;
  --bad: #ff3b3b;
  --amber: #ffb547;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  height: 100%;
  overflow: hidden;
  background: radial-gradient(circle at 50% 40%, #2b2f36 0%, #111317 70%);
  font-family: "Courier New", ui-monospace, monospace;
  /* Stop double-tap zoom, text selection and long-press menus on touch devices */
  touch-action: manipulation;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}

.scene {
  height: 100%;
  display: grid;
  place-items: center;
  perspective: 1800px;
}

.vault {
  position: relative;
  width: var(--door-size);
  height: var(--door-size);
  border-radius: 50%;
  /* Frame set into the wall */
  box-shadow:
    0 0 0 calc(var(--door-size) * 0.018) #3a3f47,
    0 0 0 calc(var(--door-size) * 0.03) #1b1e22,
    0 30px 80px rgba(0,0,0,.8);
  transform-style: preserve-3d;
}

/* ---------- Interior & speaker ---------- */
.interior {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  overflow: hidden;
  background: radial-gradient(circle at 50% 50%, #3a2a12 0%, #1a1208 55%, #050403 100%);
  box-shadow: inset 0 0 calc(var(--door-size) * 0.12) #000;
  display: grid;
  place-items: center;
}

.speaker {
  position: relative;
  width: 38%;
  aspect-ratio: 3 / 5;
  opacity: 0;
  transform: scale(.7);
  transition: opacity 1s ease 1.2s, transform 1s cubic-bezier(.2,1.4,.4,1) 1.2s;
}
.open .speaker { opacity: 1; transform: scale(1); }

.speaker-box {
  position: absolute;
  inset: 0;
  border-radius: 8%;
  background: linear-gradient(145deg, #3b3b3f, #151517);
  box-shadow: 0 20px 50px rgba(0,0,0,.8), inset 0 2px 2px rgba(255,255,255,.15);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-evenly;
  padding: 8%;
  z-index: 1;
}

.tweeter, .woofer {
  border-radius: 50%;
  background: radial-gradient(circle, #222 0%, #050505 70%, #555 72%, #222 80%);
  display: grid;
  place-items: center;
}
.tweeter { width: 38%; aspect-ratio: 1; }
.woofer  { width: 88%; aspect-ratio: 1; }

.cone {
  width: 78%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, #444 0%, #1a1a1a 45%, #0b0b0b 70%, #333 100%);
  display: grid;
  place-items: center;
  transform: scale(calc(1 + var(--beat, 0) * 0.08));
}
.dust-cap {
  width: 32%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #777, #111 70%);
}

/* Fallback pulse if the audio analyser isn't available */
.playing:not(.analysed) .cone { animation: thump .48s ease-in-out infinite; }
@keyframes thump {
  0%, 100% { transform: scale(1); }
  30% { transform: scale(1.07); }
}

.waves {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
}
.waves span {
  position: absolute;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 50%;
  border: 3px solid rgba(255, 181, 71, .6);
  opacity: 0;
}
.playing .waves span { animation: wave 2.4s ease-out infinite; }
.playing .waves span:nth-child(2) { animation-delay: .8s; }
.playing .waves span:nth-child(3) { animation-delay: 1.6s; }
@keyframes wave {
  0%   { transform: scale(.6); opacity: .9; }
  100% { transform: scale(2.4); opacity: 0; }
}

/* ---------- Door ---------- */
.door {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  transform-origin: 0% 50%;
  transform-style: preserve-3d;
  transition: transform 2.2s cubic-bezier(.55,.05,.3,1);
  z-index: 2;
}
.open .door { transform: rotateY(-110deg); }

.door-face {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 50%, transparent 0 44%, rgba(0,0,0,.35) 44.5%, transparent 45.5%),
    radial-gradient(circle at 50% 50%, transparent 0 30%, rgba(255,255,255,.08) 30.3%, transparent 31%),
    conic-gradient(from 200deg, var(--steel-2), var(--steel-1), var(--steel-2), var(--steel-3), var(--steel-2), var(--steel-1), var(--steel-2));
  box-shadow:
    inset 0 0 0 calc(var(--door-size) * 0.035) var(--steel-3),
    inset 0 0 0 calc(var(--door-size) * 0.045) var(--steel-4),
    inset 0 0 calc(var(--door-size) * 0.1) rgba(0,0,0,.6);
  transform: translateZ(1px);
  backface-visibility: hidden;
}

/* Thickness seen as the door swings */
.door-edge {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: linear-gradient(90deg, var(--steel-4), var(--steel-3));
  transform: translateZ(calc(var(--door-size) * -0.06));
}

/* Ring of rivets */
.bolts {
  position: absolute;
  inset: 5.5%;
  border-radius: 50%;
}
.bolts::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: repeating-conic-gradient(#d9dee4 0 2deg, transparent 2deg 15deg);
  -webkit-mask: radial-gradient(circle, transparent 0 93%, #000 93.5% 98%, transparent 98.5%);
          mask: radial-gradient(circle, transparent 0 93%, #000 93.5% 98%, transparent 98.5%);
  filter: drop-shadow(0 1px 1px #000);
}

/* ---------- Handle wheel ---------- */
.handle {
  position: absolute;
  left: 50%;
  top: 23%;
  width: 28%;
  aspect-ratio: 1;
  translate: -50% -50%;
  transition: rotate 1.6s cubic-bezier(.6,0,.3,1);
}
.unlocking .handle, .open .handle { rotate: 270deg; }

.spoke {
  position: absolute;
  left: 50%;
  top: 0;
  width: 9%;
  height: 100%;
  translate: -50% 0;
  border-radius: 999px;
  background: linear-gradient(90deg, #6a717a, #e3e7ec 45%, #8a919a);
  box-shadow: 0 4px 8px rgba(0,0,0,.6);
}
.spoke:nth-child(2) { rotate: 60deg; }
.spoke:nth-child(3) { rotate: -60deg; }
.spoke::before, .spoke::after {
  content: "";
  position: absolute;
  left: 50%;
  width: 190%;
  aspect-ratio: 1;
  translate: -50% 0;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 35%, #f2f4f6, #7a818a 70%);
  box-shadow: 0 2px 4px rgba(0,0,0,.6);
}
.spoke::before { top: -6%; }
.spoke::after  { bottom: -6%; }

.hub {
  position: absolute;
  inset: 34%;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #f5f7f9, #8b929b 55%, #4a5059);
  box-shadow: 0 6px 14px rgba(0,0,0,.7), inset 0 -3px 6px rgba(0,0,0,.4);
}

/* ---------- Keypad ---------- */
.keypad {
  position: absolute;
  left: 50%;
  top: 67%;
  width: 36%;
  translate: -50% -50%;
  padding: 4%;
  border-radius: 6%;
  background: linear-gradient(160deg, #2e3238, #15171a);
  box-shadow:
    0 8px 20px rgba(0,0,0,.7),
    inset 0 1px 1px rgba(255,255,255,.12),
    0 0 0 calc(var(--door-size) * 0.006) #5b626b;
  transition: box-shadow .15s;
}

.display {
  display: flex;
  justify-content: center;
  gap: 5%;
  padding: 3% 4%;
  margin-bottom: 5%;
  border-radius: 6px;
  background: #0b1a10;
  box-shadow: inset 0 2px 6px #000;
  transition: background .15s;
}
.digit {
  width: 14%;
  aspect-ratio: 1;
  border-bottom: 2px solid rgba(43,255,136,.35);
  display: grid;
  place-items: center;
  color: var(--ok);
  font-size: calc(var(--door-size) * 0.04);
  font-weight: bold;
  text-shadow: 0 0 8px var(--ok);
}

.keys {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: calc(var(--door-size) * 0.012);
}
.keys button {
  aspect-ratio: 1.75;
  border: none;
  border-radius: 18%;
  font: inherit;
  font-weight: bold;
  font-size: calc(var(--door-size) * 0.034);
  color: #e9edf1;
  background: linear-gradient(180deg, #5b626b, #353a41);
  box-shadow: 0 4px 0 #1b1e22, 0 6px 8px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.2);
  cursor: pointer;
  touch-action: manipulation;
  transition: transform .06s, box-shadow .06s;
}
.keys button.fn { color: var(--amber); font-size: calc(var(--door-size) * 0.028); }
.keys button:active, .keys button.pressed {
  transform: translateY(3px);
  box-shadow: 0 1px 0 #1b1e22, 0 2px 4px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.2);
}
.locked .keys button { pointer-events: none; }

/* Feedback flashes */
.keypad.wrong   { animation: flash-bad .25s 3, shake .45s; }
.keypad.correct { animation: flash-ok .3s 3; }
.keypad.wrong .display   { background: #3a0808; }
.keypad.wrong .digit     { color: var(--bad); text-shadow: 0 0 10px var(--bad); border-color: var(--bad); }
.keypad.correct .display { background: #0c3a1e; }

@keyframes flash-bad {
  50% { box-shadow: 0 0 40px 12px var(--bad), 0 0 0 calc(var(--door-size) * 0.006) var(--bad); }
}
@keyframes flash-ok {
  50% { box-shadow: 0 0 40px 12px var(--ok), 0 0 0 calc(var(--door-size) * 0.006) var(--ok); }
}
@keyframes shake {
  20%, 60% { translate: calc(-50% - 8px) -50%; }
  40%, 80% { translate: calc(-50% + 8px) -50%; }
}

/* ---------- Hinges ---------- */
.hinge {
  position: absolute;
  left: -2.5%;
  width: 6%;
  height: 12%;
  border-radius: 8px;
  background: linear-gradient(90deg, #3a3f47, #9aa1aa, #3a3f47);
  box-shadow: 0 4px 10px rgba(0,0,0,.7);
  z-index: 3;
}
.hinge.top { top: 22%; }
.hinge.bottom { bottom: 22%; }
