/*
Theme Name: Katie Kuhens Portfolio
Theme URI:
Author: Katie Kuhens
Author URI:
Description: Custom portfolio theme positioning Katie as a design leader. Structure-first build (no page builder). Hardened visual system: Archivo display type, cool neutrals, squared geometry, terracotta rationed to a few deliberate marks.
Version: 0.2.0
Requires at least: 6.4
Tested up to: 6.7
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: LICENSE
Text Domain: katie-portfolio
*/

/* ==========================================================================
   Tokens — serif headlines / sans-serif meta, black-and-white restraint,
   modeled on the existing live Work page (system font stacks for now;
   swap in the real webfonts whenever those are picked).
   ========================================================================== */

:root {
	/* Archivo carries every heading, number and pull-quote. Georgia at
	   weight 400 used to do this job and was the main reason the site
	   read soft — a light bookish serif on every headline. */
	--font-display: 'Archivo', 'Helvetica Neue', Helvetica, Arial, sans-serif;
	--font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;

	/* Neutrals carry a slight cool cast. Every grey here used to be warm
	   (#e0ded8 borders, #f6f5f2 surfaces, a cream band) which, stacked
	   up, read as an artisanal palette rather than an engineered one.
	   Terracotta stays warm on purpose and is now rationed hard, so the
	   warmth reads as a deliberate mark instead of a wash. */
	--color-bg: #ffffff;
	--color-text: #0d1114;
	--color-muted: #667079;
	--color-border: #d5d8dc;
	--color-accent: #c24a2c;
	--color-invert-bg: #0d1114;
	--color-invert-text: #ffffff;
	--color-surface: #f2f4f6;
	--color-surface-deep: #e6eaee; /* the one section that needs to stand apart */
}

*,
*::before,
*::after {
	box-sizing: border-box;
}

body {
	margin: 0;
	font-family: var(--font-sans);
	color: var(--color-text);
	background: var(--color-bg);
	line-height: 1.5;
}

h1, h2, h3, h4 {
	font-family: var(--font-display);
	font-weight: 700;
	line-height: 1.15;
	letter-spacing: -0.015em;
}

img {
	max-width: 100%;
	height: auto;
	display: block;
}

a {
	color: inherit;
}

/* Two arrows, two meanings — see template-parts/icon-arrow.php and
   icon-arrow-external.php. Horizontal = stays on the site; diagonal =
   leaves it (mailto, LinkedIn, GitHub, ADPList). Each nudges along its
   own axis on hover so the motion matches the glyph. */
.link-icon {
	display: inline-flex;
	width: 0.75em;
	height: 0.75em;
	margin-left: 0.45em;
	vertical-align: baseline;
	flex-shrink: 0;
}

.link-icon svg {
	width: 100%;
	height: 100%;
	display: block;
	transition: transform 0.18s ease;
}

a:hover .link-icon svg {
	transform: translateX(3px);
}

/* The diagonal one travels up-and-right instead, along its own axis. */
.icon-arrow--external {
	transition: transform 0.18s ease;
}

a:hover .icon-arrow--external {
	transform: translate(2px, -2px);
}

/* Standard inline link: underlined at rest so it is findable without
   relying on colour, accent on hover. */
