/* =============================================================================
 * watch-bgea.css  —  Osborn Watch BGEA restyle (final, accessibility-first)
 *
 * Override stylesheet for the osborn-platform plugin. MUST load AFTER the built
 * player.css (handle 'osborn-platform-player').
 *
 * PATH:   apps/osborn-v3/wp-content/plugins/osborn-platform/assets/watch-bgea.css
 * HANDLE: osborn-platform-watch-bgea  (deps: ['osborn-platform-player'])
 *
 * Routes covered:
 *   /watch/<slug>/        -> templates/watch-player.php  (full BGEA chrome; React
 *                            app + no-JS fallback share .osborn-watch-page* classes)
 *   /watch/, /watch-lab/  -> templates/watch-gallery.php (renders inside the BGEA
 *                            child-theme chrome via get_header/get_footer)
 *
 * SOURCE OF TRUTH for tokens + @font-face + brand fonts:
 *   apps/osborn-v3/wp-content/plugins/osborn-platform/assets/osborn-tokens.css
 *   (handle 'osborn-platform-tokens', enqueued globally). This file consumes the
 *   tokens via var(); it must not redefine them.
 *
 * Design rule: ONLY the actual video media may stay dark; it is framed in navy.
 * Everything else is --paper/--ink, AAA-grade contrast, >=18px body, with a
 * perceptible DUAL focus ring (gold outline + ink/white halo) that works on
 * both paper and navy (gold alone is only ~2.5:1 on paper).
 * ========================================================================== */

/* Design tokens (:root) + @font-face now live in the shared osborn-tokens.css
 * (handle 'osborn-platform-tokens', enqueued globally). This file consumes them
 * via var() and carries Watch-surface component styles only. */

/* =============================================================================
 * 1) PLAYER ACCENT REMAP  —  re-skin the dark video controls to BGEA
 * ========================================================================== */
.osborn-player {
  --osborn-player-accent: var(--navy);
  --osborn-player-accent-strong: var(--gold);
  --plyr-color-main: var(--red);
  --plyr-video-control-background-hover: var(--navy);
  --plyr-range-fill-background: var(--red);
  --plyr-range-thumb-background: var(--red);
  --plyr-tooltip-background: var(--ink);
  --plyr-tooltip-color: var(--white);
}

.osborn-player :focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 4px;
  box-shadow: 0 0 0 2px var(--white);
}

.osborn-player--watch .osborn-player__frame {
  border-radius: var(--radius);
  min-height: 0;
}

.osborn-player__watch-link {
  background: var(--white);
  border: 1px solid var(--navy);
  color: var(--navy);
  font-weight: 900;
  min-height: 48px;
}
.osborn-player__watch-link:hover,
.osborn-player__watch-link:focus-visible {
  background: var(--navy);
  border-color: var(--navy);
  color: var(--white);
}

/* Click-to-play facade: poster + red play button. JS (player-facade.js) swaps in
 * the provider iframe on click; no-JS users follow the <a href> to the provider.
 * Fills the 16:9 .osborn-player__frame (which is position:relative). */
.osborn-player__facade {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  background: var(--ink) center / cover no-repeat;
  border: 0;
  cursor: pointer;
  text-decoration: none;
}
.osborn-player__facade::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(13, 48, 71, 0.28);
}
.osborn-player__facade-play {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 84px;
  height: 84px;
  padding-left: 6px; /* optical centering of the triangle */
  border-radius: 50%;
  background: var(--red);
  color: var(--white);
  box-shadow: 0 10px 30px rgba(13, 48, 71, 0.45);
  transition:
    background-color 160ms ease,
    transform 160ms ease;
}
.osborn-player__facade:hover .osborn-player__facade-play {
  background: var(--red-strong);
  transform: scale(1.05);
}
.osborn-player__facade:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 4px;
}

/* Bare facade (single-post title screen): same full-surface click target and
 * data-* wiring, but the title screen owns ALL visuals — no poster background,
 * no flat scrim, no centered play circle (PHP omits the span). z-index lifts
 * it above the scrim/info layers (later DOM siblings, so they'd otherwise
 * paint over its focus ring); it is transparent, so nothing is occluded, and
 * the siblings are pointer-events:none, so hit-testing is unchanged. */
.osborn-player__facade--bare {
  background: transparent;
  z-index: 1;
}
.osborn-player__facade--bare::after {
  content: none;
}
.osborn-player__facade--bare:focus-visible {
  outline-offset: -3px; /* the frame clips overflow; keep the ring visible */
}

/* =============================================================================
 * 2) PLAYER SINGLE-POST VIEW  —  .osborn-watch-page (React AND no-JS fallback)
 * ========================================================================== */
.osborn-platform-watch-shell {
  background: var(--paper);
  color: var(--ink);
}

.osborn-watch-page {
  --osborn-watch-edge: clamp(1rem, 3vw, 2.5rem);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--bgea-sans);
  /* Normalize fallback x-height to the web font so the swap doesn't shift text. */
  font-size-adjust: from-font;
  min-height: auto;
  overflow: visible;
}

.osborn-watch-page__backdrop {
  background: transparent;
}

.osborn-watch-page__content {
  gap: clamp(1.5rem, 3vw, 2.5rem);
  max-width: var(--max);
  margin-inline: auto;
  /* Centered max-width column -> simple BGEA gutter. The full-bleed calc()
   * formula is only for max-width:none bands; on a capped, centered column it
   * over-pads and collapses the content width on wide viewports. */
  padding: clamp(2.5rem, 5vw, 4rem) 24px;
}

.osborn-watch-page__player {
  margin-inline: 0;
  padding: 10px;
  background: var(--navy);
  border-radius: calc(var(--radius) + 4px);
  box-shadow: var(--shadow);
}

/* -----------------------------------------------------------------------------
 * 2b) TITLE SCREEN — Netflix-style pre-play stage (templates/watch-player.php)
 *
 * Layer stack is DOM order (every layer position:absolute, no z-index):
 * blurred cover backdrop -> contained sharp poster -> muted preview <video>
 * (JS-injected by player-facade.js, mp4 provider only) -> bare facade <a>
 * (the click target) -> gradient scrim -> info block. Scrim + info are
 * pointer-events:none so the whole stage clicks through to the facade.
 * -------------------------------------------------------------------------- */
.osborn-titlescreen {
  background: var(--ink);
}

/* Full-width title-screen variant shared by the Featured block and dedicated
 * Series pages. The latter is not wrapped by .osborn-watch-featured. */
