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

:root {
  --edge: 20px;
  --shadow-text: 0 1px 6px rgba(0, 0, 0, 0.5);
}

html, body { margin: 0; padding: 0; height: 100%; }

/* Background lives on <html> only. A background on <body> would paint over
   .hero-bg, which sits at a negative z-index. */
html { background: #0b0b0b; }

body {
  font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  color: #fff;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}

/* ---------- background ---------- */

.hero-bg {
  position: fixed;
  inset: 0;
  z-index: -10;
  overflow: hidden;
}

/* One still, overscaled so the drift never exposes an edge. The two
   animations use separate CSS properties, so they compose instead of
   overwriting each other, and their durations are deliberately not multiples
   of one another — the combined pattern takes minutes to repeat and never
   reads as a metronome. */
.bg-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  scale: 1.06;
  animation: drift 41s ease-in-out infinite alternate,
             sway 29s ease-in-out infinite alternate;
  will-change: translate, rotate;
}

@keyframes drift {
  from { translate: -0.8% 0.5%; }
  to   { translate: 0.8% -0.5%; }
}

@keyframes sway {
  from { rotate: -0.12deg; }
  to   { rotate: 0.12deg; }
}

/* Top and bottom only, to keep the fixed UI readable. The middle stays clear
   so the artwork reads on its own. */
.scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to bottom,
    rgba(0,0,0,0.38) 0%,
    rgba(0,0,0,0) 26%,
    rgba(0,0,0,0) 58%,
    rgba(0,0,0,0.55) 100%);
}

/* ---------- film grain ---------- */

/* Above the artwork at -10, below the UI. Overlay blending lifts the flat
   painting without washing out the whites in the player. */
.grain {
  position: fixed;
  inset: 0;
  z-index: -5;
  pointer-events: none;
  opacity: 0.4;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}

/* ---------- top bar ---------- */

/* Name and status sit in the corner like a shop sign, so nothing is ever
   parked over the face the scene is about. */
.brand {
  position: fixed;
  top: calc(var(--edge) + env(safe-area-inset-top));
  left: var(--edge);
  z-index: 20;
}

/* The wordmark carries the page the way "Deluxe Saloon" carries saloon.wtf:
   large, heavy and in the corner. Mukta is used rather than the serif because
   Devanagari needs real weight to hold at this size against the artwork. */
.brand-name {
  margin: 0;
  font-family: "Rozha One", Mukta, serif;
  font-weight: 400;
  font-size: 46px;
  line-height: 1.05;
  letter-spacing: 0;
  filter: drop-shadow(0 2px 10px rgba(0,0,0,0.6));
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 7px;
  padding: 4px 10px;
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: 999px;
  background: rgba(255,255,255,0.07);
  backdrop-filter: blur(10px) saturate(140%);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  font-family: Mukta, Inter, sans-serif;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: rgba(255,255,255,0.9);
  font-variant-numeric: tabular-nums;
}

.badge-dot {
  width: 5px;
  height: 5px;
  border-radius: 999px;
  background: #fff;
  animation: ping 2.6s ease-in-out infinite;
}

@keyframes ping {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.3; }
}

.links {
  position: fixed;
  top: calc(var(--edge) + env(safe-area-inset-top));
  right: var(--edge);
  z-index: 20;
  display: flex;
  gap: 8px;
  filter: drop-shadow(var(--shadow-text));
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: 999px;
  color: #fff;
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  transition: opacity 0.2s ease, transform 0.1s ease;
}

.pill:hover { opacity: 0.8; }
.pill:active { transform: scale(0.95); }
.pill-arrow { display: inline-flex; rotate: -45deg; opacity: 0.5; transition: opacity 0.2s ease; }
.pill:hover .pill-arrow { opacity: 0.9; }

/* ---------- player ---------- */

