/* ============================================================================
   aio-hero-stats.css — AI Optimization page · Sections 1 (hero) + 2 (stats3)
   ----------------------------------------------------------------------------
   Loads AFTER page-ai-optimization.css. Inherits all --aio-* tokens and
   .aio2-bleed from that base file — none are redeclared here.

   Composition: hero is a 1080 px tall full-bleed video backdrop. The title
   (y=206) and subtitle (y=385) overlay the video top half. Stats3 (y=519→889)
   is a SIBLING section pulled into the video lower half via negative margin-top.
   Statement starts at y=1133, 53 px below the video bottom edge.

   Spacers (designer-measured, no rhythm-token substitution):
     206 px — hero top → title         (padding-top on .aio2-hero__inner; bakes
                                        header height + spacer-130 into one value
                                        per Figma anchor y=206 on title node)
      29 px — title → subtitle         (margin-bottom on .aio2-hero__title)
     561 px — negative pull on stats3  (margin-top: -561 lifts stats3 top to y=519;
                                        derived: 1080 − 519 = 561)
     244 px — stats3 → statement       (margin-bottom on .aio2-stats; from
                                        stats3 bottom y=889 to statement y=1133)
   ========================================================================== */


/* ---- 1. Hero --------------------------------------------------------------- */

.aio2-hero {
  /* .aio2-bleed (set on the element) handles 100vw escape — no need for
     width/margin-inline here. Only position, height, clip, and stack.
     BUG 2 FIX: hero is a 1080 px backdrop. Stats3 overlaps its lower half
     via margin-top: -561px on .aio2-stats. margin-bottom is 0 here. */
  position: relative;
  background-color: var(--aio-bg);   /* fallback: video-missing reads as intentional dark band */
  height: 1080px;
  overflow: hidden;
  margin: 0;
}

/* Background video — absolute fill behind all content */
.aio2-hero__bg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
  pointer-events: none;
}

/* Gradient overlay — top: dark → transparent (node 2001:6)
   Blends the hero into the dark page top so the video appears to emerge. */
.aio2-hero::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 15%;
  background: linear-gradient(to bottom, #070707, transparent);
  z-index: 1;
  pointer-events: none;
}

/* Gradient overlay — bottom: transparent → black → #0e0e0e (node 2001:7)
   Dissolves the video into the dark page background. "via 34.135%" = midpoint. */
.aio2-hero::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 65%;
  background: linear-gradient(to bottom, transparent 0%, rgba(0, 0, 0, 1) 34.135%, #0e0e0e 100%);
  z-index: 1;
  pointer-events: none;
}

