/* ==========================================================================
   Leme to Pontal Swimming Association
   player.css : the video player on gallery/videos/{URL}

   Loaded by that page alone. Every class here is written by
   public/assets/js/player.js, so nothing in this file paints until the script
   has run: a page without JS keeps the browser's own controls and never sees
   a rule below.

   Two decisions worth the note. The control bar sits over the picture, not
   under it, because it hides itself after a few seconds of playback and a bar
   in the flow would move the rest of the page every time it did. And gold is
   the single accent, exactly as DESIGN.md has it: it is the played part of the
   seek bar and the loading ring, and nothing else on the player. Buffered
   video, the volume level and every hover answer are foam at low opacity.

   Tokens and specificity follow site.css: single class selectors, a descendant
   only where it is genuinely a state of the player.
   ========================================================================== */

/* --- The player and its stage --------------------------------------------- */

.player {
  max-width: 960px;
  position: relative;
}

/* the box is sized before the file reports its own dimensions, so the page
   does not jump when the metadata arrives */
.player-stage {
  position: relative;
  aspect-ratio: 16 / 9;
  max-height: 70vh;
  overflow: hidden;
  border-radius: var(--r-surface);
  background: var(--sea);
}

.player-video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: var(--sea);
}

/* the stage takes focus for the keyboard shortcuts, so it carries the ring */
.player-stage:focus {
  outline: none;
}

/* --- The big play button and the replay ----------------------------------- */

.player-veil {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.player-big {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 76px;
  height: 76px;
  padding: 0;
  border: 1px solid rgba(243, 246, 248, 0.4);
  border-radius: 50%;
  background: rgba(15, 39, 64, 0.68);
  color: var(--sea-text);
  cursor: pointer;
  pointer-events: auto;
  transition: background-color var(--hover-step) ease,
    border-color var(--hover-step) ease, transform var(--hover-step) var(--ease-out),
    opacity var(--step) ease;
}

.player-big:hover {
  background: rgba(15, 39, 64, 0.88);
  border-color: var(--sea-text);
  transform: scale(1.05);
}

.player.is-playing .player-big {
  opacity: 0;
  visibility: hidden;
}

/* the replay takes the middle of the stage when the video runs out, so the
   play button gives its box up rather than only its paint */
.player.is-ended .player-big,
.player.is-broken .player-big {
  display: none;
}

.player-replay {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s3) var(--s5);
  border: 1px solid rgba(243, 246, 248, 0.5);
  border-radius: var(--r-control);
  background: rgba(15, 39, 64, 0.88);
  color: var(--sea-text);
  font: inherit;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  pointer-events: auto;
  transition: border-color var(--hover-step) ease, background-color var(--hover-step) ease;
}

.player-replay:hover {
  border-color: var(--sea-text);
}

.player-replay[hidden] {
  display: none;
}

/* --- Loading -------------------------------------------------------------- */

.player-spinner {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 46px;
  height: 46px;
  margin: -23px 0 0 -23px;
  pointer-events: none;
}

.player-spinner[hidden] {
  display: none;
}

/* the one gold ring on the player, and the only thing on it that turns */
.player-ring {
  display: block;
  width: 100%;
  height: 100%;
  border: 3px solid rgba(243, 246, 248, 0.22);
  border-top-color: var(--gold);
  border-radius: 50%;
  animation: player-spin 900ms linear infinite;
}

@keyframes player-spin {
  to { transform: rotate(360deg); }
}

/* --- The error panel ------------------------------------------------------ */

/* A format the browser refuses is known before a byte is fetched, so this
   stands in for the picture rather than over a black rectangle. */
.player-error {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s4);
  padding: var(--s5);
  text-align: center;
  background: rgba(15, 39, 64, 0.95);
  color: var(--sea-text);
}

.player-error[hidden] {
  display: none;
}

.player-error-text {
  margin: 0;
  max-width: 34ch;
  font-weight: 500;
  line-height: 1.45;
}

