/* ==========================================================================
   FRONTLINE21 — MOVEMENTS
   One block per movement of the page. Order matches the narrative.

   The reconciliation pass rebuilt the copy system. Every movement now opens
   with one text cluster (eyebrow, headline, deck, body, in one column) and
   spends its asymmetry on the photograph: five columns of picture against
   three of argument, or three against five, alternating down the page. The
   old pattern, a headline at the left and a small grey paragraph in the top
   right corner with a field of nothing between them, is gone.
   ========================================================================== */

/* --- 01 THE CALL ----------------------------------------------------------- */

.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  grid-template-rows: 1fr auto;
  overflow: hidden;
  padding-top: clamp(84px, 12vh, 132px);
}

.hero__field {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-color: var(--ink);
  background-image: url('../images/texture/f21-texture-black.jpg');
  background-size: cover;
  background-position: center;
}

/* The film is the Every Era edit, present day work intercut with the archive.
   It is graded down under the type but not buried: the scrim is weighted to
   the left, where the headline is, and opens to the right. */
.hero__field::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(
      74% 58% at 78% 12%,
      rgba(244, 245, 244, 0.06),
      rgba(244, 245, 244, 0) 60%
    ),
    linear-gradient(96deg, rgba(12, 15, 15, 0.9) 6%, rgba(12, 15, 15, 0.56) 42%, rgba(12, 15, 15, 0.22) 72%),
    linear-gradient(180deg, rgba(12, 15, 15, 0.58), rgba(12, 15, 15, 0.18) 38%, rgba(12, 15, 15, 0.96));
}

.hero__poster {
  opacity: 1;
}

video.hero__film {
  opacity: 0;
  transition: opacity 900ms var(--ease-out);
}

video.hero__film.is-ready {
  opacity: 1;
}

.hero__field picture {
  display: contents;
}

.hero__film {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 42%;
  filter: grayscale(1) contrast(1.04) brightness(0.66);
}

@media (max-width: 720px) {
  .hero__film {
    object-position: 50% 40%;
  }
}

/* The declared grid used to be drawn here as eight stationary rules. It is
   the hairline's field now (hairline.js): the same column lines, shown one at
   a time, for a moment. */

.hero__numeral {
  position: absolute;
  z-index: 1;
  right: calc(var(--margin) * -0.28);
  top: 6vh;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 46vw;
  line-height: 0.74;
  letter-spacing: -0.05em;
  color: transparent;
  -webkit-text-stroke: 1px rgba(244, 245, 244, 0.07);
  pointer-events: none;
  user-select: none;
}

@media (min-width: 1024px) {
  .hero__numeral {
    font-size: 34vw;
    top: 2vh;
  }
}

.hero__body {
  position: relative;
  z-index: 2;
  align-content: end;
  align-items: end;
  row-gap: var(--stack-lg);
  padding-bottom: clamp(32px, 5vh, 60px);
}

.hero__head .eyebrow {
  margin-bottom: var(--stack-md);
}

.hero__title span {
  display: block;
  overflow: hidden;
}

.hero__title b {
  display: block;
  font-weight: inherit;
  transform: translateY(105%);
}

.is-lit .hero__title b {
  transform: translateY(0);
  transition: transform 980ms var(--ease-out);
  transition-delay: var(--line-delay, 0ms);
}

.no-js .hero__title b {
  transform: translateY(0);
}

.is-lit .hero__title span:nth-child(1) b { --line-delay: 90ms; }
.is-lit .hero__title span:nth-child(2) b { --line-delay: 170ms; }
.is-lit .hero__title span:nth-child(3) b { --line-delay: 250ms; }
.is-lit .hero__title span:nth-child(4) b { --line-delay: 330ms; }

/* While the declaration is resolving, the glyph spans must not inherit the
   line reveal, or a glyph would slide in from below every time it returns. */
.hero__title .f21-g {
  transform: none;
}

.hero__title em {
  font-style: normal;
}

.hero__rule {
  height: 2px;
  background: var(--f21-red);
  margin-top: clamp(18px, 2.4vw, 30px);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 900ms var(--ease-line) 620ms;
}

.is-lit .hero__rule {
  transform: scaleX(1);
}

.hero__copy {
  display: flex;
  flex-direction: column;
  gap: var(--stack-md);
  align-items: flex-start;
}

.hero__copy .lead {
  font-size: var(--t-deck);
  line-height: 1.42;
  max-width: 30ch;
}

.hero__status {
  position: relative;
  z-index: 2;
  border-top: 1px solid var(--ink-line);
}

