/* ── 7Mind Case Study ────────────────────────────────────────────── */
/* Mirrors report.css's structure (page-specific layout only; skin for
   shared components — .card, .stats, .annotation-card, .section-eyebrow,
   the heading/body type scale — lives in style.css). All asset slots on
   this page are still placeholders (see .mind-placeholder) — swap in
   real exports without touching layout. */

/* ── HERO ────────────────────────────────────────────────────────── */
.mind-hero {
  /* position: relative (no z-index) keeps this a containing block for
     the .bg-blob child's top/left% without giving it its own stacking
     context — that child's z-index:-1 needs to resolve against .page's
     SHARED context (style.css) so every case study's blobs paint in
     one single behind-everything layer, not get trapped in isolated
     per-section contexts where a blob big enough to bleed past its own
     box could paint over an earlier sibling's content instead of
     staying behind it. overflow: hidden below is what actually keeps
     this particular blob contained to the hero. */
  position: relative;
  overflow: hidden;
  /* No background of its own (body's own background-color already
     supplies this off-white) — same reasoning as .mind-pull-quote/
     .mind-hifi-row above: an opaque background here would paint over
     the shared .bg-blob layer (z-index:-1, resolved against .page's
     one stacking context, not a local one — see the note above) rather
     than letting it show through. */
  /* Tucks under the fixed nav (paired with .nav-overlay, transparent
     until scrolled — see style.css) instead of sitting in the gap
     .page's padding-top reserves for it: margin-top cancels that
     padding so the hero's own top edge — and its gradient background
     with it — reaches the true page top, and padding-top gains that
     same nav-h back so the actual content (.mind-hero-top) still
     clears the nav by exactly the original 96px, unchanged. */
  margin-top: calc(-1 * var(--nav-h));
  padding: calc(96px + var(--nav-h)) var(--side-pad) 0;
  /* Plain min-height + max-height doesn't cap this on tall viewports —
     per spec, when a computed min-height exceeds max-height, min-height
     wins outright, so a bare `max-height: 746px` alongside this
     min-height would get silently ignored above ~810px tall (746 +
     var(--nav-h)). min() picks the smaller of the two itself, so the
     746px ceiling actually holds. Both operands are bumped by var(--nav-h)
     over the plain "hero fills the viewport below the nav, capped at
     746px" formula — the hero now starts nav-h higher (true page top,
     not just below the nav), so it needs that much more height to reach
     the exact same bottom edge (the viewport bottom) as before. */
  min-height: min(100vh, calc(746px + var(--nav-h)));
  display: flex;
  flex-direction: column;
}
/* Sizes/positions exactly the Figma hero frame's own 1512×746 band
   (node 1314:44729) within .mind-hero's now-taller box — inset's top
   skips the nav-h slice tucked under the nav, so a percentage-
   positioned .bg-blob child inside can use the node's own coordinates
   directly (e.g. left/top below) instead of re-deriving them against
   .mind-hero's full height. */
.mind-hero-blob-zone {
  position: absolute;
  inset: var(--nav-h) 0 0 0;
}
.mind-hero-top {
  max-width: var(--max-w);
  margin: 0 auto;
  width: 100%;
  display: grid;
  /* Even 50/50 split (.mind-hero-left's own max-width matches) instead
     of the old fixed 495px/1fr — both minmax(0, ...) so neither track
     grows past its half share to fit content, letting each side's own
     max-width/min-width (mockup included) overflow instead if it ever
     needs to. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 64px;
  /* center (not start) — .mind-hero-left has no explicit height, so
     this is what actually centers it within the row's full height
     (itself set by .mind-hero-right's height: 100%, stretched off
     .mind-hero-top's own flex: 1 height). .mind-hero-right is
     unaffected either way since its explicit height already fills the
     row regardless of align-items. */
  align-items: center;
  flex: 1;
}
/* .mind-hero-left needs no max-width of its own — a grid item stretches
   to fill its track by default, and the track itself is already
   exactly 50% (grid-template-columns above), so that's the effective
   cap already. (A max-width set here directly would be a PERCENTAGE OF
   THE TRACK, not of .mind-hero-top — grid items resolve % against
   their own grid area, not the container — so e.g. max-width: 50%
   here would actually mean 25% of .mind-hero-top, half of what it
   looks like it says.)
   Even 20px gap across all 3 hero text bits (eyebrow → title →
   subtitle) — .mind-title's margin matches .mind-tag's instead of its
   old 24px. .mind-tag and .mind-opener both override their shared
   component's default muted color (.section-eyebrow's and .body-big's
   own --mid/--black) to the warmer --brown instead, in step with the
   hero's own warm gradient. */
