@import url("web-tokens.css");

/* Inside the 1440 × 948 web frame, from the Figma player ("Web expanded - Extended",
   node 8929:90092; DESIGN.md, "Web player"). Ported from the web fork (Step 10b).
   Values are tokens from web-tokens.css. Colours come only from the --player-* variables
   on .web-screen and the mixes of them in web-tokens.css; the Plus badge is an image.
   The gradient is on .web-screen, under all of it (first below).

   Three areas, as in Figma: the top-right buttons, the now-playing column centred on
   the frame, and the playbar along the bottom.

   The Web player is one of the stage's surfaces, so every rule here and in
   web-tokens.css is nested in [data-surface="web"], the stage's attribute while it shows
   the Web player (main.js); the Playbar's are nested in [data-surface="playbar"], so the
   two share class names such as .player-bar. @keyframes can't be nested, so it's just
   below, at the top level, named apart from the Playbar's. */

/* The buffering spinner's turn (.player-spinner, below) */
@keyframes web-spin { to { transform: rotate(1turn); } }

[data-surface="web"] {

/* --- The screen under the player --------------------------------------------- */

.web-screen {
  /* Player colours, all OKLCH. Everything below paints with these.
     colour.js sets --player-bg and --player-fg from the artwork, and makes fg white
     with the gradient. */
  --player-bg: oklch(0.3 0 0);
  --player-fg: oklch(1 0 0);
  /* fg's hue goes in missing, so the mix keeps bg's hue (web-tokens.css, colour mixes) */
  --player-fg-2: color-mix(in oklch, oklch(from var(--player-fg) l c none) 70%, var(--player-bg)); /* Figma: white 70% */
  /* Over the background, under everything else; on with the Gradient setting (B), on by
     default here (surfaces.js). Figma's two layers, top first: rgba(0, 0, 0, 0.46 → 0)
     over the top 68%, and rgba(0, 0, 0, 0 / 0.3 / 0.74) towards the bottom. Every stop
     is black, so only the alpha changes. Together they're lightest at about 30% down,
     0.2985 (the Web's gradientLightest, surfaces.js). If the stops change, recalculate
     that and --player-cutout (web-tokens.css) */
  --player-gradient:
    linear-gradient(180deg, oklch(0 0 0 / 0.46) 0%, oklch(0 0 0 / 0) 68.107%),
    linear-gradient(180deg, oklch(0 0 0 / 0) 23.47%, oklch(0 0 0 / 0.3) 58.832%, oklch(0 0 0 / 0.74) 98.523%);

  background: var(--player-bg);
  transition: --player-bg 500ms ease, --player-fg 500ms ease; /* the Playbar's 500 ms, not the fork's 250 (10a checkpoint) */
}

/* The gradient fades in and out with the colours' 500 ms, so it and the text turning
   white read as one change */
.web-screen::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--player-gradient);
  opacity: 0;
  transition: opacity 500ms ease;
}

/* With the gradient the UI is white (colour.js), and the secondary text goes translucent,
   so the gradient shows through it; the other tints are in web-tokens.css */
.web-screen.has-gradient {
  --player-fg-2: oklch(from var(--player-fg) l c h / 0.7); /* Figma: white 70% */
}

.web-screen.has-gradient::before { opacity: 1; }

/* --- The player ---------------------------------------------------------------- */

/* The whole 1440 × 948 frame */
.player {
  position: absolute;
  inset: 0;
  color: var(--player-fg);
  font-family: var(--font-family);
}

.player p,
.player h2 { margin: 0; }

/* --- Top right: full screen · Switch to video ------------------------------ */
.player-top {
  position: absolute;
  top: var(--top-inset);
  right: var(--top-right);
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--top-gap);
}

.player .player-switch {
  gap: var(--switch-gap);
  padding: var(--switch-padding);
  border-radius: var(--switch-radius);
  background: var(--player-fill);
  font: var(--type-switch);
  white-space: nowrap;
}

/* --- Now playing: show name · artwork · episode title and badge ------------ */
.player-now {
  position: absolute;
  top: calc(50% + var(--now-offset));
  left: 50%;
  translate: -50% -50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--now-gap);
  width: var(--now-width);
  text-align: center;
}

.player-now-meta {
  display: flex;
  align-items: center;
  gap: var(--now-meta-gap);
  max-width: 100%;
  white-space: nowrap;
}

.player-show-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  font: var(--type-now-meta);
}

.player-now-dot { font: var(--type-now-dot); }
.player-now-type { font: var(--type-now-type); color: var(--player-fg-2); }

.player-cover {
  width: var(--cover-size);
  height: var(--cover-size);
  filter: var(--cover-shadow);
}