.code-line {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 721px) {
  .code-line {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* --- The hero on a phone, where the viewport is shorter than it claims ------
   MEASURED ON THE LIVE SITE, not guessed. At 393x734 — an iPhone 15 with
   Safari's toolbar showing, which is what 100svh actually resolves to there —
   the hero came out 772px tall and the last row of the code line ended 38px
   BELOW the fold. "05 STEWARDSHIP" was cut in half by the browser chrome, and
   the row above it was clipped at its baseline. min-height does not prevent
   that: the content simply wanted more room than the viewport had, and the
   hero grew.

   Two steps, both scoped to short viewports so nothing on a tall phone or a
   desktop moves at all.

     under 820px tall  the top padding and the code line's own padding come in,
                       and the hero gains a bottom padding that clears the home
                       indicator. Enough on its own for the 15 and the Pro Max.
     under 700px tall  the SE class, where 704px of content was being asked
                       into 629px. The gap between the head and the copy and
                       the headline's ceiling both come down.

   Verified at three sizes, last row of the code line against the fold:

     393x734   38px below  ->  10px clear
     430x814    0px clear  ->  10px clear
     375x629  127px below  ->   6px clear
   ------------------------------------------------------------------------- */

@media (max-width: 767px) and (max-height: 820px) {
  .hero {
    padding-top: clamp(56px, 7vh, 88px);
    padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
  }
  .code-line__item {
    padding-top: 9px;
    padding-bottom: 8px;
  }
}

@media (max-width: 767px) and (max-height: 700px) {
  .hero { padding-top: 38px; }
  .hero__body { row-gap: 12px; }
  .hero__title { font-size: clamp(28px, 7.6vw, 40px); }
}

.code-line__item {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 13px 12px 12px 0;
  border-bottom: 1px solid var(--ink-line-soft);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 9.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--paper-dim);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 500ms var(--ease-out), transform 500ms var(--ease-out),
    color var(--dur-fast) var(--ease-out);
  transition-delay: var(--code-delay, 0ms);
}

.is-lit .code-line__item,
.no-js .code-line__item {
  opacity: 1;
  transform: none;
}

.code-line li:nth-child(1) .code-line__item { --code-delay: 700ms; }
.code-line li:nth-child(2) .code-line__item { --code-delay: 780ms; }
.code-line li:nth-child(3) .code-line__item { --code-delay: 860ms; }
.code-line li:nth-child(4) .code-line__item { --code-delay: 940ms; }
.code-line li:nth-child(5) .code-line__item { --code-delay: 1020ms; }

@media (prefers-reduced-motion: reduce) {
  .hero__title b,
  .code-line__item {
    transform: none;
    opacity: 1;
  }

  .hero__rule {
    transform: scaleX(1);
  }
}

@media (min-width: 721px) {
  .code-line__item {
    font-size: var(--t-micro);
    border-bottom: 0;
    padding: 16px 12px 15px;
    border-left: 1px solid var(--ink-line-soft);
  }

  .code-line__item:first-child {
    padding-left: 0;
    border-left: 0;
  }
}

.code-line__item b {
  color: var(--f21-red-hi);
  font-weight: 700;
}

.code-line__item:hover,
.code-line__item:focus-visible {
  color: var(--paper);
}

.hero__cue {
  display: none;
}

@media (min-width: 721px) {
  .hero__cue {
    position: absolute;
    right: var(--margin);
    bottom: calc(100% + 22px);
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: var(--font-text);
    font-size: 9.5px;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--paper-faint);
  }

  .hero__cue::after {
    content: '';
    width: 1px;
    height: 26px;
    background: linear-gradient(180deg, var(--paper-faint), transparent);
  }
}

/* --- 02 THE HOMEFRONT -------------------------------------------------------
   The hinge of the page. Full bleed, the film graded well down so the
   declaration carries, and the copy in one cluster directly under the rule. */

.hinge {
  position: relative;
  display: grid;
  align-items: end;
  min-height: min(86svh, 780px);
  overflow: hidden;
  padding-block: clamp(80px, 15vh, 168px) clamp(44px, 8vh, 92px);
  border-bottom: 1px solid var(--ink-line);
}

.hinge__field {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--ink-deep) url('../video/f21-hero-chainsaw-poster.jpg') center / cover no-repeat;
}

.hinge__field::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(12, 15, 15, 0.94), rgba(12, 15, 15, 0.5) 34%, rgba(12, 15, 15, 0.95)),
    linear-gradient(84deg, rgba(12, 15, 15, 0.9) 4%, rgba(12, 15, 15, 0.4) 58%, rgba(12, 15, 15, 0.7));
}

.hinge__film {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 56% 44%;
  filter: grayscale(1) contrast(1.05) brightness(0.52);
}

.hinge__inner {
  position: relative;
  z-index: 2;
  width: 100%;
}

.hinge__title span {
  display: block;
}

.hinge__title em {
  font-style: normal;
  color: var(--f21-red);
}

/* The rule beneath the hinge headline is now the red line (sequence.css,
   redline.js): it runs from the headline to the paragraph on the right. */

.hinge__copy {
  margin-top: var(--cluster-gap);
  width: 100%;
}

.hinge__copy .body {
  margin-top: var(--stack-md);
}

@media (min-width: 1024px) {
  /* The deck under the headline; the qualifying paragraph a column further
     right, where the red line carries the claim to it. */
  .hinge__copy {
    display: grid;
    grid-template-columns: repeat(8, minmax(0, 1fr));
    column-gap: var(--gutter);
    align-items: start;
  }

  .hinge__copy .deck {
    grid-column: 1 / span 4;
  }

  .hinge__copy .body {
    grid-column: 5 / span 4;
    margin-top: 0;
    max-width: 52ch;
  }

  /* The disclosure continues the paragraph it sits under, so it lives in that
     paragraph's column and takes that paragraph's measure. Auto-placed, the
     <details> landed in column 1 as a one-track item, and the paragraph it
     revealed wrapped inside the width of its own label. */
  .hinge__copy .disclose {
    grid-column: 5 / span 4;
    max-width: 52ch;
  }
}

/* --- 02.1 THE GROUND --------------------------------------------------------
   Portrait against argument, sharing a top edge.

   8 September: the plate here was one landscape photograph across five
   columns. It is the twenty frame carousel now, and the frames are 9:16 at
   every width, so the proportions are the other way round — three columns of
   portrait against four of argument.

   Five columns of a 9:16 frame stood 1,580px tall on a desktop, with the
   argument floating in the top fifth of a screen of picture; and at that size
   the registration, tuned to read as two rendered pixels on a phone, rendered
   as five. At three columns the plate is about 430px wide, which puts the
   separation back at 2.4 rendered pixels and the composition back on the
   grid. */