.osborn-watch-gallery__hero--titlescreen {
  display: block;
  grid-template-columns: minmax(0, 1fr);
  padding: 10px;
}
.osborn-watch-gallery__hero--titlescreen .osborn-watch-gallery__player {
  width: 100%;
}
.osborn-watch-gallery__hero--titlescreen :is(h1, h2).osborn-titlescreen__title {
  color: var(--white);
  font-family: var(--bgea-serif);
  font-size: clamp(1.3rem, 3.4vw, 2.75rem);
  font-weight: 700;
  line-height: 1.05;
  margin: 0;
}
.osborn-watch-gallery__hero--titlescreen .osborn-watch-featured__description {
  display: -webkit-box;
  max-width: 34rem;
  overflow: hidden;
  color: rgba(255, 255, 255, 0.88);
  font-family: var(--bgea-sans);
  font-size: clamp(0.85rem, 1.4vw, 1rem);
  line-height: 1.45;
  margin: 0;
  text-shadow: 0 2px 16px rgba(0, 0, 0, 0.6);
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.osborn-titlescreen__backdrop,
.osborn-titlescreen__preview {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* Blurred cover fill: ambient color behind the scrim + poster card. The
 * preview video paints over it once playing. scale() hides the blur's edge
 * fringe. */
.osborn-titlescreen__backdrop {
  object-fit: cover;
  filter: blur(32px) brightness(0.5) saturate(1.15);
  transform: scale(1.15);
}

/* Padded poster card, IN FRONT of the scrim (and of the preview video), so the
 * art stays crisp and visible while the preview plays behind it. contain-fit
 * via max-width/max-height: portrait art becomes a tall right-hand card,
 * landscape art a wide one — neither is ever cropped (same source-aware-fit
 * rule as the card thumbs). */
.osborn-titlescreen__art {
  position: absolute;
  inset: clamp(0.9rem, 3.5vw, 2rem);
  pointer-events: none;
}
/* The img itself is absolutely positioned (right edge, vertically centered),
 * not flex-aligned: out-of-flow images are exempt from layout shift and from
 * Lighthouse's unsized-images audit — intrinsic dimensions are unknowable
 * server-side for these remote posters. */
.osborn-titlescreen__poster {
  position: absolute;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  width: auto;
  height: auto;
  max-width: 44%;
  max-height: 100%;
  border-radius: calc(var(--radius) - 2px);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5);
}

/* Muted background preview. 2px inset = the poster underneath stays the LCP
 * element (same trick as the homepage hero clip). Fades in only once frames
 * are actually rendering (.is-previewing set on the 'playing' event). */
.osborn-titlescreen__preview {
  inset: 2px;
  width: calc(100% - 4px);
  height: calc(100% - 4px);
  object-fit: cover;
  opacity: 0;
  transition: opacity 700ms ease;
  pointer-events: none;
}
.osborn-titlescreen.is-previewing .osborn-titlescreen__preview {
  opacity: 1;
}
/* Hover-injected provider-iframe preview (YouTube / download-less Vimeo). Shares
 * the preview layer's positioning + fade; an <iframe> just needs its border
 * cleared. Unlike the <video>/Vimeo-background path, a plain YouTube embed still
 * flashes a title bar (top) and a "More videos" chip (corner) that controls=0
 * can't suppress — so scale the iframe past the frame and let the frame's
 * overflow:hidden clip that chrome off. The mild center-crop of the video itself
 * is acceptable for a background loop (and the poster card covers the right). */
.osborn-titlescreen__preview--embed {
  border: 0;
  transform: scale(1.34);
  transform-origin: center;
}

.osborn-titlescreen__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(
      to top,
      rgba(9, 24, 33, 0.92) 0%,
      rgba(9, 24, 33, 0.6) 26%,
      rgba(9, 24, 33, 0.15) 55%,
      rgba(9, 24, 33, 0) 75%
    ),
    linear-gradient(
      to right,
      rgba(9, 24, 33, 0.66) 0%,
      rgba(9, 24, 33, 0.28) 40%,
      rgba(9, 24, 33, 0) 68%
    );
}

.osborn-titlescreen__info {
  position: absolute;
  left: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  /* Bottom-anchored + clipped: if a long title ever exceeds the 16:9 stage,
   * the kicker clips off the top and the Play pill stays visible. */
  justify-content: flex-end;
  max-height: 100%;
  overflow: hidden;
  gap: clamp(0.35rem, 1vw, 0.6rem);
  padding: clamp(1rem, 4vw, 2.75rem);
  /* Leave the right side to the poster card (max-width 44% + stage padding). */
  max-width: min(36rem, 56%);
  color: var(--white);
  pointer-events: none;
}

.osborn-titlescreen__kicker {
  color: var(--gold);
  font-family: var(--bgea-sans);
  font-size: clamp(0.7rem, 1.4vw, 0.85rem);
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.osborn-titlescreen__title {
  font-family: var(--bgea-serif);
  font-weight: 700;
  font-size: clamp(1.3rem, 3.4vw, 2.75rem);
  line-height: 1.05;
  text-wrap: balance;
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.45);
}

.osborn-titlescreen__facts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6em;
  font-family: var(--bgea-sans);
  font-size: clamp(0.8rem, 1.5vw, 0.95rem);
  font-weight: 600;
  color: rgba(255, 255, 255, 0.88);
}
/* CSS interpunct between segments — no raw glyphs in markup (emoji gotcha). */
.osborn-titlescreen__facts span + span::before {
  content: "";
  display: inline-block;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.7);
  margin-right: 0.6em;
  vertical-align: middle;
}

.osborn-titlescreen__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  font-family: var(--bgea-sans);
  font-size: clamp(0.7rem, 1.2vw, 0.82rem);
  font-weight: 700;
  line-height: 1.2;
  text-shadow: 0 2px 16px rgba(0, 0, 0, 0.6);
}
.osborn-titlescreen__tags > span {
  padding: 0.32rem 0.58rem;
  border: 1px solid rgba(255, 255, 255, 0.34);
  border-radius: 999px;
  background: rgba(9, 24, 33, 0.52);
  color: rgba(255, 255, 255, 0.92);
}
.osborn-titlescreen__tags > time {
  padding: 0.32rem 0.58rem;
  border: 1px solid rgba(255, 255, 255, 0.34);
  border-radius: 999px;
  background: rgba(9, 24, 33, 0.52);
  color: rgba(255, 255, 255, 0.92);
  font: inherit;
  letter-spacing: 0;
  text-transform: none;
}

/* Text responds immediately; media still waits for player-facade.js's trusted
 * 700 ms pointer dwell. Keyboard focus reveals the same context without
 * autoplay, while touch/coarse-pointer layouts keep their normal static copy. */
