/**
 * Production page — "The Rack"
 *
 * Chosen from three candidate layouts on 2026-07-21. See
 * docs/briefs/2026-07-21-production-page.md for the decision and for the
 * placeholder copy still to be verified.
 *
 * Layout only. Colour, type, space, radius, and depth come from
 * tokens.css; components come from base.css. This page uses two base
 * components — .band-graphite for both faceplates and .inset-band for
 * the installations note — and adds nothing that needed promoting.
 *
 * The premise: graphite carries the page. Two seated bands do the
 * structural work — one holding the four disciplines, one holding the
 * three phases — and the paper between them exists to keep each band an
 * object rather than a dark section. The second band deliberately reuses
 * the first band's geometry, so a reader who has parsed the disciplines
 * reads the phases faster.
 *
 * The structural rule this page has to respect is DESIGN.md §2:
 * graphite is never a page background; it arrives as an object placed on
 * the page. Both bands are bounded on all four sides, carry the bevel on
 * their top edge and a contact shadow underneath, and have paper visible
 * above and below them. Crowding either one is what would turn a
 * two-material layout into a dark theme.
 */

/* =====================================================================
   1. SECTION RHYTHM
   The bands are the heaviest objects on the site, so the paper around
   them is given more room than it would otherwise need.
   ===================================================================== */

.rack-section {
  padding-block: var(--space-5xl);
}

.rack-open {
  padding-block: var(--space-5xl) var(--space-4xl);
}

.rack-bring {
  padding-block: var(--space-4xl) var(--space-5xl);
}

.rack-close {
  padding-block: var(--space-4xl) var(--space-6xl);
  background: var(--paper-100);
  border-top: 1px solid var(--paper-200);
}

@media (max-width: 767px) {
  .rack-section {
    padding-block: var(--space-4xl);
  }
}

.rack-eyebrow {
  margin: 0 0 var(--space-lg);
  color: var(--ink-muted);
}

.rack-head {
  max-width: 42rem;
  margin-bottom: var(--space-3xl);
}

.rack-lede {
  margin-top: var(--space-xl);
  color: var(--ink-muted);
}

.rack-text {
  margin: 0;
  max-width: var(--measure-prose);
  text-wrap: pretty;
}

/* =====================================================================
   2. OPENING
   The statement sits above the plate rather than beside it. Beside it,
   the plate could not clear the 75% proportion floor in base.css §8.1
   without a second crop: a 2:1 source in a 0.85fr column resolves to
   229px against 368px of type. Stacked at the full shell it runs
   1144x572 on the baked crop, and the largest photograph on the page is
   also the first one.
   ===================================================================== */

/* Capped so the statement still breaks over two lines at the full shell.
   Uncapped it runs to a single 1144px line at the 4.5rem display step,
   which is a banner rather than a statement. `text-wrap: balance` on
   .display splits the two lines evenly. */
.rack-display {
  max-width: 24ch;
}

.rack-open-copy {
  margin-bottom: var(--space-3xl);
}

@media (min-width: 768px) {
  .rack-open-copy {
    margin-bottom: var(--space-4xl);
  }
}

/* =====================================================================
   3. PLATES
   The frame, the radius, the caption, and the role widths are the
   .plate component in base.css §8.1. Only the two page-specific
   placements are set here.
   ===================================================================== */

/* The wide plate closes the event index, outside the shell on the wide
   one. Its source is baked 2.22:1 and nothing here re-crops it — the
   aspect-ratio that used to sit on this rule squeezed the frame to 2:1
   and then to 3:2 on a phone, which was a second editorial crop taken in
   a stylesheet rather than in scripts/bake-crops.py. */
.rack-cover-bleed {
  margin-top: var(--space-4xl);
}

/* No phone-width window here, deliberately. The rule that was removed
   took this frame to 3:2 below 767px to buy back height, and the crop
   that adds height is the one that removes the side walls — the exact
   surfaces the caption says the wash was carried onto. A 210px-tall
   photograph that supports its caption beats a 310px-tall one that
   contradicts it. If the height is wanted back, bake a phone-ratio
   sibling in scripts/bake-crops.py and pick it with a <source>. */

/* =====================================================================
   4. WHAT WE COVER — the quiet index
   Understated on purpose: the reader is one scroll from the heaviest
   object on the site, and two competing structures in a row would
   flatten both. Rules separate the rows; nothing here is a card.
   ===================================================================== */

.rack-shapes {
  display: grid;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--paper-200);
}

.rack-shape {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-sm);
  padding-block: var(--space-xl);
  border-bottom: 1px solid var(--paper-200);
}

