/* ═══════════════════════════════════════════════════════════════════════════
   THE FORMATIONS: what the landing screen becomes.

   Spheres of lit points, each circled by a few orbital particles, drawn on
   this section's own canvas through the page's one point shader
   (scripts/scene/mount.js), and a camera moving between them in one
   continuous motion (scripts/scene/formations.js): three of them, AI, GAMES
   and WEB, standing round Omry and building the studio's work inside them
   (scripts/scene/worlds.js). Three lines arrive: IMAGINATION, ENGINEERED.
   in the clear air before the worlds; ONE PERSON. FROM IDEA TO PRODUCTION.
   as the worlds pour into one band round him; WHAT IS YOUR VISION?, which
   stays, under the ring they become. Then the ring comes apart and its
   points build WORK (styles/portfolio.css pins WORK under the last screen
   for it).

   Two layouts, and the default is the plain one:

     · a block: the three lines, centred, one over the other, and the three
       worlds' names in a row between the first and the rest. This is what a
       page without scripts gets, what forced colours get, and print.

     · the scene: under `(scripting: enabled)` with motion and in colour, a
       travel box TRAVEL screens tall with a stage pinned for all but the
       first, the canvas behind the lines, each name placed under its sphere
       as it is drawn, and every arrival a function of the playhead
       (scripts/scene/journey.js writes it). One more screen where the
       handoff runs (`HANDOFF_FRAME` there). With less motion, the stage is
       one screen, the worlds drawn still, every line over it.

   Nothing here is hit-tested: there is nothing in it to press. A hand over a
   world is read from the window (scripts/scene/mount.js).
   ═════════════════════════════════════════════════════════════════════════ */

.formations {
  position: relative;
  z-index: 2;
  min-height: auto;
  overflow: visible;
  padding: clamp(96px, 14vw, 170px) var(--gutter);
  background: transparent;
}

.formations-scroll,
.formations-stage { position: relative; }

.formations-canvas { display: none; }

/* ── the lines ─────────────────────────────────────────────────────────── */

.formations-lines {
  display: grid;
  justify-items: center;
  gap: clamp(28px, 5vh, 56px);
  text-align: center;
}

.formations-line {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  line-height: .92;
  text-transform: uppercase;
  text-wrap: balance;
}

