/* Custom video player. Sits on black regardless of theme — the accent colour is
   the only thing that follows the palette, so the picture is never competing
   with the UI. Everything fades out while playing and comes back on intent. */

.vp {
  position: relative;
  background: #000;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  line-height: 0;
  --vp-fg: #fff;
  --vp-dim: rgba(255, 255, 255, .62);
}
.vp video {
  display: block;
  width: 100%;
  max-height: min(78vh, 900px);
  object-fit: contain;
  background: #000;
}
.vp.is-idle { cursor: none; }

/* A whisper of gradient so white controls stay legible on a bright frame. */
.vp-shade {
  position: absolute; inset: auto 0 0 0; height: 42%;
  background: linear-gradient(transparent, rgba(0, 0, 0, .72));
  opacity: 0; transition: opacity .25s ease;
  pointer-events: none;
}
.vp.show-ui .vp-shade { opacity: 1; }

/* ---------------------------------------------------------- centre play -- */

.vp-big {
  position: absolute; left: 50%; top: 50%;
  width: 76px; height: 76px; margin: -38px 0 0 -38px;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: rgba(12, 12, 18, .55);
  backdrop-filter: blur(6px);
  color: #fff; cursor: pointer;
  opacity: 0; transform: scale(.86);
  transition: opacity .2s ease, transform .2s ease, background .2s;
  pointer-events: none;
}
.vp[data-state="paused"] .vp-big { opacity: 1; transform: scale(1); pointer-events: auto; }
.vp-big:hover { background: rgba(12, 12, 18, .75); }
.vp-big svg { width: 30px; height: 30px; margin-left: 3px; }

/* ------------------------------------------------------------- spinner --- */

.vp-spinner {
  position: absolute; left: 50%; top: 50%; width: 42px; height: 42px;
  margin: -21px 0 0 -21px;
  border: 3px solid rgba(255, 255, 255, .22);
  border-top-color: #fff; border-radius: 50%;
  animation: vp-spin .7s linear infinite;
  pointer-events: none;
}
@keyframes vp-spin { to { transform: rotate(360deg); } }

/* --------------------------------------------------------------- toast -- */

.vp-toast {
  position: absolute; left: 14px; bottom: 74px; z-index: 3;
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px;
  background: rgba(12, 12, 18, .8);
  backdrop-filter: blur(8px);
  color: #fff; border-radius: 999px;
  font-size: .82rem; line-height: 1.2;
  animation: vp-rise .25s ease both;
}
@keyframes vp-rise { from { opacity: 0; transform: translateY(6px); } }
.vp-toast button {
  font: inherit; color: var(--accent);
  background: none; border: 0; padding: 0; cursor: pointer;
  text-decoration: underline;
}

/* double-tap seek feedback */
.vp-seek {
  position: absolute; top: 0; bottom: 0; width: 34%;
  display: grid; place-items: center;
  color: #fff; font-size: .9rem; font-variant-numeric: tabular-nums;
  background: radial-gradient(circle, rgba(255, 255, 255, .16), transparent 68%);
  opacity: 0; pointer-events: none;
}
.vp-seek.left { left: 0; } .vp-seek.right { right: 0; }
.vp-seek.flash { animation: vp-flash .45s ease both; }
@keyframes vp-flash { 0% { opacity: 0; } 25% { opacity: 1; } 100% { opacity: 0; } }

/* ------------------------------------------------------------ controls -- */

.vp-bar {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 4;
  padding: 0 12px 10px;
  line-height: 1.2;
  opacity: 0; transform: translateY(6px);
  transition: opacity .22s ease, transform .22s ease;
  pointer-events: none;
}
.vp.show-ui .vp-bar { opacity: 1; transform: none; pointer-events: auto; }

/* scrubber */
.vp-scrub {
  position: relative; height: 18px; margin-bottom: 2px;
  display: flex; align-items: center; cursor: pointer;
  touch-action: none;
}
.vp-track {
  position: relative; height: 4px; width: 100%;
  background: rgba(255, 255, 255, .26); border-radius: 99px;
  transition: height .15s ease;
}
.vp-scrub:hover .vp-track, .vp-scrub.dragging .vp-track { height: 6px; }
.vp-buffered, .vp-played {
  position: absolute; left: 0; top: 0; bottom: 0;
  border-radius: 99px;
}
.vp-buffered { background: rgba(255, 255, 255, .3); }
.vp-played { background: var(--accent); }
[data-theme="midnight"] .vp-played { background-image: var(--brand-gradient); }
.vp-knob {
  position: absolute; top: 50%; width: 13px; height: 13px;
  margin: -6.5px 0 0 -6.5px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, .5);
  transform: scale(0); transition: transform .15s ease;
}
.vp-scrub:hover .vp-knob, .vp-scrub.dragging .vp-knob { transform: scale(1); }
.vp-tip {
  position: absolute; bottom: 22px; transform: translateX(-50%);
  background: rgba(12, 12, 18, .9); color: #fff;
  padding: 3px 7px; border-radius: 6px;
  font-size: .74rem; font-variant-numeric: tabular-nums;
  opacity: 0; transition: opacity .12s; pointer-events: none; white-space: nowrap;
}
.vp-scrub:hover .vp-tip, .vp-scrub.dragging .vp-tip { opacity: 1; }

