/* ==========================================================================
   NewLine Break — opening
   The hero is two strata, cut between the two lines of the headline. Stacked,
   they read as one hero. Where scroll can drive animation the stage pins and
   they part along that cut, and the page opens at the break.

   First sight is three things and nothing else: a plain statement of what the
   studio does, a real board it worked on, and the name of the client.
   ========================================================================== */

.opening {
  position: relative;
  /* Same inset the full-bleed bands use, so copy lines up with every section. */
  --bleed: max(var(--pad-x), calc((100vw - var(--shell)) / 2 + var(--pad-x)));
}

.opening__stage {
  position: relative;
  isolation: isolate;
}

.opening__inner {
  position: relative;
  z-index: 2;
  padding-inline: calc(var(--bleed) + var(--gutter)) var(--bleed);
}

/* --------------------------------------------------------------------------
   Upper stratum: the board, and the first line
   -------------------------------------------------------------------------- */

.opening__top {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: end;
  row-gap: clamp(1rem, 3vh, 2rem);
  padding-top: clamp(6.5rem, 12vh, 8rem);
  overflow: hidden;
  background: var(--ground);
}

/* The figure. A real board from a real engagement, cut out of its render so
   it sits on the page rather than in a picture frame. */
.hero__fig {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-self: end;
  min-width: 0;
  margin: 0;
  padding-inline: var(--bleed);
}

/* Sized from the height that is left once the nav, the headline and the lower
   stratum have taken theirs, so the whole hero always fits one screen. */
.hero__board {
  display: block;
  width: auto;
  height: auto;
  max-width: min(100%, 40rem);
  max-height: clamp(8.5rem, 100dvh - 35rem, 26rem);
}

.hero__fig .fig-cap { margin-top: 0.9rem; }

/* Entry. Job: arrival. The board settles into place once, and stays. */
.js .hero__board {
  animation: hero-settle 1.4s var(--ease) both;
}

@keyframes hero-settle {
  from { transform: translateY(14px) scale(1.03); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* --------------------------------------------------------------------------
   Lower stratum: the second line, the lede, the actions
   -------------------------------------------------------------------------- */

.opening__bottom {
  position: relative;
  background: var(--ground);
  padding-bottom: clamp(2.75rem, 6.5vh, 5rem);
}

/* One weight for display type across the page. Rank is carried by size, not
   by going heavier or wider. */
.hero__title {
  margin: 0;
  font-size: clamp(2.25rem, 1.1rem + 2.8vw, 4rem);
  font-weight: 600;
  font-variation-settings: 'wdth' 100, 'wght' 620;
  letter-spacing: -0.036em;
  line-height: 1.02;
  margin-left: -0.04em;
  text-wrap: balance;
}

.hero__line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}

.hero__line-in { display: block; }

/* The name, made literal: the last line is pushed to a new one and a coral
   connector traces the return. Right angles, never diagonals. */
.hero__line--broken {
  position: relative;
  margin-top: 0.06em;
  padding-left: 1.5em;
}

.hero__line--broken::before {
  content: '';
  position: absolute;
  left: 0.12em;
  bottom: 0.26em;
  width: 0.95em;
  height: 0.7em;
  border-left: 3px solid var(--break);
  border-bottom: 3px solid var(--break);
}

.hero__lower {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 2rem;
  margin-top: clamp(1.5rem, 3vh, 2.25rem);
}

.hero__copy { min-width: 0; max-width: 44rem; }

.hero__lede {
  max-width: 40ch;
  font-size: clamp(1.0625rem, 1rem + 0.4vw, 1.3125rem);
  line-height: 1.5;
  color: var(--fog);
  margin-bottom: 2rem;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
}

/* Proof, stated once and plainly: who the work is for. It is a link, because
   the claim is only worth making if the reader can go and check it. */
.hero__proof {
  display: grid;
  gap: 0.35rem;
  flex: 0 0 auto;
  padding: 0.2rem 0 0.2rem 1.25rem;
  border-left: 1px solid var(--line-lit);
  transition: border-color 0.3s var(--ease);
}

.hero__proof-k {
  font-size: 0.6875rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fog-dim);
}

.hero__proof-v {
  font-size: 1.0625rem;
  font-variation-settings: 'wdth' 100, 'wght' 560;
  letter-spacing: -0.01em;
  color: var(--text);
  transition: color 0.3s var(--ease);
}

@media (hover: hover) {
  .hero__proof:hover { border-left-color: var(--signal-lit); }
  .hero__proof:hover .hero__proof-v { color: var(--signal-lit); }
}

/* The title opts out of the generic reveal; the masked lines are the reveal.
   Job: storytelling. The second line arrives after the first, so the headline
   performs the line break the studio is named for. */
