/* ==========================================================================
   MEDIA DIALOG                          /university · /wall-of-love (ADR-22)
   The one <dialog class="zr-media"> that media.js builds on first use: it
   plays a YouTube video or zooms a screenshot. It is the demo lightbox's
   sibling (lightbox.css) and wears the same clothes — the navy blurred
   backdrop, the paper card on --zr-r-md corners, the round close button, the
   rise-out-of-blur entrance — so a visitor who has seen one has seen both.
   A native dialog: the top layer, the focus trap, Esc and the inert page come
   from the browser.

     .zr-media
       .zr-media__card  (--video | --zoom)
         .zr-media__head   .zr-media__info ( h2.zr-media__title | p.zr-media__cap )  button.zr-media__x
         .zr-media__stage  (--video > iframe | --zoom > img)
   ========================================================================== */
.zr-media{
  /* --zr-media-chrome is what the card spends on everything but the stage:
     head 68 + the inset under the stage + the two hairlines. The video card
     sizes itself from it, so the three travel together. */
  --zr-media-gut:clamp(12px,3vw,32px);
  --zr-media-inset:16px;
  --zr-media-chrome:86px;
  width:100%; max-width:none; height:100%; max-height:none;
  margin:0; padding:var(--zr-media-gut);
  border:0; background:transparent; overflow:hidden; overscroll-behavior:contain;
  color:var(--zr-body);
}
/* the display lives on [open] — an unscoped one beats the UA's
   dialog:not([open]){display:none} and leaves a blank block in the flow */
.zr-media[open]{ display:grid; place-items:center; }
.zr-media::backdrop{
  background:rgba(12,20,38,.62);
  -webkit-backdrop-filter:blur(10px) saturate(120%);
  backdrop-filter:blur(10px) saturate(120%);
  opacity:0; transition:opacity .28s var(--zr-ease-out-quad);
}
.zr-media.is-in::backdrop{ opacity:1; }

.zr-media__card{
  width:min(900px,100%); max-height:100%;
  /* a flex column: the head holds its size, the stage takes what is left */
  display:flex; flex-direction:column; overflow:hidden;
  background:var(--zr-paper);
  border:1px solid var(--zr-line);
  border-radius:var(--zr-r-md);
  box-shadow:0 40px 90px rgba(11,23,48,.30), 0 6px 18px rgba(11,23,48,.10);
  opacity:0; translate:0 16px; scale:.985; filter:blur(5px);
  transition:opacity .34s var(--zr-ease-out-quart),
             translate .34s var(--zr-ease-out-quart),
             scale .34s var(--zr-ease-out-quart),
             filter .3s var(--zr-ease-out-quart);
}
/* filter:none at rest, not blur(0): a live filter would push the player
   through an offscreen pass on every frame */
.zr-media.is-in .zr-media__card{ opacity:1; translate:0 0; scale:1; filter:none; }