/* button row */
.vp-row { display: flex; align-items: center; gap: 4px; color: var(--vp-fg); }
.vp-row .grow { flex: 1; }
.vp-btn {
  display: grid; place-items: center;
  width: 36px; height: 36px; padding: 0;
  background: none; border: 0; border-radius: 8px;
  color: var(--vp-fg); cursor: pointer;
  transition: background .15s, color .15s, transform .1s;
}
.vp-btn:hover { background: rgba(255, 255, 255, .14); }
.vp-btn:active { transform: scale(.94); }
.vp-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.vp-btn svg { width: 19px; height: 19px; }
.vp-btn.wide { width: auto; padding: 0 9px; font: inherit; font-size: .8rem; font-variant-numeric: tabular-nums; }

.vp-time {
  font-size: .8rem; font-variant-numeric: tabular-nums;
  color: var(--vp-dim); padding: 0 6px; white-space: nowrap;
}
.vp-time b { color: var(--vp-fg); font-weight: 600; }

/* volume: a slider that only takes up space when you're using it */
.vp-vol { display: flex; align-items: center; }
.vp-vol input {
  width: 0; opacity: 0; padding: 0; margin: 0;
  transition: width .18s ease, opacity .18s ease, margin .18s ease;
  accent-color: var(--accent);
  cursor: pointer;
}
.vp-vol:hover input, .vp-vol:focus-within input { width: 74px; opacity: 1; margin: 0 8px 0 2px; }

/* autoplay-next toggle. On is full-brightness with an accent underline, off is
   dimmed with the label struck through — not accent-coloured when on, because
   the accent is a green that vanishes against a green field and then reads as
   the disabled state. */
#vp-auto { display: inline-flex; align-items: center; gap: 5px; }
#vp-auto .vp-auto-label { font-size: .74rem; letter-spacing: .02em; }
#vp-auto[aria-pressed="true"] { color: var(--vp-fg); box-shadow: inset 0 -2px 0 var(--accent); border-radius: 8px 8px 3px 3px; }
#vp-auto[aria-pressed="false"] { color: var(--vp-dim); }
#vp-auto[aria-pressed="false"] .vp-auto-label { text-decoration: line-through; }
.vp-toast .vp-next-title { font-weight: 600; }
.vp-toast b { font-variant-numeric: tabular-nums; }

/* speed menu */
.vp-speed { position: relative; }
.vp-menu {
  position: absolute; right: 0; bottom: 44px;
  background: rgba(16, 16, 24, .95);
  backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: 10px; padding: 5px; min-width: 92px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, .55);
}
.vp-menu[hidden] { display: none; }
.vp-menu button {
  display: flex; width: 100%; gap: 8px;
  font: inherit; font-size: .82rem; text-align: left;
  color: #fff; background: none; border: 0; border-radius: 6px;
  padding: 7px 9px; cursor: pointer;
}
.vp-menu button:hover { background: rgba(255, 255, 255, .12); }
.vp-menu button[aria-checked="true"] { color: var(--accent); font-weight: 600; }

/* ------------------------------------------------- play-in-place overlay -- */

body.vp-modal-open { overflow: hidden; }

.vp-overlay {
  position: fixed; inset: 0; z-index: 90;
  display: flex; flex-direction: column;
  background: rgba(6, 6, 12, .88);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  overscroll-behavior: contain;
  padding: max(14px, env(safe-area-inset-top)) max(14px, env(safe-area-inset-right))
           max(14px, env(safe-area-inset-bottom)) max(14px, env(safe-area-inset-left));
  animation: vp-fade .16s ease both;
}
.vp-overlay[hidden] { display: none; }
@keyframes vp-fade { from { opacity: 0; } }