.prose a,
.cs-turn__text a,
.case-study-body a:not([class]) {
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

.prose a:hover,
.cs-turn__text a:hover,
.case-study-body a:not([class]):hover {
	color: var(--color-accent);
}

/* The site previously defined no focus style at all, so keyboard users
   got the browser default — which on a squared, high-contrast layout
   reads as an accident. */
:focus-visible {
	outline: 2px solid var(--color-accent);
	outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		transition-duration: 0.01ms !important;
		animation-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

.container {
	max-width: 72rem;
	margin-inline: auto;
	padding-inline: 1.5rem;
}

.eyebrow {
	display: block;
	font-family: var(--font-sans);
	font-size: 0.85rem;
	color: var(--color-muted);
}

.accent {
	color: var(--color-accent);
}

/* Buttons / pill CTAs */
.btn {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	background: var(--color-invert-bg);
	color: var(--color-invert-text);
	font-family: var(--font-sans);
	font-size: 0.875rem;
	text-decoration: none;
	padding: 0.7rem 1.4rem;
	border-radius: 0;
	border: none;
	font-weight: 600;
	transition: transform 0.18s ease, background-color 0.18s ease;
}

.btn:hover,
.btn:focus-visible {
	transform: translateX(4px);
	background: var(--color-accent);
}

.btn:hover .btn__icon,
.btn:focus-visible .btn__icon {
	transform: translate(2px, -2px); /* the arrow travels along its own
	   diagonal rather than sideways, so the motion matches the glyph */
}

.btn__icon {
	width: 0.8em;
	height: 0.8em;
	flex-shrink: 0;
	transition: transform 0.18s ease;
}

/* "Request my résumé" at the foot of About. The résumé is a file Katie
   sends rather than a page on the site — see the note in page-about.php. */
/* No max-width: the sibling about-rows let their content fill the 1fr
   column, and a cap here made this row visibly narrower than the rest. */
.resume-ask__text {
	margin: 0;
	color: var(--color-muted);
}

/* Site header / nav. No hairline sitewide — tried first on the
   homepage (paired with a matching light-grey hero background at the
   time) and then as a one-page test on the Work archive with NO
   matching background change, to check whether the divider was doing
   real work anywhere or was just a convention; the natural whitespace
   before each page's heading turned out to carry the separation fine
   on its own. Katie: the Work test "looks really great," extend it
   everywhere. The homepage's own grey nav/hero fill was later dropped
   too (Katie's call) — the header is plain white on every page now. */
.site-header {
	position: relative;
	padding-block: 1.5rem;
}

.site-header__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
	flex-wrap: wrap;
}

.site-branding {
	margin: 0;
}

/* Wordmark, replacing the circular "KK" monogram. The monogram was the
   only round element on a site where every other corner is square — the
   name resolves that inconsistency as a side effect.

   No aria-label needed here, unlike the monogram: the link text is the
   name, so it already announces correctly. */
.site-branding__name {
	display: inline-block;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1.0625rem;
	letter-spacing: -0.01em;
	color: var(--color-text);
	text-decoration: none;
	transition: color 0.18s ease;
}

.site-branding__name:hover {
	color: var(--color-accent);
}

.primary-nav ul {
	display: flex;
	flex-wrap: wrap;
	gap: 1.75rem;
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: 0.9rem;
}

/* Nav sits hard right, next to the header action — with three children
   and space-between, it was floating in the middle of the header. */
.primary-nav {
	margin-left: auto;
}

/* States are colour only: no underline, no accent. The terracotta rule
   put the brand colour on every page load for no informational gain,
   and an underline indicator added a second horizontal element to a bar
   that already has one. Weight carries the current page instead. */
.primary-nav a {
	display: inline-block;
	text-decoration: none;
	color: var(--color-muted);
	transition: color 0.18s ease;
}

.primary-nav a:hover {
	color: var(--color-text);
}

.primary-nav a.is-active {
	color: var(--color-text);
	font-weight: 600;
}

/* Header action — the one button on the site, per the style guide. */
/* No button behind this — a bare outlined icon on the header, not a
   filled square. Colour carries both states via currentColor: text
   colour at rest, accent on hover. Padding gives the same ~44px tap
   target the old square button had, without a visible box. */
.site-header__cta {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0.6rem;
	margin: -0.6rem;
	color: var(--color-text);
	text-decoration: none;
	transition: color 0.18s ease;
}

.site-header__cta:hover,
.site-header__cta:focus-visible {
	color: var(--color-accent);
}

.site-header__cta-icon {
	width: 1.75rem;
	height: 1.375rem;
	display: block;
	overflow: visible; /* the motion lines sit outside the envelope's own
	                      box and must not get clipped when they slide in */
}

/* Envelope tilts and nudges up-right on hover — "in flight". SVG
   transforms rotate around (0,0) by default, so transform-origin is set
   to the envelope's own centre (its rect spans x 10-24, y 6-16). */
.icon-mail__envelope {
	transform-box: fill-box;
	transform-origin: 50% 50%;
	transition: transform 0.22s ease;
}

.site-header__cta:hover .icon-mail__envelope {
	transform: rotate(-16deg) translate(2px, -1.5px);
}

/* Motion lines exist in the markup at rest but are invisible and
   pulled in toward the envelope, so nothing shifts layout when they
   appear — they fade and slide out on hover, like the envelope is
   pulling away from them. */
.icon-mail__lines {
	opacity: 0;
	transform: translateX(4px);
	transition: opacity 0.22s ease, transform 0.22s ease;
}

.site-header__cta:hover .icon-mail__lines {
	opacity: 1;
	transform: translateX(0);
}

@media (prefers-reduced-motion: reduce) {
	.icon-mail__envelope,
	.icon-mail__lines {
		transition: none;
	}
}

/* Mobile nav — a <details> disclosure, not a JS-driven panel, so
   opening/closing works with zero JS; the rules below only add the
   slide/fade entrance and the hamburger-to-X icon morph on top of that
   native behaviour. Hidden above the breakpoint; .primary-nav (bare
   inline links) is what desktop actually uses, and the two are never
   both visible at once. */
.mobile-nav {
	display: none;
}

.mobile-nav__toggle {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0.6rem;
	margin: -0.6rem;
	list-style: none;
	color: var(--color-text);
	cursor: pointer;
	transition: color 0.18s ease;
}

.mobile-nav__toggle::-webkit-details-marker {
	display: none;
}

.mobile-nav__toggle:hover {
	color: var(--color-accent);
}

.mobile-nav__toggle:focus-visible {
	outline: 2px solid var(--color-accent);
	outline-offset: 3px;
}

.icon-hamburger {
	width: 1.5rem;
	height: 1.5rem;
	display: block;
}

.icon-hamburger__line {
	transform-box: fill-box;
	transform-origin: center;
	transition: transform 0.25s ease, opacity 0.25s ease;
}

/* Top and bottom lines converge on the middle line's position and
   rotate into an X; the middle line just fades out of the way. */
.mobile-nav[open] .icon-hamburger__line--top {
	transform: translateY(5px) rotate(45deg);
}

.mobile-nav[open] .icon-hamburger__line--middle {
	opacity: 0;
}

.mobile-nav[open] .icon-hamburger__line--bottom {
	transform: translateY(-5px) rotate(-45deg);
}

/* Anchored to .site-header (see position:relative there), not
   .site-header__inner, so it can span full width — .container's own
   max-width/centering would otherwise clip it on wide phones/tablets.
   padding-inline matches .container's own so the links line up with
   the logo above them. */
.mobile-nav__panel {
	display: block;
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	z-index: 20; /* the homepage hero's reveal-on-load animation creates
	                its own stacking context, which otherwise painted
	                above this panel despite it being later/positioned —
	                without this the hero text showed straight through. */
	margin: 0;
	padding: 0.5rem 1.5rem 1.5rem;
	background: var(--color-bg);
	border-bottom: 1px solid var(--color-border);
	opacity: 1;
	transform: translateY(0);
	transition: opacity 0.25s ease, transform 0.25s ease, display 0.25s allow-discrete, overlay 0.25s allow-discrete;
}

.mobile-nav:not([open]) .mobile-nav__panel {
	display: none;
}

@starting-style {
	.mobile-nav[open] .mobile-nav__panel {
		opacity: 0;
		transform: translateY(-8px);
	}
}

.mobile-nav__panel ul {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.mobile-nav__panel a {
	display: block;
	padding: 0.75rem 0;
	font-family: var(--font-display);
	font-size: 1.25rem;
	font-weight: 600;
	text-decoration: none;
	color: var(--color-muted);
	transition: color 0.18s ease;
}

.mobile-nav__panel a:hover,
.mobile-nav__panel a:focus-visible {
	color: var(--color-text);
}

.mobile-nav__panel a.is-active {
	color: var(--color-text);
}

@media (prefers-reduced-motion: reduce) {
	.icon-hamburger__line,
	.mobile-nav__panel {
		transition: none;
	}
}

@media (max-width: 48rem) {
	.primary-nav {
		display: none;
	}

	.mobile-nav {
		display: block;
		margin-left: auto;
	}
}

/* Breadcrumb */
.breadcrumb {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	font-family: var(--font-sans);
	font-size: 0.8rem;
	color: var(--color-muted);
	margin: 0 0 3rem; /* was 1.5rem — the trail was reading as part of the title */
}

.breadcrumb [aria-current="page"] {
	color: var(--color-text);
}

.breadcrumb a {
	text-decoration: none;
	color: var(--color-muted);
}

.breadcrumb a:hover {
	color: var(--color-text);
}

/* Hero — a nested .container holds the content (markup: .hero wraps a
   .container div) rather than the section itself carrying both
   classes, so .hero's own background can go full-bleed edge to edge;
   a combined .hero.container element can only ever paint the
   constrained 72rem column. One deliberate dramatic moment inside that
   container: the headline spans most of its width (no max-width of
   its own), while the subhead stays narrow.

   Was full-height (min-height: 100vh) for a while — tried first on the
   style guide's "Editorial scale" section, prompted by garri.design's
   homepage. Katie went back on it: a content-height band like every
   other page's top section, not a full-viewport moment. */
.hero {
	display: flex;
	flex-direction: column;
	justify-content: center;
	/* justify-content: center is a no-op now that the box is exactly
	   its content's height (no min-height) — harmless to leave, but the
	   real spacing control is padding-block directly. Top bumped up
	   from 3rem: with the full-viewport hero gone, the nav sat right on
	   top of the headline with barely a break (Katie's call, wanted
	   more air between them). */
	padding-block: 5.5rem 5rem;
	margin-bottom: 3.75rem; /* ~60px gap before the next section */
}

/* Scroll-snap (forcing the homepage to land on each section) was built
   around the full-viewport hero — once that hero went back to a
   content-height band, the anchoring no longer made sense and Katie
   asked for natural scroll back. Used to live here as scroll-snap-align
   on .site-header/.hero/.featured-work/.home-leadership/.site-footer,
   plus html:has(body.home) { scroll-snap-type: y mandatory; } — all
   removed together. */

/* Homepage entrance. The hero (above) has no animation and renders
   immediately — headline and subline should never feel like they're
   waiting on something. Everything below it fades up a beat later, on
   a one-time load animation rather than a scroll-triggered one: this is
   an entrance, not a repeating effect, so plain CSS with no JS covers
   it, and it still runs with scripts disabled.

   Kept deliberately quick and small (12px of travel, well under a
   second in total) — this is meant to read as the page settling, not
   as something the visitor has to wait through. --2 lands slightly
   later so the two blocks arrive as a soft cascade rather than both
   snapping in at once. */
@keyframes home-reveal {
	from {
		opacity: 0;
		transform: translateY(12px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

.reveal-on-load {
	opacity: 0;
	/* Base timing assumes the hero fades first (delay 0, below) and this
	   section picks up right as that finishes — a handoff, not two
	   separate reveals running on their own clocks. */
	animation: home-reveal 0.8s ease 0.8s forwards;
}

/* The hero used to render instantly while everything below it faded in
   — on reflection that read as two different pages stitched together.
   It now runs the same animation at delay 0, so the whole page arrives
   as one sequence: hero, then a 0.2s-staggered pair behind it. */
.reveal-on-load--hero {
	animation-delay: 0s;
}

.reveal-on-load--2 {
	animation-delay: 1s;
}

@media (prefers-reduced-motion: reduce) {
	.reveal-on-load {
		opacity: 1;
		animation: none;
	}
}

.hero__headline {
	margin: 0 0 1.5rem;
	font-size: clamp(2.25rem, 6vw, 5.5rem);
	line-height: 0.98;
}

/* Was a muted <p>; now a real H2 statement (a client-credit reveal,
   not a value-prop sentence), so it gets the display face at a weight
   that complements the headline's bold rather than competing with it —
   same family, lighter weight, the pairing does the work. */
.hero__subline {
	/* No max-width: this used to be a shorter value-prop sentence
	   capped at 50rem/800px for readability. The client-credit list is
	   longer, and at 800px it wrapped "Autodesk" onto its own line by
	   itself (Katie caught this at the 1440px breakpoint) — the fix is
	   letting it use the full container width, not narrowing it further. */
	margin: 0;
	color: var(--color-text);
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 1.25rem;
	line-height: 1.5;
}

/* Past clients "get crossed off" instead of arriving pre-struck-through
   — a custom animated line (native text-decoration can't be animated)
   that draws left to right per client, staggered via --strike-delay
   (set inline per client in front-page.php) so the list reads as being
   checked off in sequence rather than a static fact. */
.hero__client--past {
	position: relative;
	color: var(--color-border);
}

.hero__client--past::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	top: 50%;
	height: 1.5px;
	/* Halfway between --color-border (the pale text — too faint to read
	   as animated) and --color-muted (Katie's first pass with the line —
	   too dark). color-mix keeps this tied to both tokens instead of a
	   one-off hardcoded gray. */
	background: color-mix(in srgb, var(--color-border), var(--color-muted));
	transform: scaleX(0);
	transform-origin: left;
	animation: hero-client-strike 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
	animation-delay: var(--strike-delay, 0.5s);
}

@keyframes hero-client-strike {
	to {
		transform: scaleX(1);
	}
}

@media (prefers-reduced-motion: reduce) {
	.hero__client--past::after {
		animation: none;
		transform: scaleX(1);
	}
}

/* Generic section spacing (non-homepage templates: Work archive, etc.) */
.section {
	padding-block: 3.5rem;
	border-top: 1px solid var(--color-border);
}

.section__heading {
	margin: 0 0 2rem;
	font-size: 1.5rem;
}

/* Whitespace-separated content sections (no divider lines) — used on
   Home and the other custom-styled pages (Leadership, Principles, etc.) */
.content-section {
	padding-block: 0;
	margin-bottom: 3.75rem; /* ~60px gap to the next section; collapses
	                           with the footer's own margin-top on the
	                           last section, so no extra tuning needed */
}

.content-section:first-child {
	padding-top: 4rem;
}

/* Opt-in section divider. The site's default is whitespace-only
   separation, which works where sections are short — but the Leadership
   page stacks several long ones and they ran together. The rule sits on
   the inner .container so it aligns to content rather than spanning the
   viewport. Hairline, per the style guide's one divider weight. */
.content-section--divided > .container {
	border-top: 1px solid var(--color-border);
	padding-top: 4.5rem;
}

.content-section--divided {
	margin-bottom: 4.5rem;
}

/* Section heading. Bumped from clamp(1.5rem, 2vw, 1.75rem): that
   ceiling was identical to .initiative__title's, so at wide viewports
   an h2 rendered exactly the same size as the h3s beneath it and the
   hierarchy read flat. The vw coefficient stays below .page-heading's
   5vw and above .initiative__title's 2.2vw, so the three tiers can
   never cross at any viewport width. */
.section-label {
	font-family: var(--font-display);
	font-weight: 600;
	font-size: clamp(1.875rem, 2.6vw, 2.375rem);
	margin: 0 0 2rem;
}

/* One tier down, for section headings that label a row rather than open
   a section — the About page's label column. Reuses .cs-decision__title's
   exact clamp rather than inventing a value: the style guide's rule is
   that headings take a system class and override margin only, and adding
   a fifth heading size is the failure it was written to prevent. */
.section-label--secondary {
	font-size: clamp(1.5rem, 2.5vw, 2rem);
}

/* Matched to .case-study-hero__title so Work, Leadership, Principles and
   the case studies all open at the same scale — at the old size the
   inner pages read noticeably smaller than a case study. The footer
   heading overrides this with its own smaller clamp (it is defined
   later in the file, so it still wins). */
.page-heading {
	font-size: clamp(2.25rem, 5vw, 3.75rem);
	line-height: 1.05;
	margin: 0 0 2.5rem;
}

/* A second heading on the same page that opens a section rather than the
   page. Work uses it for "Selected earlier work" — at full page scale
   the page had two competing openings. */
.page-heading--secondary {
	font-size: clamp(1.75rem, 3vw, 2.25rem);
	line-height: 1.15;
}

/* Forces a deliberate line break in a headline. */
.page-heading__line {
	display: block;
}

/* No max-width: the About rows let their content fill the 1fr column,
   and a 32rem cap made the first row visibly narrower than the four
   beneath it. Used only in that row. */
.intro-statement__supporting {
	font-family: var(--font-sans);
	color: var(--color-muted);
	font-size: 1.05rem;
	margin: 0;
}

.lede {
	font-family: var(--font-sans);
	color: var(--color-muted);
	font-size: 1.05rem;
	max-width: 48rem;
	margin: 0 0 2.5rem;
}

.text-link {
	margin-top: 1.5rem;
}

.text-link a {
	display: inline-flex;
	align-items: center;
	text-decoration: underline;
	text-underline-offset: 0.2em;
	font-size: 0.95rem;
}

.text-link a:hover {
	color: var(--color-accent);
}

/* Principles — "Where these principles came from". Prose left, the
   employer stack right, filling the 24rem of dead space .prose used to
   leave inside the 72rem container.

   Treatment follows the reference Katie supplied: oversized all-caps in
   the accent colour, very tight leading so the names read as one block,
   ragged right. align-items: start is correct here — these are unboxed
   text columns with no fill or border, so there is no visible edge to
   go ragged. */
.origin-row {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 4rem;
	align-items: start;
}

@media (max-width: 56rem) {
	.origin-row {
		grid-template-columns: 1fr;
		gap: 2.5rem;
	}
}

/* .prose has no margin reset of its own, so it was taking the UA
   default 1em top margin while the list beside it sat at margin 0 —
   which started the paragraph 16px below the names. Zeroed here only,
   so every other .prose on the site keeps its spacing. */
.origin-row .prose {
	margin-top: 0;
}

.worked-at__list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.worked-at__item {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: clamp(1.5rem, 3.4vw, 3.25rem); /* 52px at the ceiling — bumped
	   from 46px because title case reads visually smaller than all-caps
	   did at the same size (shorter x-height, no uniform cap-height block) */
	line-height: 0.98; /* names stack as one mass, per the reference */
	letter-spacing: -0.02em;
	/* No text-transform: this stack was all-caps to match Katie's
	   original reference, but at 46px it read as shouting next to a
	   site that otherwise only uses uppercase for small tracked
	   microlabels. Title case, as the data is already written. */
	color: var(--color-accent);
	overflow-wrap: break-word; /* break rather than overflow the column
	                              on the longest name */
}

/* Two-persona comparison — "A user centred opportunity" on Product Page
   Evolution. Built as markup rather than dropped in as a screenshot of
   the slide: it is three short rows of structured text, so as markup it
   stays selectable, searchable, responsive and legible at any zoom,
   and costs no image weight.

   The parallel is the whole argument — both personas, same page, both
   miss — so the two columns stay side by side even in the narrow
   decision column, with the type sized down to suit. */
.cs-jobs {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 0 1rem;
	align-content: start;
}

/* Icon + name head the column, matching the deck slide. */
/* Icon beside the name, as on the slide. The column is narrow, so the
   name is allowed to wrap to two lines and the icon stays centred
   against it rather than pinned to the first line. */
.cs-jobs__col {
	display: flex;
	align-items: center;
	gap: 0.65rem;
	margin-bottom: 1rem;
	min-width: 0;
}

.cs-jobs__icon {
	width: 1.75rem;
	height: 1.75rem;
	flex: 0 0 auto; /* never squashed by a name that wraps */
	color: var(--color-accent);
}

.cs-jobs__icon svg {
	width: 100%;
	height: 100%;
	display: block;
}

.cs-jobs__name {
	font-family: var(--font-sans);
	font-weight: 700;
	font-size: 1rem;
	line-height: 1.25;
	color: var(--color-text);
	margin: 0;
}

.cs-jobs__cell {
	margin: 0;
	padding: 0.9rem 0.9rem;
	font-size: 0.875rem;
	line-height: 1.5;
	color: var(--color-muted);
}

/* Banded rows, matching the slide's alternating fill. */
.cs-jobs__cell--band {
	background: var(--color-surface);
}

.cs-jobs__verdict {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	font-weight: 700;
	font-size: 0.9375rem;
	color: var(--color-text);
}

/* The X is the same mark the case study's turn signals use for a
   negative signal — one glyph meaning "this did not work" site-wide. */
.cs-jobs__mark {
	width: 1.05rem;
	height: 1.05rem;
	flex-shrink: 0;
	color: var(--color-accent);
}

.cs-jobs__mark svg {
	width: 100%;
	height: 100%;
	display: block;
}

.cs-jobs__close {
	grid-column: 1 / -1;
	margin: 1.5rem 0 0;
	font-size: 0.9375rem;
	font-style: italic;
	color: var(--color-muted);
}

/* Stays italic — the emphasis rides inside the italic line rather than
   breaking out of it, as on the slide. (.cs-tiers__close does reset to
   upright, but there the emphasised phrase is its own display line.) */
.cs-jobs__close strong {
	font-weight: 700;
	color: var(--color-text);
}

@media (max-width: 40rem) {
	.cs-jobs {
		grid-template-columns: 1fr;
	}

	/* Stacked, the two personas need separating or the rows run
	   together into one list. */
	.cs-jobs__name + .cs-jobs__name,
	.cs-jobs__name:nth-of-type(2) {
		margin-top: 1.75rem;
	}
}

/* JTBD intercept insights, nested inside Move 01 between the decision
   grid and the outcome bar. Was intro-on-top, then the two jobs side
   by side below — read as continuous with the fields above it, when
   Katie wanted this carved out as its own beat. Now a hairline sets it
   apart (the "no top rule, it's part of the move" call is reversed),
   and it's a left/right split — insight text left, the two jobs
   stacked right — matching .cs-decision__grid's own text-left,
   content-right convention instead of the intro-then-grid shape used
   nowhere else on the page.

   The oversized "What" / "How" in accent, with the rest of the phrase in
   text colour, is lifted from the slide. It is the one place on the page
   where type does the work instead of prose. */
.cs-jtbd {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 3rem;
	align-items: start;
	margin: 3rem 0 0;
	padding-top: 3rem;
	border-top: 1px solid var(--color-border);
}

@media (max-width: 48rem) {
	.cs-jtbd {
		grid-template-columns: 1fr;
		gap: 2.25rem;
	}
}

.cs-jtbd__intro {
	max-width: none;
}

.cs-jtbd__jobs {
	display: grid;
	gap: 2rem;
}

/* Sits under the move's h3 title (32px) and above body copy — a real
   heading for the sub-section rather than a microlabel, but clearly
   subordinate to the move it belongs to. */
.cs-jtbd__heading {
	font-family: var(--font-display);
	font-weight: 600;
	font-size: clamp(1.125rem, 1.8vw, 1.375rem);
	line-height: 1.25;
	color: var(--color-text);
	margin: 0 0 0.75rem;
}

.cs-jtbd__lede {
	margin: 0;
	color: var(--color-muted);
}

.cs-jtbd__title {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: clamp(1.75rem, 4vw, 2.75rem);
	line-height: 1.1;
	letter-spacing: -0.02em;
	color: var(--color-text);
	margin: 0 0 1rem;
}

.cs-jtbd__key {
	color: var(--color-accent);
}

.cs-jtbd__text {
	margin: 0;
	color: var(--color-muted);
	max-width: 30rem;
}

.cs-jtbd__text strong {
	color: var(--color-text);
	font-weight: 600;
}


/* Consideration tiers — three cards, recreated as markup from the deck
   slide rather than dropped in as a screenshot. Same reasoning as
   .cs-jobs: short structured text stays selectable, responsive and
   crisp at any zoom, and costs no image weight.

   The $ / $$ / $$$ marks are the deck's own shorthand for the price
   band, kept because they carry the idea faster than a sentence. */
.cs-tiers {
	display: grid;
	gap: 1rem;
	align-content: start;
}

/* Light-to-dark progression across the three tiers — the deck's own
   device, and it carries "more consideration" faster than the words do.
   Tints of --color-accent over the page ground rather than arbitrary
   greys, so the ramp belongs to the palette. */
.cs-tier {
	padding: 1.5rem;
	background: #faf0ec;
}

.cs-tier:nth-child(2) {
	background: #f4ded6;
}

.cs-tier:nth-child(3) {
	background: #edc9bd;
}

.cs-tier__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem;
	margin-bottom: 0.75rem;
}

.cs-tier__name {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1.125rem;
	line-height: 1.2;
	letter-spacing: -0.01em;
	color: var(--color-text);
	margin: 0;
}

.cs-tier__cost {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 2.25rem;
	line-height: 0.9;
	color: var(--color-accent);
	letter-spacing: 0.02em;
}

.cs-tier__detail {
	margin: 0 0 0.5rem;
	font-size: 0.875rem;
	color: var(--color-text);
}

.cs-tier__eg {
	margin: 0 0 1.25rem;
	font-size: 0.875rem;
	font-style: italic;
	color: var(--color-muted);
}

.cs-tier__task {
	margin: 0;
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--color-text);
}

.cs-tiers__close {
	margin: 0.5rem 0 0;
	font-size: 0.875rem;
	color: var(--color-muted);
}

.cs-tiers__close strong {
	display: block;
	color: var(--color-accent);
	font-weight: 600;
}

/* Validation plan — four sequenced studies, each with the success
   criterion that was written before it ran. Serif numerals in a gutter,
   the site's existing device. */
.cs-validation {
	display: grid;
	gap: 1.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
	align-content: start;
}

.cs-validation__item {
	display: grid;
	grid-template-columns: 2.5rem 1fr;
	gap: 0.9rem;
	align-items: start;
}

.cs-validation__number {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 1.25rem;
	line-height: 1.3;
	color: var(--color-accent);
}

.cs-validation__title {
	font-family: var(--font-sans);
	font-weight: 600;
	font-size: 0.9375rem;
	color: var(--color-text);
	margin: 0 0 0.35rem;
}

.cs-validation__text {
	margin: 0;
	font-size: 0.8125rem;
	line-height: 1.5;
	color: var(--color-muted);
}

/* The success criterion is the load-bearing part — it is what makes the
   sequencing honest — so it gets a rule and a tick rather than reading
   as a second paragraph. */
.cs-validation__success {
	margin: 0.6rem 0 0;
	padding-top: 0.6rem;
	border-top: 1px solid var(--color-border);
	font-size: 0.8125rem;
	line-height: 1.5;
	color: var(--color-text);
}

.cs-validation__check {
	color: var(--color-accent);
	font-weight: 700;
	margin-right: 0.15rem;
}

/* Move 04 gives the plan more room than a 1fr column: four studies with
   criteria need it, and the text stack beside them is shorter. */
.cs-decision__grid--wide {
	grid-template-columns: 1fr 1.25fr;
}

@media (max-width: 56rem) {
	.cs-decision__grid--wide {
		grid-template-columns: 1fr;
	}
}

/* Two diagrams built as HTML/CSS, matching .cs-jobs and .cs-validation's
   pattern (Product Page Evolution) — used where a case study point is
   conceptual rather than a screenshot. An AI-generated illustration
   would be the first stock-style image on a site that has otherwise
   been typography- and wireframe-driven all the way through; a real
   photo of a doorstep handoff doesn't exist; and fabricating
   "competitor screenshots" would be worse than no image at all. Both
   reuse the check/X marks already used in .cs-jobs__mark and the turn
   section's signal icons, so "yes" and "no" mean the same thing
   everywhere on the site. */

/* "No-contact handoff" — a small 2x2 fact table: did the handoff and
   the tip survive the move to contactless. Corner cell is empty on
   purpose (row labels sit to its left, column labels below it).

   Restyled to match .cs-jobs' language (Product Page Evolution's
   Pro/DIYer comparison) rather than reading as a bordered spreadsheet:
   an icon over a bold name per column, alternating surface bands
   instead of ruled grid lines, an italic closing line. The row-label
   column stays — unlike .cs-jobs' parallel lists, this is a genuine
   fact checked against two conditions, so the row needs a name both
   columns share. */
.cs-exchange {
	display: grid;
	grid-template-columns: 8rem 1fr 1fr;
	max-width: 41.5rem; /* wide enough that "Contactless delivery" holds
	                       one line under its icon and "The handoff" holds
	                       one line in the row-label column — narrower and
	                       both start wrapping */
}

.cs-exchange__head,
.cs-exchange__row {
	display: contents;
}

/* Icon to the LEFT of the name, matching .cs-jobs__col exactly — that
   layout was already corrected once (icon used to sit above the name
   there too) and this diagram should follow the same, current answer
   rather than the superseded one. */
.cs-exchange__col {
	display: flex;
	align-items: center;
	gap: 0.65rem;
	justify-content: center;
	padding: 0.25rem 0.5rem 1rem;
}

.cs-exchange__icon {
	width: 1.75rem;
	height: 1.75rem;
	flex: 0 0 auto;
	color: var(--color-accent);
}

.cs-exchange__icon svg {
	width: 100%;
	height: 100%;
	display: block;
}

.cs-exchange__col-label {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1rem;
	color: var(--color-text);
}

.cs-exchange__row-label {
	display: flex;
	align-items: center;
	padding: 1rem 0.5rem;
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--color-text);
}

.cs-exchange__mark {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 1rem;
}

/* Descriptor row — plain-text characterization of each column before
   the fact rows below it, matching .cs-jobs__cell's first (label-less)
   row rather than adding a separate kicker line above the table. */
.cs-exchange__descriptor {
	margin: 0;
	padding: 0.65rem 0.5rem;
	font-size: 0.8125rem;
	line-height: 1.4;
	text-align: center;
	color: var(--color-muted);
}

/* Banded rows, matching .cs-jobs__cell--band — alternating rather than
   ruled, so the rows read as a set, not a spreadsheet.

   An explicit .cs-exchange__row--band modifier, not a structural
   pseudo-class. :first-child failed here because .cs-exchange__head is
   the real first child; the :first-of-type replacement failed too, for
   a less obvious reason — it matches the first sibling with the same
   TAG name, and .cs-exchange__head is a <div> just like .cs-exchange__row
   is, so it claimed "first div" and neither row ever matched. An
   explicit class on the specific row sidesteps this whole family of
   bugs rather than trying a third structural selector. */
.cs-exchange__row--band .cs-exchange__row-label,
.cs-exchange__row--band .cs-exchange__mark,
.cs-exchange__row--band .cs-exchange__descriptor {
	background: var(--color-surface);
}

.cs-exchange__mark svg {
	width: 1.05rem;
	height: 1.05rem;
	display: block;
}

.cs-exchange__mark--yes {
	color: var(--color-muted);
}

.cs-exchange__mark--no {
	color: var(--color-accent);
}

.cs-exchange__close {
	grid-column: 1 / -1;
	margin: 1.5rem 0 0;
	font-size: 0.875rem;
	font-style: italic;
	color: var(--color-muted);
}

@media (max-width: 30rem) {
	.cs-exchange {
		grid-template-columns: 6.5rem 1fr 1fr;
	}

	.cs-exchange__col-label {
		font-size: 0.875rem;
	}
}

/* "Competitor curbside failure modes" — same numbered-list shape as
   .cs-validation, but each row is a failure (X, accent colour) rather
   than a success criterion (check, muted). The two lists should never
   be visually confusable on the same page. */
.cs-failures {
	display: grid;
	gap: 1.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
	align-content: start;
}

.cs-failures__item {
	display: grid;
	grid-template-columns: 1.5rem 1fr;
	gap: 0.9rem;
	align-items: start;
}

.cs-failures__mark {
	width: 1.5rem;
	height: 1.5rem;
	color: var(--color-accent);
}

.cs-failures__mark svg {
	width: 100%;
	height: 100%;
	display: block;
}

.cs-failures__title {
	font-family: var(--font-sans);
	font-weight: 600;
	font-size: 0.9375rem;
	color: var(--color-text);
	margin: 0 0 0.3rem;
}

.cs-failures__text {
	margin: 0;
	font-size: 0.8125rem;
	line-height: 1.5;
	color: var(--color-muted);
}

/* Tabbed tier carousel — case study content (Product Page Evolution).
   Full container width, one panel at a time, named tabs rather than
   dots because the tier names ARE the takeaway.

   Progressive enhancement: with no JS every panel renders, stacked, and
   the tabs hide themselves — the content is all still there and still
   makes sense. .is-enhanced is added by the script. */
/* Lives in the right column of a .cs-decision__grid (~528px), not at
   full width — so no outer margin, and the frame is capped tighter. */
.tier-carousel {
	margin: 0;
}

.tier-carousel:not(.is-enhanced) .tier-carousel__tabs {
	display: none; /* they do nothing without the script */
}

.tier-carousel__tabs {
	display: flex;
	flex-wrap: wrap;
	/* Wider gap than before — with no border/fill left to mark where one
	   tab ends and the next begins, tight spacing read as one run-on
	   label. Matches .partner-switcher__tabs' gap. */
	gap: 0.5rem 2rem;
	margin-bottom: 1.25rem;
}

/* Color-only states, no fill/border — matches .partner-switcher__tab
   and .earlier-work-tab exactly (Katie's call: wasn't keen on the
   filled-pill active state this used to have, wanted the same
   convention used everywhere else tabs switch content on the site). */
.tier-carousel__tab {
	appearance: none;
	background: none;
	border: none;
	padding: 0;
	font-family: var(--font-sans);
	font-size: 0.8125rem;
	font-weight: 400;
	color: var(--color-muted);
	cursor: pointer;
	transition: color 0.18s ease;
}

.tier-carousel__tab:hover {
	color: var(--color-text);
}

.tier-carousel__tab.is-active {
	font-weight: 600;
	color: var(--color-text);
}

.tier-carousel__tab:focus-visible {
	outline: 2px solid var(--color-accent);
	outline-offset: 2px;
}

/* The UA sheet's [hidden] rule loses to any display set here, so the
   script's panel.hidden would silently do nothing without this. */
.tier-carousel__panel[hidden] {
	display: none;
}

.tier-carousel:not(.is-enhanced) .tier-carousel__panel + .tier-carousel__panel {
	margin-top: 2.5rem;
}

/* Same treatment as the ownership map: a tall page wireframe, capped
   and scrolled rather than shrunk, so it stays legible. */
.tier-carousel__frame {
	max-height: 34rem;
	overflow-y: auto;
	overscroll-behavior: contain;
	background: var(--color-bg);
}

.tier-carousel__frame img {
	display: block;
	width: 100%;
	height: auto;
}

.tier-carousel__note {
	margin: 1rem 0 0;
	font-size: 0.875rem;
	line-height: 1.5;
	color: var(--color-muted);
}

.tier-carousel__note strong {
	color: var(--color-text);
	font-weight: 600;
}

@media (max-width: 40rem) {
	.tier-carousel__frame {
		max-height: 26rem;
	}
}

/* Leadership initiatives — Leadership page only. Replaces the earlier
   .move-row layout, which asserted four TRAITS. Each initiative is one
   long-form unit: situation and response side by side, the measured
   outcome pulled out, then the steps it actually ran in. The Home
   preview is now a two-tier statement, .lead-statement.

   The four now surface as a quadrant grid of short cards
   (.initiative-grid/.initiative-card below); the markup in this block
   — .initiative__head onward — is unchanged from when it rendered
   inline, and is reused as-is inside each card's <dialog> takeover. */

/* Four cards, two columns, a hairline cross dividing them — a literal
   quadrant rather than four boxes with backgrounds or shadows, which
   is the "colour blocking" language this system already uses
   elsewhere (see .cs-tier) applied through structure instead of tint,
   since these four are peers and a tint ramp would wrongly read as a
   ranking. */
.initiative-grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
}