@media (hover: hover) and (pointer: fine) {
  .osborn-titlescreen__reveal-item {
    max-height: 0;
    margin-block: 0;
    overflow: hidden;
    opacity: 0;
    transform: translateY(8px);
    transition:
      max-height 240ms ease,
      opacity 180ms ease,
      transform 240ms ease;
  }
  [data-osborn-preview-region]:is(:hover, :focus-within)
    .osborn-titlescreen__reveal-item,
  .osborn-titlescreen:is(:hover, :focus-within, .is-previewing)
    .osborn-titlescreen__reveal-item {
    max-height: 9rem;
    opacity: 1;
    transform: translateY(0);
  }
  /* A published date is verification context, not optional hover detail. Keep
   * it visible even though the preview runtime groups ordinary tag rows into
   * the progressive reveal stack. */
  .osborn-titlescreen__tags--date.osborn-titlescreen__reveal-item {
    max-height: 3rem;
    opacity: 1;
    transform: none;
  }
}

.osborn-titlescreen__ctas {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: clamp(0.25rem, 1vw, 0.6rem);
}

/* Decorative Play pill: the actual control is the full-surface facade <a>
 * (aria-label "Play <title>"); this just gives it a visible affordance. */
.osborn-titlescreen__play {
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  min-height: 48px;
  padding: 10px 22px;
  background: var(--red);
  color: var(--white);
  border-radius: var(--radius);
  font-family: var(--bgea-sans);
  font-size: 1.0625rem;
  font-weight: 900;
  line-height: 1;
  box-shadow: 0 10px 30px rgba(13, 48, 71, 0.45);
  transition:
    background-color 160ms ease,
    transform 160ms ease;
}
.osborn-titlescreen__play svg {
  width: 14px;
  height: 16px;
}

/* "Play next" — a REAL link (the only interactive element inside the
 * pointer-events:none info block): pointer-events back on + z-index above the
 * facade (1) so it wins the click. Ghost pill so the red Play stays primary. */
.osborn-titlescreen__next {
  position: relative;
  z-index: 2;
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding: 10px 20px;
  background: rgba(9, 24, 33, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: var(--radius);
  color: var(--white);
  font-family: var(--bgea-sans);
  font-size: 1.0625rem;
  font-weight: 900;
  line-height: 1;
  text-decoration: none;
  transition:
    background-color 160ms ease,
    border-color 160ms ease;
}
.osborn-titlescreen__next:hover {
  background: rgba(9, 24, 33, 0.85);
  border-color: var(--white);
  color: var(--white);
}
.osborn-titlescreen__next:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--white);
}
.osborn-player__facade--bare:hover
  ~ .osborn-titlescreen__info
  .osborn-titlescreen__play,
.osborn-player__facade--bare:focus-visible
  ~ .osborn-titlescreen__info
  .osborn-titlescreen__play {
  background: var(--red-strong);
  transform: scale(1.04);
}

/* Pause/resume for the background preview (WCAG 2.2.2). JS-injected into the
 * CTA row alongside Play / Play next once the preview actually plays (the
 * bottom-right stage corner belongs to the poster card now), so no-JS /
 * reduced-motion / failed-preview pages never show it. Same interactive
 * treatment as the next-link: pointer-events back on + z-index above the
 * facade so it wins the click; clicks on it do NOT bubble into the facade
 * activation (it is not inside the <a>). */
.osborn-titlescreen__preview-toggle {
  position: relative;
  z-index: 2;
  pointer-events: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.55);
  border-radius: 50%;
  background: rgba(9, 24, 33, 0.55);
  color: var(--white);
  cursor: pointer;
  transition:
    background-color 160ms ease,
    border-color 160ms ease;
}
.osborn-titlescreen__preview-toggle:hover {
  background: rgba(9, 24, 33, 0.85);
  border-color: var(--white);
}
.osborn-titlescreen__preview-toggle:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--white);
}
.osborn-titlescreen__preview-toggle svg {
  display: none;
}
.osborn-titlescreen__preview-toggle[data-state="playing"] svg:first-child {
  display: block;
}
.osborn-titlescreen__preview-toggle[data-state="paused"] svg:last-child {
  display: block;
  margin-left: 2px; /* optical centering of the triangle */
}

/* Compact phone variant: the 16:9 stage is only ~180px tall at 375px wide, so
 * the full overlay stack can't fit. Keep title + Play pill (the real <h1> and
 * meta live right below the player anyway); drop kicker + facts; shrink type. */
@media (max-width: 540px) {
  .osborn-titlescreen__kicker,
  .osborn-titlescreen__facts,
  .osborn-titlescreen__tags,
  .osborn-titlescreen__next {
    /* Phones keep the stage minimal: title + Play + pause toggle. "Next" and
     * the full series live in the rail right below. */
    display: none;
  }
  .osborn-titlescreen__tags--date {
    display: flex;
  }
  .osborn-titlescreen__info {
    gap: 0.3rem;
    padding: 0.85rem;
    max-width: 60%;
  }
  .osborn-titlescreen__title {
    font-size: 1.05rem;
    line-height: 1.15;
  }
  .osborn-titlescreen__ctas {
    gap: 0.4rem;
    margin-top: 0.35rem;
  }
  .osborn-titlescreen__play,
  .osborn-titlescreen__next {
    min-height: 40px;
    padding: 8px 14px;
    font-size: 0.95rem;
  }
  .osborn-titlescreen__play svg {
    width: 11px;
    height: 13px;
  }
  .osborn-titlescreen__poster {
    max-width: 38%;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* JS already skips injecting the preview; belt-and-braces. */
  .osborn-titlescreen__preview {
    display: none;
  }
}

.osborn-watch-page__meta {
  max-width: 720px;
  color: var(--ink);
}

.osborn-watch-page__kicker {
  color: var(--red);
  font-size: 0.85rem;
  font-weight: 900;
  letter-spacing: 0.08em;
  margin-bottom: 0.75rem;
  text-transform: uppercase;
}

.osborn-watch-page__title {
  color: var(--ink);
  font-family: var(--bgea-serif);
  font-weight: 700;
  font-size: clamp(2.05rem, 4.5vw, 3.25rem);
  line-height: 1.05;
}

.osborn-watch-page__description {
  color: var(--ink);
  font-family: var(--bgea-sans);
  font-size: clamp(1.125rem, 1.6vw, 1.25rem);
  line-height: 1.6;
  margin-top: 1rem;
  max-width: 64ch;
}

.osborn-watch-page__body {
  color: var(--ink);
  font-family: var(--bgea-sans);
  font-size: 1.125rem;
  line-height: 1.7;
  max-width: 780px;
  width: 100%;
}
.osborn-watch-page__body > :first-child {
  margin-top: 0;
}
.osborn-watch-page__body > :last-child {
  margin-bottom: 0;
}
.osborn-watch-page__body h2,
.osborn-watch-page__body h3,
.osborn-watch-page__body h4 {
  color: var(--ink);
  font-family: var(--bgea-serif);
  line-height: 1.15;
}
.osborn-watch-page__body a {
  color: var(--navy);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}
.osborn-watch-page__body a:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 4px;
}
.osborn-watch-page__body img {
  height: auto;
  max-width: 100%;
}

