/**
 * Media kit — the ASSET PICKER chrome (MK-4a; widened to two surfaces 2026-09-02).
 *
 * TWO SELECTOR FAMILIES, and the split is the point:
 *
 *   `.pb-picker-surface`      — every dialog whose job is "pick an asset for a
 *                               slot". The image picker and the SVG library both
 *                               carry it, and both therefore measure the same:
 *                               dialog height, zeroed body padding, the
 *                               chip/scroll/gate gutters, the tile dressing, the
 *                               footer band and the drop outline.
 *   `.pb-image-picker-modal`  — what is genuinely the image picker's alone:
 *                               liveness dressing, the accepted flash, its phone
 *                               gutter.
 *
 * The SVG library shipped for its whole life as a visually different product
 * doing the same job — its search stacked under the title instead of sitting in
 * the header bar, its sources a `.pb-code-tabs` strip instead of a segmented
 * pill at the head of the chip row, its cards 68px squares against the picker's
 * full-track frames, and no upload tile at all. It was fixed three times by
 * copying values across, and drifted again each time. SHARING THE CLASS IS THE
 * FIX; a second opinion about the look is what let them drift.
 *
 * Linked AFTER property-panel.css, which is where these rules came from and
 * which still owns the two families both dialogs share:
 * `.pb-image-picker-key-prompt` (and its message/title children) and
 * `.pb-image-picker-load-more`. Neither is duplicated here — the picker no
 * longer builds a load-more of its own, and the gate prompt is one look for
 * two dialogs.
 *
 * Everything the collection kit owns is ABSENT on purpose: no grid, no card,
 * no search field, no chip row, no skeleton, no empty state. The picker's
 * whole list is `.pb-coll-*` now, and a rule here that re-styled one of those
 * would be a private fork of the kit for one surface.
 */

/* ── The dialog ─────────────────────────────────────────────────────────── */

.pb-picker-surface {
  /* Fixed height so the dialog does not resize when switching source, when a
     search returns fewer rows, or when the detail view opens. The list scrolls
     inside it instead. */
  height: min(760px, 85dvh);
  max-height: 85dvh;
  display: flex;
  flex-direction: column;
}

.pb-picker-surface .pb-modal-body {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  /* Zeroed ON PURPOSE. Every band inside pays its own inset from
     --pb-picker-gutter (tokens.css) so the SCROLLER can span the full width;
     that token's comment is where the whole arrangement is written down. */
  padding: 0;
  display: flex;
  flex-direction: column;
}

/* ── THE BAR ────────────────────────────────────────────────────────────────
   DS-1: PROMOTED. The bar, the queue strip, the slot chip and the two meta
   lines all moved to collection.css as `.pb-coll-bar` / `.pb-coll-queue` /
   `.pb-coll-slots` / `.pb-coll-slot` / `.pb-coll-queue-title` /
   `.pb-coll-queue-sub`, together with their phone grid. This sheet's own
   header is what predicted the move: a rule HERE that re-styles something the
   kit owns is a private fork by construction, and the queue became something
   the kit owns the moment a second surface needed it.

   Nothing replaced them. The picker passes `queue: {...}` to
   `openCollectionBrowser` and gets the identical shape from the shared sheet. */

/* The toolbar is left holding nothing once the search moves out. Collapsed
   rather than removed: the kit built it and the kit's own code still looks it
   up (the select-all checkbox mounts there on selection surfaces). */
.pb-picker-surface .pb-coll-toolbar:empty {
  display: none;
}

/* ── The bands, each paying the gutter ──────────────────────────────────── */

/* Source and filter together: both narrow what the GRID shows, where the bar
   above is about the target. The rule is the separation, not the saving. */
.pb-picker-surface .pb-coll-chips {
  gap: var(--pb-space-4);
  padding: var(--pb-space-5) var(--pb-picker-gutter);
}

.pb-picker-surface .pb-coll-drawer {
  margin: 0 var(--pb-picker-gutter) var(--pb-space-4);
}

/* The scroller keeps its own left/right inset rather than inheriting one: the
   scrollbar then rides the dialog edge and the grid clears it. */
.pb-picker-surface .pb-coll-scroll {
  padding: 0 var(--pb-picker-gutter) var(--pb-space-8);
}

/* The gutter is the picker's, and the band needs air UNDER it: the scroller
   below carries no top padding (its top edge is normally the chip row's own
   bottom padding), so the first tile in the grid sat flush against this
   banner's bottom border. The space rides the banner rather than the scroller
   because the banner is the conditional element — a top padding on the scroller
   would double the gap under the chip row on every scope that never shows a
   gate. */