.initiative-card {
	padding: 0 2.5rem 2.5rem 0;
}

.initiative-card:nth-child(odd) {
	border-right: 1px solid var(--color-border);
}

.initiative-card:nth-child(even) {
	padding-right: 0;
	padding-left: 2.5rem;
}

.initiative-card:nth-child(-n+2) {
	border-bottom: 1px solid var(--color-border);
	padding-bottom: 2.5rem;
}

.initiative-card:nth-child(n+3) {
	padding-top: 2.5rem;
}

@media (max-width: 48rem) {
	.initiative-grid {
		grid-template-columns: 1fr;
	}

	.initiative-card,
	.initiative-card:nth-child(odd),
	.initiative-card:nth-child(even) {
		padding: 2.5rem 0;
		border-right: none;
	}

	.initiative-card:first-child {
		padding-top: 0;
	}

	.initiative-card:nth-child(-n+2) {
		border-bottom: 1px solid var(--color-border);
	}

	.initiative-card:last-child {
		border-bottom: none;
		padding-bottom: 0;
	}
}

/* Icon panel — plain surface grey, --color-text glyph, identical across
   all four cards. Only the glyph changes; see the note above on why
   colour doesn't. */
.initiative-card__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 3.5rem;
	height: 3.5rem;
	background: var(--color-surface);
	color: var(--color-text);
	margin-bottom: 1.75rem;
}

.initiative-card__icon-svg {
	width: 1.75rem;
	height: 1.75rem;
	display: block;
}

.initiative-card__title {
	font-family: var(--font-display);
	font-weight: 600;
	font-size: clamp(1.375rem, 2.2vw, 1.75rem);
	line-height: 1.2;
	color: var(--color-text);
	margin: 0 0 0.75rem;
	max-width: 22rem;
}

.initiative-card__preview {
	color: var(--color-muted);
	font-size: 1rem;
	line-height: 1.6;
	margin: 0 0 1.75rem;
	max-width: 26rem;
}

.initiative-card__cta {
	display: inline-flex;
	align-items: center;
	background: none;
	border: none;
	padding: 0;
	font-family: var(--font-sans);
	font-size: 0.95rem;
	font-weight: 600;
	color: var(--color-text);
	text-decoration: underline;
	text-underline-offset: 0.2em;
	cursor: pointer;
}

.initiative-card__cta:hover,
.initiative-card__cta:focus-visible {
	color: var(--color-accent);
}

.initiative-card__cta:focus-visible {
	outline: 2px solid var(--color-accent);
	outline-offset: 3px;
}

.initiative-card__cta:hover .link-icon svg {
	transform: translateX(3px);
}

.initiative__head {
	max-width: 46rem;
	margin-bottom: 2.5rem;
}

.initiative__title {
	font-family: var(--font-display);
	font-weight: 600;
	font-size: clamp(1.375rem, 2.2vw, 1.75rem);
	color: var(--color-text);
	margin: 0 0 0.75rem;
}

.initiative__lede {
	color: var(--color-muted);
	font-size: 1.0625rem;
	margin: 0;
}

/* Matches .cs-decision__text exactly — case studies and Leadership both
   demote "supporting detail under a field label" the same way now
   (gray + slightly smaller), rather than Leadership doing gray-only. */
.initiative__text {
	margin: 0;
	font-size: 0.95rem;
	color: var(--color-muted);
}

/* Diagnostic / response — two separate panels, not one split panel.
   As a single continuous surface the two read as one long box with a
   gap in it; separating them makes them a pair of related cards, which
   is what they actually are. */
.initiative__frame {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 1.25rem;
	margin-bottom: 2.5rem;
	/* No align-items: start here — the two panels MUST match height.
	   Grid's default stretch does it. Ragged bottoms on side-by-side
	   boxes is a thing Katie specifically doesn't want anywhere on
	   this site. */
}

.initiative__field {
	padding: 1.75rem;
	background: var(--color-surface);
}

@media (max-width: 48rem) {
	.initiative__frame {
		grid-template-columns: 1fr;
	}

	.initiative__field {
		padding: 1.5rem;
	}
}

/* Steps. Serif numerals in a narrow gutter — the site's existing
   numeral device. Deliberately not circular badges: every corner here
   is square. (This once read "except the monogram" — that circular
   KK mark has since been replaced by the wordmark.) */
.initiative__steps {
	display: grid;
	gap: 1.75rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.initiative__step {
	display: grid;
	grid-template-columns: 3.25rem 1fr;
	gap: 1.25rem;
	align-items: start;
}

@media (max-width: 40rem) {
	.initiative__step {
		grid-template-columns: 1fr;
		gap: 0.4rem;
	}
}

.initiative__step-number {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 1.5rem;
	line-height: 1.2; /* match the step title's inherited heading
	                      line-height so the numeral sits on the title's
	                      first baseline, not below it */
	color: var(--color-accent);
}

.initiative__step-title {
	font-family: var(--font-sans);
	font-weight: 600;
	font-size: 1rem;
	color: var(--color-text);
	margin: 0 0 0.35rem;
}

/* The evidence row — a fifth row on the steps' grid, but marked with an
   icon in --color-text instead of a terracotta numeral. Same rhythm as
   the method, visibly a different kind of thing: 01-04 are what I do,
   this is what it produced. Gap matches .initiative__steps' own. */
.initiative__proof {
	display: grid;
	grid-template-columns: 3.25rem 1fr;
	gap: 1.25rem;
	align-items: start;
	margin-top: 1.75rem;
}

@media (max-width: 40rem) {
	.initiative__proof {
		grid-template-columns: 1fr;
		gap: 0.4rem;
	}
}

.initiative__proof-icon {
	display: block;
	width: 1.25rem;
	height: 1.25rem;
	color: var(--color-text);
	/* Optically aligns the mark to the title's cap-height. The serif
	   numerals beside it sit on the same line via line-height: 1.2;
	   an icon has no baseline to inherit, so it gets nudged. */
	margin-top: 0.15rem;
}

.initiative__proof-icon svg {
	width: 100%;
	height: 100%;
	display: block;
}

.initiative__proof-title {
	font-family: var(--font-sans);
	font-weight: 600;
	font-size: 1rem;
	color: var(--color-text);
	margin: 0 0 0.35rem;
}

/* The collapsed example, now nested inside the evidence row rather than
   hanging off the bottom of the section — so it loses the rule and the
   large top margin it used to need as a standalone block. */
.initiative__example {
	margin-top: 1rem;
}

.initiative__example-summary {
	display: flex;
	align-items: center;
	gap: 0.7rem;
	padding: 0.4rem 0;
	cursor: pointer;
	font-family: var(--font-sans);
	font-size: 0.875rem;
	font-weight: 600;
	color: var(--color-muted);
	list-style: none; /* Firefox */
}

/* Safari/Chrome draw their own triangle without this. */
.initiative__example-summary::-webkit-details-marker {
	display: none;
}

.initiative__example-summary:hover {
	color: var(--color-accent);
}

.initiative__example-summary:focus-visible {
	outline: 2px solid var(--color-accent);
	outline-offset: 3px;
}

/* Chevron drawn from two borders — no icon file, and it rotates from
   pointing right (closed) to pointing down (open). */
.initiative__example-icon {
	width: 0.5rem;
	height: 0.5rem;
	flex-shrink: 0;
	border-right: 2px solid var(--color-accent);
	border-bottom: 2px solid var(--color-accent);
	transform: rotate(-45deg);
	transform-origin: 55% 55%;
	transition: transform 0.2s ease;
}

.initiative__example[open] .initiative__example-icon {
	transform: rotate(45deg);
}

@media (prefers-reduced-motion: reduce) {
	.initiative__example-icon {
		transition: none;
	}
}

.initiative__example-body {
	padding: 0.75rem 0 0.25rem;
}

/* Grouped by case study — the grouping IS the argument. An initiative
   citing three projects reads as a pattern; the same points in one flat
   list read as one anecdote with a long tail. */
.initiative__example-group + .initiative__example-group {
	margin-top: 1.5rem;
}

.initiative__example-project {
	font-family: var(--font-sans);
	font-size: 0.8125rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--color-text);
	margin: 0 0 0.6rem;
}

