/* ===========================================================================
   player-dock-v2.css - the SoundCloud-style docked bar, v2 for growth-tool-v2
   (the "our new ui/ux" direction, data-theme="midnight").

   PASS 2 - Derek 2026-09-18: "the album art is riding the bottom of the
   page, weird gaps... create something a lot better... allow people to sort
   by genre tags to customize it to their liking."

   THE ACTUAL BUG, diagnosed by DOM dump (not guessed): .fbpd genuinely is a
   direct child of <body> and position:fixed was computing correctly - the
   complaint was real but it was a DESIGN problem, not a broken-fixed-position
   bug. The bar sat flush at bottom:0 with only a 1px top border, so the
   34px artwork's own bottom edge landed 9px off the literal bottom of the
   browser window - "riding the bottom" is an accurate description of a bar
   with zero breathing room under it, on a page where every OTHER element
   (.q, .stat, .chart) is a floating card that never touches an edge.

   THE FIX IS STRUCTURAL, NOT COSMETIC: the bar is now a FLOATING ISLAND -
   inset on all four sides, rounded on all four corners - the same card
   language as everything else on the page, not a SoundCloud-style
   edge-glued strip. That is also why this pass reviewed against
   /high-end-visual-design: its literal mandates (Geist/Clash Display,
   rounded-[2rem] glass bezels, ambient glow shadows) are BANNED here per
   CLAUDE.md - this system already rejected that skill by name for exactly
   those collisions - but its underlying critique (don't let an element ride
   an edge with no spatial rhythm around it) was correct, and is answered
   with THIS page's own tokens: --card, --r-card, --hair, --card-shadow
   (none, midnight stays flat - no glow was added to satisfy the skill).

   WHAT ELSE CHANGED THIS PASS:
     - Artwork: 34px -> 44px (badge), 36px -> 40px (queue rows). At the old
       size "album art" undersold itself; at this size it reads as a real
       object, and --r-sm (12px) suits it better than --r-tile's 6px, which
       was tuned for a smaller unit.
     - Genre filter row: NEW. A row of chips at the top of the Next-up card,
       built from research.html's OWN .tag2 pattern (quiet fill at rest,
       lime .on state) rather than inventing a chip style - same recipe,
       copied because it already exists on this page's sibling view, and
       renamed .fbpd-tag to stay namespaced. The tags on the 9 seed tracks
       are PLACEHOLDER genre labels for this demo (see dock-v2.html) - real
       ones need to come from wherever the catalogue ends up living.
     - Everything from PASS 1 (--g accent, var(--mono)/var(--sans), var(--ease)
       motion, --rail-based left offset) is unchanged; see that history below.

   PASS 1 history, for what did NOT change this round:
     - Ground: rgba(9,9,9,.94) + blur(20px), .tabbar's own recipe.
     - Play button glyph #0d1400, matching .tabbar a.home's lime fill exactly.
     - Left offset reads --rail directly; dock.html's fit() only measures the
       dock's own height, because v2 has exactly one sidebar width to clear.
   PHONES ON since 2026-09-23, with a hide control (see the phone block at the end).
   =========================================================================== */

/* -- the original floating handle has no place here -- */
#fbmp { display: none !important; }

/* PASS 3 - Derek, with a screenshot of the scrolled page: "its weird when
   scrolling, it should be pinned to the bottom no space."

   The pass-2 floating island is what caused it, and reverted here. Two
   things made it wrong, not one:
   1. This project's OWN law, README's very first section: "edge to edge.
      No gutter, no panel, no seam" - applied to all three directions. A
      dock with a 20px gutter on three sides broke a rule already locked
      for this whole page, not just a taste call.
   2. The gutter is STATIC, but scrolling made it READ as a bug: the ground
      behind the floating bar is the same near-black as the page, so as
      content moved behind that dead 20px margin it looked like a seam
      opening and closing rather than a deliberate inset.
   Back to edge-to-edge, flush at bottom AND right, clearing only the rail
   on the left - the same geometry the live SaaS-panel dock and this page's
   own .tabbar both already use for a fixed bottom bar. Square corners,
   because a flush edge has nothing to round against; the Next-up drawer
   keeps ITS OWN --r-card rounding since that one is a genuine floating
   card, not an edge-glued bar. */
