/* =========================================================
   mbrd - cover art and the two media players on a card
   Split from items.css. Shares the transport row and scrubber shape
   with the now-playing bar. Caption plate is in item-chrome.css.
   ========================================================= */

/* Cover art inside a card (coverEl(), canvas/renderers.ts). Flex, not
   fixed aspect -- crops to the room the text leaves. */
.card-cover {
  flex: 1;
  min-height: 0;
  width: 100%;
  object-fit: cover;
  display: block;
  border-radius: var(--radius-sm);
  /* Hairline edge for pale covers on pale card stock. */
  box-shadow: 0 0 0 var(--board-hairline) color-mix(in srgb, var(--ink) 10%, transparent);
}

/* Kicker is redundant above a picture -- except on audio cards, where
   hiding it made some sleeves say AUDIO and others not. */
.card:not(.card-audio).has-cover .card-icon { display: none; }

/* Audio sleeve: square, in the corner, out of flow. Padding on the
   three text lines below clears it. */
.card-audio .card-cover {
  position: absolute;
  top: var(--card-pad-y);
  right: var(--card-pad-x);
  width: var(--sleeve);
  height: var(--sleeve);
  flex: none;
}
.card-audio {
  /* Sleeve sized in container units: fills empty height, capped at ~half
     the width so the title keeps its side. */
  --sleeve: clamp(44px, min(100cqh - 76px, 100cqw * 0.52), 320px);
  /* Room for the handle taken sideways, not as height -- height is what
     an audio card has least of. */
  padding-bottom: var(--card-pad-y);
  /* Container queries below decide what to drop as the card shrinks. */
  container: audio-card / size;
}
.card-audio.has-cover .card-icon,
.card-audio.has-cover .card-name,
.card-audio.has-cover .card-meta {
  padding-right: calc(var(--sleeve) + 10px);
}

/* Title clamped to stop the transport being pushed out through the
   bottom. -webkit- only: no engine takes unprefixed line-clamp without
   the -webkit- form. */
.card-audio .card-name {
  flex: 0 1 auto;
  min-height: 0;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}
/* Transport pinned to the foot; stops short of the handle's corner. */
.card-audio .transport {
  flex: none;
  padding-right: var(--handle-w);
}

/* Shedding order as the card shrinks. Full selectors needed because
   container queries carry no specificity. */
@container audio-card (max-height: 150px) {
  .card-audio .card-icon { display: none; }
}
@container audio-card (max-height: 126px) {
  .card-audio .card-name { -webkit-line-clamp: 2; }
}
/* Just below the clamp: the 2-line name buys back a line, so the
   footnote survives a little past where a 3-line card would drop it. */
@container audio-card (max-height: 116px) {
  .card-audio .card-meta { display: none; }
}
@container audio-card (max-height: 100px) {
  .card-audio .card-name { -webkit-line-clamp: 1; }
}

/* The <audio> element is the engine, not the interface. */
.card-audio audio { display: none; }

.transport {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: auto;
  pointer-events: auto;
}
.transport .play {
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: var(--board-hairline) solid var(--accent-text);
  border-radius: 50%;
  background: none;
  color: var(--accent-text);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
              transform var(--dur-base) var(--ease-back);
}
.transport .play svg { width: 13px; height: 13px; }
@media (hover: hover) {
  .transport .play:hover { background: var(--accent); color: var(--accent-fg); transform: scale(var(--btn-grow)); }
}
.transport.is-playing .play { background: var(--accent); color: var(--accent-fg); }

/* Waveform: RMS bars mirrored about centre. Rounded with the interface. */
.wave {
  position: relative;
  flex: 1;
  min-width: 0;
  height: 40px;
  cursor: pointer;
}
/* Two stacked lanes: the quiet one is the whole waveform, the accent one
   is clipped to the playhead so the fill can cut a bar in half. */
.wave-lane {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  gap: 1px;
}
.wave-lane i {
  flex: 1;
  min-width: 1px;
  border-radius: var(--radius-pill);
}
.wave-base i { background: color-mix(in srgb, var(--ink) 38%, transparent); }
.wave-fill {
  clip-path: inset(0 100% 0 0);
}
/* Compositing layer only while playing -- idle cards give it back. */
.transport.is-playing .wave-fill {
  will-change: clip-path;
}
.wave-fill i { background: var(--accent); }
.transport-time {
  flex: none;
  font-family: var(--font-mono);
  font-size: var(--t-tiny);
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}

/* Past the far-zoom rung the card becomes a button. The waveform, name
   and clock are sub-pixel noise at this scale. */
#world.zoom-far .card-audio .card-icon,
#world.zoom-far .card-audio .card-name,
#world.zoom-far .card-audio .card-meta,
#world.zoom-far .card-audio .wave,
#world.zoom-far .card-audio .transport-time { display: none; }

/* The card's own pad goes: the head brings its own, and the button needs the
   room. The transport fills what the head leaves (--ix-head, item-chrome.css). */
