/* ===========================================================================
   landing-intro: the reading that stands on the horizon
   ---------------------------------------------------------------------------
   The ground does not change. What changes is where the reader stands on it:
   as the cover gives way the eye comes down off its survey until the weave
   converges on a horizon, and the quotation takes the title's place above
   that line while the terrain runs away beneath it.

   The line is not a fraction of the viewport. `--terrain-plane` is the same
   projection the weave is drawn through, solved for a ground with no relief
   in it and published by the loom every frame, so the reading answers to the
   horizon the scene actually has at whatever size and at whatever point in
   the descent. The surface sample next to it, `--terrain-horizon`, carries
   the ground's own slow weather and drifts by a dozen pixels while the page
   stands still; a column hung from that drifted with it, which is the
   breathing a reader sees as the type refusing to settle.

   The reveal is the archive's own: each character in a slot that clips it,
   arriving on its own delay, studied from motion-studies/hero 1.mp4 and
   already carried by the medication record. A beat leaves through the same
   clip, upward, so the line is never bare and never crowded.
   =========================================================================== */

.landing-intro{
  --corridor:min(1060px,76vw);
  /* The column the directions are set in, to the left of the names they
     point at and on the quotation's own left edge. Its measure is whatever
     the page leaves between that edge and a gutter short of the chapter
     marks, which the index module publishes as `--index-column-left`, up to
     the chapter brief's measure. */
  --direction-gap:clamp(36px,6vw,96px);
  --direction-measure:min(290px,calc(var(--index-column-left,38vw) - 64px));
  --direction-left:calc(var(--index-column-left,38vw) / 2 - var(--direction-measure) / 2);
  --direction-size:clamp(16px,1.45vw,21px);
  /* Optical lift for the quotation and its citation; guidance cancels it. */
  --quote-lift:clamp(14px,2.8vh,20px);
  /* Keep guidance at its established distance from the masthead and ground. */
  --mark-room:18px;
  --skip-room:116px;
  --line:var(--terrain-plane,var(--terrain-horizon,62%));
  /* The top of the room the reading is given. The bar the title travels into
     stands above it, so the reading begins between that bar and the
     ground, then takes its small optical lift. The
     module measures that bar and publishes `--landing-ceiling`; the clamp is
     only the standing answer for the frame before it has. */
  --ceiling:var(--landing-ceiling,clamp(72px,8vh,96px));
  --intro-ease:cubic-bezier(.32,.06,.2,1);
  position:absolute;
  z-index:4;
  inset:0;
  opacity:0;
  pointer-events:none;
  visibility:hidden;
  transition:opacity .92s var(--intro-ease),visibility .92s
}
.landing-intro[data-intro-open="true"]{opacity:1;visibility:visible}

/* One column, standing just above the middle of the white. The room it is placed in
   runs from the bar at the top of the page to the line the ground ends at,
   and what is centerd on that room is the reading: a block hung by its foot
   closed on the horizon and left the whole upper half of the page empty above
   it, which reads as a composition that has slipped down the screen rather
   than one that was placed.

   The attribution hangs below the reading: it belongs to the quotation and retires with it, and
   left in the flow its empty space went on pushing three directions a
   fifth of the room higher than the readings they follow.

   The quotation readings share a single grid cell and every one sizes it,
   so the column's height is the same whichever reading is standing in it, and
   a stable column therefore does not move as the passage turns. */
.intro-column{
  position:absolute;
  left:50%;
  top:calc((var(--ceiling) + var(--line)) / 2 - var(--quote-lift));
  display:grid;
  justify-items:start;
  width:var(--corridor);
  transform:translate(-50%,-50%)
}
.intro-readings{display:grid;align-content:center;width:100%}
.intro-beat{
  grid-area:1 / 1;
  align-self:center;
  margin:0;
  color:var(--landing-ink);
  font-family:var(--landing-sans);
  font-size:clamp(27px,2.9vw,44px);
  font-weight:320;
  line-height:1.1;
  letter-spacing:-.038em;
  text-wrap:pretty;
  hyphens:none
}
/* The quotation readings share one cell and all three size it, which holds
   the column still between them; an idle beat therefore stays in the layout
   pass and only stops painting. */
