import { useState, useEffect, useRef, useCallback } from 'react';

// ─── Types ───────────────────────────────────────────────────────────────────

interface EpisodeInfo {
  audioUrl: string;
  title: string;
  season: number;
  episode: number;
}

interface PlayerState extends EpisodeInfo {
  currentTime: number;
}

interface PlayEpisodeEvent extends CustomEvent {
  detail: EpisodeInfo;
}

// ─── Constants ───────────────────────────────────────────────────────────────

const STORAGE_KEY = 'persistent-player-state';
const PLAYBACK_SPEEDS = [0.75, 1, 1.25, 1.5, 2] as const;
const SKIP_SECONDS = 15;
const SAVE_INTERVAL_MS = 5000;

// ─── Helpers ─────────────────────────────────────────────────────────────────

function formatTime(seconds: number): string {
  if (!isFinite(seconds) || seconds < 0) return '0:00';
  const hrs = Math.floor(seconds / 3600);
  const mins = Math.floor((seconds % 3600) / 60);
  const secs = Math.floor(seconds % 60);
  const paddedSecs = secs.toString().padStart(2, '0');
  if (hrs > 0) {
    return `${hrs}:${mins.toString().padStart(2, '0')}:${paddedSecs}`;
  }
  return `${mins}:${paddedSecs}`;
}

function loadState(): PlayerState | null {
  try {
    const raw = sessionStorage.getItem(STORAGE_KEY);
    if (!raw) return null;
    const parsed = JSON.parse(raw) as PlayerState;
    if (parsed.audioUrl && parsed.title != null) {
      return parsed;
    }
    return null;
  } catch {
    return null;
  }
}

function saveState(state: PlayerState): void {
  try {
    sessionStorage.setItem(STORAGE_KEY, JSON.stringify(state));
  } catch {
    // sessionStorage may be unavailable or full; silently ignore
  }
}

function clearState(): void {
  try {
    sessionStorage.removeItem(STORAGE_KEY);
  } catch {
    // ignore
  }
}

function buildEpisodeLabel(season: number, episode: number): string {
  if (season === 0) return 'Special';
  return `S${season}E${String(episode).padStart(2, '0')}`;
}

// ─── Component ───────────────────────────────────────────────────────────────