.player {
  position: fixed;
  left: 50%;
  bottom: calc(var(--edge) + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 16px;
  width: min(640px, calc(100vw - var(--edge) * 2));
  padding: 12px 16px;
  border-radius: 999px;
  background: rgba(28, 24, 22, 0.44);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
}

.disc {
  position: relative;
  flex: 0 0 auto;
  width: 68px;
  height: 68px;
  border-radius: 999px;
  overflow: hidden;
  box-shadow: 0 4px 16px rgba(0,0,0,0.45), inset 0 0 0 1px rgba(255,255,255,0.14);
  animation: spin 7s linear infinite;
  animation-play-state: paused;
}

.player.is-playing .disc { animation-play-state: running; }

.disc img { display: block; width: 100%; height: 100%; object-fit: cover; }

.disc-sheen {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background:
    repeating-radial-gradient(circle at 50% 50%, rgba(255,255,255,0.05) 0 2px, rgba(0,0,0,0.05) 2px 4px),
    linear-gradient(115deg, rgba(255,255,255,0.22) 0%, rgba(255,255,255,0) 38%, rgba(255,255,255,0) 62%, rgba(255,255,255,0.14) 100%);
  mix-blend-mode: screen;
  pointer-events: none;
}

.disc-hole {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 26%;
  height: 26%;
  transform: translate(-50%, -50%);
  border-radius: 999px;
  background: rgba(18,16,15,0.92);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.18), 0 0 0 3px rgba(255,255,255,0.06);
}

@keyframes spin { to { rotate: 360deg; } }

.meta { flex: 1 1 auto; min-width: 0; }

