/*
 * Campaign-home — campaign-specific styles only (docs/features/spa-home.md).
 * The page's own CSS (/a/css.acss) already styles the chrome, buttons, drawer,
 * background, header/menu and footer. Everything here is scoped under
 * `.campaign-home` so it can't affect page-builder pages.
 */

/* ── Background blur (applied to the page's existing .background) ──────────── */
.campaign-home .background {
  transition: filter 0.3s ease-out, transform 0.3s ease-out;
  will-change: filter;
  /* The fixed background is exactly the viewport, so blur(28px) fades its own
     top/bottom edges to transparent — revealing the black body as a dark band
     that lands at each (viewport-tall) block boundary and reads as a seam.
     Oversize top/bottom so those blurred edges sit off-screen. Width is left
     alone (the drawer animates it). */
  top: -52px;
  height: calc(100dvh + 104px);
}
.campaign-home.campaign-bg-blurred .background {
  filter: blur(28px);
  transform: scale(1.05);
}

/* ── Block rhythm + reveal ────────────────────────────────────────────────── */
.campaign-home .campaign-block {
  padding: clamp(48px, 9vh, 110px) 0;
  position: relative;
}
.campaign-home.campaign-js [data-transition] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.campaign-home.campaign-js [data-transition].in-view { opacity: 1; transform: none; }
.campaign-home.campaign-js [data-transition='fade'] { transform: none; }
/* When a drawer is open (including a deep-link pre-open), the reframed page IS
   the poster — its reveal-on-scroll blocks must be shown, not stuck at opacity:0
   under the poster, and must not animate as the drawer opens. */
.campaign-home.drawer-open.campaign-js [data-transition] {
  opacity: 1;
  transform: none;
  transition: none;
}

/* ── Hero (reuses the title-module markup; scoped layout here) ─────────────── */
.campaign-home .campaign-block--title {
  min-height: 86svh;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.campaign-home .campaign-block--title .titleDesignModule {
  max-width: 900px;
  margin: 0 auto;
}
.campaign-home .title-treatment .titleImage {
  display: block;
  margin: 0 auto;
  width: auto;
  max-width: min(620px, 82vw);
  max-height: 46vh;
  height: auto;
}
.campaign-home .campaign-title-text {
  font-size: clamp(2.5rem, 12vw, 6rem);
  line-height: 0.95;
  margin: 0;
}
.campaign-home .title-message {
  margin: 1rem 0 0;
}
.campaign-home .title-message h2 {
  font-weight: 500;
  font-size: clamp(1.1rem, 4vw, 1.6rem);
  margin: 0;
}
.campaign-home .btns.drawer-action {
  display: flex;
  flex-direction: column; /* stacked on mobile */
  align-items: center;
  gap: 12px;
  margin-top: 1.5rem;
}
@media (min-width: 768px) {
  /* side by side on desktop */
  .campaign-home .btns.drawer-action { flex-direction: row; justify-content: center; }
}
/* lean on the site's .btn styling; just ensure the secondary reads as ghost */
.campaign-home .campaign-cta.is-secondary {
  background: transparent;
  border: 1px solid currentColor;
}

/* ── About: sticky poster + long detail column ─────────────────────────────── */
.campaign-home .campaign-about {
  display: grid;
  gap: 28px;
  align-items: start;
}
.campaign-home .campaign-poster img {
  display: block;
  width: 100%;
  max-width: 360px;
  border-radius: 10px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45);
}
.campaign-home .campaign-about-title {
  margin: 0 0 0.4em;
  font-size: clamp(2.2rem, 6vw, 3.75rem);
  line-height: 1.02;
}
.campaign-home .campaign-synopsis {
  font-size: 1.05rem;
  line-height: 1.65;
  max-width: 60ch;
  margin: 0 0 2rem;
  opacity: 0.9;
}
/* Metadata grid (Directed by / Film details / Runtime …) + cast below. */
.campaign-home .campaign-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 22px 32px;
  margin: 0 0 1.75rem;
}
.campaign-home .campaign-meta-cast { margin: 0 0 2rem; max-width: 60ch; }
.campaign-home .campaign-meta dt,
.campaign-home .campaign-meta-cast dt {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.13em;
  opacity: 0.55;
  margin: 0 0 6px;
}
.campaign-home .campaign-meta dd,
.campaign-home .campaign-meta-cast dd { margin: 0; font-size: 1rem; line-height: 1.5; }
/* Age certificate chip. Shows the per-territory rating code (e.g. "15", "R18")
   matched to the visitor, or the legacy certification string. Rendered as text
   for now; official regional symbols are a later upgrade (docs/features/ratings.md). */
