/* ==========================================================================
   page-shorts.css — owned by templates/video_app/shorts.html
                     and templates/video_app/shorts_detail.html

   The feed is a scroll-snapped column of 9:16 players that owns its own
   scroll container: `overflow-y: auto` + `scroll-snap-type: y mandatory` on
   .yt-shorts__scroller, sized to the viewport minus the sticky masthead. It
   has to be its own scroller rather than the document, for two reasons —
   mandatory snapping on the document fights the sticky masthead, and
   shorts.js hands this element to its IntersectionObserver as `root`, so the
   ratio it measures is the ratio the visitor actually sees.

   Structure both templates emit:

     .yt-shorts[data-vt-shorts][data-mode][data-muted]
       .yt-shorts__stack            (detail only — the column beside the panel)
       .yt-shorts__scroller         the snap container
         .yt-shorts__slide          one snap stop, full height
           .yt-shorts__stage        the 9:16 box: video + every overlay
           .yt-shorts__rail         48px circles, outside the box ≥900px
       .yt-shorts__nav              up / down chevrons + position counter
       .yt-shorts__hint             keyboard legend
       .yt-shorts__panel            comments (detail only)
       .yt-shorts__scrim            the bottom sheet's backdrop (<900px)

   Reused as-is, never re-implemented here: .yt-icon-btn / .yt-icon-btn--lg
   (already the 48px circle the rail spec asks for), .yt-btn / .yt-btn--mono,
   .yt-pill--sm, .yt-card__status, .yt-avatar, .yt-empty, .yt-truncate,
   .yt-sr-only, .yt-mono.

   Non-token literals here, and why (no token exists for them):
     #fff                       every label that sits ON the video. --yt-fg
                                flips to near-black in the light theme and
                                would vanish over the picture; components.css
                                takes the same decision for its overlay
                                badges.
     #000                       the letterbox behind a contained video, again
                                matching components.css.
     rgba(0,0,0,.28 … .72)      the gradient shades and control backings that
                                keep #fff legible over a bright frame.
     rgba(255,255,255,.16/.35)  the seek track and the subscribed pill, both
                                on that same always-dark surface.
     480px / 854px              the widest the 9:16 stage is allowed to grow
                                on a tall monitor (480 × 16/9 = 853.3). Both
                                caps agree, so the box never letterboxes just
                                because the window is tall.
     900px / 1100px             breakpoints: below 900 the rail moves inside
                                the picture and the comments panel becomes a
                                bottom sheet; below 1100 the desktop-only
                                chevrons and keyboard legend go away on the
                                feed, where scroll and keys still work.
     424px                      the comments panel, matching the watch page's
                                402px secondary column plus its gutter.
     44 / 45                    z-index for the mobile sheet and its scrim:
                                deliberately under the masthead's 60, because
                                the sheet is not a focus trap and navigation
                                must stay reachable behind it.
   ========================================================================== */

/* ==========================================================================
   1. SHELL
   ========================================================================== */

.yt-shorts {
  position: relative;
  /* A column, so the <noscript> notice the feed renders with scripting off
     takes its height off the scroller instead of pushing the bottom of the
     feed out of the clipped box. With scripting on it has no height at all. */
  display: flex;
  flex-direction: column;
  /* Two declarations, not one: dvh is ignored by older engines, which then
     keep the vh line above it. */
  height: calc(100vh - var(--yt-masthead-h));
  height: calc(100dvh - var(--yt-masthead-h));
  min-height: 320px;
  overflow: hidden;
  background: var(--yt-bg);
}

