/*
 * ll-video-cta.v2.css — premium video CTA, v2.
 *
 * Separate file by design: production keeps serving ll-video-cta.css (v1)
 * untouched until this passes owner visual review.
 *
 * Derived from pipeline/creative/design/reference/premium-video-cta-direction.png.
 * Palette values were measured off that file with
 * pipeline/creative/design/sample_reference_palette.py, then normalised for
 * contrast rather than eyeballed.
 *
 * Structural rules that must not be broken:
 *   - ONE aspect ratio system-wide: 1080/2152, the native ratio of the
 *     vertical-only crop. The viewport never uses object-fit: cover, so the
 *     media is never cropped a second time in CSS.
 *   - Every top/mid/footer preview lives inside .llc-phone. No bare
 *     floating video rectangles.
 *   - The modal is a clean full-bleed player with no decorative chassis.
 *   - Android device language: no notch, no Dynamic Island. A centred
 *     punch-hole camera only.
 *   - Copy is locked. No script accents, slogans, or micro lines.
 */

/* ====================================================================== */
/* Font                                                                    */
/* ====================================================================== */

@font-face {
  font-family: "LL Playfair Display";
  src: url("/wp-content/uploads/ll-video-cta/v2/static/fonts/playfair-display-latin-var.woff2")
       format("woff2-variations");
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ====================================================================== */
/* Tokens — scoped, never global                                           */
/* ====================================================================== */

.ll-cta--v2,
.ll-cta-modal--v2 {
  --ll-ink:        #050d1f;
  --ll-ink-soft:   #0c1430;
  --ll-ink-deep:   #02060f;

  --ll-teal:       #3fe3ea;
  --ll-cyan:       #58b6f5;
  --ll-violet:     #b06ee0;
  --ll-magenta:    #e45cc8;

  --ll-grad-a:     #45e2f0;
  --ll-grad-b:     #b06ee0;

  --ll-text:       #f4f7ff;
  --ll-text-dim:   #c2cce6;

  --ll-btn-a:      #2fe3d8;
  --ll-btn-b:      #62a8f2;
  --ll-btn-ink:    #06172b;

  --ll-glow-teal:    rgba(63, 227, 234, 0.55);
  --ll-glow-magenta: rgba(228, 92, 200, 0.50);

  --ll-radius-card: 26px;

  --ll-shadow-card:   0 30px 80px -30px rgba(0, 0, 0, 0.85);
  --ll-shadow-ground: 0 38px 40px -26px rgba(0, 0, 0, 0.9);

  --ll-font-display: "LL Playfair Display", "Playfair Display", Georgia,
                     "Times New Roman", serif;
  --ll-font-ui: inherit;

  --ll-ease-rise: cubic-bezier(0.16, 0.84, 0.34, 1);

  /* Per-placement; every phone dimension derives from this one number. */
  --ll-phone-w: 216px;
}

/* ====================================================================== */
/* Card shell                                                              */
/* ====================================================================== */

/* Without this, max-width caps the CONTENT box and the padding is added on
 * top — an 880px card renders 956px wide. */
.ll-cta--v2,
.ll-cta--v2 *,
.ll-cta-modal--v2,
.ll-cta-modal--v2 * {
  box-sizing: border-box;
}

.ll-cta--v2 {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-radius: var(--ll-radius-card);
  background: var(--ll-ink);
  color: var(--ll-text);
  font-family: var(--ll-font-ui);
  box-shadow: var(--ll-shadow-card);
  margin: 32px auto;
  max-width: 960px;
}

.llc-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    radial-gradient(72% 105% at 14% 14%, rgba(176, 110, 224, 0.46), transparent 64%),
    radial-gradient(68% 100% at 88% 80%, rgba(63, 227, 234, 0.34), transparent 66%),
    radial-gradient(54% 74% at 60% 48%, rgba(228, 92, 200, 0.22), transparent 72%),
    linear-gradient(145deg, var(--ll-ink-deep) 0%, var(--ll-ink-soft) 55%, var(--ll-ink) 100%);
}

.llc-veil {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(2, 6, 15, 0.38) 0%, rgba(2, 6, 15, 0.00) 40%, rgba(2, 6, 15, 0.42) 100%);
}

/* ====================================================================== */
/* Dream veil — atmospheric entrance layers                                */
/*                                                                         */
/* Every layer here sits at z-index 0, BELOW all content (which lives at    */
/* z-index 2-4). Nothing in this section ever blurs, filters, fades or      */
/* blends over the video, the poster, the headline, Lauri or a button.     */
/* The atmosphere is its own layer; the content simply arrives on top.     */
/* ====================================================================== */

