/* ============================================================
   NR THEME — SINGLE PROJECT (case study)
   Templated zones (header / hero / meta / body / read next) + styling for the
   free-form body's layout components. Text classes (.nr-display, .nr-body*,
   .nr-section-tag, .nr-decisions* text, .nr-read-next) come from nr-type.css;
   this file adds the case zones and the LAYOUT the body needs (meta grid,
   four-up grids, points grid, decisions list layout, read-next band).
   ============================================================ */

/* Full-width main so the Read Next can be an edge-to-edge dark band; the reading
   zones centre themselves at the shared content width. */
.nr-case {
  overflow-x: clip;   /* contain the full-bleed (100vw) breakouts */
  --case-measure: 713px;   /* = .nr-body 65ch in px; a font-size-independent
                              measure so display headings + the gaps column can
                              match body text width (their own `ch` is bigger). */
}

.nr-case__header,
.nr-case__body {
  max-width: var(--content-max, 1240px);
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--gutter, clamp(20px, 4vw, 64px));
  padding-right: var(--gutter, clamp(20px, 4vw, 64px));
}

/* ---- Header ---- */
.nr-case__header { padding-top: clamp(3rem, 8vh, 6rem); }
.nr-case__eyebrow { margin: 0 0 1rem; }
.nr-case__title { max-width: 930px; margin: 0 0 1.5rem; }
/* p.nr-body-lg (nr-type) caps at 54ch; out-specify it so the intro hits 930px. */
p.nr-case__intro { max-width: 930px; margin: 0; }

/* ---- Hero ---- */
/* Full-bleed fixed-bg image — hero AND in-body breakouts (.nr-case-fullbleed) */
.nr-case-fullbleed {
  width: 100vw;
  max-width: 100vw;
  /* Vertical margin 0: this fixed-bg breakout sits BETWEEN two .nr-case-section
     wrappers, whose top/bottom padding owns the gap (no double spacing). */
  margin: 0 calc(50% - 50vw);
  min-height: 1080px;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  background-attachment: fixed;
}
@media (max-width: 820px) {
  /* Show the whole lineup full-width (the desktop `cover` crops it to the centre
     on a narrow screen). The box is sized to the image's own ratio (~60vw tall
     for this 2048×1221 image) so `contain` fills it edge-to-edge with no crop.
     NOTE: kept `scroll`, not `fixed` — `fixed` anchors the background to the
     tall viewport, which re-crops a landscape image; full visibility wins here. */
  .nr-case-fullbleed {
    min-height: 60vw;
    background-attachment: scroll;
    background-size: contain;
  }
}

/* ============================================================
   HERO SYSTEM — the hero is a <figure>.nr-case__hero (direct child of the
   full-width .nr-case), above the meta strip. Media is a <video>, an <img>, or
   a fixed-bg layer. Spacing: top margin only — the gap before the meta strip is
   owned by the meta strip's own top padding (no ad-hoc padding-bottom here, which
   would double up against it). Image heroes pick behaviour via
   nr-hero--{default|fixed|boxed}. Reveal-on-load + reduced-motion live in
   nr-case-motion.js. .nr-case overflow-x:clip backs up the no-horizontal-scroll
   guarantee.
   ============================================================ */
.nr-case__hero {
  margin: clamp(2.5rem, 6vh, 4rem) 0;   /* L/R zeroed; equal top & bottom breathing — the bottom keeps the hero caption off the meta band */
  max-width: 100%;
  box-sizing: border-box;
  overflow: hidden;                         /* clips the cover crop / reveal overshoot */
}
.nr-case__hero-cap { margin-top: 0.85rem; }

/* Fix 3 — a FIXED-bg hero with NO caption shouldn't reserve the figure's bottom
   margin (it's there to keep a caption off the meta band). With no caption that
   margin is just empty space, so drop it and let the meta strip's own top padding
   provide the gap (hero sits flush to meta). Captioned heroes are unaffected. */
.nr-case__hero.nr-hero--fixed:not(:has(.nr-case__hero-cap)) { margin-bottom: 0; }

/* VIDEO hero — fluid 16:9 frame. All three hero .webm sources are 1920x1080, so
   the box matches the media exactly: nothing to crop at any width, and the ratio
   reserves the height before metadata loads (no layout shift). object-fit is a
   safety net only, in case a future source is not 16:9. */
.nr-case__hero-video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--colour-rule-light, #eceae4);
}

/* IMAGE hero — DEFAULT and BOXED: size to the image's own aspect. The hero images
   are NOT a single ratio (16:9 through to 1:1 square for the Herb Planter), so a
   fixed height (or a hardcoded ratio) with object-fit:cover crops whichever image
   doesn't match. width:100% + height:auto lets each <img> keep its intrinsic ratio:
   it fills the page width and scales proportionally at every viewport, and there is
   no crop box to clip against. No object-fit — there is nothing to fit. */
.nr-case__hero-img {
  display: block;
  width: 100%;
  height: auto;
  max-width: 100%;
  /* Belt and braces: the box already matches the image, so this is inert — but if
     anything ever constrains the height, `contain` letterboxes rather than cropping
     the edges off (and never distorts, which `fill` would). */
  object-fit: contain;
}