.rack-shape-index {
  color: var(--ink-muted);
}

@media (min-width: 768px) {
  /* The numeral moves into its own column and the title and body share
     the second, so all five rows align on one axis regardless of how
     long a title runs. */
  .rack-shape {
    grid-template-columns: 64px minmax(0, 1fr);
    column-gap: var(--space-2xl);
    row-gap: var(--space-sm);
  }

  .rack-shape-index {
    grid-row: span 2;
    /* Optically aligns the numeral with the cap height of the serif
       title beside it; the sans sits higher in its box. */
    padding-top: 5px;
  }
}

@media (min-width: 1024px) {
  /* Three columns once there is room: the title moves out of the body's
     column so the row actually spans the rule above it. At two columns
     the 68ch body left the right half of every rule empty, which read as
     an unfinished table rather than a quiet one. */
  /* 19rem holds the longest title ("Conferences and all-hands") on one
     line at Title size; below that four of the five titles broke, and a
     column of two-line titles beside one-line bodies reads as an
     accident rather than a rhythm. */
  .rack-shape {
    grid-template-columns: 64px 19rem minmax(0, 1fr);
    column-gap: var(--space-2xl);
  }

  .rack-shape-index {
    grid-row: auto;
  }

  .rack-shape-title {
    align-self: start;
    text-wrap: balance;
  }
}

.rack-install {
  max-width: 44rem;
  margin-top: var(--space-3xl);
}

.rack-install-label {
  margin: 0 0 var(--space-sm);
  color: var(--ink-muted);
}

.rack-install .title {
  margin-bottom: var(--space-md);
}

.rack-install-link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: var(--space-sm);
  font-family: var(--font-sans);
  font-size: var(--type-ui-size);
}

/* =====================================================================
   5. THE BANDS
   base.css's .band-graphite provides the surface, the bevel, the contact
   shadow, and the bounding. Only the interior is styled here.
   ===================================================================== */

/* A rem cap, not a ch cap. `ch` resolves against THIS element's font —
   1rem Public Sans — not against the serif headline inside it, so a ch
   value here silently constrains the headline to roughly half its
   intended measure. */
.rack-band-head {
  max-width: 44rem;
  margin-bottom: var(--space-3xl);
}

.rack-band-eyebrow {
  margin: 0 0 var(--space-lg);
  color: var(--graphite-300);
}

.rack-band-headline {
  color: var(--paper-000);
}

.rack-band-lede {
  margin: var(--space-xl) 0 0;
  max-width: var(--measure-prose);
  color: var(--graphite-300);
  font-family: var(--font-serif);
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  text-wrap: pretty;
}

/* =====================================================================
   6. THE FOUR COLUMNS
   Divided by engraved rules rather than boxed into four panels. The
   divisions on a real faceplate are lines cut into it, not raised boxes
   bolted onto it, and four panels inside a panel would nest a card in a
   card, which the system prohibits outright.
   ===================================================================== */

.rack-columns {
  display: grid;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--graphite-700);
}

.rack-column {
  display: grid;
  gap: var(--space-sm);
  align-content: start;
  padding-block: var(--space-xl);
  border-bottom: 1px solid var(--graphite-700);
}

.rack-column:last-child {
  border-bottom: 0;
}

.rack-column-name {
  color: var(--paper-000);
}

.rack-column-text {
  margin: 0;
  max-width: var(--measure-prose);
  color: var(--graphite-300);
  font-family: var(--font-serif);
  font-size: var(--type-body-size);
  line-height: var(--type-body-leading);
  text-wrap: pretty;
}

/* Signal Bright, not Signal Ink: on a graphite ground the darker blue
   does not clear contrast. DESIGN.md §2. */
.rack-column-link {
  display: inline-flex;
  align-items: center;
  align-self: start;
  min-height: 44px;
  color: var(--signal-bright);
  font-family: var(--font-sans);
  font-size: var(--type-ui-size);
  text-underline-offset: 0.18em;
  transition: color var(--duration-hover) var(--ease-out-quart);
}

.rack-column-link:hover {
  color: var(--paper-000);
}

@media (min-width: 1024px) {
  /* Four across, split by vertical rules. The three content rows are
     declared on the list and each item takes them as a subgrid, so name,
     body, and link align across all four columns regardless of how many
     lines a gloss runs to. Without it each item is its own grid and the
     rows drift apart. */
  .rack-columns {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-template-rows: auto 1fr auto;
    /* Pulls the outer padding back to the band's edge so the first
       column aligns flush with the heading above it while all four keep
       identical internal padding. Unequal padding is what makes a middle
       column measurably narrower than its neighbours. */
    margin-inline: calc(var(--space-xl) * -1);
  }

  .rack-column {
    grid-row: span 3;
    grid-template-rows: subgrid;
    padding: var(--space-xl);
    border-bottom: 0;
    border-left: 1px solid var(--graphite-700);
  }

  .rack-column:first-child {
    border-left: 0;
  }
}

