/*
  Layout — positioning and flow only. No color and no typography
  decisions, with exactly one named exception: structural overlays
  like the legibility scrim, which exist to make positioned content
  readable and are themselves a positioning concern. Anything else
  describing what something looks like belongs in components.css.
*/

.skip-link {
  position: absolute;
  top: var(--space-xs);
  left: var(--space-xs);
  z-index: var(--z-skip-link);
  transform: translateY(-200%);
}

.skip-link:focus {
  transform: translateY(0);
}

/* ---------------------------------------------------------------
   Release page — one full-viewport, non-scrolling frame. This is a
   poster, not a webpage: everything fits in one view by design.
--------------------------------------------------------------- */
.release {
  position: relative;
  height: 100vh; /* fallback for browsers without dvh support */
  height: 100dvh;
  overflow: hidden;
}

/* Full-bleed video layer. Positioned independently of .content below,
   so moving .content later never means touching this rule. */
.background-media {
  position: absolute;
  inset: 0;
  z-index: var(--z-media);
  overflow: hidden;
}

/* The legibility scrim. A pseudo-element rather than its own HTML
   element — it's conceptually part of the background media, not a
   separate thing to track in the markup. Guarantees text contrast
   independent of whatever the video/poster underneath looks like. */
.background-media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1; /* local to this element's own stacking context */
  /* Bottom stop is 0.90, not a rounder-looking 0.75-0.8: verified by
     computing actual contrast ratios against a worst-case bright/white
     video. At lower opacity, the muted footer text color fails WCAG AA
     (3.08:1) in that scenario; 0.90 clears it with margin (5.29:1) while
     primary text stays far above threshold regardless. This is the
     number that makes the "contrast is guaranteed against the scrim,
     never the video" promise actually true, not just asserted. */
  background: linear-gradient(
    to bottom,
    rgba(var(--neutral-900-rgb), 0) 0%,
    rgba(var(--neutral-900-rgb), 0.15) 45%,
    rgba(var(--neutral-900-rgb), 0.9) 100%
  );
}

.media-poster,
.media-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The content column: centered, width-capped, anchored toward the
   bottom of the frame (comfortable one-handed thumb reach on mobile),
   with real breathing room above the safe area rather than sitting
   flush against it. */
.content {
  position: relative;
  z-index: var(--z-content);
  height: 100%;
  max-width: var(--content-max-width);
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--space-lg);
  padding-left: max(var(--space-lg), env(safe-area-inset-left));
  padding-right: max(var(--space-lg), env(safe-area-inset-right));
  padding-top: max(var(--space-lg), env(safe-area-inset-top));
  padding-bottom: max(var(--space-2xl), calc(env(safe-area-inset-bottom) + var(--space-lg)));
}

.streaming-links {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

/* ---------------------------------------------------------------
   Hub page — a normal scrolling document, not a fixed frame. The
   archive is expected to grow to 50+ entries, so this page needs to
   scroll by design, unlike release pages.
--------------------------------------------------------------- */
.hub {
  max-width: var(--content-max-width);
  margin-inline: auto;
  padding-left: max(var(--space-lg), env(safe-area-inset-left));
  padding-right: max(var(--space-lg), env(safe-area-inset-right));
  padding-top: var(--space-3xl);
  padding-bottom: var(--space-3xl);
  display: flex;
  flex-direction: column;
  gap: var(--space-2xl);
}

.release-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.socials {
  display: flex;
  gap: var(--space-sm);
  margin-top: var(--space-2xs);
}