.vp-overlay-bar {
  display: flex; align-items: center; gap: 14px;
  width: min(1100px, 100%); margin: 0 auto 10px;
  color: #fff;
}
.vp-overlay-title {
  font-weight: 650; font-size: 1rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  flex: 1; min-width: 0;
}
.vp-overlay-link { color: rgba(255, 255, 255, .72); font-size: .85rem; text-decoration: underline; }
.vp-overlay-link:hover { color: #fff; }
.vp-overlay-close {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  display: grid; place-items: center;
  font: inherit; font-size: 1.05rem; line-height: 1;
  color: #fff; background: rgba(255, 255, 255, .12);
  border: 0; border-radius: 50%; cursor: pointer;
}
.vp-overlay-close:hover { background: rgba(255, 255, 255, .22); }

.vp-overlay-stage {
  flex: 1; min-height: 0;
  width: min(1100px, 100%); margin: 0 auto;
  display: flex; align-items: center;
}
/* The player takes the whole stage immediately, and the video letterboxes
   inside it. Sizing to the video instead would mean a 300×150 box until
   metadata arrives and then a jump to full height on every single open — and
   it would give the open animation a target rect that isn't where the player
   ends up. */
.vp-overlay-stage .vp { width: 100%; height: 100%; }
.vp-overlay-stage .vp video {
  width: 100%; height: 100%;
  max-height: none;
  object-fit: contain;
}

@media (max-width: 560px) {
  .vp-overlay { padding-left: 8px; padding-right: 8px; }
  .vp-overlay-title { font-size: .9rem; }
  .vp-overlay-link { display: none; }
}

/* ---------------------------------------------------------------- touch -- */

@media (hover: none) {
  /* Nothing may depend on hover, so the grab handle and tooltip are always on. */
  .vp-knob { transform: scale(1); }
  .vp-track { height: 5px; }
  .vp-scrub { height: 30px; }                /* a fingertip-sized grab area */
  .vp-btn { width: 44px; height: 44px; }
  .vp-btn svg { width: 22px; height: 22px; }
  .vp-btn.wide { padding: 0 14px; font-size: .88rem; }
  .vp-time { font-size: .86rem; }
  .vp-bar { padding: 0 10px 12px; }
  .vp-menu button { padding: 12px 12px; font-size: .9rem; }
}

/* The bar must clear the home indicator, in page and in fullscreen alike. */
.vp-bar { padding-bottom: max(10px, env(safe-area-inset-bottom)); }
.vp:fullscreen .vp-bar {
  padding-left: max(12px, env(safe-area-inset-left));
  padding-right: max(12px, env(safe-area-inset-right));
}
.vp:fullscreen video { max-height: 100vh; height: 100vh; }

@media (max-width: 560px) {
  /* The slider goes — the hardware keys own the level on a phone. The mute
     toggle stays. Those keys change the volume; they cannot clear a muted flag
     on the element, so hiding this button too left a remembered mute with no
     way back: silent for good, on every video, with nothing to press. */
  .vp-vol input { display: none; }
  /* Bar space is short on a phone: the toggle keeps its icon and its colour. */
  #vp-auto .vp-auto-label { display: none; }
  .vp-big { width: 66px; height: 66px; margin: -33px 0 0 -33px; }
  .vp { border-radius: var(--radius-sm); }
  .vp video { max-height: 68vh; }
  /* Clear the control bar completely — overlapping the scrubber looks broken. */
  .vp-toast { left: 10px; right: 10px; bottom: 96px; z-index: 5; font-size: .8rem; }
  .vp-seek { font-size: 1rem; }
}

/* Landscape phone: the video is the whole point, so let it fill. */
@media (max-height: 500px) and (orientation: landscape) and (hover: none) {
  .vp { border: 0; border-radius: 0; }
  .vp video { max-height: calc(100dvh - 60px); }
}
@media (prefers-reduced-motion: reduce) {
  .vp-bar, .vp-shade, .vp-big, .vp-knob, .vp-track { transition: none; }
}

/* --------------------------------------------------------- turned video -- */

/* Same idea as the thumbnails in style.css: give the video the frame's
   dimensions *swapped*, then turn it, so it lands back over the frame exactly.
   What makes that possible is a frame with a definite size to query. On the
   watch page that comes from --vp-ar, which player.js sets from the video's own
   dimensions (already swapped) as soon as metadata arrives; in the overlay and
   in fullscreen the frame is told its size directly, so it must not also carry
   a ratio.
   object-fit stays `contain`, so the picture letterboxes inside the turned box
   rather than being cropped — a portrait clip on a wide page gets black down
   the sides, which is exactly what an unrotated portrait clip already does.

   This block sits last on purpose. Several rules above set width, height or
   max-height on `.vp video` at the same specificity — most of all the
   fullscreen one — and every last of them has to lose to these. */
.vp[data-rot] {
  container-type: size;
  aspect-ratio: var(--vp-ar, 16 / 9);
  max-height: min(78vh, 900px);
}
.vp-overlay-stage .vp[data-rot],
.vp[data-rot]:fullscreen { aspect-ratio: auto; max-height: none; }

.vp[data-rot] video {
  position: absolute; left: 50%; top: 50%;
  max-height: none;
  object-fit: contain;
  transform-origin: 50% 50%;
  transform: translate(-50%, -50%) rotate(var(--rot));
}
.vp[data-rot="90"] video,
.vp[data-rot="270"] video { width: 100cqh; height: 100cqw; }
.vp[data-rot="180"] video { width: 100cqw; height: 100cqh; }
