/* Generated from apps/dev-site/design-system. Edit the token sources. */
/* Mpalo media player.

   One component for MP4 playback on every Mpalo surface. The player is a
   solid surface with no border, the one system radius, and the softer media
   shadow (half the opacity of the overlay shadow). It has no window chrome:
   no traffic-light dots, no title bar, no divider rules.

   Markup lives in apps/dev-site/pages/media.ejs. Behavior lives in media.js.
   The public specification is developer.mpalo.com/media. */

.mpalo-video {
  --mpalo-video-pad: clamp(1rem, 2.5vw, 1.5rem);
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 0;
  border-radius: var(--radius);
  background: var(--media-stage-bg);
  box-shadow:
    var(--shadow-media),
    0 0 var(--mpalo-ambient-blur) var(--mpalo-ambient-spread) rgb(var(--mpalo-ambient-rgb) / var(--mpalo-ambient-opacity));
  transition: box-shadow 200ms linear;
  color: var(--text-1);
  font-family: var(--surface-font-body);
  letter-spacing: var(--ls-body);
}

/* A low-resolution copy of the current frame, blurred and set behind the
   player. The visible edge is the ambient shadow, and its color is whatever
   the nearby picture pixels are at that moment. */
.mpalo-video-ambient {
  position: absolute;
  left: -2%;
  top: -2%;
  z-index: 0;
  width: 104%;
  height: 104%;
  border-radius: calc(var(--radius) * 1.15);
  filter: blur(var(--mpalo-ambient-blur)) saturate(1.1);
  opacity: var(--mpalo-ambient-opacity);
  pointer-events: none;
}

.mpalo-video [hidden] { display: none !important; }

.mpalo-video-shell {
  position: relative;
  --mpalo-ambient-rgb: 0 0 0;
  --mpalo-ambient-opacity: 0.55;
  --mpalo-ambient-blur: 18px;
  --mpalo-ambient-spread: 2px;
}

/* The backdrop is the only thing between the expanded player and the page.
   Clicking it closes the expansion; the video keeps playing. */
.mpalo-video-backdrop {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--scrim);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 320ms linear, visibility 0s linear 320ms;
}

.mpalo-video-backdrop.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity 90ms linear, visibility 0s linear 0s;
}

/* The frame holds the 16 by 9 stage and the bottom controls on one plane.
   The stage is true black so the picture, not the interface, sets the tone. */
.mpalo-video__frame {
  position: relative;
  aspect-ratio: 16 / 9;
}

.mpalo-video__stage {
  position: absolute;
  inset: 0;
  background: var(--media-stage-bg);
}

.mpalo-video__video {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  object-fit: contain;
  background: var(--media-stage-bg);
  cursor: pointer;
}

.mpalo-video__overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* The picture is the default state. Controls and metadata fade in fast on
   hover or focus, then fade out more slowly when the pointer leaves. */
.mpalo-video__top,
.mpalo-video__center,
.mpalo-video__bottom {
  opacity: 0;
  visibility: hidden;
  transition: opacity 320ms linear, visibility 0s linear 320ms;
}

.mpalo-video:hover .mpalo-video__top,
.mpalo-video:hover .mpalo-video__center,
.mpalo-video:hover .mpalo-video__bottom,
.mpalo-video:focus-visible .mpalo-video__top,
.mpalo-video:focus-visible .mpalo-video__center,
.mpalo-video:focus-visible .mpalo-video__bottom {
  opacity: 1;
  visibility: visible;
  transition: opacity 90ms linear, visibility 0s linear 0s;
}

.mpalo-video:has(:focus-visible) .mpalo-video__top,
.mpalo-video:has(:focus-visible) .mpalo-video__center,
.mpalo-video:has(:focus-visible) .mpalo-video__bottom {
  opacity: 1;
  visibility: visible;
  transition: opacity 90ms linear, visibility 0s linear 0s;
}

/* Touch surfaces have no hover. Keep the controls visible there. */
@media (hover: none) {
  .mpalo-video__top,
  .mpalo-video__center,
  .mpalo-video__bottom {
    opacity: 1;
    visibility: visible;
    transition: none;
  }
}

/* A touch tablet has no hover but enough width for the top-center caption. */
@media (hover: none) and (min-width: 721px) {
  .mpalo-video__transcript {
    top: var(--mpalo-video-pad);
    bottom: auto;
    max-width: min(30%, 30rem);
  }
}

.mpalo-video__top {
  position: absolute;
  top: var(--mpalo-video-pad);
  right: var(--mpalo-video-pad);
  left: var(--mpalo-video-pad);
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--gap-within);
  pointer-events: none;
}

.mpalo-video__cluster {
  display: flex;
  align-items: center;
  gap: var(--gap-within);
  min-width: 0;
  pointer-events: auto;
}

/* The two top-left controls read as one group, the same height as the volume
   pill. The controls inside are quiet; the group carries the fill. */
.mpalo-video__cluster--group {
  gap: 0.25rem;
  padding: 0;
  border-radius: var(--radius);
  background: var(--media-control-bg);
}