/* Two by two between 768px and 1024px: four across is too narrow for a
   68ch gloss, and one column wastes the width. */
@media (min-width: 768px) and (max-width: 1023px) {
  .rack-columns {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    /* Two bands of three rows, so the catalog links still align with
       each other across a pair even though the glosses differ by two
       lines. Without the subgrid the links float at the foot of their
       own text and the row loses its baseline. */
    grid-template-rows: repeat(2, auto 1fr auto);
    margin-inline: calc(var(--space-xl) * -1);
  }

  .rack-column {
    grid-row: span 3;
    grid-template-rows: subgrid;
    padding: var(--space-xl);
    border-left: 1px solid var(--graphite-700);
  }

  .rack-column:nth-child(odd) {
    border-left: 0;
  }

  .rack-column:nth-last-child(-n + 2) {
    border-bottom: 0;
  }
}

/* =====================================================================
   7. THE EVIDENCE PAIR
   Two photographs on paper, sitting between the two bands. They are the
   reason the second band still reads as an object: without paper and an
   image between them the page would go dark for two full screens.
   ===================================================================== */

.rack-evidence {
  display: grid;
  gap: var(--space-2xl);
  margin-bottom: var(--space-4xl);
}

/* One source is baked 1.67:1 and the other 0.94:1, so both are given a
   common window and cropped into it. Left to their own proportions the
   portrait ran nearly twice the height of its neighbour and opened a
   rectangle of dead paper beside the landscape caption. Object-position
   is set per image so the crop keeps the subject: the cases sit low in
   their frame, the technician high in his.

   440px against a 548px column is 1.25:1, the geometric mean of the two
   source ratios. The window was 400px, which is 1.37:1 and sat much
   closer to the landscape — it took 18% off the cases and 31% off the
   desk. At 1.25 the two frames give up a comparable share, and the pair
   gains 40px of height in a section that had none to spare.

   The real fix is upstream: re-bake both sources to one ratio in
   scripts/bake-crops.py and delete this rule. A shared CSS window over
   two disagreeing baked crops is the compromise, not the intent. */
.rack-evidence img {
  height: clamp(300px, 32vw, 440px);
  object-fit: cover;
}

.rack-evidence figure:first-child img {
  object-position: 50% 62%;
}

.rack-evidence figure:last-child img {
  object-position: 50% 26%;
}

@media (min-width: 900px) {
  .rack-evidence {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-3xl);
    align-items: start;
  }
}

/* =====================================================================
   8. THE PHASE BAND
   The same faceplate as the disciplines, holding the three phases. The
   numeral is the one place on this page where a figure runs at display
   scale, which is what tells the reader this band is a sequence rather
   than a list.
   ===================================================================== */

.rack-phase-band {
  display: grid;
  gap: 0;
  margin: 0;
  padding-block: var(--space-2xl);
  list-style: none;
}

@media (min-width: 768px) {
  .rack-phase-band {
    padding-block: var(--space-3xl);
  }
}

.rack-phase {
  display: grid;
  gap: var(--space-sm);
  align-content: start;
  padding-block: var(--space-2xl);
  border-top: 1px solid var(--graphite-700);
}

.rack-phase:first-child {
  border-top: 0;
  padding-top: 0;
}

.rack-phase-numeral {
  color: var(--graphite-500);
  font-family: var(--font-sans);
  font-size: 3rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums slashed-zero;
}

.rack-phase-title {
  margin-bottom: var(--space-sm);
  color: var(--paper-000);
}