.intro-beat[data-beat-state="idle"]{visibility:hidden;pointer-events:none}
/* The passage carries its own emphasis, and the cut keeps it. */
.intro-beat b{font-weight:600;letter-spacing:-.042em}

/* The directions are the archive's own voice rather than the end of the
   passage they follow, and they give the middle of the page away. As each
   one arrives, the chapters it names are revealed in the center at the
   coordinates the chapter index gives them, so the direction narrows to the
   room beside those names. Timeline and readings 01–04 use the left;
   Summary and appendages use the matching space on the right. Both columns
   reserve the same lower room for the shared navigation row.

   It leaves the flow to do it. The quotation readings share one grid cell and the
   cell is sized by whichever of them is tallest; a direction set in a narrow
   column runs to five lines and would have sized the cell off itself, which
   would have carried the quotation's own three readings out of the middle of
   the room they are centerd in. Out of flow, the cell is the quotation's and
   the quotation does not move. */
/* Two classes, and not for emphasis: the readings restate their own size at
   two narrower windows, and a rule of one class written above those loses to
   them however specific its intent. */
.intro-beat.intro-beat--guidance{
  position:absolute;
  left:calc(var(--direction-left) - (50vw - var(--corridor) / 2));
  top:0;
  width:var(--direction-measure);
  max-width:none;
  font-size:var(--direction-size);
  font-weight:400;
  line-height:1.38;
  letter-spacing:-.018em;
  text-wrap:pretty;
  transform:translateY(var(--direction-shift));
  transition:transform .82s var(--intro-ease)
}
/* Level with the names it names, and never under the bar or over the skip
   control. `--index-anchor` is the middle of the set the index has standing
   at this moment, published by the column module, and `--beat-height` is
   this direction's own height, published by the opening module, so the
   direction's top is solved in the page's own coordinates and then clamped
   to its established upper and lower reading limits. Those limits stay fixed
   when the navigation moves. `--direction-shift` is that top expressed from the
   top of the column the direction is set in, which is where the room's
   middle less half the reading cell puts it. It travels on a transform,
   which is the only way a move between two rests can be smooth on a page
   already drawing a terrain. */
.intro-beat--guidance{
  --room-mid:calc((var(--ceiling) + var(--line)) / 2);
  --direction-top:clamp(
    calc(var(--ceiling) + var(--mark-room)),
    calc(var(--index-anchor,var(--room-mid)) - var(--beat-height,0px) / 2),
    calc(var(--line) - var(--skip-room) - var(--beat-height,0px)));
  --direction-shift:calc(var(--direction-top) - var(--room-mid) + var(--intro-cell,0px) / 2 + var(--quote-lift))
}
.intro-beat.intro-beat--right{
  left:calc(100vw - var(--direction-left) - var(--direction-measure) - (50vw - var(--corridor) / 2))
}
.intro-beat--guidance b{font-weight:600;letter-spacing:-.022em}
@media(prefers-reduced-motion:reduce){
  .intro-beat.intro-beat--guidance{transition:none}
}

/* Where the reader is in the passage, in the archive's own position mark: a
   dot for each reading and the current one drawn out into a pill. It is the
   same component the chapter drawer carries. Both controls share the quote's
   edges and one baseline: progress starts the row, and Skip closes it. */