.ground {
  padding-top: var(--movement-pad);
}

/* ONE MODULE, 8 September, second pass.
   Portrait at three columns; adjacent to it — column four, not column five —
   the title, the argument and the six grounds in one column. The six were a
   separate full-width list under the grid, which left the plate standing
   beside a paragraph and a screen of nothing; and the copy started a column
   away from the plate, so on a wide display the two read as unrelated
   objects. Together the title, body and six rows stand about as tall as the
   plate, which is what makes it one composition rather than a picture with
   some text near it. */
.ground__grid {
  row-gap: var(--stack-lg);
  align-items: start;
}

.ground__plate {
  margin: 0;
}

/* A 9:16 plate at full width on a tablet is 1,230px of picture with the
   argument stranded under it, and the registration, tuned for two rendered
   pixels, renders at four. From the desktop up the three columns size it. */
@media (min-width: 640px) and (max-width: 1023px) {
  .ground__plate { max-width: 460px; }
}

.ground__copy .eyebrow {
  margin-bottom: var(--stack-md);
}

.ground__title {
  font-size: clamp(30px, 3.3vw, 54px);
}

/* The six grounds inside the copy column: tighter than the old full-width
   list, the indent step smaller so the last row does not walk out of the
   column, and the note measure set to the column rather than to 46ch. */
.ranks--ground {
  margin-top: clamp(28px, 4vh, 48px);
}

.ranks--ground .rank {
  padding: clamp(11px, 1.3vw, 16px) 0;
  margin-left: calc(var(--indent, 0) * clamp(3px, 0.5vw, 10px));
}

.ranks--ground .rank__name {
  font-size: clamp(18px, 1.5vw + 6px, 26px);
}

.ranks--ground .rank__note {
  max-width: none;
}

@media (min-width: 1024px) {
  /* The copy column starts on the plate's top edge: one module, two
     materials. */
  .ground__copy {
    padding-top: 2px;
  }

  /* At the desktop the plate takes its three columns at whatever width they
     are — about 430px at 1440, about 560px at 1920 — and the column beside it
     is sized to stand as tall. */
  .ground__plate { max-width: none; }
}

@media (min-width: 1600px) {
  .ground__title { font-size: clamp(54px, 3vw, 64px); }
  .ranks--ground .rank { padding: 18px 0; }
}

.pull.gc-1-6 {
  margin-top: var(--stack-xl);
}

@media (min-width: 1024px) {
  .ground .pull {
    margin-left: calc((100% + var(--gutter)) / var(--cols) * 2);
    max-width: 36ch;
  }
}

.ranks {
  border-top: 1px solid var(--ink-line);
  margin-top: var(--stack-xl);
}

.rank {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: clamp(14px, 2vw, 28px);
  row-gap: 4px;
  align-items: baseline;
  padding: clamp(14px, 1.8vw, 22px) 0;
  border-bottom: 1px solid var(--ink-line);
  margin-left: calc(var(--indent, 0) * clamp(5px, 1vw, 20px));
  position: relative;
}

.rank:nth-child(1) { --indent: 0; }
.rank:nth-child(2) { --indent: 1; }
.rank:nth-child(3) { --indent: 2; }
.rank:nth-child(4) { --indent: 3; }
.rank:nth-child(5) { --indent: 4; }
.rank:nth-child(6) { --indent: 5; }

.rank::before {
  content: '';
  position: absolute;
  left: 0;
  bottom: -1px;
  height: 1px;
  width: 100%;
  background: var(--f21-red);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 900ms var(--ease-line);
  transition-delay: var(--reveal-delay, 0ms);
}

.rank.is-in::before {
  transform: scaleX(calc(0.1 + var(--indent) * 0.18));
}

.rank__no {
  font-family: var(--font-text);
  font-size: var(--t-micro);
  letter-spacing: 0.18em;
  color: var(--f21-red-hi);
  font-weight: 700;
}

.rank__name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(19px, 2.6vw, 30px);
  text-transform: uppercase;
  letter-spacing: -0.005em;
  line-height: 1;
  white-space: nowrap;
}

.rank__note {
  grid-column: 2;
  font-size: var(--t-body);
  color: var(--paper-dim);
  max-width: 46ch;
}

@media (min-width: 721px) {
  .rank {
    /* Quantico is a wide face: let the name column take exactly the width it
       needs so a long rank never runs into its note. */
    grid-template-columns: 4ch max-content minmax(0, 1fr);
    align-items: baseline;
  }

  .rank__note {
    grid-column: 3;
    text-align: left;
  }
}

@media (min-width: 1024px) {
  .rank {
    grid-template-columns: 5ch max-content minmax(0, 1fr);
  }
}

/* --- 03 THE CODE ------------------------------------------------------------ */

/* CORRECTION 01, 7 September. One composition instead of two screens.

   The head is a single row: the movement's title at four columns and the
   argument for the code at four beside it. Under it the stage puts the
   formation, the open discipline and its photograph side by side, so a man
   can see the whole code and the one he has entered at the same time, which
   is the thing the section is for.

   The proportions began at the brief's 22 / 33 / 45 and were refined against
   the longest of the five entries, Self-Control, at 1366 by 768: the copy
   column needed more than a third to keep its paragraph at a comfortable
   measure without shrinking the type, and the formation gives it up because a
   compact cluster reads at any size. */