.initiative__example-project a {
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

.initiative__example-project a:hover {
	color: var(--color-accent);
}

.initiative__example-list {
	margin: 0;
	padding: 0 0 0 1.1rem;
	display: grid;
	gap: 0.75rem;
	color: var(--color-muted);
	max-width: 44rem;
}

.initiative__example-list li::marker {
	color: var(--color-border);
}

/* Full-screen takeover behind each card's "Learn more" — a native
   <dialog> (see assets/js/initiative-modal.js), so the browser
   supplies the focus trap and Esc-to-close for free.

   A right-anchored panel now, not a full sheet — capped so the
   Leadership page stays visible (and blurred) in the remaining strip
   on the left, which a click on closes it exactly like a click on
   ::backdrop always did: ::backdrop paints across the FULL viewport
   regardless of the dialog's own width, so the exposed strip already
   IS the backdrop and needs no new click handling.

   transform is what slides the panel; overlay/display with
   allow-discrete plus @starting-style below is the standard pattern
   for animating a native <dialog> open AND closed (without it, close()
   removes the dialog from the top layer before a transition could
   run, and only the opening animates). Browsers without support just
   pop open/closed instantly — nothing breaks, it's only the motion
   that's absent. */
.initiative-modal {
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	/* The UA stylesheet centres a modal <dialog> via its own left:0
	   (part of an inset:0 shorthand) plus margin:auto. left:0 competes
	   with right:0 here — with left, right AND width all non-auto at
	   once, left wins the over-constrained resolution and right gets
	   ignored, anchoring the panel to the LEFT edge instead of the
	   right. Explicitly freeing left is what makes right:0 the one
	   that actually resolves. */
	left: auto;
	width: min(70vw, 60rem);
	max-width: 100%;
	max-height: 100%;
	margin: 0;
	padding: 0;
	border: none;
	background: var(--color-bg);
	transform: translateX(100%);
	transition: transform 0.35s ease, overlay 0.35s ease allow-discrete, display 0.35s ease allow-discrete;
}

.initiative-modal[open] {
	transform: translateX(0);
}

@starting-style {
	.initiative-modal[open] {
		transform: translateX(100%);
	}
}

@media (prefers-reduced-motion: reduce) {
	.initiative-modal {
		transition: none;
	}
}

@media (max-width: 48rem) {
	.initiative-modal {
		width: 100%;
	}
}

/* Blur, not a flat dark tint — the one deliberate first on an
   otherwise flat, no-blur-anywhere site, because this is the one
   place the exposed page behind the panel is the point: it's reading
   as "still there, just not what you're doing right now" rather than
   hidden. */
.initiative-modal::backdrop {
	background: rgba(13, 17, 20, 0.28);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	opacity: 0;
	transition: opacity 0.35s ease, overlay 0.35s ease allow-discrete, display 0.35s ease allow-discrete;
}

.initiative-modal[open]::backdrop {
	opacity: 1;
}

@starting-style {
	.initiative-modal[open]::backdrop {
		opacity: 0;
	}
}

@media (prefers-reduced-motion: reduce) {
	.initiative-modal::backdrop {
		transition: none;
	}
}

.initiative-modal__content {
	max-width: 46rem;
	height: 100%;
	margin: 0 auto;
	padding: 6rem 1.5rem 6rem;
	overflow-y: auto;
	box-sizing: border-box;
}

/* No box — a bare icon directly on the panel, same posture as the
   header's email icon (.site-header__cta): colour-only states,
   padding alone gives it a real tap target instead of a visible
   square. */
.initiative-modal__close {
	position: fixed;
	top: 1.75rem;
	right: 1.75rem;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0.75rem;
	background: none;
	border: none;
	color: var(--color-text);
	cursor: pointer;
	transition: color 0.18s ease;
}

.initiative-modal__close:hover,
.initiative-modal__close:focus-visible {
	color: var(--color-accent);
}

.initiative-modal__close:focus-visible {
	outline: 2px solid var(--color-accent);
	outline-offset: 2px;
}

.initiative-modal__close-icon {
	width: 1.125rem;
	height: 1.125rem;
	display: block;
	transition: transform 0.22s ease;
}

/* Same family as the mail icon's "in flight" hover — a quick spin
   rather than a stillness-to-stillness snap. 90deg leaves an X
   looking like an X at rest either side of it, so the motion itself
   is the whole effect, not a different resting shape. */
.initiative-modal__close:hover .initiative-modal__close-icon,
.initiative-modal__close:focus-visible .initiative-modal__close-icon {
	transform: rotate(90deg);
}

@media (prefers-reduced-motion: reduce) {
	.initiative-modal__close-icon {
		transition: none;
	}
}

/* The modal reuses .initiative__head unchanged, but centred content
   this wide no longer wants a 46rem cap fighting the panel's own
   46rem cap — drop it so the header uses the full column. */
.initiative-modal .initiative__head {
	max-width: none;
}

@media (max-width: 40rem) {
	.initiative-modal__content {
		padding: 5rem 1.25rem 4rem;
	}

	.initiative-modal__close {
		top: 1rem;
		right: 1rem;
	}
}

/* Previous/Next footer — click through all four without closing back
   out to the grid. Wraps around; see the docblock in
   leadership-initiatives.php on why a dead end is worse here than a
   loop. */
.initiative-modal__nav {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 1.5rem;
	margin-top: 4rem;
	padding-top: 2.5rem;
	border-top: 1px solid var(--color-border);
}

/* Label (icon + "Previous"/"Next") sits above the title on its own
   line rather than beside it. Inline, the icon was the thing flush
   against the true column edge and the title sat inset from it by the
   icon's width — fine on its own, but it broke the shared left margin
   every other heading in this modal lines up on (Katie caught this:
   Next looked right-aligned, Previous didn't read as left-aligned).
   Stacked, the title is a plain block with nothing before it, so both
   buttons' titles land on the same edges .initiative__head etc. use —
   only the small label row carries the icon inset now. */
.initiative-modal__nav-btn {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.5rem;
	background: none;
	border: none;
	padding: 0;
	font-family: inherit;
	cursor: pointer;
}

.initiative-modal__nav-label {
	display: flex;
	align-items: center;
	gap: 0.5rem;
}

.initiative-modal__nav-btn--next {
	justify-self: end;
	align-items: flex-end;
}

.initiative-modal__nav-title {
	display: block;
	font-family: var(--font-display);
	font-weight: 600;
	font-size: 1.0625rem;
	color: var(--color-text);
}

.initiative-modal__nav-btn--next .initiative-modal__nav-title {
	text-align: right;
}

.initiative-modal__nav-btn:hover .initiative-modal__nav-title,
.initiative-modal__nav-btn:focus-visible .initiative-modal__nav-title {
	color: var(--color-accent);
}

.initiative-modal__nav-btn:focus-visible {
	outline: 2px solid var(--color-accent);
	outline-offset: 4px;
}

.initiative-modal__nav-icon {
	width: 1.25rem;
	height: 1.25rem;
	flex-shrink: 0;
	color: var(--color-text);
	transition: transform 0.18s ease;
}

.initiative-modal__nav-icon--prev {
	transform: scaleX(-1);
}

.initiative-modal__nav-btn--prev:hover .initiative-modal__nav-icon,
.initiative-modal__nav-btn--prev:focus-visible .initiative-modal__nav-icon {
	transform: scaleX(-1) translateX(3px);
}

.initiative-modal__nav-btn--next:hover .initiative-modal__nav-icon,
.initiative-modal__nav-btn--next:focus-visible .initiative-modal__nav-icon {
	transform: translateX(3px);
}

@media (prefers-reduced-motion: reduce) {
	.initiative-modal__nav-icon {
		transition: none;
	}
}

@media (max-width: 40rem) {
	.initiative-modal__nav {
		grid-template-columns: 1fr;
		gap: 1.5rem;
	}

	.initiative-modal__nav-btn--next {
		justify-self: stretch;
		align-items: flex-start;
	}

	.initiative-modal__nav-btn--next .initiative-modal__nav-title {
		text-align: left;
	}
}

/* Homepage leadership statement — two tiers.
   The claim carries display size; the three initiatives sit beneath it
   at a readable size. As one block at 40px the whole thing ran six
   lines, which is the point where display type stops being a statement
   and turns into oversized body copy.
   The claim's 52rem at 40px is roughly a 45-character measure. The list
   is narrower still, so the two have distinct silhouettes rather than
   looking like one paragraph that changed its mind. */
.lead-statement {
	margin: 0 0 2rem; /* matches .case-study-grid so the gap above each
	                     section's text-link is identical */
}

.lead-statement__claim {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: clamp(1.5rem, 3.2vw, 2.5rem);
	line-height: 1.2;
	letter-spacing: -0.015em;
	color: var(--color-text);
	max-width: 52rem;
	margin: 0;
	text-wrap: pretty;
}

.lead-statement__claim strong {
	font-weight: 700;
	color: var(--color-accent);
}

/* "How I partner" tab switcher — prompted by billysweeney.com's
   homepage hero (a row of audience tabs, one large paragraph swapping
   underneath). Replaces the earlier 3x2 grid that showed all six
   partnerships at once; see template-parts/how-i-partner.php. Same
   tablist visual language as .tier-carousel's role="tab" pattern, but
   plain text rather than pill buttons — colour contrast only, no
   border/fill — since this sits at page level rather than inside dense
   case-study content, and pill buttons would read as a filter control. */
.partner-switcher {
	margin: 0;
}

.partner-switcher:not(.is-enhanced) .partner-switcher__tabs {
	display: none; /* they do nothing without the script */
}

.partner-switcher__tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 2rem;
	margin-bottom: 1.25rem;
}

.partner-switcher__tab {
	appearance: none;
	background: none;
	border: none;
	padding: 0;
	font-family: var(--font-sans);
	font-size: 0.9375rem;
	font-weight: 400;
	color: var(--color-muted);
	cursor: pointer;
	transition: color 0.18s ease;
}

.partner-switcher__tab:hover {
	color: var(--color-text);
}

.partner-switcher__tab.is-active {
	font-weight: 600;
	color: var(--color-text);
}

.partner-switcher__tab:focus-visible {
	outline: 2px solid var(--color-accent);
	outline-offset: 3px;
}

/* The UA sheet's [hidden] rule loses to any display set here, so the
   script's panel.hidden would silently do nothing without this. */
.partner-switcher__panel[hidden] {
	display: none;
}

.partner-switcher:not(.is-enhanced) .partner-switcher__panel + .partner-switcher__panel {
	margin-top: 2rem;
}

/* Display-weight statement, not body copy — this is now the section's
   opening move rather than one of six equal grid cells, so it earns a
   scale close to .partner-close__claim below (the section's closing
   statement), reading as a matched pair either side of the switcher. */
.partner-switcher__panel {
	font-family: var(--font-display);
	font-weight: 500;
	font-size: clamp(1.25rem, 2.4vw, 1.75rem);
	line-height: 1.5;
	color: var(--color-text);
	max-width: 46rem;
	margin: 0;
	text-wrap: pretty;
}

/* Switching partners used to hard-cut (panel.hidden flips with no
   transition at all) — every other component touched this session got
   at least a color/position transition, so this one shouldn't be the
   one exception. First attempt only faded the incoming panel in, which
   read as a snap-then-fade rather than one motion (Katie's call: "a
   little jarring") — the outgoing panel vanished instantly with no
   transition of its own. partner-switcher.js now fades the old panel
   out first (--exit, 150ms), then swaps and fades the new one in
   (--enter), forcing a reflow before re-adding either class so it
   restarts on every switch, including the initial panel on load. */
.partner-switcher__panel--enter {
	animation: partner-panel-enter 0.3s ease;
}

.partner-switcher__panel--exit {
	animation: partner-panel-exit 0.15s ease forwards;
}