.yt-shorts__scroller {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scroll-snap-type: y mandatory;
  /* A flick at the end of the feed must not start scrolling the page behind
     it, or the masthead slides away mid-swipe. */
  overscroll-behavior-y: contain;
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.yt-shorts__scroller::-webkit-scrollbar { width: 0; height: 0; }

/* The scroller is focusable (tabindex="-1") so shorts.js can move focus here
   after a keyboard jump without stealing it from a control. */
.yt-shorts__scroller:focus { outline: none; }

.yt-shorts__slide {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  height: 100%;
  padding: 12px 12px 12px 24px;
  box-sizing: border-box;
  scroll-snap-align: center;
  /* One slide per gesture: a hard flick must not skip three Shorts, each of
     which would then be asked to load. */
  scroll-snap-stop: always;
}

/* ==========================================================================
   2. THE 9:16 STAGE

   width is derived from the height by aspect-ratio, and both dimensions are
   capped. object-fit: contain (never cover) is what keeps a 3:4 or 1:1
   "vertical" upload from being cropped — is_short only guarantees taller than
   wide, and width/height are nullable, so the exact ratio is never assumed.
   ========================================================================== */

.yt-shorts__stage {
  position: relative;
  flex: 0 1 auto;
  min-width: 0;
  aspect-ratio: 9 / 16;
  height: 100%;
  max-height: min(100%, 854px);
  width: auto;
  max-width: min(100%, 480px);
  border-radius: var(--yt-radius-md);
  overflow: hidden;
  background: #000;
  isolation: isolate;
}

/* The shade that keeps #fff legible over a bright frame: dark at the top for
   the sound button, dark at the bottom for the overlay block. */
.yt-shorts__stage::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    none;
  background-color: rgba(0, 0, 0, .38);   /* flat scrim over the clip */
}

.yt-shorts__video {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* No background of its own: the stage supplies the letterbox, and an opaque
     video would hide the no-thumbnail watermark sitting behind it. */
  background: transparent;
  display: block;
}

/* Shown when the row has no thumbnail: a watermark behind the video rather
   than a black rectangle that reads as a broken player. It is covered as soon
   as the first frame paints. */
.yt-shorts__blank {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, .35);
}

/* The <video> fallback paragraph, shown only by an engine that cannot play
   the file at all. */
.yt-shorts__fallback-copy {
  padding: 24px;
  color: #fff;
  font-size: 14px;
  text-align: center;
}

.yt-shorts__fallback-copy a { color: var(--yt-accent); text-decoration: underline; }

/* ==========================================================================
   3. PLAY / PAUSE SURFACE
   ========================================================================== */

.yt-shorts__surface {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  background: none;
  border: 0;
  cursor: pointer;
  /* No focus ring on the surface itself — it would trace the whole picture.
     The ring is drawn as an inset on the stage instead. */
  outline: none;
}

.yt-shorts__surface:focus-visible {
  box-shadow: inset 0 0 0 3px var(--yt-accent);
  border-radius: var(--yt-radius-md);
}

.yt-shorts__play {
  position: absolute;
  z-index: 3;
  top: 50%;
  left: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 72px;
  height: 72px;
  margin: -36px 0 0 -36px;
  border-radius: 50%;
  background: rgba(0, 0, 0, .6);
  color: #fff;
  opacity: 0;
  transform: scale(.86);
  transition: opacity var(--yt-transition), transform var(--yt-transition);
  pointer-events: none;
}

.yt-shorts__slide[data-paused="1"] .yt-shorts__play {
  opacity: 1;
  transform: scale(1);
}

/* ==========================================================================
   4. SOUND — the unmute affordance

   Muted is the default because every browser refuses to autoplay with sound
   before the visitor has interacted with the page, so the state has to be
   advertised rather than hidden: an icon button plus a worded pill, both
   carrying data-vt-shorts-mute.
   ========================================================================== */

.yt-shorts__sound {
  position: absolute;
  z-index: 4;
  top: 8px;
  right: 8px;
}

.yt-shorts__sound-btn {
  background: rgba(0, 0, 0, .5);
  color: #fff;
}

.yt-shorts__sound-btn:hover { background: rgba(0, 0, 0, .72); }