.llc-atmos {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  /* GSAP tweens these; the gradient positions follow. No blur, no
   * backdrop-filter — a drifting gradient is far cheaper and does not force
   * the card into an expensive filter pass. */
  --veil-a-x: 12%;
  --veil-a-y: 26%;
  --veil-b-x: 88%;
  --veil-b-y: 74%;
  background:
    radial-gradient(58% 76% at var(--veil-a-x) var(--veil-a-y),
                    rgba(176, 110, 224, 0.40), transparent 62%),
    radial-gradient(56% 72% at var(--veil-b-x) var(--veil-b-y),
                    rgba(63, 227, 234, 0.30), transparent 64%);
}

/* One restrained travelling light sweep, used once on the CTA. It lives
 * INSIDE the pill and is removed from the DOM when the entrance finishes,
 * so nothing persists over the button. */
.llc-btn { position: relative; overflow: hidden; }

.llc-btn__sweep {
  position: absolute;
  top: 0;
  bottom: 0;
  left: -40%;
  width: 40%;
  pointer-events: none;
  background: linear-gradient(100deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.42) 50%,
    rgba(255, 255, 255, 0) 100%);
}

/* Headline line masks. The splitter wraps each rendered line; each line
 * clips from below. Inline-block on the inner span keeps the transform
 * from affecting layout, and the wrapper keeps the line box identical so
 * there is zero layout shift. */
.llc-line {
  display: block;
  overflow: hidden;
}
.llc-line > span {
  display: inline-block;
  will-change: transform;
}

/* Lauri's directional reveal mask. Applied only for the duration of the
 * entrance and cleared afterwards. */
.llc-lauri[data-ll-mask] {
  -webkit-mask-image: linear-gradient(var(--mask-dir, 270deg),
    #000 0%, #000 35%, rgba(0, 0, 0, 0) 72%);
          mask-image: linear-gradient(var(--mask-dir, 270deg),
    #000 0%, #000 35%, rgba(0, 0, 0, 0) 72%);
  -webkit-mask-size: 260% 100%;
          mask-size: 260% 100%;
  -webkit-mask-position: var(--mask-pos, 100%) 0;
          mask-position: var(--mask-pos, 100%) 0;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
}

/* Chassis depth ramp during the entrance. Shadow only — never the screen. */
.llc-phone { --ll-depth: 1; }

/* Continuous ring motion: extremely slow, opposite directions, and paused
 * whenever the card is off screen so it costs nothing when unseen. */
@keyframes llc-ring-cw  { to { transform: rotate(360deg); } }
@keyframes llc-ring-ccw { to { transform: rotate(-360deg); } }

.ll-cta--v2[data-ll-anim="done"] .llc-portal__ring--outer {
  animation: llc-ring-cw 90s linear infinite;
}
.ll-cta--v2[data-ll-anim="done"] .llc-portal__ring--inner {
  animation: llc-ring-ccw 120s linear infinite;
}
.ll-cta--v2[data-ll-offscreen="1"] .llc-portal__ring {
  animation-play-state: paused;
}

/* ---- Shared grid slots. Placements only assign areas and tokens. ------ */

.ll-cta--v2 .llc-eyebrow-slot {
  grid-area: eyebrow;
  position: relative;
  z-index: 4;
}

/* No `ch` cap here. `ch` resolves against the inherited UI font, not the
 * display serif, so a 26ch cap collapsed the copy column to ~238px and
 * squeezed the headline. Placements set a px cap where they need one. */
.ll-cta--v2 .llc-copy {
  grid-area: copy;
  position: relative;
  z-index: 4;
  min-width: 0;
}

.ll-cta--v2 .llc-stage {
  grid-area: stage;
  position: relative;
  z-index: 2;
  display: grid;
  place-items: center;
  min-width: 0;
}

.ll-cta--v2 .llc-action {
  grid-area: action;
  position: relative;
  z-index: 4;   /* must sit above .llc-veil, or the button reads washed out */
  display: flex;
}

/* Desktop keeps the portal behind the phone; mobile moves it behind Lauri.
 * Two elements rather than one repositioned element, because they sit in
 * different stacking contexts. */
.ll-cta--v2 .llc-mobile-portal { display: none; }

/* ====================================================================== */
/* Type                                                                    */
/* ====================================================================== */

.llc-eyebrow {
  display: block;
  font-family: var(--ll-font-ui);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ll-teal);
  margin: 0 0 14px;
  white-space: nowrap;
}

.llc-headline {
  margin: 0;
  font-family: var(--ll-font-display);
  font-weight: 600;
  font-size: clamp(28px, 3.6vw, 44px);
  line-height: 1.06;
  letter-spacing: -0.01em;
  color: var(--ll-text);
  text-wrap: balance;
}

.llc-accent {
  background: linear-gradient(95deg, var(--ll-grad-a) 8%, var(--ll-grad-b) 92%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* If background-clip:text is unsupported the text would vanish. */
  @supports not ((-webkit-background-clip: text) or (background-clip: text)) {
    color: var(--ll-grad-a);
    background: none;
  }
}

.llc-rule {
  display: block;
  width: 64px;
  height: 2px;
  margin: 20px 0 0;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--ll-teal), rgba(63, 227, 234, 0));
}

