/* POST PLAYER v2 (2026-11-05, Rob approved mock 1, docs/feed-player-mocks-20261105.html): the glass dock for every post video in the
   fullscreen viewer (.pfeed). One dock at the bottom of the viewer's chrome layer (the same layer as the old .vctrl, under the
   .pfeed-bar header): the song row (when the post has an Apple Music preview), the gold scrubber with a drag thumbnail, the times,
   loop / play / sound. Controls fade after 2.5 s (media.pp2-off), a tap on the picture toggles them, hidden mode keeps a 3 px line.
   The dock's dress is lifted from assets/livereplay2.css (the glass .lr2-ctl, the gold .lr2-fill, the .lr2-knob, the .lr2-tip):
   the shared tokens live here so both players read as one family. Mounted by assets/player2.js; k/v post_player_v2 (default on). */
:root{--pp2-gold:#f5c518;--pp2-gold2:#e2a63c;--pp2-ink:#fff;--pp2-mut:rgba(255,255,255,.72);
  --pp2-glass:rgba(30,28,34,.5);--pp2-line:rgba(255,255,255,.14);--pp2-dock-h:96px}
/* the old transport stands down inside the viewer while v2 is mounted; the post actions pfMoveActs folds into .vc-row stay (a rail above the dock) */
.pfeed .pp2-on > .vctrl > .vc-seek,.pfeed .pp2-on > .vctrl .vc-btn,.pfeed .pp2-on > .vctrl .vc-flex,
.pfeed .pp2-on > .vc-mini,.pfeed .pp2-on > .vc-sound{display:none!important}
.pfeed .pp2-on > .vctrl > .vc-tl{display:none!important}
.pfeed .pp2-on > .vctrl .vc-tcur,.pfeed .pp2-on > .vctrl .vc-tdur{display:none!important}
.pfeed .pp2-on .vctrl .vc-sound{display:none!important}   /* the speaker folded into the row (pf-inrow): the dock owns sound (it still clicks this button) */
/* THE ACTION RAIL (coordinator 2026-11-05): gift / comment / repost / share stand in a vertical rail on the right edge, above the dock */
.pfeed .post .pp2-on.has-vctrl > .vctrl,.pfeed .pp2-on > .vctrl{left:auto!important;right:max(12px,calc((100% - 760px) / 2 + 12px))!important;bottom:calc(var(--pp2-dock-h) + 4px)!important;width:auto!important;padding:0!important;background:none}
.pfeed .pp2-on > .vctrl > .vc-row{flex-direction:column;align-items:center;gap:8px;margin:0}
.pfeed .post .pp2-on > .vctrl .vc-row .pf-act{width:36px;height:36px;background:rgba(30,28,34,.5);border:1px solid rgba(255,255,255,.16);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px)}
/* the old hands-free rail (loop / pause / 5 s) stands down while the dock is up: loop + play live in the dock, 5 s is the double-tap */
.pfeed:has(.pp2-on) .pf-hf-dock,.pfeed:has(.pp2-on) .pf-hf-rep,.pfeed:has(.pp2-on) .pf-hf-rate,.pfeed:has(.pp2-on) .pf-hf-speeds,.pfeed:has(.pp2-on) .pf-hf-rep-tag{display:none!important}
/* the caption + the "More from" chip sit left of the rail */
.pfeed .post:has(.pp2-on) .body,.pfeed .post:has(.pp2-on) .mf-wrap,.pfeed .post:has(.pp2-on) .mf-wrap > *{max-width:calc(100% - 68px)!important;box-sizing:border-box}
/* the caption clears the dock by 8px (--pp2-dock-h = the dock + its 8px inset + 8px air); the action rail is to its right (the viewer reserved 71px for the old bar; the dock is taller and the player2.js sets --pp2-dock-h on the post too) */
html .pfeed .post:has(.media video):has(.pp2-on) .post-main{padding-bottom:calc(var(--pp2-dock-h,111px) + env(safe-area-inset-bottom))}
html.pf-e2e .pfeed .post:has(.media video):has(.pp2-on) .post-main{padding-bottom:calc(var(--pp2-dock-h,111px) + var(--pf-sb,0px))}   /* the edge-to-edge viewer measures its own safe area (--pf-sb); html. matches the specificity of rova.css's pf-e2e rule */
.pfeed .pp2-on > .vctrl::before{display:none}
.pfeed .pp2-on > .vctrl > .vc-row{justify-content:flex-end;gap:8px}
/* the dock */
.pp2{position:absolute;left:8px;right:8px;bottom:8px;max-width:760px;margin:0 auto;z-index:7;display:flex;flex-direction:column;gap:6px;padding:10px 10px 8px;border-radius:22px;
  background:var(--pp2-glass);border:1px solid var(--pp2-line);border-top-color:rgba(255,255,255,.26);box-shadow:0 8px 30px rgba(0,0,0,.35);
  -webkit-backdrop-filter:blur(22px) saturate(160%);backdrop-filter:blur(22px) saturate(160%);
  color:var(--pp2-ink);font:500 12px/1.2 system-ui,-apple-system,"Segoe UI",sans-serif;
  opacity:1;transform:none;transition:opacity .22s ease,transform .22s ease;touch-action:none;-webkit-user-select:none;user-select:none}