.yt-shorts__sound-hint {
  position: absolute;
  z-index: 4;
  top: 56px;
  right: 8px;
  background: rgba(0, 0, 0, .62);
  color: #fff;
  /* visibility, not opacity alone: it also takes the pill out of the tab
     order while it is hidden. */
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--yt-transition), visibility var(--yt-transition);
}

.yt-shorts__sound-hint:hover { background: rgba(0, 0, 0, .82); }

.yt-shorts[data-muted="1"] .yt-shorts__slide[data-active="1"] .yt-shorts__sound-hint {
  opacity: 1;
  visibility: visible;
}

/* Autoplay with sound was actually refused: make the pill unmissable. */
.yt-shorts[data-sound-blocked="1"] .yt-shorts__slide[data-active="1"] .yt-shorts__sound-hint {
  background: var(--yt-brand);
  color: #fff;
}

/* ==========================================================================
   5. SEEK BAR

   A real <input type="range">, so it is keyboard operable for free and
   shorts.js can leave arrow-key seeking to the browser while the input has
   focus (its own ↑/↓ handler bails on form controls). The played portion is a
   gradient driven by --vt-played, which the script updates; Firefox draws
   ::-moz-range-progress over the same track.
   ========================================================================== */

.yt-shorts__seek-wrap {
  position: absolute;
  z-index: 4;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 0 10px 4px;
}

.yt-shorts__seek {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: 16px;
  margin: 0;
  background: transparent;
  cursor: pointer;
}

.yt-shorts__seek::-webkit-slider-runnable-track {
  height: 3px;
  border-radius: 2px;
  /* Both colour stops sit at the SAME position, so this is a hard edge — two
     flat blocks, no visible blend. It is the only way to fill a native range
     input's track; there is no separate fill element to style. */
  background: linear-gradient(
    to right,
    var(--yt-brand) var(--vt-played, 0%),
    rgba(255, 255, 255, .35) var(--vt-played, 0%)
  );
}

.yt-shorts__seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 12px;
  height: 12px;
  margin-top: -4.5px;
  border: 0;
  border-radius: 50%;
  background: #fff;
}

.yt-shorts__seek::-moz-range-track {
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, .35);
}

.yt-shorts__seek::-moz-range-progress {
  height: 3px;
  border-radius: 2px;
  background: var(--yt-brand);
}

.yt-shorts__seek::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border: 0;
  border-radius: 50%;
  background: #fff;
}

.yt-shorts__seek:focus-visible {
  outline: 2px solid var(--yt-accent);
  outline-offset: 2px;
}

/* ==========================================================================
   6. BOTTOM-LEFT OVERLAY

   pointer-events: none on the block, auto on its controls — the gradient and
   the empty space beside the title stay part of the tap-to-pause surface.
   ========================================================================== */

.yt-shorts__meta {
  position: absolute;
  z-index: 5;
  left: 0;
  right: 0;
  bottom: 20px;
  padding: 0 12px;
  color: #fff;
  pointer-events: none;
}

/* right: 0 on desktop because the rail is outside the picture there; the
   ≤899px block reserves the 64px the overlaid rail needs. */

.yt-shorts__meta a,
.yt-shorts__meta button,
.yt-shorts__meta summary { pointer-events: auto; }

.yt-shorts__owner {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  min-width: 0;
}

.yt-shorts__handle {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  color: #fff;
  font-size: 14px;
  font-weight: 500;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
}

.yt-shorts__handle:hover > span { text-decoration: underline; }
.yt-shorts__handle--anon { opacity: .9; }
.yt-shorts__handle--anon:hover > span { text-decoration: none; }

.yt-shorts__subscribe {
  height: 32px;
  padding: 0 12px;
  flex: 0 0 auto;
  font-size: 13px;
}

/* app.js drops --mono when the subscribed state flips on, so the subscribed
   pill needs its own legible-over-video treatment. */
.yt-shorts__subscribe.yt-btn--subscribed {
  background: rgba(255, 255, 255, .16);
  color: #fff;
}