.llc-lede {
  margin: 16px 0 0;
  font-size: 15px;
  line-height: 1.5;
  color: var(--ll-text-dim);
  max-width: 34ch;
}

/* ====================================================================== */
/* Brand avatar — a real <img>, never a magnified background-image         */
/* ====================================================================== */

.llc-brand {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 14px;
}

.llc-avatar {
  display: block;
  flex: none;
  width: var(--ll-avatar-size, 48px);
  height: var(--ll-avatar-size, 48px);
  border-radius: 50%;
  object-fit: cover;
  background: var(--ll-ink-soft);
  border: 2px solid rgba(63, 227, 234, 0.65);
  box-shadow: 0 0 14px rgba(63, 227, 234, 0.38);
}

.llc-brand .llc-eyebrow { margin: 0; }

/* ====================================================================== */
/* Lauri portrait — free-form silhouette, bleeds into the composition      */
/* ====================================================================== */

.llc-lauri {
  position: absolute;
  z-index: 3;
  pointer-events: none;
  user-select: none;
  filter: drop-shadow(0 26px 34px rgba(0, 0, 0, 0.55));
}

.llc-lauri img {
  display: block;
  width: 100%;
  height: auto;
}

/* ====================================================================== */
/* Portal rings                                                            */
/* ====================================================================== */

.llc-portal {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: grid;
  place-items: center;
  pointer-events: none;
}

.llc-portal__ring {
  position: absolute;
  border-radius: 50%;
  aspect-ratio: 1;
  opacity: 0.95;
  filter: drop-shadow(0 0 18px rgba(120, 160, 255, 0.35));
}