@keyframes partner-panel-enter {
	from {
		opacity: 0;
		transform: translateY(4px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

@keyframes partner-panel-exit {
	to {
		opacity: 0;
		transform: translateY(-4px);
	}
}

@media (prefers-reduced-motion: reduce) {
	.partner-switcher__panel--enter,
	.partner-switcher__panel--exit {
		animation: none;
	}
}

/* Section closer for "How I partner" — a plain block below the
   switcher now, not a seventh grid cell.

   Same two-tier device as the homepage's .lead-statement, at a smaller
   display size: this closes a section rather than carrying one, and it
   follows the switcher's own display-scale statement, so it should not
   shout as loudly as the homepage statement does after a run of cards. */
.partner-close {
	/* Space alone separates this from the switcher above it — a rule
	   made it read as a divided sub-section rather than as the section
	   resolving. Wider than before now that the section's lede is gone:
	   this is the only place left naming "no shared roadmap, no
	   authority" (the lede used to say the same thing above the
	   switcher), so it needs to read as a deliberate closing beat, not
	   as more text right after the panel. */
	margin-top: 4.5rem;
}

.partner-close__claim {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: clamp(1.25rem, 2.4vw, 1.75rem);
	line-height: 1.3;
	letter-spacing: -0.01em;
	color: var(--color-text);
	max-width: 48rem;
	margin: 0;
	text-wrap: pretty;
}

.partner-close__claim strong {
	font-weight: 700;
	color: var(--color-accent);
}

.partner-close .text-link {
	margin-top: 1.25rem;
}

/* Principles grid — 3x2, hairline dividers directly on each cell (not
   bordered boxes). Previously used a background-color-behind-the-gap
   technique, which was producing an unwanted gray box artifact — plain
   per-cell borders are more predictable and were swapped in instead.
   An outer border ("complete the table") was tried and reverted —
   Katie preferred internal dividers only. */
.principles-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	margin: 0;
	padding: 0; /* <ul> ships a browser-default padding-inline-start for
	               the list marker indent — with .principle-cell's own
	               list-style: none, that indent had nothing to mark but
	               was still shifting the whole grid right of the
	               headline and lede above it. */
	list-style: none;
}

.principle-cell {
	padding: 1.75rem;
	margin: 0;
	list-style: none;
	border-right: 1px solid var(--color-border);
	border-bottom: 1px solid var(--color-border);
}

/* Flush to the container at both edges. Uniform padding made the first
   column start 1.75rem in from the page's left margin and the last stop
   1.75rem short of the right, so the whole grid read as inset against
   the headings and prose above it — which sit flush. Dropping the outer
   padding also widens every cell, so the copy wraps less and the block
   gets shorter. Internal padding stays: it is what keeps text off the
   hairline dividers. */
.principle-cell:nth-child(3n + 1) {
	padding-left: 0;
}

.principle-cell:nth-child(3n) {
	padding-right: 0;
	border-right: none;
}

.principle-cell:nth-last-child(-n+3) {
	border-bottom: none;
}

@media (max-width: 48rem) {
	.principles-grid {
		grid-template-columns: 1fr;
	}

	/* Single column: every cell is both first and last in its row. */
	.principle-cell {
		padding-inline: 0;
		border-right: none;
	}

	.principle-cell:nth-last-child(-n+3) {
		border-bottom: 1px solid var(--color-border);
	}

	.principle-cell:last-child {
		border-bottom: none;
	}
}

.principle-cell__number {
	display: block;
	font-family: var(--font-display);
	font-size: 1.25rem;
	color: var(--color-accent);
	margin-bottom: 0.5rem;
}

.principle-cell__title {
	font-family: var(--font-sans);
	font-weight: 500;
	font-size: 1rem;
	color: var(--color-text);
	margin: 0 0 0.5rem;
}

.principle-cell__body {
	color: var(--color-muted);
	margin: 0;
	font-size: 0.9rem;
}

/* Experience page — role rows. Uses the 12rem label column (dates and
   company beside the role), the same device as the About rows and the
   case study summary. */
.role-row {
	display: grid;
	grid-template-columns: 12rem 1fr;
	gap: 3rem;
	align-items: start;
	padding-block: 2rem;
	border-bottom: 1px solid var(--color-border);
}

.role-row:last-of-type {
	border-bottom: none;
}

@media (max-width: 40rem) {
	.role-row {
		grid-template-columns: 1fr;
		gap: 0.75rem;
	}
}

.role-row__company {
	margin: 0;
	font-family: var(--font-sans);
	font-size: 0.9rem;
	font-weight: 600;
	color: var(--color-text);
}

.role-row__title {
	font-family: var(--font-display);
	font-weight: 600;
	font-size: 1.25rem;
	margin: 0 0 0.85rem;
}

.role-row__highlights {
	margin: 0;
	padding-left: 1.1rem;
	max-width: 44rem;
}

.role-row__highlights li {
	font-family: var(--font-sans);
	font-size: 0.95rem;
	line-height: 1.6;
	color: var(--color-muted);
	margin-bottom: 0.5rem;
}

/* 404 — the oversized numeral is decorative; the real heading follows
   it, so the numeral is aria-hidden and the h1 carries the message. */
.error-404__code {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: clamp(4rem, 14vw, 9rem);
	line-height: 0.9;
	letter-spacing: -0.03em;
	color: var(--color-border);
	margin: 0 0 1rem;
}

.error-404__links {
	display: flex;
	gap: 2.5rem;
	flex-wrap: wrap;
	margin-top: 2.5rem;
}

.error-404__links .text-link {
	margin: 0;
}

/* Generic readable-width wrapper for a block of narrative prose */
.prose {
	max-width: 48rem;
	color: var(--color-muted); /* was unset, so it inherited body's
	                               near-black --color-text — every other
	                               lede/description on the site is muted */
}

/* Emphasis by changing TYPEFACE, not just weight — spotted on
   wearekbd.com (Katie: "I like how she mixes fonts in her paragraphs
   to make words stand out"). Their body copy is serif with bold-sans
   pull phrases; the equivalent swap here is sans body copy with an
   emphasised phrase in the display face, since that's the pairing this
   site already has. First try: Principles' "getting them through the
   org." */
.prose strong {
	font-family: var(--font-display);
	font-weight: 700;
	color: var(--color-text);
}

/* Case-study reference list ("See the principles in action")
   — deliberately lighter than the bordered card component used on
   Home/Work, since this is a third reference point on the site. */
/* Matches .earlier-work-list exactly on Katie's call — same grid + gap
   rhythm, and the same single baseline-aligned line (title, client/date,
   description all riding together, wrapping only if space runs out)
   rather than the meta forced onto its own line underneath. */
.case-study-reference-list {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
	gap: 1rem;
}

.case-study-reference-list__item {
	padding-block: 0.75rem;
}

.case-study-reference-list__link {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem 1.5rem;
	text-decoration: none;
	color: inherit;
	transition: color 0.2s ease, transform 0.2s ease;
}

.case-study-reference-list__text {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 1rem;
	align-items: baseline;
}

.case-study-reference-list__title {
	font-weight: 600;
}

.case-study-reference-list__arrow {
	width: 1rem;
	height: 1rem;
	color: var(--color-muted);
	flex-shrink: 0;
	transition: color 0.2s ease;
}

.case-study-reference-list__arrow svg {
	width: 100%;
	height: 100%;
	display: block;
}

/* Matches .earlier-work-list's hover exactly (Work page, "Selected
   earlier work") — same row shape, same internal-link arrow, so the
   two lists should feel like the same component. Whole row shifts
   color and position together (Katie's call) rather than the title
   underlining on its own and only the arrow sliding — one motion, not
   two competing ones. */
.case-study-reference-list__link:hover,
.case-study-reference-list__link:focus-visible {
	color: var(--color-accent);
	transform: translateX(0.25rem);
}

.case-study-reference-list__link:hover .case-study-reference-list__arrow,
.case-study-reference-list__link:focus-visible .case-study-reference-list__arrow {
	color: var(--color-accent);
}

/* Case study cards / grid */
.case-study-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
	gap: 2rem;
	margin: 0 0 2rem;
	padding: 0;
	list-style: none;
}

.case-study-grid--stacked {
	grid-template-columns: 1fr;
}

/* Work page's Featured section — 3 columns side by side, deliberately
   different from the homepage's stacked treatment */
.case-study-grid--3col {
	grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 64rem) {
	.case-study-grid--3col {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (max-width: 40rem) {
	.case-study-grid--3col {
		grid-template-columns: 1fr;
	}
}

.case-study-card__link {
	display: flex;
	flex-direction: column;
	height: 100%; /* grid items already stretch to equal row height by
	                 default (align-items:stretch); without this, the
	                 card's border only wrapped its own content height,
	                 so cards in the same row still looked uneven even
	                 though their grid cells were the same size */
	position: relative;
	border: 1px solid var(--color-border);
	border-radius: 0; /* half the original 0.875rem — fully sharp
	                             corners read as too severe/cold once tried live */
	padding: 2rem;
	text-decoration: none;
	color: inherit;
	transition: transform 0.25s ease;
}

.case-study-card__link:hover,
.case-study-card__link:focus-visible {
	transform: rotate(-0.4deg) scale(1.012);
}

.case-study-card__arrow {
	position: absolute;
	top: 1.75rem;
	right: 1.75rem;
	width: 1.1rem;
	height: 1.1rem;
	color: var(--color-muted);
}

.case-study-card__arrow-icon,
.case-study-card__arrow svg {
	width: 100%;
	height: 100%;
	display: block;
}

.case-study-card__meta {
	margin: 0 0 0.5rem;
	font-size: 0.875rem;
	color: var(--color-muted);
}

.case-study-card__title {
	margin: 0 0 0.5rem;
	font-size: 1.75rem;
	padding-right: 2rem;
}

.case-study-card__reframe {
	margin: 0 0 1.25rem;
	color: var(--color-muted);
	max-width: 34rem;
}

.case-study-card__stats {
	display: flex;
	flex-wrap: wrap;
	gap: 2rem;
}

.case-study-stat {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
}

.case-study-stat__value {
	font-family: var(--font-display);
	font-size: 1.1rem;
}

.case-study-stat__value--accent {
	color: var(--color-accent);
	font-weight: 600;
}

.case-study-stat__label {
	font-family: var(--font-sans);
	font-size: 0.75rem;
	color: var(--color-muted);
}

/* Deliberately NOT .section-label. This sits right after "How we
   worked" — same bold display heading twice in a row, one saying
   "worked" and the other "work", read as an accidental echo rather
   than two real section openers. It's also a closing/exit moment
   (browse elsewhere, then the footer), not new content, so a quiet
   eyebrow label undersells it correctly instead of announcing it like
   the sections above it. */
.more-work__label {
	display: block;
	margin: 0 0 1.5rem;
	font-family: var(--font-sans);
	font-size: 0.8125rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--color-muted);
}

/* "More work" — end of a case study, three compact cards linking to
   other case studies. Deliberately its own small component rather
   than .case-study-card sized down: same border/no-radius language,
   at roughly a third of the padding, title + one meta line only, no
   reframe sentence, no stat row. Trialled on the style guide as
   title-only vs. title + client/date; Katie picked title + client/date. */
.more-work {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 1.25rem;
}

@media (max-width: 48rem) {
	.more-work {
		grid-template-columns: 1fr;
	}
}

.more-work-card {
	position: relative;
	display: block;
	border: 1px solid var(--color-border);
	padding: 1.25rem 2.25rem 1.25rem 1.25rem;
	text-decoration: none;
	color: inherit;
	transition: transform 0.25s ease;
}

/* Tilt/scale added on Katie's call, matching .case-study-card__link's
   hover. The border-to-black this used to have is gone too — Katie
   wanted consistency across every card on the site (tilt only), after
   trying the black stroke on the featured cards and not liking it
   there. */
.more-work-card:hover,
.more-work-card:focus-visible {
	transform: rotate(-0.4deg) scale(1.012);
}

.more-work-card__arrow {
	position: absolute;
	top: 1.25rem;
	right: 1.25rem;
	width: 0.85rem;
	height: 0.85rem;
	color: var(--color-muted);
}

.more-work-card__arrow svg {
	width: 100%;
	height: 100%;
	display: block;
}

.more-work-card__meta {
	display: block;
	margin-bottom: 0.35rem;
	font-size: 0.8125rem;
	color: var(--color-muted);
}

.more-work-card__title {
	display: block;
	font-family: var(--font-display);
	font-weight: 600;
	font-size: 1.0625rem;
	line-height: 1.3;
	color: var(--color-text);
	padding-right: 1rem;
}

/* Earlier work — category tabs + lightweight list */
.earlier-work-tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 1.75rem;
	margin: 0 0 1.75rem;
	padding: 0;
}

/* Matches .partner-switcher__tab exactly on Katie's call — color
   contrast only (bold + dark when active), not the underline this used
   to carry. Two tab components on the site were using two different
   conventions for the same idea. */
.earlier-work-tab {
	appearance: none;
	background: none;
	border: none;
	padding: 0;
	font-family: var(--font-sans);
	font-size: 0.9rem;
	font-weight: 400;
	color: var(--color-muted);
	cursor: pointer;
	transition: color 0.18s ease;
}

.earlier-work-tab:hover {
	color: var(--color-text);
}

.earlier-work-tab.is-active {
	font-weight: 600;
	color: var(--color-text);
}

.earlier-work-tab:focus-visible {
	outline: 2px solid var(--color-accent);
	outline-offset: 3px;
}

.earlier-work-list {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
	gap: 1rem;
}

.earlier-work-list__item {
	padding-block: 0.75rem;
}

/* Whole row is a link now (title/client/excerpt + a trailing arrow, same
   click affordance as case-study-reference-list) — Katie noted these
   didn't look clickable at all before. .earlier-work-list__item itself
   sets no `display` of its own now, so the browser's built-in
   `[hidden]{display:none}` rule (relied on by work-filter.js) applies
   with no override needed — see the general lesson on this elsewhere
   in the stylesheet: only add a `[hidden]` override when the element
   ALSO sets a competing `display` value. */
.earlier-work-list__link {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem 1.5rem;
	text-decoration: none;
	color: inherit;
	transition: color 0.2s ease, transform 0.2s ease;
}

.earlier-work-list__text {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 1rem;
	align-items: baseline;
}

.earlier-work-list__title {
	font-weight: 600;
}

.earlier-work-list__arrow {
	width: 1rem;
	height: 1rem;
	color: var(--color-muted);
	flex-shrink: 0;
	transition: color 0.2s ease;
}

.earlier-work-list__arrow svg {
	width: 100%;
	height: 100%;
	display: block;
}

/* Whole row shifts color and position together on hover (Katie's
   call) rather than the title underlining on its own and only the
   arrow sliding — one motion, not two competing ones. */
.earlier-work-list__link:hover,
.earlier-work-list__link:focus-visible {
	color: var(--color-accent);
	transform: translateX(0.25rem);
}

.earlier-work-list__link:hover .earlier-work-list__arrow,
.earlier-work-list__link:focus-visible .earlier-work-list__arrow {
	color: var(--color-accent);
}

/* Mentorship Resources page — name + external arrow on one line, an
   optional description below. Same shape as .earlier-work-list, kept
   as its own component rather than reused because that one is
   documented and styled specifically around case studies. */
.resource-list {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
	gap: 1.25rem;
}

.resource-list__item {
	padding-bottom: 1.25rem;
	border-bottom: 1px solid var(--color-border);
}

.resource-list__item:last-child {
	padding-bottom: 0;
	border-bottom: none;
}

.resource-list__link {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	text-decoration: none;
	color: inherit;
}

.resource-list__name {
	font-weight: 600;
	transition: color 0.2s ease;
}

.resource-list__link:hover .resource-list__name,
.resource-list__link:focus-visible .resource-list__name {
	color: var(--color-accent);
	text-decoration: underline;
}

.resource-list__arrow {
	width: 1rem;
	height: 1rem;
	color: var(--color-muted);
	flex-shrink: 0;
	transition: transform 0.2s ease, color 0.2s ease;
}

.resource-list__arrow svg {
	width: 100%;
	height: 100%;
	display: block;
}

.resource-list__link:hover .resource-list__arrow,
.resource-list__link:focus-visible .resource-list__arrow {
	color: var(--color-accent);
	transform: translate(2px, -2px);
}

.resource-list__desc {
	margin: 0.5rem 0 0;
	max-width: 42rem;
	font-size: 0.9rem;
	color: var(--color-muted);
}

/* Plain title-only list — no URLs exist for these, so no link
   treatment (arrow, hover colour) is offered for something that
   doesn't go anywhere. */
.resource-book-list {
	margin: 0;
	padding: 0;
	list-style: none;
	columns: 2;
	column-gap: 3rem;
}

@media (max-width: 40rem) {
	.resource-book-list {
		columns: 1;
	}
}

/* Hairline removed between titles on Katie's call — she didn't like it
   here specifically (the rest of the page keeps its dividers). Padding
   alone carries the separation between book titles now. */
.resource-book-list li {
	padding-block: 0.75rem;
	break-inside: avoid;
}

.resource-disclaimer {
	margin: 0;
	max-width: 42rem;
	font-size: 0.85rem;
	font-style: italic;
	color: var(--color-muted);
}

/* Contact page — simple, uncluttered list of reach-me methods */
.contact-list {
	margin: 0 0 3rem;
	padding: 0;
	list-style: none;
	display: grid;
	gap: 0.25rem;
	max-width: 24rem;
}

.contact-list__item {
	border-bottom: 1px solid var(--color-border);
}

.contact-list__item a {
	display: flex;
	justify-content: space-between;
	padding-block: 0.9rem;
	text-decoration: none;
}

.contact-list__item a:hover {
	color: var(--color-accent);
}

.contact-list__label {
	color: var(--color-muted);
	font-size: 0.9rem;
}

/* Single case study — hero: eyebrow, title, subtitle, lede, and a cover
   image when one is set. The two-column split only applies when a cover
   image actually exists; without one the hero runs full width (a fixed
   grid split used to run unconditionally and squeezed the title into
   half the container on every case study, since none have covers yet). */
.case-study-header {
	padding-block: 2.5rem 0;
}

.case-study-hero--with-cover {
	display: grid;
	grid-template-columns: 1.1fr 1fr;
	gap: 3rem;
	align-items: start;
}

@media (max-width: 56rem) {
	.case-study-hero--with-cover {
		grid-template-columns: 1fr;
	}
}

.case-study-hero__eyebrow {
	font-family: var(--font-sans);
	font-size: 0.75rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--color-muted);
	margin: 0 0 1.25rem;
}