.osborn-watch-page__actions {
  gap: 0.75rem;
  margin-top: 1.5rem;
}

.osborn-watch-page__link {
  align-items: center;
  background: var(--white);
  border: 1px solid var(--navy);
  border-radius: var(--radius);
  color: var(--navy);
  display: inline-flex;
  justify-content: center;
  min-height: 48px;
  font-family: var(--bgea-sans);
  font-size: 1.0625rem;
  font-weight: 900;
  line-height: 1.1;
  padding: 12px 20px;
  text-decoration: none;
  transition:
    background-color 160ms ease,
    border-color 160ms ease,
    color 160ms ease;
}
.osborn-watch-page__link:hover {
  background: var(--navy);
  border-color: var(--navy);
  color: var(--white);
}
.osborn-watch-page__link:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 4px;
  box-shadow: 0 0 0 2px var(--ink);
}

/* PRIMARY fallback "Watch on Vimeo/YouTube" link -> red CTA. Scoped to
 * --fallback ONLY (React's Transcript/Next links never reddened) and guarded
 * with :not([download]) so the download-only branch is never the loud primary. */
.osborn-watch-page--fallback .osborn-watch-page__actions
  .osborn-watch-page__link:not([download]):first-child {
  background: var(--red);
  border-color: var(--red);
  color: var(--white);
}
.osborn-watch-page--fallback
  .osborn-watch-page__actions
  .osborn-watch-page__link:not([download]):first-child:hover {
  background: var(--red-strong);
  border-color: var(--red-strong);
  color: var(--white);
}

.osborn-watch-fallback__poster {
  border-radius: var(--radius);
  background: var(--ink);
  text-decoration: none;
}
.osborn-watch-fallback__poster:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 4px;
  box-shadow: 0 0 0 2px var(--white);
}
.osborn-watch-fallback__play {
  color: var(--white);
  background: rgba(13, 48, 71, 0.4);
}

.osborn-watch-page__related {
  display: grid;
  gap: 18px;
  padding-bottom: clamp(2.5rem, 5vw, 4rem);
}

/* =============================================================================
 * 3) GALLERY DOCUMENT  —  standalone doc, no chrome
 * ========================================================================== */
.osborn-watch-gallery-document {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--bgea-sans);
  font-size-adjust: from-font;
  font-size: 1.125rem;
  line-height: 1.55;
}

.osborn-platform-watch-gallery-shell {
  background: var(--paper);
  color: var(--ink);
  /* player.css (built from packages/osborn-player) sets its own pre-BGEA
   * `Inter, ...` stack on this shell — Inter (non-Tight) is NOT shipped, so
   * every descendant fell through to system-ui instead of the brand sans
   * (caught by the verify-site font census, 2026-07-01). Same specificity,
   * this file loads after player.css (hard dependency), so we win. */
  font-family: var(--bgea-sans);
}

/* Canonical Watch hierarchy. Separators are CSS-only decoration; the current
 * page is text (not a self-link), while every ancestor remains keyboard
 * reachable. The same item resolver also feeds BreadcrumbList JSON-LD. */