.mind-tag { margin-bottom: 20px; color: var(--brown); }
.mind-title { margin-bottom: 20px; }
.mind-opener { max-width: 480px; color: var(--brown); }
.mind-hero-right {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  height: 100%;
}
.mind-hero-mockup {
  width: 100%;
  max-width: 320px;
  aspect-ratio: 375 / 760;
  margin-bottom: -74px; /* bleeds past the hero's bottom edge, clipped by overflow:hidden above */
}

/* ── META ROW ────────────────────────────────────────────────────── */
/* Matches CleanHub's own .ch-meta-row (report.css) — no divider line,
   just a plain top gap (there, a 64px flex-gap + 24px padding-top,
   since it's a flex sibling of .ch-hero-top inside .ch-hero itself;
   here margin-top stands in for that flex-gap since .mind-meta-row
   stays a plain block sibling AFTER </header>, not nested inside it —
   .mind-hero's own fixed height/overflow:hidden deliberately crops the
   mockup image at several breakpoints this session, and nesting this
   row inside would make it share that same fixed budget, squeezing or
   clipping it). Bottom padding (56px) is 7Mind's own existing rhythm
   into the Overview section below — CleanHub has no equivalent to
   match there. */
.mind-meta-row {
  /* --max-w-outer + side-pad-in-padding (not --max-w + margin: auto
     alone) — same pattern .mind-body uses: this row sits outside
     .mind-hero, so it needs its OWN side-pad inset (.mind-hero-top's
     side margins come from .mind-hero's own padding, which this row
     never inherits) to keep clear of the page edge below --max-w-outer,
     while still landing on the same --max-w content width above it. */
  max-width: var(--max-w-outer);
  margin: 64px auto 0;
  width: 100%;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px 40px;
  padding: 24px var(--side-pad) 56px;
}
.mind-meta-label { margin-bottom: 8px; }

/* ── PLACEHOLDER MEDIA ───────────────────────────────────────────── */
/* Same idea as .ch-placeholder-media (report.css) — flagged here as a
   candidate to promote into a shared component if a third case study
   needs it too. */
.mind-placeholder {
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, #e8e4de 0%, #d8d2ca 100%);
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 16px;
}
/* Every placeholder also carries .frame (style.css) for the glass-card
   treatment real screens get in Figma's own "Image frame" component —
   .frame targets an <img>/<video> child for its own border-radius, but
   its ::before bleed (the actual glow/shadow) doesn't need one, so it
   renders around a plain placeholder div just as well. --frame-radius
   is overridden to match this element's own 12px (24px on the hero)
   so the bled halo's curve lines up with the placeholder's corner
   instead of the component's unrelated 8px default. */
.mind-placeholder.frame { --frame-radius: 12px; }
.mind-placeholder span {
  font-family: var(--font-sans);
  font-size: 12px;
  line-height: 1.5;
  color: var(--mid);
  opacity: 0.7;
}
.mind-placeholder--phone {
  aspect-ratio: 375 / 780;
  max-width: 280px;
  margin: 0 auto;
}
.mind-placeholder--wide { aspect-ratio: 16 / 7; }
.mind-placeholder--diagram { aspect-ratio: 16 / 10; }

/* Real hero screenshot (replaces the old .mind-placeholder there) —
   .frame still supplies the glass-card halo via its ::before, just
   sized to this 16px corner instead of the component's 8px default
   (border-radius is .frame's own box; --frame-radius matches it on
   the wrapped <img>; --frame-bleed keeps the halo's outer curve the
   same 16px past that, so both arcs share one center point instead of
   reading as a ring of uneven thickness — see .frame's own note in
   style.css). The image itself fills .mind-hero-mockup's own
   fixed-aspect box. */
.mind-hero-mockup .frame {
  /* Without an explicit height, .frame (plain block, no % height of
     its own) shrink-wraps to whatever height its img content resolves
     to — and the img's own height: 100% has no definite ancestor to
     resolve against (.frame's is auto), so per spec it falls back to
     the *image file's own* intrinsic aspect ratio (856:1852) instead
     of .mind-hero-mockup's intended 375:760 box, stretching the whole
     mockup well past its meant-to-be height. height: 100% here gives
     .frame a genuinely definite size to resolve against (.mind-hero-
     mockup's own aspect-ratio, which is exactly why that property is
     there) — the img's height: 100% then resolves against THIS instead,
     letting object-fit: cover crop the source image to the intended box
     rather than the box stretching to fit the source image. */
  height: 100%;
  border-radius: 16px;
  --frame-radius: 16px;
  --frame-bleed: 16px;
}
.mind-hero-mockup-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The source PNG's own aspect ratio (856:1852) isn't quite this box's
     (375:760), so cover always has ~44px to crop somewhere — default
     center position split that evenly top/bottom, eating into the
     phone's rounded top bezel. This mockup already bleeds off the
     bottom on purpose (.mind-hero-mockup's own negative margin-bottom),
     so top keeps the crop there too instead of splitting it, showing
     the phone's top intact. */
  object-position: top;
}