.title, .artist {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.title { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
.artist { margin-top: 1px; font-size: 14px; color: rgba(255,255,255,0.7); }

.seek {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: 14px;
  margin: 6px 0 0;
  background: transparent;
  cursor: pointer;
}

.seek::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 999px;
  background: linear-gradient(to right, #fff var(--progress, 0%), rgba(255,255,255,0.28) var(--progress, 0%));
}

.seek::-moz-range-track {
  height: 4px;
  border-radius: 999px;
  background: linear-gradient(to right, #fff var(--progress, 0%), rgba(255,255,255,0.28) var(--progress, 0%));
}

/* The thumb only appears on hover, so the resting state is a clean hairline. */
.seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 12px;
  height: 12px;
  margin-top: -4px;
  border: 0;
  border-radius: 999px;
  background: #fff;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.seek::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border: 0;
  border-radius: 999px;
  background: #fff;
  opacity: 0;
  transition: opacity 0.15s ease;
}

.player:hover .seek::-webkit-slider-thumb,
.seek:focus-visible::-webkit-slider-thumb { opacity: 1; }
.player:hover .seek::-moz-range-thumb,
.seek:focus-visible::-moz-range-thumb { opacity: 1; }

.time {
  margin-top: 2px;
  font-size: 12px;
  color: rgba(255,255,255,0.65);
  font-variant-numeric: tabular-nums;
}

.controls { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; }

.ctl {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: #fff;
  cursor: pointer;
  transition: opacity 0.2s ease, transform 0.1s ease, background 0.2s ease;
}

.ctl:hover { background: rgba(255,255,255,0.12); }
.ctl:active { transform: scale(0.92); }

.ctl.play {
  width: 52px;
  height: 52px;
  background: #fff;
  color: #16130f;
  box-shadow: 0 4px 14px rgba(0,0,0,0.28);
}

.ctl.play:hover { background: #fff; opacity: 0.9; }

.ctl.play .i-pause { display: none; }
.player.is-playing .ctl.play .i-play { display: none; }
.player.is-playing .ctl.play .i-pause { display: block; }

:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* ---------- hidden youtube host ---------- */

.yt-host {
  position: fixed;
  width: 1px;
  height: 1px;
  bottom: 0;
  left: 0;
  opacity: 0;
  pointer-events: none;
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .disc, .bg-img, .badge-dot { animation: none !important; }
}

/* ---------- mobile ---------- */

@media (max-width: 767px) {
  :root { --edge: 16px; }

  .brand-name { font-size: 36px; }
  .pill { padding: 10px; }
  .pill-label, .pill-arrow { display: none; }

  .player { gap: 12px; padding: 10px 12px; }
  .disc { width: 60px; height: 60px; }
  .title { font-size: 15px; }
  .artist { font-size: 13px; }
  .ctl { width: 32px; height: 32px; }
  .ctl.play { width: 48px; height: 48px; }
  .seek::-webkit-slider-thumb { opacity: 1; }
  .seek::-moz-range-thumb { opacity: 1; }
}

@media (max-width: 400px) {
  .controls { gap: 2px; }
  .ctl { width: 30px; height: 30px; }
}

/* ---------- click effects ---------- */

.fx {
  position: fixed;
  inset: 0;
  z-index: 15;
  pointer-events: none;
  overflow: hidden;
}

/* Caption-sized, not meme-sized: it should read as a subtitle burned into the
   frame, so it stays small, tight and white rather than shouting. */
.fx-word {
  position: absolute;
  font-family: Mukta, Inter, sans-serif;
  font-size: clamp(16px, 1.8vw, 21px);
  font-weight: 800;
  letter-spacing: 0.02em;
  color: #fff;
  white-space: nowrap;
  text-shadow: 0 2px 14px rgba(0,0,0,0.75);
  animation: word-in 1.5s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

@keyframes word-in {
  0%   { opacity: 0; translate: 0 8px; }
  12%  { opacity: 1; translate: 0 0; }
  70%  { opacity: 1; }
  100% { opacity: 0; translate: 0 -14px; }
}

/* A short white bloom where the ball met the glass. */
.fx-flash {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at var(--cx, 50%) var(--cy, 50%), rgba(255,255,255,0.42) 0%, rgba(255,255,255,0) 18%);
  animation: flash-out 0.45s ease-out forwards;
}

@keyframes flash-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}

/* Camera flinch, not an earthquake — the scene moves, the UI does not. */
body.is-jolted .hero-bg { animation: jolt 0.4s cubic-bezier(0.36, 0.07, 0.19, 0.97); }

@keyframes jolt {
  0%, 100% { translate: 0 0; }
  20%      { translate: -5px 3px; }
  45%      { translate: 4px -3px; }
  70%      { translate: -2px 1px; }
}

@media (prefers-reduced-motion: reduce) {
  body.is-jolted .hero-bg { animation: none; }
}

/* Nothing else announces that the scene is interactive, so this does — then
   gets out of the way for good the moment it has been understood. */
.hint {
  position: fixed;
  left: 50%;
  bottom: calc(var(--edge) + 108px + env(safe-area-inset-bottom));
  translate: -50% 0;
  z-index: 20;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  white-space: nowrap;
  font-size: 12.5px;
  font-weight: 500;
  color: rgba(255,255,255,0.82);
  text-shadow: 0 1px 8px rgba(0,0,0,0.7);
  pointer-events: none;
  opacity: 0;
  animation: hint-in 0.7s ease-out 1.4s forwards;
}

.hint svg { animation: hint-tap 2.6s ease-in-out 2.1s infinite; }

@keyframes hint-in {
  to { opacity: 1; }
}

/* A small press, not a bounce. */
@keyframes hint-tap {
  0%, 62%, 100% { translate: 0 0; }
  70%           { translate: 0 3px; }
  78%           { translate: 0 0; }
}

.hint.is-gone {
  opacity: 0;
  animation: none;
  transition: opacity 0.45s ease;
}

@media (max-width: 767px) {
  .hint { bottom: calc(var(--edge) + 96px + env(safe-area-inset-bottom)); }
}

@media (prefers-reduced-motion: reduce) {
  .hint { animation: none; opacity: 1; }
  .hint svg { animation: none; }
}