.mpalo-video__cluster--group .mpalo-video__control {
  background: transparent;
}

.mpalo-video__cluster--group .mpalo-video__control:hover {
  background: var(--media-control-bg-hover);
}

.mpalo-video__control,
.mpalo-video__play {
  display: inline-grid;
  flex: none;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: var(--radius);
  background: var(--media-control-bg);
  color: var(--text-1);
  font: inherit;
  line-height: 1;
  cursor: pointer;
  transition: background-color var(--dur-fast) linear, color var(--dur-fast) linear;
}

.mpalo-video__control {
  width: 2.5rem;
  height: 2.5rem;
}

.mpalo-video__play {
  width: var(--mpalo-play-size);
  height: var(--mpalo-play-size);
  background: var(--media-control-bg);
  color: var(--text-1);
}

.mpalo-video__control:hover {
  background: var(--media-control-bg-hover);
  color: var(--text-1);
}

.mpalo-video__play:hover {
  background: var(--media-control-bg-hover);
  color: var(--text-1);
}

.mpalo-video__control:focus-visible,
.mpalo-video__play:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.mpalo-video__control .mi {
  --mi-size: 1.25rem;
  --mi-opsz: 20;
}

.mpalo-video__play .mi {
  --mi-size: calc(var(--mpalo-play-size) * 0.82);
  --mi-opsz: 48;
  --mi-wght: 500;
  --mi-fill: 1;
}

.mpalo-video__play [data-video-icon="pause"] {
  display: none;
}

.mpalo-video.is-playing .mpalo-video__play [data-video-icon="play"] {
  display: none;
}

.mpalo-video.is-playing .mpalo-video__play [data-video-icon="pause"] {
  display: block;
}

.mpalo-video__center {
  --mpalo-play-size: clamp(5rem, 9vw, 6rem);
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(2rem, 5.5vw, 4rem);
  pointer-events: none;
}

.mpalo-video__center .mpalo-video__control {
  width: calc(var(--mpalo-play-size) * 0.75);
  height: calc(var(--mpalo-play-size) * 0.75);
}

.mpalo-video__center .mpalo-video__control .mi {
  --mi-size: calc(var(--mpalo-play-size) * 0.62);
  --mi-opsz: 32;
}

.mpalo-video__center .mpalo-video__control,
.mpalo-video__center .mpalo-video__play {
  pointer-events: auto;
}

/* The volume pill is one solid group. The mute button inside it is quiet so
   the group reads as a single control, not two nested buttons. */
.mpalo-video__volume {
  display: flex;
  flex: 0 1 10rem;
  align-items: center;
  gap: var(--gap-within);
  min-height: 2.5rem;
  padding: 0 0.25rem 0 0.5rem;
  border-radius: var(--radius);
  background: var(--media-control-bg);
}

.mpalo-video__volume .mpalo-video__control {
  background: transparent;
}

.mpalo-video__volume .mpalo-video__control:hover {
  background: var(--media-control-bg-hover);
}

.mpalo-video__volume .mpalo-video__range {
  --mpalo-range-progress: 25%;
  flex: 1;
  width: auto;
  min-width: 4rem;
}

/* One range treatment for progress and volume. The filled portion is text-1,
   the remaining track is surface-4. No alpha, no border, no second radius. */
.mpalo-video__range {
  --mpalo-range-progress: 0%;
  display: block;
  width: 100%;
  height: 0.5rem;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: var(--radius);
  background: linear-gradient(
    to right,
    var(--text-1) 0 var(--mpalo-range-progress),
    var(--surface-4) var(--mpalo-range-progress) 100%
  );
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
}

.mpalo-video__range::-webkit-slider-runnable-track {
  height: 0.5rem;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
}

.mpalo-video__range::-moz-range-track {
  height: 0.5rem;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
}

.mpalo-video__range::-webkit-slider-thumb {
  width: 1rem;
  height: 1rem;
  margin-top: -0.25rem;
  border: 0;
  border-radius: var(--radius);
  background: var(--text-1);
  appearance: none;
  -webkit-appearance: none;
}

.mpalo-video__range::-moz-range-thumb {
  width: 1rem;
  height: 1rem;
  border: 0;
  border-radius: var(--radius);
  background: var(--text-1);
}

.mpalo-video__range:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 4px;
}

/* Bottom: title, description, actions, then the timeline. It sits on the
   picture with no panel and no tint; the text shadow carries legibility. The
   title is interface text, so it uses Helvetica, not Radley. */
.mpalo-video__bottom {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: var(--mpalo-video-pad);
  pointer-events: none;
}

.mpalo-video__actions,
.mpalo-video__timeline {
  pointer-events: auto;
}

.mpalo-video__meta {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.5rem;
}

.mpalo-video__meta--actions-only {
  justify-content: flex-end;
}

.mpalo-video__text {
  min-width: 0;
}

