/* ==========================================================================
   exe.cute v3 — 03 · The approach   (4.0 vh sticky wrapper; 4 stages x 0.75 vh)

   "No generic templates. / No unnecessary complexity. / Just precise, tailor-made execution."

   The section performs its own argument: two claims are struck through and then run the
   develop BACKWARDS, dissolving into the same 4px dot matrix of --ink that everything on
   this page is made of; the third resolves forward out of it. Choreography lives in
   js/ui/approach.js — this file owns geometry, type and the two static gestures (the
   strike-through and the accent hairline) that JS only scrubs.

   Typography and the strike technique are carried over from v2's `.cut__line` block
   (css/styles.css:326-378). The strike is an inline background rather than a pseudo-element
   or `text-decoration` for two reasons: it is scrubbable from 0% to 100%, and with
   `box-decoration-break: clone` it draws one rule per wrapped line fragment instead of a
   single bar across the block — which is what keeps it honest at 390px, where the longer
   claims wrap.
   ========================================================================== */

.approach {
  position: relative;
  /* The wrapper height — (1 + 4 * 0.75) * viewportHeight — is written inline by
     core/stage.js. Never set it here; the two would fight and the stage boundaries
     would stop matching the pinned travel. */
}

.approach__sticky {
  position: sticky;
  top: 0;
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding: 0 var(--gutter);
}

/* --------------------------------------------------------------------------
   The three claims
   -------------------------------------------------------------------------- */
.approach__lines {
  display: flex;
  flex-direction: column;
  gap: clamp(0.35em, 1.5vw, 0.6em);
  width: 100%;
}

/* `align-self: flex-start` in a column flex container shrink-wraps the cross size, so each
   claim is exactly as wide as its own text and the strike-through stops where the sentence
   does. That is why v2 used it, and it is why the h2 must stay a block: as a flex item its
   child span is then a real inline box, which is what `box-decoration-break: clone` needs. */
.approach__line {
  align-self: flex-start;
  max-width: 100%;
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: clamp(1.75rem, 5.6vw, 5.6rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--bone);
}

.approach__txt {
  display: inline;
  /* the strike: an inline background, scrubbed 0% -> 100% from JS */
  background-image: linear-gradient(var(--bone), var(--bone));
  background-repeat: no-repeat;
  background-position: 0 54%;
  background-size: 0% 2px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* `.develop` (base.css) holds the dot-matrix mask while a claim is resolving or dissolving.
   At --dev-r == --dev-full the mask still clips the corner of every 4px cell, so once a
   claim is fully resolved js/ui/approach.js drops the mask entirely — "solid" then means
   solid, which is what the token comment promises and what the 1px accent hairline below
   needs in order not to land in a gap between dots. */
.approach__txt.is-solid {
  -webkit-mask-image: none;
  mask-image: none;
}

/* --------------------------------------------------------------------------
   The one claim that survives — the accent hairline under `precise`
   (v2's `::after` + scaleX, driven here by --hair rather than a class + transition,
   so it scrubs both ways with the scroll like everything else on the page)
   -------------------------------------------------------------------------- */
.approach__line--keep em {
  position: relative;
  color: var(--bone);
}
.approach__line--keep em::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.02em;
  height: 1px;
  background: var(--accent);
  transform: scaleX(var(--hair, 0));
  transform-origin: left center;
}

/* --------------------------------------------------------------------------
   Static fallback — `?nomotion` (class added by JS) and prefers-reduced-motion.

   The wrapper collapses to normal flow, the sticky child becomes a plain relative block
   (relative, not static, so `.section__meta--abs` keeps its containing block), and the
   section's end state is drawn without a single moving pixel: three legible claims, two of
   them struck, the hairline under `precise` already out. The argument survives; the motion
   does not. `height: auto !important` beats the inline height core/stage.js may already
   have written, since an author !important declaration outranks a normal inline one.
   -------------------------------------------------------------------------- */
.approach.is-static {
  height: auto !important;
}
.approach.is-static .approach__sticky {
  position: relative;
  top: auto;
  min-height: 0;
  padding: clamp(96px, 18vh, 200px) var(--gutter) clamp(72px, 12vh, 150px);
}

@media (prefers-reduced-motion: reduce) {
  .approach {
    height: auto !important;
  }
  .approach__sticky {
    position: relative;
    top: auto;
    min-height: 0;
    padding: clamp(96px, 18vh, 200px) var(--gutter) clamp(72px, 12vh, 150px);
  }
  /* the two eliminated claims keep their strike; the surviving one keeps its hairline */
  .approach__line:not(.approach__line--keep) .approach__txt {
    background-size: 100% 2px;
  }
  .approach__line--keep {
    --hair: 1;
  }
}

/* --------------------------------------------------------------------------
   Small screens: the claims wrap, so the strike has to as well — which the inline
   background already handles. Only the vertical rhythm needs loosening.
   -------------------------------------------------------------------------- */
@media (max-width: 560px) {
  .approach__lines {
    gap: clamp(0.5em, 3vw, 0.9em);
  }
  .approach__line {
    font-size: clamp(1.75rem, 8.2vw, 2.6rem);
  }
}