@media (min-width: 900px) {
  /* Three across, split by vertical rules. SEVEN content rows as a
     subgrid — numeral, title, then one row per spec term and value, then
     the body — so every engraved rule lands at the same height in all
     three columns.

     THE SPEC PAIRS ARE ROWS OF THE BAND, NOT OF THE COLUMN. Giving the
     <dl> a single row of its own was the earlier arrangement and it drifted
     two different ways, both of which put a rule at a different height from
     its neighbours:

       1. The row is sized to the tallest column, and a shorter <dl> was
          stretched to match. Its own rows are auto and align-content
          defaults to stretch, so the surplus was shared out between all
          four of them rather than left at the bottom; align-self: center
          on the term then floated its rule into the middle of a row that
          was taller than the text in it. Consultation's Deliverable rule
          sat 13px below the other two on that alone.
       2. A value that wraps in one column and not another moves every
          rule beneath it. "One to two weeks before load-in" takes two
          lines at 900px and one line from 1024px up, so the band was
          correct on a desktop and wrong on a small laptop.

     Sharing the rows kills both: a term and its value are the same track
     across the band, so the rules cannot drift however the copy sets, and
     the surplus collects under the last value where there is no rule to
     move. Any spec pair added here needs two more rows in both templates.

     Row gap goes to zero because a uniform gap would also open between a
     term and its value, where the spacing is carried by their own padding.
     The three gaps that were doing real work are restored as margins.

     No negative margin here, unlike .rack-columns. That trick works on a
     list nested INSIDE the band; this element is the band, and pulling
     its own margins out pushed it 24px wider than the shell on both
     sides. The first and last columns drop their outer padding instead,
     which lands the same flush alignment without moving the band. */
  .rack-phase-band {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-rows: auto auto auto auto auto auto 1fr;
  }

  .rack-phase {
    grid-row: span 7;
    grid-template-rows: subgrid;
    row-gap: 0;
    padding: 0 var(--space-xl);
    border-top: 0;
    border-left: 1px solid var(--graphite-700);
  }

  .rack-phase:first-child {
    padding-left: 0;
    padding-top: 0;
    border-left: 0;
  }

  .rack-phase:last-child {
    padding-right: 0;
  }

  /* Replacing the row gap the line above removed, so the band's vertical
     rhythm is unchanged: 8px under the numeral, 16px under the title,
     24px under the last spec value. */
  .rack-phase-title {
    margin-top: var(--space-sm);
    margin-bottom: var(--space-lg);
  }
}

/* =====================================================================
   9. PHASE SPEC PAIRS
   Timeline and Deliverable, engraved into the faceplate as a ruled
   two-column readout — the spec panel's own vocabulary, applied to a
   process instead of to an item.
   ===================================================================== */

.rack-spec {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0;
  margin: 0 0 var(--space-lg);
}

@media (min-width: 640px) and (max-width: 899px) {
  .rack-spec {
    grid-template-columns: minmax(0, auto) minmax(0, 1fr);
    column-gap: var(--space-xl);
  }
}

.rack-spec dt,
.rack-spec dd {
  margin: 0;
  padding: var(--space-sm) 0;
  border-top: 1px solid var(--graphite-700);
}

.rack-spec dt {
  color: var(--graphite-300);
  align-self: center;
}

.rack-spec dd {
  color: var(--paper-200);
}

/* Where the pair stacks, the key and its value are a single row, so the
   value must not repeat the rule that opened the pair. */
.rack-spec dd {
  border-top: 0;
  padding-top: 0;
}

@media (min-width: 640px) and (max-width: 899px) {
  .rack-spec dd {
    border-top: 1px solid var(--graphite-700);
    padding-top: var(--space-sm);
  }
}

/* Three across, the pairs become rows of the band itself so a rule cannot
   land at a different height from the same rule in the next column. The
   reasoning is with .rack-phase-band in section 8.

   THIS BLOCK HAS TO SIT AFTER THE BASE .rack-spec RULE ABOVE, not with the
   rest of the ≥900 layout. That rule sets `margin` as a shorthand and is
   later in the file, so a margin-bottom declared up there is overridden at
   equal specificity and the gap under the pairs silently reverts to 16px. */
@media (min-width: 900px) {
  .rack-spec {
    grid-row: span 4;
    grid-template-rows: subgrid;
    /* Replaces the 16px margin plus the 8px row gap the band no longer
       has, so the space under the last value is unchanged at 24px. */
    margin-bottom: var(--space-xl);
  }
}

/* =====================================================================
   10. CLOSE
   ===================================================================== */

.rack-close-heading {
  max-width: 24ch;
  margin-bottom: var(--space-3xl);
}

.rack-split {
  display: grid;
  gap: var(--space-2xl);
  padding-top: var(--space-2xl);
  border-top: 1px solid var(--paper-300);
}

.rack-split-col {
  display: grid;
  gap: var(--space-lg);
  align-content: start;
  justify-items: start;
}

.rack-split-col .btn {
  margin-top: var(--space-sm);
}

@media (min-width: 768px) {
  .rack-split {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-4xl);
  }

  .rack-split-col:last-child {
    padding-left: var(--space-4xl);
    border-left: 1px solid var(--paper-300);
  }
}

@media (max-width: 479px) {
  .rack-split-col .btn {
    width: 100%;
  }
}