.mind-media-label {
  margin-bottom: 12px;
  display: block;
}
/* ── BODY ────────────────────────────────────────────────────────── */
.mind-body {
  max-width: var(--max-w-outer);
  margin: 0 auto;
  padding: 0 var(--side-pad) 120px;
}
.mind-section { margin-top: 100px; }
.mind-section-label { margin-bottom: 12px; }
.mind-h2 { margin-bottom: 24px; }
.mind-prose-col { max-width: var(--content-w); }
.mind-p { margin-bottom: 20px; max-width: var(--content-w); }
.mind-p:last-child { margin-bottom: 0; }

/* Sub-headings nested inside a .mind-section (mirrors .ch-iteration-title).
   Top/bottom only (not the margin shorthand) — every use of these pairs
   with .section-narrow for its 800px centering (margin-left/right:auto),
   and the shorthand's implicit "0" for the unset sides would win over
   that (same specificity, declared later in the cascade), pinning the
   element flush left at full width instead of centering it. */
.mind-iteration-title { margin-top: 80px; margin-bottom: 20px; }
.mind-sub-title { margin-top: 40px; margin-bottom: 12px; }

/* ── MEDIA ROW (text left / media right — IA changes, Library/Home/
   Search sub-blocks) ────────────────────────────────────────────── */
.mind-media-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 460px);
  gap: 56px;
  align-items: start;
  margin: 56px 0 32px;
}
/* Narrow variant — the Problem section's single-paragraph-plus-screen
   intro reads as a continuation of the surrounding .section-narrow
   prose, not a wide two-column layout like the Process section's
   text+diagram rows, so it gets the same 800px cap, a bigger gap, and
   the paragraph centered against the (taller) image instead of
   top-aligned. */
.mind-media-row--narrow {
  /* 280px instead of the base rule's 460px cap: matches the phone
     screenshot's own intended size, not a wider diagram's. min(...,
     50%) keeps that 280px cap as long as there's room for it, but
     stops the column from ever taking more than half the row — once
     the row itself is narrow enough that half of it is under 280px,
     the column (and the image filling it, width: 100%) scales down
     from there instead of forcing the text column to keep shrinking
     to make room for a fixed 280px. The .frame glow is allowed to
     bleed past this into the gap (its documented zero-footprint
     behavior), same as everywhere else .frame is used — the column
     isn't padded out to cover it. */
  grid-template-columns: minmax(0, 1fr) min(280px, 50%);
  max-width: var(--content-w);
  margin-left: auto;
  margin-right: auto;
  /* 100px before "The behavioral data was just as telling:" — the
     section-level gap, since this row closes out the intro and the
     stats are a fresh beat. Top stays the inherited 56px. */
  margin-bottom: 100px;
  gap: 80px;
  align-items: center;
}

/* ── STATS (3 items, problem section) ─────────────────────────────
   Columns/gap/padding come from the shared .stats component now
   (style.css, auto-fit + minmax(200px)) — wraps on its own, no
   breakpoint needed here. Only the row's own placement stays
   page-specific. */
.mind-stats {
  max-width: var(--content-w-md);
  /* Top stays 40px (gap from the "telling:" lead-in right above); the
     100px is only needed after, into the use-case-map row below. */
  margin: 40px auto 100px;
}

/* ── BULLETS ─────────────────────────────────────────────────────── */
.mind-bullets {
  list-style: none;
  /* Top/bottom only — see .mind-iteration-title's note above, same trap
     with .section-narrow (used everywhere this list appears in Outcome,
     and most of Process). */
  margin-top: 12px;
  margin-bottom: 20px;
  max-width: var(--content-w);
}
.mind-bullets li {
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  color: var(--black);
  font-weight: 400;
  padding: 8px 0 8px 20px;
  position: relative;
}
.mind-bullets li::before {
  content: '•';
  position: absolute;
  left: 0;
  color: var(--black);
}
.mind-bullets li b,
.mind-bullets li strong {
  color: var(--black);
  font-weight: 600;
}

/* Plain disc list continuing a prose paragraph (e.g. the Problem
   section's use-case synthesis) — distinct from .mind-bullets, which
   is a divided list of bold-label lines, not a running-text list.
   Pairs with .body-regular for type, matching the surrounding .mind-p
   paragraphs exactly. */
.mind-plain-list {
  list-style: disc;
  padding-left: 24px;
  margin: -4px 0 20px;
}
.mind-plain-list li { margin-bottom: 4px; }
.mind-plain-list li:last-child { margin-bottom: 0; }