.case-study-hero__title {
	font-size: clamp(2.25rem, 5vw, 3.75rem);
	line-height: 1.05;
	margin: 0 0 1rem;
}

.case-study-hero__subtitle {
	font-family: var(--font-display);
	font-size: clamp(1.25rem, 2vw, 1.5rem);
	line-height: 1.3;
	color: var(--color-text);
	margin: 0;
	/* Wide enough that a subtitle of this length holds one line on
	   desktop (34rem was breaking it in two), but still capped so a
	   longer one on a future case study keeps a readable measure. */
	max-width: 56rem;
}

.case-study-cover {
	width: 100%;
	border-radius: 0;
	overflow: hidden;
}

/* "What changed" outcomes — a literal quadrant grid (Katie's call, same
   structural "colour blocking" language as .initiative-grid on the
   Leadership page: a hairline cross dividing four peers, rather than
   the fixed-label-column rows this used to be). Most case studies carry
   exactly four metrics; one (Contactless Ordering) has three — the
   third simply lands alone in row two with no stray divider, via the
   :last-child override below. */
.cs-outcomes {
	display: grid;
	grid-template-columns: 1fr 1fr;
	margin: 0;
	padding: 0;
	list-style: none;
}

.cs-outcome {
	padding: 0 2.5rem 2rem 0;
}

.cs-outcome:nth-child(odd) {
	border-right: 1px solid var(--color-border);
}

.cs-outcome:nth-child(odd):last-child {
	border-right: none;
}

.cs-outcome:nth-child(even) {
	padding-right: 0;
	padding-left: 2.5rem;
}

.cs-outcome:nth-child(-n+2) {
	border-bottom: 1px solid var(--color-border);
	padding-bottom: 2rem;
}

.cs-outcome:nth-child(n+3) {
	padding-top: 2rem;
}

@media (max-width: 48rem) {
	.cs-outcomes {
		grid-template-columns: 1fr;
	}

	.cs-outcome,
	.cs-outcome:nth-child(odd),
	.cs-outcome:nth-child(even) {
		padding: 2rem 0;
		border-right: none;
	}

	.cs-outcome:first-child {
		padding-top: 0;
	}

	.cs-outcome:last-child {
		padding-bottom: 0;
	}
}

.cs-outcome__stat {
	display: block;
	font-family: var(--font-sans);
	font-weight: 700;
	font-size: clamp(1.75rem, 3vw, 2.25rem);
	line-height: 1.1;
	color: var(--color-text);
	margin-bottom: 0.5rem;
	font-variant-numeric: tabular-nums;
}

/* Progressive enhancement for outcome-stat-count.js: the pending class
   (added only once the script runs) starts a stat invisible so it can
   fade/count up as the quadrant scrolls into view; without JS, or with
   prefers-reduced-motion, stats render at full opacity immediately,
   same as before this existed. */
.cs-outcome__stat--pending {
	opacity: 0;
	transform: translateY(6px);
	transition: opacity 0.4s ease, transform 0.4s ease;
}

.cs-outcome__stat--pending.cs-outcome__stat--revealed {
	opacity: 1;
	transform: translateY(0);
}

/* The arrow in a before/after stat ("72% → 88%") can't count up like a
   plain number, so it bounces toward the after-value instead once
   revealed — pointing at the change rather than counting it. */
.cs-outcome__stat-arrow {
	display: inline-block;
}

.cs-outcome__stat--revealed .cs-outcome__stat-arrow {
	animation: cs-outcome-arrow-bounce 0.6s ease 0.15s both;
}

@keyframes cs-outcome-arrow-bounce {
	0% {
		transform: translateX(0);
	}
	40% {
		transform: translateX(6px);
	}
	70% {
		transform: translateX(-2px);
	}
	100% {
		transform: translateX(0);
	}
}

@media (prefers-reduced-motion: reduce) {
	.cs-outcome__stat--revealed .cs-outcome__stat-arrow {
		animation: none;
	}
}

.cs-outcome__label {
	display: block;
	font-family: var(--font-sans);
	font-weight: 600;
	font-size: 1rem;
	margin-bottom: 0.5rem;
}

.cs-outcome__caption {
	margin: 0;
	font-family: var(--font-sans);
	font-size: 0.95rem;
	color: var(--color-muted);
	max-width: 34rem;
}

.cs-outcome__attribution {
	margin: 0.5rem 0 0;
	font-family: var(--font-sans);
	font-size: 0.85rem;
	font-style: italic;
	color: var(--color-muted);
}

/* Attribution / Reflection — the honest close, two columns. */
.cs-closing {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 4rem;
	margin-block: 4.5rem;
}

@media (max-width: 48rem) {
	.cs-closing {
		grid-template-columns: 1fr;
		gap: 2.5rem;
	}
}

.cs-closing__field + .cs-closing__field {
	margin-top: 1.75rem;
}

.cs-closing__text {
	margin: 0;
	font-family: var(--font-sans);
	font-size: 0.95rem;
	color: var(--color-muted);
	max-width: 30rem;
}

/* Earlier Work's counterpart to .case-study-exec-summary below — no
   box, no labelled Problem / What I did split, no separate "Where it
   landed" band. Three columns instead: a short unlabelled summary,
   Role · Scope · Client, and the single headline metric (there's
   usually just one, for these lighter entries) — .cs-outcome__stat /
   __label / __caption reused verbatim from the metrics band further
   down the page, since it's the same fact told once instead of twice.
   Everything else on the page (the decision blocks below, text-left /
   image-right) matches a featured case study exactly; this strip is
   the one section Earlier Work does differently. */
.cs-summary {
	display: grid;
	grid-template-columns: 1fr 12rem 15rem;
	gap: 3rem;
	align-items: start;
	margin-top: 3rem;
	padding-top: 2.5rem;
	border-top: 1px solid var(--color-border);
}

/* Image-only entries (no _cs_mandate, so no "The gist" field renders at
   all — see the PHP's `if ( $mandate )`) drop the gist column entirely
   and let Role/Scope/Client/Credit spread across the full width as a
   row instead of stacking in the narrow sidebar column they use
   alongside a gist. :has() detects this from the actual markup, so it
   needs no template change or extra class. */
.cs-summary:not(:has(.cs-summary__lede)) {
	grid-template-columns: 1fr;
}

.cs-summary:not(:has(.cs-summary__lede)) .cs-summary__meta {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 1.25rem 3rem;
}

@media (max-width: 48rem) {
	.cs-summary {
		grid-template-columns: 1fr;
		gap: 1.75rem;
	}

	.cs-summary:not(:has(.cs-summary__lede)) .cs-summary__meta {
		grid-template-columns: 1fr;
	}
}

.cs-summary__lede {
	margin: 0;
	font-size: 1rem;
	line-height: 1.6;
	color: var(--color-text);
}

.cs-summary__meta {
	display: flex;
	flex-direction: column;
	gap: 1.25rem;
}

.cs-summary__field {
	display: flex;
	flex-direction: column;
}

/* Tighter than .cs-microlabel's own 0.6rem everywhere else on the
   site — Katie wanted label and value read as one unit here, closer
   than the site's usual label-to-body rhythm. Scoped to this strip so
   .cs-microlabel's default spacing elsewhere is untouched. */
.cs-summary__field .cs-microlabel,
.cs-summary__impact .cs-microlabel {
	margin-bottom: 0.25rem;
}

.cs-summary__value {
	margin: 0;
	font-size: 1rem;
	color: var(--color-text);
}

.cs-summary__impact {
	max-width: 20rem;
}

.cs-summary__impact .cs-outcome__stat {
	margin-bottom: 0.2rem;
}

/* Summary panel — sidebar heading, a Problem / What I did pair, then
   hairline label-value rows. Katie compared this layout against a
   version rebuilt from .about-row's label+rule device and preferred
   this one; the copy is what got rewritten out of the reference page's
   vocabulary ("Executive summary" → "The short version", and the field
   labels are hers now). */
/* Bottom border restored (Katie wants the gist visibly closed off, not
   just opened). This previously produced a doubled hairline on Screen
   to Aisle and Checkout & Apple Pay specifically, whose content starts
   directly with a .cs-decision — which draws its own border-top — with
   nothing between them but margin. The actual fix is on .cs-decision
   below (border suppressed only when it's the very first thing in
   .case-study-body), not dropping this rule again. */
.case-study-exec-summary {
	display: grid;
	grid-template-columns: 12rem 1fr;
	gap: 4rem;
	margin-block: 5rem;
	padding-block: 4rem;
	border-top: 1px solid var(--color-border);
	border-bottom: 1px solid var(--color-border);
	align-items: start;
}

@media (max-width: 48rem) {
	.case-study-exec-summary {
		grid-template-columns: 1fr;
		gap: 1.5rem;
	}
}

.case-study-exec-summary__heading {
	margin: 0;
}

.case-study-exec-summary__body {
	display: flex;
	flex-direction: column;
}

.case-study-exec-summary__intro {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 4rem;
	/* No rule under this pair: it read as a divider sitting above the
	   Role row rather than as the close of the problem/solution block.
	   Separation comes from the gap below instead. */
	padding-bottom: 0;
}

@media (max-width: 40rem) {
	.case-study-exec-summary__intro {
		grid-template-columns: 1fr;
		gap: 1.5rem;
	}
}

.case-study-exec-summary__label,
.case-study-exec-summary__row-label {
	display: block;
	line-height: 1.4;
	font-family: var(--font-sans);
	font-size: 0.75rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--color-muted);
	margin-bottom: 0.5rem;
}

.case-study-exec-summary__value,
.case-study-exec-summary__row-value {
	margin: 0;
	color: var(--color-text);
}

/* Same font-swap emphasis as .prose strong (Principles) — "The
   problem" is the one paragraph per case study that gets it, not
   every field, so it stays a rare beat rather than a template rule. */
.case-study-exec-summary__value strong {
	font-family: var(--font-display);
	font-weight: 700;
}

.case-study-exec-summary__rows {
	display: flex;
	flex-direction: column;
	margin-top: 3rem;
}

.case-study-exec-summary__row {
	display: grid;
	grid-template-columns: 12rem 1fr;
	gap: 1.5rem;
	padding-block: 1.15rem;
	border-bottom: 1px solid var(--color-border);
}

.case-study-exec-summary__row:last-child {
	border-bottom: none;
}

@media (max-width: 40rem) {
	.case-study-exec-summary__row {
		grid-template-columns: 1fr;
		gap: 0.5rem;
	}
}

.case-study-exec-summary__row-label {
	margin-bottom: 0;
}

/* Full-bleed tinted band — the page's rhythm device, alternating with
   white. Uses --color-surface, a near-neutral value shift rather than a
   new hue, so it stays clear of the color-blocking rejected elsewhere on
   this site. Must sit OUTSIDE .container to reach the viewport edges. */
/* Straight from the inverted section into the band — a strip of white
   between two full-bleed colour sections read as an accident. */
.cs-turn + .cs-band {
	margin-top: 0;
}

.cs-band {
	background: var(--color-surface);
	padding-block: 5rem;
	margin-block: 6rem; /* collapses with the preceding section's margin;
	                       deliberately generous so the summary above has
	                       room to breathe before the band starts */
}

.cs-band__grid {
	display: grid;
	grid-template-columns: 18rem 1fr;
	gap: 3rem;
	align-items: start;
	margin-bottom: 3rem;
}

/* Used where the grid holds the section's content directly (heading
   left, columns right) rather than acting as a header above a list. */
.cs-band__grid--flush {
	margin-bottom: 0;
}

@media (max-width: 48rem) {
	.cs-band__grid {
		grid-template-columns: 1fr;
		gap: 1rem;
		margin-bottom: 2rem;
	}
}

/* Sizing comes from .section-label (applied alongside in the markup) so
   every section heading on the page shares one scale and can't drift —
   these had grown four different sizes before. */
.cs-band__heading {
	margin: 0;
}

.cs-band__lede {
	font-family: var(--font-sans);
	font-size: 1rem;
	color: var(--color-muted);
	margin: 0;
	max-width: 32rem;
}

.cs-band__columns {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 2.5rem;
}

@media (max-width: 48rem) {
	.cs-band__columns {
		grid-template-columns: 1fr;
		gap: 2rem;
	}
}

.cs-band__text {
	margin: 0;
	font-family: var(--font-sans);
	font-size: 0.95rem;
	color: var(--color-text);
}

/* Section lead-in with its supporting figure alongside: heading and
   intro line in a narrow left column, the figure in the wider right one.
   Shares the band's 18rem column so the two sections' grid lines align
   down the page, and it narrows the figure, which ran too wide at the
   full container width. */
.cs-split {
	display: grid;
	grid-template-columns: 18rem 1fr;
	gap: 3rem;
	align-items: start;
	margin: 4rem 0;
}


/* Scoped to Contactless Ordering's exchange-table lede, not a change to
   .cs-split generally — Header and PPE's cs-split figures are full
   screenshots that want the wider 1fr slot; this one's lede was
   wrapping to three lines in the same fixed 18rem, and the diagram next
   to it (now capped at 28rem, above) doesn't need the extra room the
   wider text column takes back. */
.cs-split--tight {
	grid-template-columns: 24rem 1fr;
}

@media (max-width: 48rem) {
	.cs-split {
		grid-template-columns: 1fr;
		gap: 1.5rem;
	}
}

.cs-split__heading {
	margin: 0 0 1rem;
}

.cs-split__lede {
	margin: 0;
	font-family: var(--font-sans);
	font-size: 0.95rem;
	color: var(--color-muted);
}

/* The figure is a grid column here, so its standalone margin would push
   it out of line with the heading beside it. */
.cs-split .cs-figure {
	margin: 0;
}

/* Shared micro-label — the device that keeps this page from reading as
   paragraph after paragraph. Every short block of prose gets one. The
   label VOCABULARY is Katie's (THE SITUATION / THE CALL / WHAT IT COST /
   HOW I KNEW / MINE / THE TEAM'S), deliberately rewritten off the
   reference page's CONTEXT / DECISION / TRADEOFF / EVIDENCE set.

   Muted, NOT terracotta: there are ~22 of these on a case study page,
   and in the accent colour they diluted it to wallpaper. Terracotta is
   now rationed on this template to three places — the hero eyebrow, the
   two summary labels, and the closing principle's rule. */
.cs-microlabel {
	display: block;
	font-family: var(--font-sans);
	font-size: 0.7rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--color-muted);
	margin-bottom: 0.6rem;
}