.pb-picker-surface .pb-image-picker-key-prompt {
  padding: var(--pb-space-4) var(--pb-picker-gutter);
  margin-bottom: var(--pb-space-6);
}

/* The source controls (MK-4b), inserted at the head of the kit's CHIP row.
   Only the PLACEMENT is here: `.pb-seg` in builder.css owns the look, and a
   second opinion about it would fork the primitive MK-1a exists to prevent.

   The rule that separates it from the chips beside it is a divider, not a gap —
   "which library" and "which category" are different questions asked in the
   same row, and a gap alone reads as one long list of filters. */
.pb-picker-sources {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  flex: none;
  gap: var(--pb-space-3);
  margin-inline-end: var(--pb-space-2);
  padding-inline-end: var(--pb-space-4);
  border-inline-end: 1px solid var(--pb-border);
}

/* The provider row is subordinate to the scope, and says so at a glance. */
.pb-image-picker-providers {
  font-size: var(--pb-font-sm);
}

/* ── The phone sheet ────────────────────────────────────────────────────────
   ONE control row is a desktop shape. In a 390px sheet the segmented control is
   ~180px of fixed width, which left the search field about 120 wide — narrower
   than its own placeholder. It stacks, search FIRST: the field is what the
   thumb reaches for, and the scope is a decision you make once. The gutter
   halves for the same reason the track does — 48px of chrome out of 390 is an
   eighth of the sheet spent on nothing. */
@media (max-width: 640px) {
  .pb-picker-surface {
    --pb-picker-gutter: var(--pb-space-6);
  }

  /* DS-1: the phone grid, the two grid-area assignments and the scrolling
     strip all moved to collection.css with the queue. What stays is the ONE
     declaration that is this surface's rather than the kit's — the gutter,
     which is `--pb-picker-gutter` and belongs to the picker's band system.
     This sheet is linked after collection.css, so it wins the tie. */
  .pb-picker-surface .pb-coll-bar {
    padding: var(--pb-space-5) var(--pb-picker-gutter);
  }

  /* The sheet's own bottom corners are SQUARE (it sits on the viewport edge),
     so the band that paints them must be too — the desktop rounding above
     would carve two notches out of the bottom of the sheet. */
  .pb-picker-surface .pb-image-picker-foot {
    border-radius: 0;
  }
}

/* ── The whole dialog is a drop target (MK-4a) ──────────────────────────── */

/* The upload PANE used to be the only place a drop landed, so dropping onto
   the grid — the obvious gesture once the grid is what fills the dialog — did
   nothing. The outline is drawn inside the card so it cannot be clipped by the
   overlay, and `pointer-events` stays untouched: suppressing them on the card
   would cancel the dragover that keeps the drop alive. */
.pb-picker-surface.pb-drag-over::after {
  content: '';
  position: absolute;
  inset: var(--pb-space-2);
  border: 2px dashed var(--pb-accent);
  border-radius: var(--pb-radius-lg);
  background: color-mix(in srgb, var(--pb-accent) 8%, transparent);
  pointer-events: none;
  z-index: var(--pb-z-base);
}

/* ── Status, footer band, paging ────────────────────────────────────────── */

/* Messages — "type at least 2 characters", a partial fan-out note, a reach
   failure. Above the footer, centred, and gone entirely when there is nothing
   to say. */
.pb-image-picker-status {
  margin: 0;
  text-align: center;
  color: var(--pb-text-dim);
  font-size: var(--pb-font-base);
  padding: var(--pb-space-4) var(--pb-picker-gutter) 0;
}

.pb-image-picker-status:empty {
  display: none;
}

/* What the list holds, and who it came from. A band rather than two centred
   lines: the count is a fact about the grid above it and the attribution is a
   credit, and stacking them centre-aligned made one look like a caption of the
   other. */
/* Must beat `display: flex` below — see the same guard on the key prompt in
   property-panel.css. */
.pb-image-picker-foot[hidden] {
  display: none;
}

/* The band is the dialog's last child AND the only one that paints its own
   background, so it — not `.pb-modal` — is what the bottom corners are made of.
   Without this the card's rounded corners were squared off by an opaque
   rectangle sitting on top of them. Minus the 1px card border, which is what
   the radius is measured from. The kit's own `.pb-modal-footer` needs no
   equivalent: it is transparent, so the card's own corner shows through. */