.llc-portal__ring--outer {
  width: 132%;
  background: conic-gradient(from 210deg,
    rgba(228, 92, 200, 0) 0deg,
    rgba(228, 92, 200, 0.85) 70deg,
    rgba(63, 227, 234, 0.9) 180deg,
    rgba(88, 182, 245, 0) 290deg,
    rgba(228, 92, 200, 0) 360deg);
  -webkit-mask: radial-gradient(circle, transparent 61%, #000 62%, #000 66%, transparent 67%);
          mask: radial-gradient(circle, transparent 61%, #000 62%, #000 66%, transparent 67%);
  filter: blur(0.4px);
}

.llc-portal__ring--inner {
  width: 112%;
  background: conic-gradient(from 30deg,
    rgba(63, 227, 234, 0) 0deg,
    rgba(63, 227, 234, 0.75) 90deg,
    rgba(176, 110, 224, 0.8) 210deg,
    rgba(176, 110, 224, 0) 330deg);
  -webkit-mask: radial-gradient(circle, transparent 64%, #000 65%, #000 68%, transparent 69%);
          mask: radial-gradient(circle, transparent 64%, #000 65%, #000 68%, transparent 69%);
}

/* ====================================================================== */
/* Phone chassis — brand-neutral Android. No notch, no Dynamic Island.     */
/* Every dimension derives from --ll-phone-w so it scales as one object.   */
/* ====================================================================== */

.llc-phone {
  --bezel: calc(var(--ll-phone-w) * 0.026);
  --radius-outer: calc(var(--ll-phone-w) * 0.105);

  position: relative;
  z-index: 3;
  width: var(--ll-phone-w);
  padding: var(--bezel);
  padding-bottom: calc(var(--bezel) * 1.15);
  border-radius: var(--radius-outer);
  background:
    linear-gradient(145deg, #2a2f45 0%, #0c1020 42%, #161a2e 78%, #22273c 100%);
  /* Depth ramps with --ll-depth during the entrance. Shadow and glow only:
   * the app screen itself is never touched. */
  box-shadow:
    /* grounded shadow */
    0 calc(38px * var(--ll-depth)) calc(40px * var(--ll-depth)) -26px rgba(0, 0, 0, 0.9),
    /* dual rim glow, teal from the left, magenta from the right */
    calc(-10px * var(--ll-depth)) 0 calc(34px * var(--ll-depth)) -8px var(--ll-glow-teal),
    calc( 10px * var(--ll-depth)) 0 calc(34px * var(--ll-depth)) -8px var(--ll-glow-magenta),
    /* inner glass rim */
    inset 0 1px 0 rgba(255, 255, 255, 0.30),
    inset 0 -1px 0 rgba(255, 255, 255, 0.10);
}

.llc-phone__viewport {
  position: relative;
  z-index: 3;                  /* above the chassis glare, which is z-index 1 */
  aspect-ratio: 1080 / 2152;   /* native ratio of the vertical-only crop */
  width: 100%;
  overflow: hidden;
  border-radius: calc(var(--radius-outer) - var(--bezel));
  background: #000;
  /* Explicitly inert: the app screen is never filtered, faded or blended. */
  filter: none;
  opacity: 1;
  mix-blend-mode: normal;
  backdrop-filter: none;
}

/*
 * No object-fit: cover. The media is authored at exactly this ratio, so it
 * fills the viewport with no second crop and no lost app width.
 */
.llc-phone__screen {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: fill;
  /* Ask for the good downscaler rather than the fast one. */
  image-rendering: auto;
  filter: none;
  opacity: 1;
  mix-blend-mode: normal;
  /* Own compositing layer so the decoded frame is not re-rasterised with
   * the card's painted background on every repaint. */
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* Reduced-motion still. Hidden by default; swapped in below. */
.llc-phone__still { display: none; }
.llc-phone__still img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: fill;
}

/* Punch-hole camera. Sits over the app background where the Android status
 * bar used to be, which is exactly where the real device's cutout is. */
.llc-phone__camera {
  position: absolute;
  top: calc(var(--bezel) + var(--ll-phone-w) * 0.028);
  left: 50%;
  transform: translateX(-50%);
  width: calc(var(--ll-phone-w) * 0.022);
  height: calc(var(--ll-phone-w) * 0.022);
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #2c3350, #05070d 70%);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.10);
  z-index: 4;
  pointer-events: none;
}

/* Hairline earpiece slit above the camera. */
.llc-phone__speaker {
  position: absolute;
  top: calc(var(--bezel) + var(--ll-phone-w) * 0.012);
  left: 50%;
  transform: translateX(-50%);
  width: 14%;
  height: 1.5px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.13);
  z-index: 4;
  pointer-events: none;
}

/*
 * One soft diagonal glass reflection — on the CHASSIS ONLY.
 *
 * This previously sat at z-index 5 with inset:0 and mix-blend-mode:screen,
 * which covered 100% of the app screen. Two costs: a screen blend over a
 * dark gradient lifts the blacks and flattens contrast (making compression
 * artefacts far more visible), and the blend forced the <video> into a
 * composited blend group. Decorative chassis effects must never touch the
 * app screen.
 *
 * Now it paints UNDER the viewport (z-index 1 vs the viewport's 3), so it is
 * only ever visible on the bezel ring, and the blend mode is gone entirely
 * so no blend group is created over the video.
 */
.llc-phone__glare {
  position: absolute;
  inset: 0;
  border-radius: var(--radius-outer);
  background: linear-gradient(152deg,
    rgba(255, 255, 255, 0.22) 0%,
    rgba(255, 255, 255, 0.06) 18%,
    rgba(255, 255, 255, 0) 42%);
  pointer-events: none;
  z-index: 5;
  /* Paint ONLY in the bezel ring: the padding box is filled, the content box
   * (which is exactly the viewport) is punched out. Belt and braces with the
   * z-order above — nothing decorative touches the app screen. */
  padding: var(--bezel);
  padding-bottom: calc(var(--bezel) * 1.15);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
}

/* Side hardware. Android convention: power right, volume left. */
.llc-phone__power,
.llc-phone__vol {
  position: absolute;
  width: 2px;
  border-radius: 2px;
  background: linear-gradient(180deg, #3a4159, #1a1f30);
  z-index: 2;
}
.llc-phone__power {
  right: -2px;
  top: 24%;
  height: calc(var(--ll-phone-w) * 0.16);
}
.llc-phone__vol {
  left: -2px;
  top: 17%;
  height: calc(var(--ll-phone-w) * 0.24);
}

/* ====================================================================== */
/* Button                                                                  */
/* ====================================================================== */

.llc-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 15px 26px 15px 30px;
  min-height: 56px;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  font-family: var(--ll-font-ui);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--ll-btn-ink);
  background: linear-gradient(96deg, var(--ll-btn-a) 0%, var(--ll-btn-b) 100%);
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.22) inset,
    0 10px 30px -8px rgba(47, 227, 216, 0.55);
  transition: transform 180ms var(--ll-ease-rise), box-shadow 180ms ease;
}

.llc-btn:hover { transform: translateY(-1px); }
.llc-btn:focus-visible {
  outline: 3px solid var(--ll-teal);
  outline-offset: 3px;
}

.llc-btn__label { min-width: 0; }

/* The arrow is an inline SVG flex item, not a text glyph. As "&rsaquo;" it
 * rendered as a clipped comma inside the pill on several faces. */
.llc-btn__chev {
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  display: block;
  align-self: center;
  overflow: visible;
}

/* ====================================================================== */
/* MID — "Want me to interpret your dream?" / "See How It Works"           */
/* ====================================================================== */

.ll-cta--v2[data-ll-placement="mid"] {
  --ll-phone-w: 196px;
  display: grid;
  /* Three columns, not the reference's four. At an 960px article card the
   * action cannot have its own column without starving the headline, so the
   * button sits under the copy. */
  grid-template-columns: minmax(0, 1fr) 252px 216px;
  grid-template-rows: auto auto auto;
  grid-template-areas:
    "eyebrow portrait stage"
    "copy    portrait stage"
    "action  portrait stage";
  align-content: center;
  column-gap: 20px;
  padding: 44px 38px 0;
  min-height: 470px;
}

.ll-cta--v2[data-ll-placement="mid"] .llc-eyebrow-slot { align-self: end; }
.ll-cta--v2[data-ll-placement="mid"] .llc-copy { align-self: start; max-width: 360px; }
.ll-cta--v2[data-ll-placement="mid"] .llc-action {
  align-self: start;
  margin-top: 26px;
  margin-bottom: 44px;
}

/* Lauri is her own column between the copy and the phone and bleeds off the
 * bottom edge, as in the reference. She is NOT an overlay - as an absolute
 * element she ended up behind the phone. */
.ll-cta--v2[data-ll-placement="mid"] .llc-lauri {
  grid-area: portrait;
  position: relative;
  align-self: end;
  justify-self: center;
  width: 322px;
  max-width: none;
  margin-right: -54px;   /* slight overlap into the phone's glow */
  /* The cutout has a hard horizontal crop at its base; bleed it past the
   * card edge so that edge is never visible. */
  margin-bottom: -46px;
}

/* ====================================================================== */
/* FOOTER — "Ready to understand your dream?" / "Watch How It Works"       */
/* One action only. "Interpret My Dream Free" never appears here.          */
/* ====================================================================== */

.ll-cta--v2[data-ll-placement="footer"] {
  --ll-phone-w: 196px;
  display: grid;
  grid-template-columns: 286px minmax(0, 1fr) 226px;
  grid-template-rows: auto auto auto;
  grid-template-areas:
    "portrait eyebrow stage"
    "portrait copy    stage"
    "portrait action  stage";
  align-content: center;
  column-gap: 24px;
  padding: 46px 38px 0;
  min-height: 470px;
}

.ll-cta--v2[data-ll-placement="footer"] .llc-eyebrow-slot { align-self: end; }
.ll-cta--v2[data-ll-placement="footer"] .llc-copy { align-self: start; max-width: 360px; }
.ll-cta--v2[data-ll-placement="footer"] .llc-action {
  align-self: start;
  margin-top: 24px;
  margin-bottom: 46px;
}

/* Footer places Lauri as a real grid item (she is a column in the
 * reference), not an absolute overlay like the mid card. */
.ll-cta--v2[data-ll-placement="footer"] .llc-lauri {
  grid-area: portrait;
  position: relative;
  align-self: end;
  width: 330px;
  max-width: none;
  margin-bottom: -46px;
}

/* ====================================================================== */
/* TOP — "Want to see how I interpret a dream about losing your car?"      */
/* Compact. Not in the reference; derived from its language.               */
/* ====================================================================== */

/*
 * Three-part composition: larger phone left, copy centre, real Lauri cutout
 * anchored to the bottom-right. v2's top card put a small phone on the left,
 * copy floating mid-card and nothing at all on the right.
 */
.ll-cta--v2[data-ll-placement="top"] {
  --ll-phone-w: 212px;
  --ll-avatar-size: 48px;
  display: grid;
  grid-template-columns: 244px minmax(0, 1fr) 268px;
  grid-template-rows: auto auto auto;
  grid-template-areas:
    "stage eyebrow portrait"
    "stage copy    portrait"
    "stage action  portrait";
  align-content: center;
  column-gap: 30px;
  padding: 40px 34px 0;
  min-height: 470px;
}

.ll-cta--v2[data-ll-placement="top"] .llc-stage { grid-row: 1 / -1; }
.ll-cta--v2[data-ll-placement="top"] .llc-eyebrow-slot { align-self: end; }
.ll-cta--v2[data-ll-placement="top"] .llc-copy { align-self: start; max-width: 420px; }

/* Desktop shows the free-form cutout, so the circular avatar in the eyebrow
 * would be a redundant second Lauri. */
.ll-cta--v2[data-ll-placement="top"] .llc-brand .llc-avatar { display: none; }

.ll-cta--v2[data-ll-placement="top"] .llc-lauri {
  grid-area: portrait;
  position: relative;
  align-self: end;
  justify-self: end;
  width: 292px;
  max-width: none;
  margin-right: -18px;
  margin-bottom: -44px;
}

.ll-cta--v2[data-ll-placement="top"] .llc-headline {
  font-size: clamp(24px, 2.3vw, 32px);
  max-width: 17ch;
}

.ll-cta--v2[data-ll-placement="top"] .llc-action {
  align-self: start;
  margin-top: 22px;
  margin-bottom: 44px;
}

/* Intermediate desktop / tablet: drop the portrait column before anything
 * can clip, rather than letting three columns fight over the width. */
@media (min-width: 768px) and (max-width: 1023px) {
  .ll-cta--v2[data-ll-placement="top"] {
    --ll-phone-w: 180px;
    grid-template-columns: 210px minmax(0, 1fr);
    grid-template-areas:
      "stage eyebrow"
      "stage copy"
      "stage action";
    column-gap: 24px;
  }
  .ll-cta--v2[data-ll-placement="top"] .llc-lauri { display: none; }
}

/* ====================================================================== */
/* Mobile                                                                  */
/* ====================================================================== */

@media (max-width: 767px) {
  .ll-cta--v2 {
    border-radius: 20px;
    margin: 24px auto;
  }

  /* Single column, reference order: eyebrow -> Lauri in the portal ->
   * headline/lede -> phone -> button. */
  .ll-cta--v2[data-ll-placement="top"],
  .ll-cta--v2[data-ll-placement="mid"],
  .ll-cta--v2[data-ll-placement="footer"] {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    grid-template-areas: "eyebrow" "portrait" "copy" "stage" "action";
    justify-items: center;
    grid-auto-flow: row;
    align-content: start;
    text-align: center;
    row-gap: 18px;
    column-gap: 0;
    padding: 32px 20px 36px;
    min-height: 0;
    height: auto;
  }

  /* At least as prominent as desktop, per owner direction. */
  .ll-cta--v2[data-ll-placement="top"] { --ll-phone-w: 228px; --ll-avatar-size: 52px; }

  /*
   * TOP mobile — four separate zones in natural grid flow. Nothing is
   * absolutely positioned over the phone, so the headline can never overlap
   * the app conversation the way it did in v2, and card height comes from
   * content rather than a min-height canvas.
   *
   *   1 eyebrow row (52px avatar + wordmark)
   *   2 headline block
   *   3 dominant centred phone preview
   *   4 full-width CTA
   */
  .ll-cta--v2[data-ll-placement="top"] {
    grid-template-areas: "eyebrow" "copy" "stage" "action";
    row-gap: 16px;
    padding: 26px 20px 28px;
  }
  /* The desktop rule spans the stage across every row. Without this reset it
   * keeps spanning on mobile, so the phone sits under the eyebrow, headline
   * and button and they all render on top of the app conversation. */
  .ll-cta--v2[data-ll-placement="top"] .llc-stage {
    grid-row: auto;
    grid-area: stage;
  }
  .ll-cta--v2[data-ll-placement="top"] .llc-headline {
    font-size: 25px;
    line-height: 1.12;
    max-width: 20ch;
    margin-inline: auto;
  }
  /* The large cutout is desktop-only; mobile keeps the refined avatar. */
  .ll-cta--v2[data-ll-placement="top"] .llc-lauri { display: none; }
  .ll-cta--v2[data-ll-placement="top"] .llc-brand .llc-avatar { display: block; }
  .ll-cta--v2[data-ll-placement="top"] .llc-action { margin: 0; }
  .ll-cta--v2[data-ll-placement="mid"] { --ll-phone-w: 208px; }
  .ll-cta--v2[data-ll-placement="footer"] { --ll-phone-w: 208px; }

  /* Nothing may span rows on mobile — every zone stays in document flow. */
  .ll-cta--v2 .llc-stage,
  .ll-cta--v2 .llc-copy,
  .ll-cta--v2 .llc-eyebrow-slot,
  .ll-cta--v2 .llc-action,
  .ll-cta--v2 .llc-lauri { grid-row: auto; }
  /* Full width, so splitting the headline into line blocks during the
   * entrance cannot make the column shrink-wrap and shift layout. */
  .ll-cta--v2 .llc-copy { max-width: 100%; width: 100%; }
  .ll-cta--v2 .llc-brand { justify-content: center; }
  .ll-cta--v2 .llc-rule { margin-left: auto; margin-right: auto; }
  .ll-cta--v2 .llc-lede { margin-left: auto; margin-right: auto; }
  .ll-cta--v2 .llc-action { width: 100%; }
  .ll-cta--v2 .llc-btn {
    width: 100%;
    min-height: 58px;      /* 56-64px, not a full-height panel */
    padding: 16px 22px;
    font-size: 16px;
  }

  .ll-cta--v2 .llc-headline { font-size: 28px; }

  /* Lauri centred inside the portal ring above the headline — the third
   * panel of the reference. */
  .ll-cta--v2[data-ll-placement="mid"] .llc-lauri,
  .ll-cta--v2[data-ll-placement="footer"] .llc-lauri {
    grid-area: portrait;
    position: relative;
    left: auto;
    bottom: auto;
    align-self: center;
    justify-self: center;
    width: 236px;
    margin: 6px auto -10px;
    z-index: 3;
  }

  /* On mobile the portal belongs behind Lauri, not behind the phone. */
  .ll-cta--v2[data-ll-placement="mid"] .llc-mobile-portal,
  .ll-cta--v2[data-ll-placement="footer"] .llc-mobile-portal {
    grid-area: portrait;
    display: block;
    position: relative;
    align-self: center;
    justify-self: center;
    width: 300px;
    aspect-ratio: 1;
    z-index: 1;
  }

  .ll-cta--v2[data-ll-placement="footer"] .llc-action { margin: 4px 0 0; }
  .ll-cta--v2[data-ll-placement="mid"] .llc-lauri { margin-right: auto; }
}

/*
 * Carried over from the v1 hotfix VERBATIM and deliberately.
 * display:none removes the footer from layout AND prevents the
 * IntersectionObserver-driven preview from initialising, requesting media,
 * or generating an impression while hidden. It stays until the mobile
 * footer passes owner visual approval.
 */
@media (max-width: 767px) {
  .ll-cta[data-ll-placement="footer"] {
    display: none !important;
    height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
  }
}

/* ====================================================================== */
/* Modal — clean full-bleed player, NO decorative chassis                  */
/* ====================================================================== */

.ll-cta-modal--v2 {
  padding: 0;
  border: 0;
  max-width: none;
  max-height: none;
  width: 100vw;
  height: 100dvh;
  overflow: hidden;
  background: transparent;
}

.ll-cta-modal--v2::backdrop {
  background: rgba(2, 5, 12, 0.88);
  backdrop-filter: blur(6px);
}

/*
 * Desktop: video and a COMPACT CTA panel centred as one group, panel to the
 * right of the video. Mobile: CTA immediately below. The video is always the
 * dominant element; the panel is an invitation, not a second advert.
 */
.ll-cta-modal__frame {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 30px;
  padding: 24px;
  box-sizing: border-box;
}

.ll-cta-modal__player {
  position: relative;
  flex: 0 0 auto;
  aspect-ratio: 1080 / 2152;
  height: min(86dvh, 940px);
  width: auto;
  max-width: 60vw;
  border-radius: 20px;
  overflow: hidden;
  background: #000;
  box-shadow: 0 40px 90px -24px rgba(0, 0, 0, 0.8);
}

.ll-cta-modal__video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: fill;
  background: #000;
}

.ll-cta-modal__cta {
  flex: 0 0 auto;
  width: 290px;
  max-width: 42vw;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  padding: 20px 22px 22px;
  border-radius: 20px;
  background: rgba(5, 13, 31, 0.92);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08);
}