.campaign-home .campaign-cert {
  display: inline-block;
  margin-left: 0.55em;
  padding: 0 0.4em;
  border: 1px solid currentColor;
  border-radius: 3px;
  font-size: 0.82em;
  line-height: 1.5;
  opacity: 0.8;
}
/* Trailer / Share action row. */
.campaign-home .campaign-about-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 30px;
  margin: 0 0 2rem;
}
.campaign-home .campaign-action {
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  padding: 6px 0;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  opacity: 0.85;
  transition: opacity 0.2s ease;
}
.campaign-home .campaign-action:hover { opacity: 1; }
.campaign-home .campaign-action-icon { display: inline-flex; }
.campaign-home .campaign-action.is-copied::after {
  content: 'Link copied';
  margin-left: 0.5em;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  opacity: 0.7;
}
.campaign-home .campaign-about-showtimes {
  margin-top: 0.5rem;
  padding-top: 1.75rem;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}
.campaign-home .campaign-section-title {
  font-size: clamp(1.6rem, 6vw, 2.4rem);
  margin: 0 0 1rem;
}

@media (min-width: 768px) {
  .campaign-home .campaign-about {
    grid-template-columns: minmax(220px, 340px) 1fr;
    gap: 56px;
  }
  /* Freeze the poster while the long right column (incl. showtimes) scrolls. */
  .campaign-home .campaign-poster {
    position: sticky;
    top: clamp(88px, 13vh, 130px);
    align-self: start;
  }
}

/* ── Trailer lightbox ─────────────────────────────────────────────────────── */
.campaign-lightbox {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}
.campaign-lightbox[hidden] { display: none; }
.campaign-lightbox-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.8);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.campaign-lightbox-panel {
  position: relative;
  z-index: 1;
  /* Size so the 16:9 frame always fits within both viewport width and height. */
  width: min(1100px, 100vw - 32px, calc((100vh - 120px) * 16 / 9));
}
.campaign-lightbox-frame { width: 100%; aspect-ratio: 16 / 9; border-radius: 12px; overflow: hidden; box-shadow: 0 30px 90px rgba(0, 0, 0, 0.6); }
.campaign-lightbox-frame iframe,
.campaign-lightbox-frame .trailerModule,
.campaign-lightbox-frame .trailerModule iframe { width: 100%; height: 100%; }
/* Reuses the drawer's X (.drawer-close two-span markup); just place it in the
   viewport corner instead of the drawer's. */
.campaign-lightbox .campaign-lightbox-close {
  position: absolute;
  top: clamp(12px, 3vh, 28px);
  right: clamp(12px, 3vw, 28px);
  z-index: 2;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
}
body.campaign-lightbox-open { overflow: hidden; }

/* ── Parallax layers (transforms come from campaign-home.js) ───────────────── */
.campaign-home.campaign-js [data-parallax] { will-change: transform; }
/* ── Trailer: image-to-background-zoom (scale comes from campaign-home.js) ───── */
.campaign-home .campaign-block--trailer { padding: 0; }
.campaign-home .campaign-trailer-zoom {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: min(72svh, 720px);
  overflow: hidden;
  text-decoration: none;
  color: #fff;
}
.campaign-home .campaign-trailer-zoom-img {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  transform: scale(1);
  transform-origin: center;
  will-change: transform;
}
.campaign-home .campaign-trailer-zoom-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(0,0,0,0.35), rgba(0,0,0,0.15) 40%, rgba(0,0,0,0.5));
}
/* Centered circular play button (the still's only overlay). */
.campaign-home .campaign-trailer-play {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: clamp(76px, 9vw, 104px);
  height: clamp(76px, 9vw, 104px);
  border-radius: 999px;
  color: #fff;
  background: rgba(150, 150, 150, 0.45);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  transition: transform 0.25s ease, background 0.25s ease;
}
.campaign-home .campaign-trailer-play svg {
  /* Twice the original 30px; margin scales with it to keep the triangle
     optically centred in the circle. */
  width: 60px;
  height: 60px;
  margin-left: 8px;
}
.campaign-home .campaign-trailer-zoom:hover .campaign-trailer-play {
  transform: scale(1.06);
  background: rgba(150, 150, 150, 0.6);
}

@media (prefers-reduced-motion: reduce) {
  .campaign-home .background { transition: none; }
  .campaign-home.campaign-js [data-transition] { opacity: 1; transform: none; transition: none; }
  /* JS skips parallax/zoom under reduced motion; ensure nothing is left shifted. */
  .campaign-home [data-parallax],
  .campaign-home .campaign-trailer-zoom-img { transform: none !important; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Polish amends — cinematic refinement of the campaign chrome. Scoped to
   .campaign-home so page-builder sites are untouched. Ordered after the base
   rules above so same-specificity overrides win.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Shared reflective edge: a 2px gradient rim (catch-light at top → shadow at
   bottom) masked to the element's own radius. Reads as a thin reflective bevel. */
/* The ribbon is already position:fixed (a positioned element), so its ::after
   anchors correctly — do NOT add position:relative here or it drops out of the
   corner into normal flow. */
.campaign-home .campaign-poster,
.campaign-home .campaign-trailer-zoom { position: relative; }
.campaign-home .campaign-poster::after,
.campaign-home .campaign-trailer-zoom::after,
.campaign-home header .header-wrap a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.275) 0%,
    rgba(255, 255, 255, 0.06) 22%,
    rgba(0, 0, 0, 0) 55%,
    rgba(0, 0, 0, 0.21) 100%
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
  z-index: 3;
}

