/* ================================================================
   LAYOUT — Page structure, grid, containers
   ================================================================ */

/* ── Content wrapper: 95% width, max 1440px — sections limited to this rule ── */
.content-wrap {
  width: var(--content-width);
  max-width: 1440px;
  margin-left: auto;
  margin-right: auto;
}

/* ── Page Wrapper ─────────────────────────────────────────────── */
.page {
  max-width: var(--page-max);
  margin: 0 auto;
  position: relative;
}

/* ── Section: fills content-wrap (inherits 95% / 1440px rule) ─── */
/* ONE STEP DOWN THE LADDER. Vertical air was `--sp-20` (80) top and bottom,
   so every act break was 160px, on top of a 60px crease gap and a 64px
   heading gap — roughly a third of a 900px viewport spent on separation
   before any content appeared. The page read as stretched rather than calm.
   Everything moved down one token step: section 80 → 64 (act gap 128), crease
   64 → 48, heading 64 → 48. The RATIOS are unchanged, so the hierarchy reads
   the same; only the scalar moved. Mobile was already tight and is untouched. */
.section {
  width: 100%;
  padding: var(--sp-16) var(--gutter-inner);
  position: relative;
}

/* The hero is a panel whose bottom margin equals the side inset (40px),
   so it only contributes 40px of the inter-block rhythm. Pad the first
   section below it (padding, not margin — margins would collapse with the
   hero's) so the hero→Work gap matches the 160px between sections
   (40 hero margin + 88 padding-top = 128, matching the new act gap). */
.hero + .section {
  padding-top: 88px;
}

/* `.footer__cta` carries `.section` for its PADDING only — the measure lives
   on `.footer` itself (it is a sibling of <main>, so it re-creates
   `.content-wrap` rather than inheriting it). This block previously re-created
   the measure a second time here, which applied the 95% twice and pulled every
   footer edge ~19px inside the sections above. Cancel, don't re-apply. */
.footer__cta.section {
  width: auto;
  max-width: none;
  margin-left: 0;
  margin-right: 0;
}

/* Crease — the Warm Precision house-mark. The dark line is the fold
   valley, with a catch-light above and soft shadow below so the rule
   reads as a scored paper edge rather than a flat stroke.

   The crease is DRAWN, not ruled: it runs a ~0.6px hairline at each end
   and swells to ~2px mid-span, with the peak left of centre. Paper creases
   hardest where the hand presses — the PRESSURE carries the warmth. Its
   centerline is LEVEL (the silhouette mirrors about the midline); it used
   to waver ~1.8px, which over this run length read as a crooked line
   rather than a drawn one. Don't put the waver back.
   The line stays continuous end to end and spans the full gutter-to-gutter
   rail; only its WEIGHT varies, never its extent.

   Total ink is LESS than the flat 2px rule this replaced — it only reaches
   2.3px at the single strongest point and is lighter everywhere else. Tune
   weight via `--rule-box-section` (tokens.css); `--crease-inset` must stay
   at half the box minus 1px or the vertical rhythm shifts.

   The silhouette is `--rule-silhouette` (tokens.css) — the SAME shape the
   content rules use at half the box. One hand, two pressures.

   The catch-light and shadow are `drop-shadow()` filters rather than
   `box-shadow`, so they follow the pressed silhouette instead of
   tracing the element's rectangle. */
.section__divider {
  --crease-box:   var(--rule-box-section);
  --crease-inset:  4px;   /* the box grew around the line — pull it back so the
                             crease lands where the old 2px rule sat (rhythm).
                             ALWAYS half the box minus 1px. */
  width: 100%;
  height: var(--crease-box);
  margin-top: calc(var(--crease-inset) * -1);
  margin-bottom: calc(var(--sp-12) - var(--crease-inset));
  filter:
    drop-shadow(0 -1px 0     var(--crease-highlight))
    drop-shadow(0  1px 1.5px var(--crease-shadow));
}

/* The crease body. The mask lives HERE, not on the parent, because
   `filter` resolves BEFORE `mask` on the same element — the drop-shadows
   would be computed on the full rectangle and then clipped away, losing
   the scored-edge reading entirely. Parent filters, child mask. */
.section__divider::after {
  content: "";
  display: block;
  height: 100%;
  background-color: var(--divider-section);
  -webkit-mask: var(--rule-silhouette) no-repeat 50% 50% / 100% 100%;
          mask: var(--rule-silhouette) no-repeat 50% 50% / 100% 100%;
}