.ll-cta-modal__avatar {
  --ll-avatar-size: 68px;
  margin: 0;
}

/* Brand line above the headline. Tightened gaps keep the panel the same
 * compact height it was before this line existed. */
.ll-cta-modal__eyebrow {
  margin: 0;
  font-size: 12px;
  letter-spacing: 0.18em;
}

.ll-cta-modal__title {
  margin: 0;
  font-family: var(--ll-font-display);
  font-weight: 600;
  font-size: 25px;
  line-height: 1.14;
  color: var(--ll-text);
}

.ll-cta-modal__cta-btn {
  width: 100%;
  min-height: 56px;
  padding: 14px 20px;
  font-size: 16px;
  text-decoration: none;
  white-space: nowrap;     /* label stays on one line */
  /* Restrained: no oversized glow on the modal CTA. */
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.22) inset;
}

.ll-cta-modal__close {
  position: absolute;
  top: 14px;
  right: 16px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 0;
  cursor: pointer;
  font-size: 26px;
  line-height: 1;
  color: var(--ll-text);
  background: rgba(255, 255, 255, 0.14);
  z-index: 3;
}
.ll-cta-modal__close:focus-visible {
  outline: 3px solid var(--ll-teal);
  outline-offset: 2px;
}

/*
 * Mobile: stack, and budget the height so the video, its native controls
 * and the CTA all fit inside 100dvh with the Close button clear.
 * Player 58dvh + panel ~128px + close row + padding stays under 100dvh.
 */