.player-error-link {
  display: inline-flex;
  align-items: center;
  padding: var(--s3) var(--s5);
  border: 1px solid rgba(232, 238, 243, 0.55);
  border-radius: var(--r-control);
  color: var(--sea-text);
  font-size: 1rem;
  font-weight: 600;
  text-decoration: none;
  transition: border-color var(--hover-step) ease, background-color var(--hover-step) ease;
}

.player-error-link:hover {
  border-color: var(--sea-text);
  background: rgba(243, 246, 248, 0.12);
}

/* --- The control bar ------------------------------------------------------ */

.player-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  padding: var(--s3) var(--s4) var(--s2);
  background: rgba(15, 39, 64, 0.92);
  color: var(--sea-text);
  transition: opacity var(--step) ease;
}

/* A bar at 92 per cent still takes the colour of whatever is behind it, and a
   frame of white water or a bright sky pushed the labels close to unreadable.
   The scrim is the same ink faded out upwards, so the bar has something dark to
   sit against whatever the video is doing under it. */
.player-bar::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: var(--s7);
  background: linear-gradient(rgba(15, 39, 64, 0), rgba(15, 39, 64, 0.72));
  pointer-events: none;
}

.player.is-idle .player-bar {
  opacity: 0;
  pointer-events: none;
}

/* nothing in the bar can be reached while the file will not play, and the
   panel over it carries a download link of its own */
.player.is-broken .player-bar {
  opacity: 0;
  pointer-events: none;
}

.player.is-idle .player-stage {
  cursor: none;
}

/* On ink the ink half of the site's two tone ring disappears into the bar, so
   the outline turns foam and the gold ring carries on doing its half. This is
   the same exception site.css makes for the gold live band. */
.player-bar :focus-visible {
  outline-color: var(--foam);
}

.player-controls {
  display: flex;
  align-items: center;
  gap: var(--s1);
}

.player-spacer {
  flex: 1 1 auto;
}

.player-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s2);
  border: 1px solid transparent;
  border-radius: var(--r-control);
  background: transparent;
  color: var(--sea-text);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--step) ease;
}

.player-btn:hover {
  background: rgba(243, 246, 248, 0.14);
}

.player-icon {
  display: inline-flex;
  flex: 0 0 auto;
}

.player-time {
  padding: 0 var(--s2);
  font-size: 0.875rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  white-space: nowrap;
}

/* --- The seek bar --------------------------------------------------------- */

.player-seek {
  position: relative;
  display: flex;
  align-items: center;
  height: 22px;
  margin-bottom: var(--s1);
  cursor: pointer;
  touch-action: none;
}

.player-track {
  position: relative;
  width: 100%;
  height: 4px;
  border-radius: 2px;
  background: rgba(243, 246, 248, 0.22);
  transition: height var(--hover-step) var(--ease-out);
}

.player-seek:hover .player-track,
.player.is-scrubbing .player-track {
  height: 6px;
}

.player-buffer {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0;
  border-radius: 2px;
  background: rgba(243, 246, 248, 0.42);
}

.player-fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0;
  border-radius: 2px;
  background: var(--gold);
}

/* the knob is the end of the fill rather than an element of its own, so the
   script writes one width for the whole bar and nothing can fall out of step */
.player-fill::after {
  content: '';
  position: absolute;
  right: -6px;
  top: 50%;
  width: 12px;
  height: 12px;
  margin-top: -6px;
  border-radius: 50%;
  background: var(--gold);
  opacity: 0;
  transition: opacity var(--hover-step) ease;
}

.player-seek:hover .player-fill::after,
.player.is-scrubbing .player-fill::after {
  opacity: 1;
}

