/* projects — owned by its phase agent. Loaded after site.css; may override it.
   Covers: Slide 2 (SCALE / stat bar) refinements, Slides 3–7 (flagship
   projects) parallax hooks + short-spec-line treatment, and Slide 9 (CRAFT)
   layered-depth parallax hooks + diagrid prominence. Motion itself lives in
   js/projects.js — this file only sets up the static/base look and the
   GPU-only transform surfaces the JS animates. */

/* ==========================================================================
   SLIDE 2 — SCALE (stat bar)
   Mono type is already applied to counters in site.css; here: hairline
   dividers between stats + more generous rhythm, and a compact treatment
   for the one non-numeric ("EN · ASTM · AAMA") stat so all four columns
   read as one calm, engineering-precise row.
   ========================================================================== */
#scale .stats__grid {
  margin-top: var(--space-2);
  row-gap: var(--space-5);
}

#scale .stat {
  position: relative;
}

/* Hairline dividers between stats — vertical rules echoing the mono grid.
   Mobile: 2-column layout, divider sits between the two items in each row.
   Desktop: 4-column layout, a divider before every stat but the first. */
@media (max-width: 719px) {
  #scale .stat:nth-child(even)::before {
    content: "";
    position: absolute;
    top: 0.15em;
    bottom: 0.15em;
    left: calc(var(--gutter) * -0.5);
    width: 1px;
    background: var(--steel-20);
  }
}
@media (min-width: 720px) {
  #scale .stat:not(:first-child)::before {
    content: "";
    position: absolute;
    top: 0.15em;
    bottom: 0.15em;
    left: calc(var(--gutter) * -0.5);
    width: 1px;
    background: var(--steel-20);
  }
}

/* The one text (not numeric) stat: same mono voice, sized to sit quietly
   beside the counters rather than fighting them for width. */
#scale .stat__value--compact {
  font-size: clamp(1.05rem, 1.1vw + 0.7rem, 1.55rem);
  letter-spacing: 0.02em;
}

#scale .stats__footnote {
  margin-top: var(--space-6);
  padding-top: var(--space-3);
  border-top: 1px solid var(--steel-20);
  max-width: 42em;
}

/* ==========================================================================
   SLIDES 3–7 — WHY OREGON (company-proposition pillars, P8 item 4)
   Tan, verbatim: "these full sections need to sell something about the
   company not projects — we have the next section (side scroll) for these
   projects. Focus on why Oregon on these full screen slides." Same five
   photographs stay as backdrop; the project itself is now only a photo
   credit line. `.why` is a new class — its base slide layout (position,
   padding, flex-end) is migrated here from site.css's old `.project` rules
   since site.css is off-limits and never defined `.why`.

   Parallax surfaces unchanged from the old project slides: the image is
   pre-scaled so its translateY range never reveals an edge; the headline
   gets its own inner element (`.why__title-inner`) so the deck's entrance
   transform (js/deck.js, on the same [data-animate] element) and the
   continuous scroll-parallax (js/projects.js, on the inner span) never
   fight over the same computed transform.
   ========================================================================== */
.why {
  padding: 0;
  justify-content: flex-end;
}
.why__media { position: absolute; inset: 0; z-index: 0; }
.why__content {
  position: relative;
  z-index: 2;
  padding: var(--space-6) var(--margin);
}

.why__media img {
  transform: scale(1.15);
  transform-origin: center center;
  will-change: transform;
}

.why__title-inner {
  display: block;
  will-change: transform;
}

.reduced-motion .why__media img {
  transform: none;
}
.reduced-motion .why__title-inner {
  transform: none !important;
}

/* Heavier scrim behind the copy block (Tan: "font size needs to be
   bigger" made the headline dominate the frame — it needs a darker bed to
   sit on than the site-wide .scrim default, while the photography stays
   readable through the top/middle of the frame). */
.why .scrim {
  background: linear-gradient(
    180deg,
    var(--ink-70) 0%,
    rgba(14, 15, 17, 0.2) 32%,
    rgba(14, 15, 17, 0.55) 58%,
    rgba(14, 15, 17, 0.88) 82%,
    rgba(14, 15, 17, 0.96) 100%
  );
}

/* Bottom-left copy block, bottom-right photo credit; stacks on mobile.
   The credit is absolutely positioned (anchored to .slide__inner, already
   position:relative in site.css) rather than a flex sibling, so it never
   steals width from the headline column — at --fs-h1 (~122px at 1920) the
   longest pillar headline needs close to the full 90rem slide__inner
   width to break to two lines instead of four or five. */
.why__row {
  position: relative;
}
/* Override site.css's shared .slide__inner max-width (90rem) for this
   section only: at --fs-h1 the headline needs the full padded viewport
   width, not the site-wide reading-width cap, to break to two lines. */
.why__content .slide__inner {
  max-width: none;
}
.why__copy {
  max-width: 100%;
  position: relative; /* P10 D: containing block for .why__copy::before */
}