/* A Short whose row has no channel: the pill stays focusable (aria-disabled,
   not disabled) so its explanation is reachable, and reads as unavailable. */
.yt-shorts__subscribe[aria-disabled="true"] {
  opacity: .55;
  cursor: not-allowed;
}

.yt-shorts__title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  max-height: 2.9em;
  margin: 0 0 6px;
  color: #fff;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.4;
  /* A 200-character title with no spaces still has to wrap. */
  overflow-wrap: anywhere;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
}

.yt-shorts__title a { color: inherit; }
.yt-shorts__title a:hover { text-decoration: underline; }

.yt-shorts__stats {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  color: #fff;
  font-size: 13px;
  opacity: .92;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
}

.yt-shorts__desc {
  margin-top: 8px;
  max-width: 40ch;
  font-size: 13px;
}

.yt-shorts__desc > summary {
  display: inline-flex;
  align-items: center;
  height: 28px;
  padding: 0 10px;
  border-radius: 14px;
  background: rgba(0, 0, 0, .55);
  color: #fff;
  cursor: pointer;
  list-style: none;
}

.yt-shorts__desc > summary::-webkit-details-marker { display: none; }
.yt-shorts__desc[open] > summary { margin-bottom: 6px; }

.yt-shorts__desc-body {
  max-height: 26vh;
  overflow-y: auto;
  padding: 8px 10px;
  border-radius: var(--yt-radius-sm);
  background: rgba(0, 0, 0, .62);
  color: #fff;
  line-height: 1.5;
  overflow-wrap: anywhere;
  pointer-events: auto;
}

.yt-shorts__desc-body a { color: var(--yt-accent); }

/* ==========================================================================
   7. RIGHT-HAND RAIL

   ≥900px it sits beside the picture, on the page background, so it uses the
   theme tokens. <900px it moves inside the picture and switches to the
   over-video palette.
   ========================================================================== */

.yt-shorts__rail {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  flex: 0 0 auto;
  width: 56px;
}