.js .hero__title.reveal { opacity: 1; transform: none; }

.js .hero__title .hero__line-in {
  transform: translateY(110%);
  transition: transform 0.9s var(--ease);
}

.js .hero__title.is-in .hero__line-in { transform: none; }
.js .hero__title--lower.is-in .hero__line-in { transition-delay: 0.12s; }

/* --------------------------------------------------------------------------
   Wide: the board stands beside the first line, not above it. On a laptop
   screen height is the scarce thing, and side by side the board is twice the
   size it would be stacked.
   -------------------------------------------------------------------------- */

@media (min-width: 1081px) {
  /* Above this width the two-line structure is the design, not a by-product
     of the container width. Hold it. */
  .hero__line { white-space: nowrap; }

  .opening__top {
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: clamp(1.5rem, 3vw, 3rem);
  }

  .opening__top > .opening__inner {
    grid-column: 1;
    grid-row: 1;
    padding-right: 0;
  }

  .hero__fig {
    grid-column: 2;
    grid-row: 1;
    padding-left: 0;
    padding-bottom: 0.4rem;
  }

  .hero__board { max-height: clamp(10rem, 100dvh - 29rem, 27rem); }
}

/* --------------------------------------------------------------------------
   Inside the break: stacked, this is simply the next section
   -------------------------------------------------------------------------- */

.opening__gap {
  position: relative;
  background: var(--strata);
  border-block: 1px solid var(--line);
}

/* --------------------------------------------------------------------------
   The opening, scroll-driven

   Three gates: a browser that can drive animation from scroll position, motion
   being welcome, and a viewport tall enough to hold a pinned stage. Fail any
   of them and the stack above is what renders. No scroll listener, no library.
   -------------------------------------------------------------------------- */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) and (min-height: 620px) {
    .opening {
      /* One screen of hero, then two of pinned travel: the strata part, the
         seam fails, the step joins it. */
      height: 300dvh;
      view-timeline: --open block;
      /* Not auto. Auto takes scroll-padding as the inset, which would start
         this timeline 6rem early and leave the strata ajar at rest. */
      view-timeline-inset: 0;
    }

    .opening__stage {
      position: sticky;
      top: 0;
      display: flex;
      flex-direction: column;
      height: 100dvh;
      /* clip, not hidden: hidden would make this a scroll container and the
         sticky would have nothing left to stick to. */
      overflow: clip;
    }

    .opening__top {
      flex: 1 1 auto;
      min-height: 0;
    }

    .opening__bottom { flex: 0 0 auto; }

    .opening__top,
    .opening__bottom {
      z-index: 2;
      will-change: transform;
      animation: linear both;
      animation-timeline: --open;
      /* A short hold first, so the hero is read before it moves. */
      animation-range: contain 3% contain 36%;
    }

    .opening__top    { animation-name: part-up; }
    .opening__bottom { animation-name: part-down; }

    /* Hidden at the very end, and only there: a stratum that has left the
       screen must take its links out of the tab order with it. */
    @keyframes part-up   { to { transform: translateY(-101%); visibility: hidden; } }
    @keyframes part-down { to { transform: translateY(101%);  visibility: hidden; } }

    /* The cut itself. Coral, because this is the break happening. It is
       absent at rest, where the two strata must read as one surface. */
    .opening__top::after,
    .opening__bottom::before {
      content: '';
      position: absolute;
      left: 0;
      right: 0;
      z-index: 3;
      height: 1px;
      background: var(--break);
      animation: cut-show linear both;
      animation-timeline: --open;
      animation-range: contain 3% contain 7%;
    }

    .opening__top::after     { bottom: 0; }
    .opening__bottom::before { top: 0; }

    @keyframes cut-show { from { opacity: 0; } to { opacity: 1; } }

    .opening__gap {
      position: absolute;
      inset: 0;
      z-index: 1;
      border: 0;
    }
  }
}

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */

/* Stacked: the board goes above the headline, so the two lines of the
   sentence are never separated by a picture. */
@media (max-width: 1080px) {
  .hero__fig {
    order: -1;
    justify-self: start;
    padding-left: calc(var(--bleed) + var(--gutter));
  }
}

@media (max-width: 820px) {
  .opening__inner { padding-inline: var(--pad-x); }
  .hero__fig { padding-inline: var(--pad-x); }
  .hero__line--broken { padding-left: 1.6em; }
  .hero__lower { display: block; }
  .hero__proof { display: inline-grid; margin-top: 2rem; }

  /* Without scripting the nav sits in the flow above the opening at this
     width, so the room kept clear for a fixed bar is not needed. */
  html:not(.js) .opening__top { padding-top: 2rem; }
}