/* IMAGE hero — FIXED: full-bleed fixed-bg parallax (desktop); the figure caption
   still flows below in normal flow. The only fixed hero (Macklowe) is a 1920x1080
   image, so the 16:9 ratio box matches it; the height now scales with the width
   instead of being pinned at 1080px. */
.nr-case__hero-bg {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  background-attachment: fixed;
}

/* IMAGE hero — BOXED: inset L/R (70px desktop → ~20px mobile). Boxed heroes are
   inset product/artefact shots where the edges of the object are the point, so
   boxed NEVER crops — that behaviour now comes free from .nr-case__hero-img above
   (size-to-image), which is why there is no separate "natural" variant any more.
   .nr-hero--boxed-natural is kept only as a legacy alias so a post still holding
   that old field value keeps its inset. */
.nr-hero--boxed,
.nr-hero--boxed-natural { padding-left: clamp(20px, 5vw, 70px); padding-right: clamp(20px, 5vw, 70px); }

/* Mobile — shorter heroes; fixed→scroll fallback (background-attachment:fixed is
   unreliable on mobile); reduce the boxed inset; never exceed the viewport. */
@media (max-width: 820px) {
  .nr-case__hero { width: 100%; max-width: 100%; margin-left: 0; margin-right: 0; }
  /* The old 60vh crop box is gone: heroes keep their own ratio here too, so nothing
     is clipped on a narrow screen. The fixed-bg parallax still falls back to scroll
     (background-attachment:fixed is unreliable on mobile) and keeps its 16:9 box. */
  .nr-case__hero-bg { background-attachment: scroll; }
  /* Hero VIDEO goes true full-bleed (edge to edge) on mobile; its 16:9 ratio box
     scales with the viewport width. */
  .nr-case__hero--video {
    width: 100vw;
    max-width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
  }
}

/* ---- Figure + caption — REUSABLE convention across all case studies ----
   <figure class="nr-case-fig [nr-case-fig--full]"><img|video|iframe>
     <figcaption class="nr-case-fig__cap">CAPTION</figcaption></figure>
   Caption = .nr-label scale, centred under the media (matches the live design).
   overflow:hidden so the JS media scale-settle never spills. */
.nr-case-fig {
  margin: clamp(2rem, 5vh, 3.5rem) 0;
  overflow: hidden;
}
.nr-case-fig img,
.nr-case-fig video {
  display: block;
  width: 100%;
  height: auto;
}
.nr-case-fig iframe {
  display: block;
  width: 100%;
  max-width: 100%;
  border: 0;
}
.nr-case-fig__cap {
  margin: 1.7rem 0 0;
  font-family: var(--font-body, 'DM Sans', system-ui, sans-serif);
  font-size: 0.694rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.4;
  color: var(--colour-mid);
  text-align: center;
}
.nr-case-fig__cap a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }

/* Pier photo (Bruichladdich) — crop to 4:3 on MOBILE ONLY; keeps its wider
   ratio on desktop (fix 3). Hook class on the figure in the body. */
@media (max-width: 820px) {
  .nr-case-fig--pier img { aspect-ratio: 4 / 3; object-fit: cover; }
}

/* Near-full-bleed variant — big media (e.g. the storm/pier photo) breaks out
   almost to the viewport edges, with a small gutter so it sits JUST under full
   bleed rather than touching the edges. */
.nr-case-fig--full {
  --fig-bleed: clamp(16px, 2vw, 40px);
  width: calc(100vw - 2 * var(--fig-bleed));
  max-width: calc(100vw - 2 * var(--fig-bleed));
  margin-left: calc(50% - 50vw + var(--fig-bleed));
  margin-right: calc(50% - 50vw + var(--fig-bleed));
}
/* Caption on a full-bleed figure sits back at the content column. */
.nr-case-fig--full .nr-case-fig__cap {
  max-width: var(--content-max, 1240px);
  margin-left: auto;
  margin-right: auto;
  padding: 0.85rem var(--gutter, clamp(20px, 4vw, 64px)) 0;
}

/* BOXED in-body media — the same idea as the hero `boxed` style, applied in the
   body: the media breaks out toward the viewport but stays inset 70px each side
   (reducing on mobile), framing it. It reuses the section's NORMAL scroll-reveal
   (the block opacity/rise + media scale-settle) — NOT the hero's load rise. */
.nr-case-fig--boxed {
  --box-inset: clamp(20px, 5vw, 70px);
  width: calc(100vw - 2 * var(--box-inset));
  max-width: calc(100vw - 2 * var(--box-inset));
  margin-left: calc(50% - 50vw + var(--box-inset));
  margin-right: calc(50% - 50vw + var(--box-inset));
}
.nr-case-fig--boxed .nr-case-fig__cap {
  max-width: var(--content-max, 1240px);
  margin-left: auto;
  margin-right: auto;
  padding: 0 var(--gutter, clamp(20px, 4vw, 64px)) 0;
}

/* MOBILE — standalone figure MEDIA goes full-bleed (edge-to-edge) so it's bigger
   on small screens; this overrides the boxed inset and the --full near-bleed too.
   The caption stays IN-COLUMN (re-inset to the content width + gutter). Reuses the
   case breakpoint (820px) and the established 100vw / margin:50%-50vw helper,
   contained by .nr-case { overflow-x: clip } so there's no horizontal scroll.
   The three-up grid (.nr-case-grid) is EXCLUDED — its figures stay in their
   columns (they carry captions/titles/links and column padding). */