.osborn-watch-breadcrumbs {
  box-sizing: border-box;
  color: var(--muted);
  font-family: var(--bgea-sans);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.5;
  margin: 0 auto;
  max-width: var(--max);
  padding: clamp(1.25rem, 3vw, 2rem) 24px 0;
  width: 100%;
}
.osborn-watch-breadcrumbs ol {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem 0.7rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.osborn-watch-breadcrumbs li {
  align-items: center;
  display: inline-flex;
  gap: 0.7rem;
  min-width: 0;
}
.osborn-watch-breadcrumbs li + li::before {
  border-color: currentColor;
  border-style: solid;
  border-width: 1px 1px 0 0;
  content: "";
  display: block;
  flex: 0 0 0.42rem;
  height: 0.42rem;
  opacity: 0.58;
  transform: rotate(45deg);
  width: 0.42rem;
}
.osborn-watch-breadcrumbs a {
  color: var(--navy);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.osborn-watch-breadcrumbs a:hover {
  color: var(--red-strong);
}
.osborn-watch-breadcrumbs a:focus-visible {
  outline: 3px solid var(--navy);
  outline-offset: 3px;
  box-shadow: 0 0 0 2px var(--white);
}
.osborn-watch-breadcrumbs [aria-current="page"] {
  color: var(--ink);
  overflow-wrap: anywhere;
}
.osborn-watch-breadcrumbs + .osborn-watch-gallery {
  padding-top: clamp(1rem, 2vw, 1.5rem);
}
.osborn-watch-page__content > .osborn-watch-breadcrumbs {
  margin: 0;
  max-width: none;
  padding: 0;
}

.osborn-watch-gallery {
  --osborn-gallery-border: var(--line);
  --osborn-gallery-muted: var(--muted);
  --osborn-gallery-card-width: 300px;
  gap: clamp(2rem, 4vw, 2.75rem);
  max-width: var(--max);
  /* Centered max-width column -> simple BGEA gutter (see note in section 2). */
  padding: clamp(1.5rem, 4vw, 2.5rem) 24px;
  /* player.css sets `display:grid` with no explicit columns, so the single
   * implicit track is `auto` and grows to a descendant's min-content. On
   * narrow viewports that blew the whole gallery past the screen edge (the
   * navy hero, search, chips and cards all overflowed to the right on mobile,
   * pre-existing). Pin the track to the container width and let each child
   * shrink inside it — the canonical grid-blowout fix. */
  grid-template-columns: minmax(0, 1fr);
}
.osborn-watch-gallery > * {
  min-width: 0;
}

/* Reset player.css's max-width:1680px + padding:2.5rem so the navy hero panel
 * and the catalog rails share one 1180px edge gutter (no floating panel). */
.osborn-watch-gallery__hero,
.osborn-watch-gallery__catalog {
  margin: 0;
  max-width: none;
  padding-inline: 0;
}

.osborn-watch-gallery__hero {
  align-items: stretch;
  background: var(--navy);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: clamp(1.25rem, 3vw, 2rem);
  padding-bottom: clamp(1.25rem, 3vw, 2rem);
  gap: clamp(1.25rem, 3vw, 2rem);
}

.osborn-watch-gallery__player > [data-osborn-player-root],
.osborn-watch-gallery__player .osborn-player__frame {
  border-radius: var(--radius);
}
.osborn-watch-gallery__player .osborn-player {
  box-shadow: var(--shadow-deep);
}

.osborn-watch-gallery__empty-player {
  background:
    linear-gradient(135deg, rgba(197, 150, 59, 0.22), transparent 48%),
    var(--navy);
  border: 1px solid var(--line-on-navy);
  border-radius: var(--radius);
}

.osborn-watch-gallery__active {
  border-left: 1px solid var(--line-on-navy);
  /* With the meta column clamped (title + description below) it can be
   * shorter than the 16:9 player; the stretched grid item would otherwise
   * distribute the slack between its rows. */
  align-content: start;
}
.osborn-watch-gallery__active p:not(.osborn-watch-gallery__eyebrow) {
  color: var(--on-navy-body);
  line-height: 1.6;
  /* Import descriptions run to 1,000+ chars (chapter dumps); clamp the panel
   * copy — the full text still lives on the single-video page. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  line-clamp: 4;
  overflow: hidden;
}

.osborn-watch-gallery__eyebrow {
  color: var(--red);
  font-size: 0.82rem;
  font-weight: 900;
}
.osborn-watch-gallery__hero .osborn-watch-gallery__eyebrow,
.osborn-watch-gallery__empty-player .osborn-watch-gallery__eyebrow {
  color: var(--gold-on-navy);
}

/* player.css forces ALL gallery headings to #fff -> invisible on paper.
 * Base (0,1,0) = ink+serif; hero scope (0,2,0) re-whitens h1 on navy. */
.osborn-watch-gallery h1,
.osborn-watch-gallery h2,
.osborn-watch-gallery h3 {
  color: var(--ink);
  font-family: var(--bgea-serif);
  font-weight: 700;
  line-height: 1.05;
}
.osborn-watch-gallery__hero h1,
.osborn-watch-gallery__hero h2,
.osborn-watch-gallery__empty-player h1,
.osborn-watch-gallery__active h1 {
  color: var(--white);
}
.osborn-watch-gallery__empty-player h1 {
  font-size: clamp(1.75rem, 4vw, 2.4rem);
}

/* Now-playing title: player.css's 3rem gallery h1 is sized for full-width
 * catalog headings; in the ~320px aside a long fragment title became a
 * seven-line tower taller than the player. Size for the column instead
 * (same specificity as player.css's .osborn-watch-gallery h1/h2 — this file
 * loads after, so we win). Covers the h1 (bare Library) and the h2 that the
 * topic views demote it to (watch-gallery.php). */
.osborn-watch-gallery__active h1,
.osborn-watch-gallery__active h2 {
  font-size: clamp(1.45rem, 2vw, 1.9rem);
  line-height: 1.2;
  overflow-wrap: break-word;
  text-wrap: balance;
}

/* Topic landing header (/watch/topic/<term>/) — the collection leads the
 * page; sits on paper above the navy hero panel. */
.osborn-watch-gallery__topic-header {
  display: grid;
  gap: 0.5rem;
  justify-items: start;
}
.osborn-watch-gallery__topic-header h1 {
  font-size: clamp(2.05rem, 3.6vw, 2.6rem);
  text-wrap: balance;
}
.osborn-watch-gallery__topic-meta {
  color: var(--muted);
  font-weight: 700;
  margin: 0;
}
.osborn-watch-gallery__topic-meta a {
  color: var(--navy);
  text-underline-offset: 3px;
}

.osborn-watch-gallery__facts {
  border-top-color: var(--line-on-navy);
}
.osborn-watch-gallery__facts div {
  border-bottom-color: var(--line-on-navy);
}
.osborn-watch-gallery__facts dt {
  color: var(--on-navy-label);
}
.osborn-watch-gallery__facts dd {
  color: var(--white);
}

.osborn-watch-gallery__catalog {
  gap: 2rem;
}

/* Toolbar: catalog heading on the left, search form on the right. Previously
 * had no layout rule, so the form fell below the heading at every width. */
.osborn-watch-gallery__toolbar {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
}
.osborn-watch-gallery__toolbar > div {
  min-width: 0;
}

/* The visible search shell is route-owned and must paint before Pagefind's
 * deferred result-panel stylesheet arrives on interaction. */
.osborn-search-form {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 8px;
  max-width: 420px;
  margin: 0;
  padding: 6px;
  background: rgba(255, 255, 255, 0.94);
  border: 1px solid var(--line, rgba(18, 33, 42, 0.16));
  border-radius: 9px;
}
.osborn-search-form input,
.osborn-search-form button {
  min-height: 44px;
  border: 0;
  border-radius: 6px;
  font: inherit;
}
.osborn-search-form input {
  min-width: 0;
  background: transparent;
  padding: 0 12px;
  color: var(--ink, #12212a);
}
.osborn-search-form button {
  background: var(--ink, #12212a);
  color: #fff;
  font-weight: 900;
  text-transform: uppercase;
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  padding: 0 18px;
  cursor: pointer;
}
.osborn-watch-gallery__toolbar .osborn-search-form {
  flex: 0 1 420px;
}
/* Topic views drop the toolbar heading (the topic header + rail header already
 * name the collection), leaving just the in-collection search — align it left. */
.osborn-watch-gallery__toolbar--search-only {
  justify-content: flex-start;
}

.osborn-watch-gallery__rail-header > span {
  color: var(--muted);
  font-weight: 900;
}

/* A page can already supply the collection name immediately above a Watch Row.
 * Keep the row heading in the document outline and as its aria-labelledby
 * target, while removing the repeated visual label from that page context. */
.osborn-watch-gallery__rail-header--screen-reader {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Horizontal rails need room inside their scrollport for the lifted card
 * shadow. Declaring overflow-y:visible alone cannot expose it: CSS computes
 * that axis to auto whenever overflow-x scrolls. Expand the scrollport by the
 * same amount as its inline padding so the padded content area remains exactly
 * as wide as the surrounding column, then offset it back so the first card
 * still aligns with the rail header and neighboring sections.
 *
 * Chromium pixel measurement of the transformed hover state found the first
 * non-transparent shadow pixel 47.75px beyond each card side, 29.85px above,
 * and 66.36px below. Including the 3.5% scale and -4px lift relative to the
 * card's untransformed row position requires 53px inline, 39px above, and 68px
 * below; these values round up to the spacing scale with a small safety margin. */
.osborn-watch-gallery__rail:not(.osborn-watch-gallery__rail--grid) {
  --osborn-gallery-rail-shadow-gutter: 3.5rem;
  /* content-visibility:auto adds paint containment to every rail. Extend that
   * containment clip through the padded scrollport or it will still cut off
   * the scaled card and shadow even when the track geometry is correct. */
  overflow-clip-margin: var(--osborn-gallery-rail-shadow-gutter);
}
.osborn-watch-gallery__rail:not(.osborn-watch-gallery__rail--grid)
  > .osborn-watch-gallery__rail-track {
  box-sizing: border-box;
  width: calc(
    100% +
    var(--osborn-gallery-rail-shadow-gutter) +
    var(--osborn-gallery-rail-shadow-gutter)
  );
  margin-inline: calc(-1 * var(--osborn-gallery-rail-shadow-gutter));
  padding: 2.75rem var(--osborn-gallery-rail-shadow-gutter) 4.5rem;
  overflow-x: auto;
  overflow-y: visible;
  scroll-padding-inline: var(--osborn-gallery-rail-shadow-gutter);
}

/* Optional "View all →" link on a Watch Row (→ its /watch/topic/ landing). Spans
 * its own header row so it never fights the count / paddle grid columns. The arrow
 * is CSS pseudo-content, not an HTML codepoint — twemoji can't box a ::after glyph
 * (see the emoji-glyph gotcha, play_icon_svg() in watch-route.php). */
.osborn-watch-gallery__rail-viewall {
  grid-column: 1 / -1;
  justify-self: start;
  font-size: 0.8rem;
  font-weight: 800;
  color: var(--navy);
  text-decoration: none;
}
.osborn-watch-gallery__rail-viewall::after {
  content: " \2192";
}
.osborn-watch-gallery__rail-viewall:hover {
  text-decoration: underline;
}

/* Grid track (.osborn-watch-gallery__rail--grid): the same cards, wrapping into
 * a responsive grid instead of the horizontal scroller player.css sets up.
 * Used on /watch/topic/<slug>/ (one collection IS the page) and by the Watch
 * Row block's "grid" layout. Narrow screens still use the shared card width as
 * their minimum; full desktop grids switch to an explicit four-up layout below
 * so tall poster collections show more titles without squeezing tablets. */
.osborn-watch-gallery__rail--grid :where(.osborn-watch-gallery__rail-track) {
  grid-auto-flow: row;
  grid-auto-columns: unset;
  grid-template-columns: repeat(
      auto-fill,
      minmax(min(var(--osborn-gallery-card-width, 280px), 100%), 1fr)
    );
  overflow: visible;
  overscroll-behavior-inline: auto;
  scroll-snap-type: none;
}
@media (min-width: 1100px) {
  .osborn-watch-gallery__rail--grid :where(.osborn-watch-gallery__rail-track) {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.osborn-watch-gallery__filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}
/* Keep the chips hidden until pagefind-search.js wires them (it removes [hidden]).
 * Needed because the display:flex above would otherwise override the attribute. */
.osborn-watch-gallery__filters[hidden] {
  display: none;
}
/* A collection chip filters the Library by toggling [hidden] on the rails that
 * don't match (applyRailFilter() in pagefind-search.js). player.css styles the
 * rail `display: grid`, which overrides the UA [hidden] rule, so without this the
 * filtered-out rails stay on screen and the chips look inert. Same fix as above. */
.osborn-watch-gallery__rail[hidden] {
  display: none;
}

/* Media-library facade poster: a real <img> child of the facade anchor (native
 * srcset + eager LCP fetch), replacing the old inline background-image. Fills
 * the anchor exactly like background-size:cover did; the play button follows it
 * in DOM order, so it keeps painting on top. */
.osborn-player__facade {
  position: relative;
  overflow: hidden;
}
.osborn-player__facade-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.osborn-player__facade-poster--contain {
  object-fit: contain;
}

/* Below-fold rails skip layout/paint until they approach the viewport — /watch/
 * renders ~10 rails / 1,100+ DOM nodes and only the hero + first rail are ever
 * in the first paint. The intrinsic-size placeholder (`auto` = remembered size
 * after first render) keeps the scrollbar stable; content stays in the a11y
 * tree, so the aria-live counts and Pagefind chip filtering are unaffected. */
.osborn-watch-gallery__rail {
  content-visibility: auto;
  contain-intrinsic-size: auto 360px;
}
/* Grid rails are one tall wrapping collection, not an offscreen horizontal row.
 * They do not scroll inside their track, so paint containment has no benefit
 * here and clips the scaled card at the grid boundary. Let the card and shadow
 * paint outside both the track and rail. */
.osborn-watch-gallery__rail--grid {
  content-visibility: visible;
  contain-intrinsic-size: none;
  overflow: visible;
}
/* A tall-poster rail is roughly 620px including its heading and card body. Give
 * content-visibility a matching first-visit placeholder so scrolling does not
 * jump when the 30:43 cards approach the viewport. */
.osborn-watch-gallery__rail--poster:not(.osborn-watch-gallery__rail--grid) {
  contain-intrinsic-size: auto 620px;
}
.osborn-watch-gallery__filter {
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink);
  font-weight: 900;
  min-height: 44px;
  padding: 9px 15px;
}
.osborn-watch-gallery__filter strong {
  color: var(--green);
}
.osborn-watch-gallery__filter[aria-current="page"] {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--ink);
}
/* FIX: green-on-gold is only 3.38:1; force the active count badge to ink. */
.osborn-watch-gallery__filter[aria-current="page"] strong {
  color: var(--ink);
}
/* Collection NAV (Watch Library block): server-rendered <a> pills to the full
 * /watch/topic/ grids, replacing the collapse-to-one-rail filter chips
 * (2026-07-09). Reuses the chip pill look above; these rules only adapt it from
 * <button> to <a> (anchors underline and baseline-align by default). Always
 * visible — real links, no JS wiring to wait for. */
.osborn-watch-gallery__collection-nav a.osborn-watch-gallery__filter {
  align-items: center;
  display: inline-flex;
  gap: 6px;
  text-decoration: none;
}
/* Grid membership sub-filters (watch-filters.js): toggle buttons above a topic
 * grid. Same pill look; active state is aria-pressed (a toggle, not a location),
 * mirroring the aria-current gold above. */
.osborn-watch-gallery__grid-filters {
  flex: 1 1 32rem;
}
.osborn-watch-gallery__grid-tools {
  align-items: end;
  display: flex;
  flex-wrap: wrap;
  gap: 12px 18px;
  justify-content: space-between;
  margin-bottom: 6px;
}
.osborn-watch-gallery__sort {
  align-items: center;
  color: var(--muted);
  display: flex;
  flex: 0 0 auto;
  font-size: 0.8rem;
  font-weight: 800;
  gap: 8px;
}
.osborn-watch-gallery__sort select {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink);
  font: inherit;
  min-height: 44px;
  padding: 8px 34px 8px 12px;
}
.osborn-watch-gallery__filter[aria-pressed="true"] {
  background: var(--gold);
  border-color: var(--gold);
  color: var(--ink);
}
.osborn-watch-gallery__filter[aria-pressed="true"] strong {
  color: var(--ink);
}
/* Filtered-out grid cards hide via [hidden]; the card's own display rules would
 * otherwise override the UA attribute style (same class of fix as the
 * rail[hidden] rule above). */
.osborn-watch-gallery__card[hidden] {
  display: none;
}

/* Provider-filter CSS removed with the provider filter UI (2026-06-22 Osborn
 * sync). Do not re-add [data-provider-filter] / card[data-provider] rules — the
 * Watch/Library UI no longer filters or labels by YouTube/Vimeo/MP4. */

.osborn-watch-gallery__card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink);
  position: relative;
  transform-origin: center;
}
.osborn-watch-gallery__card[aria-current="true"] {
  border-color: var(--red);
  box-shadow: 0 0 0 2px rgba(181, 58, 47, 0.3);
}

.osborn-watch-gallery__thumb {
  background: linear-gradient(135deg, var(--navy), var(--ink));
  color: rgba(255, 255, 255, 0.82);
}
/* Croppable landscape/4:3 featured images fill the card by default. The PHP
 * renderer marks portrait posters and gives them an uncropped source; those use
 * contain so titles/artwork stay whole. Legacy non-YouTube thumbs already carry
 * transparent padding from build-watch-poster-thumbs.mjs. */
.osborn-watch-gallery__thumb img {
  object-fit: cover;
}
.osborn-watch-gallery__thumb--contain img {
  object-fit: contain;
}
/* Manual Watch Row mode for collections made entirely of portrait posters.
 * 600x860 (30:43) is the modal source size. The renderer supplies an uncropped
 * image, then this frame makes the small, centered cover crop at display time —
 * no 16:9 letterbox and no hard-cropped derivative. */
.osborn-watch-gallery__rail--poster .osborn-watch-gallery__thumb {
  aspect-ratio: 30 / 43;
}
.osborn-watch-gallery__rail--poster .osborn-watch-gallery__thumb img {
  object-fit: cover;
  object-position: 50% 50%;
}

/* Card hover preview (desktop/mouse only; injected by player-facade.js). Sits
 * over the poster inside the thumb's overflow:hidden / 16:9 box and fades in once
 * the iframe loads. pointer-events off so the click still lands on the card link;
 * aria-hidden + tabindex -1 keep it out of the a11y tree. The YouTube variant is
 * scaled past the frame so overflow clips its title bar / "More videos" chrome
 * (same trick as the title-screen embed). z-index 2 covers the ::before play
 * triangle + ::after gradient. */
.osborn-watch-gallery__card-preview {
  position: absolute;
  /* 2x the thumb, centred, clipped by the thumb's overflow:hidden. The oversize
   * is deliberate: a small YouTube embed refuses muted autoplay AND shows a big
   * fraction of chrome, so we hand it a player twice the thumb's size (which
   * autoplays) and let the overflow crop the title bar / watermark / captions off
   * the edges. translate() centres it reliably (percentage top/left do not). */
  top: 50%;
  left: 50%;
  width: 200%;
  height: 200%;
  transform: translate(-50%, -50%);
  border: 0;
  opacity: 0;
  transition: opacity 240ms ease;
  pointer-events: none;
  z-index: 2;
  background: var(--ink, #12212a);
}
.osborn-watch-gallery__thumb.is-previewing .osborn-watch-gallery__card-preview {
  opacity: 1;
}
.osborn-watch-gallery__card-preview:is(video) {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
@media (prefers-reduced-motion: reduce) {
  .osborn-watch-gallery__card-preview {
    transition: none;
  }
}

.osborn-watch-gallery__card-body {
  padding: 18px 20px;
}
.osborn-watch-gallery__card-title {
  color: var(--ink);
  font-family: var(--bgea-serif);
  font-size: 1.1rem;
  font-weight: 700;
  line-height: 1.2;
}
.osborn-watch-gallery__card-meta {
  color: var(--green);
  font-weight: 900;
  text-transform: uppercase;
  font-size: 0.74rem;
  letter-spacing: 0.03em;
}
.osborn-watch-gallery__card-meta--date {
  letter-spacing: 0;
  text-transform: none;
}
.osborn-watch-gallery__card-meta--date time {
  color: inherit;
  font: inherit;
}

.osborn-watch-gallery__active-date time {
  font-weight: 800;
}

.osborn-watch-gallery__card-reveal {
  display: none;
}

@media (hover: hover) and (pointer: fine) {
  .osborn-watch-gallery__card-reveal {
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 3;
    display: flex;
    min-height: 9rem;
    max-height: 68%;
    flex-direction: column;
    gap: 0.45rem;
    overflow: hidden;
    padding: clamp(1rem, 1.8vw, 1.35rem);
    border-radius: 0 0 calc(var(--radius) - 1px) calc(var(--radius) - 1px);
    background:
      linear-gradient(180deg, rgba(9, 24, 33, 0.9), rgba(9, 24, 33, 0.98)),
      var(--navy);
    box-shadow: 0 -20px 40px rgba(9, 24, 33, 0.36);
    color: var(--white);
    opacity: 0;
    pointer-events: none;
    transform: translateY(12px);
    transition:
      opacity 180ms ease,
      transform 220ms ease;
  }
  .osborn-watch-gallery__rail:not(.osborn-watch-gallery__rail--poster)
    .osborn-watch-gallery__card-body,
  .osborn-watch-gallery__rail:not(.osborn-watch-gallery__rail--poster)
    .osborn-watch-gallery__card-reveal {
    grid-row: 2;
    grid-column: 1;
  }
  .osborn-watch-gallery__rail:not(.osborn-watch-gallery__rail--poster)
    > .osborn-watch-gallery__rail-track {
    grid-auto-rows: max-content;
  }
  .osborn-watch-gallery__rail:not(.osborn-watch-gallery__rail--poster)
    .osborn-watch-gallery__card-reveal {
    position: relative;
    inset: auto;
    box-sizing: border-box;
    width: 100%;
    height: auto;
    min-height: 0;
    max-height: none;
    align-self: stretch;
    box-shadow: none;
  }
  .osborn-watch-gallery__card:not(.is-preview-dismissed):is(
      :hover,
      :focus-visible,
      .is-previewing
    )
    .osborn-watch-gallery__card-reveal {
    opacity: 1;
    transform: translateY(0);
  }
  .osborn-watch-gallery__card:not(.is-preview-dismissed):is(
      :hover,
      :focus-visible,
      .is-previewing
    ) {
    z-index: 4;
    transform: translateY(-4px) scale(1.035);
  }
}

.osborn-watch-gallery__card-reveal-kicker {
  color: var(--gold);
  font-family: var(--bgea-sans);
  font-size: 0.7rem;
  font-weight: 900;
  letter-spacing: 0.07em;
  line-height: 1.2;
  text-transform: uppercase;
}
.osborn-watch-gallery__card-reveal-title {
  display: -webkit-box;
  overflow: hidden;
  color: var(--white);
  font-family: var(--bgea-serif);
  font-size: clamp(0.98rem, 1.5vw, 1.18rem);
  font-weight: 700;
  line-height: 1.2;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
.osborn-watch-gallery__card-reveal-copy {
  display: -webkit-box;
  overflow: hidden;
  color: rgba(255, 255, 255, 0.88);
  font-family: var(--bgea-sans);
  font-size: 0.82rem;
  font-weight: 600;
  line-height: 1.4;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
}
.osborn-watch-gallery__card-reveal-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: auto;
  color: rgba(255, 255, 255, 0.9);
  font-family: var(--bgea-sans);
  font-size: 0.67rem;
  font-weight: 800;
  line-height: 1.2;
}
.osborn-watch-gallery__card-reveal-tags > span {
  max-width: 100%;
  overflow: hidden;
  padding: 0.24rem 0.45rem;
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: 999px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.osborn-watch-gallery__filter:hover,
.osborn-watch-gallery__card:hover {
  border-color: var(--navy);
}
.osborn-watch-gallery__filter:focus-visible,
.osborn-watch-gallery__card:focus-visible,
.osborn-watch-gallery__rail-track:focus-visible,
.osborn-watch-gallery a:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 4px;
  box-shadow: 0 0 0 2px var(--ink);
}
.osborn-watch-gallery__card:hover,
.osborn-watch-gallery__card:focus-visible {
  box-shadow: var(--shadow);
}

/* Rail prev/next paddles — a click affordance for mouse users (rail-nav.js).
 * Hidden by default: they appear only on hover-capable fine-pointer devices
 * wider than the mobile breakpoint, and only after rail-nav.js confirms the
 * track actually overflows ([data-osborn-rail-nav-ready]). Touch, no-JS, and
 * the static mirror render the header exactly as before. The chevrons are
 * inline SVG — never ‹/›/arrow codepoints (emoji-glyph gotcha, see
 * play_icon_svg() in watch-route.php). Smooth paddle scrolling rides the
 * track's CSS scroll-behavior, which the reduced-motion block below resets. */
.osborn-watch-gallery__rail-track {
  scroll-behavior: smooth;
}
.osborn-watch-gallery__rail-nav {
  display: none;
}
@media (hover: hover) and (pointer: fine) and (min-width: 721px) {
  /* Third header column for the paddle cluster; collapses to 0 when the nav
   * is hidden, so the pre-paddle layout is preserved exactly. */
  .osborn-watch-gallery__rail-header {
    grid-template-columns: minmax(0, 1fr) auto auto;
  }
  .osborn-watch-gallery__rail-nav[data-osborn-rail-nav-ready] {
    display: inline-flex;
    gap: 8px;
    align-self: end;
  }
  .osborn-watch-gallery__rail-nav button {
    display: inline-grid;
    place-items: center;
    inline-size: 36px;
    block-size: 36px;
    padding: 0;
    background: transparent;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    color: var(--ink);
    cursor: pointer;
    transition:
      border-color 0.15s ease,
      background-color 0.15s ease,
      color 0.15s ease;
  }
  .osborn-watch-gallery__rail-nav button:hover:not(:disabled) {
    background: var(--navy);
    border-color: var(--navy);
    color: var(--white);
  }
  .osborn-watch-gallery__rail-nav button:focus-visible {
    outline: 3px solid var(--gold);
    outline-offset: 2px;
    box-shadow: 0 0 0 2px var(--ink);
  }
  .osborn-watch-gallery__rail-nav button:disabled {
    opacity: 0.35;
    cursor: default;
  }
}

/* =============================================================================
 * 4) RESPONSIVE
 * ========================================================================== */
@media (max-width: 720px) {
  .osborn-search-form {
    grid-template-columns: 1fr;
  }
  .osborn-watch-page__content {
    padding-inline: 1rem;
  }
  .osborn-watch-page__player {
    margin-inline: 0;
  }
  .osborn-watch-page__actions {
    flex-direction: column;
    align-items: stretch;
  }
  .osborn-watch-page__link {
    width: 100%;
  }

  .osborn-watch-gallery {
    --osborn-gallery-card-width: min(80vw, 300px);
    padding-inline: 16px;
  }
  .osborn-watch-gallery__hero {
    padding: 1.25rem;
  }
  .osborn-watch-gallery__active {
    border-left: 0;
    border-top: 1px solid var(--line-on-navy);
    padding: 1rem 0 0;
  }
  /* Stack the toolbar and let the form fill the width on small screens.
   * align-items:stretch overrides the desktop flex-end so the form (a flex
   * item in the stacked column) spans full width instead of shrinking. */
  .osborn-watch-gallery__toolbar {
    flex-direction: column;
    align-items: stretch;
  }
  .osborn-watch-gallery__toolbar .osborn-search-form {
    width: 100%;
    max-width: none;
    flex-basis: auto;
  }
}

/* =============================================================================
 * 5) REDUCED MOTION  —  extend player.css block to gallery cards/filters/rail
 * ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .osborn-player *,
  .osborn-watch-page *,
  .osborn-watch-gallery__card,
  .osborn-watch-gallery__filter {
    transition-delay: 0ms !important;
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .osborn-watch-gallery__rail-track {
    scroll-behavior: auto !important;
  }
  .osborn-watch-gallery__card:hover,
  .osborn-watch-gallery__card:focus-visible {
    transform: none !important;
  }
  .osborn-watch-gallery__card:not(.is-preview-dismissed):is(
      :hover,
      :focus-visible,
      .is-previewing
    )
    .osborn-watch-gallery__card-reveal {
    transform: none;
    transition: none;
  }
}