.player-artwork {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--cover-radius);
  background: var(--player-fill); /* until it loads */
}

.player-now-titles {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--now-titles-gap);
  width: 100%;
}

/* Long titles wrap to 2 lines at most */
.player-episode-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  font: var(--type-episode-title);
}

.player-badge-plus { display: block; }

/* --- Playbar: the episode · the controls over the progress bar · volume ---- */
.player-bar {
  position: absolute;
  inset: auto 0 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--bar-gap);
  padding: var(--bar-padding);
  filter: var(--bar-shadow);
}

.player-bar-info {
  flex: 1 1 0;
  display: flex;
  align-items: center;
  gap: var(--info-gap);
  min-width: 0;
  min-height: var(--info-min-height);
}

.player-bar-thumb {
  flex: none;
  width: var(--thumb-size);
  height: var(--thumb-size);
}

.player-bar-artwork {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--thumb-radius);
  background: var(--player-fill);
}

.player-bar-text {
  display: grid;
  min-width: 0;
  max-width: calc(var(--info-max-width) - var(--thumb-size) - var(--info-gap));
}

.player-bar-title,
.player-bar-show {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.player-bar-title { font: var(--type-bar-title); }

.player-bar-meta {
  display: flex;
  align-items: center;
  gap: var(--meta-gap);
  min-width: 0;
  font: var(--type-bar-meta);
  color: var(--player-fg-2);
  white-space: nowrap;
}

.player-bar-meta .icon { background-color: var(--player-fg-2); }

.player-bar-actions {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  gap: var(--actions-gap);
  min-width: var(--actions-min);
  max-width: var(--actions-max);
}

/* Playback in the middle, speed just left of it; the hidden Next keeps playback
   centred on the progress bar, as in Figma */
.player-bar-controls {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--speed-gap);
  padding-right: var(--controls-inset);
}

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

.player .player-skip,
.player-next-slot,
.player .player-speed {
  flex: none;
  width: var(--control-size);
  height: var(--control-size);
}

.player .player-speed {
  font: var(--type-speed);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.player-bar-progress {
  display: flex;
  align-items: center;
  gap: var(--progress-gap);
  height: var(--progress-height);
  font: var(--type-time);
  font-variant-numeric: tabular-nums;
  color: var(--player-fg-2);
}

.player-elapsed,
.player-total {
  flex: none;
  width: var(--time-width);
  white-space: nowrap;
}

.player-elapsed { text-align: right; }

.player-bar-trailing {
  flex: 1 1 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--trailing-gap);
  min-width: 0;
}

/* Figma's 16 px padding on the trailing column, as a margin: padding would add to the
   column's equal share of the row and push the controls off centre */
.player-bar-volume {
  display: flex;
  align-items: center;
  gap: var(--volume-gap);
  margin-right: var(--trailing-padding);
}

/* --- Sliders: the progress and volume bars ---------------------------------- */
/* --progress (0–1) is set by web-player.js. The band (::before) is the pointer area, taller
   than the 6 px track */
.player-progress,
.player-volume {
  --progress: 0;
  position: relative;
  height: var(--track-height);
  border-radius: calc(var(--track-height) / 2);
  background: var(--player-track);
  cursor: pointer;
  touch-action: none; /* a drag scrubs rather than scrolls */
  -webkit-user-select: none;
  user-select: none;
}

.player-progress { flex: 1; min-width: 0; }
.player-volume { flex: none; width: var(--volume-width); }

.player-progress::before,
.player-volume::before {
  content: "";
  position: absolute;
  inset: calc(var(--track-height) / 2 - var(--scrub-band) / 2) 0;
}

.player-progress-fill,
.player-volume-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: calc(var(--progress) * 100%);
  border-radius: inherit;
  background: var(--player-fg);
  pointer-events: none;
}

/* The handle: hidden at rest, as in the design; shown on hover (Figma), while dragging
   and with keyboard focus */
.player-progress::after,
.player-volume::after {
  content: "";
  position: absolute;
  top: 50%;
  left: calc(var(--progress) * 100%);
  width: var(--handle-size);
  height: var(--handle-size);
  translate: -50% -50%;
  border-radius: 50%;
  background: var(--player-fg);
  box-shadow: var(--handle-shadow);
  opacity: 0;
  pointer-events: none;
}

@media (hover: hover) {
  .player-progress:hover::after,
  .player-volume:hover::after { opacity: 1; }
}

.player-progress.is-scrubbing::after,
.player-volume.is-scrubbing::after,
.player-progress:focus-visible::after,
.player-volume:focus-visible::after { opacity: 1; }