.code {
  overflow: hidden;
}

.code__head {
  align-items: end;
  row-gap: var(--stack-md);
}

.code__title {
  /* Held below the movement scale: this is a title over a composition, not a
     declaration filling a screen. */
  font-size: clamp(28px, 3.4vw, 52px);
}

.code__deck {
  max-width: 52ch;
}

.code__stage {
  margin-top: var(--stack-lg);
}

@media (min-width: 1024px) {
  /* The stage has to settle whole inside 1366 by 768 under a 73 px
     navigation, which leaves 695 px. The section's own padding, the head row
     and the stage are budgeted against that, and the budget is what these
     numbers are: the padding comes down, the title is held to the scale of a
     title, and the discipline's internal spacing is set for a column rather
     than for a page. The body copy is not touched: it stays at 18.5 px. */
  .code {
    padding-top: clamp(36px, 3.1vw, 52px);
    padding-bottom: clamp(36px, 3.1vw, 52px);
  }

  .code__stage {
    display: grid;
    grid-template-columns:
      minmax(196px, 21fr)
      minmax(0, 38fr)
      minmax(0, 41fr);
    column-gap: var(--gutter);
    align-items: center;
    margin-top: var(--stack-md);
  }

  /* The formation is the first column of the stage, and it is vertically
     centred against the discipline beside it rather than sitting on top of
     the page's flow. */
  .code .phalanx {
    grid-column: 1;
    grid-row: 1;
    margin-top: 0;
  }

  /* The discipline occupies the other two columns. The panel's own grid is
     replaced here: inside the stage it is text then plate, at the stage's
     proportions, not a fresh eight column grid. */
  .code .discipline {
    grid-column: 2 / 4;
    grid-row: 1;
    margin-top: 0;
    min-width: 0;
  }

  .code .discipline__panel.grid {
    grid-template-columns: minmax(0, 34fr) minmax(0, 42fr);
    column-gap: var(--gutter);
    align-items: center;
  }

  .code .discipline__text.gc-1-3,
  .code .discipline__plate.gc-4-5 {
    grid-column: auto;
  }

  /* The discipline's internal rhythm, set for this column. Page level stacks
     between six short elements were most of the section's height; this is the
     same order at a cluster's spacing. Nothing is hidden, nothing scrolls
     inside itself, and no paragraph is cut. */
  .code .discipline__name { margin-top: 6px; }
  .code .discipline__imperative { margin-top: clamp(10px, 1vw, 16px); }
  .code .discipline__body { margin-top: clamp(12px, 1.1vw, 18px); }
  .code .discipline__cite { margin-top: clamp(14px, 1.3vw, 20px); }
  .code .discipline__close { margin-top: clamp(16px, 1.5vw, 24px); }

  .code .discipline__imperative { max-width: 30ch; }

  /* ------------------------------------------------------------------------
     THE MANIFESTO'S STAGE, 9 September.

     The same component at the same proportion, with no photograph beside the
     argument: the formation keeps its 21 units so the lockup is identical to
     the homepage's, and the discipline takes both remaining columns as one.
     Its paragraph is then held to a reading measure rather than let out to
     the full width of the stage, because the MANifesto is a page a man has
     just read and a ninety character line would undo that.
     ------------------------------------------------------------------------ */
  .code__stage--manifesto {
    grid-template-columns:
      minmax(196px, 21fr)
      minmax(0, 79fr);
  }

  .code__stage--manifesto .discipline { grid-column: 2; }

  .code__stage--manifesto .discipline__panel.grid {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
  }

  .code__stage--manifesto .discipline__text.gc-1-6 { grid-column: auto; }

  .code__stage--manifesto .discipline__body { max-width: 54ch; }
  .code__stage--manifesto .discipline__imperative { max-width: 38ch; }
}

/* --- The code on a phone -------------------------------------------------------
   Designed at 390 as its own composition, not as the desktop row narrowed.
   Three desktop columns cannot become three phone columns, so they become a
   clean stack in reading order: the formation, then the photograph of the
   discipline that is open, then the discipline itself.

   The formation keeps all five names. A cluster small enough to sit beside a
   photograph on a 390 px screen would have about fifty pixels a shield, which
   is not enough for a label and not enough for a comfortable target, so the
   formation takes the width and the photograph goes under it. That is the
   stacked option the brief allows, chosen over a row that only just fits.

   Every shield keeps a 44 px target in both directions and the gaps in the
   formation keep neighbouring targets apart. Nothing is shrunk to make a
   screen: the body copy, the scripture and the whole discipline are here at
   their normal size, and on a short phone the page simply scrolls. */