/* "Holding the line at launch" — the story's peak: the launch metrics
   looked bad and Katie argued against a rollback. It has to stand out,
   but near-black was too heavy ("the black background... it's just too
   much here"), so it takes a warm cream full-bleed band instead —
   distinctly warmer than the near-neutral --color-surface used by the
   other two bands, so it reads as its own moment rather than a third
   repeat. The cream version of this was dropped when the palette went
   cool — warm cream fought the blue-grey neutrals. */
.cs-turn {
	background: var(--color-surface-deep);
	padding-block: 6rem;
	margin-block: 6rem 0; /* the outcomes band butts straight up beneath */
	overflow-x: clip; /* a bleeding child must not give the PAGE a
	                     horizontal scrollbar. clip, not hidden — hidden
	                     would make this a scroll container and break
	                     position: sticky for anything inside it. */
}

.cs-turn__grid {
	display: grid;
	grid-template-columns: 1.35fr 1fr;
	gap: 4.5rem;
	align-items: start;
}

/* Nothing in the right column — don't leave a 1fr hole beside the
   narrative. */
.cs-turn__grid--single {
	grid-template-columns: 1fr;
}

/* The figure that fills the right column when a turn has no signal
   metrics. align-items: start above means it tops out with the
   narrative rather than centring against it. */
.cs-turn__figure {
	min-width: 0;
}

/* Split layout: text column left, image column right running the FULL
   height of the section and off the right edge of the viewport.

   The section itself becomes the grid — no .container — so the image
   column can touch the top and bottom edges. The text column carries
   the container's alignment instead: max() reproduces the centred
   72rem container's left gutter, collapsing to the plain 1.5rem padding
   once the viewport is narrower than the container.

   Why it scrolls rather than scaling to fit: the asset is a whole
   product page, far taller than any section should be. Not being able
   to see all of it at once IS the argument the section is making. */
.cs-turn--split {
	display: grid;
	grid-template-columns: 1fr 1fr;
	align-items: stretch;
	padding-block: 0; /* the figure has to reach both edges */
}

.cs-turn__col {
	padding-block: 6rem;
	padding-left: max(1.5rem, calc((100vw - 72rem) / 2 + 1.5rem));
	padding-right: 3.5rem;
	min-width: 0;
}

/* position/inset rather than height:100% — a stretched grid item
   resolves its height late, and a percentage height on the child can
   come out as auto. Absolute inset is unambiguous. */
.cs-turn--split .cs-turn__figure {
	position: relative;
	overflow: hidden;
	min-width: 0;
}

.cs-turn--split .cs-turn__figure-scroll {
	position: absolute;
	inset: 0;
	overflow-y: auto;
	overscroll-behavior: contain; /* don't chain to the page at the ends */
	background: var(--color-bg);
}

.cs-turn__figure-img {
	display: block;
	width: 100%;
	height: auto;
}

@media (max-width: 60rem) {
	/* Stacked: the image can no longer take its height from a text
	   column beside it, so it gets an explicit one. */
	.cs-turn--split {
		grid-template-columns: 1fr;
	}

	.cs-turn__col {
		padding-block: 4rem;
		padding-right: 1.5rem;
	}

	.cs-turn--split .cs-turn__figure {
		height: 26rem;
	}
}

/* Ownership key for the wireframe. Sits under the narrative because the
   image bleeds off-screen and has no room for one. */
.cs-turn__legend {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem 1.75rem;
	margin: 2rem 0 0;
	padding: 0;
	list-style: none;
}

.cs-turn__legend-item {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	font-size: 0.875rem;
	color: var(--color-muted);
}

.cs-turn__legend-swatch {
	width: 1.5rem;
	height: 1rem;
	flex-shrink: 0;
}

@media (max-width: 48rem) {
	.cs-turn__grid {
		grid-template-columns: 1fr;
		gap: 2.5rem;
	}
}

/* Sits above the two-column grid, not inside it, so the signals column
   starts level with the first paragraph rather than with the heading. */
.cs-turn__heading {
	margin: 0 0 2.25rem;
}

.cs-turn__text {
	font-family: var(--font-sans);
	font-size: 1rem;
	line-height: 1.7;
	margin: 0 0 1.25rem;
	color: var(--color-text);
	max-width: 44rem;
}

.cs-turn__text:last-child {
	margin-bottom: 0;
}

/* Signals stack vertically, all at one size. An earlier version sized
   only the dipped metric large, which made the section read as nothing
   but bad news; and colouring it terracotta made the brand accent mean
   "bad". All four now share a treatment — the story is that one dipped
   while the rest held or climbed, and that only reads if they match. */
/* Status glyph in its own column so the marks line up vertically: at a
   glance it reads as one X and three checks. Both glyphs are the same
   neutral colour on purpose — colouring the negative one was tried and
   made the whole section read as bad news. Shape carries the meaning. */
.cs-turn__signal {
	display: grid;
	grid-template-columns: 1.5rem 1fr;
	gap: 1.25rem;
	align-items: start;
	padding-block: 1.25rem;
	border-bottom: 1px solid var(--color-border);
}

.cs-turn__signal-icon {
	width: 1.5rem;
	height: 1.5rem;
	margin-top: 0.3rem; /* optical alignment with the numeral's cap height */
	color: var(--color-text);
}

.cs-turn__signal-icon svg {
	width: 100%;
	height: 100%;
	display: block;
}

.cs-turn__signal:first-child {
	padding-top: 0;
}

.cs-turn__signal:last-child {
	border-bottom: none;
}

.cs-turn__signal-value {
	display: block;
	font-family: var(--font-sans);
	font-weight: 700;
	font-size: clamp(1.75rem, 3vw, 2.25rem);
	line-height: 1.1;
	color: var(--color-text);
	margin-bottom: 0.4rem;
	white-space: nowrap;
}

.cs-turn__signal-label {
	display: block;
	font-family: var(--font-sans);
	font-size: 0.75rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--color-muted);
}

/* The closing statement — the line the whole section builds to.

   The principle is lifted onto its own oversized line with the sentence
   around it set small, so the emphasis lands on the principle rather
   than on the sentence that happens to contain it.

   Deliberately NOT the terracotta-bordered pull-quote device: that
   belongs to .mentorship-quote and the body blockquote, where the words
   are someone else's. This line is Katie's own conclusion. */
/* Hairline restored — tried removing it along with the .cs-decision
   dividers, but this one earns its place: unlike a Move (which closes
   with its own "what it unlocked" box before the next one starts),
   nothing marks the jump from small narrative/legend text straight
   into this oversized pulled statement without it. Same job as the
   left-border accent on a blockquote pull-quote elsewhere on the
   site — it signals "something set apart starts here", not just a
   boundary that already had one. */
.cs-turn__close {
	margin: 3.5rem 0 0;
	padding-top: 2.75rem;
	border-top: 1px solid var(--color-border);
	/* In the split layout this sits inside the text column, so the
	   principle's 46rem cap below is wider than its container and the
	   column does the wrapping. Nothing to change — noted so the cap
	   doesn't look like a bug. */
	/* No cap here — the principle needs room to hold one line. The
	   lead-in and trailing sentence are capped individually instead. */
}

.cs-turn__close-lead,
.cs-turn__close-after {
	display: block;
	font-family: var(--font-sans);
	font-size: 1rem;
	line-height: 1.6;
	color: var(--color-muted);
	max-width: 32rem;
}

.cs-turn__close-principle {
	display: block;
	font-family: var(--font-display);
	/* Sized so a principle of this length holds one line on desktop —
	   wrapped across two it was impossible to judge. text-wrap: balance
	   keeps the break sensible if a longer one does wrap. */
	font-size: clamp(1.5rem, 3.2vw, 2.5rem);
	font-weight: 400;
	line-height: 1.15;
	letter-spacing: -0.015em;
	color: var(--color-text);
	margin-block: 0.9rem;
	max-width: 46rem;
	text-wrap: balance;
}

/* "What it unlocked" — the payoff closing each decision. A thin outlined
   box spanning the decision, with an unlocked-padlock mark in its own
   left column. Not an arrow: the two arrows already mean "stays on the
   site" and "leaves the site". */
.cs-outcome-bar {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 1.25rem;
	align-items: start;
	margin-top: 2.75rem;
	padding: 1.5rem 1.75rem;
	border: 1px solid var(--color-border);
}

@media (max-width: 36rem) {
	.cs-outcome-bar {
		grid-template-columns: 1fr;
		gap: 1rem;
	}
}

.cs-outcome-bar__icon {
	width: 1.5rem;
	height: 1.5rem;
	color: var(--color-muted);
	flex-shrink: 0;
}

.cs-outcome-bar__icon svg {
	width: 100%;
	height: 100%;
	display: block;
}

.cs-outcome-bar__label {
	display: block;
	font-family: var(--font-sans);
	font-size: 0.7rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--color-muted);
	margin-bottom: 0.5rem;
}

.cs-outcome-bar__text {
	margin: 0;
	font-family: var(--font-sans);
	font-size: 1rem;
	line-height: 1.55;
	color: var(--color-text);
}

/* Case study body. The 42rem reading measure is applied to the PROSE
   elements rather than the whole container, so figures and decision
   blocks can use the container's full width while paragraphs keep a
   comfortable line length. (Capping the container itself meant every
   multi-column figure was squeezed into the prose column.) */
.case-study-body > p,
.case-study-body > ul,
.case-study-body > ol,
.case-study-body > blockquote {
	max-width: 42rem;
}

/* Plain hairline, for the rare case a case study needs a visible break
   between "The gist" and its first Move (Checkout & Apple Pay: with no
   .cs-split/.cs-flow intro before it and .cs-decision:first-child's
   margin zeroed — see the note there — the two sections otherwise sat
   with almost no separation at all). Not used by every case study;
   added directly in the ones that need it. */
.case-study-body > hr {
	border: none;
	border-top: 1px solid var(--color-border);
	margin: 3.5rem 0;
}

.case-study-body > h2 {
	font-family: var(--font-display);
	font-weight: 600;
	font-size: clamp(1.5rem, 2.5vw, 1.875rem);
	margin: 3.5rem 0 1.25rem;
	max-width: 42rem;
}

/* Pull-quote — without this it renders on browser defaults (indented
   italic), which reads as an accident rather than emphasis. */
.case-study-body > blockquote {
	margin: 2.5rem 0;
	padding-left: 1.75rem;
	border-left: 3px solid var(--color-accent);
}

.case-study-body > blockquote p {
	font-family: var(--font-display);
	font-size: clamp(1.25rem, 2vw, 1.5rem);
	line-height: 1.4;
	margin: 0;
}

/* Numbered decision block — the narrative core. Micro-labelled short
   paragraphs on the left, supporting image on the right, and a
   near-black bar underneath stating what the decision unlocked.
   (A variant using the serif-numeral + rule device — .move-row then,
   .initiative__step-number now — was
   tried; Katie preferred this eyebrow-label form. The numbering copy is
   hers — "Call 01", matching the "Three calls that changed it" section
   title, rather than the reference page's "DECISION 01".) */
/* Hairline between Moves removed on Katie's call: each Move already
   ends in a bordered "what it unlocked" box (.cs-outcome-bar), which
   reads as its own natural close — a rule immediately after it doubled
   up the separation. Spacing alone (this margin) carries the break
   now. */
.cs-decision {
	margin: 4rem 0;
}

/* Screen to Aisle and Checkout & Apple Pay start their content
   directly with a Move — no .cs-split/.cs-flow intro first — so
   without this, the first Move's own top margin would stack with
   "The gist"'s bottom margin across the two .container wrappers
   between them (they're not adjacent siblings, so the margins don't
   collapse on their own), leaving far more air than any other gap on
   the page. */
.case-study-body > .cs-decision:first-child {
	margin-top: 0;
}

.cs-decision__number {
	display: block;
	font-family: var(--font-sans);
	font-size: 0.7rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--color-muted);
	margin-bottom: 1rem;
}

.cs-decision__title {
	font-family: var(--font-display);
	font-weight: 600;
	font-size: clamp(1.5rem, 2.5vw, 2rem);
	line-height: 1.15;
	margin: 0 0 2rem;
	max-width: 30rem;
}

.cs-decision__grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 3rem;
	align-items: start;
}

@media (max-width: 48rem) {
	.cs-decision__grid {
		grid-template-columns: 1fr;
		gap: 2rem;
	}
}

.cs-decision__field + .cs-decision__field {
	margin-top: 1.75rem;
}

.cs-decision__text {
	margin: 0;
	font-family: var(--font-sans);
	font-size: 0.95rem;
	color: var(--color-muted);
}

/* Inside a decision the image is a grid column, so its own standalone
   margin would push it out of line with the text column beside it.
   .cs-figure needs the same override — missing here, its own
   margin: 3rem 0 pushed real screenshots down out of alignment with
   the text (Katie caught this on Screen to Aisle's Move 03). */
.cs-decision__grid .case-study-image-placeholder,
.cs-decision__grid .cs-figure {
	margin: 0;
}

/* About page — single photo beside the tagline/supporting text. An
   offset colour-block version, then a tilted soft-shadow version, were
   both tried and reverted — Katie only meant to drop the styling, not
   go back to the 3-photo grid: plain photo, original single-photo +
   beside-text layout kept. */
.about-intro {
	display: flex;
	align-items: flex-start;
	gap: 3rem;
	flex-wrap: wrap;
	margin-bottom: 2rem;
}

.about-photo {
	width: 16rem;
	max-width: 100%;
	flex-shrink: 0;
}

.about-photo img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 1;
	object-fit: cover;
}

.about-intro__text {
	flex: 1 1 18rem;
	padding-top: 0.5rem;
}


/* About page — label-left, content-right rows for "About Katie" / What
   I do / How I work / Client experience, matching Katie's live site
   rather than a heading stacked above its content */
.about-row {
	display: grid;
	grid-template-columns: 12rem 1fr;
	gap: 3rem;
	align-items: start;
}

@media (max-width: 40rem) {
	.about-row {
		grid-template-columns: 1fr;
	}
}

.about-row__label {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	margin: 0;
}

.about-row__rule {
	flex: 1;
	height: 1px;
	background: var(--color-border);
}

/* About page — "What I do" capability list */
.capability-list {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
	gap: 0 2rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.capability-list li {
	padding-block: 0.75rem;
}

.client-group__label {
	display: block;
	font-weight: 700;
	margin-bottom: 0.4rem;
}

.client-group__names {
	color: var(--color-muted);
	margin: 0;
}

/* About page — "Client experience" groups */
.client-groups {
	display: grid;
	gap: 2rem;
	margin: 0;
}

/* Password gate for a locked case study — sits right after "the gist",
   replacing the rest of the page. A self-contained bordered panel (the
   same 1px var(--color-border) box .case-study-card already uses)
   rather than a full-bleed hairline section, so it never risks doubling
   up against whichever gist variant's own border sits directly above it
   (.case-study-exec-summary ends in one already; see the project's
   earlier double-hairline bug). */
.cs-locked {
	max-width: 30rem;
	margin: 3rem auto 5rem;
	padding: 2.5rem 2rem;
	border: 1px solid var(--color-border);
	text-align: center;
}

.cs-locked__text {
	color: var(--color-muted);
	margin: 0 0 1.5rem;
}

.cs-locked__form {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	gap: 0.75rem;
}

.cs-locked__input {
	flex: 1 1 12rem;
	max-width: 16rem;
	padding: 0.7rem 1rem;
	font-family: inherit;
	font-size: 0.9rem;
	color: var(--color-text);
	border: 1px solid var(--color-border);
	border-radius: 0;
}

.cs-locked__form.is-checking .btn {
	opacity: 0.6;
}

.cs-locked__error {
	width: 100%;
	margin: 0.75rem 0 0;
	font-size: 0.85rem;
	color: var(--color-accent);
}

/* case-study-lock.js fades this out, swaps in the real content behind
   the gate, then fades it back in — see #cs-gated-content in
   single-case_study.php. No-JS visitors never see this class; the form
   just does a normal full-page submit instead. */
#cs-gated-content {
	transition: opacity 0.3s ease;
}

