/* AQcredix — the private-bucket video player.
 *
 * Palette tokens only, no literal colours, so this follows light, dark and neon without a
 * second definition. The one exception is the poster image itself, which is a photograph.
 */

/* The poster fills the frame behind the play button. object-fit:cover rather than a
   background-image so the browser treats it as a real image — it can be lazily loaded,
   it carries alt text, and it is sized by the same rules as every other picture here. */
.vp-poster{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;display:block;
}

/* The whole frame is the target, not just the 56px circle — people aim at the picture. */
[data-video-key]:not(.vp-playing){cursor:pointer;}
[data-video-key]:not(.vp-playing):hover .play{transform:scale(1.08);}

.vp-video{
  position:relative;z-index:1;
  width:100%;height:100%;display:block;
  background:#000000;
  object-fit:contain;      /* letterbox rather than crop — never cut off a speaker's head */
}

/* ---------- fullscreen ----------
   The HOST goes fullscreen, not the video — see the note in player.js. That makes the host
   the size of the screen, so the video inside has to be told to fill it, and the container
   query the overlay is sized against now reports the full screen width, which is what
   brings the speaker's roles back at a size worth reading. */
.aqv-host:fullscreen,
.aqv-host:-webkit-full-screen{
  /* SIZED EXPLICITLY, NOT BY aspect-ratio + max-width.
     A fullscreen element is given `position:fixed; inset:0` by the browser, and four pinned
     edges beat aspect-ratio and max-width: the frame filled the whole screen and the shape
     was simply ignored. On a 20:9 phone in landscape that put the logo and the fullscreen
     button out on the black bar beside the picture, and off the edge of some screens.

     So the insets are released and both dimensions are computed from the video's own ratio,
     taking whichever of width or height the screen runs out of first. --vp-arn is that
     ratio as a plain number, set from the file once its metadata loads; 1.7778 (16:9) only
     applies in the instant before that or if metadata never arrives. */
  position:fixed;
  inset:auto;
  top:50%;left:50%;
  transform:translate(-50%,-50%);
  width:min(100vw, calc(100vh * var(--vp-arn, 1.7778)));
  height:min(100vh, calc(100vw / var(--vp-arn, 1.7778)));
  max-width:none;max-height:none;
  background:#000;               /* the letterbox is black on every device, in every theme */
  border:none;border-radius:0;
  display:block;
}
/* The area around the picture. Black rather than the theme background, because a letterbox
   that glows teal in neon mode looks like a rendering fault rather than a choice. */
.aqv-host:fullscreen::backdrop{background:#000;}
.aqv-host:fullscreen .vp-video,
.aqv-host:-webkit-full-screen .vp-video{
  width:100%;height:100%;object-fit:contain;display:block;
}

/* ---------- our own fullscreen button ----------
   Bottom right, clear of the video's own control bar on the left. It is the one thing in
   this frame besides the video that takes a click; the branded overlay above it stays
   pointer-events:none. */
.vp-fs{
  /* 52px up, to clear the browser's own control bar rather than sit on top of it. */
  position:absolute;z-index:5;right:10px;bottom:52px;
  width:34px;height:34px;padding:0;
  display:flex;align-items:center;justify-content:center;
  border-radius:8px;cursor:pointer;
  background:rgba(4,16,14,.62);border:1px solid rgba(255,255,255,.22);
  color:#F4F2EC;
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);
  opacity:0;transition:opacity .2s ease, background .2s ease, border-color .2s ease;
}
.vp-fs svg{width:17px;height:17px;}
/* Appears when the frame is touched or hovered, like any player control, so it does not
   sit permanently over the picture. Always visible to the keyboard. */
.vp-playing:hover .vp-fs,
.vp-playing:focus-within .vp-fs,
.vp-fs:focus-visible{opacity:1;}
.vp-fs:hover{background:rgba(4,16,14,.85);border-color:var(--brand-2);}
.vp-fs.is-on svg{transform:scale(-1);}

/* A coarse pointer has no hover, so there is nothing to reveal it with — it stays up. */
@media (pointer:coarse){ .vp-playing .vp-fs{opacity:1;} }

/* ---------- waiting for the signed link ----------
   A spinner rather than a frozen play button, because the wait is a real network round
   trip: the server has to check the subscription before it will sign anything. */
.vp-loading .play{opacity:.35;pointer-events:none;}
.vp-loading::after{
  content:"";position:absolute;z-index:2;
  width:34px;height:34px;border-radius:50%;
  border:2px solid var(--border);
  border-top-color:var(--brand-2);
  animation:vp-spin .7s linear infinite;
}
@keyframes vp-spin{to{transform:rotate(360deg);}}

/* Someone who has asked for less motion still needs to know it is working, so the ring
   pulses in place instead of turning. */
@media (prefers-reduced-motion:reduce){
  .vp-loading::after{animation:vp-pulse 1.4s ease-in-out infinite;}
  @keyframes vp-pulse{0%,100%{opacity:.35;}50%{opacity:1;}}
}

/* ---------- refused, and why ----------
   Sits over the poster rather than replacing it: the picture is what made them want to
   watch, and taking it away to deliver bad news makes the refusal feel like a dead end. */
.vp-msg{
  position:absolute;inset:0;z-index:3;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:14px;padding:24px;text-align:center;
  background:linear-gradient(0deg,rgba(0,0,0,.88),transparent);
  backdrop-filter:blur(3px);
}
.vp-msg p{
  margin:0;max-width:34ch;
  font-size:clamp(14.5px,1.6vw,17px);line-height:1.5;
  color:var(--fg);
  text-shadow:0 1px 10px var(--bg-deep);
}
.vp-msg .btn{flex:none;}

@media (max-width:560px){
  .vp-msg{gap:11px;padding:18px;}
}