/* ── head: the title or the caption, then the close button ─────────────── */
.zr-media__head{ flex:0 0 auto; display:flex; align-items:center; gap:14px; padding:18px 16px 14px; }
.zr-media__info{ flex:1 1 auto; min-width:0; }
.zr-media__title{
  margin:0; font-size:17px; line-height:24px; font-weight:500;
  letter-spacing:-.012em; color:var(--zr-ink);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.zr-media__cap{
  margin:0; display:flex; flex-wrap:wrap; align-items:center; gap:2px 8px;
  font-size:14px; line-height:20px; color:var(--zr-muted);
}
.zr-media__src{ font-weight:500; color:var(--zr-ink); }
.zr-media__orig{ color:var(--zr-blue); text-decoration:none; }
.zr-media__orig:hover{ text-decoration:underline; text-underline-offset:2px; }
.zr-media__orig:focus-visible{ outline:2px solid var(--zr-blue); outline-offset:3px; border-radius:4px; }

.zr-media__x{
  flex:0 0 auto; width:36px; height:36px; padding:0; border-radius:50%;
  display:grid; place-items:center; cursor:pointer;
  border:1px solid var(--zr-line); background:#fff; color:var(--zr-ink);
  transition:background .16s var(--zr-ease-out-quad),
             border-color .16s var(--zr-ease-out-quad);
}
.zr-media__x:hover{ background:#F5F7FB; border-color:var(--zr-line); }
.zr-media__x:focus-visible{ outline:2px solid var(--zr-blue); outline-offset:2px; }
.zr-media__x svg{ width:16px; height:16px; }
/* a finger needs 44px; the pointer keeps the lightbox's 36px */
@media (pointer:coarse){
  .zr-media__x{ width:44px; height:44px; }
  /* the caption's link stands alone, so it gets the same 44px; the negative margin keeps the row's height */
  .zr-media__orig{ display:inline-flex; align-items:center; min-height:44px; margin-block:-12px; }
}

/* ── stage ─────────────────────────────────────────────────────────────── */
.zr-media__stage{
  flex:0 1 auto; min-height:0;
  margin:0 var(--zr-media-inset) var(--zr-media-inset); border-radius:14px;
}

/* Video: 16:9, at most 1100px, never taller than the viewport. The card takes
   its width from the height that is left, so the frame stays 16:9 on a short
   window; if the head ever wraps, the stage gives way (min-height:0) and the
   player letterboxes itself on the navy. */
.zr-media__card--video{
  width:min(1100px, 100%, calc((100vh - 2 * var(--zr-media-gut) - var(--zr-media-chrome)) * 16 / 9 + 2 * var(--zr-media-inset)));
  width:min(1100px, 100%, calc((100dvh - 2 * var(--zr-media-gut) - var(--zr-media-chrome)) * 16 / 9 + 2 * var(--zr-media-inset)));
}
.zr-media__stage--video{
  /* an explicit width instead of stretch + inline margins: WebKit resolves aspect-ratio against the stretched
     width including the margins, which made the stage 13-18px too tall and letterboxed the player */
  align-self:center; width:calc(100% - 2 * var(--zr-media-inset)); margin-inline:0;
  position:relative; aspect-ratio:16 / 9; overflow:hidden;
  background:linear-gradient(140deg,#1B2A44,#0B1730);
}
.zr-media__stage--video > iframe{
  position:absolute; inset:0; width:100%; height:100%;
  display:block; border:0; background:#0B1730;
}

/* Zoom: the screenshot at the card's width; a tall one (some are 1736×3702)
   scrolls inside the stage while the head — the caption row — stays put. */
.zr-media__stage--zoom{
  overflow:auto; overscroll-behavior:contain; -webkit-overflow-scrolling:touch;
  background:#F5F7FB;
  border:1px solid var(--zr-line-soft);
}
.zr-media__stage--zoom:focus-visible{ outline:2px solid var(--zr-blue); outline-offset:2px; border-radius:14px; }
.zr-media__stage--zoom img{ display:block; width:100%; height:auto; margin-inline:auto; }

/* Phones get it as a bottom sheet, like the demo lightbox: a gutter either
   side of the stage leaves nothing to look at. The strip above the sheet keeps
   the backdrop tappable under a full-height screenshot. */
@media (max-width:680px){
  /* chrome here = the 24px strip + a two-line head (72) + the inset + a hairline */
  .zr-media{ --zr-media-gut:0px; --zr-media-inset:12px; --zr-media-chrome:110px;
             padding:max(24px, env(safe-area-inset-top, 0px)) 0 0; }
  .zr-media[open]{ align-items:end; }   /* match .zr-media[open]'s specificity */
  .zr-media__card{ border-radius:var(--zr-r-md) var(--zr-r-md) 0 0; border-bottom:0; }
  .zr-media__head{ padding:16px 12px 12px; }
  /* two lines beat an ellipsis on a 375px header */
  .zr-media__title{ font-size:16px; line-height:22px; white-space:normal; overflow:visible; }
  .zr-media__stage{ margin-bottom:calc(var(--zr-media-inset) + env(safe-area-inset-bottom, 0px)); border-radius:12px; }
  .zr-media__stage--zoom:focus-visible{ border-radius:12px; }

  /* A desktop-width review is unreadable at 366px. A tap on it toggles
     .is-big (media.js): the screenshot comes up to reading size and the stage
     pans both ways; the hint is decoration, the gesture is pointer-only and
     pinch-zoom works regardless. */
  .zr-media__stage--zoom img{ cursor:zoom-in; }
  .zr-media__card.is-big .zr-media__stage--zoom img{ width:max(100%, min(240%, 900px)); max-width:none; cursor:zoom-out; }
  .zr-media__card--zoom .zr-media__info::after{
    content:"Tap the screenshot to enlarge it"; display:block; margin-top:2px;
    font-size:12px; line-height:16px; color:var(--zr-muted);
  }
  .zr-media__card--zoom.is-big .zr-media__info::after{ content:"Tap again to fit it to the screen"; }
}

/* base.css shortens every transition under reduced motion, but `*` does not
   reach ::backdrop; media.js closes without the fade delay in that case. */
@media (prefers-reduced-motion:reduce){
  .zr-media::backdrop,
  .zr-media__card{ transition:none; }
  .zr-media__card{ translate:none; scale:none; filter:none; }
}