.yt-shorts__rail-item {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.yt-shorts__rail-btn {
  background: var(--yt-bg-chip);
  color: var(--yt-fg);
}

.yt-shorts__rail-btn:hover { background: var(--yt-bg-hover); }

.yt-shorts__rail-btn[aria-pressed="true"] { color: var(--yt-accent); }

.yt-shorts__rail-count {
  max-width: 56px;
  color: var(--yt-fg-secondary);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.2;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 899px) {
  .yt-shorts__slide { padding: 0; gap: 0; }

  /* Full bleed, like mobile YouTube. */
  .yt-shorts__stage {
    max-width: 100%;
    max-height: 100%;
    border-radius: 0;
  }

  .yt-shorts__rail {
    position: absolute;
    z-index: 6;
    right: 4px;
    bottom: 92px;
    width: 56px;
    gap: 12px;
  }

  .yt-shorts__rail-btn {
    background: rgba(0, 0, 0, .38);
    color: #fff;
  }

  .yt-shorts__rail-btn:hover { background: rgba(0, 0, 0, .62); }
  .yt-shorts__rail-btn[aria-pressed="true"] { color: var(--yt-accent); }

  .yt-shorts__rail-count {
    color: #fff;
    text-shadow: 0 1px 2px rgba(0, 0, 0, .7);
  }

  .yt-shorts__meta { right: 64px; bottom: 24px; }
}

/* ==========================================================================
   8. NAVIGATION CHEVRONS + POSITION COUNTER
   ========================================================================== */

.yt-shorts__nav {
  position: absolute;
  z-index: 7;
  right: 16px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.yt-shorts__nav-btn {
  background: var(--yt-bg-chip);
  color: var(--yt-fg);
}

.yt-shorts__nav-btn:hover { background: var(--yt-bg-hover); }
.yt-shorts__nav-btn[disabled] { opacity: .35; }

.yt-shorts__counter {
  color: var(--yt-fg-secondary);
  font-size: 12px;
  letter-spacing: .02em;
}

.yt-shorts__hint {
  position: absolute;
  z-index: 7;
  left: 16px;
  bottom: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: 42ch;
  color: var(--yt-fg-secondary);
  font-size: 12px;
  line-height: 1.4;
}

.yt-shorts__hint kbd {
  display: inline-block;
  min-width: 18px;
  padding: 1px 4px;
  border: 1px solid var(--yt-border);
  border-radius: 4px;
  background: var(--yt-bg-chip);
  color: var(--yt-fg);
  font-family: var(--yt-font);
  font-size: 11px;
  text-align: center;
}

.yt-shorts__noscript {
  margin: 0;
  padding: 12px 16px;
  border-bottom: 1px solid var(--yt-border);
  background: var(--yt-bg-elevated);
  color: var(--yt-fg);
  font-size: 13px;
  line-height: 1.5;
}

/* Below 1100px the gutter these live in is gone. The feed loses them —
   scrolling and the keyboard both still work — while the detail page keeps
   them, because there they are the only prev/next control, and drops them
   into the flow under the player instead of over it. */
@media (max-width: 1100px) {
  .yt-shorts__nav,
  .yt-shorts__hint { display: none; }

  .yt-shorts--detail .yt-shorts__nav {
    display: flex;
    position: static;
    transform: none;
    flex-direction: row;
    justify-content: center;
    gap: 16px;
    padding: 8px 12px;
  }

  .yt-shorts--detail .yt-shorts__hint {
    display: flex;
    position: static;
    justify-content: center;
    flex-wrap: wrap;
    max-width: none;
    padding: 0 12px 10px;
    text-align: center;
  }
}

/* ==========================================================================
   9. DETAIL LAYOUT + COMMENTS PANEL

   Desktop: .yt-shorts--detail is a flex row, so the panel is a sibling of the
   player column and opening it pushes the stage left rather than covering it.
   The panel keeps a fixed-width inner box while the outer flex basis animates,
   so its content never squashes mid-slide.
   Mobile (<900px): the same element becomes a bottom sheet over a scrim.
   ========================================================================== */

.yt-shorts--detail {
  display: flex;
  flex-direction: row;
  align-items: stretch;
}

.yt-shorts__stack {
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 0;
  height: 100%;
}

.yt-shorts__panel {
  flex: 0 0 0px;
  width: 0;
  overflow: hidden;
  border-left: 1px solid var(--yt-border);
  background: var(--yt-bg);
  visibility: hidden;
  transition: flex-basis var(--yt-transition), width var(--yt-transition),
              visibility var(--yt-transition);
}

.yt-shorts--panel .yt-shorts__panel {
  flex: 0 0 min(424px, 42vw);
  width: min(424px, 42vw);
  visibility: visible;
}

.yt-shorts__panel-inner {
  display: flex;
  flex-direction: column;
  width: min(424px, 42vw);
  height: 100%;
}

.yt-shorts__panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex: 0 0 auto;
  padding: 12px 8px 12px 16px;
  border-bottom: 1px solid var(--yt-border);
}

.yt-shorts__panel-head h2 { margin: 0; }

/* shorts.js moves focus here when the panel opens; the panel itself is the
   visible change, so the ring would only outline a heading. */
.yt-shorts__panel-head h2:focus { outline: none; }

.yt-shorts__panel-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 12px 16px 24px;
}

.yt-shorts__panel-note {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-bottom: 16px;
  padding: 10px 12px;
  border-radius: var(--yt-radius-sm);
  background: var(--yt-bg-chip);
  color: var(--yt-fg-secondary);
  font-size: 13px;
  line-height: 1.5;
}

.yt-shorts__panel-note .yt-icon { flex: 0 0 auto; margin-top: 2px; }

/* partials/comments.html renders its thread from `comments`, and this view
   supplies no such key — see the note at the top of shorts_detail.html — so
   the partial always shows its "No comments yet" line. True on a Short with
   none; a contradiction on one with four, where the note above already says
   the thread lives on the full player page. The template declares
   data-has-comments and forms.css keeps ownership of the class; this is only
   a page-scoped override, exactly as page-watch.css scopes .yt-watch
   .yt-comments. */