/* 1 ── Title CTAs: side-by-side on desktop (only stack on mobile). The site's
   .btns rules make each button flex-grow + min-width:245px, which forced a wrap;
   let them be auto-width and sit in a row once there's space. */
@media (min-width: 768px) {
  .campaign-home .campaign-block--title .btns.drawer-action {
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: center;
    gap: 1rem; /* the gutter between the two halves */
  }
  /* Equal 50/50 blocks spanning the title width; the container gap is the only
     gutter (zero the site's per-button margin). */
  .campaign-home .campaign-block--title .btns.drawer-action > .campaign-cta {
    flex: 1 1 0;
    min-width: 0;
    margin: 0;
  }
}

/* 3 ── About poster: dominant on desktop, sized off the viewport height (90vh).
   The grid column collapses to the poster's intrinsic width at that height. */
.campaign-home .campaign-poster { border-radius: 12px; }
.campaign-home .campaign-poster img { border-radius: inherit; box-shadow: 0 32px 80px rgba(0, 0, 0, 0.5); }
@media (min-width: 768px) {
  .campaign-home .campaign-about { grid-template-columns: auto minmax(0, 1fr); gap: 64px; }
  /* Re-assert sticky here: the reflective-edge rule above sets position:relative
     (needed so the ::after anchors on mobile), which would otherwise override
     the sticky positioning — and make `top` a relative push-down that drops the
     poster below the right column. As sticky, `top` is the scroll offset and the
     poster's natural top stays aligned with the right column. */
  .campaign-home .campaign-poster { position: sticky; top: clamp(64px, 8vh, 110px); }
  .campaign-home .campaign-poster img {
    width: auto;
    max-width: none;
    height: 80vh;
    max-height: 80vh;
  }
}

/* 4 ── Trailer: a contained 16/9 frame at the content width, rounded ~20px,
   instead of full-bleed. (The still still gently zooms within the frame.) */
.campaign-home .campaign-block--trailer { padding: clamp(48px, 9vh, 110px) 0; }
.campaign-home .campaign-block--trailer .campaign-trailer-zoom {
  width: 100%;
  min-height: 0;
  aspect-ratio: 16 / 9;
  border-radius: 1.25rem;
  box-shadow: 0 32px 90px rgba(0, 0, 0, 0.5);
}

/* 5 ── Footer: drop its own backdrop blur + tint; it fights the page's blurred
   key art and reads as a jarring panel. (.footer also carries `.grain`.) */
.campaign-home footer.grain,
.campaign-home footer {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  background-color: transparent;
}

/* 6 ── Footer top edge: a 2px reflective hairline (light, fading at the ends). */
.campaign-home footer { position: relative; }
.campaign-home footer::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.25) 18%,
    rgba(255, 255, 255, 0.25) 82%,
    rgba(255, 255, 255, 0) 100%
  );
  pointer-events: none;
}

/* Kill only the widget-tab grain leak: the site's `nav::before` grain is
   unscoped, so it bleeds onto the embedded widget's tab nav (nav.widget-nav),
   which reads as a stray grainy band. The drawer panel keeps its grain overlay
   (.drawer-bg-inner) — that one's wanted. .campaign-home-only. */
.campaign-home nav::before {
  background-image: none;
}

/* 7 ── Menu: actually centre the title + nav items. The site's `nav ul` keeps
   the browser's default ~40px inline-start padding, which shoved the centred
   text to the right. Zero it and centre explicitly. */
.campaign-home nav:not(.widget-nav):not(.assemble-widget nav) ul {
  padding: 0;
  margin: 0;
  text-align: center;
}

/* ── Hero 3x3 placement (design_home_title_position / design_home_cta_position,
   docs/features/module-position.md). The hero keeps its classic centered
   layout unless the section carries .campaign-hero--positioned; then the title
   group (and, when positioned separately, the CTA row) become full-bleed
   layers anchored to one of 9 grid positions per breakpoint. ──────────────── */