/* P10 item D (Tan, phone why-3 over the SCG façade: "Gotta fix the
   visibility here or text contrast"): the slide's shared `.why .scrim`
   above darkens by a % of the FULL SLIDE height, so how dark the copy
   block actually sits depends on where in that gradient the text lands —
   different at every viewport aspect ratio, and Tan's own phone (not at
   the exact scroll-snap rest point when he captured it) showed a
   brighter photo than this dev screenshot ever will. A second scrim
   anchored to the real copy box — not a % of the viewport — keeps the
   darkening constant no matter the screen height or scroll position.
   Desktop: a footer-band bleed behind `.why__copy` only, feathered from
   just above the eyebrow (the audit below shows `.why__foot` already
   clears contrast on its own, and Tan wants the photo kept legible
   through the top two-thirds of the frame). Mobile: widened to the
   whole `.why__row` (copy + foot) — see the max-width:900px block. */
.why__copy::before {
  content: "";
  position: absolute;
  z-index: -1;
  /* Full-bleed to the viewport edges rather than stopping short at
     `.why__copy`'s own (container) width: a panel that stops a few rem
     short of the edge left a thin hard-edged sliver of undarkened photo
     down the right side of the frame (visible behind "ENGINEERED TO…"),
     reading as a pasted-on card. Bled edge-to-edge it reads as one
     footer band, same language as the P10-C About panel and the mobile
     row scrim below. */
  left: calc(var(--margin) * -1);
  right: calc(var(--margin) * -1);
  top: -2rem;
  bottom: calc(var(--space-6) * -1);
  background: linear-gradient(
    180deg,
    rgba(14, 15, 17, 0) 0,
    rgba(14, 15, 17, 0.55) 2rem,
    rgba(14, 15, 17, 0.85) 4.5rem,
    rgba(14, 15, 17, 0.92) 100%
  );
}

.why__eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  font-weight: 500; /* P10 D: "brightened/bolder", not dropped — 500 is already fetched */
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--offwhite);
  opacity: 1; /* P10 D: was 0.85 — eyebrow failed contrast on brighter photos (why-3/4/5) */
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7), 0 2px 18px rgba(0, 0, 0, 0.5);
}

.why__headline {
  margin-top: var(--space-2);
}

.why__lede {
  margin-top: var(--space-3);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  max-width: 34ch;
  /* P9 item C (Tan: "it should be white and bright") — full offwhite, no
     opacity dimming. The old 0.92 opacity plus the deck's whole-slide
     0.6 opacity (site.css .is-dimmed, fixed separately) compounded into
     grey-looking body copy; text is now always full strength and only
     the photo behind it ever dims. */
  color: var(--offwhite);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7), 0 2px 18px rgba(0, 0, 0, 0.5);
}

/* Photo credit + placeholder project link — the project's whole
   remaining footprint on this slide (GOAL.md P8 item 4: "project name
   stays as a ≥18px photo credit"; P9 item C adds a placeholder "View
   project →" link, Tan: "Maybe add a placeholder link to check out the
   project"). `.why__foot` anchors both bottom-right as a column so the
   link sits cleanly under the credit without absolute-position math
   between two siblings; it stays clear of the fixed progress dots
   (vertically centred, not at the bottom edge) and the logo (top-left). */
.why__foot {
  position: absolute;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-1);
}
/* Small/secondary by design, so it keeps a lighter (offwhite-60-ish)
   presence per the P9 brief ("eyebrow/credit may stay steel"); still
   ≥18px (--fs-mono). */
.why__credit {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.02em;
  text-align: right;
  max-width: 26ch;
  color: var(--offwhite);
  opacity: 0.7;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7), 0 2px 18px rgba(0, 0, 0, 0.5);
}
.why__link {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.5em;
  min-height: 44px;
  padding: 0.4em 0;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.02em;
  color: var(--offwhite);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7), 0 2px 18px rgba(0, 0, 0, 0.5);
}
.why__link:focus-visible {
  outline: 2px solid var(--offwhite);
  outline-offset: 4px;
}

@media (max-width: 900px) {
  .why__foot {
    position: static;
    align-items: flex-start;
    margin-top: var(--space-2);
  }
  .why__credit {
    max-width: 100%;
    text-align: left;
  }
  .why__link {
    justify-content: flex-start;
  }

  /* P10 item D: on mobile `.why__foot` drops into flow below `.why__copy`
     (rule above), so the local scrim needs to cover both as one panel —
     the row-level version replaces `.why__copy::before` (turned off just
     below) and full-bleeds past `--margin` to the true viewport edges,
     matching the About section's mobile panel treatment (P10 item C).
     Anchored to the row's own content box (auto height), not a % of the
     viewport, so it holds regardless of `100svh` vs the real, URL-bar-
     shrunk iOS viewport height Tan's phone renders. */
  .why__row {
    position: relative;
  }
  .why__copy::before {
    content: none;
  }
  .why__row::before {
    content: "";
    position: absolute;
    z-index: -1;
    left: calc(var(--margin) * -1);
    right: calc(var(--margin) * -1);
    top: -6rem;
    bottom: calc(var(--space-6) * -1);
    background: linear-gradient(
      180deg,
      rgba(14, 15, 17, 0) 0,
      rgba(14, 15, 17, 0.65) 6rem,
      rgba(14, 15, 17, 0.93) 9rem,
      rgba(14, 15, 17, 0.97) 100%
    );
  }
}