@media (max-width: 1023px) {
  .code__stage {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    row-gap: clamp(14px, 3vw, 22px);
    margin-top: clamp(16px, 3.5vw, 26px);
    /* The formation keeps its own height. Stretched into the row it would
       centre itself in the spare space and leave a hole under the labels. */
    align-items: start;
  }

  .code .phalanx {
    /* Held in from the edges so the outer shields are not against the gutter
       and the cluster reads as one object. */
    width: min(100%, 340px);
    justify-self: center;
    margin-top: 0;
  }

  /* Photograph above the panel: the plate is pulled to the top of the
     discipline, the argument follows it. */
  .code .discipline__panel.grid {
    display: flex;
    flex-direction: column;
    row-gap: clamp(12px, 2.6vw, 18px);
  }

  .code .discipline__plate.gc-4-5 { order: -1; }

  /* A shallow crop. The portrait source is composed for a full bleed plate
     and would take two thirds of the screen here; the frame keeps the upper
     middle of it, which is where the faces and the hands are. */
  .code .discipline__plate .editorial__frame {
    aspect-ratio: 21 / 9;
    overflow: hidden;
  }

  /* The landscape composition, cropped to a band. The discipline plates no
     longer carry a portrait source: a 9:16 frame cropped to a shallow band
     lands in the background of the picture, and what has to survive the crop
     is the faces, the hands and the work. */
  .code .discipline__plate img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 42%;
  }

  /* The index sits on the name's line rather than above it. Same two pieces
     of information, one row instead of two, which is a row the composition
     needs more than the numeral needs its own line. */
  .code .discipline__text {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: baseline;
    column-gap: 12px;
  }

  .code .discipline__index {
    font-size: 20px;
    grid-column: 1;
    grid-row: 1;
  }

  .code .discipline__name {
    margin-top: 0;
    grid-column: 2;
    grid-row: 1;
  }

  .code .discipline__imperative,
  .code .discipline__body,
  .code .discipline__cite,
  .code .discipline__close {
    grid-column: 1 / -1;
  }
  .code .discipline__imperative { margin-top: 10px; }
  .code .discipline__body { margin-top: 12px; }
  .code .discipline__cite { margin-top: 14px; }
  .code .discipline__close { margin-top: 16px; }
}

@media (max-width: 767px) {
  .code {
    padding-top: clamp(32px, 7vw, 48px);
    padding-bottom: clamp(32px, 7vw, 48px);
  }

  .code__head { row-gap: var(--stack-sm); }

  .phalanx {
    --ph-shield-w: 52px;
    --ph-lead-w: 62px;
  }
}

/* --- 04 THE CODE IN PRACTICE, THE SLIDESHOW --------------------------------------
   Twenty scenes, four for each discipline, at the size of a plate. The stage is
   a true sixteen by nine on a desktop, about eighty six percent of the shell,
   centred; below the breakpoint it is the portrait composition, full width.
   Every slide is stacked in the same grid cell and crossfaded, so the stage
   never changes height and nothing on the page moves while it advances. */

.slideshow-movement {
  background: var(--ink-deep);
}

.slideshow {
  position: relative;
  margin-top: var(--stack-lg);
  width: min(100%, 86%);
  margin-inline: auto;
}

@media (max-width: 767px) {
  .slideshow { width: 100%; }
}

.slideshow:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 6px;
}

.slideshow__stage {
  display: grid;
  position: relative;
  aspect-ratio: 1672 / 941;
  overflow: hidden;
  background: var(--ink-deep);
}

@media (max-width: 767px) {
  .slideshow__stage { aspect-ratio: 941 / 1672; }
}

.slideshow__slide {
  grid-area: 1 / 1;
  margin: 0;
  position: relative;
  opacity: 0;
  transition: opacity 720ms var(--ease-out);
  pointer-events: none;
}

.slideshow__slide.is-on {
  opacity: 1;
  pointer-events: auto;
}

.slideshow__frame {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.slideshow__frame picture,
.slideshow__frame img {
  display: block;
  width: 100%;
  height: 100%;
}

.slideshow__slide img {
  object-fit: cover;
}

/* The gradient is local to the overlay rather than a wash over the whole
   picture, so the photograph keeps its full range everywhere the type is not.
   The discipline sits lower left, the declaration lower right, both inside
   the safe area on every crop. */
.slideshow__overlay {
  position: absolute;
  inset: auto 0 0 0;
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: var(--stack-md);
  padding: clamp(64px, 11vw, 140px) clamp(18px, 3vw, 44px) clamp(16px, 2.6vw, 34px);
  background: linear-gradient(to top, rgba(6, 8, 8, 0.88), rgba(6, 8, 8, 0.5) 44%, transparent);
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
}

.slideshow__discipline {
  font-size: clamp(10px, 1.1vw, 13px);
  letter-spacing: 0.24em;
  color: var(--f21-red-hi);
  flex: none;
  padding-bottom: 0.3em;
}

.slideshow__declaration {
  font-size: clamp(16px, 2.2vw, 34px);
  letter-spacing: 0;
  line-height: 1.06;
  text-align: right;
  color: var(--paper);
  text-wrap: balance;
  max-width: 22ch;
}

@media (max-width: 620px) {
  .slideshow__overlay {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
    padding-bottom: 22px;
  }
  .slideshow__declaration { text-align: left; font-size: clamp(19px, 5.6vw, 26px); }
}

.slideshow__controls {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: var(--stack-sm);
}

/* 44px minimum, because these are the one part of the module a thumb has to
   find on a phone. */
.slideshow__btn {
  min-width: 44px;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--ink-line);
  background: transparent;
  color: var(--paper-dim);
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}

.slideshow__btn:hover,
.slideshow__btn:focus-visible {
  color: var(--paper);
  border-color: var(--f21-red);
}

.slideshow__count {
  margin-left: auto;
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.2em;
  color: var(--paper-faint);
}

/* Reduced motion holds one scene. The controls still work, so the reader can
   move through the whole set deliberately; it simply never moves on its own. */
@media (prefers-reduced-motion: reduce) {
  .slideshow__slide { transition: none; }
}

/* --- 05 THE FILM -------------------------------------------------------------
   Full width, sixteen by nine, sound off until asked. The film has no
   dialogue: its declarations are typography inside the picture, so nothing in
   it depends on hearing. The transcript module and the web caption track that
   duplicated that typography were retired on 8 September. */