.campaign-home .campaign-block--title.campaign-hero--positioned {
  align-items: stretch;
  justify-content: flex-start; /* the sole child spans full width; just defeat the centering */
  text-align: initial;
}
.campaign-home .campaign-hero--positioned .titleDesignModule {
  position: relative;
  flex: 1 1 auto;
  width: 100%;
  max-width: none;
  margin: 0;
  min-height: 86svh;
}
.campaign-home .campaign-hero-layer {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  padding: clamp(16px, 5vh, 56px) clamp(16px, 5vw, 72px);
  pointer-events: none; /* layers overlap; only their content is interactive */
}
.campaign-home .campaign-hero-layer > * {
  pointer-events: auto;
}
/* The title group keeps its intrinsic width inside the layer. */
.campaign-home .campaign-hero-layer .title-treatment,
.campaign-home .campaign-hero-layer .title-message {
  max-width: min(900px, 100%);
}
/* Alignment follows the layer, not the hardcoded .text-center. */
.campaign-home .campaign-hero-layer .title-message h2 {
  text-align: inherit;
}
/* Positioned CTAs keep their block nature: the group is a definite-width
   block (capped like the classic hero's title image, 620px) that the classic
   50/50 rule above fills — two buttons split it, a lone button spans it —
   rather than buttons shrinking to their labels. The layer's align-items
   places the block within the cell. */
.campaign-home .campaign-hero-layer .btns.drawer-action {
  margin-top: 0;
  width: min(620px, 100%);
}
/* Stacked mobile CTAs are full-width blocks at their natural height (the
   site's `.btns > *` 20rem flex-basis is vertical in this column layout).
   flex-shrink stays on for the 768px tie, where the desktop row direction
   still applies and the two full-width buttons must shrink back to 50/50. */
@media (max-width: 768px) {
  .campaign-home .campaign-hero-layer .btns.drawer-action > .campaign-cta {
    flex: 0 1 auto;
    box-sizing: border-box; /* the site css has no global border-box */
    width: 100%;
    min-width: 0;
    margin: 0;
  }
}
/* Breakpoints intentionally overlap at exactly 768px with the mobile block
   last, so pos-sm wins the tie — the same convention as the site CSS
   (utils.mobile/desktop and the v5 button position rules). */
@media (min-width: 768px) {
  .campaign-home .campaign-hero-layer.pos-lg-h-left { align-items: flex-start; text-align: left; }
  .campaign-home .campaign-hero-layer.pos-lg-h-center { align-items: center; text-align: center; }
  .campaign-home .campaign-hero-layer.pos-lg-h-right { align-items: flex-end; text-align: right; }
  .campaign-home .campaign-hero-layer.pos-lg-v-top { justify-content: flex-start; }
  .campaign-home .campaign-hero-layer.pos-lg-v-middle { justify-content: center; }
  .campaign-home .campaign-hero-layer.pos-lg-v-bottom { justify-content: flex-end; }
  .campaign-home .campaign-hero-layer.pos-lg-h-left .btns.drawer-action { justify-content: flex-start; }
  .campaign-home .campaign-hero-layer.pos-lg-h-center .btns.drawer-action { justify-content: center; }
  .campaign-home .campaign-hero-layer.pos-lg-h-right .btns.drawer-action { justify-content: flex-end; }
}
@media (max-width: 768px) {
  .campaign-home .campaign-hero-layer.pos-sm-h-left { align-items: flex-start; text-align: left; }
  .campaign-home .campaign-hero-layer.pos-sm-h-center { align-items: center; text-align: center; }
  .campaign-home .campaign-hero-layer.pos-sm-h-right { align-items: flex-end; text-align: right; }
  .campaign-home .campaign-hero-layer.pos-sm-v-top { justify-content: flex-start; }
  .campaign-home .campaign-hero-layer.pos-sm-v-middle { justify-content: center; }
  .campaign-home .campaign-hero-layer.pos-sm-v-bottom { justify-content: flex-end; }
  /* Stacked mobile CTAs align as a block; the buttons themselves stay full-width. */
  .campaign-home .campaign-hero-layer.pos-sm-h-left .btns.drawer-action { align-items: flex-start; }
  .campaign-home .campaign-hero-layer.pos-sm-h-center .btns.drawer-action { align-items: center; }
  .campaign-home .campaign-hero-layer.pos-sm-h-right .btns.drawer-action { align-items: flex-end; }
}

/* Same-cell-on-one-breakpoint handling (planHeroLayers): when the title and
   CTA positions match on exactly one breakpoint, the renderer emits a merged
   layer for that breakpoint plus split layers for the other, and these
   toggles pick which set shows. The ranges are complementary (a viewport can
   never hide BOTH variants) and the tie at exactly 768px goes to the MOBILE
   variant — the pos-sm-* alignment rules above win there, so the visible
   layer set must be the mobile one or a mobile-only collision would overlap
   again at precisely 768px. */
@media (min-width: 768.02px) {
  .campaign-home .hero-only-sm { display: none; }
}
@media (max-width: 768px) {
  .campaign-home .hero-only-lg { display: none; }
}