@media (max-width: 820px) {
  .nr-case-fig {
    width: 100vw;
    max-width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
  }
  .nr-case-fig .nr-case-fig__cap {
    max-width: var(--content-max, 1240px);
    margin-left: auto;
    margin-right: auto;
    padding-left: var(--gutter, clamp(20px, 4vw, 64px));
    padding-right: var(--gutter, clamp(20px, 4vw, 64px));
  }
  /* Reset figures INSIDE a multi-column wrapper back to their column so they keep
     content margins when the columns stack on mobile (only TRUE standalone
     full-width figures full-bleed). Wrappers: .nr-case-grid (Bruichladdich's 3-up
     maps/bottles use .nr-case-fig; Botanist §08 uses .nr-case-card, not matched at
     all) and .nr-case-split (the reusable 50/50 two-column section). */
  .nr-case-grid .nr-case-fig,
  .nr-case-split .nr-case-fig {
    width: auto;
    max-width: none;
    margin-left: 0;
    margin-right: 0;
  }
  .nr-case-grid .nr-case-fig .nr-case-fig__cap,
  .nr-case-split .nr-case-fig .nr-case-fig__cap {
    max-width: none;
    padding-left: 0;
    padding-right: 0;
  }
}

/* Figure GRID — equal columns of figures (the 3-up maps and bottle viewers).
   Each child .nr-case-fig keeps its own caption (maps) or none (bottles); the
   grid gap owns the spacing. Collapses to a single column on mobile. */
.nr-case-grid {
  display: grid;
  gap: 1.5rem;
  width: 100%;
  margin: 2.5rem 0;
  align-items: start;
}
.nr-case-grid--3 { grid-template-columns: repeat(3, 1fr); }
.nr-case-grid .nr-case-fig { margin: 0; max-width: none; }
@media (max-width: 820px) {
  .nr-case-grid--3 { grid-template-columns: 1fr; }
}

/* Richer grid card (Botanist §08) — same grid container, but each cell stacks:
   image, a label-style caption, a display title, a description, and an optional
   "view →" link pinned to the foot so cards with/without links bottom-align. */
.nr-case-card { display: flex; flex-direction: column; min-width: 0; }
.nr-case-card__img {
  width: 100%; height: auto; display: block;
  aspect-ratio: 3 / 4; object-fit: cover;   /* portrait product shots */
}
.nr-case-card .nr-label { margin: 1rem 0 0.5rem; }
.nr-case-card__title {
  font-family: var(--font-display, 'Fraunces', Georgia, serif);
  font-weight: 300;
  font-size: clamp(1.4rem, 2.2vw, 1.95rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  margin: 0 0 0.6rem;
}
.nr-case-card__desc { margin: 0 0 1.25rem; }
.nr-case-card__link {
  margin-top: auto; align-self: flex-start;
  font-family: var(--font-body, 'DM Sans', system-ui, sans-serif);
  font-size: var(--text-sm, 0.833rem);
  text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--colour-ink); text-decoration: none;
  border-bottom: 1px solid currentColor; padding-bottom: 2px;
  transition: color 0.25s ease;
}
.nr-case-card__link:hover,
.nr-case-card__link:focus-visible { color: var(--colour-mid); }

/* §08 card "View" link: the card is a flex COLUMN, so its default align-items:stretch
   sizes the link to the full column width, which makes an .nr-link hover underline
   (background-size: 100%) span the whole column. Shrink the link to its content so the
   underline is only as wide as the text and arrow. */
.nr-case-card > .nr-link,
.nr-case-card > .nr-case-card__link { align-self: flex-start; }

/* Aspect-ratio box for live iframe embeds (Sketchfab) — iframes have no
   intrinsic ratio, so the wrapper sets one and the iframe fills it. The
   iframe's own attributes/inline styles are left untouched; !important here
   only overrides leftover inline sizing so the embed fills the box. */
.nr-embed {
  position: relative;
  width: 100%;
  overflow: hidden;
  background: var(--colour-rule-light);
}
.nr-embed--landscape { aspect-ratio: 16 / 9; }   /* maps (native 1024×540) */
.nr-embed--portrait  { aspect-ratio: 3 / 4; }    /* bottles (native 640×850) */
.nr-embed iframe {
  position: absolute !important;
  inset: 0 !important;
  width: 100% !important;
  height: 100% !important;
  border: 0;
  display: block;
}

/* ------------------------------------------------------------
   HOTSPOT IMAGE — reusable: an image with pulsing, focusable markers that reveal
   a caption on hover / keyboard focus / tap (CSS only, no JS). The pulsing ring
   reuses the .nr-avail dot technique (nr-avail-pulse keyframe, in nr-header.css).
   Markers are positioned over the image by --x / --y percentages (trivial to
   nudge). Wrap in a .nr-case-fig so it inherits the global figure spacing and the
   mobile full-bleed behaviour.
   ------------------------------------------------------------ */