/* ── The media crease ─────────────────────────────────────────────
   The house-mark, moved into the page's largest mass. The crease used to
   appear exactly twice in ~5,500px and only as a section divider, so the
   signature lived in the gaps BETWEEN the cards while the cards themselves
   spoke a generic tile vocabulary. One fold across the top edge makes each
   project read as a panel of the same sheet.

   ONE PER PAGE, NOT ONE PER CARD. It first went on all five project media
   plates; at five card-tops plus three section creases the homepage read as
   ruled, which is exactly the failure the "do not scatter the crease" rule
   exists to prevent. It is now on `.project-card--full` — the flagship, and
   the sheet's top fold — and on the case cover, which is that page's single
   hero plate. Do not put it back on `--half`.

   The FLYER deliberately does NOT carry it, which is a knowing exception to
   the keep-the-three-plates-identical rule stated below. That rule exists for
   the plate FILL: a large area changing colour mid-flight reads as a pop. A
   6px tapered mark at one edge, in motion for 680ms under a dissolving veil,
   does not. If it ever does, the fix is for the head director to stamp a
   class on the flyer when the source card had one — not to give every card a
   crease again.

   Same drawn silhouette (`--rule-silhouette`) at the FINE box — a card top
   is a lesser fold than an act break, and the mark's discipline is that
   WEIGHT states the level, never a different shape.

   Lit differently from the section crease for one reason: this one lands on
   a photograph, not on paper. `.section__divider` gets its catch-light from
   `drop-shadow()` filters on the parent, which needs the parent to be a bare
   box; here the parent is a clipped image frame. So the highlight and the
   valley are baked into the gradient instead and the mask tapers them
   together. Do NOT convert this to a parent filter — these parents run
   `overflow: hidden` + `corner-shape: squircle`, and a filter also creates a
   containing block, which would break the flyer's fixed positioning during
   the page transition. */
.project-card--full .project-card__media::before,
.case-cover__media::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: var(--rule-box-fine);
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    var(--crease-highlight) 0%,
    var(--crease-highlight) 34%,
    rgba(120, 108, 88, 0.55) 34%,
    rgba(120, 108, 88, 0.55) 50%,
    var(--crease-shadow) 50%,
    rgba(45, 40, 30, 0) 100%
  );
  -webkit-mask: var(--rule-silhouette) no-repeat 50% 50% / 100% 100%;
          mask: var(--rule-silhouette) no-repeat 50% 50% / 100% 100%;
}

.section__heading {
  font-family: var(--type-h2-font);
  font-size: var(--type-h2-size);
  line-height: var(--type-h2-line);
  font-weight: var(--weight-regular);
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
  margin-bottom: var(--sp-12);
}

/* ── Project Grid — TWELVE COLUMNS ────────────────────────────────
   Every row is the same 12-column field; cards claim column SPANS. Nothing
   sizes itself by ratio.

   This replaced per-row `grid-template-columns` (`1fr`, `1fr 1fr`,
   `2fr 1fr`). The first two happened to land on the module — at a 1274
   container with a 40px gutter one column is 69.5px, so `1fr 1fr` = 617 =
   exactly span 6. But `2fr 1fr` is a RATIO, not a span: it produced
   822.7 / 411.3 where the module wanted 836 / 398. **13.3px off**, on the
   widest object on the page, with nothing else on the page sharing that
   edge. That is the whole reason it read as not-following-the-grid.

   A ratio agrees with a grid only by coincidence. Use spans. */
.project-grid {
  display: flex;
  flex-direction: column;
  gap: var(--sp-16);   /* row rhythm — see "air" note below */
}

.project-row {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--sp-10);
}

/* Span classes — the only sanctioned widths. If a card needs a width that
   is not one of these, it needs a different span, not a new rule. */
.project-card--full  { grid-column: span 12; }   /* 1274 */
.project-card--lead  { grid-column: span 7;  }   /*  727 */
.project-card--minor { grid-column: span 5;  }   /*  508 */
.project-card--half  { grid-column: span 6;  }   /*  617 — even pair, unused today */

/* THE GRID EXPRESSES RANK. Five projects laid out full / 1:1 / 1:1 gave every
/* THE COMPOSITION — 12 · (5+7) · (7+5).
   Five projects laid out full / 6+6 / 6+6 said only "there are five of them".
   The wide slot now ALTERNATES SIDES between the two half-rows, so the page
   reads as a composed spread rather than a stack: flagship full bleed, then a
   zigzag. 7/5 (727/508) rather than 8/4 (836/398) — 8/4 is a strong enough
   asymmetry that the minor card goes nearly square and stops holding its own,
   and the point is rank, not drama.

   Which project takes each wide slot is an EDITORIAL call, held in the markup
   (`--lead` / `--minor`), not here. Pindo leads row 3 because it is the one
   Karl founded, designed, and built himself. Swap the two classes to change
   it; the grid does not care. */

/* Air. The row gap was `--sp-10` (40) — the same value as the gap BETWEEN two
   cards in a row, so the grid read as an even field of tiles with no grouping.
   Rows now sit on `--sp-16` (64) while cards within a row stay at 40, which is
   what makes a row read as a row. This is the single biggest lever on how
   composed the section feels, and it costs nothing but space. */