.film {
  background: var(--ink-deep);
  padding-block: var(--movement-pad);
}

.cluster--film {
  margin-bottom: var(--stack-lg);
}

.film__title {
  font-size: clamp(38px, 6.4vw, 108px);
}

.film__stage {
  margin: 0;
}

/* The plate: the band and the frame share one width. The film is sixteen by
   nine, so the frame is too: no pillarboxing, and no crop of a composition
   that was typeset to the edge. It runs full bleed until that would push it
   past the viewport, then it centres. */
.film__plate {
  width: min(100%, calc(84svh * 16 / 9));
  margin-inline: auto;
}

.film__frame {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
  border-bottom: 1px solid var(--ink-line);
  overflow: hidden;
  max-height: 84svh;
}

.film__video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: #000;
}

/* --- 06 THE FIELD MANUAL ----------------------------------------------------
   The offer section lives in home.css under the "offer" namespace since
   8 September 2026: .manual is the request dialog (manual-modal.css). */

/* --- 07 TWENTY ONE DAYS ------------------------------------------------------
   The calendar and the Wall of Truth live in wall.css. */

/* --- 08 BROTHERHOOD --------------------------------------------------------- */

.brotherhood {
  background: var(--ink-deep);
}

.rank-of-lines {
  display: grid;
  grid-template-columns: repeat(24, minmax(0, 1fr));
  align-items: end;
  height: clamp(48px, 7vw, 96px);
  gap: 0;
  margin-bottom: var(--stack-lg);
}

.rank-of-lines i {
  display: block;
  width: 1px;
  height: 100%;
  background: var(--ink-line);
  transform: scaleY(0.18);
  transform-origin: 50% 100%;
  transition: transform 620ms var(--ease-line), background-color 620ms linear;
  transition-delay: var(--d, 0ms);
}

/* A rank of men, not a barcode. Uneven heights, and red on a few. */
.rank-of-lines.is-in i {
  transform: scaleY(var(--sy, 1));
  background: var(--paper-faint);
}

.rank-of-lines i:nth-child(8n + 1) { --sy: 0.58; }
.rank-of-lines i:nth-child(8n + 2) { --sy: 0.84; }
.rank-of-lines i:nth-child(8n + 3) { --sy: 0.46; }
.rank-of-lines i:nth-child(8n + 4) { --sy: 1; }
.rank-of-lines i:nth-child(8n + 5) { --sy: 0.66; }
.rank-of-lines i:nth-child(8n + 6) { --sy: 0.9; }
.rank-of-lines i:nth-child(8n + 7) { --sy: 0.52; }
.rank-of-lines i:nth-child(8n + 8) { --sy: 0.76; }

.rank-of-lines.is-in i:nth-child(6n + 4) {
  background: var(--f21-red);
}

.brotherhood__head {
  row-gap: var(--stack-lg);
  align-items: start;
  margin-bottom: var(--stack-lg);
}

/* The aside hangs below and to the right of the headline, in the second row,
   where the red line has to travel to reach it. */
@media (min-width: 1024px) {
  .brotherhood__aside {
    grid-row: 2;
  }
  .brotherhood__head {
    row-gap: var(--stack-lg);
  }
}

.brotherhood__aside .body {
  margin-top: var(--stack-md);
}

.brotherhood__wide {
  margin: 0;
}

/* The sandbag line runs edge to edge: the one full bleed interruption on the
   page, at the point where the story turns from one man to many. */
@media (min-width: 1024px) {
  .brotherhood .brotherhood__wide {
    margin-inline: calc(-1 * var(--margin));
  }
}

.brotherhood__band {
  margin-top: var(--stack-xl);
  row-gap: var(--stack-lg);
  align-items: start;
}

/* Eyebrow to heading, at the tight end of the scale. LAYOUT_RATIONALE asks for
   an obvious parent: the kicker and the headline have to read as one cluster,
   not as two blocks that happen to be near each other. */
.band-head {
  font-size: clamp(30px, 3.3vw, 54px);
}

/* The Red Band panel, on the page's own ground. CORRECTION 08: what stood
   here was the light band component stretched over a whole column, which
   read as a cream card interrupting the movement. There is no card now. The
   column is the page: the photograph beside it, the promise in light Poppins
   at full strength on charcoal, one rule, then the terms and the honest
   state. The heading takes the shared printed material at its own size tier,
   with the light inside the ink and nothing softening its silhouette. */
.band-panel {
  align-self: center;
}

.band-panel__promise {
  color: var(--paper);
  max-width: 46ch;
}

@media (max-width: 767px) {
  /* Photograph, headline, promise, price, state. The photograph leads because
     the object is the argument; nothing here is boxed and nothing is padded
     out to fill a panel that no longer exists. */
  .brotherhood__band {
    row-gap: var(--stack-md);
  }

  .band-panel {
    align-self: start;
  }

  .band-order {
    margin-top: var(--stack-md);
  }
}

/* The Red Band order block. A ruled panel rather than a card: two hairlines,
   sharp corners, no fill and no shadow, so it reads as part of the editorial
   column instead of a shop widget dropped into it. */

.band-order {
  margin-top: var(--stack-lg);
  padding: var(--stack-md) 0 0;
  border-top: 1px solid var(--ink-line);
  width: 100%;
}

.band-order__price {
  margin-top: var(--stack-sm);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(19px, 2.1vw, 25px);
  line-height: 1.15;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--paper);
  text-wrap: balance;
}