.nr-hotspots { position: relative; display: block; line-height: 0; }
.nr-hotspots > img { display: block; width: 100%; height: auto; }
.nr-hotspot {
  position: absolute;
  left: var(--x, 50%);
  top: var(--y, 50%);
  transform: translate(-50%, -50%);
  width: 30px; height: 30px;
  margin: 0; padding: 0;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid var(--colour-paper, #F5F3EE);
  background: rgba(14, 13, 11, 0.55);
  color: var(--colour-paper, #F5F3EE);
  font-family: var(--font-body, 'DM Sans', system-ui, sans-serif);
  font-size: 0.75rem; font-weight: 600; line-height: 1;
  cursor: pointer;
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  z-index: 1;
}
.nr-hotspot::after {
  content: "";
  position: absolute; left: 50%; top: 50%;
  width: 30px; height: 30px; border-radius: 50%;
  border: 1px solid var(--colour-paper, #F5F3EE);
  transform: translate(-50%, -50%);
  animation: nr-avail-pulse 2.8s ease-out infinite;
  pointer-events: none;
}
.nr-hotspot:hover, .nr-hotspot:focus { z-index: 3; }
.nr-hotspot__label {
  position: absolute;
  left: 50%; bottom: calc(100% + 12px);
  transform: translateX(-50%);
  width: max-content; max-width: min(16rem, 60vw);
  padding: 0.45rem 0.7rem;
  border-radius: 2px;
  background: var(--colour-ink, #0E0D0B);
  color: var(--colour-paper, #F5F3EE);
  font-family: var(--font-body, 'DM Sans', system-ui, sans-serif);
  font-size: var(--text-sm, 0.833rem);
  line-height: 1.3; letter-spacing: 0.01em;
  text-align: center;
  opacity: 0; visibility: hidden;
  transition: opacity 0.2s ease;
  pointer-events: none;
  z-index: 4;
}
/* Upper markers flip their tooltip BELOW so it never clips above the image. */
.nr-hotspot--below .nr-hotspot__label { top: calc(100% + 12px); bottom: auto; }
/* Reveal on hover, keyboard focus, and tap (plain :focus fires on touch). */
.nr-hotspot:hover .nr-hotspot__label,
.nr-hotspot:focus .nr-hotspot__label { opacity: 1; visibility: visible; }
.nr-hotspot:focus-visible { outline: 2px solid var(--colour-paper, #F5F3EE); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .nr-hotspot::after { animation: none; } }

/* ------------------------------------------------------------
   DASH LIST — body list rendered with an en-dash marker (not a disc), at the
   body text measure. Used for short technical step lists in case bodies.
   ------------------------------------------------------------ */
.nr-dash-list {
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
  max-width: var(--case-measure, 713px);
}
.nr-dash-list li {
  position: relative;
  margin: 0 0 0.65rem;
  padding-left: 1.4rem;
  font-family: var(--font-body, 'DM Sans', system-ui, sans-serif);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--colour-ink-2, var(--colour-ink));
}
.nr-dash-list li:last-child { margin-bottom: 0; }
.nr-dash-list li::before {
  content: "\2013";   /* en-dash */
  position: absolute;
  left: 0;
  color: var(--colour-mid);
}

/* ------------------------------------------------------------
   DRAM-TRAY DIAGRAM COLUMN (Dram Tray §02) — a centred diagram block: text above
   and below a slightly-inset image. 8% padding on the column reduces the image
   size; the figure allows overflow so the roll-in reveal isn't clipped. The image
   desaturates to black & white on hover (pointer-fine only).
   ------------------------------------------------------------ */
.nr-dram-diagram { padding: 8%; text-align: center; }
.nr-case-split__media.nr-dram-diagram > .nr-case-fig { margin: 2rem auto; overflow: visible; }

/* Opt-in extra breathing room above/below a full-bleed grid (Dram Tray §03). */
.nr-case-grid.nr-grid--pad50 { padding-top: 50px; padding-bottom: 50px; }

/* A figure holding a roll-in image must not clip it: the roll starts translated /
   rotated to the left and would be cut by the figure's default overflow:hidden on
   the first frame. Scoped to roll figures only; the breakout is contained by
   .nr-case { overflow-x: clip } so no horizontal scroll. */
.nr-case-fig:has(> img.nr-reveal-roll) { overflow: visible; }
.nr-dram-diagram .nr-h5 { margin: 0 0 0.4rem; }
.nr-dram-diagram p { margin: 0; }
.nr-dram-diagram img { filter: grayscale(0); transition: filter 0.5s ease; }
@media (hover: hover) and (pointer: fine) {
  .nr-dram-diagram img:hover { filter: grayscale(1); }
}

/* ---- Meta strip — full-bleed band; inner grid centres at content width.
   VARIABLE columns (4 or 7+ both lay out cleanly). ---- */
.nr-case-meta {
  /* The band's vertical size is owned by the inner min-height (200px, centred).
     The band carries the SAME generous top/bottom rhythm as .nr-case-section (the
     padding is the single source of the band height — the old 200px inner
     min-height floor is dropped so the two don't stack into a doubled gap). */
  padding-top: clamp(3.5rem, 8vw, 7rem);
  padding-bottom: clamp(3.5rem, 8vw, 7rem);
  border-top: 0.5px solid var(--colour-rule);
  background: var(--colour-rule-light, #eceae4);   /* full-width band */
}
.nr-case-meta__inner {
  max-width: var(--content-max, 1240px);
  margin: 0 auto;
  padding-left: var(--gutter, clamp(20px, 4vw, 64px));
  padding-right: var(--gutter, clamp(20px, 4vw, 64px));
  display: grid;
  grid-template-columns: repeat(4, 1fr);   /* fixed 4-col max — 7 items => 4 + 3 */
  align-content: center;
  gap: 2rem 2.5rem;                          /* row-gap / column-gap */
}
/* 4 desktop → 3 tablet → 2 small → 1 mobile; items flow in order and wrap. */
@media (max-width: 900px) { .nr-case-meta__inner { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 620px) { .nr-case-meta__inner { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 400px) { .nr-case-meta__inner { grid-template-columns: repeat(2, 1fr); } }   /* fix 4: stay 2-col at the smallest, never 1-col */

.nr-case-meta__item { display: flex; flex-direction: column; gap: 0.4rem; }
.nr-case-meta__value { font-size: var(--text-sm, 0.833rem); line-height: 1.55; color: var(--colour-ink); }

/* ---- Body — readable rhythm; the inner content carries its own .nr- classes ----
   Vertical padding is now owned by .nr-case-section (one shared rhythm); the body
   keeps only its horizontal gutter so the first/last section padding provides the
   even join to the meta strip above and Read Next below. */
.nr-case__body {
  padding-top: 0;
  padding-bottom: 0;
}
.nr-case__body > :first-child { margin-top: 0; }
.nr-case__body video,
.nr-case__body img { max-width: 100%; height: auto; display: block; }

/* ============================================================
   SECTION RHYTHM — ONE shared vertical-spacing system. Every case-study
   section (paper or coloured) carries .nr-case-section. Top == bottom so the
   page reads as an even, repeating rhythm; the join between any two sections is
   bottom-padding + top-padding (symmetric). Coloured sections add
   .nr-case-band.nr-case-band--alt for the full-bleed colour; the padding here
   sits INSIDE the colour so the band's internal breathing room matches paper.
   Scales with viewport width: spacious on desktop, tighter-but-consistent on
   mobile. Internal spacing (paragraph margins, heading→body gap, grid gaps) is
   left untouched — only section-level rhythm is unified here.
   ============================================================ */
.nr-case-section {
  padding-top: clamp(3.5rem, 8vw, 7rem);
  padding-bottom: clamp(3.5rem, 8vw, 7rem);
}
/* First/last child margins fold into the section padding (no double gap),
   two levels deep to cover the coloured band's __inner wrapper. Scoped under
   .nr-case__body so this out-specifies the element-level body rhythm rules (e.g.
   `.nr-case__body p.nr-body { margin-bottom: 1.25rem }`, 0,2,1) — otherwise a
   section ending in a paragraph kept a 20px tail and read ~132px instead of 112. */
.nr-case__body .nr-case-section > :first-child,
.nr-case__body .nr-case-section > :first-child > :first-child { margin-top: 0; }
.nr-case__body .nr-case-section > :last-child,
.nr-case__body .nr-case-section > :last-child > :last-child { margin-bottom: 0; }

/* A section whose LAST child is a full-bleed coloured band (Macklowe's points /
   embed bands) drops its own bottom padding: the band is the visual terminus, so
   the next section's top padding alone provides the single rhythm unit. Without
   this, the band sat above 112px (this pb) + 112px (next pt) = a doubled gap
   before §03 / §06 — far more than the 112px that follows the full-bleed image. */
.nr-case-section:has(> .points-band:last-child),
.nr-case-section:has(> .nr-embed-band:last-child) { padding-bottom: 0; }

/* Clip the media scale-settle (nr-case-motion.js) so the 1.06 start never
   spills or shifts layout. Aspect ratios are held by the elements themselves
   (video width/height attrs; craft img aspect-ratio), so overflow:hidden only
   masks the transient overshoot, not the resting layout. */
.nr-plp-capture,
.nr-pdp-split__media,
.nr-craft { overflow: hidden; }

/* Fix 4 — the PLP/PDP videos now use the standard .nr-case-fig structure (so they
   inherit the global mobile full-bleed). Zero only the figure's vertical margin in
   these wrappers so the DESKTOP layout is unchanged; the mobile full-bleed rule
   (which sets margin-left/right) is left free to break them out edge-to-edge. */
.nr-plp-block > .nr-case-fig,
.nr-pdp-split__media > .nr-case-fig { margin-top: 0; margin-bottom: 0; }

/* ------------------------------------------------------------
   SECTION LEAD-INS & BREAKS
   Each major section opens with a right-aligned tag paragraph:
   <p style="text-align:right"><span class="nr-section-tag">NN / Title</span></p>.
   Every section gets generous top space. Sections additionally flagged
   .nr-break open with a full-bleed hairline rule (the Enfold <hr> dividers,
   lost on shortcode strip). The rule is opt-in per section, not automatic.
   ------------------------------------------------------------ */
.nr-case__body p:has(> .nr-section-tag) {
  margin-top: 0;   /* section top space comes from .nr-case-section padding */
  margin-bottom: clamp(1.25rem, 3vh, 2rem);
}
.nr-case__body p:has(> .nr-section-tag) .nr-section-tag { margin-bottom: 0; }
.nr-case__body > p:has(> .nr-section-tag):first-child { margin-top: 0; }

/* Full-bleed divider rule above flagged sections; inner padding re-aligns the
   tag to the content column so the section number stays at the column's right
   edge while the rule itself spans the viewport. */
.nr-case__body p.nr-break:has(> .nr-section-tag) {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  padding-top: clamp(2rem, 3.5vw, 3rem);   /* generous space AFTER the divider rule, before the eyebrow (was a cramped ~1.6rem) */
  padding-left: calc((100vw - min(100vw, var(--content-max, 1240px))) / 2 + var(--gutter, clamp(20px, 4vw, 64px)));
  padding-right: calc((100vw - min(100vw, var(--content-max, 1240px))) / 2 + var(--gutter, clamp(20px, 4vw, 64px)));
  border-top: 1px solid var(--colour-rule);
  box-sizing: border-box;
}

/* A section that OPENS with a .nr-break divider needs less top padding: the
   divider itself is the boundary, and the previous section's full bottom padding
   already separates it. Without this, the divider floated under prev-pb (112) +
   this-pt (112) = ~224px — too much above §05/§07's rules (and read as excess
   bottom padding on the §06/§04 that precede them). */
.nr-case-section:has(> .nr-break:first-child) { padding-top: clamp(2.5rem, 4vw, 3.25rem); }

/* In-body rhythm. Headings carry a 25px breathing gap to their following
   paragraph; paragraphs keep a consistent bottom margin. */
.nr-case__body h2.nr-display { margin: 0; padding-bottom: 25px; }
.nr-case__body p.nr-body,
.nr-case__body p.nr-body-lg { margin-top: 0; margin-bottom: 1.25rem; }

/* Point 1 — ALL section display headings cap at a tight 16ch measure (beats the
   65ch rule below via higher specificity). */
.nr-case h2,
.nr-case__body h2.nr-display { max-width: 16ch; }

/* In-body section headings run on a 65ch measure. */
.nr-case__body .nr-display { max-width: 65ch; }
/* Headings flagged .nr-measure match the body text width (713px) instead of the
   display font's much-wider 65ch, so they wrap on the same measure as the copy
   beneath them. */
.nr-case__body h2.nr-display.nr-measure { max-width: var(--case-measure); }
/* The decisions heading matches its own intro (640px). */
.nr-decisions-header h2.nr-display { max-width: 640px; }

/* ------------------------------------------------------------
   FOUR-UP GRID — craft details + the model-viewer embeds.
   (Added on body prep; the strip had left these flat.) Row on desktop,
   2-up on tablet, stacked on mobile.
   ------------------------------------------------------------ */
.nr-grid--4 {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(1.25rem, 3vw, 2.5rem);
  /* full bleed: break out of the body column to span the viewport */
  width: 100vw;
  max-width: 100vw;
  box-sizing: border-box;
  margin: clamp(1.5rem, 4vh, 2.5rem) calc(50% - 50vw) clamp(2.5rem, 6vh, 4rem);
  padding-left: var(--gutter, clamp(20px, 4vw, 64px));
  padding-right: var(--gutter, clamp(20px, 4vw, 64px));
}
.nr-craft p { margin: 0; }
.nr-craft .nr-label { margin: 0.75rem 0 0.4rem; }
.nr-craft img { width: 100%; height: auto; display: block; aspect-ratio: 1 / 1; object-fit: cover; }
.nr-embed model-viewer { width: 100%; }     /* inline style sets the height */
.nr-embed h6 { margin: 0.75rem 0 0; }

@media (max-width: 820px) {
  .nr-grid--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 520px) {
  .nr-grid--4 { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------
   PDP SPLIT — Block B: copy on the left, portrait capture on the right
   ------------------------------------------------------------ */
.nr-pdp-split {
  display: grid;
  grid-template-columns: 2fr 1fr;   /* video (left) 2/3, copy (right) 1/3 */
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;   /* copy top-aligns with the top of the capture */
  margin: clamp(1.5rem, 4vh, 2.5rem) 0 clamp(2.5rem, 6vh, 4rem);
}
.nr-pdp-split__media video { width: 100%; height: auto; display: block; }
@media (max-width: 820px) {
  .nr-pdp-split { grid-template-columns: 1fr; gap: 1.5rem; }
}

/* ------------------------------------------------------------
   PLP CAPTURE — Block A: capped at native 1920×1200, centred, with gutters
   (explicitly NOT full bleed — stays inside the margins, scales down below
   1920). The eyebrow + video share one container so the label aligns to the
   video's left edge.
   ------------------------------------------------------------ */
.nr-plp-block {
  width: min(calc(100vw - 2 * var(--gutter, clamp(20px, 4vw, 64px))), 1920px);
  position: relative;
  left: 50%;
  transform: translateX(-50%);
  margin-block: clamp(1.5rem, 4vh, 2.5rem);
}
.nr-plp-block > .nr-label { text-align: left; margin: 0 0 0.75rem; }
.nr-plp-capture { width: 100%; }
.nr-plp-capture video { width: 100%; height: auto; display: block; }

/* ------------------------------------------------------------
   LIVE 3D EMBED — full-bleed #eceae4 band behind the lead text + models
   ------------------------------------------------------------ */
.nr-embed-band {
  width: 100vw;
  max-width: 100vw;
  margin: clamp(1.5rem, 4vh, 2.5rem) calc(50% - 50vw) clamp(2.5rem, 6vh, 4rem);
  padding: clamp(2.5rem, 6vh, 4rem) 0;
  background: var(--colour-rule-light, #eceae4);
}
.nr-embed-band__lead {
  max-width: var(--content-max, 1240px);
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--gutter, clamp(20px, 4vw, 64px));
  padding-right: var(--gutter, clamp(20px, 4vw, 64px));
}
/* The body lead otherwise inherits .nr-body's 65ch cap, which the band's auto
   margins then centre; widen it to the content column so it reads left-aligned. */
.nr-embed-band p.nr-body.nr-embed-band__lead { max-width: var(--content-max, 1240px); }
/* the grid already spans the band (which is full width); don't double-break-out */
.nr-embed-band .nr-grid--4 {
  width: auto;
  max-width: none;
  margin-left: 0;
  margin-right: 0;
  margin-bottom: 0;
}

/* ------------------------------------------------------------
   POINTS GRID — "three things 3D can do" (ported; was unstyled)
   ------------------------------------------------------------ */
/* full-bleed band; inner grid centres at content width (matches the meta strip) */
.points-band {
  width: 100vw;
  max-width: 100vw;
  margin: clamp(1.5rem, 4vh, 2.5rem) calc(50% - 50vw) clamp(2.5rem, 6vh, 4rem);
  padding: clamp(2rem, 5vh, 3.5rem) 0;
  background: var(--colour-rule-light, #eceae4);
}
.points-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
  max-width: var(--content-max, 1240px);
  margin: 0 auto;
  padding-left: var(--gutter, clamp(20px, 4vw, 64px));
  padding-right: var(--gutter, clamp(20px, 4vw, 64px));
}
.point {
  border-top: 2px solid var(--colour-rule, #d9d6cf);
  padding-top: 1rem;
  font-family: var(--font-body, 'DM Sans', system-ui, sans-serif);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--colour-ink-2);
}
.point-num {
  font-size: 0.812rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--colour-ink);
  margin-bottom: 1rem;
}
@media (max-width: 720px) {
  .points-grid { grid-template-columns: 1fr; }
}

/* ------------------------------------------------------------
   DESIGN DECISIONS — list LAYOUT (ported; text classes live in nr-type.css)
   ------------------------------------------------------------ */
/* §04 now carries .nr-case-section, which owns the top/bottom rhythm. No bespoke
   padding here — a `padding` shorthand would override the section's clamp. The
   inner (.nr-decisions-inner) handles width; horizontal padding isn't needed. */
.nr-decisions-inner { max-width: 1180px; margin: 0 auto; position: relative; }
/* No width cap on the header so the nr-display heading stays on one line; the
   intro keeps its own 640px measure (nr-type). */
.nr-decisions-header { margin-bottom: clamp(2rem, 5vh, 3.5rem); }
.nr-decisions-list { list-style: none; padding: 0; margin: 0; }
.nr-decisions-list .nr-decision {
  display: grid;
  grid-template-columns: 60px 280px 1fr;
  gap: 2rem;
  padding: 1.75rem 0;
  border-top: 1px solid var(--colour-rule);
  align-items: baseline;
  margin: 0;
}
.nr-decisions-list .nr-decision:last-child { border-bottom: 1px solid var(--colour-rule); }
.nr-decisions-list .nr-decision::before,
.nr-decisions-list .nr-decision::marker { content: none; display: none; }

@media (max-width: 960px) {
  .nr-decisions-list .nr-decision { grid-template-columns: 48px 1fr; gap: 0.75rem 1.5rem; }
  .nr-decision-title { grid-column: 2; }
  .nr-decision-desc { grid-column: 2; margin-top: 0.75rem; max-width: none; }
}
@media (max-width: 600px) {
  .nr-decisions-list .nr-decision { grid-template-columns: 1fr; gap: 0.5rem; }
  .nr-decision-title, .nr-decision-desc { grid-column: 1; }
}

/* ------------------------------------------------------------
   BLOCK EYEBROWS — Block B / Block C take a larger lead-in above their media
   so each capture reads as its own beat.
   ------------------------------------------------------------ */
.nr-case__body p.nr-label:has(+ .nr-pdp-split),
.nr-case__body p.nr-label:has(+ p + .nr-craft-grid) { padding-top: 100px; }

/* ------------------------------------------------------------
   THREE HONEST GAPS — the gaps use bare .nr-decision-num/title/desc stacked as
   direct children of §06's .nr-case-section (not the .nr-decisions-list grid in
   §04, which is nested and so never matches these `>` rules). Style them as a
   stacked list: a content-width rule + real space above each gap, and above the
   closing "What I'd do differently" paragraph.
   ------------------------------------------------------------ */
.nr-case-section > .nr-decision-num {
  display: block;
  margin-top: clamp(2.5rem, 5vh, 3.5rem);
  padding-top: clamp(2rem, 4vh, 3rem);
  border-top: 1px solid var(--colour-rule);
  max-width: var(--case-measure);   /* rule spans the body text measure, not the
                                       narrow 65ch of its own small mono font */
}
.nr-case-section > .nr-decision-title { margin: 0.75rem 0; max-width: var(--case-measure); }
.nr-case-section > .nr-decision-desc { margin: 0; max-width: var(--case-measure); }
.nr-case-section > .nr-decision-desc + p.nr-body {
  margin-top: clamp(2.5rem, 5vh, 3.5rem);
  padding-top: clamp(2rem, 4vh, 3rem);
  border-top: 1px solid var(--colour-rule);
}

/* ------------------------------------------------------------
   READ NEXT — dark band, full-width, inner content column
   ------------------------------------------------------------ */
.nr-readnext {
  /* No top margin: the last section's bottom padding already provides the gap, and
     this band has its own generous inner padding. The old margin stacked on top of
     the section pb (~112 + ~92 = ~200px) — a doubled, excessive bottom gap. */
  margin-top: 0;
  background: var(--colour-rule-light, #eceae4);
}
.nr-readnext__inner {
  max-width: var(--content-max, 1240px);
  margin: 0 auto;
  padding: clamp(3rem, 8vh, 6rem) var(--gutter, clamp(20px, 4vw, 64px));
}
.nr-readnext__heading {
  margin: 0.5rem 0 1rem;
  font-family: var(--font-display, 'Fraunces', Georgia, serif);
  font-weight: 300;
  font-size: clamp(1.3rem, 2.2vw, 1.728rem);
}

/* ============================================================
   TARGETED SECTION FIXES — full-bleed bands, 50/50 splits, dividers,
   full-bleed map grid + video. All 100vw breakouts are contained by
   .nr-case { overflow-x: clip } so no horizontal scrollbar appears.
   ============================================================ */

/* Full-bleed band — breaks the content column out to the viewport edges.
   --alt paints the alternate #ECEAE4 background; __inner re-centres text at the
   content column. (Points 2, 6, 7.) */
.nr-case-band {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  /* vertical rhythm is owned by .nr-case-section (coloured sections carry both
     classes); the band itself only handles the full-bleed breakout + colour */
}
.nr-case-band--alt { background: var(--colour-rule-light, #ECEAE4); }
.nr-case-band__inner {
  max-width: var(--content-max, 1240px);
  margin: 0 auto;
  padding-left: var(--gutter, clamp(20px, 4vw, 64px));
  padding-right: var(--gutter, clamp(20px, 4vw, 64px));
}
.nr-case-band__inner > :first-child { margin-top: 0; }
.nr-case-band__inner > :last-child { margin-bottom: 0; }
/* A grid placed directly in a band spans the full band width (gutters only);
   symmetric margin gives even internal space above AND below it. */
.nr-case-band > .nr-case-grid {
  width: 100%;
  margin: clamp(1.5rem, 4vh, 2.5rem) 0;
  padding-left: var(--gutter, clamp(20px, 4vw, 64px));
  padding-right: var(--gutter, clamp(20px, 4vw, 64px));
  box-sizing: border-box;
}

/* Full-bleed 1px hairline divider (points 10, 11). */
.nr-case-divider {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  height: 0;
  border: 0;
  border-top: 1px solid var(--colour-rule, #D9D6CF);
}

/* Mobile — an alt band already separates itself with its own background, so a
   hairline immediately either side of it reads as a stray rule. The :has()
   selector covers the divider before a band, since CSS has no previous-sibling
   combinator. 820px matches this stylesheet's mobile breakpoint. */
@media (max-width: 820px) {
  .nr-case__body .nr-case-band--alt + .nr-case-divider,
  .nr-case__body .nr-case-divider:has(+ .nr-case-band--alt) {
    display: none;
  }
}

/* Two-column 50/50 split (media | text); stacks on mobile.
   --media-left puts the media column first. (Points 3, 8, 9-adjacent, 11.) */
.nr-case-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
  margin: clamp(1.5rem, 4vh, 2.5rem) 0;
}
.nr-case-split__text > :first-child { margin-top: 0; }
.nr-case-split__media { margin: 0; }
.nr-case-split__media > .nr-case-fig { margin: 0; }
.nr-case-split__media img,
.nr-case-split__media video { width: 100%; height: auto; display: block; }
/* a portrait phone capture shouldn't blow up to half the page — cap it (point 8) */
.nr-case-split--portrait .nr-case-split__media { justify-self: center; }
.nr-case-split--portrait .nr-case-split__media > * { max-width: 380px; margin-inline: auto; }
/* Vertically centre a split's columns on the cross axis (fixes A, H). */
.nr-case-split--center { align-items: center; }
/* Full-bleed split — the two columns span the viewport, gutters preserved (fix G).
   Contained by .nr-case { overflow-x: clip } so no horizontal scrollbar. */
.nr-case-split--bleed {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  box-sizing: border-box;
  padding-left: var(--gutter, clamp(20px, 4vw, 64px));
  padding-right: var(--gutter, clamp(20px, 4vw, 64px));
}
@media (max-width: 820px) {
  .nr-case-split { grid-template-columns: 1fr; gap: 1.5rem; }
}

/* Full-bleed maps grid (point 2): 3 columns spanning the viewport; each map
   fixed 540px tall on desktop, 1:1 square single-column on mobile. */
.nr-embed--map { aspect-ratio: auto; height: 540px; }
@media (max-width: 820px) {
  .nr-embed--map { height: auto; aspect-ratio: 1 / 1; }
}

/* Full-bleed video (point 9) — edge to edge like the hero, 16:9 ratio box. */
.nr-case-video--full {
  width: 100vw;
  max-width: 100vw;
  margin: clamp(2.5rem, 6vh, 4rem) calc(50% - 50vw);
}
.nr-case-video--full video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}
.nr-case-video--full .nr-case-fig__cap {
  max-width: var(--content-max, 1240px);
  margin: 0.85rem auto 0;
  padding: 0 var(--gutter, clamp(20px, 4vw, 64px));
}