.mpalo-video .mpalo-video__title {
  margin: 0;
  color: var(--text-1);
  font-family: var(--surface-font-body);
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  font-weight: 900;
  line-height: 1.15;
  letter-spacing: var(--ls-body);
  text-shadow: var(--media-text-shadow);
}

.mpalo-video .mpalo-video__description {
  max-width: 70ch;
  margin: 0.375rem 0 0;
  color: var(--text-2);
  font-size: var(--fs-sm);
  line-height: 1.45;
  text-shadow: var(--media-text-shadow);
}

.mpalo-video__actions {
  display: flex;
  flex: none;
  gap: var(--gap-within);
}

.mpalo-video__timeline {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.mpalo-video__time {
  min-width: 3.5rem;
  color: var(--text-2);
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  text-shadow: var(--media-text-shadow);
}

.mpalo-video__time--remaining {
  text-align: right;
}

.mpalo-video__timeline .mpalo-video__range {
  flex: 1;
}

/* Transcript: a caption over the picture, not a panel below it. It sits at
   the bottom center by default and moves to the top center while the player
   is hovered or focused. */
.mpalo-video__transcript {
  position: absolute;
  bottom: var(--mpalo-video-pad);
  left: 50%;
  z-index: 2;
  max-width: min(80%, 48rem);
  transform: translateX(-50%);
  text-align: center;
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.18s linear;
}

/* Position changes happen while the caption is invisible, so it fades out
   where it is and fades back in at the other edge instead of snapping. */
.mpalo-video__transcript.is-top {
  top: var(--mpalo-video-pad);
  bottom: auto;
  max-width: min(30%, 30rem);
}

/* On narrow players the top row takes most of the width, so the caption
   moves below it instead of colliding with the volume pill. */
@media (max-width: 720px) {
  .mpalo-video__transcript.is-top {
    top: calc(var(--mpalo-video-pad) + 3.5rem);
    max-width: min(70%, 30rem);
  }
}

.mpalo-video__transcript.is-fading {
  opacity: 0;
}

/* The transcript toggle is a state control: filled when captions are on. */
.mpalo-video [data-video-transcript][aria-expanded="true"] .mi {
  --mi-fill: 1;
}

.mpalo-video .mpalo-video__transcript-line {
  display: inline-block;
  max-width: none;
  margin: 0;
  padding: 0.375rem 0.75rem;
  border-radius: var(--radius);
  background: var(--media-caption-bg);
  color: var(--text-1);
  font-size: var(--fs-sm);
  line-height: 1.45;
  text-shadow: var(--media-text-shadow);
}

.mpalo-video .mpalo-video__status {
  position: absolute;
  right: var(--mpalo-video-pad);
  bottom: var(--mpalo-video-pad);
  left: var(--mpalo-video-pad);
  z-index: 2;
  max-width: none;
  margin: 0;
  padding: 0.75rem 1rem;
  border-radius: var(--radius);
  background: var(--red);
  color: var(--on-red);
  font-size: var(--fs-sm);
  line-height: 1.4;
}

/* Expanded: the player sits above the page on a backdrop. Clicking the
   backdrop or pressing Escape closes it; the video keeps playing. */
body.mpalo-video-expanded {
  overflow: hidden;
}

.mpalo-video.is-expanded {
  position: fixed;
  top: 50%;
  left: 50%;
  z-index: 101;
  width: min(92vw, 163.5vh);
  max-width: 96rem;
  transform: translate(-50%, -50%);
}

.mpalo-video.is-expanded .mpalo-video__frame {
  aspect-ratio: 16 / 9;
}

.mpalo-video.is-expanded .mpalo-video__stage {
  position: absolute;
  inset: 0;
}

.mpalo-video.is-expanded .mpalo-video__bottom {
  position: absolute;
}

@media (max-width: 720px) {
  .mpalo-video__frame {
    aspect-ratio: auto;
  }

  .mpalo-video__stage {
    position: relative;
    inset: auto;
    aspect-ratio: 16 / 9;
  }

  .mpalo-video__bottom {
    position: static;
  }

  .mpalo-video__top {
    flex-direction: row;
    align-items: flex-start;
  }

  .mpalo-video__top .mpalo-video__cluster {
    justify-content: flex-start;
  }

  .mpalo-video__volume {
    flex: 0 1 8rem;
    width: auto;
  }

  .mpalo-video__meta {
    flex-direction: column;
    align-items: stretch;
  }

  .mpalo-video__actions {
    justify-content: flex-start;
  }

  .mpalo-video__transcript,
  .mpalo-video:hover .mpalo-video__transcript,
  .mpalo-video:focus-visible .mpalo-video__transcript {
    top: auto;
    bottom: var(--mpalo-video-pad);
    max-width: calc(100% - 2 * var(--mpalo-video-pad));
  }

  .mpalo-video:has(:focus-visible) .mpalo-video__transcript {
    top: auto;
    bottom: var(--mpalo-video-pad);
    max-width: calc(100% - 2 * var(--mpalo-video-pad));
  }

  .mpalo-video.is-expanded {
    width: 100vw;
    max-width: none;
  }
}