#world.zoom-far .card-audio { padding: 0; }
#world.zoom-far .card-audio .transport {
  position: absolute;
  inset: var(--ix-head) 0 0;
  margin-top: 0;
  justify-content: center;
  /* Handle is hidden at this zoom, so no corner to clear. */
  padding: 0;
}
#world.zoom-far .card-audio .play {
  /* As large as the room under the name allows, and never past 60% of the
     card's short half. Sized off the half alone, it was taller than that room
     on an ordinary card and hung off the foot. 100cqh is the card's height
     (container: audio-card above), less the head and a pad under the button. */
  --far-play: max(0px, min(calc(var(--half-min, 98px) * 0.6),
                           calc(100cqh - var(--ix-head) - var(--ix-pad))));
  width:  var(--far-play);
  height: var(--far-play);
  /* Ring thickens with the button or it antialiases away. */
  border-width: max(var(--board-hairline), calc(var(--far-play) * 0.05));
}
#world.zoom-far .card-audio .play svg { width: 38%; height: 38%; }

/* At far zoom, a sleeve card shows the art full-bleed with the play
   button over it -- a recognisable record from across the board. */
#world.zoom-far .card-audio.has-cover::after { content: none; }

#world.zoom-far .card-audio.has-cover .card-cover {
  position: absolute;
  inset: 0;
  /* Both dimensions needed: the corner-sleeve rule above sets a width. */
  width: 100%;
  height: 100%;
  border-radius: inherit;
  box-shadow: none;
}
/* No head over a sleeve, so the button centres on the whole card, over the
   art (a later sibling, so it paints above it). */
#world.zoom-far .card-audio.has-cover .transport { inset: 0; }
/* Plate under the button over artwork -- accent ring alone disappears
   on a dark sleeve. */
#world.zoom-far .card-audio.has-cover .play {
  --far-play: calc(var(--half-min, 98px) * 0.6);
  background: color-mix(in srgb, var(--paper-card) 84%, transparent);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
}

/* Video transport (canvas/video.ts). Floats over the picture; hidden
   until selected or playing. pointer-events off so the card stays
   one drag target. */
.vplayer {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
}

/* Centre play button on a parked video. Sized from --half-min so it
   belongs to the card's scale, with floor and ceiling. */
.vbig {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  display: grid;
  place-items: center;
  width:  clamp(30px, calc(var(--half-min, 100px) * 0.42), 92px);
  height: clamp(30px, calc(var(--half-min, 100px) * 0.42), 92px);
  padding: 0;
  border: var(--board-hairline) solid var(--accent-text);
  border-radius: 50%;
  background: var(--paper-card);
  color: var(--accent-text);
  cursor: pointer;
  pointer-events: auto;
  transition: opacity var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease),
              scale var(--dur-base) var(--ease-back);
}
.vbig svg { width: 40%; height: 40%; }
/* scale, not transform -- translate above is doing the centring. */
@media (hover: hover) {
  .vbig:hover { background: var(--accent); color: var(--accent-fg); scale: var(--btn-grow); }
}
.vplayer.is-playing .vbig { opacity: 0; pointer-events: none; }

/* Stopped waveform is not a control -- the card face stays a drag
   target until there is something to seek through. */
.transport:not(.is-playing) .wave {
  pointer-events: none;
  cursor: inherit;
}

/* Caption hidden at rest on images and video -- the picture is the card.
   Back on hover, focus, and while editing. */
.item[data-type="image"] .item-bar,
.item[data-type="video"] .item-bar {
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease);
}
.item[data-type="image"]:hover .item-bar,
.item[data-type="image"]:focus-within .item-bar,
.item[data-type="image"].is-editing .item-bar,
.item[data-type="video"]:hover .item-bar,
.item[data-type="video"]:focus-within .item-bar,
.item[data-type="video"].is-editing .item-bar { opacity: 1; }

/* Playing clip hides its caption (a label over moving video reads as
   damage) but keeps the handle for the touch menu. */
.item:has(.vplayer.is-playing) .item-label { opacity: 0; }
.item:has(.vplayer.is-playing) .item-bar {
  background: none;
  border-top-color: transparent;
  /* Must also stop catching the pointer -- the invisible plate was
     blocking tap-to-pause. */
  pointer-events: none;
}

/* Far zoom: the big play button goes -- a clip that far out is a swatch. */
#world.zoom-far .vbig { display: none; }

/* Unplayable clip (markUnplayable(), canvas/renderers.ts). Controls go
   rather than greying out -- the honest reading is nothing to press. */
.item.is-unplayable .vbig,
.item.is-unplayable .transport { display: none; }

.media-dead {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 6px 10px;
  font-size: var(--t-small);
  font-style: var(--display-italic);
  color: var(--ink-3);
  background: var(--paper-card);
  border-top: var(--board-hairline) solid var(--rule);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}
/* On a card it is one of the plate's rows, not a strip over a picture. */
.card .media-dead {
  position: static;
  padding: 6px 0 0;
  background: none;
  border-top: none;
}
#world.zoom-far .media-dead { display: none; }

/* Fallback without color-mix() -- see tokens.css section 7. */
@supports not (color: color-mix(in srgb, red, blue)) {
  .card-cover { box-shadow: 0 0 0 var(--board-hairline) rgb(var(--ink-c) / 10%); }
  .wave-base i { background: rgb(var(--ink-c) / 38%); }
  #world.zoom-far .card-audio.has-cover .play {
    background: rgb(var(--paper-card-c) / 84%);
  }
}