/* ── About Layout ─────────────────────────────────────────────── */
/* SAME 12-COLUMN FIELD AS THE WORK GRID — heading 5, content 7.
   This was `1fr 1fr` (617/617), so the two sections below the work grid sat on
   a 6/6 split while the grid above them ran 5+7 / 7+5. One page, two rhythms.
   Now the seam lands at 624, which is where the work grid's row-2 seam already
   is, so About and Record line up with the row above rather than near it.

   NOTE — `5fr 7fr` would NOT be the same thing. With a 40px gap it resolves to
   514/720, not 508/727: fr units divide the space left AFTER the gap, spans
   divide the field itself. This is the same trap that put the old `2fr 1fr`
   work row 13.3px off the module. Spans, always.

   The 7 column is also the right home for the bio: at 24px it runs 66
   characters there (56 at the old 617), still inside the comfortable measure. */
.about-layout {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--sp-10);
  align-items: start;
}

.about-layout > :first-child { grid-column: span 5; }
.about-layout > :last-child  { grid-column: span 7; }

/* ── Footer CTA Layout ────────────────────────────────────────── */
/* DEAD — no markup uses `.footer-cta-layout`; the footer ink block lays itself
   out with `.footer__top`. Kept only so its responsive rules below don't
   dangle. If the footer ever wants two columns again, put it on the 12-column
   field with spans like `.about-layout` — do not revive this `1fr 1fr`. */
.footer-cta-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-10);
  align-items: stretch;
}

/* ── Responsive ───────────────────────────────────────────────── */
/* 
   SPACING PHILOSOPHY FOR MOBILE:
   ─────────────────────────────────────────────────────────────────
   We do NOT globally override --sp-* tokens. Instead, we apply
   spacing per semantic role:
   
   1. Section spacing (between page blocks): stays generous (40px+)
   2. Component gap (between cards/blocks): moderate (24–32px)
   3. Internal spacing (within components): proportional reduction
   4. Element spacing (heading→body→CTA): slight reduction only
   5. Divider/border spacing (around rules): compact (12–16px)
   6. Inline/small spacing (tag gaps, etc.): minimal change
   
   Typography tokens and gutters are still globally overridden.
   ───────────────────────────────────────────────────────────────── */

@media (max-width: 1024px) {
  :root {
    --type-h1-size: 56px;
    --type-h1-line: 64px;
    --type-h2-size: 40px;
    --type-h2-line: 48px;
    --type-h3-size: 32px;
    --type-h3-line: 40px;
    /* Surface radius — tablet step */
    --radius-panel: 40px;
    --radius-card:  14px;
  }

  /* The 12-column field collapses to one column; every span resets with it,
     or a `span 7` would overflow a 1-column grid. */
  .project-row {
    grid-template-columns: 1fr;
  }

  .project-card--full,
  .project-card--lead,
  .project-card--minor,
  .project-card--half {
    grid-column: auto;
  }

  /* Component gap: slightly tighter */
  .about-layout {
    grid-template-columns: 1fr;
    gap: 36px;
  }

  /* Spans reset with the field, or a `span 7` overflows one column. */
  .about-layout > :first-child,
  .about-layout > :last-child {
    grid-column: auto;
  }

  .footer-cta-layout {
    grid-template-columns: 1fr;
  }

  /* Divider spacing: start reducing (less the crease inset — the drawn
     crease sits inside a taller box; see the base rule) */
  .section__divider {
    margin-bottom: calc(48px - var(--crease-inset));
  }

  .section__heading {
    margin-bottom: 48px;
  }
}

/* ── Mobile: 768px and below ──────────────────────────────────── */
@media (max-width: 768px) {
  :root {
    /* Typography only — titles scale down; body stays fixed */
    --type-h1-size: 36px;
    --type-h1-line: 44px;
    --type-h2-size: 30px;
    --type-h2-line: 38px;
    --type-h3-size: 24px;
    --type-h3-line: 32px;
    --type-h4-size: 18px;
    --type-h4-line: 24px;
    --type-display-size: 18px;
    --type-display-line: 26px;
    /* Gutters only */
    --gutter:       16px;
    --gutter-inner: 16px;
    /* Surface radius — mobile step (card floor = 16px) */
    --radius-panel: 32px;
    --radius-card:  12px;
  }

  /* The footer re-creates this measure rather than inheriting it (it is a
     sibling of <main>), so it needs the same mobile override — applied in
     `footer.css`, because that file is linked after this one and its
     `.footer` rule would otherwise win on source order. Change one, change
     both. */
  .content-wrap {
    width: 100%;
  }

  /* 1. Section spacing: still generous */
  .section {
    padding: 48px var(--gutter);
  }

  /* Match the 96px inter-section gap below the hero
     (16 hero margin + 80 padding-top = 96). */
  .hero + .section {
    padding-top: 80px;
  }

  /* 2. Component gap: moderate */
  .project-grid {
    gap: 28px;
  }

  .project-row {
    gap: 28px;
  }

  .about-layout {
    gap: 28px;
  }

  .footer-cta-layout {
    gap: 28px;
  }

  /* 5. Divider spacing: compact (less the crease inset) */
  .section__divider {
    margin-bottom: calc(20px - var(--crease-inset));
  }

  /* 4. Element spacing: slight reduction */
  .section__heading {
    margin-bottom: 28px;
  }
}