/* Centred content column, above gradients */
.aio2-hero__inner {
  position: relative;
  z-index: 2;
  max-width: var(--container);
  margin-left: auto;
  margin-right: auto;
  padding-top: 206px;     /* anchor y=206 for title node 2001:296; bakes header height + spacer-130 */
  padding-left: var(--gutter);
  padding-right: var(--gutter);
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* Title — node 2001:296
   Font: var(--f-sans). NOT Helvetica Neue — theme font only per build brief. */
.aio2-hero__title {
  font-family: var(--f-sans);
  font-size: 70px;
  line-height: 75px;
  font-weight: 500;
  color: var(--on-dark-1);
  text-align: center;
  max-width: 578px;
  margin: 0 0 29px;      /* spacer-29: title → subtitle */
}

/* Subtitle — node 2001:295 */
.aio2-hero__subtitle {
  font-family: var(--f-sans);
  font-size: 18px;
  line-height: 26px;
  font-weight: 400;
  color: var(--on-dark-1);
  text-align: center;
  max-width: 502px;
  margin: 0;
}


/* ---- 2. Stats3 ------------------------------------------------------------- */

.aio2-stats {
  /* BUG 2 FIX: pull stats3 up to y=519 by overlapping the hero's lower half.
     margin-top: -(1080 - 519) = -561px. position:relative + z-index:2 puts
     the section above the hero's gradient pseudo-elements (z-index: 1) and
     inner content (z-index: 2 in hero, but hero's stacking context is lower
     in the page order). */
  position: relative;
  z-index: 2;
  margin-top: -561px;
  margin-bottom: 244px;   /* spacer-244: stats3 bottom y=889 → statement y=1133 */
  margin-right: 0;
  margin-left: 0;
}

/* Three-card grid — "3 BOX" node 2007:3 */
.aio2-stats3__grid {
  display: flex;
  flex-wrap: wrap;
  gap: 15px;
  /* BUG 3 FIX: mirror .container pattern from styles.css line 84.
     Padding lives INSIDE max-width (border-box) so content box = exactly
     --container (1200 px). Card width: (1200 − 30) / 3 = 390 px. ✓       */
  max-width: calc(var(--container) + var(--gutter) * 2);
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
  /* corner-scale-in custom properties — JS reads --csi-stagger */
  --csi-duration: 0.25s;
  --csi-ease:     cubic-bezier(.165, .84, .44, 1);
  --csi-stagger:  0.25s;
  --csi-origin:   top left;
}

.aio2-stats3__card {
  flex: 1 0 0;
  min-width: 300px;
  max-width: 390px;
  /* min-height, NOT height. The design's 370px assumes the 1920 layout where the
     card is 390 wide. As the viewport narrows the container shrinks (--gutter is
     4vw and vw is not zoom-scaled), the Korean rewraps taller, and a fixed height
     spills the source line out of the card — measured at 1511px: +25px, at 1400px:
     +65px. Flex row keeps all three cards equal height via the default stretch. */
  min-height: 370px;
  background-color: var(--aio-bg-card);   /* background-color: safe with var(); background: not */
  border: 1px solid var(--aio-blue);       /* border shorthand + var() is fine per platform rules */
  border-radius: var(--aio-radius);
  padding-top: 74px;
  /* Symmetric 31px sides → 328px content box, matching the design's widest text
     node (2001:289 is 329px). The spec's pr-63px was averaged across three cards
     whose auto-width text nodes have right insets of 30/74/77px; applying the
     average to all three forced ~2 extra wrapped lines on the longest card. */
  padding-right: 31px;
  padding-bottom: 74px;
  padding-left: 31px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

/* Large body statement — top of card */
.aio2-stats3__stat {
  font-family: var(--f-sans);
  font-size: 30px;
  line-height: 40px;
  font-weight: 500;
  letter-spacing: -0.6px;
  color: var(--on-dark-1);
  margin: 0;
  /* line-mask-up custom properties */
  --lmu-duration: 0.75s;
  --lmu-ease:     cubic-bezier(.77, 0, .175, 1);
}

/* Source attribution — bottom of card */
.aio2-stats3__src {
  font-family: var(--f-sans);
  font-size: 12px;
  line-height: 20px;
  font-weight: 400;
  letter-spacing: -0.24px;
  color: rgba(255, 255, 255, 0.6);
  margin: 0;
  /* line-mask-up custom properties */
  --lmu-duration: 0.75s;
  --lmu-ease:     cubic-bezier(.77, 0, .175, 1);
}


/* ---- Animation: corner-scale-in -------------------------------------------
   Ported from fx-lib/css/reveals.css · davispolk.com ruCardsAppear
   Scoped to .aio2-stats3__grid so these rules never collide with other pages.
   JS wires:  reads --csi-stagger, applies transitionDelay per child,
              adds .is-in when the grid enters viewport.                       */

.aio2-stats3__grid[data-fx="corner-scale-in"] > * {
  transform: scale(0);
  transform-origin: var(--csi-origin);
  transition: transform var(--csi-duration) var(--csi-ease);
  will-change: transform;
}

.aio2-stats3__grid[data-fx="corner-scale-in"] > *.is-in {
  transform: scale(1);
}


/* ---- Animation: line-mask-up -----------------------------------------------
   Ported from fx-lib/css/text.css · davispolk.com showByLine
   Scoped to .aio2-stats3 elements.

   CRITICAL — all lines inside one element animate SIMULTANEOUSLY.
   There is no nth-child stagger here by design: the source collapses every
   line to t=0 via GSAP position "-=0.75". Adding per-line delay would diverge.
   Only the per-card 0.25s stagger (--csi-stagger, managed by JS) applies.

   JS wires:  splits content into .fx-lmu__mask > .fx-lmu__inner spans,
              then adds .is-in on the element when it enters viewport.        */

.aio2-stats3__stat[data-fx="line-mask-up"],
.aio2-stats3__src[data-fx="line-mask-up"] {
  display: block;
}

.aio2-stats3__stat[data-fx="line-mask-up"] .fx-lmu__mask,
.aio2-stats3__src[data-fx="line-mask-up"] .fx-lmu__mask {
  display: block;
  overflow: hidden;
}

.aio2-stats3__stat[data-fx="line-mask-up"] .fx-lmu__inner,
.aio2-stats3__src[data-fx="line-mask-up"] .fx-lmu__inner {
  display: block;
  transform: translateY(100%);
  transition: transform var(--lmu-duration) var(--lmu-ease);
  will-change: transform;
}

.aio2-stats3__stat[data-fx="line-mask-up"].is-in .fx-lmu__inner,
.aio2-stats3__src[data-fx="line-mask-up"].is-in .fx-lmu__inner {
  transform: translateY(0);
}


/* ---- prefers-reduced-motion ------------------------------------------------
   The base file (page-ai-optimization.css) kills all transition/animation
   durations to 0.001ms globally. These rules additionally SET the end states
   so elements are visible immediately even before JS fires .is-in.
   Use !important: the base backstop targets duration only, not transform.    */

@media (prefers-reduced-motion: reduce) {
  .aio2-stats3__grid[data-fx="corner-scale-in"] > * {
    transform: scale(1) !important;
    transition: none !important;
  }

  .aio2-stats3__stat[data-fx="line-mask-up"] .fx-lmu__inner,
  .aio2-stats3__src[data-fx="line-mask-up"] .fx-lmu__inner {
    transform: translateY(0) !important;
    transition: none !important;
  }
}


/* ---- Mobile ----------------------------------------------------------------
   Values read from the Figma 375 mobile frame (node 740:2).
   Nothing may overflow horizontally at 375px viewport.                       */

@media (max-width: 768px) {

  /* Hero: switch to auto height (video aspect drives it) and restore gap
     to stats3. 70vh is below the 1152px zoom threshold so no vw/vh
     compensation is needed here. */
  .aio2-hero {
    height: auto;
    min-height: 70vh;
    margin: 0 0 60px;
  }

  /* 80px left only 3px of air under the 77px fixed nav — the title read as
     glued to the header. 160px gives ~83px clearance. */
  .aio2-hero__inner {
    padding-top: 160px;
  }

  /* 740:297 — 34/40 over two authored lines; 17px down to the subtitle
     (title box ends y=11572, subtitle starts y=11589). */
  .aio2-hero__title {
    font-size: 34px;
    line-height: 40px;
    letter-spacing: 0;
    max-width: 100%;
    margin: 0 0 17px;
  }

  /* 740:296 — 16/22. */
  .aio2-hero__subtitle {
    font-size: 16px;
    line-height: 22px;
    max-width: 100%;
  }

  /* Stats3: undo desktop overlap, restore normal flow below the hero. */
  .aio2-stats {
    position: static;
    margin-top: 0;
    margin-bottom: 100px;
    margin-left: 0;
    margin-right: 0;
  }

  /* 740:283 — three 335x319 cards, 20px apart. */
  .aio2-stats3__grid {
    flex-direction: column;
    gap: 20px;
  }

  /* 740:285 specifies py-74 / pl-31 / pr-63 in a fixed 319px box, but that was
     drawn around a 4-line stat: on the live cards it leaves most of the height
     as empty padding. Tightened to 32/28 and the fixed height dropped so each
     card sizes to its own content — the three are still equal-height siblings
     via the flex row's default stretch. The design's 22px gap is kept.
     Note this widens the text column from 241px to 279px, so the stat wraps to
     fewer lines than the Figma frame shows; that is the intended trade for
     removing the dead space. */
  .aio2-stats3__card {
    flex: unset;
    max-width: 100%;
    min-width: 0;
    height: auto;
    min-height: 0;
    padding-top: 32px;
    padding-right: 28px;
    padding-bottom: 32px;
    padding-left: 28px;
    gap: 22px;
    justify-content: center;
  }

  /* 740:286 — 24/30, down from the desktop 30/40. */
  .aio2-stats3__stat {
    font-size: 24px;
    line-height: 30px;
    letter-spacing: -0.48px;
  }

  /* Opt these two out of the phone-wide `body { word-break: break-all }`
     (styles.css, deliberate: it trades ragged Korean rag for mid-word breaks).
     At this size the break-all was splitting "AI에게" into "AI" + "에게" and the
     English source line into "Sear" + "ch". The Korean here is short-eojeol and
     wraps cleanly on word boundaries anyway, so keep-all costs no rag.
     overflow-wrap: break-word is still inherited, so a genuinely unbreakable
     string can never overflow the card. */
  .aio2-stats3__stat,
  .aio2-stats3__src {
    word-break: keep-all;
  }

  /* 740:287 — 10/14. The desktop `margin-top:auto` is dropped here: the mobile
     card centres its whole content block rather than pinning the source to the
     bottom edge, so an auto margin would fight justify-content:center. */
  .aio2-stats3__src {
    font-size: 10px;
    line-height: 14px;
    letter-spacing: -0.2px;
    margin-top: 0;
  }

}