.pb-image-picker-foot {
  display: flex;
  align-items: center;
  gap: var(--pb-space-5);
  padding: var(--pb-space-5) var(--pb-picker-gutter);
  border-top: 1px solid var(--pb-border-soft);
  border-radius: 0 0 calc(var(--pb-modal-radius) - 1px) calc(var(--pb-modal-radius) - 1px);
  background: var(--pb-surface-2);
  color: var(--pb-text-dim);
  font-size: var(--pb-font-base);
}

.pb-image-picker-count {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pb-image-picker-attribution {
  margin-left: auto;
  text-align: right;
  color: var(--pb-text-dim);
  font-size: var(--pb-font-sm);
  opacity: 0.7;
}

.pb-image-picker-more {
  display: block;
  margin: var(--pb-space-6) auto 0;
}

/* ── The tile ───────────────────────────────────────────────────────────────
   The kit owns the card; these are the two places an IMAGE tile differs from a
   record card, and both are consequences of the same rule — the frame is the
   only bordered object and the caption sits on the dialog surface beneath it.

   With a 4px gap the filename read as a label attached to the picture above it
   AND to the picture below it at the same time; the tile needs to be more
   strongly grouped than the grid. 2px of optical inset lines the text edge up
   with the frame's hairline rather than with its outer box. */
.pb-picker-surface .pb-coll-card,
.pb-picker-surface .pb-coll-tile-primary {
  gap: var(--pb-space-4h);
}

.pb-picker-surface .pb-coll-title,
.pb-picker-surface .pb-coll-meta-line {
  padding-inline: var(--pb-space-1);
}

/* The upload TILE takes the same frame ratio as a record, because it sits in
   the same row as one. Records ask the kit for `aspect: 'wide'` (3/2) and a
   tile has no poster spec to ask with, so it kept the default 16/10 — 8px
   shorter, which put its caption on a different baseline from every caption
   beside it. */
.pb-picker-surface .pb-coll-tile .pb-coll-poster {
  aspect-ratio: var(--pb-coll-poster-ratio-wide);
}

/* `1600×900 · WEBP` is a column of numbers read down the grid, so it gets
   tabular figures. It deliberately keeps the kit's `--pb-text-dim` and does NOT
   take the prototype's `--pb-text-faint`: the prototype has no dark register,
   and faint on the dark surface measures 3.6:1 against dim's 6.8:1 — below AA
   for 11px text. The size and weight already subordinate it. */
.pb-picker-surface .pb-coll-meta-line {
  font-variant-numeric: tabular-nums;
}

/* Upload is the one tile that CREATES rather than picks, and the accent is how
   it says so. The kit's neutral `create` dressing is right in a catalog where
   the tile competes with 40 records; here it is the first thing in the grid and
   the only route to a file on your own machine. */
.pb-picker-surface .pb-coll-tile-create .pb-coll-poster {
  border-color: var(--pb-accent);
  background: var(--pb-accent-tint);
  color: var(--pb-accent);
}

/* The hover deepens the SAME wash rather than taking the kit's
   `--pb-accent-subtle`, which is a solid mid-blue — a jump from an 8% tint to a
   55% fill reads as a different control, not as the same one under a cursor. */
.pb-picker-surface .pb-coll-tile-create .pb-coll-tile-primary:hover .pb-coll-poster,
.pb-picker-surface .pb-coll-tile-create .pb-coll-tile-primary:focus-visible .pb-coll-poster {
  background: var(--pb-accent-glow);
  color: var(--pb-accent);
}

/* ── Liveness (MK-3, re-expressed against the kit's item) ───────────────── */

/* Two DIFFERENT states, and collapsing them would be a lie in one direction
   or the other.

   A DEAD SOURCE is proven: the corpus sweep found the url on a dead origin AND
   unsatisfiable from any reference bundle. The kit already paints
   `aria-disabled` from `state.disabled` and the card's META LINE says "Source
   offline" — real text, not generated content, so a screen reader announces it
   and a test can assert it. This is only what makes it LOOK like a record
   rather than a control.

   A FAILED PREVIEW is not a verdict on the pick — the thumbnail is a smaller
   VARIANT url, not the canonical one `download()` fetches — so that card stays
   live and merely stops pretending it has a picture. */
.pb-image-picker-modal .pb-coll-item[aria-disabled='true'] {
  cursor: default;
  opacity: 0.55;
  filter: saturate(0.35);
}

.pb-image-picker-modal .pb-coll-poster > img[data-pb-thumb-failed] {
  /* Kept in flow — the poster still reserves its 3/2 box, so nothing reflows
     when a thumbnail gives up. `.pb-checker` is deliberately not used: a failed
     preview is an ABSENCE, and the checkerboard is a claim about
     transparency. */
  visibility: hidden;
}

.pb-image-picker-modal .pb-coll-poster:has(> img[data-pb-thumb-failed])::before {
  content: 'Preview unavailable';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--pb-space-3);
  text-align: center;
  font-size: var(--pb-font-xs);
  color: var(--pb-text-faint);
}

