*, *::before, *::after {
  box-sizing: border-box;
}

:root {
  --color-accent: #58A6FF;
  --color-accent-hover: #79C0FF;
  --color-bg: #0D1117;
  --color-bg-secondary: #161B22;
  --color-bg-tertiary: #21262D;
  --color-border: #30363D;
  --color-danger: #F85149;
  --color-success: #3FB950;
  --color-text: #E6EDF3;
  --color-text-muted: #8B949E;
  --color-text-subtle: #6E7681;
  --color-warning: #D29922;
  --font-mono: 'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, monospace;
  --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;
}

html {
  scroll-behavior: smooth;
  /* Solid dark fallback so the full viewport (including areas beyond body content height)
     is never white/default. The body gradient will paint on top for the top section. */
  background-color: var(--color-bg);
}

body {
  /* Ensure the body box is at least full viewport height. */
  min-height: 100vh;

  /* Base black from the html fallback. The visible "gradient" effect is created
     by the ::before pseudo-element overlay (see below). This keeps the base
     color solid black while adding a noticeable top tint. */
  background-color: var(--color-bg);

  color: var(--color-text);
  font-family: var(--font-sans);
  line-height: 1.6;
  margin: 0;
  position: relative;  /* needed for the absolute pseudo-element */
}

/* Top gradient tint overlay.
   - Uses the exact same --color-bg-secondary (blue-black) at the top.
   - Fades to transparent around the middle of the page (by ~55vh).
   - This creates a noticeable blue-black tint at the top that quickly fades
     to the pure black base.
   - The height covers the top half so the effect is visible in the upper part
     of the page as requested.
   - z-index -1 puts it behind the content but on top of the background.
   - The two colors remain exactly the original ones. */
body::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 60vh;
  background: linear-gradient(
    180deg,
    var(--color-bg-secondary) 0%,
    transparent 55%
  );
  z-index: -1;
  pointer-events: none;
}

a:link {
  color: inherit;
}

.oss-hero {
  /* Background is now provided by the body gradient so the transition
     is continuous and smooth across the hero area instead of being
     confined to this section (which created a hard block on OLED). */
  background: transparent;
  padding: 8rem 0 5rem;
  text-align: center;
}

.page-main {
  /* The body now owns the background gradient; no need for a solid
     color here that could fight or create seams. */
  background: transparent;
  color: var(--color-text);
}

#drain-img {
  color: black;
  height: 37px;
  width: 36px;
  opacity: 0; /* initial state for one-time load fade-in */
  cursor: pointer;
  transform-origin: center center;
  transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 1400ms ease;
  will-change: transform;
}

#drain-img:hover:not(.drain-clicking) {
  transform: scale(1.25);
}

@keyframes drain-click-anim {
  0%   { transform: scale(1.25); }
  25%  { transform: scale(0.75); }
  60%  { transform: scale(1.35); }
  80%  { transform: scale(1.1);  }
  100% { transform: scale(1); }
}

#drain-img.drain-clicking {
  animation: drain-click-anim 0.65s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

/* When the click animation ends we are back at the "rest" scale.
   If the mouse is still hovering, the hover transition will smoothly take it to the large size.
   If the mouse has left, it stays at rest — no instant snap from a "settled at 1.25" state. */

/* Subtle, calm glowing ring while music is playing.
   Uses filter: drop-shadow so the glow follows the transparent shape of drain.png
   (not a rectangular box). Removed when paused.
   Feels thematic and not flashy. */
#drain-img.playing {
  filter: drop-shadow(0 0 6px rgba(88, 166, 255, 0.55))
          drop-shadow(0 0 14px rgba(88, 166, 255, 0.32))
          drop-shadow(0 0 26px rgba(88, 166, 255, 0.18));
  transition: filter 180ms ease;
}

#drain-img {
  transition: filter 180ms ease; /* smooth on/off for the glow */
}

#iy7of {
  display: flex;
  flex-direction: row;
  justify-content: center;
  min-height: 100px;
}