#cs-gated-content.cs-gated-content--fading {
	opacity: 0;
}

@media (prefers-reduced-motion: reduce) {
	#cs-gated-content {
		transition: none;
	}
}

/* Contact form — unused since round 5 moved contact info into the global
   footer (see below), left in place in case a form comes back later */
.contact-form {
	display: grid;
	gap: 1rem;
	max-width: 32rem;
}

.contact-form label {
	display: block;
	margin-bottom: 0.25rem;
}

.contact-form input,
.contact-form textarea {
	width: 100%;
	padding: 0.5rem;
	font-family: inherit;
	border: 1px solid var(--color-border);
	border-radius: 0;
}

.contact-form__honeypot {
	position: absolute;
	left: -9999px;
}

.contact-form button {
	font-family: var(--font-sans);
}

.form-notice {
	padding: 0.75rem 1rem;
	border: 1px solid var(--color-border);
	border-radius: 0;
	margin-bottom: 1.5rem;
}

/* Site footer (round 5) — the global contact point on every page: large
   headline + email on the left, light meta info on the right, no
   divider line between them, copyright below both. */
.site-footer {
	padding-block: 4rem 2rem;
	border-top: 1px solid var(--color-border);
	margin-top: 3rem;
	color: var(--color-muted);
	font-size: 0.875rem;
}

.site-footer__contact {
	display: grid;
	grid-template-columns: 2fr 1fr 1fr; /* wider first column so the
	                                        heading fits on one line */
	gap: 3rem;
	align-items: start;
	margin-bottom: 3rem;
}

@media (max-width: 56rem) {
	.site-footer__contact {
		grid-template-columns: 1fr 1fr;
	}

	.site-footer__main {
		grid-column: 1 / -1;
	}
}

@media (max-width: 32rem) {
	.site-footer__contact {
		grid-template-columns: 1fr;
	}
}

.site-footer__heading {
	color: var(--color-text);
	font-size: clamp(1.5rem, 2.2vw, 1.875rem); /* smaller than the default
	                            .page-heading clamp so "Let's make
	                            something happen." fits on one line
	                            within this column's width */
	white-space: nowrap;
	margin-bottom: 0.75rem; /* was inheriting .page-heading's larger
	                            2.5rem gap, too much space before the
	                            short email link right below it */
}

@media (max-width: 40rem) {
	.site-footer__heading {
		white-space: normal;
	}
}

.contact-email-link {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	font-family: var(--font-display);
	font-size: 1.5rem;
	color: var(--color-accent);
	text-decoration: underline;
}

.contact-email-link__icon {
	width: 0.8em;
	height: 0.8em;
	display: inline-flex;
}

.contact-email-link__icon svg {
	width: 100%;
	height: 100%;
	display: block;
}

.site-footer__links {
	display: grid;
	gap: 0.85rem;
	align-content: start;
}

.site-footer__links a {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	text-decoration: underline;
	width: fit-content;
}

.contact-meta {
	display: grid;
	gap: 1rem;
}

.contact-meta p {
	margin: 0;
}

.contact-meta__link-icon {
	width: 0.7rem;
	height: 0.7rem;
	display: inline-flex;
}

.contact-meta__link-icon svg {
	width: 100%;
	height: 100%;
	display: block;
}

.contact-meta__location {
	display: flex;
	align-items: center;
	gap: 0.5rem;
}

.contact-meta__location svg {
	width: 0.9rem;
	height: 0.9rem;
	flex-shrink: 0;
}

.site-footer__copyright {
	margin: 0;
}

/* Leadership page — headline/subline on the left, a mentorship/ADPList
   tie-in on the right (settled on this after comparing 3 directions;
   the other two read as "corny" for a professional leadership page) */
/* Mentorship — the block and its supporting quotes sit side by side:
   mentorship content fixed on the left, quotes on a carousel on the
   right (one visible at a time, dot navigation underneath). */
.leadership-mentorship-row {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 3rem;
	align-items: start;
}

@media (max-width: 48rem) {
	.leadership-mentorship-row {
		grid-template-columns: 1fr;
	}
}

.leadership-mentorship {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
}

.leadership-mentorship--full {
	max-width: 36rem;
}

.leadership-mentorship__label {
	font-family: var(--font-sans);
	font-size: 0.8rem;
	font-weight: 600;
	color: var(--color-text);
}

.leadership-mentorship--full .leadership-mentorship__label {
	font-family: var(--font-display);
	font-size: clamp(1.5rem, 2vw, 1.75rem);
	font-weight: 600;
	color: var(--color-text);
}

.leadership-mentorship__body {
	font-family: var(--font-sans);
	font-size: 1rem;
	line-height: 1.6;
	color: var(--color-muted);
	margin: 0;
}

.leadership-mentorship--full .leadership-mentorship__body {
	font-size: 1.1rem;
}

.leadership-mentorship__links {
	display: flex;
	flex-wrap: wrap;
	gap: 1.5rem;
}

.leadership-mentorship__link {
	display: inline-flex;
	align-items: center;
	font-family: var(--font-sans);
	font-size: 0.95rem;
	text-decoration: underline;
	text-underline-offset: 0.2em;
	width: fit-content;
}

.leadership-mentorship__link:hover {
	color: var(--color-accent);
}

/* Mentorship testimonials — one visible at a time in a carousel next
   to the mentorship block, with dot navigation underneath. Placeholder
   quotes until Katie has real ones from mentees. */
.mentorship-carousel {
	display: flex;
	flex-direction: column;
}

/* Explicit [hidden] override — author `display` rules on this
   selector silently beat the browser's built-in [hidden]{display:none}
   UA rule regardless of specificity (bit us once already on the Work
   page filter). No display property is set on .mentorship-quote
   itself, but this stays explicit so a future layout change here
   can't quietly reintroduce that bug. */
.mentorship-quote[hidden] {
	display: none;
}

.mentorship-carousel__dots {
	display: flex;
	gap: 0.6rem;
	margin-top: 2rem;
}

.mentorship-carousel__dot {
	width: 0.6rem;
	height: 0.6rem;
	padding: 0;
	border-radius: 0;
	border: 1px solid var(--color-border);
	background: transparent;
	cursor: pointer;
}

.mentorship-carousel__dot.is-active {
	background: var(--color-accent);
	border-color: var(--color-accent);
}

/* Stylized to actually stand out — a bold accent rule + an oversized
   quotation mark, rather than plain paragraph text with a border */
.mentorship-quote {
	margin: 0;
	padding: 0 0 0 1.75rem;
	border-left: 3px solid var(--color-accent);
}

.mentorship-quote__mark {
	display: block;
	font-family: var(--font-display);
	font-size: 4rem;
	line-height: 0.5;
	color: var(--color-accent);
	margin-bottom: 1rem;
}

.mentorship-quote__text {
	font-family: var(--font-display);
	font-size: 1.5rem;
	line-height: 1.4;
	margin: 0 0 1.25rem;
}

.mentorship-quote__attribution {
	font-family: var(--font-sans);
	font-style: normal;
	font-weight: 600;
	font-size: 0.9rem;
	display: block;
}

.mentorship-quote__detail {
	display: block;
	font-weight: 400;
	color: var(--color-muted);
	font-size: 0.85rem;
	margin-top: 0.15rem;
}

/* ==========================================================================
   Case study body figures — an authoring toolkit for post_content.
   Diagrams recreated from Katie's Autodesk deck (structure taken from
   the slides' actual shape XML; the palette is this site's own).

   NOTE: .cs-flow and .cs-figure are in use on the Header Modernization
   study. .cs-tensions, .cs-bar-row and .cs-datarow are currently unused
   — kept deliberately as ready components for the two case studies still
   to be written (Product Page Evolution, account convergence), not left
   behind by accident. Delete them if those studies don't need them.

   REBUILT: the first pass used peach-tinted badge fills, gray pill blocks
   and outlined circles — none of which appear anywhere else on this site,
   and the tinted fills in particular repeated the color-blocking treatment
   Katie rejected twice on the Leadership page. These now use only the
   established vocabulary: hairline rules, terracotta as a thin accent
   (never a fill), bold black sans numerals, small uppercase gray labels.
   ========================================================================== */

.cs-figure {
	margin: 3rem 0;
}

/* For a tall, narrow screenshot (a single phone screen, not a wide
   composite) that would otherwise stretch to fill the whole grid
   column and tower over the text beside it. Shrinks the image itself
   rather than capping its height with a scrollbar — Katie didn't want
   the image to scroll, she wanted it smaller. */
.cs-figure--compact {
	max-width: 60%;
	margin-inline: auto;
}

@media (max-width: 40rem) {
	.cs-figure--compact {
		max-width: 80%;
	}
}

/* Guard: these figures lay inline <span>s out with CSS grid, so a stray
   <br> becomes an extra grid item and silently breaks every column.
   wpautop (which injects exactly that) is already disabled for single
   case studies in functions.php — this is belt-and-suspenders in case
   content is later re-saved through the wp-admin editor. */
.cs-figure br {
	display: none;
}

.cs-figure__title {
	font-family: var(--font-sans);
	font-size: 0.75rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--color-muted);
	margin: 0 0 1.25rem;
}

/* Before → after comparison rows (deck slide 7: fragmentation → platform).

   Each row is banded rather than rule-separated, with white gaps
   between, so the three columns read as a table without needing
   dividers.

   The column template is FIXED and identical on every row. It has to be:
   each row is its own grid, so any content-based sizing (max-content,
   auto) is computed per row and the arrows land at different x
   positions. That misalignment was the actual complaint, not the
   alignment of the text. */
.cs-flow {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}

.cs-flow__row {
	display: grid;
	/* The 1rem gap put the right-hand text only ~16px from the arrow
	   while the left text trailed off far earlier, so the arrow read as
	   attached to the right column. A wider gutter gives it room on both
	   sides, and the slightly wider right column nudges it a touch left
	   of true centre — matching the reference. */
	grid-template-columns: 1fr 2rem 1.1fr;
	gap: 2.5rem;
	align-items: baseline;
	background: var(--color-surface);
	padding: 1.4rem 2rem;
}

/* Above body size on purpose: this is a figure meant to be scanned, and
   at 0.9rem it was smaller than the prose around it. The larger type
   also fills more of the left column, which narrows the ragged gap
   before the arrow — it does not fix the centring, but it helps. */
.cs-flow__from,
.cs-flow__to {
	font-family: var(--font-sans);
	font-size: 1.0625rem;
	line-height: 1.35;
}

.cs-flow__from {
	color: var(--color-text);
}

.cs-flow__to {
	color: var(--color-text);
	font-weight: 700;
}

.cs-flow__arrow {
	color: var(--color-text);
	font-size: 1.25rem;
	text-align: center;
}

@media (max-width: 32rem) {
	.cs-flow__row {
		grid-template-columns: 1fr;
		gap: 0.35rem;
		padding: 1rem 1.25rem;
	}

	.cs-flow__arrow {
		display: none;
	}
}

/* Design tensions (deck slide 8) — same rule-above-label DNA as
   .cs-outcome, three across. */
.cs-tensions {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 2.5rem;
}

@media (max-width: 40rem) {
	.cs-tensions {
		grid-template-columns: 1fr;
		gap: 2rem;
	}
}

.cs-tension__rule {
	display: block;
	width: 2.5rem;
	height: 3px;
	background: var(--color-text);
	margin-bottom: 1.25rem;
}

.cs-tension__name {
	display: block;
	font-family: var(--font-sans);
	font-weight: 600;
	font-size: 0.95rem;
	color: var(--color-text);
	margin-bottom: 0.5rem;
}

.cs-tension__description {
	margin: 0;
	font-family: var(--font-sans);
	font-size: 0.9rem;
	color: var(--color-muted);
}

/* Labelled bar comparison (deck slide 16: findability 72% → 88%). Slim
   bars so they read as data, not as color blocks. */
.cs-bar-row {
	display: grid;
	grid-template-columns: 9rem 1fr 3.5rem;
	align-items: center;
	gap: 1.25rem;
	padding-block: 1.1rem;
	border-bottom: 1px solid var(--color-border);
}

.cs-bar-row:last-child {
	border-bottom: none;
}

.cs-bar__label {
	font-family: var(--font-sans);
	font-size: 0.75rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--color-muted);
}

.cs-bar__track {
	height: 0.5rem;
	background: var(--color-surface);
}

.cs-bar__fill {
	display: block;
	height: 100%;
	background: var(--color-muted);
}

.cs-bar-row--after .cs-bar__fill {
	background: var(--color-accent);
}

.cs-bar__value {
	font-family: var(--font-sans);
	font-weight: 700;
	font-size: 1.25rem;
	color: var(--color-text);
	text-align: right;
}

@media (max-width: 36rem) {
	.cs-bar-row {
		grid-template-columns: 1fr auto;
		gap: 0.5rem 1rem;
	}

	.cs-bar__track {
		grid-column: 1 / -1;
		order: 3;
	}
}

/* Label/value hairline rows — for supporting figures that are read, not
   scanned as headline stats (task-tier success rates, launch signals). */
.cs-datarow {
	display: grid;
	grid-template-columns: 1fr auto;
	gap: 1.5rem;
	align-items: baseline;
	padding-block: 0.9rem;
	border-bottom: 1px solid var(--color-border);
}

.cs-datarow:last-child {
	border-bottom: none;
}

.cs-datarow__label {
	font-family: var(--font-sans);
	font-size: 0.9rem;
	color: var(--color-text);
}

.cs-datarow__value {
	font-family: var(--font-sans);
	font-size: 0.9rem;
	font-weight: 600;
	color: var(--color-muted);
	white-space: nowrap;
}

.cs-datarow__value--flagged {
	color: var(--color-accent);
}

/* Figure + caption for real case study imagery. Sits at container
   width — deliberately outside the 42rem prose measure, so screenshots
   are legible — and never full-bleed: the only edge-to-edge things on a
   case study are the two bands and the launch section. */
.cs-media {
	margin: 3rem 0;
}

/* max-width, never width: a 375px mobile screenshot stretched to the
   1104px container rendered three times its natural size and looked
   enormous and soft. Images now sit at natural size, capped by the
   container. */
.cs-media img {
	max-width: 100%;
	width: auto;
	height: auto;
	display: block;
	border: 1px solid var(--color-border);
}

.cs-media figcaption {
	margin-top: 0.85rem;
	font-family: var(--font-sans);
	font-size: 0.8rem;
	line-height: 1.5;
	color: var(--color-muted);
	max-width: 42rem;
}

/* Image placeholder — dashed border deliberately unlike every other
   bordered box on the site, so it reads as "not final". Temporary:
   Katie is supplying the real screenshots. */
.case-study-image-placeholder {
	margin: 3rem 0;
	aspect-ratio: 16 / 9;
	border: 1px dashed var(--color-border);
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--color-surface);
}

.case-study-image-placeholder__label {
	font-family: var(--font-sans);
	font-size: 0.8rem;
	color: var(--color-muted);
	text-align: center;
	padding: 1rem;
	max-width: 24rem;
}