.player-tip {
  position: absolute;
  bottom: 100%;
  margin-bottom: var(--s1);
  padding: var(--s1) var(--s2);
  border-radius: var(--r-control);
  background: var(--ink);
  color: var(--sea-text);
  font-size: 0.8125rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  white-space: nowrap;
  transform: translateX(-50%);
  pointer-events: none;
}

.player-tip[hidden] {
  display: none;
}

/* --- Sound ---------------------------------------------------------------- */

.player-sound {
  display: flex;
  align-items: center;
  gap: var(--s2);
}

.player-volume {
  position: relative;
  display: flex;
  align-items: center;
  width: 76px;
  height: 22px;
  cursor: pointer;
  touch-action: none;
}

.player-volume-track {
  position: relative;
  width: 100%;
  height: 4px;
  border-radius: 2px;
  background: rgba(243, 246, 248, 0.22);
}

/* foam, not gold: the level of the sound is not the one accent of the page */
.player-volume-fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 100%;
  border-radius: 2px;
  background: var(--sea-text);
}

.player-volume-fill::after {
  content: '';
  position: absolute;
  right: -5px;
  top: 50%;
  width: 10px;
  height: 10px;
  margin-top: -5px;
  border-radius: 50%;
  background: var(--sea-text);
}

/* --- The playback rate menu ----------------------------------------------- */

.player-rate {
  position: relative;
  display: flex;
}

.player-rate-now {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

.player-rate-panel {
  position: absolute;
  right: 0;
  bottom: 100%;
  z-index: 4;
  display: grid;
  gap: 2px;
  min-width: 8rem;
  margin-bottom: var(--s2);
  padding: var(--s1);
  border: 1px solid var(--sea-rule);
  border-radius: var(--r-control);
  background: var(--ink);
}

.player-rate-panel[hidden] {
  display: none;
}

.player-rate-item {
  padding: var(--s2) var(--s3);
  border: 0;
  border-radius: var(--r-control);
  background: transparent;
  color: var(--sea-text);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
  text-align: left;
  cursor: pointer;
  transition: background-color var(--menu-step) ease;
}

.player-rate-item:hover {
  background: rgba(243, 246, 248, 0.14);
}

.player-rate-item[aria-pressed='true'] {
  background: rgba(243, 246, 248, 0.2);
}

/* --- The live region ------------------------------------------------------ */

.player-live {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --- Fullscreen ----------------------------------------------------------- */

/* One selector per rule: an engine that does not know :fullscreen would drop
   the whole list, and with it the prefixed half it does know. */

.player:fullscreen {
  max-width: none;
  background: var(--sea);
}

.player:-webkit-full-screen {
  max-width: none;
  background: var(--sea);
}

.player:fullscreen .player-stage {
  height: 100%;
  max-height: none;
  aspect-ratio: auto;
  border-radius: 0;
}

.player:-webkit-full-screen .player-stage {
  height: 100%;
  max-height: none;
  aspect-ratio: auto;
  border-radius: 0;
}

/* --- Narrow screens ------------------------------------------------------- */

@media (max-width: 700px) {
  /* the seek bar keeps the full width; the two controls a phone has no room
     for are the volume slider, which a phone answers with its own buttons,
     and the floating window, which it has no place to float into */
  .player-volume {
    display: none;
  }

  .player-pip {
    display: none;
  }

  .player-download-text {
    display: none;
  }

  .player-big {
    width: 62px;
    height: 62px;
  }

  .player-time {
    padding: 0 var(--s1);
    font-size: 0.8125rem;
  }
}

/* --- Reduced motion ------------------------------------------------------- */

/* The ring stops turning and stays as a ring, which still says the file is
   being fetched; the bar arrives and leaves at once instead of fading. */

@media (prefers-reduced-motion: reduce) {
  .player-ring {
    animation: none;
  }

  .player-bar {
    transition: none;
  }

  .player-big:hover {
    transform: none;
  }

  .player-track {
    transition: none;
  }

  .player-fill::after {
    transition: none;
    opacity: 1;
  }
}
