/* ========== YT AUDIO WIDGET (floating, draggable) ==========
   Fully self-contained - every selector here is scoped to .yt-* classes
   that exist nowhere else in the project, so this file has zero overlap
   with any other stylesheet. Independent of the rest of the site by
   design (see js/yt-audio-widget.js for the same isolation on the JS
   side) - safe to delete this file + its <link> + the widget markup in
   index.html + its own script tag to remove the feature entirely,
   without touching anything else. */
/* Default/rest state: lives in normal flow, embedded in the header (see
   index.html - 3rd child of .header-mid - and css/header.css's own
   .header-mid > #ytWidget grid-placement rule) - NOT fixed/floating
   until js/yt-audio-widget.js's click handler promotes it (see that
   file: sets position/left/top/width inline the instant the user clicks
   the minimized pill). position:static + width:auto here is that rest
   state; every other property below (background/blur/border/shadow) is
   the "open" look, inert until .minimized (below) is removed. */
/* #ytWidget itself stays the plain outer shell - position/drag/width/
   transition/cast box-shadow, overflow:visible so that cast shadow isn't
   clipped. The inset outline lives on its own ::before pseudo-element,
   and the actual blur on #ytBlurLayer, a real canvas - see both further
   below - full-bleed behind both the header row and the playlist when
   open either way. .yt-widget-inner (further below) is just the content
   wrapper/clip for children. */
.yt-widget {
  position: relative;
  width: auto;
  border: none;
  border-radius: 10px;
  overflow: visible;
  color: #fff;
  user-select: none;
  z-index: 999;
  font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
  transition: width 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* backdrop-filter itself is confirmed non-functional here - real-browser
   test (not headless) showed zero visible blur even from
   background:transparent + backdrop-filter:blur(30px) alone, isolated
   from every other property, so this isn't a support-detection false
   positive or an opacity/z-index mistake, the GPU path for
   backdrop-filter just isn't active in this context. Kept only for the
   1px inset outline now (a real, non-backdrop box-shadow, unaffected by
   that) - the actual blur comes from #ytBlurLayer below instead: a
   canvas kept redrawn with a live crop of .bg-video
   (js/yt-widget-blur-fallback.js) with a plain CSS `filter: blur()` on
   it, which doesn't depend on backdrop-filter's GPU support at all. z-
   index:2 - above both the canvas (0) and .yt-widget-inner's content
   (1), so the outline line itself stays crisp regardless of what's under
   it. */
.yt-widget::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.14);
  pointer-events: none;
}
/* The actual blur layer (see the comment above ::before) - a real DOM
   canvas, not a pseudo-element, since backdrop-filter itself doesn't
   work here and a plain `filter` needs real pixels to blur, which only
   js/yt-widget-blur-fallback.js's redraw loop can supply. inset:0 +
   border-radius:inherit covers #ytWidget's box corner to corner, same as
   the old ::before did - filter:blur naturally softens that rounded edge
   too (a normal, well-supported filter behavior, not the broken
   border-radius+overflow-auto-scroll clipping path .yt-playlist works
   around further below). z-index:0, under both .yt-widget-inner's real
   content (1) and ::before's outline (2).
   Text behind the widget was tried as a second layer here (real DOM
   clones of whatever page elements sat behind it, repositioned to match)
   - reverted: visible double/misaligned text through the widget in real
   use, plus perceptible lag, despite clean results in testing here. Back
   to video-only; text behind the widget goes back to showing through
   sharp/unblurred, same as before that attempt. */
.yt-blur-layer {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  display: block;
  border-radius: inherit;
  filter: blur(8px);
  pointer-events: none;
}
/* Same elastic easing as .yt-widget's own width transition above,
   extended to left/top too - for whatever future code snaps the
   floating widget to a position/edge via this class, so a snap reads
   with the same characteristic small bounce as every other widget
   movement instead of a flat linear/ease slide. */