.intro-navigation{
  position:absolute;
  left:calc((100% - var(--corridor)) / 2);
  right:calc((100% - var(--corridor)) / 2);
  top:calc(var(--line) - 72px);
  display:grid;
  grid-template-columns:minmax(0,1fr) auto;
  column-gap:24px;
  align-items:center;
  z-index:1
}
.intro-progress{
  --dot:6px;
  --dot-open:34px;
  --dot-gap:9px;
  --dot-count:7;
  position:relative;
  grid-column:1;
  grid-row:1;
  justify-self:start;
  display:flex;
  align-items:center;
  margin:0;
  gap:var(--dot-gap);
  /* Pinned to what the row measures at rest, so a mark can be drawn out
     without the row breathing under it. */
  width:calc(var(--dot-count) * var(--dot) + (var(--dot-open) - var(--dot))
    + (var(--dot-count) - 1) * var(--dot-gap));
  contain:layout
}
/* The current mark is drawn out into a pill, which is a width change: `scaleX`
   would squash the round caps into ellipses at six pixels, so transform cannot
   express it. This is `landing-pill-drawer.css`'s own decision at its own
   sizes, and the cost is bounded the same way, by the pinned width and the
   containment above: seven dots in a row that cannot reflow anything outside
   itself. */
.intro-progress span{
  display:block;
  flex:0 0 auto;
  width:var(--dot);
  height:var(--dot);
  border-radius:999px;
  background:color-mix(in srgb,var(--landing-ink) 20%,transparent);
  transition:background .44s ease,width .56s var(--intro-ease)
}
.intro-progress span[data-read="true"]{background:color-mix(in srgb,var(--landing-ink) 40%,transparent)}
.intro-progress span[data-current="true"]{
  width:var(--dot-open);
  background:color-mix(in srgb,var(--landing-ink) 66%,transparent)}

/* The attribution closes the column, under the reading and still clear of the
   ground. It is set against the far edge of the measure, so the quotation
   opens on the left of the corridor and is answered on the right. */
.intro-credit{
  position:absolute;
  right:0;
  top:100%;
  display:grid;
  gap:3px;
  justify-self:end;
  margin:clamp(22px,2.8vh,34px) 0 0;
  max-width:60ch;
  color:color-mix(in srgb,var(--landing-ink) 62%,var(--landing-paper));
  font:450 10px/1.62 var(--landing-mono);
  letter-spacing:.01em;
  text-align:right;
  /* Ranged right against the far edge of the measure, so the rag is on the
     inside where the quotation is; balanced, because four lines of monospace
     set to a hard edge otherwise step in and out by twenty characters. */
  text-wrap:balance;
  opacity:0;
  transition:opacity .8s var(--intro-ease)
}
.landing-intro[data-intro-credit="true"] .intro-credit{opacity:1}
.intro-credit cite{font-style:italic}

/* The way out of the sequence, offered inside it. A reader who has taken the
   archive's point before its last rest should not have to spend three more
   gestures to act on it, and a page that answers every gesture with a page
   turn has to say somewhere that it can also be left. It is the page's own
   skip link wearing the archive's link affordance, and it hands the reader to
   the index at once rather than travelling there. */
.intro-skip{
  position:relative;
  z-index:1;
  grid-column:2;
  grid-row:1;
  justify-self:end;
  margin:0;
  box-sizing:border-box;
  min-height:44px;
  display:inline-flex;
  align-items:center;
  padding:11px 15px;
  border:1px solid color-mix(in srgb,var(--landing-ink) 15%,transparent);
  border-radius:999px;
  color:color-mix(in srgb,var(--landing-ink) 66%,var(--landing-paper));
  font:500 10px/1 var(--landing-mono);
  letter-spacing:.085em;
  text-transform:uppercase;
  text-decoration:none;
  white-space:nowrap;
  pointer-events:auto;
  transition:color .25s ease,border-color .25s ease,background .25s ease}
.intro-skip::after{
  content:"";
  display:inline-block;
  width:9px;
  height:9px;
  margin-left:9px;
  vertical-align:-1px;
  background:currentColor;
  mask:var(--mhc-link-arrow-right) center / contain no-repeat;
  -webkit-mask:var(--mhc-link-arrow-right) center / contain no-repeat;
  transform:rotate(90deg) translateX(-1px);
  transition:transform .3s var(--mhc-link-ease,cubic-bezier(.22,1,.36,1))}