@media (max-width: 900px) {
  .ll-cta-modal__frame {
    flex-direction: column;
    justify-content: center;
    gap: 14px;
    padding: 58px 14px 16px;
  }
  .ll-cta-modal__player {
    height: min(58dvh, 560px);
    max-width: 92vw;
  }
  .ll-cta-modal__cta {
    width: min(92vw, 420px);
    max-width: 92vw;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    padding: 12px 14px 14px;
  }
  .ll-cta-modal__avatar { --ll-avatar-size: 64px; }
  .ll-cta-modal__title {
    flex: 1 1 0;
    min-width: 0;
    font-size: 19px;
    line-height: 1.15;
  }
  .ll-cta-modal__eyebrow {
    flex: 1 1 100%;
    order: -1;
    margin-left: 76px;     /* clears the 64px avatar + gap */
    font-size: 11px;
  }
  .ll-cta-modal__cta-btn { flex: 1 1 100%; min-height: 56px; }
}

.ll-cta-body-lock { overflow: hidden; }

/* ====================================================================== */
/* Motion — entrance state. GSAP drives the reveal; these are the          */
/* pre-animation values so nothing flashes before the timeline runs.       */
/* ====================================================================== */

.ll-cta--v2[data-ll-anim="pending"] .llc-phone,
.ll-cta--v2[data-ll-anim="pending"] .llc-lauri,
.ll-cta--v2[data-ll-anim="pending"] .llc-portal__ring,
.ll-cta--v2[data-ll-anim="pending"] .llc-atmos,
.ll-cta--v2[data-ll-anim="pending"] .llc-eyebrow-slot,
.ll-cta--v2[data-ll-anim="pending"] .llc-eyebrow,
.ll-cta--v2[data-ll-anim="pending"] .llc-headline,
.ll-cta--v2[data-ll-anim="pending"] .llc-rule,
.ll-cta--v2[data-ll-anim="pending"] .llc-lede,
.ll-cta--v2[data-ll-anim="pending"] .llc-action {
  opacity: 0;
}



/* ====================================================================== */
/* Reduced motion                                                          */
/*                                                                         */
/* v1 hid the <video> outright, which also hid its poster and left a black */
/* box. v2 swaps in a real <picture> of Lauri's fully rendered answer.     */
/* ====================================================================== */

@media (prefers-reduced-motion: reduce) {
  .ll-cta--v2 .llc-phone__screen { display: none; }
  .ll-cta--v2 .llc-phone__still { display: block; width: 100%; height: 100%; }

  .ll-cta--v2[data-ll-anim="pending"] * { opacity: 1 !important; }
  .ll-cta--v2 .llc-atmos { opacity: 1 !important; }
  .ll-cta--v2 .llc-btn__sweep { display: none !important; }
  .ll-cta--v2 .llc-lauri[data-ll-mask] {
    -webkit-mask-image: none !important;
            mask-image: none !important;
  }
  .ll-cta--v2 .llc-portal__ring { animation: none !important; }
  .ll-cta--v2 *,
  .ll-cta-modal--v2 * {
    animation: none !important;
    transition: none !important;
  }
}