.player-progress:focus-visible,
.player-volume:focus-visible {
  outline: var(--focus-ring) solid var(--player-fg);
  outline-offset: calc(var(--focus-offset) + 2px);
}

/* --- Buttons: real buttons. Play, the skips, speed and volume act (web-player.js); the rest only press */
.player button {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: var(--focus-radius);
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.player button:focus-visible {
  outline: var(--focus-ring) solid var(--player-fg);
  outline-offset: var(--focus-offset);
}

/* Hover and pressed, from Figma (web-tokens.css). Hover only where the pointer can hover,
   so a tap doesn't leave it showing; pressed is a step darker */

/* The icon buttons and speed: a circle behind the icon, larger than the button and
   centred on it, so the layout doesn't move */
.player .player-icon-button,
.player .player-speed {
  position: relative;
  isolation: isolate; /* the circle stays behind the icon */
}

.player .player-icon-button::before,
.player .player-speed::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: -1;
  width: var(--state-circle-large);
  height: var(--state-circle-large);
  translate: -50% -50%;
  border-radius: 50%;
  pointer-events: none;
}

.player .player-skip::before,
.player .player-speed::before {
  width: var(--state-circle);
  height: var(--state-circle);
}

/* Switch to video: its fill turns the hover blue */
@media (hover: hover) {
  .player .player-icon-button:hover::before,
  .player .player-speed:hover::before,
  .player .player-switch:hover { background: var(--state-hover); }
  .player .player-play:hover { background: var(--play-hover); }
}

.player .player-icon-button:active::before,
.player .player-speed:active::before,
.player .player-switch:active { background: var(--state-pressed); }

.player .player-icon-button {
  flex: none;
  width: var(--icon-button);
  height: var(--icon-button);
}

.player .player-skip { width: var(--control-size); height: var(--control-size); }

/* The play button: an fg circle with the glyph in the colour around it (--player-cutout:
   bg, or bg under the gradient). Play, Pause and the spinner are stacked in one cell;
   Play and Pause crossfade */
.player .player-play {
  display: grid;
  place-items: center;
  flex: none;
  width: var(--play-size);
  height: var(--play-size);
  border-radius: 50%;
  background: var(--player-fg);
  transition: transform var(--press-out);
}

/* Play/Pause, pressed: a step darker than its hover blue, and the mobile spring */
.player .player-play:active {
  transform: scale(var(--play-pressed-scale));
  background: var(--play-pressed);
  transition: transform var(--press-in);
}

.player-play > * { grid-area: 1 / 1; }

.player-play .icon {
  background-color: var(--player-cutout);
  transition: opacity var(--crossfade);
}

.player-play .icon-play { translate: var(--play-glyph-shift) 0; }

.player-play .icon-pause,
.player-play.is-playing .icon-play { opacity: 0; }
.player-play.is-playing .icon-pause { opacity: 1; }

/* Buffering: not in the design. A spinner in the glyph's colour replaces the glyph while
   the audio loads or seeks */
.player-spinner {
  display: none;
  width: var(--spinner-size);
  height: var(--spinner-size);
  box-sizing: border-box;
  border: var(--spinner-stroke) solid var(--player-cutout);
  border-top-color: transparent;
  border-radius: 50%;
  animation: web-spin 1s linear infinite;
}

.player-play.is-buffering .icon { display: none; }
.player-play.is-buffering .player-spinner { display: block; }

/* --- Icons: each SVG from assets/web/ (Figma, unchanged) as a mask, painted with a
   player colour, at the SVG's own width and height --------------------------- */
.icon {
  display: block;
  flex: none;
  background-color: var(--player-fg);
  mask: var(--icon) no-repeat 0 0 / 100% 100%;
}

.icon-enter-fullscreen { --icon: url("../assets/web/enter-fullscreen.svg"); width: 32px; height: 32px; }
.icon-video-switch { --icon: url("../assets/web/video-switch.svg"); width: 18px; height: 14px; }
.icon-video-meta { --icon: url("../assets/web/video-meta.svg"); width: 18px; height: 14px; }
.icon-back-10 { --icon: url("../assets/web/back-10.svg"); width: 24px; height: 24px; }
.icon-forward-30 { --icon: url("../assets/web/forward-30.svg"); width: 24px; height: 24px; }
.icon-play { --icon: url("../assets/web/play.svg"); width: 24px; height: 24px; } /* the paused state */
.icon-pause { --icon: url("../assets/icons/pause.svg"); width: 24px; height: 24px; } /* mobile's, at 24 */
.icon-compress { --icon: url("../assets/web/compress.svg"); width: 32px; height: 32px; }
.icon-volume { --icon: url("../assets/web/volume.svg"); width: 32px; height: 32px; }

} /* [data-surface="web"] */