.yt-widget.snapping {
  transition: left 0.35s cubic-bezier(0.34, 1.56, 0.64, 1), top 0.35s cubic-bezier(0.34, 1.56, 0.64, 1), width 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* Drop shadow only while open - the compact/minimized pill (both
   embedded in the header and floating) keeps just the inset outline
   (on ::before above), no cast shadow. This is .yt-widget's own
   box-shadow, separate from ::before's - a cast (non-inset) shadow
   paints outside the box entirely, so it's unaffected by whatever
   paints on top inside the box. */
.yt-widget:not(.minimized) {
  box-shadow: 10px 16px 34px rgba(0,0,0,0.55);
}
.yt-widget-inner {
  position: relative;
  z-index: 1;
  border-radius: 10px;
  overflow: hidden;
}
/* Native browser drag-and-drop (distinct from the Pointer Events drag
   js/yt-audio-widget.js implements itself) on any child - an image, a
   selected text run - would otherwise be able to hijack a pointerdown
   started on/near it before our own handler gets a clean gesture. */
.yt-widget * {
  -webkit-user-drag: none;
}
/* Compact pill: the widget's default appearance both at initial page
   load (see index.html - the "minimized" class ships on the element
   itself) and again whenever js/yt-audio-widget.js re-applies it (the
   dblclick toggle, or auto-minimize after 6s idle once floating) - same
   single class drives both the header-embedded AND the floating-pill
   look, the only difference being whichever position/left/top/width the
   JS has (or hasn't) set inline at that moment. Keeps the EXACT SAME
   background/blur/border/shadow as the open look above (inherited, not
   restated here) - only width changes between the two states, so the
   widget never looks like a different, more-opaque panel while
   minimized. */
/* No width rule here on purpose - minimizeWidget()/expandWidget()
   (js/yt-audio-widget.js) always pin style.width to an explicit px number
   themselves (never '') before touching this class, specifically so the
   width transition always animates between two explicit values. A
   `width: auto !important` here used to be needed to beat a leftover
   inline 300px, but forcing the change through `auto` is exactly what
   made the transition snap instead of ease (auto's value depends on the
   .yt-body/.yt-controls/.yt-volume/.yt-playlist display:none rules below,
   which toggle in the same synchronous recalc - confirmed via isolated
   repro that this combination never animates in this engine, regardless
   of !important or requestAnimationFrame staging). Now that JS always
   supplies the correct explicit number up front, this class never needs
   to fight an inline value on its own. */
.yt-widget.minimized .yt-drag-handle {
  border-bottom: none;
  padding: 6px 14px;
  cursor: pointer;
}
.yt-widget.minimized .yt-body,
.yt-widget.minimized .yt-controls,
.yt-widget.minimized .yt-volume,
.yt-widget.minimized .yt-playlist {
  display: none;
}
.yt-drag-handle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  cursor: grab;
  border-bottom: 1px solid rgba(255,255,255,0.06);
}
.yt-drag-handle:active { cursor: grabbing; }
.yt-eq {
  display: flex;
  align-items: flex-end;
  gap: 1.5px;
  height: 13px;
  margin-left: 14px;
  -webkit-mask-image: repeating-linear-gradient(to bottom, #000 0px, #000 1.5px, transparent 1.5px, transparent 3px);
  mask-image: repeating-linear-gradient(to bottom, #000 0px, #000 1.5px, transparent 1.5px, transparent 3px);
}
.yt-eq span {
  width: 2px;
  background: rgba(255,255,255,0.5);
  height: 3px;
  border-radius: 1px;
  transition: background 0.2s ease;
}
.yt-eq.playing span {
  background: rgba(255,255,255,0.85);
  animation: eq-bounce 0.9s ease-in-out infinite;
}
.yt-eq.playing span:nth-child(1) { animation-delay: 0s; }
.yt-eq.playing span:nth-child(2) { animation-delay: 0.15s; }
.yt-eq.playing span:nth-child(3) { animation-delay: 0.3s; }
.yt-eq.playing span:nth-child(4) { animation-delay: 0.45s; }
.yt-eq.playing span:nth-child(5) { animation-delay: 0.6s; }
.yt-eq.playing span:nth-child(6) { animation-delay: 0.75s; }
@keyframes eq-bounce {
  0%, 100% { height: 3px; }
  50% { height: 12px; }
}
.yt-label { font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: rgba(255,255,255,0.35); }
.yt-body { display: flex; align-items: center; gap: 12px; padding: 12px; }
.yt-thumb { width: 44px; height: 44px; border-radius: 6px; background: #1c1c1f; background-size: cover; background-position: center; flex-shrink: 0; }
.yt-meta { flex: 1; min-width: 0; overflow: hidden; }
.yt-title { font-size: 13px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.yt-sub { font-size: 11px; color: rgba(255,255,255,0.45); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 2px; }
.yt-track-count {
  font-size: 10px;
  color: rgba(255,255,255,0.35);
  margin-top: 2px;
}
.yt-controls { display: flex; align-items: center; gap: 4px; padding: 0 12px 12px; }
.yt-btn { background: none; border: none; color: #fff; cursor: pointer; display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; border-radius: 50%; opacity: 0.85; transition: opacity 0.15s ease, background 0.15s ease; }
.yt-btn:hover { opacity: 1; background: rgba(255,255,255,0.08); }
.yt-btn.yt-play { width: 36px; height: 36px; background: #fff; color: #0a0a0c; opacity: 1; }
.yt-btn.yt-play:hover { background: #e8e8e8; }
.yt-progress { flex: 1; height: 6px; background: rgba(255,255,255,0.12); border-radius: 2px; margin: 0 8px; position: relative; cursor: pointer; }
.yt-progress-fill { position: absolute; left: 0; top: 0; bottom: 0; width: 0%; background: #fff; border-radius: 2px; }
.yt-progress-handle {
  position: absolute;
  right: -5px;
  top: 50%;
  transform: translateY(-50%);
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,0.4);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.yt-progress:hover .yt-progress-handle,
.yt-progress-handle.dragging {
  opacity: 1;
}
.yt-volume { padding: 0 12px 12px; display: flex; align-items: center; gap: 8px; }
.yt-volume input[type="range"] { flex: 1; accent-color: #fff; }
.yt-mute-btn {
  background: none;
  border: none;
  color: rgba(255,255,255,0.6);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  transition: color 0.15s ease;
}
.yt-mute-btn:hover {
  color: #fff;
}

/* Playlist panel: js/yt-audio-widget.js toggles .yt-widget's own
   playlist-open class (via a click on .yt-thumb) and renders
   #ytPlaylist's own contents - see that file for both. */
.yt-thumb {
  cursor: pointer;
}
.yt-playlist {
  max-height: 0;
  opacity: 0;
  overflow-y: auto;
  pointer-events: none;
  overscroll-behavior: contain;
  border-top: 1px solid rgba(255,255,255,0.06);
  /* Bottom corners only - .yt-playlist is always the last child when
     open, so this is the widget's own bottom edge. border-radius here is
     mostly decorative, not a real clip: confirmed by direct testing (with
     playlist heights from 120px to 216px, with/without backdrop-filter,
     with clip-path swapped in for border-radius+overflow, with the
     scrolling layer force-promoted via translateZ/will-change - every
     combination left the same artifact) that Chromium does not reliably
     round off the scrolled-out content of an overflow-y:auto box, on
     EITHER this element or an ancestor's own overflow:hidden - only the
     flat rectangular edge is honored, so the next (should-be-hidden) row
     keeps poking a square corner past the curve here and at .yt-widget's
     matching 10px corner. mask-image below (a real per-pixel alpha
     composite, not a box clip) is what actually hides it - see there. */
  border-radius: 0 0 9px 9px;
  /* Real fix for the corner leak documented above: fades this element's
     own last ~40px to transparent, so whatever of the next row bleeds
     past the (non-clipping) border-radius fades out with it instead of
     showing as a hard square edge. Mask compositing doesn't share the
     same failure as the box clip above (confirmed by the same testing) -
     applies reliably even to the same overflow-y:auto scrolled content.
     40px (taller than one 40px row) rather than a thinner fade - tested
     down to 26px and a faint ghost of the leaking row still showed
     through at the very corner pixels; this height clears it fully. */
  -webkit-mask-image: linear-gradient(to top, transparent 0, #000 40px);
  mask-image: linear-gradient(to top, transparent 0, #000 40px);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
  transition: max-height 0.45s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.3s ease;
}
.yt-playlist.scrollbar-near {
  scrollbar-color: rgba(255,255,255,0.25) transparent;
}
.yt-playlist {
  cursor: grab;
}
.yt-playlist.grabbing {
  cursor: grabbing;
}
.yt-playlist::-webkit-scrollbar {
  width: 6px;
}
.yt-playlist::-webkit-scrollbar-thumb {
  background: transparent;
  border-radius: 3px;
}
.yt-playlist.scrollbar-near::-webkit-scrollbar-thumb {
  background: rgba(255,255,255,0.25);
}
.yt-playlist::-webkit-scrollbar-track {
  background: transparent;
}
.yt-widget.playlist-open .yt-playlist {
  max-height: 216px;
  opacity: 1;
  pointer-events: auto;
}
.yt-playlist-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  cursor: pointer;
}
.yt-playlist-item:hover {
  background: rgba(255,255,255,0.06);
}
.yt-playlist-item.active {
  background: rgba(255,255,255,0.1);
}
.yt-playlist-item img {
  width: 28px;
  height: 28px;
  border-radius: 4px;
  object-fit: cover;
  flex-shrink: 0;
  background: #1c1c1f;
}
.yt-playlist-item .ytp-title {
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