/* Lit metal, on the studio heading's own terms: a statement. */
.formations-first {
  font-size: clamp(2.7rem, 7.4vw, 7.6rem);
  letter-spacing: .02em;
  background: linear-gradient(177deg,
    #ffffff 2%, #eef4f7 20%, #b9c6cd 48%, #8894a0 68%, #b3c2ce 92%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Who it is, at the moment the three worlds become one: the person large,
   what he does under it, quieter. */
.formations-one { display: grid; justify-items: center; gap: .18em; }
.formations-one__lead {
  font-size: clamp(2.6rem, 6.6vw, 6.8rem);
  letter-spacing: .02em;
  color: #fff;
  text-shadow: 0 0 30px rgba(99, 216, 255, .2), 0 2px 24px rgba(2, 6, 11, .85);
}
.formations-one__tail {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: clamp(.78rem, 1.15vw, 1.05rem);
  letter-spacing: .32em;
  color: rgba(214, 238, 248, .82);
  text-shadow: 0 1px 14px rgba(2, 6, 11, .9);
}

/* The question, at full white and a size up: the one line the section ends
   on, with a little of the formations' own light behind it. */
.formations-ask {
  font-size: clamp(3rem, 8.4vw, 8.8rem);
  letter-spacing: .015em;
  color: #fff;
  text-shadow: 0 0 34px rgba(99, 216, 255, .22), 0 2px 24px rgba(2, 6, 11, .8);
}

/* ── the worlds' names ─────────────────────────────────────────────────── */

.formations-worlds {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(20px, 5vw, 64px);
  margin: clamp(36px, 6vh, 64px) 0;
  padding: 0;
  list-style: none;
}
.formations-world {
  display: grid;
  justify-items: center;
  gap: 6px;
  text-align: center;
}
.formations-world__name {
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 2.6vw, 2.6rem);
  line-height: .9;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #fff;
}
.formations-world__sub {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: clamp(.62rem, .8vw, .78rem);
  letter-spacing: .26em;
  text-transform: uppercase;
  color: rgba(214, 238, 248, .72);
}
/* Each in its world's light. */
.formations-world[data-world="ai"] .formations-world__name { text-shadow: 0 0 22px rgba(34, 230, 255, .45), 0 2px 18px rgba(2, 6, 11, .9); }
.formations-world[data-world="games"] .formations-world__name { text-shadow: 0 0 22px rgba(255, 120, 200, .4), 0 0 40px rgba(255, 170, 70, .25), 0 2px 18px rgba(2, 6, 11, .9); }
.formations-world[data-world="web"] .formations-world__name { text-shadow: 0 0 22px rgba(120, 110, 255, .45), 0 2px 18px rgba(2, 6, 11, .9); }

/* ═══ THE SCENE ══════════════════════════════════════════════════════════ */
@media (scripting: enabled) and (forced-colors: none) {

  .formations { padding: 0; }

  /* Held at the top for the length of the travel. `overflow: clip` is on THIS
     element rather than on the section, as on every pinned stage here: a
     clipping ancestor between a sticky box and the scroller breaks the stick.
     Nothing on it takes a pointer: in the handoff it lies over WORK. */
  .formations-stage {
    position: sticky;
    top: 0;
    height: 100svh;
    overflow: clip;
    pointer-events: none;
  }

  .formations-canvas {
    display: block;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    background: transparent;
    opacity: 0;
    transition: opacity 900ms var(--ease-soft);
  }
  /* Lit on the frame the first one is drawn (scripts/scene/journey.js). */
  .formations.is-lit .formations-canvas { opacity: 1; }

  /* Each name stands under its sphere: placed there each frame by the
     canvas (scripts/scene/mount.js), and dark until it is. */
  .formations-worlds {
    position: absolute;
    inset: 0;
    z-index: 1;
    margin: 0;
    display: block;
  }
  .formations-world {
    position: absolute;
    left: 0;
    top: 0;
    opacity: 0;
    white-space: nowrap;
    will-change: transform, opacity;
  }
  .formations:not(.is-lit) .formations-world { visibility: hidden; }

  /* The first line stands in the middle of the frame; the other two under
     Omry, in the same place, each arriving on its own number. */
  .formations-lines {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: grid;
    grid-template-rows: 1fr auto;
    justify-items: center;
    padding: 0 var(--gutter) clamp(28px, 7svh, 72px);
  }
  .formations-line { grid-area: 2 / 1; max-width: 16ch; align-self: end; }
  .formations-first { grid-area: 1 / 1 / 3 / 2; align-self: center; }
  .formations-one { max-width: none; }

  /* The first resolves forward out of the depth: tracked wide, soft and a
     little low, it closes to its set width as it lands; and it leaves the
     way the camera passes it, rising, opening and going soft. */
  .formations-first {
    opacity: calc(var(--first, 0) * (1 - var(--first-out, 0)));
    letter-spacing: calc(.02em + (1 - var(--first, 0)) * .32em);
    filter: blur(calc((1 - var(--first, 0)) * 10px + var(--first-out, 0) * 8px));
    transform: translate3d(0, calc((1 - var(--first, 0)) * 26px - var(--first-out, 0) * 34px), 0)
               scale(calc(1 + var(--first-out, 0) * .07));
  }

  /* The second arrives as the worlds pour into the band round him, and
     leaves as the band becomes the ring. */
  .formations-one {
    opacity: calc(var(--one, 0) * (1 - var(--one-out, 0)));
    filter: blur(calc((1 - var(--one, 0)) * 8px + var(--one-out, 0) * 6px));
    transform: translate3d(0, calc((1 - var(--one, 0)) * 22px - var(--one-out, 0) * 18px), 0);
  }
  .formations-one__lead { letter-spacing: calc(.02em + (1 - var(--one, 0)) * .26em); }

  /* The question arrives the same way and stays: it leaves only in the
     handoff, as the points that will be WORK leave the ring around it. */
  .formations-ask {
    opacity: calc(var(--ask, 0) * (1 - var(--leave, 0)));
    letter-spacing: calc(.015em + (1 - var(--ask, 0)) * .28em);
    filter: blur(calc((1 - var(--ask, 0)) * 10px + var(--leave, 0) * 6px));
    transform: translate3d(0, calc((1 - var(--ask, 0)) * 26px - var(--leave, 0) * 22px), 0)
               scale(calc(1 - var(--leave, 0) * .04));
  }

  /* The travel. `svh`, like every travel box on this page, so a sliding URL
     bar does not restate the length of the shot. scripts/scene/formations.js's
     TRAVEL is this number, and tests/scene.mjs holds the two together. */
  @media (prefers-reduced-motion: no-preference) {
    .formations-scroll { height: 900svh; }
  }

  /* ...and one screen more, where WORK is built in the frame rather than
     scrolled up into it: the handoff (scripts/scene/formations.js, HANDOFF).
     The stage holds for it while the ring's points fly into WORK, which is
     pinned under this same screen (styles/portfolio.css). The condition is
     scripts/scene/journey.js's HANDOFF_FRAME. */
  @media screen and (min-width: 901px) and (min-height: 640px) and (min-aspect-ratio: 1/1) and (prefers-reduced-motion: no-preference), screen and (max-width: 900px) and (prefers-reduced-motion: no-preference) {
    .formations-scroll { height: 1000svh; }
  }

  /* A reader who asked for less motion is given the worlds without the
     journey: one screen, the three drawn still round Omry, their names under
     them, the first line over them and the other two under him. */
  @media (prefers-reduced-motion: reduce) {
    .formations-lines { grid-template-rows: auto 1fr auto auto; padding-top: clamp(76px, 11svh, 112px); gap: clamp(8px, 1.6vh, 18px); }
    .formations-line { opacity: 1; filter: none; transform: none; letter-spacing: .02em; }
    .formations-first { grid-area: 1 / 1; align-self: start; max-width: none; font-size: clamp(1.8rem, 4vw, 4rem); }
    .formations-one { grid-area: 3 / 1; }
    .formations-ask { grid-area: 4 / 1; font-size: clamp(2rem, 4.2vw, 4.2rem); }
    .formations-one__lead { font-size: clamp(1.6rem, 3vw, 3rem); letter-spacing: .02em; }
  }
}

/* The document, in order, in ink: no travel, no pin, no drawing. */
@media print {
  .formations { padding: 48px 0 !important; }
  .formations-scroll { height: auto !important; }
  .formations-stage { position: static !important; height: auto !important; overflow: visible !important; }
  .formations-canvas { display: none !important; }
  .formations-worlds { position: static !important; display: flex !important; }
  .formations-world { position: static !important; opacity: 1 !important; transform: none !important; }
  .formations-line { opacity: 1 !important; filter: none !important; transform: none !important; }
  .formations-first { background: none !important; -webkit-text-fill-color: #000 !important; color: #000 !important; }
  .formations-ask, .formations-one__lead, .formations-one__tail, .formations-world__name, .formations-world__sub { color: #000 !important; text-shadow: none !important; }
}