.band-order__mission {
  margin-top: var(--stack-sm);
  color: var(--paper-dim);
  max-width: 46ch;
}

.band-order__act {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px var(--stack-md);
  margin-top: var(--stack-md);
}

/* Inert, and it has to look inert without looking broken. Held at the same
   weight as a live primary action so the composition can be judged, then
   pulled back with opacity and a default cursor. It is still focusable, so it
   still needs a visible focus ring. */
.band-order__cta[aria-disabled='true'] {
  opacity: 0.55;
  cursor: default;
}

.band-order__cta[aria-disabled='true']:hover {
  --btn-fg: var(--ink);
  --btn-bg: var(--paper);
  --btn-bd: var(--paper);
}

.band-order__cta[aria-disabled='true']:hover::after {
  width: 14px;
}

.band-order__state {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--font-display);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--f21-red);
}

.band-order__dot {
  width: 6px;
  height: 6px;
  flex: none;
  background: var(--f21-red);
}

/* --- 09 FIELD REPORTS -------------------------------------------------------- */

.cluster--reports {
  margin-bottom: var(--stack-lg);
}

.reports__table {
  margin: 0;
}

/* Near full width: the plate takes the shell, less a column on the right, so
   it reads as the page's largest photograph without becoming a second hero. */
@media (min-width: 1024px) {
  .reports__table {
    width: calc((100% - var(--gutter) * 7) / 8 * 7 + var(--gutter) * 6);
  }
}

/* .reports__grid held the two-up row removed on 7 September (correction 06).
   The rule goes with it: the movement now ends on its declaration. */

/* --- 10 THE MILLION MAN INITIATIVE ----------------------------------------------
   A full width declaration, then the argument at three to five, then the one
   action. There is deliberately no counter, no meter and no total, because
   none has been approved and a number invented here would be the one thing on
   the page that is not true. The note says so plainly. */

.million {
  padding-bottom: clamp(56px, 7vw, 104px);
}

.million__title {
  margin-top: var(--stack-md);
  font-size: clamp(40px, 7.4vw, 124px);
  max-width: 14ch;
}

.million__body {
  margin-top: var(--cluster-gap);
  row-gap: var(--stack-md);
  align-items: start;
  padding-top: var(--stack-md);
  border-top: 1px solid var(--ink-line);
  position: relative;
}

/* The line begins here and the closing declaration converges on it: a red
   length at the left of the rule, running out of the headline. */
.million__body::before {
  content: '';
  position: absolute;
  left: 0;
  top: -1px;
  width: clamp(88px, 12vw, 200px);
  height: 3px;
  background: var(--f21-red);
}

.million__note {
  font-size: var(--t-body);
  line-height: 1.55;
  color: var(--paper-faint);
  max-width: 34ch;
  padding-left: var(--stack-md);
  border-left: 1px solid var(--ink-line);
}

.million__body .deck {
  max-width: 46ch;
}

.million__act {
  margin-top: var(--stack-lg);
}

/* --- 11 THE DECLARATION ------------------------------------------------------ */

.declaration {
  position: relative;
  overflow: hidden;
  text-align: left;
  padding-block: clamp(96px, 14vh, 200px) clamp(110px, 16vh, 220px);
}

/* Ten runs straight into eleven. The hairline the movement rule would draw
   here is dropped, so the two read as one closing passage. */
.million + .declaration::before {
  display: none;
}

.declaration__converge {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  opacity: 0.55;
  pointer-events: none;
}

.declaration__converge line {
  stroke: var(--ink-line);
  stroke-width: 1;
  stroke-dasharray: 1200;
  stroke-dashoffset: 1200;
  transition: stroke-dashoffset 1400ms var(--ease-line);
  transition-delay: var(--d, 0ms);
}

.declaration__converge.is-in line {
  stroke-dashoffset: 0;
}

/* 9 September: the sixth line was the centre of the fan — dead vertical, and
   the only red one — so it read as a permanent red rule down the middle of
   the closing section rather than as part of the converging geometry. Both
   the line and this rule are gone. The fan is the ten that remain, in the
   hairline grey the rest of the site's structure uses; the red in this
   section is the declaration and the ambient static, which is where a signal
   belongs. */

.declaration__inner {
  position: relative;
  z-index: 1;
}

.declaration__title {
  margin-top: var(--stack-md);
  font-size: clamp(38px, 8.2vw, 132px);
}

.declaration__title em {
  font-style: normal;
  color: var(--f21-red-hi);
}

.declaration__foot {
  display: grid;
  gap: var(--stack-lg);
  align-items: end;
  margin-top: var(--cluster-gap);
  padding-top: var(--stack-md);
  border-top: 1px solid var(--ink-line);
}

@media (min-width: 1024px) {
  .declaration__foot {
    grid-template-columns: minmax(0, 5fr) minmax(0, 3fr);
    column-gap: var(--gutter);
  }
  .declaration__foot .btn { justify-self: start; }
}

/* ==========================================================================
   THE CODE, COMPACT ON A PHONE. 8 September 2026.

   The brief: a tight explanation and the COMPLETE five-shield diagram
   together in the usable viewport under the header, with all five labels
   legible, and the discipline photographs kept for the desktop.

   What this does NOT do is force it into a fixed height. On a short screen,
   or with enlarged text, a locked height either clips the formation or
   shrinks the labels until the code cannot be read — and an unreadable code
   is a worse outcome than a scroll. So the space is taken back from padding
   and from copy that is elaboration rather than the idea, and beyond that the
   section is allowed to grow and the page is allowed to scroll.
   ========================================================================== */