.fbpd {
  position: fixed; z-index: 120;
  left: var(--rail); right: 0; bottom: 0;
  background: rgba(9, 9, 9, .94);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  border-top: 1px solid var(--hair);
  box-sizing: border-box;
  --p: 0%;   /* the playhead, written by the dock's MutationObserver */
  transform: translateY(0);
  transition: transform 220ms var(--ease);
}
.fbpd * { box-sizing: border-box; }
.fbpd.is-away { transform: translateY(100%); }

.fbpd-in {
  position: relative;
  display: flex; align-items: center; gap: 18px;
  height: 64px; padding: 0 22px;
}

/* -- transport -------------------------------------------------------------
   Same two weights as before (.85 / .6); every control gets a quiet rounded
   fill on hover - v2's own "chips, toggles, segments" language (--fill-1 +
   --r-ctl) rather than a colour-only change. */
.fbpd-tr { display: flex; align-items: center; gap: 2px; flex: none; }

.fbpd-skip {
  width: 32px; height: 32px; padding: 0; border: 0; background: none;
  border-radius: var(--r-ctl, 6px);
  cursor: pointer; color: rgba(255,255,255,.85);
  display: flex; align-items: center; justify-content: center;
  transition: color .3s var(--ease), background-color .3s var(--ease);
}
.fbpd-skip:hover { color: #fff; background: var(--fill-1); }
.fbpd-skip svg { width: 20px; height: 20px; display: block; }

/* an accent circle with a dark glyph - #0d1400 is .tabbar a.home's exact
   fill. The one rounded-by-default control, except here nothing else is
   square either, so it reads as the loudest control, not an exception. */
.fbpd-play {
  width: 38px; height: 38px; margin: 0 4px; padding: 0; border: 0; cursor: pointer;
  border-radius: 50%;
  background: var(--g); color: #0d1400;
  display: flex; align-items: center; justify-content: center;
  transition: transform .3s var(--ease);
}
.fbpd-play:hover { transform: scale(1.06); }
.fbpd-play .tri, .fbpd-play .pause { width: 17px; height: 17px; display: block; }
.fbpd-play .pause { display: none; }
.fbmp-playing .fbpd-play .tri { display: none; }
.fbmp-playing .fbpd-play .pause { display: block; }

.fbpd-mode {
  width: 30px; height: 30px; padding: 0; border: 0; background: none;
  border-radius: var(--r-ctl, 6px);
  cursor: pointer; color: rgba(255,255,255,.6);
  display: flex; align-items: center; justify-content: center;
  transition: color .3s var(--ease), background-color .3s var(--ease);
}
.fbpd-mode svg { width: 20px; height: 20px; display: block; }
.fbpd-mode:hover { color: #fff; background: var(--fill-1); }
.fbpd-mode.is-on { color: var(--g); }

/* -- the timeline ------------------------------------------------------- */
.fbpd-seek { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 10px; }
.fbpd-t {
  flex: none; font-family: var(--mono); font-size: 10px; letter-spacing: .04em;
  color: var(--ink-3); font-variant-numeric: tabular-nums; min-width: 30px;
}
.fbpd-t.r { text-align: right; }

.fbpd-linewrap { position: relative; flex: 1 1 auto; min-width: 60px; display: flex; align-items: center; }

.fbpd-line {
  position: relative;
  flex: 1 1 auto; height: 16px; cursor: pointer;
  display: flex; align-items: center; touch-action: pan-y;
}
.fbpd-line::before {
  content: ''; position: absolute; left: 0; right: 0; top: 50%;
  transform: translateY(-50%); height: 4px; border-radius: 2px;
  background: linear-gradient(to right, #fff 0 var(--p, 0%), rgba(255,255,255,.14) var(--p, 0%) 100%);
}
.fbpd-seek:hover .fbpd-line::before,
.fbpd-line:focus-visible::before {
  background: linear-gradient(to right, var(--g) 0 var(--p, 0%), rgba(255,255,255,.14) var(--p, 0%) 100%);
}
.fbpd-line i { display: none; }

.fbpd-dot {
  position: absolute; top: 50%; left: var(--p, 0%);
  width: 10px; height: 10px; border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 2px var(--ground, #0a0a0a);
  transform: translate(-50%, -50%) scale(0);
  opacity: 0; pointer-events: none;
  transition: left 90ms linear, transform .3s var(--ease), opacity .3s var(--ease);
}
.fbpd-seek:hover .fbpd-dot,
.fbpd-line:focus-visible ~ .fbpd-dot { opacity: 1; transform: translate(-50%, -50%) scale(1); }

/* -- volume ---------------------------------------------------------------*/
.fbpd-vol { flex: none; display: flex; align-items: center; gap: 6px; }
.fbpd-ico {
  width: 30px; height: 30px; padding: 0; border: 0; background: none;
  border-radius: var(--r-ctl, 6px);
  cursor: pointer; color: rgba(255,255,255,.6); text-decoration: none;
  display: flex; align-items: center; justify-content: center;
  transition: color .3s var(--ease), background-color .3s var(--ease);
}
.fbpd-ico:hover { color: #fff; background: var(--fill-1); }
.fbpd-ico svg { width: 20px; height: 20px; display: block; }
.fbpd-vol .v-off { display: none; }
.fbpd.is-muted .fbpd-vol .v-on { display: none; }
.fbpd.is-muted .fbpd-vol .v-off { display: block; }
.fbpd.is-muted .fbpd-vol .fbpd-ico { color: var(--ink); }

.fbpd-volrange {
  -webkit-appearance: none; appearance: none;
  width: 0; opacity: 0; height: 3px; border-radius: 2px; margin: 0; padding: 0;
  background: linear-gradient(to right, var(--g) 0 var(--v, 100%), var(--fill-2) var(--v, 100%) 100%);
  cursor: pointer; transition: width .3s var(--ease), opacity .3s var(--ease);
}
.fbpd-vol:hover .fbpd-volrange,
.fbpd-volrange:focus-visible { width: 68px; opacity: 1; }
.fbpd-volrange::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 9px; height: 9px; border-radius: 50%; border: 0;
  background: var(--ink); cursor: pointer;
}
.fbpd-volrange::-moz-range-thumb {
  width: 9px; height: 9px; border-radius: 50%; border: 0;
  background: var(--ink); cursor: pointer;
}

/* -- the sound badge --------------------------------------------------------
   Behind a vertical rule and hard right. Artwork bumped 34 -> 44px - at the
   old size the phrase "album art" oversold what was on screen; --r-sm suits
   this size better than --r-tile, which was tuned for a smaller unit. */
.fbpd-badge {
  flex: none; display: flex; align-items: center; gap: 12px;
  padding-left: 18px; border-left: 1px solid var(--hair);
  align-self: stretch;
}
.fbpd-art {
  width: 44px; height: 44px; flex: none; object-fit: cover; display: block;
  border-radius: var(--r-sm, 12px);
  background: var(--card); border: 1px solid var(--hair);
}
.fbpd-meta { width: 156px; min-width: 0; }
.fbpd-artist {
  font-family: var(--mono); font-size: 9px; letter-spacing: .1em; text-transform: uppercase;
  line-height: 1.45; color: var(--ink-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.fbpd-title {
  font-family: var(--sans); font-weight: 700;
  font-size: 12px; line-height: 1.4; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.fbpd-like { border-radius: var(--r-ctl, 6px); }
.fbpd-like:hover { color: var(--g); background: var(--fill-1); }
.fbpd.is-q .fbpd-q { color: var(--g); background: var(--fill-1); }

/* -- Next up -----------------------------------------------------------
   A floating card in the SAME family as every other card on this page:
   --card background, --r-card radius, --card-shadow (none in midnight).
   Anchors above the queue button, sized to its content, no scroller. */
.fbpd-drawer {
  display: none;
  position: absolute; right: 0; bottom: calc(100% + 14px);
  /* PASS 3: the dock lost its 20px side insets, so this only has to clear
     .fbpd-in's own 22px padding on each side now, not the dock's too. */
  width: min(600px, calc(100vw - var(--rail) - 44px));
  background: var(--card);
  border: 1px solid var(--hair);
  border-radius: var(--r-card, 20px);
  box-shadow: var(--card-shadow);
  max-height: calc(100vh - 140px); overflow: auto;
}
.fbpd.is-q .fbpd-drawer { display: block; }

.fbpd-qhead {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 18px 14px;
  border-bottom: 1px solid var(--hair);
}
.fbpd-qtitle { font-family: var(--sans); font-weight: 700; font-size: 14px; color: var(--ink); }
.fbpd-qclose {
  width: 28px; height: 28px; padding: 0; border: 0; border-radius: var(--r-ctl, 6px);
  background: none; cursor: pointer; color: var(--ink-3);
  display: flex; align-items: center; justify-content: center;
  transition: color .3s var(--ease), background-color .3s var(--ease);
}
.fbpd-qclose:hover { color: var(--ink); background: var(--fill-1); }
.fbpd-qclose svg { width: 15px; height: 15px; }

/* -- genre filter row --------------------------------------------------
   NEW. research.html's own .tag2 recipe, copied and namespaced rather
   than reinvented: quiet fill at rest, lime .on when active. "All" is the
   default and clears any active genre. PLACEHOLDER genre labels - see
   dock-v2.html's TRACK_GENRES map. */
.fbpd-qtags {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 12px 18px; border-bottom: 1px solid var(--hair);
}
.fbpd-tag {
  padding: 5px 11px; border: 0; border-radius: 999px;
  background: var(--fill-1); font-family: var(--mono); font-size: 10px;
  letter-spacing: .09em; text-transform: uppercase; color: var(--ink-3);
  cursor: pointer; transition: color .3s var(--ease), background-color .3s var(--ease);
}
.fbpd-tag:hover { color: var(--ink-2); background: var(--fill-2); }
.fbpd-tag.on { color: var(--g); background: var(--g-soft); }

.fbpd-drawer #fbmp-list { display: block; max-height: none; margin: 0; padding: 6px 8px 8px; }

.fbpd-drawer .fbmp-item {
  position: relative;
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 8px 10px; border: 0; border-radius: var(--r-sm, 12px);
  background: none; cursor: pointer; text-align: left;
  font-family: var(--sans); color: var(--ink-2);
  transition: background-color .3s var(--ease), opacity .3s var(--ease), max-height .35s var(--ease);
}
.fbpd-drawer .fbmp-item:hover { background: var(--fill-1); }
/* filtered out by a genre chip - collapsed, not just hidden, so the card
   shrinks to its content instead of leaving a hole. */
.fbpd-drawer .fbmp-item[data-hide] {
  display: none;
}
.fbpd-drawer .fbmp-item .no { display: none; }
.fbpd-rowart {
  width: 40px; height: 40px; flex: none; object-fit: cover; display: block;
  border-radius: var(--r-sm, 12px);
  background: var(--card-up); border: 1px solid var(--hair);
}
.fbpd-drawer .fbmp-item .nm { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.fbpd-drawer .fbmp-item .ar {
  order: 1; display: block;
  font-family: var(--mono); font-size: 9px; letter-spacing: .1em; text-transform: uppercase;
  line-height: 1.5; color: var(--ink-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.fbpd-drawer .fbmp-item .t {
  order: 2; display: block;
  font-size: 12.5px; font-weight: 600; line-height: 1.4; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.fbpd-drawer .fbmp-item .dur {
  flex: none; font-family: var(--mono); font-size: 9.5px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
/* the genre tag riding the duration column - quiet, mono, no pill (the
   queue already has enough pills in the filter row above it). */
.fbpd-rowtag {
  flex: none; font-family: var(--mono); font-size: 8.5px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-3); margin-right: 4px;
}

.fbpd-drawer .fbmp-item[aria-current="true"] { background: var(--fill-1); }
.fbpd-drawer .fbmp-item[aria-current="true"] .t { color: var(--g); }
.fbmp-playing .fbpd-drawer .fbmp-item[aria-current="true"] .fbpd-rowart { opacity: .3; }
.fbmp-playing .fbpd-drawer .fbmp-item[aria-current="true"]::before {
  content: ''; position: absolute; left: 31px; top: 50%;
  transform: translate(-50%, -50%);
  width: 11px; height: 12px;
  background: linear-gradient(90deg, var(--g) 0 4px, transparent 4px 7px, var(--g) 7px 11px);
  pointer-events: none;
}

/* -- the page has to give the dock its height back -------------------------
   --fbpd-h is the dock's own measured height (dock-v2.html's fit()) - no
   extra gap to fold in now that PASS 3 put it back edge-to-edge. 65px
   fallback is the 64px bar plus its 1px top border, for the moment before
   the script runs. */
body.has-fbpd { padding-bottom: var(--fbpd-h, 65px); }

/* -- the rail's badge row lines up with the dock ---------------------------
   Derek 2026-09-23: "the divider on top should flow perfectly with the media
   player". The side-foot's border-top and the dock's border-top must be ONE
   line across the whole window. Its height used to fall out of its padding +
   the badge's text leading (~69px, and more on pages without v2-sc.css), so
   the rule sat a few px above the dock's. Pin it to the dock's own measured
   height instead, border included, and centre the badge in it. */
body.has-fbpd .side-foot {
  box-sizing: border-box; height: var(--fbpd-h, 65px);
  border-top: 1px solid var(--hair);
  display: flex; align-items: center;
  padding-top: 0; padding-bottom: 0;
}
body.has-fbpd .side-foot .badge { flex: 1 1 auto; min-width: 0; }

@media (max-width: 1100px) {
  .fbpd-in { gap: 14px; }
  .fbpd-meta { width: 120px; }
}
@media (max-width: 900px) {
  .fbpd-mode, .fbpd-vol { display: none; }
  .fbpd-meta { width: 108px; }
}

/* -- hide control + the pill: phone only, nothing of it exists above 700px -- */
.fbpd-hide, .fbpd-pill { display: none; }

/* -- phone ---------------------------------------------------------------
   Derek 2026-09-23: on for phones, with a HIDE option. The bar sits ON TOP
   of v2-shell.js's .tabbar (--fbpd-b is its measured height, see fit()),
   one row: art · title · prev/play/next · queue · hide. The seek line gives
   way to a 2px progress rule along the top edge. z-index 34 puts it one
   under the tabbar's 35, so hiding slides it down BEHIND the tab bar
   rather than over it. */
@media (max-width: 700px) {
  .fbpd {
    left: 0; bottom: var(--fbpd-b, 0px); z-index: 34;
    transition: transform 220ms var(--ease), visibility 0s linear 0s;
  }
  .fbpd::before {
    content: ''; position: absolute; left: 0; top: -1px; height: 2px;
    width: var(--p, 0%); background: var(--g); pointer-events: none;
    transition: width 90ms linear;
  }
  .fbpd-in { height: 56px; padding: 0 6px 0 12px; gap: 8px; }
  .fbpd-seek, .fbpd-like, .fbpd-vol, .fbpd-mode { display: none; }
  /* dissolve the badge so its children can be sequenced with the transport */
  .fbpd-badge { display: contents; }
  .fbpd .fbpd-art { order: -3; width: 40px; height: 40px; border-radius: var(--r-ctl, 6px); }
  .fbpd-meta { order: -2; flex: 1 1 auto; width: auto; min-width: 0; }
  .fbpd-tr { order: 1; }
  .fbpd-play { width: 36px; height: 36px; margin: 0 2px; }
  .fbpd-q { order: 2; }
  .fbpd-hide { order: 3; display: flex; }
  .fbpd-drawer {
    left: 12px; right: 12px; width: auto;
    max-height: calc(100vh - var(--fbpd-b, 0px) - 56px - 48px);
  }
  .fbpd-qtags { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; }
  .fbpd-qtags::-webkit-scrollbar { display: none; }
  .fbpd-tag { flex: none; }

  /* hidden: slid away, out of the tab order once it has gone */
  body.fbpd-hid .fbpd {
    transform: translateY(calc(100% + 2px));
    visibility: hidden;
    transition: transform 220ms var(--ease), visibility 0s linear 220ms;
  }
  body.has-fbpd.fbpd-hid { padding-bottom: 0; }

  /* the way back: bottom right, clear of the tab bar */
  body.fbpd-hid .fbpd-pill {
    display: flex; align-items: center; gap: 8px;
    position: fixed; z-index: 34;
    right: 12px; bottom: calc(var(--fbpd-b, 0px) + 12px);
    height: 34px; padding: 0 14px 0 12px; margin: 0;
    border: 1px solid var(--hair); border-radius: 999px;
    background: rgba(9, 9, 9, .94);
    backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
    font-family: var(--mono); font-size: 10px; letter-spacing: .1em;
    text-transform: uppercase; color: var(--ink-2); cursor: pointer;
  }
  .fbpd-eq { display: flex; align-items: flex-end; gap: 2px; height: 11px; }
  .fbpd-eq i { width: 2px; background: var(--g); border-radius: 1px; }
  .fbpd-eq i:nth-child(1) { height: 5px; }
  .fbpd-eq i:nth-child(2) { height: 11px; }
  .fbpd-eq i:nth-child(3) { height: 7px; }
  .fbmp-playing .fbpd-eq i { animation: fbpd-eq .9s ease-in-out infinite alternate; }
  .fbmp-playing .fbpd-eq i:nth-child(2) { animation-delay: -.3s; }
  .fbmp-playing .fbpd-eq i:nth-child(3) { animation-delay: -.6s; }
}
@keyframes fbpd-eq { from { height: 3px; } to { height: 11px; } }

@media (prefers-reduced-motion: reduce) {
  .fbpd, .fbpd-play, .fbpd-dot, .fbpd-line i, .fbpd-volrange { transition: none; }
  .fbpd-eq i { animation: none !important; }
}