.yt-shorts__panel[data-has-comments="1"] .yt-comments__empty { display: none; }

/* The <noscript> line closes the detail column, so its rule belongs on top. */
.yt-shorts--detail .yt-shorts__noscript {
  border-bottom: 0;
  border-top: 1px solid var(--yt-border);
}

.yt-shorts__scrim { display: none; }

@media (max-width: 899px) {
  .yt-shorts--detail { display: block; }

  .yt-shorts__panel {
    position: fixed;
    z-index: 45;
    left: 0;
    right: 0;
    bottom: 0;
    top: auto;
    width: auto;
    flex: none;
    height: min(76vh, 560px);
    border-left: 0;
    border-top: 1px solid var(--yt-border);
    border-radius: var(--yt-radius-lg) var(--yt-radius-lg) 0 0;
    box-shadow: var(--yt-shadow-menu);
    transform: translateY(100%);
    transition: transform var(--yt-transition), visibility var(--yt-transition);
  }

  .yt-shorts--panel .yt-shorts__panel {
    width: auto;
    flex: none;
    transform: translateY(0);
  }

  .yt-shorts__panel-inner { width: 100%; }

  .yt-shorts__scrim {
    display: block;
    position: fixed;
    z-index: 44;
    inset: 0;
    background: var(--yt-scrim);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--yt-transition), visibility var(--yt-transition);
  }

  .yt-shorts--panel .yt-shorts__scrim {
    opacity: 1;
    visibility: visible;
  }
}

/* ==========================================================================
   10. NOT-READY SLIDE

   Defensive: both shorts views resolve ready videos only, so this is written
   for the day one of them stops doing that. Same status vocabulary as the
   cards, so .yt-card__status keeps owning the colours.
   ========================================================================== */

.yt-shorts__pending {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 24px;
  text-align: center;
}

.yt-shorts__pending-thumb {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: .35;
}

.yt-shorts__pending .yt-card__status,
.yt-shorts__pending-note,
.yt-shorts__pending-error {
  position: relative;
  z-index: 1;
  max-width: 30ch;
}

.yt-shorts__pending-note,
.yt-shorts__pending-error {
  color: #fff;
  font-size: 13px;
  line-height: 1.5;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .7);
}

.yt-shorts__pending-error { color: var(--yt-danger); }

/* ==========================================================================
   11. EMPTY FEED

   Not a snap feed at all: a normal page explaining the two conditions that
   make an upload a Short.
   ========================================================================== */

.yt-shorts-empty {
  max-width: 760px;
}

.yt-shorts-empty__rule {
  margin-top: 8px;
  padding: 20px;
  border: 1px solid var(--yt-border);
  border-radius: var(--yt-radius-md);
  background: var(--yt-bg-elevated);
}

.yt-shorts-empty__rule > * + * { margin-top: 12px; }

.yt-shorts-empty__list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.yt-shorts-empty__list li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  color: var(--yt-fg);
  font-size: 14px;
  line-height: 1.5;
}

.yt-shorts-empty__list .yt-icon {
  flex: 0 0 auto;
  margin-top: 2px;
  color: var(--yt-fg-secondary);
}

.yt-shorts-empty__actions { gap: 12px; }

/* ==========================================================================
   12. REDUCED MOTION

   tokens.css already collapses every animation and transition globally; these
   restate the two that matter here so the file is still correct read alone,
   and shorts.js additionally passes behavior:'auto' to scrollIntoView, which
   CSS cannot reach.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .yt-shorts__scroller { scroll-behavior: auto; }

  .yt-shorts__play,
  .yt-shorts__sound-hint,
  .yt-shorts__panel,
  .yt-shorts__scrim { transition: none; }

  .yt-shorts__play { transform: scale(1); }
}