.intro-skip:is(:hover,:focus-visible){
  border-color:color-mix(in srgb,var(--landing-ink) 34%,transparent);
  background:color-mix(in srgb,var(--landing-ink) 5%,transparent);
  color:var(--landing-ink)}
.intro-skip:is(:hover,:focus-visible)::after{transform:rotate(90deg) translateX(2px)}
.intro-skip:focus-visible{outline:2px solid var(--mhc-accent-ink);outline-offset:3px}
.intro-credit b{font-weight:600;color:color-mix(in srgb,var(--landing-ink) 84%,var(--landing-paper))}

/* The clipped character. `overflow:hidden` on the slot is what makes a
   half-arrived letter read as sliced rather than as floating, and the padding
   pair restores the room ascenders and descenders need inside that clip. */
.intro-word{display:inline-block;white-space:nowrap}
.intro-slot{display:inline-block;overflow:hidden;vertical-align:bottom;padding-block:.16em;margin-block:-.16em}
/* No `will-change` here. A reading is cut into upward of a hundred and fifty
   clipped characters, and a standing hint on each of them asks the compositor
   for a hundred and fifty layers that outlive the half-second they were
   wanted for; the animation itself promotes what it needs while it runs. */
.intro-letter{display:inline-block;transform-origin:50% 100%}
[data-beat-state="waiting"] .intro-letter{opacity:0;transform:translate3d(0,116%,0) rotate(var(--letter-tilt,0deg))}
[data-beat-state="arriving"] .intro-letter{
  animation:intro-letter-arrive var(--letter-duration,560ms) cubic-bezier(.2,.72,.22,1)
    calc(var(--letter-delay,0ms) + var(--beat-entry,0ms)) both}
[data-beat-state="leaving"] .intro-letter{
  animation:intro-letter-leave var(--letter-exit,360ms) cubic-bezier(.62,.03,.86,.34) var(--letter-exit-delay,0ms) both}
@keyframes intro-letter-arrive{
  from{opacity:0;transform:translate3d(0,116%,0) rotate(var(--letter-tilt,0deg))}
  62%{opacity:1}
  to{opacity:1;transform:translate3d(0,0,0) rotate(0deg)}
}
@keyframes intro-letter-leave{
  from{opacity:1;transform:translate3d(0,0,0) rotate(0deg)}
  to{opacity:0;transform:translate3d(0,-118%,0) rotate(calc(var(--letter-tilt,0deg) * -.7))}
}

/* quote 2.mp4: intact words travel horizontally, then gather into a sentence.
   Each column enters from its outer edge, keeping the chapter names clear.
   The beat's vertical positioning remains on its own separate transform. */
.intro-beat--guidance{--word-travel:clamp(-260px,-18vw,-100px)}
.intro-beat--guidance.intro-beat--right{--word-travel:clamp(100px,18vw,260px)}
.intro-beat--guidance[data-beat-state="waiting"] .intro-word{
  opacity:0;transform:translate3d(var(--word-travel),0,0)
}
.intro-beat--guidance[data-beat-state="arriving"] .intro-word{
  animation:intro-word-arrive 720ms cubic-bezier(.16,1,.3,1)
    calc(var(--word-delay,0ms) + var(--beat-entry,0ms)) both
}
.intro-beat--guidance[data-beat-state="leaving"] .intro-word{
  animation:intro-word-leave 300ms cubic-bezier(.55,.05,.8,.3) var(--word-exit-delay,0ms) both
}
@keyframes intro-word-arrive{
  from{opacity:0;transform:translate3d(var(--word-travel),0,0)}
  18%{opacity:1}
  to{opacity:1;transform:translate3d(0,0,0)}
}
@keyframes intro-word-leave{
  from{opacity:1;transform:translate3d(0,0,0)}
  to{opacity:0;transform:translate3d(calc(var(--word-travel) * .24),0,0)}
}