export default function PersistentPlayer() {
  const audioRef = useRef<HTMLAudioElement | null>(null);
  const progressBarRef = useRef<HTMLDivElement | null>(null);
  const saveTimerRef = useRef<number | null>(null);

  const [episodeInfo, setEpisodeInfo] = useState<EpisodeInfo | null>(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);
  const [buffered, setBuffered] = useState(0);
  const [volume, setVolume] = useState(1);
  const [speedIndex, setSpeedIndex] = useState(1); // default 1x
  const [isVisible, setIsVisible] = useState(false);
  const [isDraggingProgress, setIsDraggingProgress] = useState(false);

  // ── Restore state on mount ──────────────────────────────────────────────

  useEffect(() => {
    const saved = loadState();
    if (saved) {
      setEpisodeInfo({
        audioUrl: saved.audioUrl,
        title: saved.title,
        season: saved.season,
        episode: saved.episode,
      });
      setCurrentTime(saved.currentTime);
      setIsVisible(true);
    }
  }, []);

  // ── Listen for play-episode custom events ───────────────────────────────

  useEffect(() => {
    function handlePlayEpisode(e: Event) {
      const event = e as PlayEpisodeEvent;
      const { audioUrl, title, season, episode } = event.detail;
      if (!audioUrl) return;

      setEpisodeInfo({ audioUrl, title, season, episode });
      setCurrentTime(0);
      setDuration(0);
      setBuffered(0);
      setIsVisible(true);

      // Playback will start once the audio element loads the new source
      // (handled in the audioUrl effect below)
    }

    document.addEventListener('play-episode', handlePlayEpisode);
    return () => document.removeEventListener('play-episode', handlePlayEpisode);
  }, []);

  // ── Wire up audio element when episode changes ──────────────────────────

  useEffect(() => {
    const audio = audioRef.current;
    if (!audio || !episodeInfo) return;

    // If source changed, load new source
    if (audio.src !== episodeInfo.audioUrl) {
      audio.src = episodeInfo.audioUrl;
      audio.load();
    }

    // Restore saved position for restored state (non-zero currentTime means restored)
    if (currentTime > 0 && audio.readyState >= 1) {
      audio.currentTime = currentTime;
    }

    // Auto-play if this is a fresh play-episode event (currentTime === 0)
    // For restored sessions, don't auto-play
    const isRestoredSession = currentTime > 0;
    if (!isRestoredSession) {
      const playOnReady = () => {
        audio.play().catch(() => {
          // Browser may block autoplay; user will click play manually
        });
        audio.removeEventListener('canplay', playOnReady);
      };
      if (audio.readyState >= 3) {
        audio.play().catch(() => {});
      } else {
        audio.addEventListener('canplay', playOnReady);
        return () => audio.removeEventListener('canplay', playOnReady);
      }
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [episodeInfo?.audioUrl]);

  // ── Restore currentTime once audio metadata is loaded ───────────────────

  useEffect(() => {
    const audio = audioRef.current;
    if (!audio || !episodeInfo) return;

    const handleLoadedMetadata = () => {
      const saved = loadState();
      if (saved && saved.audioUrl === episodeInfo.audioUrl && saved.currentTime > 0) {
        audio.currentTime = saved.currentTime;
        setCurrentTime(saved.currentTime);
      }
    };

    audio.addEventListener('loadedmetadata', handleLoadedMetadata);
    return () => audio.removeEventListener('loadedmetadata', handleLoadedMetadata);
  }, [episodeInfo]);

  // ── Audio event handlers ────────────────────────────────────────────────

  useEffect(() => {
    const audio = audioRef.current;
    if (!audio) return;

    const onPlay = () => setIsPlaying(true);
    const onPause = () => setIsPlaying(false);
    const onEnded = () => {
      setIsPlaying(false);
      setCurrentTime(0);
    };
    const onTimeUpdate = () => {
      if (!isDraggingProgress) {
        setCurrentTime(audio.currentTime);
      }
    };
    const onDurationChange = () => {
      if (isFinite(audio.duration)) {
        setDuration(audio.duration);
      }
    };
    const onProgress = () => {
      if (audio.buffered.length > 0) {
        setBuffered(audio.buffered.end(audio.buffered.length - 1));
      }
    };

    audio.addEventListener('play', onPlay);
    audio.addEventListener('pause', onPause);
    audio.addEventListener('ended', onEnded);
    audio.addEventListener('timeupdate', onTimeUpdate);
    audio.addEventListener('durationchange', onDurationChange);
    audio.addEventListener('progress', onProgress);

    return () => {
      audio.removeEventListener('play', onPlay);
      audio.removeEventListener('pause', onPause);
      audio.removeEventListener('ended', onEnded);
      audio.removeEventListener('timeupdate', onTimeUpdate);
      audio.removeEventListener('durationchange', onDurationChange);
      audio.removeEventListener('progress', onProgress);
    };
  }, [isDraggingProgress]);

  // ── Periodic state persistence ──────────────────────────────────────────

  useEffect(() => {
    if (!episodeInfo || !isPlaying) {
      if (saveTimerRef.current != null) {
        window.clearInterval(saveTimerRef.current);
        saveTimerRef.current = null;
      }
      return;
    }

    saveTimerRef.current = window.setInterval(() => {
      const audio = audioRef.current;
      if (audio && episodeInfo) {
        saveState({
          ...episodeInfo,
          currentTime: audio.currentTime,
        });
      }
    }, SAVE_INTERVAL_MS);

    return () => {
      if (saveTimerRef.current != null) {
        window.clearInterval(saveTimerRef.current);
        saveTimerRef.current = null;
      }
    };
  }, [episodeInfo, isPlaying]);

  // ── Save state on pause / before unload ─────────────────────────────────

  useEffect(() => {
    function handleBeforeUnload() {
      const audio = audioRef.current;
      if (audio && episodeInfo) {
        saveState({ ...episodeInfo, currentTime: audio.currentTime });
      }
    }

    window.addEventListener('beforeunload', handleBeforeUnload);
    return () => window.removeEventListener('beforeunload', handleBeforeUnload);
  }, [episodeInfo]);

  // ── Controls ────────────────────────────────────────────────────────────

  const togglePlayPause = useCallback(() => {
    const audio = audioRef.current;
    if (!audio) return;
    if (audio.paused) {
      audio.play().catch(() => {});
    } else {
      audio.pause();
      if (episodeInfo) {
        saveState({ ...episodeInfo, currentTime: audio.currentTime });
      }
    }
  }, [episodeInfo]);

  const skipBack = useCallback(() => {
    const audio = audioRef.current;
    if (!audio) return;
    audio.currentTime = Math.max(0, audio.currentTime - SKIP_SECONDS);
  }, []);

  const skipForward = useCallback(() => {
    const audio = audioRef.current;
    if (!audio) return;
    audio.currentTime = Math.min(audio.duration || 0, audio.currentTime + SKIP_SECONDS);
  }, []);

  const cycleSpeed = useCallback(() => {
    setSpeedIndex((prev) => {
      const next = (prev + 1) % PLAYBACK_SPEEDS.length;
      const audio = audioRef.current;
      if (audio) {
        audio.playbackRate = PLAYBACK_SPEEDS[next];
      }
      return next;
    });
  }, []);

  const handleVolumeChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    const val = parseFloat(e.target.value);
    setVolume(val);
    const audio = audioRef.current;
    if (audio) {
      audio.volume = val;
    }
  }, []);

  const handleProgressClick = useCallback(
    (e: React.MouseEvent<HTMLDivElement>) => {
      const bar = progressBarRef.current;
      const audio = audioRef.current;
      if (!bar || !audio || !duration) return;

      const rect = bar.getBoundingClientRect();
      const fraction = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
      const newTime = fraction * duration;
      audio.currentTime = newTime;
      setCurrentTime(newTime);
    },
    [duration],
  );

  const handleProgressMouseDown = useCallback(
    (e: React.MouseEvent<HTMLDivElement>) => {
      setIsDraggingProgress(true);
      handleProgressClick(e);

      const handleMouseMove = (ev: MouseEvent) => {
        const bar = progressBarRef.current;
        const audio = audioRef.current;
        if (!bar || !audio || !duration) return;
        const rect = bar.getBoundingClientRect();
        const fraction = Math.max(0, Math.min(1, (ev.clientX - rect.left) / rect.width));
        const newTime = fraction * duration;
        audio.currentTime = newTime;
        setCurrentTime(newTime);
      };

      const handleMouseUp = () => {
        setIsDraggingProgress(false);
        document.removeEventListener('mousemove', handleMouseMove);
        document.removeEventListener('mouseup', handleMouseUp);
      };

      document.addEventListener('mousemove', handleMouseMove);
      document.addEventListener('mouseup', handleMouseUp);
    },
    [duration, handleProgressClick],
  );

  const closePlayer = useCallback(() => {
    const audio = audioRef.current;
    if (audio) {
      audio.pause();
      audio.removeAttribute('src');
      audio.load();
    }
    setIsPlaying(false);
    setEpisodeInfo(null);
    setCurrentTime(0);
    setDuration(0);
    setBuffered(0);
    setIsVisible(false);
    clearState();
  }, []);

  // ── Keyboard shortcuts ──────────────────────────────────────────────────

  useEffect(() => {
    if (!episodeInfo) return;

    function handleKeyDown(e: KeyboardEvent) {
      // Only respond when not typing in an input
      const target = e.target as HTMLElement;
      if (
        target.tagName === 'INPUT' ||
        target.tagName === 'TEXTAREA' ||
        target.tagName === 'SELECT' ||
        target.isContentEditable
      ) {
        return;
      }

      switch (e.key) {
        case ' ':
          e.preventDefault();
          togglePlayPause();
          break;
        case 'ArrowLeft':
          e.preventDefault();
          skipBack();
          break;
        case 'ArrowRight':
          e.preventDefault();
          skipForward();
          break;
      }
    }

    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [episodeInfo, togglePlayPause, skipBack, skipForward]);

  // ── Derived values ──────────────────────────────────────────────────────

  const progressPercent = duration > 0 ? (currentTime / duration) * 100 : 0;
  const bufferedPercent = duration > 0 ? (buffered / duration) * 100 : 0;
  const currentSpeed = PLAYBACK_SPEEDS[speedIndex];
  const episodeLabel = episodeInfo ? buildEpisodeLabel(episodeInfo.season, episodeInfo.episode) : '';

  // ── Render ──────────────────────────────────────────────────────────────

  return (
    <>
      {/* Hidden audio element - always mounted so it survives re-renders */}
      <audio ref={audioRef} preload="metadata" />

      <div
        className="persistent-player"
        style={{
          transform: isVisible ? 'translateY(0)' : 'translateY(100%)',
        }}
        role="region"
        aria-label="Audio player"
      >
        {/* Progress bar - full width across top of player */}
        <div
          className="persistent-player__progress-bar"
          ref={progressBarRef}
          onClick={handleProgressClick}
          onMouseDown={handleProgressMouseDown}
          role="slider"
          aria-label="Playback progress"
          aria-valuemin={0}
          aria-valuemax={duration}
          aria-valuenow={currentTime}
          aria-valuetext={`${formatTime(currentTime)} of ${formatTime(duration)}`}
          tabIndex={0}
        >
          <div
            className="persistent-player__progress-buffered"
            style={{ width: `${bufferedPercent}%` }}
          />
          <div
            className="persistent-player__progress-fill"
            style={{ width: `${progressPercent}%` }}
          />
          <div
            className="persistent-player__progress-handle"
            style={{ left: `${progressPercent}%` }}
          />
        </div>

        <div className="persistent-player__content">
          {/* Left: Episode info */}
          <div className="persistent-player__info">
            {episodeLabel && (
              <span className="persistent-player__badge">{episodeLabel}</span>
            )}
            <span className="persistent-player__title" title={episodeInfo?.title ?? ''}>
              {episodeInfo?.title ?? ''}
            </span>
          </div>

          {/* Center: Playback controls */}
          <div className="persistent-player__controls">
            <button
              className="persistent-player__btn persistent-player__btn--skip"
              onClick={skipBack}
              aria-label="Skip back 15 seconds"
              title="Skip back 15 seconds"
            >
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <polyline points="1 4 1 10 7 10" />
                <path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10" />
                <text x="12" y="16" textAnchor="middle" fill="currentColor" stroke="none" fontSize="8" fontWeight="700">15</text>
              </svg>
            </button>

            <button
              className="persistent-player__btn persistent-player__btn--play"
              onClick={togglePlayPause}
              aria-label={isPlaying ? 'Pause' : 'Play'}
              title={isPlaying ? 'Pause' : 'Play'}
            >
              {isPlaying ? (
                <svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor">
                  <rect x="6" y="4" width="4" height="16" rx="1" />
                  <rect x="14" y="4" width="4" height="16" rx="1" />
                </svg>
              ) : (
                <svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor">
                  <polygon points="6 3 20 12 6 21 6 3" />
                </svg>
              )}
            </button>

            <button
              className="persistent-player__btn persistent-player__btn--skip"
              onClick={skipForward}
              aria-label="Skip forward 15 seconds"
              title="Skip forward 15 seconds"
            >
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <polyline points="23 4 23 10 17 10" />
                <path d="M20.49 15a9 9 0 1 1-2.13-9.36L23 10" />
                <text x="12" y="16" textAnchor="middle" fill="currentColor" stroke="none" fontSize="8" fontWeight="700">15</text>
              </svg>
            </button>
          </div>

          {/* Time display */}
          <div className="persistent-player__time">
            <span>{formatTime(currentTime)}</span>
            <span className="persistent-player__time-separator">/</span>
            <span>{formatTime(duration)}</span>
          </div>

          {/* Right: Volume, speed, close */}
          <div className="persistent-player__right">
            <div className="persistent-player__volume">
              <button
                className="persistent-player__btn persistent-player__btn--icon"
                onClick={() => {
                  const audio = audioRef.current;
                  if (!audio) return;
                  if (audio.volume > 0) {
                    audio.volume = 0;
                    setVolume(0);
                  } else {
                    audio.volume = 1;
                    setVolume(1);
                  }
                }}
                aria-label={volume === 0 ? 'Unmute' : 'Mute'}
                title={volume === 0 ? 'Unmute' : 'Mute'}
              >
                {volume === 0 ? (
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                    <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" />
                    <line x1="23" y1="9" x2="17" y2="15" />
                    <line x1="17" y1="9" x2="23" y2="15" />
                  </svg>
                ) : volume < 0.5 ? (
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                    <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" />
                    <path d="M15.54 8.46a5 5 0 0 1 0 7.07" />
                  </svg>
                ) : (
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                    <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" />
                    <path d="M15.54 8.46a5 5 0 0 1 0 7.07" />
                    <path d="M19.07 4.93a10 10 0 0 1 0 14.14" />
                  </svg>
                )}
              </button>
              <input
                type="range"
                className="persistent-player__volume-slider"
                min="0"
                max="1"
                step="0.05"
                value={volume}
                onChange={handleVolumeChange}
                aria-label="Volume"
              />
            </div>

            <button
              className="persistent-player__btn persistent-player__btn--speed"
              onClick={cycleSpeed}
              aria-label={`Playback speed: ${currentSpeed}x`}
              title={`Playback speed: ${currentSpeed}x`}
            >
              {currentSpeed}x
            </button>

            <button
              className="persistent-player__btn persistent-player__btn--close"
              onClick={closePlayer}
              aria-label="Close player"
              title="Close player"
            >
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <line x1="18" y1="6" x2="6" y2="18" />
                <line x1="6" y1="6" x2="18" y2="18" />
              </svg>
            </button>
          </div>
        </div>
      </div>

      <style>{`
        .persistent-player {
          position: fixed;
          bottom: 0;
          left: 0;
          right: 0;
          z-index: 1000;
          height: 72px;
          background: hsl(220 20% 6% / 0.95);
          backdrop-filter: blur(20px);
          -webkit-backdrop-filter: blur(20px);
          border-top: 1px solid hsl(200 85% 55% / 0.15);
          transition: transform 350ms cubic-bezier(0.4, 0, 0.2, 1);
          display: flex;
          flex-direction: column;
        }

        [data-theme="light"] .persistent-player {
          background: hsl(220 20% 97% / 0.92);
          border-top-color: hsl(200 85% 42% / 0.2);
        }

        /* ── Progress bar ─────────────────────────────────────── */

        .persistent-player__progress-bar {
          position: relative;
          width: 100%;
          height: 3px;
          background: hsl(220 12% 24% / 0.5);
          cursor: pointer;
          flex-shrink: 0;
        }

        .persistent-player__progress-bar:hover {
          height: 5px;
        }

        .persistent-player__progress-bar:hover .persistent-player__progress-handle {
          opacity: 1;
        }

        .persistent-player__progress-bar:focus-visible {
          outline: 2px solid var(--color-accent, hsl(200 85% 55%));
          outline-offset: 2px;
        }

        .persistent-player__progress-bar:focus-visible .persistent-player__progress-handle {
          opacity: 1;
        }

        [data-theme="light"] .persistent-player__progress-bar {
          background: hsl(220 12% 85% / 0.5);
        }

        .persistent-player__progress-buffered {
          position: absolute;
          top: 0;
          left: 0;
          height: 100%;
          background: hsl(220 8% 48% / 0.3);
          pointer-events: none;
        }

        .persistent-player__progress-fill {
          position: absolute;
          top: 0;
          left: 0;
          height: 100%;
          background: var(--color-accent, hsl(200 85% 55%));
          pointer-events: none;
        }

        .persistent-player__progress-handle {
          position: absolute;
          top: 50%;
          width: 10px;
          height: 10px;
          border-radius: 50%;
          background: var(--color-accent, hsl(200 85% 55%));
          transform: translate(-50%, -50%);
          opacity: 0;
          transition: opacity 150ms ease;
          pointer-events: none;
        }

        /* ── Content layout ───────────────────────────────────── */

        .persistent-player__content {
          display: flex;
          align-items: center;
          flex: 1;
          padding: 0 16px;
          gap: 16px;
          min-width: 0;
        }

        /* ── Episode info ─────────────────────────────────────── */

        .persistent-player__info {
          display: flex;
          align-items: center;
          gap: 10px;
          min-width: 0;
          flex: 1;
        }

        .persistent-player__badge {
          display: inline-flex;
          align-items: center;
          padding: 2px 8px;
          border-radius: 9999px;
          font-size: 0.7rem;
          font-weight: 600;
          background: hsl(200 85% 55% / 0.2);
          color: var(--color-accent, hsl(200 85% 55%));
          border: 1px solid hsl(200 85% 55% / 0.3);
          white-space: nowrap;
          flex-shrink: 0;
        }

        .persistent-player__title {
          font-size: 0.875rem;
          font-weight: 500;
          color: var(--color-text-primary, hsl(220 10% 92%));
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
          min-width: 0;
        }

        /* ── Controls ─────────────────────────────────────────── */

        .persistent-player__controls {
          display: flex;
          align-items: center;
          gap: 4px;
          flex-shrink: 0;
        }

        .persistent-player__btn {
          display: inline-flex;
          align-items: center;
          justify-content: center;
          background: none;
          border: none;
          cursor: pointer;
          color: var(--color-text-secondary, hsl(220 8% 68%));
          padding: 6px;
          border-radius: 6px;
          transition: color 150ms ease, background 150ms ease;
        }

        .persistent-player__btn:hover {
          color: var(--color-text-primary, hsl(220 10% 92%));
          background: hsl(220 16% 16% / 0.6);
        }

        [data-theme="light"] .persistent-player__btn:hover {
          background: hsl(220 16% 92% / 0.6);
        }

        .persistent-player__btn:focus-visible {
          outline: 2px solid var(--color-accent, hsl(200 85% 55%));
          outline-offset: 2px;
          color: var(--color-text-primary, hsl(220 10% 92%));
        }

        .persistent-player__btn--play:focus-visible {
          color: hsl(220 20% 8%);
          box-shadow: 0 0 16px hsl(200 85% 55% / 0.3);
        }

        .persistent-player__btn--play {
          width: 40px;
          height: 40px;
          border-radius: 50%;
          color: hsl(220 20% 8%);
          background: var(--color-accent, hsl(200 85% 55%));
        }

        .persistent-player__btn--play:hover {
          color: hsl(220 20% 8%);
          background: var(--color-accent-hover, hsl(200 85% 65%));
          box-shadow: 0 0 16px hsl(200 85% 55% / 0.3);
        }

        .persistent-player__btn--speed {
          font-size: 0.7rem;
          font-weight: 700;
          min-width: 36px;
          font-family: var(--font-mono, monospace);
        }

        .persistent-player__btn--close {
          opacity: 0.5;
        }

        .persistent-player__btn--close:hover {
          opacity: 1;
        }

        /* ── Time display ─────────────────────────────────────── */

        .persistent-player__time {
          display: flex;
          align-items: center;
          gap: 4px;
          font-size: 0.75rem;
          font-family: var(--font-mono, monospace);
          color: var(--color-text-muted, hsl(220 6% 48%));
          white-space: nowrap;
          flex-shrink: 0;
        }

        .persistent-player__time-separator {
          opacity: 0.5;
        }

        /* ── Volume ───────────────────────────────────────────── */

        .persistent-player__right {
          display: flex;
          align-items: center;
          gap: 4px;
          flex-shrink: 0;
        }

        .persistent-player__volume {
          display: flex;
          align-items: center;
          gap: 4px;
        }

        .persistent-player__volume-slider {
          width: 72px;
          height: 4px;
          -webkit-appearance: none;
          appearance: none;
          background: hsl(220 12% 24%);
          border-radius: 2px;
          outline: none;
          cursor: pointer;
        }

        [data-theme="light"] .persistent-player__volume-slider {
          background: hsl(220 12% 80%);
        }

        .persistent-player__volume-slider::-webkit-slider-thumb {
          -webkit-appearance: none;
          width: 12px;
          height: 12px;
          border-radius: 50%;
          background: var(--color-accent, hsl(200 85% 55%));
          border: none;
          cursor: pointer;
        }

        .persistent-player__volume-slider::-moz-range-thumb {
          width: 12px;
          height: 12px;
          border-radius: 50%;
          background: var(--color-accent, hsl(200 85% 55%));
          border: none;
          cursor: pointer;
        }

        /* ── Mobile responsive ────────────────────────────────── */

        @media (max-width: 768px) {
          .persistent-player {
            height: 64px;
          }

          .persistent-player__content {
            padding: 0 10px;
            gap: 8px;
          }

          .persistent-player__info {
            flex: 1;
            min-width: 0;
          }

          .persistent-player__title {
            font-size: 0.8rem;
            max-width: 120px;
          }

          .persistent-player__volume {
            display: none;
          }

          .persistent-player__btn--speed {
            display: none;
          }

          .persistent-player__time {
            font-size: 0.65rem;
          }

          .persistent-player__btn--play {
            width: 34px;
            height: 34px;
          }

          .persistent-player__btn--play svg {
            width: 18px;
            height: 18px;
          }

          .persistent-player__btn--skip svg {
            width: 14px;
            height: 14px;
          }
        }

        @media (max-width: 480px) {
          .persistent-player__btn--skip {
            display: none;
          }

          .persistent-player__time {
            display: none;
          }

          .persistent-player__title {
            max-width: 140px;
          }
        }
      `}</style>
    </>
  );
}