@media (max-width: 767px) {
  /* The photographs go. They are the desktop's, and on a phone they sit
     between the reader and the diagram the section exists to show. Still in
     the markup and still lazy, so they are not fetched while hidden. */
  .code .discipline__plate { display: none; }

  /* Elaboration, not the idea. See the note in index.html. */
  .code__deck-more { display: none; }

  .code .code__head {
    row-gap: 8px;
    margin-bottom: clamp(10px, 2.5vw, 16px);
  }

  .code__stage { row-gap: clamp(10px, 2.4vw, 16px); margin-top: clamp(10px, 2.4vw, 16px); }

  /* The formation is the point of this screen, so it gets the width it needs
     to keep five labels readable rather than being held to a tidy square. */
  .code .phalanx { width: min(100%, 380px); }

  /* The discipline that opens under it is a summary here: name, imperative,
     citation. The full argument is a scroll away and is not removed. */
  .code .discipline__panel.grid { row-gap: 10px; }
}

/* A plate with no 9:16 companion yet.
   The portrait stage crops to the middle third, which for the Self-Control
   coaching plate would remove the four teammates kneeling around the mat and
   leave a man's hands on a bent-over boy. The witnesses are what make it a
   practice rather than something else, so this plate is contained on the wall
   ground instead of cropped. Scoped to the one frame that carries
   data-uncropped; it goes when the portrait arrives. */
@media (max-width: 767px) {
  .slideshow__frame[data-uncropped] {
    display: grid;
    place-items: center;
    background: var(--ink);
  }
  .slideshow__frame[data-uncropped] img {
    object-fit: contain;
    height: auto;
    max-height: 100%;
  }
}

/* --- The passage that closes the code --------------------------------------
   Page twelve of the manual, at the end of The Code and before The Homefront.
   It is the turn inward: the formation has just been set out, and this is
   what it is for. It is inside the code's own narrative rather than a
   movement of its own, so it carries no eyebrow, no index and no control.

   WHAT WENT WRONG THE FIRST TIME
   The figure carried max-width: 17ch. A ch is the width of the zero in the
   element's OWN font, and the figure's font is the 16px body — so the
   passage was held to 17 body zeros, about 150px, and the display type
   inside it wrapped one word to a line and clipped at the right edge. The
   measure now belongs to the element whose type it is measuring, and the
   line breaks are authored phrases rather than whatever a width produces. */

.turn {
  padding-block: clamp(72px, 13vh, 170px);
  border-top: 1px solid var(--ink-line);
  background: var(--ink-deep);
}

.turn__quote {
  margin: 0;
  width: 100%;
}

.turn__quote blockquote { margin: 0; }

.turn__text {
  display: block;
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-style: italic;
  /* 24px at 320, 27px at 390, 44px at 768, 62px at 1440, 74px at 1920. */
  font-size: clamp(24px, 3.4vw + 13px, 78px);
  line-height: 1.12;
  letter-spacing: -0.012em;
}

/* From the tablet up the phrases are the lines. Below it the <br>s are not
   drawn and the phone wraps by width; the two heart phrases stay whole. */
.turn__br { display: none; }

.turn__ph { white-space: nowrap; }

@media (min-width: 768px) {
  .turn__br { display: inline; }
  .turn__text { line-height: 1.08; }
}

/* On a phone the passage takes the whole shell. A taller section is the
   right price for a readable one. */
@media (max-width: 767px) {
  .turn { padding-block: clamp(56px, 10vh, 96px); }
  .turn__text { line-height: 1.14; }
}

.turn__source {
  margin-top: clamp(28px, 5vh, 64px);
  color: var(--paper-faint);
  font-style: normal;
}

.turn__source b {
  display: block;
  color: var(--paper-dim);
  font-weight: 400;
}

/* ==========================================================================
   THE RED STATIC (hairline.js), 8 September, evening.

   A one pixel red vertical line that flickers into a region for a moment,
   slips sideways, and is gone. The field is laid behind the reading layer of
   every region that carries data-hairline, is inert to the pointer, and is
   empty whenever the script has nothing to show.

   It has to hold against both the bright and the dark parts of a film, so it
   carries a small dark drop of its own: on a blown highlight a bare red line
   at one pixel loses its edge, and on the near-black ground the drop is
   invisible.
   ========================================================================== */

[data-hairline] { position: relative; }

.hairlines {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  contain: layout paint;
}

/* The hero's film sits under it and the hero's body over it. */
.hero .hairlines { z-index: 1; }

/* In Begin the field is appended after the converging lines and before the
   reading layer, which carries its own z-index of 1. */
.declaration .hairlines { z-index: 0; }

/* A region whose content is in normal flow needs its reading layer lifted
   over the field, or the field would sit on top of the copy. Named one by
   one rather than as a descendant rule: the hero's own children are
   absolutely positioned, and forcing position on those would move them. */
.homefront > .hinge,
.homefront > .shell,
.action > .shell,
.million > .shell,
.manifesto-hero > .shell,
.calendar-movement > .shell,
.supply-hero > .shell,
.manual-preview > .shell { position: relative; z-index: 1; }

.hairline {
  position: absolute;
  width: 1px;
  opacity: 0;
  pointer-events: none;
  will-change: opacity, transform;
  filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.45));
}

@media (prefers-reduced-motion: reduce) {
  .hairlines { display: none; }
}