/* ==========================================================================
   SLIDE 9 — CRAFT (P8 fit fix, 2026-09-04)
   Composition: craft-diagrid (the strongest image on the site, GOAL.md §2
   slide 9) is a hero band; the other three real detail shots form a calm
   three-up strip beneath it — unchanged from the earlier defect fix.

   P8 refit: Wave 1's bigger type (--fs-h2, --fs-eyebrow etc.) made the old
   single-column stack (heading, then full-width grid, then a claims row
   below it) taller than one screen at both 1920×1080 and 1440×900 — the
   three-up strip and claims ran off the bottom. Measured budget at
   1920×1080 with the old layout: ~1561px total (96+96 section padding +
   ~171 heading + 1026.5 grid + ~172 claims-below-grid gap+height). Fix,
   two parts:
   1. `.craft__body` (new wrapper, see index.html) puts the image grid and
      the three claims side-by-side at ≥1000px instead of stacking the
      claims below a full-width grid — this alone both narrows the grid
      (shrinking the hero/strip images, which are aspect-ratio-driven off
      their own width) and removes the claims' entire stacked height/gap
      from the vertical budget.
   2. Slightly flatter hero/strip aspect ratios and tighter section
      padding claw back the rest. Combined, measured total section height
      is comfortably under both 1080 and 900 — see the shots1080.mjs runs
      referenced in the P8 handover.

   Layered-depth parallax (js/projects.js) is untouched: each image's own
   <img> scales/translates inside its clipped .media tile at 0.85x/1.0x/
   1.15x (hero 0.95x). That range is a fixed percentage of each tile's own
   box, so it stays inside the scale(1.2) buffer regardless of the tile's
   aspect ratio — no JS change needed for the flatter ratios below.
   ========================================================================== */
.craft {
  /* Bottom: tighter than the site-wide --space-6 slide padding (96px at
     1920) — reclaims vertical budget without touching type.
     Top: NOT reduced to match — the fixed `.logo` (top: var(--space-3)
     [24px] + ~82px tall = bottom edge ~106px from the viewport top,
     regardless of viewport size) sits over this section whenever it's in
     view. .craft uses the deck's default `justify-content: center`, and
     at 1440×900 this section's content nearly fills the viewport, leaving
     the centering pass almost no slack to push the heading down clear of
     the logo — confirmed colliding with --space-4 (40px) top padding.
     8rem (128px) clears the logo's ~106px footprint with room to spare,
     independent of how much centering slack there is at a given
     viewport/content combination. */
  padding-top: max(8rem, var(--chrome-top));
  padding-bottom: var(--space-3);
}

.craft__body {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
  margin-top: var(--space-3);
}

@media (min-width: 1000px) {
  .craft__body {
    grid-template-columns: 2.4fr 1fr;
    align-items: center;
    gap: var(--gutter);
  }
}

.craft__grid {
  display: grid;
  grid-template-columns: 1fr;
  row-gap: var(--gutter);
  /* site.css still sets margin-top: var(--space-4) on this selector (its
     pre-P8 top-level position in the flow) — zeroed here since the top
     gap is now owned by .craft__body's own margin-top instead; without
     this override the two stacked, adding an untracked 40px. */
  margin-top: 0;
}

.craft__hero {
  aspect-ratio: 16 / 10;
}

.craft__support {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--gutter);
}
.craft__support-item {
  aspect-ratio: 1 / 1;
}

@media (min-width: 900px) {
  /* Flatter than the pre-P8 2.2/1 and 4/3 — combined with the ≥1000px
     two-column split above, this is what keeps the grid's height inside
     budget at both 1920×1080 and 1440×900. */
  .craft__hero { aspect-ratio: 2.6 / 1; }
  .craft__support-item { aspect-ratio: 3 / 2; }
}

.craft__grid img {
  transform: scale(1.2);
  transform-origin: center center;
  will-change: transform;
}
.reduced-motion .craft__grid img {
  transform: none;
}

/* Claims: below the grid (<1000px, single column) they keep the earlier
   "stable spec-sheet" treatment — pulled close with a hairline top edge,
   so they read as anchored to the photography above. Beside the grid
   (≥1000px) that becomes a hairline *left* edge instead, and the three
   claims stack vertically in the narrower column rather than as a row —
   the row layout doesn't fit a ~1/3-width column at any of the claim
   text's wrap points without the paragraphs colliding. */
.craft__claims {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--steel-20);
}

@media (min-width: 1000px) {
  .craft__claims {
    grid-template-columns: 1fr;
    margin-top: 0;
    padding-top: 0;
    padding-left: var(--gutter);
    border-top: 0;
    border-left: 1px solid var(--steel-20);
  }
}