/* ── PROBLEM: STICKY CARDS + ANNOTATED SCREENS ─────────────────────
   Sticky left cards stay pinned (no fade, no 1:1 pairing with a given
   screen) while the right column's three screens scroll past — per
   Figma node 1176:42714. They use the shared .card--compact variant
   (style.css, per node 1258:34564) rather than full-size .card —
   without it, 3 full-size cards stacked don't fit a normal viewport
   height while sticky. */
.mind-sticky-scroll {
  display: grid;
  grid-template-columns: minmax(0, 300px) 1fr;
  gap: 64px;
  margin-top: 40px;
  /* This is the single tallest, densest block on the page (3 cards +
     3 annotated screens, several thousand px of scroll) — 56px (the
     "big block" tier .mind-media-row--narrow/.mind-pull-quote use)
     rendered correctly but read as imperceptible after that much
     scroll distance. Bumped to the "major section break" tier
     (.mind-section's own margin-top, .ch-section's in report.css)
     for a separation unambiguous enough to register after it. */
  margin-bottom: 100px;
}
.mind-sticky-left {
  position: sticky;
  top: calc(var(--nav-h) + 40px);
  height: fit-content;
  align-self: start;
}
.mind-sticky-cards {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.mind-sticky-right {
  display: flex;
  flex-direction: column;
  gap: 56px;
}

/* ── SHOT CANVAS (screen + pointing annotations) ───────────────────
   CleanHub's .ch-shot-canvas method (report.css/report.js), ch-
   renamed to mind- — not reinvented: a canvas with a fixed height
   (required since every child below is positioned absolutely, which
   on its own gives the canvas zero intrinsic height) holds a
   positioned screen and positioned annotation cards; connector lines
   are SVG, drawn by JS from each annotation's actual rendered edge to
   a target point, redrawn on resize/font-load/reveal. All annotations
   here are the negative/red variant only (no solution counterpart),
   so — unlike CleanHub's neutral-gray lines, deliberately restrained
   since it draws both variants — the line itself carries the same
   red, matching the reference design.

   All three canvases use a literal fixed height (not aspect-ratio),
   with the screen and every annotation a fixed px width centered via
   left: calc(50% ± Npx) — the free space around them compresses first
   as the viewport narrows, and the content itself doesn't shrink
   until that space runs out. A fixed canvas height also decouples
   each annotation's top:% from the canvas's own width — without it,
   screen 1's two stacked left annotations would have started
   overlapping well before the layout actually ran out of horizontal
   room, since their gap would have been shrinking right along with
   the width. data-target-cx/-cy (fixed px offset from canvas center,
   vs. -x/-y's percentage of canvas size) is what keeps a connector
   line aligned with this fixed-px content as the canvas resizes —
   see mind.js. Screen 1's phone matches screens 2 & 3's width (250px)
   so all three read as the same size while scrolling between them. */
.mind-shot-canvas {
  position: relative;
  width: 100%;
}
.mind-shot-img { position: absolute; }
.mind-shot-img.mind-placeholder--phone { max-width: none; margin: 0; }
.mind-shot-annotation {
  position: absolute;
  max-width: none;
}
/* Reveal: translateX slide (mirrors .ch-reveal) — kept distinct from
   the page's general .mind-reveal (translateY fade) used elsewhere,
   since mind.js's scroll-reveal branches on which class an element
   carries and the two motions shouldn't mix on the same element. */
.mind-shot-reveal {
  opacity: 0;
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.mind-shot-reveal[data-direction="right"] { transform: translateX(-16px); }
.mind-shot-reveal[data-direction="left"] { transform: translateX(16px); }
.mind-shot-reveal.is-visible { opacity: 1; transform: translateX(0); }
.mind-shot-lines {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  overflow: visible;
}
.mind-shot-lines line { stroke-width: 1; stroke: var(--red); }
.mind-shot-lines circle { fill: var(--red); }
/* Line + dot fade in only once their annotation's own reveal
   transition actually ends (see revealMindShotLine in mind.js) —
   tracked via data-line-revealed rather than the annotation's own
   is-visible, which flips on well before the slide settles. */
.mind-shot-line-item { opacity: 0; transition: opacity 0.5s ease; }
.mind-shot-line-item.is-visible { opacity: 1; }

/* ── PULL QUOTE / DESIGN CHALLENGE ─────────────────────────────────
   Same component as .ch-pull-quote (report.css) — border, padding,
   margin, and type all reconciled to match it exactly. The one
   deliberate difference: width: fit-content instead of stretching to
   fill --content-w-md. .ch-pull-quote's sentences run long enough to
   want that full width; this page's is a single short sentence, and
   letting it stretch left a lot of empty box around short text, so it
   hugs the sentence instead — max-width stays only as a safety cap for
   a narrower viewport or a longer sentence than today's. margin: auto
   centers the (now not full-width) box horizontally. */
.mind-pull-quote {
  border: 1px solid var(--neutral-border);
  border-radius: 10px;
  padding: 48px 72px;
  margin: 200px auto;
  max-width: var(--content-w-md);
  width: fit-content;
  /* position: relative (no z-index) — a containing block for the
     .bg-blob child's top/left%, but its z-index:-1 needs to resolve
     against .page's ONE shared stacking context (style.css), not a
     context scoped to just this box (see .page's own note on why). */
  position: relative;
}
.mind-pull-quote-label { margin-bottom: 15px; }
/* Layout only — pairs with .h2-section for type. color is a legitimate
   override: .h2-section defaults to --black, but a pull quote wants the
   warmer --dark-brown. */
.mind-pull-quote-text {
  color: var(--dark-brown);
  margin: 0;
}

/* ── SPLIT ROW (text capped at 420px beside one image) ─────────────
   Shared by the "From IA to interface" Library/Home/Search write-ups
   and the hi-fi mockup cluster below — text column capped at 420px,
   image column flexible, side by side above 900px, stacked at or
   below it (see the ≤900px block). margin-top defaults to 40px, the
   .mind-sub-title value it's standing in for: each heading's own top
   margin moves to the row instead (reset to 0 below), so the row's
   margin is what collapses with whatever precedes it — exactly as the
   heading's own margin used to when it was a plain block-flow sibling
   of the old .mind-media-row, rather than adding on top of a non-
   collapsing grid-item margin now that it's nested inside the row.
   .mind-hifi-row overrides this to 80px for its own .mind-iteration-
   title. margin-bottom is shared as-is; it still collapses normally
   with whatever plain block-flow sibling follows the row. */
.mind-split-row {
  display: grid;
  grid-template-columns: minmax(0, 420px) minmax(0, 1fr);
  gap: 64px;
  align-items: start;
  margin-top: 40px;
  margin-bottom: 32px;
}
/* Modifier for wherever a row needs the section-level 80px gap above
   it instead of the default 40px (e.g. the first row after a heading,
   or — in "Proposed IA changes" — between Library and Home too). */
/* position: relative (no z-index) — a containing block for a .bg-blob
   child's top/left% (only the Library redesign row actually carries
   one; harmless on the other two instances), but its z-index:-1 needs
   to resolve against .page's ONE shared stacking context (style.css),
   not a context scoped to just this row. */
.mind-split-row--lead { margin-top: 80px; position: relative; }
/* Symmetric modifier for the section-level 80px gap below instead of
   the default 32px — the use-case-map row closes out the intro right
   before the "three connected problems" sticky-scroll, which reads as
   a big enough beat to warrant it. */
.mind-split-row--trail { margin-bottom: 80px; }
.mind-split-text .mind-sub-title,
.mind-split-text .mind-iteration-title {
  margin-top: 0;
}
/* .mind-split-text/.mind-split-media carry no rules of their own — a
   grid item stretches to fill its column (capped at 420px for text)
   by default. None of these composites gets a .mind-media-label
   eyebrow — each already bakes its own label(s) in. Most also bake in
   their own shadow, so skip .frame entirely; the "Proposed IA
   changes" diagrams are the exception (flat, no shadow of their own),
   so they alone use it, plus .frame--flush (see style.css) so the
   glass border sits flush against the diagram's own edge instead of
   the usual 8px halo past it, which read as unwanted padding around a
   diagram this size. */
.mind-split-image {
  display: block;
  width: 100%;
  height: auto;
  max-width: var(--content-w-md);
  margin: 0;
}

/* ── HI-FI MOCKUP CLUSTER (.mind-split-row instance) ────────────── */
/* position: relative (no z-index) — a containing block for the
   .bg-blob child's top/left%, but its z-index:-1 needs to resolve
   against .page's ONE shared stacking context (style.css), not a
   context scoped to just this row — see .page's own note on why:
   this row's blob is large/blurred enough to bleed past its own box,
   and giving this row its own z-index would let that bleed paint OVER
   the previous row's content instead of staying behind it. */
.mind-hifi-row { margin-top: 80px; position: relative; }

/* ── MEASURING SUCCESS GRID ──────────────────────────────────────── */
/* 6 tracks (not 3) so the trailing row — 5 cards means row 2 holds
   just the last 2 — can be centered rather than left-hugging: each
   card spans 2 tracks (3 full-width cards fill all 6), and cards 4-5
   are each shifted one track right, landing on tracks 2-3 and 4-5 and
   leaving track 1 and 6 empty in equal measure. This placement is
   pinned to today's exact count of 5 cards — revisit the nth-child
   rules below if a card is added or removed. */
.mind-measure-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 32px;
  max-width: var(--content-w-md);
  margin: 32px auto;
}
/* Heading (h3-serif, 32/40), body (body-regular) and padding (24px)
   are already .card's own shared defaults — nothing to override here.
   Gap between title and body also now matches that 12px default; kept
   explicit since this is the one place that spec is pinned by name. */
.mind-measure-grid .card { grid-column: span 2; gap: 12px; }
.mind-measure-grid .card:nth-child(4) { grid-column: 2 / span 2; }
.mind-measure-grid .card:nth-child(5) { grid-column: 4 / span 2; }

/* ── SCROLL REVEAL ───────────────────────────────────────────────── */
.mind-reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.mind-reveal.is-visible { opacity: 1; transform: translateY(0); }

/* ── RESPONSIVE ──────────────────────────────────────────────────── */
/* .mind-media-row's only surviving use is .mind-media-row--narrow (the
   Problem section's intro) — its 280px-fixed phone column has plenty
   of room to shrink before the row needs to stack, so it holds the
   2-column layout all the way down to 600px instead of the general
   1100px tier. */
@media (max-width: 699px) {
  /* --narrow's 80px gap (vs. the base rule's 56px) is sized for the
     wider desktop column, not this cramped a track — below 700px it
     just falls back to that plain 56px default. */
  .mind-media-row--narrow { gap: 56px; }
}
@media (max-width: 600px) {
  .mind-media-row { grid-template-columns: 1fr; gap: 56px; }
  /* Stacked, the grid's own 56px gap is meant to be the whole visible
     gap — .mind-p's usual 20px margin-bottom would otherwise add on
     top of it (margin and grid gap both apply, they don't collapse
     into each other), since this paragraph isn't :last-child here. */
  .mind-media-row--narrow .mind-p {
    margin-bottom: 0;
  }
  /* Capped at 260px and centered — target the .frame wrapper itself,
     not just the image inside it, so the glow shrinks and re-centers
     along with the visible image instead of staying stretched to the
     stacked column's full width around a now-smaller, off-center
     picture. */
  .mind-media-row--narrow .frame {
    max-width: 260px;
    margin: 0 auto;
    /* Image above the text at this breakpoint — order (not a DOM
       reorder) so reading/tab order stays text-then-image. */
    order: -1;
  }
}
/* Tier 2 (901-1400px): the sticky cards + sticky-left column stay
   exactly as they are at desktop width (nothing here touches
   .mind-sticky-scroll/.mind-sticky-left) — only .mind-shot-canvas
   changes, from the absolute-positioned fixed-px overlay (which has
   nowhere near enough margin to give below ~1400px — confirmed
   overlapping the sticky cards by 12px at 1330px) to a plain 2-column
   grid: annotations stacked in column 1, screen in column 2, ordinary
   grid flow instead of position:absolute. A normal grid track can't
   spill into a neighboring column the way fixed-px absolute content
   could, so this is what actually removes the overlap risk rather
   than just moving it — the sticky cards can safely stay sticky
   because nothing on the right can bleed into them anymore.
   Screen 1's 3 annotations (data-target-cx's branching line included)
   fall back to reading top-to-bottom as plain stacked cards — the
   connector lines are a desktop-only device, same as always below a
   breakpoint. */
@media (max-width: 1400px) and (min-width: 901px) {
  .mind-shot-canvas {
    /* Stays relative (not static) — the .mind-shot-lines SVG overlay is
       position:absolute and needs the canvas as its positioning
       context, same as at desktop width, now that screen 1's first two
       annotations keep their connector line in this tier too. */
    position: relative;
    height: auto !important;
    aspect-ratio: unset !important;
    display: grid;
    /* Column 1 caps at the annotation's own max-width (420px) instead
       of 1fr — 1fr filled all remaining canvas width, so once the
       annotation hit its cap the leftover just sat as dead space
       inside the column (annotation stranded far from the image)
       instead of becoming outer margin. justify-content:center then
       centers the (annotations + gap + image) pair as a unit within
       the canvas, splitting that leftover evenly on both sides —
       matching how the desktop tier's screens 2/3 read. */
    grid-template-columns: minmax(0, 420px) minmax(160px, 260px);
    justify-content: center;
    gap: 24px;
    align-items: center;
  }
  .mind-shot-img {
    position: static !important;
    left: auto !important;
    top: auto !important;
    width: 100% !important;
    height: auto !important;
    grid-column: 2;
    grid-row: 1;
  }
  .mind-shot-annotations-col {
    grid-column: 1;
    grid-row: 1;
    display: flex;
    flex-direction: column;
    gap: 16px;
  }
  .mind-shot-annotation {
    position: static !important;
    left: auto !important;
    top: auto !important;
    width: 100% !important;
    max-width: 420px !important;
  }
  /* Same reasoning as the ≤900px block below: .frame's glass bleed
     needs a positioning context back once position:static applies. */
  .mind-shot-img.frame { position: relative !important; }
}
@media (max-width: 900px) {
  /* The base rule's 746px cap is desktop-only — below 900px the
     hero-top (side-by-side down to 600px, fully stacked below that —
     see the 600-900 and ≤600px blocks) can already legitimately run
     taller than that, and plain min-height: auto sizes the hero to its
     content instead of stretching to fill the viewport, so there's
     nothing left for a cap to guard against here. padding-top keeps
     the base rule's added var(--nav-h) (margin-top's -var(--nav-h)
     isn't touched here, so it's still in effect) — only the 96px it
     was stacked on shrinks to 48px, same tightening the old mobile
     override made. */
  .mind-hero { min-height: auto; padding-top: calc(48px + var(--nav-h)); }
  .mind-meta-row { grid-template-columns: 1fr 1fr; }
  /* 2 per row instead of 3 — the desktop gap (32px) is sized for that
     wider 3-column row, so it's tightened to 24px alongside the
     column change. Card 5 (odd one out) just falls into column 1 of
     its own row, left-aligned at the same half-width as the rest —
     plain grid flow, no spanning/centering rule needed. Back to 2 real
     tracks (not the base rule's 6, which only exists to center row 2
     at the 3-column desktop width) — the base rule's span/nth-child
     placement is reset to auto so cards fall into plain 1-per-column
     flow here instead of overflowing a 2-track row. */
  .mind-measure-grid { grid-template-columns: 1fr 1fr; gap: 24px; }
  .mind-measure-grid .card,
  .mind-measure-grid .card:nth-child(4),
  .mind-measure-grid .card:nth-child(5) {
    grid-column: auto;
  }
  .mind-pull-quote { padding: 32px; }
  .mind-split-row { grid-template-columns: 1fr; gap: 32px; }

  /* --content-w (800px) is sized for the >900px layout, where it reads
     as a deliberate narrow-column choice against a much wider page.
     Below 900px, --side-pad drops to 32px (style.css), so the
     available width (viewport − 64px) already exceeds 800px up near
     this breakpoint's top end — e.g. 836px at exactly 900px wide — and
     the leftover gap next to full-bleed elements reads as a stray
     misalignment, not a narrow column. Dropping the cap on every
     element that carries it lets these sections fill the same width
     as everything else at this tier. */
  .section-narrow,
  .mind-prose-col,
  .mind-p,
  .mind-bullets,
  .mind-media-row--narrow {
    max-width: none;
  }

  /* Drop the sticky column and the 2-column grid tier 2 set up in
     favor of one plain stack — .mind-shot-annotations-col reverts to
     a bare wrapper (its flex styling came from the tier-2 query, out
     of range here) so its 3 children just flow like any other stacked
     card. */
  .mind-sticky-scroll { grid-template-columns: 1fr; gap: 32px; }
  /* Stacked, this is no longer the single tallest block on the page
     (the base rule's 100px comment) — zeroed out, whatever follows
     supplies its own top spacing instead. */
  .mind-sticky-scroll.mind-sticky-scroll--variant-b { margin-bottom: 0; }
  .mind-sticky-left { position: static; }
  /* The 3 problem cards go side by side here (row, not the desktop
     sidebar's column) — full-width row now that the sticky column is
     gone, so stacking them one under another would waste the width.
     .card getting flex: 1 is what actually splits that row into 3
     equal cards, rather than each shrinking to its own title length. */
  .mind-sticky-cards { flex-direction: row; }
  .mind-sticky-cards .card { flex: 1; }
  .mind-shot-canvas { display: flex; flex-direction: column; gap: 12px; }
  .mind-shot-img,
  .mind-shot-annotations-col,
  .mind-shot-annotation {
    width: 100% !important;
    height: auto !important;
  }
  .mind-shot-annotations-col { display: flex; flex-direction: column; gap: 12px; }
  .mind-shot-lines { display: none; }
  .mind-shot-img.frame { position: relative !important; }
}
/* Hero, 600-900px: stays side-by-side (the base rule's 50/50 grid,
   untouched here) instead of stacking full-width like the ≤600px tier
   below — only .mind-hero-right's own vertical treatment and the
   mockup's own size change (per Figma node 1325:35531). */
@media (max-width: 900px) and (min-width: 601px) {
  /* Zeroed instead of the ≤900px block's calc(48px + var(--nav-h)) —
     that padding only existed to leave room above the >900px-sized
     mockup; now that the mockup is smaller (80% below) and vertically
     centered, .mind-hero-top's row can fill the hero's full height
     instead, which is what actually makes align-items: center below
     center the mockup against the WHOLE header rather than a
     padding-shrunk slice of it. */
  .mind-hero {
    padding-top: 0;
    /* Restores the base rule's own formula — the ≤900px block above
       (shared with the ≤600px tier, which needs a plain content-driven
       height for its full-width stack) resets this to min-height: auto,
       which left this tier's hero shrinking to whatever its (now much
       smaller, width: 80%) mockup or text needed instead of holding the
       taller, design-intended proportions. */
    min-height: min(100vh, calc(746px + var(--nav-h)));
  }
  /* Keeps the text column legible as the 50/50 grid keeps narrowing
     toward this tier's own 601px floor (~236px at that width, plain
     50%) — same floor-guarding idea as .mind-hero-mockup's own
     min-width just below. */
  .mind-hero-left { min-width: 290px; }
  /* Vertically centered instead of bottom-docked (the base rule's
     align-items: flex-end) — .mind-hero-mockup's own negative-margin
     bleed past the hero's bottom edge is reset to 0 and traded for
     this instead. */
  .mind-hero-right { align-items: center; }
  .mind-hero-mockup {
    /* Smaller at this tier (Figma's own 650px-wide reference frame
       sizes it well under the >900px tier's 320px cap) — 80% of the
       column instead of stretching to fill it, which is also what
       lets it size (and center) via its own aspect-ratio instead of
       needing the old min-width: 250px + negative margin-right trick
       to avoid shrinking too far. min-width keeps that 80% from ever
       shrinking the mockup past a legible size as the column narrows
       toward this tier's own 601px floor. */
    width: 80%;
    min-width: 260px;
    margin-bottom: 0;
  }
}
@media (max-width: 600px) {
  /* Back to a plain full-width stack below 600px — the previous
     block's (min-width: 601px) already keeps its side-by-side/centered/
     bled-wider treatment from applying down here at all, so this is
     the only hero-layout override left standing at this tier, same as
     before that 600-900px tier existed.
     A fixed 880px (not min-height) replaces the base rule's
     viewport-fit min-height (already at min-height: auto since the
     ≤900px block) — stacked content at this width (top padding + text
     + 68px gap + the full-aspect-ratio image) already runs taller than
     that on its own, so a plain min-height wouldn't actually constrain
     anything; height here is what lets .mind-hero's own overflow:
     hidden crop the excess (the image's own bottom edge) down to this
     exact box, same spirit as the image's own 32px negative-margin-
     bottom bleed just below — both crop the image, just at two
     different edges. Text stays in its natural DOM order on top (no
     order override needed, unlike this tier's own image-first
     predecessor). gap (64px at every wider tier) becomes the visible
     text→image gap now that they're stacked in one column, bumped to
     68px specifically.
     .mind-hero-left's own padding-top stacks on top of .mind-hero's own
     112px (48px base + var(--nav-h) = 64px, from the ≤900px block
     above) rather than replacing it — 68px here is what makes that
     total exactly 180px (112 + 68), not 180px on its own. */
  .mind-hero { height: 880px; }
  .mind-hero-top { grid-template-columns: 1fr; gap: 68px; }
  .mind-hero-left { padding-top: 68px; }
  .mind-hero-mockup { max-width: 350px; margin-bottom: -32px; }
  /* Re-centers the blob for this tier's much narrower frame — the
     wider tiers' left: calc(50% + 437px)/+200px math is set inline per
     instance (case-study-7mind.html), so !important is what lets a
     stylesheet rule win over that instead of needing a third inline
     variant tied to a media query, which inline style can't express. */
  .mind-hero-blob-zone .bg-blob { left: calc(50% + 200px) !important; }
  .mind-meta-row { grid-template-columns: 1fr; }
  /* Back to a plain stack below 600px — the 2-per-row tier above only
     works while there's still room for a real row; narrower than
     that, one under another reads better. Between-card gap tightens
     to 12px (from 24px) to match the denser stack, and each card's
     own padding/internal gap shrink alongside it. */
  .mind-measure-grid { grid-template-columns: 1fr; gap: 12px; }
  .mind-measure-grid .card { padding: 24px 18px; gap: 8px; }
  /* Back to a plain stack below 600px — the row above only works
     while there's still a full row's width for 3 cards; narrower than
     that, one under another reads better. */
  .mind-sticky-cards { flex-direction: column; }
  .mind-sticky-cards .card { flex: none; }
}