/* ── The detail view ────────────────────────────────────────────────────── */

.pb-image-detail {
  display: flex;
  flex-direction: column;
  gap: var(--pb-space-4);
  padding: var(--pb-space-6);
}

.pb-image-detail-frame {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: var(--pb-coll-poster-ratio-wide);
  border-radius: var(--pb-coll-poster-radius);
  overflow: hidden;
  background: var(--pb-surface-2);
}

.pb-image-detail-frame > img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: cover;
}

/* The same rule the poster follows: shown whole, inset, and NEVER scaled past
   natural size. `object-fit` alone would still stretch the element to the box. */
.pb-image-detail-contain > img {
  padding: var(--pb-coll-poster-pad);
  object-fit: contain;
}

.pb-image-detail-title {
  margin: 0;
  font-size: var(--pb-font-xl);
  font-weight: 600;
  color: var(--pb-text-bright);
  overflow-wrap: anywhere;
}

.pb-image-detail-meta {
  margin: 0;
  color: var(--pb-text-dim);
  font-size: var(--pb-font-sm);
}

.pb-image-detail-offline {
  margin: 0;
  padding: var(--pb-space-3) var(--pb-space-4);
  border-radius: var(--pb-radius);
  background: var(--pb-danger-bg);
  color: var(--pb-text);
  font-size: var(--pb-font-sm);
}

/* ── The variant chooser ────────────────────────────────────────────────── */

/* What this replaces: a "4 sizes" badge that opened a popover of inert <div>s
   with no click handler. It looked like a control, absorbed a click, and could
   not act. A radio group because the choice is exclusive and one option is
   always in effect. */
.pb-image-detail-variants {
  margin: 0;
  padding: var(--pb-space-3);
  border: 1px solid var(--pb-border);
  border-radius: var(--pb-radius);
}

.pb-image-detail-variants legend {
  padding: 0 var(--pb-space-2);
  font-size: var(--pb-font-xs);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--pb-text-dim);
}

.pb-image-detail-variant {
  display: flex;
  align-items: center;
  gap: var(--pb-space-3);
  padding: var(--pb-space-2);
  border-radius: var(--pb-radius-sm);
  cursor: pointer;
}

.pb-image-detail-variant:hover {
  background: var(--pb-surface-hover);
}

.pb-image-detail-variant:focus-within {
  outline: 2px solid var(--pb-accent);
  outline-offset: -2px;
}

.pb-image-detail-variant-label {
  font-weight: 600;
  color: var(--pb-text);
}

.pb-image-detail-variant small {
  color: var(--pb-text-faint);
  font-size: var(--pb-font-xs);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The detail stage's Back and Use ride the DIALOG HEADER now
   (`.pb-dialog-header-action`, builder.css); the row that used to hold them at
   the bottom of the body is gone with them. */

/* ── The accept beat (MK-6) ─────────────────────────────────────────────── */

/* The first beat of the dismissal: the card the user chose presses, while the
   dialog's own exit animation is already running. Nothing new is minted — the
   ring pulse is `feedback.landed()`, the repo's ONE landed animation, and the
   attention-keyframe ledger stays at 14. This is only the press.

   `transform` on the POSTER rather than the item, so it composites without
   disturbing the grid track and cannot nudge its neighbours. */
.pb-image-picker-modal .pb-coll-accepted .pb-coll-poster {
  transform: scale(0.96);
  transition: transform 140ms cubic-bezier(0.34, 1.4, 0.64, 1);
}

@media (prefers-reduced-motion: reduce) {
  .pb-image-picker-modal .pb-coll-item,
  .pb-image-picker-modal .pb-coll-poster,
  .pb-image-detail-variant,
  .pb-image-picker-modal .pb-coll-accepted .pb-coll-poster {
    /* `none`, never a short duration — a 1ms transition still schedules a
       frame and still animates; the rule is that reduced motion means no
       motion, not fast motion. */
    transition: none;
  }

  /* The press is a TRANSFORM, so suppressing its transition is not enough —
     the end state would simply snap to 96%. `markAccepted` also returns early
     under reduced motion, and this is the belt to that brace: a class applied
     by any other path must still not move anything. */
  .pb-image-picker-modal .pb-coll-accepted .pb-coll-poster {
    transform: none;
  }
}