.pp2 *{box-sizing:border-box}
/* hidden mode (pp2-off): dock + the action rail go, the 3 px line stays */
.pfeed .pp2-off > .pp2,.pfeed .pp2-off > .vctrl{opacity:0;pointer-events:none;transform:translateY(6px)}
.pfeed .pp2-off > .vctrl{transition:opacity .22s ease,transform .22s ease}
.pp2-line{position:absolute;left:0;right:0;bottom:0;height:3px;z-index:7;background:rgba(255,255,255,.2);opacity:0;transition:opacity .22s ease;pointer-events:none}
.pp2-line > i{position:absolute;left:0;top:0;bottom:0;width:0;background:var(--pp2-gold)}
.pfeed .pp2-off > .pp2-line{opacity:1}
/* the viewer's own idle chrome (pfeed-idle) also hides the dock; the line comes up in its place */
.pfeed.pfeed-idle .pp2-on > .pp2{opacity:0;pointer-events:none;transform:translateY(6px)}
.pfeed.pfeed-idle .pp2-on > .pp2-line{opacity:1}
/* song row */
.pp2-song{display:flex;align-items:center;gap:8px;padding:5px 6px 5px 5px;border-radius:14px;background:rgba(255,255,255,.08)}
.pp2-song[hidden]{display:none}
.pp2-art{width:30px;height:30px;flex:none;border-radius:7px;background:#e9e6e0 center/cover no-repeat;object-fit:cover}
.pp2-st{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.pp2-st b{display:block;font-size:11.5px;font-weight:650;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pp2-st small{display:block;font-size:10.5px;color:var(--pp2-mut);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* scrubber (the live-replay bar, trimmed) */
.pp2-bar{position:relative;height:22px;margin:0 4px;cursor:pointer;outline:none;border-radius:6px;touch-action:none}
.pp2-bar:focus-visible{box-shadow:0 0 0 2px var(--pp2-gold)}
.pp2-track{position:absolute;left:0;right:0;top:50%;height:4px;margin-top:-2px;border-radius:2px;background:rgba(255,255,255,.25);transition:height .15s ease,margin-top .15s ease}
.pp2-bar:hover .pp2-track,.pp2-scrub .pp2-track{height:6px;margin-top:-3px}
.pp2-buf,.pp2-fill{position:absolute;left:0;top:0;bottom:0;width:100%;border-radius:inherit;transform-origin:0 50%;transform:scaleX(0)}
.pp2-buf{background:rgba(255,255,255,.18)}
.pp2-fill{background:linear-gradient(90deg,var(--pp2-gold2),var(--pp2-gold))}
.pp2-knob{position:absolute;top:50%;left:0;width:14px;height:14px;margin:-7px 0 0 -7px;border-radius:50%;background:#fff;box-shadow:0 0 0 4px rgba(232,194,90,.35),0 1px 6px rgba(0,0,0,.5);transform:scale(.85);transition:transform .15s ease}
.pp2-bar:hover .pp2-knob,.pp2-scrub .pp2-knob{transform:scale(1)}
/* THE DRAG PREVIEW (2026-11-06, Rob: "a small, clean, glassy preview of the part I'm dragging to"): a frosted bubble centred over the thumb (a child of the media beside the dock),
   8px above the bar, clamped inside it. Frame = --pp2-tw x --pp2-th (player2.js sizeTip: 144 wide, 120 for a portrait clip, the clip's aspect
   clamped 3:4..16:9), the time under it. No border, hairline or top highlight. The frame is the tip's own <canvas> (a hidden twin <video>
   drawn into it), with the poster as a CSS background until the first frame lands: never an <img>, which inside .post .media picks up the
   feed's media-image sizing / cover-zoom / Ken Burns (the "zoomed thumbnail"). Selectors are pinned under .pfeed .post .media so no
   viewer media rule can size or transform it. */
.pp2-tip{position:absolute;bottom:130px;left:0;z-index:9;display:flex;flex-direction:column;align-items:center;gap:4px;padding:4px 4px 5px;border-radius:14px;
  background:rgba(28,26,32,.42);border:0;outline:0;box-shadow:0 10px 28px rgba(0,0,0,.32);
  -webkit-backdrop-filter:blur(18px) saturate(160%);backdrop-filter:blur(18px) saturate(160%);
  pointer-events:none;visibility:hidden;opacity:0;transform:translateX(-50%) translateY(4px) scale(.94);transform-origin:50% 100%;
  transition:opacity .12s ease,transform .12s ease,visibility 0s linear .12s}
.pp2-scrub .pp2-tip{visibility:visible;opacity:1;transform:translateX(-50%);transition:opacity .12s ease,transform .12s ease,visibility 0s}
.pfeed .post .media > .pp2-tip > .pp2-tip-i,.pp2-tip > .pp2-tip-i{position:relative;display:block;width:var(--pp2-tw,144px);height:var(--pp2-th,81px);border-radius:10px;overflow:hidden;
  background:#111 center/cover no-repeat;border:0;transform:none;animation:none}
.pfeed .post .media > .pp2-tip > .pp2-tip-i > canvas,.pp2-tip > .pp2-tip-i > canvas{position:absolute;left:0;top:0;display:block;width:100% !important;height:100% !important;max-width:none !important;max-height:none !important;
  margin:0;border:0;border-radius:0;opacity:0;transform:none !important;animation:none !important}
.pp2-tip > .pp2-tip-i.pp2-has > canvas{opacity:1}
.pp2-tip-t{font:600 12px/1.2 system-ui,-apple-system,"Segoe UI",sans-serif;font-variant-numeric:tabular-nums;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.45)}
@media (prefers-reduced-motion:reduce){.pp2-tip,.pp2-scrub .pp2-tip{transition:none;transform:translateX(-50%)}}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){.pp2-tip{background:rgba(20,18,24,.88)}}
/* the row */
.pp2-row{display:flex;align-items:center;gap:8px;min-height:32px}
.pp2-t{font-variant-numeric:tabular-nums;color:var(--pp2-mut);font-size:11.5px;min-width:34px}
.pp2-t.pp2-dur{text-align:right}
.pp2-sp{flex:1}
.pp2-b{position:relative;display:inline-grid;place-items:center;flex:none;width:32px;height:32px;padding:0;border:0;border-radius:50%;background:rgba(255,255,255,.1);color:var(--pp2-ink);cursor:pointer;
  -webkit-tap-highlight-color:transparent;transition:background .15s ease,transform .1s ease}
.pp2-b:hover{background:rgba(255,255,255,.18)}
.pp2-b:active{transform:scale(.92)}
.pp2-b:focus-visible{outline:2px solid var(--pp2-gold);outline-offset:1px}
.pp2-b svg{width:17px;height:17px;display:block}
.pp2-b.pp2-play{width:36px;height:36px;background:var(--pp2-gold);color:#141006}
.pp2-b.pp2-play svg{width:20px;height:20px}
.pp2-b.pp2-play:hover{background:#ffd43a}
.pp2-b[aria-pressed="true"]{color:var(--pp2-gold);background:rgba(245,197,24,.16)}
.pp2-b.pp2-sb{width:28px;height:28px}
/* the skip glyphs (double-tap a side) */
.pp2-skip{position:absolute;top:50%;width:64px;height:64px;margin-top:-32px;border-radius:50%;z-index:8;display:grid;place-items:center;pointer-events:none;
  background:rgba(20,18,24,.55);border:1px solid rgba(255,255,255,.2);color:#fff;font:700 15px/1 system-ui,-apple-system,"Segoe UI",sans-serif;font-variant-numeric:tabular-nums;
  opacity:0;transform:scale(.7);transition:opacity .18s ease,transform .18s ease}
.pp2-skip.pp2-l{left:12%}.pp2-skip.pp2-r{right:12%}
.pp2-skip.pp2-in{opacity:1;transform:scale(1)}
@media (max-width:420px){.pp2{left:6px;right:6px;bottom:6px;padding:8px 8px 7px}.pp2-b{width:30px;height:30px}.pp2-b.pp2-play{width:34px;height:34px}}
@media (prefers-reduced-motion:reduce){.pp2,.pp2-skip,.pfeed .pp2-off > .vctrl,.pp2-line{transition:none}}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){.pp2{background:rgba(20,18,24,.9)}}
/* WIDE SCREENS (>= 1000px): rova.css sizes the caption column itself (width:min(760px, ...), max-width:none !important), so the rail's 68px is taken off the WIDTH there; same specificity, later, wins */
@media (min-width:1000px){html body .pfeed.pfeed.pfeed .post:has(.pp2-on) .post-main.post-main.post-main > :is(.body,.mf-wrap){width:min(624px,calc(100% - 136px))!important}}

/* 2026-11-05 QA (Rob, /p/60577 in full screen: "the apple music in front of their content"): the dock's song artwork inherited the feed's
   `.post .media img{width:100%;height:clamp(...)}` and drew at 727px over the video. Pin it to the 30px chip at a higher specificity. */
.post .media .pp2 img.pp2-art,.pfeed .post .media .pp2 img.pp2-art{width:30px !important;height:30px !important;max-width:30px !important;min-height:0 !important;flex:none;border-radius:7px;object-fit:cover;animation:none !important;transform:none !important}

/* 2026-11-05 QA (Rob: "incomplete border radius on some panels", the rail over the dock): the action buttons go back to the APPROVED viewer
   dock's horizontal row (Nov 4 mock) instead of a vertical rail. Bottom to top: the player dock (scrubber), the button row, the glass dock
   (song / caption / comments, one block, one width), the "More from" chip. Nothing overlaps. */
html body .pfeed.pfeed .post .media.pp2-on.has-vctrl > .vctrl,html body .pfeed.pfeed .post .media.pp2-on > .vctrl{
  left:0 !important;right:0 !important;width:min(760px,calc(100% - 16px)) !important;margin:0 auto !important;bottom:calc(var(--pp2-dock-h,96px) + 2px) !important;padding:0 4px !important}
html body .pfeed.pfeed .post .media.pp2-on > .vctrl > .vc-row{flex-direction:row !important;justify-content:flex-end !important;align-items:center;gap:8px !important}
html body .pfeed.pfeed .post:has(.pp2-on) .post-main > :is(.body,.mf-wrap),html body .pfeed.pfeed .post:has(.pp2-on) .post-main > .mf-wrap > *{max-width:none !important}
html body .pfeed.pfeed .post:has(.media video):has(.pp2-on) .post-main.post-main{padding-bottom:calc(var(--pp2-dock-h,96px) + 54px + env(safe-area-inset-bottom)) !important}
html.pf-e2e body .pfeed.pfeed .post:has(.media video):has(.pp2-on) .post-main.post-main{padding-bottom:calc(var(--pp2-dock-h,96px) + 54px + var(--pf-sb,0px)) !important}
@media (min-width:1000px){
  html body .pfeed.pfeed.pfeed .post:has(.pp2-on) .post-main.post-main.post-main > :is(.body,.embed-music,.croller,.mf-wrap){width:min(760px, calc(100% - var(--pf-gut-l) - var(--pf-gut-r))) !important}
}
/* 2026-11-05 QA: the old seek bar is nested inside the row (the direct-child rule missed it); the song lives ONCE in the viewer, on the glass dock's
   Apple Music card, so the player dock drops its own song row there. */
html body .pfeed .pp2-on .vctrl .vc-seek,html body .pfeed .pp2-on .vctrl .vc-tl{display:none !important}
html body .pfeed .post:has(.post-main > .embed-music) .pp2 .pp2-song{display:none !important}
/* 2026-11-05 QA (Rob: "when the video scrubber disappears it should slide down to not leave blank space"): when the dock fades (pp2-off), the button
   row and the glass dock above it glide down into its place (same 220 ms curve); when it comes back they glide up again. Only the whole-chrome
   idle (.pfeed-idle) hides the buttons. */
html body .pfeed.pfeed .post .media.pp2-on > .vctrl{transition:bottom .24s cubic-bezier(.2,.8,.2,1),opacity .22s ease,transform .22s ease}
html body .pfeed.pfeed .post .post-main.post-main{transition:padding-bottom .24s cubic-bezier(.2,.8,.2,1)}
html body .pfeed.pfeed:not(.pfeed-idle) .post .media.pp2-on.pp2-off > .vctrl{opacity:1 !important;pointer-events:auto !important;transform:none !important;bottom:10px !important}
html body .pfeed.pfeed .post:has(.media video):has(.pp2-off) .post-main.post-main{padding-bottom:calc(58px + env(safe-area-inset-bottom)) !important}
html.pf-e2e body .pfeed.pfeed .post:has(.media video):has(.pp2-off) .post-main.post-main{padding-bottom:calc(58px + var(--pf-sb,0px)) !important}
/* 2026-11-06 (Rob: "Don't like the vertical buttons ... move them back to the bottom"): a CAROUSEL's pinned bar (.pf-cbar, not .media) carries pp2-on
   too and missed the 11-05 revert above, so galleries still stood the buttons up in a rail. Every pp2 host gets the horizontal row above the dock. */
html body .pfeed.pfeed .post .pf-cbar.pp2-on > .vctrl{left:0 !important;right:0 !important;width:min(760px,calc(100% - 16px)) !important;margin:0 auto !important;bottom:calc(var(--pp2-dock-h,96px) + 2px) !important;padding:0 4px !important}
html body .pfeed.pfeed .post .pf-cbar.pp2-on > .vctrl > .vc-row{flex-direction:row !important;justify-content:flex-end !important;align-items:center;gap:8px !important}
/* NO PLAYER ON A PHOTO SLIDE (Rob 2026-11-06: "this is a photo so why does it have a progress bar like its a video"): in a gallery the video dock
   (scrubber, times, loop / play / sound) shows only while the CURRENT slide is a video; on a photo slide it is gone (the song card keeps its own bar). */
html body .pfeed .post .media.carousel:has(.cslide.cs-cur):not(:has(.cslide.cs-cur video)) .pp2,
html body .pfeed .post .media.carousel:has(.cslide.cs-cur):not(:has(.cslide.cs-cur video)) .pp2-line{display:none !important}
/* 2026-11-06 (Rob, @khanyi "Dump" 17-slide carousel /p/61369): "the repeat button ... doesn't accept my clicks and the play nor sound buttons
   work, they just make my mouse into a magnifying glass". A carousel's dock lives in the pinned .pf-cbar, which rova.css makes
   pointer-events:none (only its .vctrl is re-enabled), so the dock inherited none and every click fell through to the slide's <video>
   (cursor:zoom-in). The dock takes its own clicks wherever it is mounted, unless it is faded (pp2-off) or the viewer is idle. */
html body .pfeed .post .pp2-on:not(.pp2-off) > .pp2{pointer-events:auto;cursor:default}
html body .pfeed.pfeed-idle .post .pp2-on > .pp2{pointer-events:none}
html body .pfeed .post .pp2-on > .pp2 :is(.pp2-b,.pp2-bar){cursor:pointer}
/* PHOTO SLIDE OF A MIXED CAROUSEL (Rob 2026-11-06): the caption / ticker block and the action row sat high on a photo slide, still riding over a
   dock that is not there (the .pf-cbar keeps pp2-on once a video slide mounted it, and `:has(.media video)` is true for any carousel holding a
   video). Keyed to the CURRENT slide: a photo slide gets the photo layout (the action row on the bottom inset, the block 47px above it, as a
   photo post); a video slide keeps the dock rules above (dock shown: above the dock; dock faded: pp2-off's glide down). */
html body .pfeed.pfeed .post:has(.media.carousel .cslide.cs-cur):not(:has(.cslide.cs-cur video)) .post-main.post-main{padding-bottom:calc(47px + env(safe-area-inset-bottom)) !important}
html.pf-e2e body .pfeed.pfeed .post:has(.media.carousel .cslide.cs-cur):not(:has(.cslide.cs-cur video)) .post-main.post-main{padding-bottom:calc(47px + var(--pf-sb,0px)) !important}
html body .pfeed.pfeed .post .media.carousel:has(.cslide.cs-cur):not(:has(.cslide.cs-cur video)) > .pf-cbar.pp2-on > .vctrl{bottom:0 !important;padding:0 10px calc(9px + env(safe-area-inset-bottom)) !important}
/* the ticker's expand chevron (.cr-go): its right margin matches the avatar's left inset (7px measured at 1440 and 1900; the pill's 3px end
   padding left the disc 4px off the edge). The disc's 1px border sits inside, so 6px of padding = a 7px gap. */
html body .pfeed .post .post-main > .croller{padding-right:6px}
/* a gallery's faded dock: its pinned bar's button row glides down with the block (the .media rules above never matched .pf-cbar, so on a video
   slide the row stayed up at the dock height while the block slid under it) */
html body .pfeed.pfeed .post .media.carousel > .pf-cbar.pp2-on > .vctrl{transition:bottom .24s cubic-bezier(.2,.8,.2,1),opacity .22s ease,transform .22s ease}
html body .pfeed.pfeed:not(.pfeed-idle) .post .media.carousel > .pf-cbar.pp2-on.pp2-off > .vctrl{opacity:1 !important;pointer-events:auto !important;transform:none !important;bottom:10px !important}
@media (prefers-reduced-motion:reduce){html body .pfeed.pfeed .post .media.carousel > .pf-cbar.pp2-on > .vctrl,html body .pfeed.pfeed .post .post-main.post-main{transition:none}}