/* The opening is long enough to want its own travel, and the page carries no
   scrollbar: the rests are the way through it, and a bar down the edge only
   reports a length the reader is not meant to be measuring. `overscroll-
   behavior` is the other half of that: a page whose travel is entirely
   between declared rests has nothing beyond its two ends, and the rubber band
   at them drags the whole composition off a rest and throws it back, which is
   the shake a reader meets on arriving at the cover. */
.landing-enhanced.landing-has-intro .loom-stage{height:920svh;min-height:6000px}
html:has(body.landing-page){scrollbar-width:none;-ms-overflow-style:none;overscroll-behavior-y:none}
body.landing-page{overscroll-behavior-y:none}
html:has(body.landing-page)::-webkit-scrollbar{width:0;height:0;display:none}
body.landing-page::-webkit-scrollbar{width:0;height:0;display:none}

/* The cover's own furniture stands down while the reading holds the line. It
   goes early and slowly, because it is the first thing in the opening gesture
   to move and a reader should see the cover being taken apart rather than
   find it already gone. */
.landing-intro-quiet .terrain-readout,
.landing-intro-quiet .landing-continue{opacity:0;pointer-events:none;transition:opacity .86s ease}

@media(max-width:1100px){
  .landing-intro{--corridor:min(760px,86vw)}
  .intro-beat{font-size:clamp(21px,3.4vw,34px)}
}
@media(max-width:820px){
  .landing-intro{--corridor:calc(100vw - 72px);--direction-gap:28px}
  .intro-beat{font-size:clamp(21px,4.4vw,27px)}
  .intro-progress{--dot-open:26px;--dot-gap:7px;--dot:5px}
  .intro-credit{justify-self:start;text-align:left}
}

/* Script off. The opening is a quotation and four
   directions, and every one of them is readable standing still. */
body:not(.landing-enhanced) .landing-intro{
  position:relative;
  inset:auto;
  width:min(760px,calc(100vw - 48px));
  margin:0 auto;
  padding:clamp(48px,8vh,96px) 0;
  opacity:1;
  visibility:visible
}
body:not(.landing-enhanced) .intro-column{position:relative;left:auto;top:auto;width:100%;transform:none}
body:not(.landing-enhanced) .intro-credit{position:relative;right:auto;top:auto;justify-self:start;text-align:left}
body:not(.landing-enhanced) .intro-beat{grid-area:auto;align-self:auto;margin-bottom:.8em;visibility:visible}
body:not(.landing-enhanced) .intro-beat--guidance{position:static;left:auto;width:auto;max-width:none;transform:none}
body:not(.landing-enhanced) .intro-navigation{position:static;display:block}
body:not(.landing-enhanced) .intro-skip{position:static;margin:1.4em 0 0;display:inline-block}
body:not(.landing-enhanced) .intro-credit{opacity:1}
body:not(.landing-enhanced) .intro-progress{display:none}

/* The study's still frame: every clipped character at rest, so a capture
   reports where the type sits rather than where it happens to be passing. */
.preview-still .intro-letter,
.preview-still .intro-beat--guidance .intro-word,
.preview-still .pill-caption-letter{animation:none!important;opacity:1!important;transform:none!important}
.preview-still .intro-beat[data-beat-state="leaving"]{visibility:hidden}

@media(prefers-reduced-motion:reduce){
  .landing-enhanced.landing-has-intro .loom-stage{height:640svh;min-height:3900px}
  .landing-intro,.intro-credit,.intro-progress,.intro-progress span,.intro-skip,.intro-skip::after{transition:none}
  .intro-skip:is(:hover,:focus-visible)::after{transform:rotate(90deg) translateX(-1px)}
  [data-beat-state] .intro-letter{animation:none!important;opacity:1!important;transform:none!important}
  .intro-beat--guidance[data-beat-state] .intro-word{animation:none!important;opacity:1!important;transform:none!important}
}