#dtd-container {
  display: flex;
  flex-direction: column;
  align-items: center;
}

#iuyh6 {
  align-self: center;
  color: black;
  height: 30px;
  width: 164px;
  cursor: pointer;
  transform-origin: center center;
  opacity: 0; /* initial state for one-time load fade-in */
  transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 1400ms ease;
  will-change: transform;
}

#iuyh6:hover:not(.drain-clicking) {
  transform: scale(1.25);
}

#iuyh6.drain-clicking {
  animation: drain-click-anim 0.65s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}

/* Same principle for the logo image: click animation now ends at rest scale.
   Hover transition (if active) will fluidly return it to the large size after the bounce.
   Mouse leave during/after click = smooth settle to normal, no snap. */

#song-menu {
  width: 380px;
  height: 190px;
  position: relative;
  overflow: visible;
  opacity: 0;
  transform: scaleY(0);
  transform-origin: top center;
  transition: opacity 0.4s ease, transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
  pointer-events: none;
  z-index: 20;
}

#song-menu.open {
  opacity: 1;
  transform: scaleY(1);
  pointer-events: all;
}

#ml0 { transition: stroke-dashoffset 0.4s ease; }
#ml1 { transition: stroke-dashoffset 0.4s ease 0.07s; }
#ml2 { transition: stroke-dashoffset 0.4s ease 0.14s; }

#sel-circle {
  position: absolute;
  width: 68px;
  height: 60px;
  overflow: visible;
  pointer-events: none;
  transition: left 0.45s cubic-bezier(0.34, 1.56, 0.64, 1),
              top  0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.snum {
  position: absolute;
  font-family: 'Nanum Brush Script', cursive;
  font-size: 38px;
  color: white;
  cursor: pointer;
  transform: scale(0);
  transform-origin: center center;
  user-select: none;
  display: inline-block;
}

@media (max-width: 480px) {
  pre code {
    white-space: pre-wrap;
  }
}

/* Top-of-page pulsating white glow (atmospheric low-end pulse visual).
   - Used for all songs via different real-time detectors:
     - Song 0 (drain.mp3): precise musical phrase windows + energy spikes.
     - Song 1 (swandive.mp3): robust dynamic low-end (kick + sub-bass) detector using rolling average
       of the lowest analyser bins. Pulse strength scales with the actual intensity of each low-end hit (always active).
     - Song 2 (burnslow.mp3): same robust detector, gated to the specified time segments.
   - Full-width linear wash across the entire top section (not a centered radial spot).
   - Pulses *downwards* from the top edge on beats (the bright/fade zone extends further down
     on strong pulses, then relaxes) — feels like the page is breathing with the track’s deep rhythmic foundation.
   - Opacity + gradient extent are both driven live from the analyser (0 / base when inactive).
   - Screen blend + blur for a soft, non-harsh light wash that brightens the top hero area.
   - Taller height so it meaningfully covers the top section / hero padding.
   - z-index places it behind the grid dots (z5) but above the body tint (::before z-1).
   - The drain image and logo (normal flow) sit in front in the center. */
#top-pulse-glow {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 55vh;
  pointer-events: none;
  z-index: 2;
  opacity: 0;
  /* The bright part of the downward wash is controlled by --top-glow-extent (set from JS).
     On beat the extent grows (pushes the glow further down the page), then decays back.
     This gives the "pulsates downwards" motion across the top section.
     Values here + the JS extent tunables have been toned down (less bright core, shorter tail). */
  background: linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.92) 0%,
    rgba(255, 255, 255, 0.48) var(--top-glow-extent, 14%),
    rgba(255, 255, 255, 0.14) calc(var(--top-glow-extent, 14%) + 11%),
    transparent 62%
  );
  mix-blend-mode: screen;
  filter: blur(16px);
  /* No transition on opacity or the custom prop — JS drives both at ~60 fps for tight response.
     The decay in segmentPulse (plus the extent calc) gives the pulse length and downward motion. */
}