/*
Theme Name: Lovable Atmosphere — Sevenality
Theme URI: https://sevenality.com
Description: Sevenality's site-specific child of Lovable Atmosphere. Holds only what is genuinely Sevenality: the brand marble textures, the Adobe Fonts (Typekit) loader for prenton / utopia-std-headline, the brand pattern set, and the brand token overrides in theme.json. Everything else is inherited from the canonical parent so it stays in sync.
Author: Sevenality
Template: lovableatmosphere
Version: 2.17.1
Requires at least: 6.5
Requires PHP: 7.4
Text Domain: lovableatmosphere-sevenality
*/




/* ─────────────────────────────────────────────────────────────
   INK ON DARK

   Four steps. The stylesheet carried TWELVE distinct alphas of
   white — .42 .45 .5 .6 .62 .7 .72 .74 .78 .82 .85 — all doing
   one job: dimming text on a dark ground. Nobody can distinguish
   72% white from 74% white; they are two decisions where the
   reader perceives one.

   Mapped so no existing value moves by more than .07, which is
   below the threshold where a tonal step reads as a change rather
   than as the same colour.

   NOT INCLUDED, deliberately: the per-project accent. That is
   computed per case study from the client's own artwork (see
   lib/project-accent.php) and is supposed to differ on every
   page — it is art direction, not drift.
   ───────────────────────────────────────────────────────────── */
:root{
	--ink-on-dark       : #fff;
	--ink-on-dark-soft  : rgba(255,255,255,.78);
	--ink-on-dark-dim   : rgba(255,255,255,.66);
	--ink-on-dark-faint : rgba(255,255,255,.5);  /* .45 measured 4.47:1 on the
	                                               #1a1a1a philanthropy band — a
	                                               0.03 miss. .5 clears it. */
	--sev-blue-light    : #80ABD7;
	--sev-blue-deep     : #0c3d5d;
	--sev-black         : #0d0d0d;
}
/* ─────────────────────────────────────────────────────────────
   SPACING SCALE

   Two scales, because this theme legitimately spaces two ways:
   static component padding, and section rhythm that grows with the
   viewport.

   Before this there were 26 distinct static values between .15rem
   and 2.25rem — including .3, .35, .4 and .45 as four separate
   decisions — and 71 distinct fluid clamps. Nine of those 71 were
   pairs identical apart from whitespace, e.g.

     clamp(2rem,4vw,3rem)     used 12x
     clamp(2rem, 4vw, 3rem)   used  3x

   the same value authored twice because nobody could look it up.
   ───────────────────────────────────────────────────────────── */
:root{
	/* static — nearest-step mapping */
	--s-3xs : .25rem;
	--s-2xs : .375rem;
	--s-xs  : .5rem;
	--s-sm  : .75rem;
	--s-md  : 1rem;
	--s-lg  : 1.25rem;
	--s-xl  : 1.5rem;
	--s-2xl : 2rem;
	--s-3xl : 3rem;
	--s-4xl : 4rem;

	/* fluid — section rhythm, mapped by ceiling */
	--sp-1 : clamp(.75rem, 1.5vw, 1.25rem);
	--sp-2 : clamp(1rem, 2vw, 1.75rem);
	--sp-3 : clamp(1.5rem, 3vw, 2.5rem);
	--sp-4 : clamp(2rem, 4vw, 3.5rem);
	--sp-5 : clamp(3rem, 6vw, 5rem);
	--sp-6 : clamp(4rem, 8vw, 7rem);
	--sp-7 : clamp(5rem, 12vw, 10rem);
}
/* ─────────────────────────────────────────────────────────────
   TYPE SCALE

   Ten steps. Before this the four main surfaces rendered 36
   distinct sizes between them, including EIGHT inside a 7px band
   (9,10,11,12,13,14,15,16) and THIRTEEN display clamps each used
   exactly once — two of which were byte-identical apart from
   whitespace:

     clamp(2rem,1.3rem + 3.2vw,4rem)
     clamp(2rem, 1.3rem + 3.2vw, 4rem)

   That is the definition of no system: the same decision made
   twice, independently, and stored twice.

   Steps are mapped by clamp CEILING, because the ceiling is what a
   reader meets on a desktop and what the hierarchy is judged on.
   ───────────────────────────────────────────────────────────── */
:root{
	/* ── The parent's editorial ramp, mapped onto ours ──────────────────────
	   The parent theme owns the NAMES (--atm-t-*) and its blog components
	   reference nothing else. This is where this site supplies the VALUES.

	   Before this, /ideas/ — the posts page, and a primary surface on a site
	   positioned around writing — rendered in the parent's own sizes and sat
	   outside the ramp everything else here uses. Now the blog is typeset in
	   the same eleven steps as the homepage, and gflidev keeps its own. */
	--atm-t-hero    : var(--t-h1);
	--atm-t-display : var(--t-h2);
	--atm-t-title   : var(--t-h3);
	--atm-t-lead    : var(--t-lead);
	--atm-t-body    : var(--t-body);
	--atm-t-small   : var(--t-small);
	--atm-t-meta    : var(--t-meta);
	--atm-t-micro   : var(--t-micro);

	--t-micro : .625rem;                                  /* 10px — eyebrows, chip labels */
	--t-meta  : .75rem;                                   /* 12px — meta, counts, captions */
	--t-small : .875rem;                                  /* 14px — secondary UI */
	--t-body  : 1rem;                                     /* 16px — NOT the document body.
	                                                          Named badly and worth stating: the
	                                                          page's reading size is 21px, set by
	                                                          the parent's styles.typography.
	                                                          fontSize clamp. This is a COMPONENT
	                                                          step used in 9 places (buttons,
	                                                          stat labels, definition lists). Use
	                                                          --t-lead, or the `read` font-size
	                                                          preset, for anything a reader reads
	                                                          at length. */
	--t-lead  : clamp(1.0625rem, 1rem + .45vw, 1.3125rem); /* 17 → 21 — standfirsts.
	                                                          Ceiling deliberately 21px, not 22:
	                                                          the parent theme already sets body
	                                                          and links at 21px in 81 places. A
	                                                          22px step would have been a second
	                                                          size nobody could tell apart from
	                                                          the first. Meet the rhythm that is
	                                                          already there rather than add to it. */
	--t-h4    : clamp(1.25rem, 1rem + 1.4vw, 2rem);       /* 20 → 32 */
	--t-h3    : clamp(1.6rem, 1.2rem + 2.2vw, 2.75rem);   /* 26 → 44 */
	--t-statement: clamp(1.75rem, 1.1rem + 2.6vw, 4rem); /* 28 → 55 — the
	                                                        section-opening
	                                                        statement. A REAL
	                                                        step, not drift: it
	                                                        was already
	                                                        hand-authored twice
	                                                        on the homepage
	                                                        ("A brand is a
	                                                        coherence problem",
	                                                        "Tell us what's
	                                                        keeping you up at
	                                                        night") and it sits
	                                                        between the hero at
	                                                        96 and sub-heads at
	                                                        44. Snapping it
	                                                        either way would
	                                                        have collapsed two
	                                                        levels into one. */
	--t-h2    : clamp(2rem, 1.4rem + 3.4vw, 4rem);        /* 32 → 64 */
	--t-h1    : clamp(2.5rem, 1.5rem + 5.4vw, 6rem);      /* 40 → 96 */
	--t-mega  : clamp(3.25rem, 1.5rem + 8vw, 9rem);       /* the one display size */
}
/*
 * Keep this file minimal. Brand tokens belong in theme.json; this holds only
 * what theme.json provably cannot win.
 *
 * WHY THESE RULES EXIST:
 * theme.json `styles.typography.fontFamily` emits a global-styles rule for
 * body, but the parent ships a COMPILED stylesheet (build/theme-styles.css)
 * that also sets `body { font-family: ... }`. That bundle is enqueued as a
 * real stylesheet and lands after global styles, so it wins on cascade order
 * and the body silently rendered in Hanken Grotesk.
 *
 * The visible symptom was subtle and worth remembering: `prenton` reported as
 * `unloaded` in document.fonts. Browsers only fetch a webfont when something
 * actually matches it — because the parent's rule kept winning, Prenton was
 * never requested at all. The font wasn't broken; nothing was asking for it.
 *
 * The child stylesheet declares a dependency on `theme-styles` (see
 * functions.php), so these rules load after the parent's and take effect.
 */

body {
	font-family: var(--wp--preset--font-family--sans);
	font-weight: 300;
}

/* ============================================================
   WIDTH INTENT
   One system, replacing three copy-pasted versions of the same
   three rules (About, Philanthropy and Press each carried their own).
   ============================================================

   THE PROBLEM THIS SOLVES
   Every pattern root is a constrained layout, so WordPress emits

     :where(.is-layout-constrained) > :where(:not(.alignfull)...) {
         max-width: var(--wp--style--global--content-size);
         margin-left: auto !important;
         margin-right: auto !important;
     }

   against every direct child. Two consequences, both measured:

   1. Sections cap at contentSize (46rem / 736px) even when they hold a
      grid that needs the whole band. Philanthropy's Writing section was
      still doing this — 736px wide at left=352 while every sibling ran
      1380px at left=30 — because `.sp-arts-sec` was left out of that
      pattern's hand-written band list.
   2. Each child re-centres on ITS OWN measure, so a single section had
      left edges at 30, 352, 355 and 468px: four starting points.

   WHY EVERY SELECTOR HERE DOUBLES ITS CLASS
   WordPress's own rule is :where()-wrapped and therefore beatable by a single
   class. The PARENT THEME IS NOT. lovableatmosphere ships a deliberate,
   un-:where()'d override in src/css/theme/layout.scss (compiled into
   build/theme-styles.css, documented in its docs/WORDPRESS-CONSTRAINED-LAYOUT.md):

     .wp-block-group.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) {
         max-width: var(--wp--style--global--content-size);
         margin-left: auto !important;
         margin-right: auto !important;
     }

   Two classes, so (0,2,0). A single-class `.sev-band` at (0,1,0) loses to it
   outright — confirmed against the live cascade via CSS.getMatchedStylesForNode,
   which showed `.sev-band` matching and still computing to 736px. Doubling the
   class makes these (0,2,0), which ties, and the child stylesheet is enqueued
   with `theme-styles` as a dependency so it resolves later and wins. That is
   the same mechanism the hand-written `.sevenality-phil > .sp-hero` rules
   further down already rely on.

   Note that specificity decides between !important declarations too, which is
   why the margin rule needs the doubled class AND the !important: it is
   competing with `margin-left: auto !important` at (0,2,0).

   USAGE
     .sev-band     a section: holds contents to the wide measure and makes
                   every child start at the same left edge
     .sev-fill     a child that manages its own grid; fills the band
     .sev-mid      a child at the bridging measure
     .sev-prose    a child at the reading measure

   Prose that already carries a `ch`-based max-width (headings at 18ch,
   notes at 52ch) needs none of these. A `ch` measure is a typographic
   decision and should outrank a layout default — the audit found most
   736px boxes on About and Press were micro-labels and ch-measured
   headings, which are correct as they stand. Reach for an intent only
   where an element would otherwise inherit contentSize by accident. */

:root {
	--sev-w-prose: var(--wp--style--global--content-size, 46rem); /*  736px - reading measure */
	--sev-w-mid: 68rem;                                           /* 1088px - bridge */
	--sev-w-wide: var(--wp--style--global--wide-size, 86.25rem);  /* 1380px - full band */
}

.sev-band.sev-band {
	max-width: var(--sev-w-wide);
	width: 100%;
	margin-inline:auto;
}

/* Every child starts at the band's left edge rather than centring on its
   own width. See the !important note above for why this needs the weight. */
.sev-band.sev-band > * {
	margin-inline: 0 !important;
}

.sev-band.sev-band .sev-fill {
	max-width: none;
	width: 100%;
}

.sev-band.sev-band > .sev-mid {
	max-width: var(--sev-w-mid);
}

.sev-band.sev-band > .sev-prose {
	max-width: var(--sev-w-prose);
}

/* ============================================================
   PATTERN STYLES
   Only what block attributes cannot express: the index layout,
   the shared row device, and the quote band stage.
   ============================================================ */

/* ---------- Work index ---------- */
.sevenality-index__layout {
	display: grid;
	grid-template-columns: 1fr;
	gap:var(--sp-3);
}

@media (min-width: 960px) {
	.sevenality-index__layout {
		grid-template-columns: repeat(12, 1fr);
		gap:var(--sp-4);
	}
	/* panel LEFT and sticky — the image anchors while the names scroll past */
	.sevenality-index__panel {
		grid-column: 1 / span 5;
		position: sticky;
		top: clamp(4rem, 12vh, 7rem);
		align-self: start;
	}
	/* centre the names against the panel so neither leaves a dead quadrant */
	.sevenality-index__rows {
		grid-column: 7 / span 6;
		align-self: center;
	}
}

.sevenality-index__panel {
	position: relative;
	aspect-ratio: 4 / 5;
	overflow: hidden;
	background: #161616;
}

.sevenality-index__panel img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	opacity: 0;
	transition: opacity .45s ease;
}

/* first image is visible before hydration, so the panel is never empty */
.sevenality-index__panel img:first-child,
.sevenality-index__panel img.is-active {
	opacity: 1;
}
/* once a choice is made, only the active one shows */
.sevenality-index__panel:has(img.is-active) img:first-child:not(.is-active) {
	opacity: 0;
}

/* ---------- the shared row device (index + ideas) ---------- */
.sevenality-row {
	display: grid;
	grid-template-columns: auto 1fr auto;
	gap:var(--s-xs) var(--sp-1);
	align-items: baseline;
	padding-block:var(--sp-2);
	border-block-start: 1px solid rgba(255, 255, 255, .16);
	text-decoration: none;
	transition: opacity .3s ease;
}

.sevenality-row:last-child {
	border-block-end: 1px solid rgba(255, 255, 255, .16);
}

/* dim the set, light the one — hierarchy without weight, and no JS needed */
.sevenality-index__rows:hover .sevenality-row,
.sevenality-ideas__rows:hover .sevenality-row {
	opacity: .32;
}

.sevenality-index__rows .sevenality-row:hover,
.sevenality-index__rows .sevenality-row:focus-visible,
.sevenality-ideas__rows .sevenality-row:hover,
.sevenality-ideas__rows .sevenality-row:focus-visible {
	opacity: 1;
}

.sevenality-row__num {
	font-family: var(--wp--preset--font-family--sans);
	font-size:var(--t-micro);
	letter-spacing: .2em;
	color:var(--sev-blue-light);
}

.sevenality-row__name {
	font-family: var(--wp--preset--font-family--display);
	font-size:var(--t-h3);
	line-height: 1.05;
	letter-spacing: -.02em;
	color:var(--ink-on-dark);
}

.sevenality-row__meta {
	font-family: var(--wp--preset--font-family--sans);
	font-weight: 300;
	font-size:var(--t-micro);
	letter-spacing: .18em;
	text-transform: uppercase;
	color:var(--ink-on-dark-faint);
	text-align: right;
}

/* ---------- Services brief (homepage) ----------
   Three lines stated plainly. Not the hub's full acts — see the pattern
   docblock for why that would have been several thousand pixels of repeat. */
.sevenality-svcbrief .svb-head__row {
	display: flex; align-items: baseline; justify-content: space-between; gap:var(--s-xl);
	padding-block-end:var(--s-md);
	border-block-end: 1px solid var(--sev-rule);
	margin-block-end:var(--sp-3);
}
.sevenality-svcbrief .svb-micro {
	font-family: var(--wp--preset--font-family--sans);
	font-size:var(--t-micro); letter-spacing: .24em; text-transform: uppercase;
	color: var(--sev-accent); margin:0;
}
.sevenality-svcbrief .svb-all {
	white-space: nowrap; font-family: var(--wp--preset--font-family--sans);
	font-size:var(--t-meta); letter-spacing: .06em; color: inherit;
	text-decoration: none !important;
	border-bottom: 1px solid var(--sev-rule); padding-bottom:var(--s-3xs);
}
.sevenality-svcbrief .svb-all:hover { border-color: var(--sev-accent); color: var(--sev-accent); }

/* Four programs, not three disciplines — see patterns/services-brief.php for
   why the band changed axis. Two rows of two rather than four thin columns:
   at 1560px a quarter column is ~360px, and the situation lines run to two
   words short of wrapping badly in it. */
.sevenality-svcbrief .svb-grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap:var(--sp-3) var(--sp-4);
}
@media (max-width: 860px) { .sevenality-svcbrief .svb-grid { grid-template-columns: minmax(0, 1fr); } }

.sevenality-svcbrief .svb-line {
	display: grid;
	gap:var(--s-xs);
	align-content: start;
	padding-block-start:var(--s-md);
	border-block-start: 1px solid var(--sev-rule);
	color: inherit;
	text-decoration: none !important;
	transition: opacity .3s ease;
}
/* Same dim-the-set, light-the-one hierarchy the row device uses. Weight is
   not available in this type kit, so opacity does the work. */
.sevenality-svcbrief .svb-grid:hover .svb-line { opacity: .35; }
.sevenality-svcbrief .svb-line:hover,
.sevenality-svcbrief .svb-line:focus-visible { opacity: 1; }
.sevenality-svcbrief .svb-line__n {
	font-family: var(--wp--preset--font-family--sans);
	font-size:var(--t-micro); letter-spacing: .2em; color: var(--sev-ink-dim);
}
.sevenality-svcbrief .svb-line__name {
	font-family: var(--wp--preset--font-family--display);
	font-size:var(--t-h4);
	line-height: 1.06; letter-spacing: -.02em; color: var(--sev-ink);
}
.sevenality-svcbrief .svb-line__d {
	font-family: var(--wp--preset--font-family--sans);
	font-weight: 300; font-size:var(--t-small); line-height: 1.6;
	color: var(--sev-ink-dim); max-width: 34ch;
}
.sevenality-svcbrief .svb-line__c {
	font-family: var(--wp--preset--font-family--sans);
	font-size:var(--t-micro); letter-spacing: .16em; text-transform: uppercase;
	color: var(--sev-accent); font-variant-numeric: tabular-nums;
	margin-block-start:var(--s-2xs);
}

/* ---------- Philanthropy brief (homepage) ----------
   One number, set large. The Philanthropy page owns the 40x40 marks grid; this
   takes the figure and not the device. */
.sevenality-philbrief .phb__micro {
	font-family: var(--wp--preset--font-family--sans);
	font-size:var(--t-micro); letter-spacing: .24em; text-transform: uppercase;
	color: var(--sev-accent);
	margin:0 0 var(--sp-3);
	padding-block-end:var(--s-md);
	border-block-end: 1px solid var(--sev-rule);
}
.sevenality-philbrief .phb__body {
	display: grid;
	gap:var(--sp-4);
	align-items: center;
}
@media (min-width: 900px) {
	/* `auto` for the numeral, not a percentage. A 42% column was narrower than
	   "1,600" set at 13rem, so the figure ran straight over the heading beside
	   it — a fixed fraction cannot know how wide a glyph string is. Letting the
	   column size to its content and giving the text the remainder makes the
	   overlap impossible rather than unlikely. */
	.sevenality-philbrief .phb__body {
		/* Centred as a PAIR rather than pinned left. Capping the measure left
		   ~460px of dead space to the right of the text while the figure sat
		   hard against the left edge, so the band read as stranded rather than
		   composed. `justify-content: center` on a max-content grid centres
		   the figure and the copy together and lets the air fall on both
		   sides. */
		grid-template-columns: auto minmax(0, max-content);
		justify-content: center;
		gap: clamp(2rem, 5vw, 5.5rem);
	}
}
.sevenality-philbrief .phb__body > * { min-width: 0; }
/* aria-hidden in the markup: the heading beside it already says "1,600
   students", so a screen reader hearing the numeral twice would be reading
   the layout rather than the sentence. */
.sevenality-philbrief .phb__fig {
	font-family: var(--wp--preset--font-family--display);
	font-size:var(--t-mega);
	line-height: .82; letter-spacing: -.045em;
	color: var(--sev-accent);
	margin:0;
	font-variant-numeric: tabular-nums;
}
.sevenality-philbrief .phb__h {
	font-family: var(--wp--preset--font-family--display);
	font-weight: 400;
	font-size:var(--t-h3);
	line-height: 1.1; letter-spacing: -.02em;
	margin:0 0 var(--s-md); max-width: 22ch;
}
.sevenality-philbrief .phb__d {
	font-family: var(--wp--preset--font-family--sans);
	font-weight: 300; font-size:var(--t-body); line-height: 1.7;
	color: var(--sev-ink-dim); margin:0 0 var(--s-xl); max-width: 46ch;
}
.sevenality-philbrief .phb__go {
	font-family: var(--wp--preset--font-family--sans);
	font-size:var(--t-meta); letter-spacing: .14em; text-transform: uppercase;
	/* Was var(--sev-accent). This band spends its accent on the 1,600 — the
	   one proof figure on the page, and the moment the whole band is built
	   around — plus the micro label every band carries. A third kind put it
	   past DESIGN.md principle 8, and this is the one the amendment does not
	   cover: the permission is for a repeated link colour WITHIN a repeating
	   element, which is the Ideas and Work card links. This is a lone link at
	   the foot of a band. It keeps its underline and reads as a link without
	   the tint. */
	color: var(--sev-ink); text-decoration: none !important;
	border-bottom: 1px solid currentColor; padding-bottom:var(--s-3xs);
}

/* ---------- Ideas: featured writing ----------
   Image-led cards at the same scale as the work rail's, because this section
   now sits ABOVE the work and has to be able to hold that position. Three up,
   equal columns — the count is known, so no auto-fit. */
.sevenality-ideas .svi-head__row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap:var(--s-xl);
	padding-block-end:var(--s-md);
	border-block-end: 1px solid var(--sev-rule);
	margin-block-end:var(--sp-3);
}
.sevenality-ideas .svi-micro {
	font-family: var(--wp--preset--font-family--sans);
	font-size:var(--t-micro);
	letter-spacing: .24em;
	text-transform: uppercase;
	color: var(--sev-accent);
	margin:0;
}
.sevenality-ideas .svi-all {
	white-space: nowrap;
	font-family: var(--wp--preset--font-family--sans);
	font-size:var(--t-meta);
	letter-spacing: .06em;
	color: inherit;
	text-decoration: none !important;
	border-bottom: 1px solid var(--sev-rule);
	padding-bottom:var(--s-3xs);
}
.sevenality-ideas .svi-all:hover { border-color: var(--sev-accent); color: var(--sev-accent); }
.sevenality-ideas .svi-h {
	font-family: var(--wp--preset--font-family--display);
	font-weight: 400;
	font-size:var(--t-h2);
	line-height: 1.04;
	letter-spacing: -.03em;
	margin:0 0 var(--sp-3);
	max-width: 18ch;
}

.sevenality-ideas .svi-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap:var(--sp-2);
}
@media (max-width: 900px) { .sevenality-ideas .svi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) { .sevenality-ideas .svi-grid { grid-template-columns: minmax(0, 1fr); } }

/* The Programs band's lead — see patterns/services-brief.php. Set at the
   `statement` step (55px) rather than h2 (64px): this band opens a list, it does
   not open the page, and 55/32 puts its lead ratio at 1.7 alongside the other
   bands' 2.0–3.4 rather than above them. */
.sevenality-svcbrief .svb-h {
	font-family: var(--wp--preset--font-family--display);
	font-weight: 400;
	font-size: var(--t-statement);
	line-height: 1.06;
	letter-spacing: -.02em;
	margin: var(--s-md) 0 0;
	max-width: 20ch;
}

/* The head row is core blocks now, so its children arrive with block margins. */
.sevenality-ideas .svi-head__row > p { margin: 0; }

/* The grid is a core/post-template. Core ships it as a list; the reset kills
   the marker and padding so the existing grid rules apply unchanged. */
.sevenality-ideas .svi-grid {
	list-style: none;
	padding: 0;
	margin: 0;
}
/* The post-template also carries core's FLOW layout class, whose `> * + *`
   rule puts a block-start margin on every item after the first. In a flow list
   that is the block gap; inside this grid it silently drops cards two and three
   below card one. Measured rather than guessed: the li tops came back
   1791.5 / 1811.5 / 1811.5 with margin-top 0px / 20px / 20px. */
.sevenality-ideas .svi-grid > li { margin: 0; }

.sevenality-ideas .svi-card {
	display: flex;
	flex-direction: column;
	color: inherit;
	/* Anchor for the stretched link below. */
	position: relative;
}

/* THE WHOLE CARD IS THE CLICK TARGET, from ONE link.
   The old markup wrapped every card in an <a>, which is a big target but also
   an anchor containing a heading and a paragraph. Here only the title is a
   link — one link, one accessible name — and its ::after is stretched over the
   card to restore the target. */
.sevenality-ideas .svi-card__t a::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}
/* !important because the theme underlines links with !important; the old
   markup needed the same escape on its wrapping <a>. */
.sevenality-ideas .svi-card__t a {
	color: inherit;
	text-decoration: none !important;
}

.sevenality-ideas .svi-card__media {
	display: block;
	overflow: hidden;
	background: var(--wkc-card, light-dark(#F1EEE9, rgba(255,255,255,.05)));
	margin-block-end:var(--s-md);
	position: relative;
}
/* core/post-featured-image writes the aspect ratio onto its own inner img when
   the aspectRatio attribute is set, so the ratio is not repeated here. */
.sevenality-ideas .svi-card__media img {
	width: 100%; height: 100%;
	object-fit: cover; display: block;
	transition: transform .6s cubic-bezier(.2,.7,.2,1);
}
.sevenality-ideas .svi-card:hover .svi-card__media img,
.sevenality-ideas .svi-card:focus-within .svi-card__media img { transform: scale(1.04); }

/* NO FEATURED IMAGE: the title becomes the art. A grey box would read as a
   broken card; type at scale reads as a decision — and this section is meant
   to lead with typography anyway.

   core/post-featured-image returns an EMPTY STRING when a post has no
   thumbnail — not an empty wrapper — so there is nothing in the DOM to detect
   directly. :has() asks the card whether an image ever arrived.

   This replaces a stand-in that repeated the title inside the media box under
   aria-hidden. The title now does both jobs while being rendered once, which
   is one fewer thing for a screen reader to skip past. */
.sevenality-ideas .svi-card:not(:has(.svi-card__media img)) .svi-card__t {
	/* Takes the media box's place in the column rather than sitting under an
	   absent one, so a type card and an image card start at the same height. */
	order: -1;
	aspect-ratio: 4 / 3;
	display: grid;
	align-content: end;
	padding:var(--sp-1);
	margin-block-end:var(--s-md);
	/* Was var(--sev-accent). The card already reads as art from the tinted
	   ground and the display type filling a 4/3 box; setting the type in
	   accent as well made this a THIRD kind of accent-marked thing in the
	   band, past the two DESIGN.md principle 8 allows. The wash stays — a
	   12% tint fading to transparent is a ground, not a mark. */
	color: var(--sev-ink);
	background: linear-gradient(160deg,
		color-mix(in srgb, var(--sev-accent) 12%, transparent),
		transparent 70%);
	/* A long unbroken word in a narrow column has nowhere to go; let it break
	   rather than overflow. */
	overflow-wrap: anywhere;
	hyphens: auto;
	/* The base rule clamps to three lines with -webkit-box, which is for a
	   title sitting UNDER art. Here the title IS the art and has a 4/3 box to
	   fill, so `display: grid` above both lays it out and drops the clamp. */
}

.sevenality-ideas .svi-card__t {
	font-family: var(--wp--preset--font-family--display);
	font-weight: 400;
	font-size:var(--t-h4);
	line-height: 1.1;
	letter-spacing: -.02em;
	/* Three lines, then ellipsis. One post title here runs to five lines while
	   its neighbours take two, which left the standfirsts starting at three
	   different heights and the row reading as broken rather than editorial.
	   The full title is still the link's accessible name. */
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
	/* core/post-title is an <h3> and arrives with heading margins. */
	margin: 0;
}
.sevenality-ideas .svi-card:hover .svi-card__t,
.sevenality-ideas .svi-card:hover .svi-card__t a { color: var(--sev-accent); }

.sevenality-ideas .svi-card__date {
	font-family: var(--wp--preset--font-family--sans);
	font-size:var(--t-meta);
	letter-spacing: .06em;
	color: var(--sev-ink-dim);
	margin:0 0 var(--s-2xs);
}

.sevenality-ideas .svi-card__d {
	font-family: var(--wp--preset--font-family--sans);
	font-size:var(--t-small);
	line-height: 1.55;
	color: var(--sev-ink-dim);
	margin-block-start:var(--s-xs);
	max-width: 34ch;
}
/* core/post-excerpt wraps its text in its own <p>, which the hand-written
   markup did not have. Without this the card gains a paragraph's worth of
   space it was never designed to carry. */
.sevenality-ideas .svi-card__d p { margin: 0; }

.sevenality-ideas .svi-card__go {
	margin-block-start:auto;
	margin-block-end:0;
	padding-block-start:var(--s-md);
	font-family: var(--wp--preset--font-family--sans);
	font-size:var(--t-meta);
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--sev-accent);
}

/* The band renders as a heading over nothing once the seeded test posts are
   removed and before the first real POV is published. Say so rather than
   leave a hole. */
.sevenality-ideas .svi-empty {
	font-family: var(--wp--preset--font-family--sans);
	font-size:var(--t-small);
	color: var(--sev-ink-dim);
	margin: 0;
}

@media (prefers-reduced-motion: reduce) {
	.sevenality-ideas .svi-card__media img { transition: none; }
	.sevenality-ideas .svi-card:hover .svi-card__media img { transform: none; }
}

/* MODIFIER: a figure in the middle of the row.
   The base device stays `auto 1fr auto` for the work index; this adds a fourth
   column so the count sits between the name and the label instead of the row
   running on empty. Set in the display face at a readable size — it is a fact
   about what is behind the link, not a caption, and at eyebrow size it would
   read as decoration. */
.sevenality-row--counted {
	grid-template-columns: auto 1fr auto auto;
}

.sevenality-row__count {
	font-family: var(--wp--preset--font-family--display);
	font-size:var(--t-lead);
	line-height: 1.1;
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}

@media (max-width: 560px) {
	.sevenality-row {
		grid-template-columns: auto 1fr;
	}
	.sevenality-row__meta {
		grid-column: 2;
		text-align: left;
	}
	/* Two columns on a phone: the count drops under the name and the label
	   sits beside it, rather than four columns crushing into a stack of
	   fragments. */
	.sevenality-row--counted {
		grid-template-columns: auto 1fr;
	}
	.sevenality-row__count {
		grid-column: 2;
	}
}

/* ---------- Quote band ---------- */
.sevenality-qband__stage {
	position: relative;
	margin-block-start:var(--sp-3);
}

.sevenality-qslide {
	display: grid;
	grid-template-columns: 1fr;
	gap:var(--sp-3);
	margin:0;
	opacity: 0;
	visibility: hidden;
	position: absolute;
	inset-block-start: 0;
	inset-inline: 0;
	transition: opacity .5s ease;
}

/* first slide visible pre-hydration so the band is never blank */
.sevenality-qslide:first-child {
	opacity: 1;
	visibility: visible;
	position: relative;
}

.sevenality-qband__stage:has(.is-current) .sevenality-qslide:first-child:not(.is-current) {
	opacity: 0;
	visibility: hidden;
	position: absolute;
}

.sevenality-qslide.is-current {
	opacity: 1;
	visibility: visible;
	position: relative;
}

@media (min-width: 900px) {
	.sevenality-qslide {
		grid-template-columns: repeat(12, 1fr);
		align-items: start;
	}
	.sevenality-qslide__text {
		grid-column: 1 / span 8;
	}
	/* THE ATTRIBUTION BELONGS TO THE QUOTE.
	   It used to sit at columns 10–12 with `align-items: start`, which aligned
	   it to the top of the GRID ROW rather than to anything in the quote —
	   measured at 75.1% from the left while the quote ended around 66%, and
	   starting 3% ABOVE the quote's own first line, with column 9 as an empty
	   gutter between them. It read as a floating label rather than as a name
	   attached to words.

	   Underneath, on the quote's own left edge, is the plain reading of
	   "someone said this". */
	.sevenality-qslide__cite {
		grid-column: 1 / span 8;
	}
}

/* A short rule marks the hand-off from the words to whose words they are. */
.sevenality-qslide__cite::before {
	content: "";
	display: block;
	inline-size: 2.5rem;
	block-size: 1px;
	background: currentColor;
	opacity: .3;
	margin-block-end: var(--s-md);
}

.sevenality-qslide__text {
	font-family: var(--wp--preset--font-family--serif-text);
	font-size:var(--t-h4);
	line-height: 1.36;
	color:var(--ink-on-dark);
	margin:0;
	text-wrap: pretty;
}

.sevenality-qslide__cite {
	font-style: normal;
	padding-block-start:var(--s-xs);
}

.sevenality-qslide__name {
	display: block;
	font-family: var(--wp--preset--font-family--sans);
	font-size:var(--t-micro);
	letter-spacing: .2em;
	text-transform: uppercase;
	color:var(--sev-blue-light);
	font-style: normal;
}

.sevenality-qslide__org {
	display: block;
	font-family: var(--wp--preset--font-family--sans);
	font-weight: 300;
	font-size:var(--t-meta);
	color:var(--ink-on-dark-faint);
	margin-block-start:var(--s-2xs);
}

/* Arrows sit either side of the indicators on one row. The dots keep their own
   top margin, so the row takes none — otherwise the two stack up and the band
   grows a dead strip under the quote. */
.sevenality-qnav {
	display: flex;
	align-items: center;
	gap:var(--s-md);
}

.sevenality-qarrow {
	inline-size: 2.25rem;
	block-size: 2.25rem;
	margin-block-start:var(--sp-4);
	display: grid;
	place-items: center;
	padding:0;
	background: transparent;
	border: 1px solid rgba(255, 255, 255, .22);
	border-radius: 50%;
	color:var(--ink-on-dark-dim);
	cursor: pointer;
	transition: border-color .25s ease, color .25s ease;
}
.sevenality-qarrow svg { inline-size: 1rem; block-size: 1rem; }
.sevenality-qarrow:hover { border-color:var(--ink-on-dark-dim); color:var(--ink-on-dark); }
.sevenality-qarrow:focus-visible { outline: 2px solid #80ABD7; outline-offset: 2px; }

.sevenality-qdots {
	display: flex;
	gap:var(--s-sm);
	margin-block-start:var(--sp-4);
}

/*
 * The indicator is a 2px rule with a 44px hit area.
 *
 * The parent enforces `min-height: 44px` on buttons — the WCAG minimum touch
 * target — which was squaring these off. That rule is right and should not be
 * overridden: a 2px-tall button is a 2px tap target. So the BUTTON keeps its
 * full 44px and stays transparent, and a pseudo-element draws the visible
 * rule centred inside it. Design and hit area are decoupled.
 */
.sevenality-qdot {
	width: 3rem;
	min-height: 44px;
	padding:0;
	border: 0;
	cursor: pointer;
	background: transparent;
	display: flex;
	align-items: center;
}

.sevenality-qdot::before {
	content: "";
	display: block;
	width: 100%;
	height: 2px;
	background: rgba(255, 255, 255, .22);
	transition: background .3s ease;
}

.sevenality-qdot:hover::before,
.sevenality-qdot:focus-visible::before {
	background: rgba(255, 255, 255, .5);
}

.sevenality-qdot.is-current::before {
	background: #fff;
}

@media (prefers-reduced-motion: reduce) {
	.sevenality-index__panel img,
	.sevenality-qslide,
	.sevenality-row,
	.sevenality-qdot::before {
		transition: none;
	}
}

/*
 * Pinned method section — paint the scroll distance.
 *
 * A pinned block is lifted out of flow, leaving the generated
 * `.lvbl-pin-spacer` holding only its scroll height. The spacer is
 * transparent, so the theme's warm cream body (#fff8f2) showed through for
 * the whole 460vh the method section occupies — a huge pale gap between two
 * dark sections, visible on any fast scroll or if the pin fails.
 *
 * Paint the spacer that contains this section, scoped with :has() so other
 * pinned sections can carry their own colour.
 */
.lvbl-pin-spacer:has(> .sevenality-method) {
	background-color:var(--sev-blue-deep);
}

/* ============================================================
   HERO — LAYERED MARBLE DEPTH
   Depth from three planes of the SAME image, not three images:
   the file is already cached, so the extra layers cost no
   requests and no bytes. Each plane drifts at a different rate,
   which is what reads as depth when the page is static, while
   the plugin's bg-parallax handles depth on scroll.
   ============================================================ */
.sevenality-hero {
	position: relative;
	isolation: isolate; /* keep blend modes off the page behind */
}

/* Plane 1 — the core cover image. Slow, wide drift. */
.sevenality-hero .wp-block-cover__image-background {
	transform-origin: 52% 48%;
	will-change: transform;
	animation: sevenality-drift-a 46s ease-in-out infinite alternate;
}

/* Plane 2 — same marble, larger and softer, drifting the OTHER way.
   Counter-motion is what sells parallax; matched motion just looks
   like one moving photo. */
.sevenality-hero::before {
	content: "";
	position: absolute;
	inset: -8%;
	z-index: 0;
	background: var(--sevenality-marble) center / cover no-repeat;
	opacity: .45;
	mix-blend-mode: soft-light;
	transform-origin: 45% 55%;
	will-change: transform;
	animation: sevenality-drift-b 61s ease-in-out infinite alternate;
	pointer-events: none;
}

/* Plane 3 — a slow luminance sweep. Suggests light moving across a
   liquid surface; the thing that stops it reading as a still. */
.sevenality-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background: radial-gradient(
		60% 50% at 30% 40%,
		rgba(128, 171, 215, .18) 0%,
		rgba(128, 171, 215, 0) 70%
	);
	will-change: opacity, transform;
	animation: sevenality-sheen 38s ease-in-out infinite alternate;
	pointer-events: none;
}

/* content and scrim must sit above all three planes */
.sevenality-hero > .wp-block-cover__background,
.sevenality-hero > .wp-block-cover__inner-container {
	position: relative;
	z-index: 2;
}

@keyframes sevenality-drift-a {
	from { transform: scale(1.06) translate3d(-1.2%, -0.8%, 0); }
	to   { transform: scale(1.12) translate3d(1.2%,  0.9%, 0); }
}

@keyframes sevenality-drift-b {
	from { transform: scale(1.14) translate3d(1.6%,  1.1%, 0) rotate(0.4deg); }
	to   { transform: scale(1.06) translate3d(-1.5%, -1.2%, 0) rotate(-0.3deg); }
}

@keyframes sevenality-sheen {
	from { opacity: .55; transform: translate3d(-6%, -3%, 0); }
	to   { opacity: 1;   transform: translate3d(7%, 4%, 0); }
}

/* Ambient motion is decoration. Under reduced-motion the depth stays
   (the planes remain offset and scaled) but nothing moves. */
@media (prefers-reduced-motion: reduce) {
	.sevenality-hero .wp-block-cover__image-background,
	.sevenality-hero::before,
	.sevenality-hero::after {
		animation: none;
	}
}

/* ============================================================
   SCHEME-AWARE HOMEPAGE
   Light canvas with dark bands as punctuation — the original
   Sevenality pattern, restored.

   .sevenality-band  flips with the scheme (thesis, work, ideas, contact)
   .sevenality-hero / .sevenality-method / .sevenality-quoteband
                     stay FIXED in both schemes. They are brand covers,
                     not surfaces: the marble, the FLAME deck and the
                     testimonial band punctuate the page in either mode.

   Colour lives here rather than in block attributes on purpose — an
   inline style from a block attribute beats any stylesheet, so a
   hardcoded background in block markup can never be scheme-aware.
   ============================================================ */
:root {
	--sev-canvas:      light-dark(#FBFBFB, #0d0d0d);
	--sev-ink:         light-dark(#14171a, #ffffff);
	--sev-ink-soft:    light-dark(#4A4A4A, rgba(255, 255, 255, .72));
	/* Light value darkened from #8a8d90, which measured 3.17:1 against the
	   #fff8f2 ground — below the 4.5:1 AA floor, on the token used for every
	   standfirst, figure label and meta line on the site. #6e7174 clears it at
	   4.72:1. The dark value is unchanged: measured on the case study template
	   it already passes, and darkening it there would have dimmed text that is
	   correct. */
	--sev-ink-dim:     light-dark(#6a6c6f, rgba(255, 255, 255, .5));
	--sev-rule:        light-dark(#E4E2DE, rgba(255, 255, 255, .16));
	--sev-accent:      light-dark(#306090, #80ABD7);
}

.sevenality-band {
	background-color: var(--sev-canvas);
	color: var(--sev-ink);
	border-block-start: 1px solid var(--sev-rule);
}

.sevenality-band :is(h1, h2, h3, h4, p, span, cite, dd, dt) {
	color: inherit;
}

/* eyebrows and numerals take the accent, which also flips.
   The row count belongs here by that same rule — it is a numeral. Stating it
   explicitly rather than leaving it to `:is(...) { color: inherit }`, which
   was already handing it the link colour and happened to land on the accent
   on a light band and would not have on a dark one. */
.sevenality-band [style*="letter-spacing:0.24em"],
.sevenality-band .sevenality-row__num,
.sevenality-band .sevenality-row__count {
	color: var(--sev-accent);
}

.sevenality-band .sevenality-row__meta {
	color: var(--sev-ink-dim);
}

.sevenality-band .sevenality-row {
	border-block-start-color: var(--sev-rule);
}

.sevenality-band .sevenality-row:last-child {
	border-block-end-color: var(--sev-rule);
}

.sevenality-band .sevenality-row__name {
	color: var(--sev-ink);
}

/* the index panel placeholder should not be a black hole on light */
.sevenality-band .sevenality-index__panel {
	background: light-dark(#EFEDEA, #161616);
}

/* the contact CTA button inverts against the canvas */
.sevenality-band .wp-block-button__link {
	background-color: var(--sev-ink) !important;
	color: var(--sev-canvas) !important;
}

/* Fixed brand bands — explicitly NOT scheme-aware.
   Restated here so a future edit to .sevenality-band cannot leak into
   them by accident. */
.sevenality-hero,
.sevenality-method,
.sevenality-quoteband,
/* The philanthropy brief sits on #1a1a1a and needs the tokens flipped the same
   way. It first shipped with an `is-dark` class, which is what the case-study
   template uses and means nothing here — the result was near-black type on a
   near-black band. The mechanism is color-scheme, not a class name. */
.sevenality-philbrief {
	color-scheme: dark;
}

/* ============================================================
   GLOBAL MARBLE TRACK — the page-wide layer
   Decoration only: no content, no pointer events, and it reuses
   the marble already fetched for the hero so it costs nothing.
   The runtime positions it fixed and drives opacity/scale from
   story progress; everything here is just how it LOOKS.
   ============================================================ */
.sevenality-gtrack{
	pointer-events:none;
	height:100vh;
	background:var(--sevenality-marble) center / cover no-repeat;
	mix-blend-mode:soft-light;
	opacity:0;            /* runtime takes over; invisible if JS never runs */
	will-change:opacity, transform;
	z-index:0;
}

/* Never let decoration sit over content. */
.sevenality-band,
.sevenality-hero,
.sevenality-method,
.sevenality-quoteband{ position:relative; z-index:1 }

@media (prefers-reduced-motion: reduce){
	.sevenality-gtrack{ display:none }
}

/* Hero headline: colour one word WITHOUT nesting a span.
 *
 * The headline previously wrapped "communities" in an inline <span>. That
 * span sat INSIDE an element carrying lvbl-anim-split-words-mask, which wraps
 * every word in its own span to clip it — the extra nesting level escaped the
 * layout entirely (measured at x=1451 on a 1440 viewport) and pushed a
 * horizontal scrollbar onto the whole page. Removing the nested span dropped
 * overflowing elements from 1 to 0.
 *
 * The splitter emits `<span data-word="N">` per word, so the colour can come
 * from CSS instead and both the masked reveal and the two-tone headline
 * survive.
 *
 * ⚠ INDEX-BOUND: data-word="2" is the third word. If the headline copy
 * changes, update this index or the wrong word turns blue.
 * "Building(0) better(1) communities(2) by(3) building(4) better(5) brands(6)"
 */
.sevenality-hero h1 [data-word="2"]{ color: var(--wp--preset--color--brand-light, #80ABD7) }
.sevenality-hero{ overflow: clip }

/* Contain sub-pixel horizontal overflow.
   Measured 1447px scrollWidth against a 1440px viewport — 7px of horizontal
   scroll with NO element reporting an oversized box. It comes from transformed
   descendants (the word-split spans and the hero's depth layers) contributing
   to the scrollable overflow area rather than to layout.
   `clip` rather than `hidden`: hidden would create a scroll container and
   break the position:sticky pins in the method section. */
html, body { overflow-x: clip }

/* The story anchor must not participate in layout.
   sevenality_ensure_story_anchor() wraps the content in <div data-lvbl-story>
   so the plugin's global timeline has something to measure. That wrapper made
   every section a GRANDCHILD of .entry-content, which broke the theme's
   alignfull escape — full-bleed bands collapsed to the 680px content column.
   display:contents removes the wrapper's box from layout while leaving the
   element in the DOM for the runtime to measure. */
.lvbl-story { display: contents }

/* Index rows are not body links.
   The theme underlines content links with
   `.entry-content a:not(.btn):not(.wp-block-button__link)` — specificity
   (0,3,1), which beats a bare `.sevenality-row` at (0,1,0). Match its shape
   so this ties and wins on load order, rather than reaching for !important. */
.entry-content a.sevenality-row:not(.wp-block-button__link) {
	text-decoration: none;
}

/* Section interiors span their band.
   The bands are constrained layouts, so WordPress caps non-aligned children
   at --wp--style--global--content-size (46rem here, since theme.json now owns
   layout). That is right for prose and wrong for these full-width devices —
   the work index collapsed to a 273px panel beside 339px of rows.
   These wrappers manage their own internal grid and should fill the band. */
.sevenality-band .sevenality-index__layout,
.sevenality-band .sevenality-ideas__rows,
.sevenality-quoteband .sevenality-qband,
.sevenality-band > .wp-block-group {
	/* (0,2,0) to beat WordPress's constrained-layout rule
	   `.is-layout-constrained > :where(:not(.alignfull)…)` at (0,1,0) —
	   a bare class ties and loses on load order. */
	max-width: none;
	width: 100%;
}

/* ============================================================
   CASE STUDY (single-project.php)
   One template, sixteen looks. --cs-accent is set per project
   from its featured image; .is-dark flips the canvas when the
   accent needs a dark ground to stay legible.
   ============================================================ */
.sevenality-cs{
	--cs-canvas:#FBFBFB; --cs-ink:#14171a; --cs-soft:#4A4A4A;
	--cs-dim:#8a8d90; --cs-rule:#E4E2DE;
	--cs-gutter:clamp(1.25rem,4vw,4.5rem); --cs-measure:44rem;
	background:var(--cs-canvas); color:var(--cs-ink);
}
.sevenality-cs.is-dark{
	--cs-canvas:#0d0d0d; --cs-ink:#ffffff; --cs-soft:rgba(255,255,255,.72);
	--cs-dim:rgba(255,255,255,.45); --cs-rule:rgba(255,255,255,.16);
}
.sevenality-cs .cs-wrap{max-width:1560px;margin-inline:auto;padding-inline:var(--cs-gutter)}
.sevenality-cs .cs-micro{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.24em;text-transform:uppercase;color:var(--cs-accent);margin:0}

/* hero — the project's colour washes its own image */
.sevenality-cs .cs-hero{position:relative;isolation:isolate;overflow:clip;min-height:clamp(30rem,76vh,44rem);display:flex;align-items:flex-end;background:#0b0b0c;padding-block:var(--sp-5)}
.sevenality-cs .cs-hero__img{position:absolute;inset:0;z-index:0}
.sevenality-cs .cs-hero__img img{width:100%;height:100%;object-fit:cover}
.sevenality-cs .cs-hero__scrim{position:absolute;inset:0;z-index:1;background:
	radial-gradient(75% 65% at 18% 82%, color-mix(in srgb, var(--cs-accent) 55%, transparent) 0%, transparent 62%),
	linear-gradient(180deg,rgba(6,8,12,.30) 0%,rgba(6,8,12,.16) 40%,rgba(6,8,12,.88) 100%)}
.sevenality-cs .cs-hero__in{position:relative;z-index:2;width:100%}
.sevenality-cs .cs-hero .cs-micro{color:var(--ink-on-dark-dim)}
.sevenality-cs .cs-hero__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h1);line-height:1;letter-spacing:-.03em;color:var(--ink-on-dark);margin:var(--s-lg) 0 0;max-width:18ch;text-wrap:balance}
.sevenality-cs .cs-hero__meta{display:flex;flex-wrap:wrap;gap:var(--s-xs);margin-block-start:var(--sp-3);padding-block-start:var(--s-lg);border-block-start:1px solid rgba(255,255,255,.22)}
.sevenality-cs .cs-tag{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.2em;text-transform:uppercase;color:var(--ink-on-dark-soft);border:1px solid rgba(255,255,255,.32);padding:var(--s-3xs) var(--s-xs)}

/* the arc */
.sevenality-cs .cs-arc{padding-block:var(--sp-6)}
.sevenality-cs .cs-act{display:grid;grid-template-columns:1fr;gap:var(--sp-3);padding-block:var(--sp-4);border-block-start:1px solid var(--cs-rule)}
@media(min-width:900px){
	.sevenality-cs .cs-act{grid-template-columns:repeat(12,1fr);align-items:start}
	.sevenality-cs .cs-act__label{grid-column:1/span 3}
	.sevenality-cs .cs-act__body{grid-column:5/span 7}
	/* THE ALTERNATION IS GONE. Flipping the label from left to right on every
	   other act was meant to supply rhythm, but the acts are named Objective,
	   Challenge, Solutions, Results — a reader is following an argument, and
	   moving the signpost each time makes them re-find it. With the in-body
	   images restored the plates now provide the variation, which is what
	   should have been carrying it. */
}
.sevenality-cs .cs-act__n{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.2em;color:var(--cs-accent-ink,var(--cs-accent));margin:0}
/* Every act is announced in the project's colour, not just Results. The
   readable variant is used because seven of fourteen accents fail 4.5:1 on
   the dark canvas — see the note in single-project.php. */
.sevenality-cs .cs-act__h{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h3);line-height:1.1;letter-spacing:-.02em;margin:var(--s-xs) 0 0;text-transform:capitalize;color:var(--cs-accent-ink,var(--cs-accent))}
.sevenality-cs .cs-act__body p{margin:0 0 var(--s-lg);font-size:var(--t-lead);line-height:1.7;color:var(--cs-soft);max-width:var(--cs-measure)}
.sevenality-cs .cs-act__body p:last-child{margin:0}
/* results is the answer the reader came for */
.sevenality-cs .cs-act--results .cs-act__body p{color:var(--cs-ink);font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-h4);line-height:1.5;border-inline-start:2px solid var(--cs-accent);padding-inline-start:var(--s-lg)}

/* plates */
.sevenality-cs .cs-plate{margin-block:var(--sp-5)}
.sevenality-cs .cs-plate--bleed{width:100vw;margin-inline:calc(50% - 50vw)}
.sevenality-cs .cs-plate--duo{display:grid;grid-template-columns:1fr;gap:var(--sp-2)}
@media(min-width:760px){.sevenality-cs .cs-plate--duo{grid-template-columns:repeat(2,1fr)}}
.sevenality-cs .cs-plate figcaption{font-family:var(--wp--preset--font-family--sans);font-weight:300;font-size:var(--t-micro);color:var(--cs-dim);margin-block-start:var(--s-sm)}
.sevenality-cs .cs-plate--bleed figcaption{max-width:1560px;margin-inline:auto;padding-inline:var(--cs-gutter)}
.sevenality-cs .cs-extra{max-width:var(--cs-measure);color:var(--cs-soft);padding-block-start:var(--sp-3);border-block-start:1px solid var(--cs-rule)}

/* testimonial — the accent carries the band */
.sevenality-cs .cs-quote{background:color-mix(in srgb, var(--cs-accent) 88%, #101014);color:var(--ink-on-dark);padding-block:var(--sp-6)}
.sevenality-cs .cs-quote .cs-micro{color:var(--ink-on-dark-dim)}
.sevenality-cs .cs-quote__t{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-h4);line-height:1.4;margin:var(--s-lg) 0 0;max-width:34ch}
.sevenality-cs .cs-quote__c{font-style:normal;display:block;margin-block-start:var(--s-xl);padding-block-start:var(--s-md);border-block-start:1px solid rgba(255,255,255,.22)}
.sevenality-cs .cs-quote__n{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.2em;text-transform:uppercase;color:var(--ink-on-dark)}
.sevenality-cs .cs-quote__co{display:block;font-family:var(--wp--preset--font-family--sans);font-weight:300;font-size:var(--t-meta);color:var(--ink-on-dark-dim);margin-block-start:var(--s-2xs)}

/* more work + cta */
.sevenality-cs .cs-next{padding-block:var(--sp-5)}
.sevenality-cs .cs-rows{margin-block-start:var(--sp-3)}
.sevenality-cs .cs-row{display:grid;grid-template-columns:auto 1fr auto;gap:var(--s-xs) var(--sp-1);align-items:baseline;padding-block:var(--sp-2);border-block-start:1px solid var(--cs-rule);transition:opacity .3s ease}
.sevenality-cs .cs-row:last-child{border-block-end:1px solid var(--cs-rule)}
.sevenality-cs .cs-rows:hover .cs-row{opacity:.32}
.sevenality-cs .cs-rows .cs-row:hover,.sevenality-cs .cs-rows .cs-row:focus-visible{opacity:1}
.entry-content .sevenality-cs a.cs-row,.sevenality-cs a.cs-row{text-decoration:none}
.sevenality-cs .cs-row__n{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.2em;color:var(--cs-accent)}
.sevenality-cs .cs-row__name{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h4);line-height:1.06;letter-spacing:-.02em;margin:0;color:var(--cs-ink)}
.sevenality-cs .cs-row__meta{font-family:var(--wp--preset--font-family--sans);font-weight:300;font-size:var(--t-micro);letter-spacing:.18em;text-transform:uppercase;color:var(--cs-dim);text-align:right}
@media(max-width:560px){.sevenality-cs .cs-row{grid-template-columns:auto 1fr}.sevenality-cs .cs-row__meta{grid-column:2;text-align:left}}
.sevenality-cs .cs-cta{background:color-mix(in srgb, var(--cs-accent) 8%, var(--cs-canvas));padding-block:var(--sp-5);border-block-start:1px solid var(--cs-rule)}
/* Explicit ink. Without it this fell through to the same near-black that hid
   the act headings — 'Let's create something amazing together' was invisible
   on the dark canvas. */
.sevenality-cs .cs-cta__t{color:var(--cs-ink);font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h3);line-height:1.05;letter-spacing:-.025em;margin:var(--s-lg) 0 0;max-width:20ch;text-wrap:balance}
.sevenality-cs .cs-btn{display:inline-flex;align-items:center;gap:var(--s-sm);margin-block-start:var(--s-2xl);font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.2em;text-transform:uppercase;background:var(--cs-ink);color:var(--cs-canvas);padding:var(--s-md) var(--s-2xl);text-decoration:none}

/* Plate framing.
   Attached images range from full-bleed photography to small logo files, so
   an unframed plate leaves little assets floating in whitespace. Give every
   plate a consistent frame and CONTAIN rather than cover — cropping a logo
   or a business-card layout to fill a box is worse than letterboxing it —
   with a faint accent ground so the letterboxing reads as intentional. */
.sevenality-cs .cs-plate figure{
	margin:0;
	background:color-mix(in srgb, var(--cs-accent) 6%, var(--cs-canvas));
	overflow:hidden;
}
.sevenality-cs .cs-plate--bleed figure{aspect-ratio:21/9}
.sevenality-cs .cs-plate--duo figure{aspect-ratio:4/3}
.sevenality-cs .cs-plate figure img{
	width:100%;height:100%;object-fit:contain;display:block;
}
@media(max-width:760px){
	.sevenality-cs .cs-plate--bleed figure{aspect-ratio:16/10}
}

/* Authored inline images inside an ACF body.
   Many bodies carry their own <p><img …></p>. Give them the same frame as a
   plate, and break them out of the reading measure so they are not squeezed
   into a text column. */
.sevenality-cs .cs-act__body p:has(img){
	max-width:none;
	margin-block:var(--sp-3);
}
.sevenality-cs .cs-act__body img{
	width:100%;height:auto;display:block;
	background:color-mix(in srgb, var(--cs-accent) 6%, var(--cs-canvas));
}
/* The results accent rule marks PROSE, not pictures — without this it runs
   down the side of an image paragraph as a long stray line. */
.sevenality-cs .cs-act--results .cs-act__body p:has(img){
	border-inline-start:0;
	padding-inline-start:0;
}

/* Keep the site header above page content.
   .site-header is position:absolute at top:0 with no z-index, so it relies on
   page content being transparent. Any template whose <main> paints an opaque
   background covers the nav entirely — which is exactly what happened on the
   work index. Give the header a stacking order instead of asking every
   template to stay transparent. */
.site-header { z-index: 20 }

/* And reserve room for it, since an absolute header takes no space in flow. */
.sevenality-workindex .wi-head { padding-block-start:var(--sp-7)}

/* ============================================================
   WORK GRID (templates/tpl-portfolio.php)
   Image-led. The work is the point, so tiles are square and
   large, on a dark ground so the imagery carries the page.
   One grid + filter, never grouped sections — grouping turned
   17 projects into 55 repeated rows.
   ============================================================ */
.sevenality-workgrid{
	--wg-canvas:#0d0d0d; --wg-ink:#fff;
	--wg-dim:rgba(255,255,255,.5); --wg-rule:rgba(255,255,255,.16);
	--wg-gutter:clamp(1.25rem,4vw,4.5rem);
	background:var(--wg-canvas);color:var(--wg-ink);
}
.sevenality-workgrid .wg-wrap{max-width:1560px;margin-inline:auto;padding-inline:var(--wg-gutter)}
.sevenality-workgrid .wg-micro{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.24em;text-transform:uppercase;color:var(--wp--preset--color--brand-light,#80ABD7);margin:0}

/* Head was 722px — 23.4% of the page — with the right half empty and the
   first row of work below the fold. Top padding roughly halved, and the intro
   moved into that empty column instead of running under the title. */
.sevenality-workgrid .wg-head{padding-block:var(--sp-5) var(--sp-3)}
.sevenality-workgrid .wg-head__grid{display:grid;gap:var(--sp-3)}
@media(min-width:900px){
	.sevenality-workgrid .wg-head__grid{
		grid-template-columns:minmax(0,1fr) minmax(0,26rem);
		/* Top-aligned. Bottom-aligning them looked right in principle — the
		   intro's last line settling onto the title's baseline — but the intro
		   column is much the taller of the two, so it pushed the title down
		   and left a dead quadrant above the eyebrow. Aligned from the top,
		   the short title and the long standfirst start together and the slack
		   falls under the title, which is where a magazine puts it. */
		align-items:start;
		column-gap:var(--sp-5);
	}
}
.sevenality-workgrid .wg-title{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h1);line-height:.98;letter-spacing:-.03em;margin:var(--s-lg) 0 0;max-width:14ch}
.sevenality-workgrid .wg-intro{max-width:44rem}
/* This copy is supporting material, not a lead paragraph, and at full size it
   was what set the head's height on every width — three paragraphs before a
   phone visitor saw a single project. Smaller and tighter buys back most of a
   screen without cutting a word. */
.sevenality-workgrid .wg-intro p{font-family:var(--wp--preset--font-family--sans);font-weight:300;font-size:var(--t-small);line-height:1.6;color:var(--ink-on-dark-dim);margin:0 0 var(--s-sm)}
.sevenality-workgrid .wg-intro p:last-child{margin:0}

/* filter chips */
/* The filter is a control strip, not a section. It was spending ~128px of
   vertical between the head and the first tile; the rule already separates
   them, so the space was doing the job twice. */
.sevenality-workgrid .wg-controls{display:flex;flex-wrap:wrap;gap:var(--s-xs);padding-block:var(--sp-1);border-block-end:1px solid var(--wg-rule);margin-block-end:var(--sp-2)}
.sevenality-workgrid .wg-chip{
	font-family:var(--wp--preset--font-family--sans);font-weight:400;
	font-size:var(--t-micro);letter-spacing:.16em;text-transform:uppercase;
	color:var(--ink-on-dark-dim);background:transparent;
	border:1px solid var(--wg-rule);padding:var(--s-xs) var(--s-md);cursor:pointer;
	display:inline-flex;align-items:center;gap:var(--s-xs);
	transition:color .25s ease,border-color .25s ease,background .25s ease;
}
.sevenality-workgrid .wg-chip:hover,.sevenality-workgrid .wg-chip:focus-visible{color:var(--ink-on-dark);border-color:var(--ink-on-dark-faint)}
.sevenality-workgrid .wg-chip.is-on{color:var(--sev-black);background:#fff;border-color:var(--ink-on-dark)}
.sevenality-workgrid .wg-chip__n{font-variant-numeric:tabular-nums;opacity:.55;font-size:var(--t-micro)}

/* Situation chips are sentences, not single words — "One brand, many
   audiences" against the old "Branding". Measured at 390px they wrapped to
   FOUR rows, putting ~160px of filter bar above the first tile on a page
   whose whole job is showing work, and reintroducing exactly the
   below-the-fold problem the header grid was reshaped to fix.

   So on narrow screens the bar scrolls sideways instead of stacking: one row,
   fixed cost, and the horizontal swipe is the familiar phone gesture for a
   filter row. The scrollbar is hidden but the overflow is real, so keyboard
   and trackpad scrolling still reach the last chip. */
@media (max-width: 700px){
	.sevenality-workgrid .wg-controls{
		flex-wrap:nowrap;
		overflow-x:auto;
		scrollbar-width:none;
		-webkit-overflow-scrolling:touch;
	}
	.sevenality-workgrid .wg-controls::-webkit-scrollbar{display:none}
	.sevenality-workgrid .wg-chip{flex:0 0 auto}
}

/* the grid — square tiles, image-led */
.sevenality-workgrid .wg-grid{
	display:grid;
	grid-template-columns:repeat(auto-fill,minmax(min(100%,17rem),1fr));
	gap:var(--sp-1);
	padding-block-end:var(--sp-5);
}
/* TWO UP ON PHONES. `auto-fill` at a 17rem minimum resolves to ONE column
   below ~640px, which made the grid 5,828px of a 7,449px page — sixteen
   full-width tiles, a seven-screen scroll to see the work. Two up halves it
   and, more importantly, lets a visitor compare projects instead of meeting
   them one at a time. The meta has to come down with the tile or the title
   swallows a 165px square. */
@media(max-width:640px){
	.sevenality-workgrid .wg-grid{
		grid-template-columns:repeat(2,minmax(0,1fr));
		gap:var(--s-xs);
	}
	.sevenality-workgrid .wg-tile__meta{
		padding:var(--s-xs) var(--s-sm);
		padding-block-start:var(--s-2xl);
		gap:var(--s-3xs);
	}
	.sevenality-workgrid .wg-tile__name{font-size:var(--t-small);line-height:1.2}
	/* One line, not two: at half width a two-line tagline is taller than the
	   name it belongs to. */
	.sevenality-workgrid .wg-tile__type{font-size:var(--t-micro);line-height:1.35;-webkit-line-clamp:1}
}
.sevenality-workgrid .wg-tile{
	position:relative;display:block;text-decoration:none;color:inherit;
	background:#141414;overflow:hidden;
}
.sevenality-workgrid .wg-tile__media{display:block;aspect-ratio:1;overflow:hidden;position:relative}
.sevenality-workgrid .wg-tile__media img{
	width:100%;height:100%;object-fit:cover;display:block;
	transition:transform .6s cubic-bezier(.2,.7,.2,1);
}
/* the accent veil — the project's own colour, held at rest, arriving on
   engagement so the wall reads as work first and colour second */
.sevenality-workgrid .wg-tile__veil{
	position:absolute;inset:0;
	background:color-mix(in srgb, var(--wg-accent) 42%, transparent);
	opacity:0;transition:opacity .35s ease;
}
.sevenality-workgrid .wg-tile__meta{
	position:absolute;inset-inline:0;inset-block-end:0;z-index:2;
	display:flex;flex-direction:column;gap:var(--s-3xs);
	padding:var(--sp-1);
	/* Tall, eased scrim. A short one is fine over dark photography and fails
	   over light tiles — Hope Center and Bellame are near-white at the foot,
	   which left the title unreadable. This holds white type over any image. */
	padding-block-start:var(--sp-5);
	background:linear-gradient(0deg,
		rgba(8,8,10,.94) 0%,
		rgba(8,8,10,.80) 38%,
		rgba(8,8,10,.42) 68%,
		rgba(8,8,10,0) 100%);
	transform:translateY(.35rem);opacity:.92;
	transition:transform .35s ease,opacity .35s ease;
}
.sevenality-workgrid .wg-tile__name{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-lead);line-height:1.15;color:var(--ink-on-dark)}
/* Sentence case, not the 9px uppercase eyebrow that suited a one-word
   discipline. A tagline IS a sentence and has to read as one; clamped to two
   lines so a long one cannot shove the title off the tile. */
.sevenality-workgrid .wg-tile__type{font-family:var(--wp--preset--font-family--sans);font-weight:300;font-size:var(--t-meta);line-height:1.45;letter-spacing:0;text-transform:none;color:var(--ink-on-dark-soft);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}

.sevenality-workgrid .wg-tile:hover .wg-tile__media img,
.sevenality-workgrid .wg-tile:focus-visible .wg-tile__media img{transform:scale(1.05)}
.sevenality-workgrid .wg-tile:hover .wg-tile__veil,
.sevenality-workgrid .wg-tile:focus-visible .wg-tile__veil{opacity:1}
.sevenality-workgrid .wg-tile:hover .wg-tile__meta,
.sevenality-workgrid .wg-tile:focus-visible .wg-tile__meta{transform:none;opacity:1}
.sevenality-workgrid .wg-tile:focus-visible{outline:2px solid #fff;outline-offset:2px}

/* filtered out */
.sevenality-workgrid .wg-tile.is-out{display:none}

.sevenality-workgrid .wg-note{font-family:var(--wp--preset--font-family--sans);font-weight:300;font-size:var(--t-meta);line-height:1.6;color:var(--wg-dim);max-width:60ch;margin:0 0 var(--sp-5)}

@media(prefers-reduced-motion:reduce){
	.sevenality-workgrid .wg-tile__media img,
	.sevenality-workgrid .wg-tile__veil,
	.sevenality-workgrid .wg-tile__meta,
	.sevenality-workgrid .wg-chip{transition:none}
}

/* Explicit colour on the work-grid headings.
   The theme styles h1/.entry-title with its own colour, which outranks the
   colour inherited from .sevenality-workgrid — on a dark canvas that rendered
   the page title near-invisible. */
.sevenality-workgrid .wg-title,
.sevenality-workgrid h1 { color:var(--ink-on-dark) }
.sevenality-workgrid .wg-intro p { color:var(--ink-on-dark-dim) }

/* Dark-canvas pages: the header overlaps `main`, so header furniture sitting in
   that overlap has to switch ink. The scheme toggle is black by default and
   vanished on the work index and on all nine dark case studies in light mode. */
body.sevenality-dark-canvas .lvbl-cst-icon{color:var(--ink-on-dark-soft)}
body.sevenality-dark-canvas .lvbl-cst-toggle:hover .lvbl-cst-icon,
body.sevenality-dark-canvas .lvbl-cst-toggle:focus-visible .lvbl-cst-icon{color:var(--ink-on-dark)}

/* ============================================================
   SEVENALITY FOOTER
   A sitemap on black marble, signed with the wordmark.
   ============================================================
   What this replaces was 990px — 18% of a page — for SIX links, five of them
   the header nav restated while that header is sticky and never leaves the
   screen. See footer.php for the promises it made that nothing backed.

   The marble is the theme's own brand-texture-dark.jpg, not the blue hero
   texture: the footer should feel like the same material seen in shadow, not
   a second hero. */
/* Doubled class, (0,2,0). The parent ships `.site-footer{background:...}` in
   build/dark-mode-styles.css — a SHORTHAND, which resets background-image to
   none — and that bundle is enqueued AFTER this stylesheet, so a single class
   loses on order. Measured: background-image computed to `none` with the rule
   present and the texture returning 200. */
.sevenality-footer.sevenality-footer{
	position:relative;
	background-color:#0b0b0c;
	/* Two declarations on purpose. The first is always valid and is what a
	   browser without image-set() support uses; the second overrides it where
	   image-set() IS supported and takes the WebP. 324 KB -> 16 KB. */
	background-image:url("assets/textures/brand-texture-dark.jpg");
	background-image:image-set(url("assets/textures/brand-texture-dark.webp") type("image/webp"), url("assets/textures/brand-texture-dark.jpg") type("image/jpeg"));
	background-size:cover;
	background-position:center;
	color:var(--ink-on-dark);
	--sf-rule:rgba(255,255,255,.16);
	--sf-dim:rgba(255,255,255,.6);
	padding-block:var(--sp-5) var(--sp-2);
	margin-block-start:0;
	overflow:hidden;
}
.sevenality-footer .sf-inner{width:min(100% - 2rem,var(--sev-w-wide,86.25rem));margin-inline:auto}

/* ---- sitemap ---- */
.sevenality-footer .sf-map{display:grid;gap:var(--sp-3);grid-template-columns:repeat(2,minmax(0,1fr))}
@media(min-width:820px){.sevenality-footer .sf-map{grid-template-columns:repeat(4,minmax(0,1fr))}}
.sevenality-footer .sf-col__h{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.24em;text-transform:uppercase;color:var(--sev-blue-light);margin:0 0 var(--s-md);padding-block-end:var(--s-sm);border-block-end:1px solid var(--sf-rule)}
.sevenality-footer .sf-col__list{list-style:none;margin:0;padding:0}
.sevenality-footer .sf-col__list a{display:block;padding-block:var(--s-xs);font-family:var(--wp--preset--font-family--sans);font-size:var(--t-small);line-height:1.35;color:var(--ink-on-dark);text-decoration:none !important}
.sevenality-footer .sf-col__list a:hover,
.sevenality-footer .sf-col__list a:focus-visible{color:var(--sev-blue-light)}

/* ---- the sign-off ----
   Sized in vw so the wordmark spans the measure at any viewport rather than
   being pinned to one breakpoint. Ten characters of the display face fill
   roughly 5.2em, so ~19vw lands it edge to edge on a 1440 band. */
.sevenality-footer .sf-sign{
	position:relative;
	font-family:var(--wp--preset--font-family--display);
	font-weight:400;
	font-size:min(19vw,17rem);
	line-height:.82;
	letter-spacing:-.045em;
	margin:var(--sp-5) 0 0;
	color:var(--ink-on-dark);
	white-space:nowrap;
}
.sevenality-footer .sf-sign__base,
.sevenality-footer .sf-sign__fill{display:block}

/* THE FILL SWEEP
   The blue marble is the SAME stone as the footer ground, lit — the two
   textures are the same swirl in different values, so the letters read as the
   material they are cut from rather than as a pasted-in picture.

   The fill copy is laid exactly over the base. `background-clip:text` paints
   the marble inside the letterforms; the mask then reveals it left to right in
   reading order, so the signature completes as you arrive.

   The mask edge is deliberately WIDE — 18% of the word — which is the whole
   "blur": a soft boundary bleeding into the letters costs nothing to paint,
   where an actual filter on display type this size is expensive. */
.sevenality-footer .sf-sign__fill{
	position:absolute;
	/* Extended BELOW the box on purpose. background-clip:text paints only
	   within the element's background box, and line-height:.82 leaves the
	   descenders hanging outside it — the tail of the "y" stayed white while
	   the rest of the word had filled. Dropping the bottom edge by a quarter
	   of an em brings the descender inside the painted area. */
	inset:0 0 -.25em 0;
	/* Reuses --sevenality-marble (printed in wp_head by
	   sevenality_marble_custom_property) rather than naming the theme JPEG
	   again. The custom property resolves to the uploaded marble attachment —
	   the SAME artwork at the same 1440x1080, 59 KB as WebP against 1,478 KB
	   for the theme file — and the page has already downloaded it for the hero
	   image, so painting the text costs nothing further. Measured: the JPEG was
	   the single heaviest resource on the site, pulled in by this one rule to
	   fill letterforms. It stays on disk as the fallback the property itself
	   uses when no attachment is set. */
	background-image:var(--sevenality-marble);
	background-size:cover;
	background-position:center;
	-webkit-background-clip:text;
	background-clip:text;
	color:transparent;
	-webkit-mask-image:linear-gradient(to right,#000 calc(var(--sf-p) - 18%),transparent var(--sf-p));
	mask-image:linear-gradient(to right,#000 calc(var(--sf-p) - 18%),transparent var(--sf-p));
	pointer-events:none;
}

/* 0% is the DEFAULT, which means the fill is masked out entirely and the solid
   white base is what shows. That is the fallback for Firefox, which has no
   scroll-driven animation, and for reduced motion. The signature is never
   half-arrived by accident. */
@property --sf-p{syntax:'<percentage>';inherits:false;initial-value:0%}

@supports (animation-timeline: view()){
	@media(prefers-reduced-motion:no-preference){
		/* THE RANGE'S CEILING IS THE SUBJECT'S HEIGHT.
		 *
		 * Measured on the Reposition spoke: the footer is 658px tall, so its
		 * `entry` phase spans exactly 658px of scroll, and `entry 12% 88%`
		 * spent 480px of that — scrollY 2476 to 2956, finishing 80px before
		 * the document ended. Sampling --sf-p confirmed it: 0% at 2396, 118%
		 * by 2956. On a trackpad fling to the bottom, the whole signature
		 * writes itself in a fraction of a second and is already finished
		 * when the reader arrives.
		 *
		 * Widening the percentages could not fix it, because 658px was the
		 * entire budget. So the TIMELINE moves to a taller subject: #main,
		 * the whole page body above the footer. `entry` on that starts as the
		 * page content begins arriving and finishes as it clears, which
		 * spends thousands of pixels instead of hundreds — and crucially the
		 * signature is already well underway BEFORE the footer appears,
		 * rather than racing to complete inside it.
		 *
		 * The range was then chosen by measurement rather than taste. Sampling
		 * --sf-p at eight scroll positions across four candidate ranges:
		 *
		 *   contain 0% 100%   completes at ~87% of scroll — before the footer
		 *                     is on screen at all, so nobody ever sees it move
		 *   cover 70% 100%    only reaches 98% by the page end — never lands
		 *   cover 50% 95%     begins at half the scroll, completes exactly at
		 *                     the bottom, and is still visibly writing while
		 *                     the footer is in view
		 *
		 * That is 1,518px of scroll on this page against 480px before, and
		 * because the range is relative to #main it scales with page length
		 * instead of being a fixed pixel budget that suits one template.
		 */
		/* A named view-timeline is only visible to DESCENDANTS of the element
		 * that declares it. `.sf-sign__fill` lives in <footer>, a SIBLING of
		 * #main, so naming the timeline on #main alone left the reference
		 * unresolved — and with `animation-fill-mode: both` that pins the
		 * signature at its END state, permanently full, on every page. It
		 * looked like a styling choice rather than a broken animation.
		 * `timeline-scope` on a common ancestor hoists the name so the footer
		 * can see it. */
		body{timeline-scope:--sf-in}
		#main{view-timeline-name:--sf-in;view-timeline-axis:block}
		.sevenality-footer .sf-sign__fill{
			animation:sf-fill linear both;
			animation-timeline:--sf-in;
			animation-range:cover 50% cover 95%;
		}
		@keyframes sf-fill{from{--sf-p:0%}to{--sf-p:118%}}
	}
}

.sevenality-footer .sf-meta{display:flex;flex-wrap:wrap;justify-content:space-between;gap:var(--s-sm) var(--s-xl);margin-block-start:var(--sp-2);padding-block-start:var(--s-lg);border-block-start:1px solid var(--sf-rule)}
.sevenality-footer .sf-copy,
.sevenality-footer .sf-place{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta);color:var(--sf-dim);margin:0}

/* ============================================================
   WORK CAROUSEL
   Editorial slides over the current project's own photograph,
   blurred. See patterns/work-carousel.php.
   ============================================================ */
.sevenality-wcar{position:relative;overflow:hidden;isolation:isolate;color:var(--ink-on-dark);padding-block:var(--sp-6)}

/* backdrop: the current slide's image, blurred hard enough to be colour
   rather than picture, so type stays readable over any of the six */
.sevenality-wcar .wcar-bg{position:absolute;inset:0;z-index:-1}
.sevenality-wcar .wcar-bg__layer{
	position:absolute;inset:-8%;
	background-size:cover;background-position:center;
	filter:blur(42px) saturate(1.25);
	opacity:0;transition:opacity .6s ease;
}
.sevenality-wcar .wcar-bg__layer.is-current{opacity:1}
/* Without this the blurred photo alone gives 2-3:1 on light images. */
.sevenality-wcar .wcar-bg__veil{position:absolute;inset:0;background:rgba(10,10,12,.72)}

.sevenality-wcar .wcar-in{
	max-width:var(--wp--style--global--wide-size,86.25rem);
	margin-inline:auto;padding-inline:var(--sp-3);
}

/* head */
.sevenality-wcar .wcar-head{
	display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
	gap:var(--s-md) var(--sp-2);
	padding-block-end:var(--sp-3);
	border-block-end:1px solid rgba(255,255,255,.18);
}
.sevenality-wcar .wcar-title{
	font-family:var(--wp--preset--font-family--display);font-weight:400;
	font-size:var(--t-h3);line-height:1;letter-spacing:-.02em;
	margin:0;color:var(--ink-on-dark);
}
.sevenality-wcar .wcar-controls{display:flex;align-items:center;gap:var(--sp-1)}
.sevenality-wcar .wcar-count{
	font-family:var(--wp--preset--font-family--sans);font-weight:300;
	font-size:var(--t-meta);letter-spacing:.18em;color:var(--ink-on-dark-dim);margin:0;
	font-variant-numeric:tabular-nums;
}
.sevenality-wcar .wcar-all{
	font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta);
	letter-spacing:.16em;text-transform:uppercase;color:var(--ink-on-dark);text-decoration:none;
	padding:var(--s-sm) var(--s-md);min-height:44px;display:inline-flex;align-items:center;
	border:1px solid rgba(255,255,255,.34);transition:background .25s ease,color .25s ease;
}
.sevenality-wcar .wcar-all:hover,.sevenality-wcar .wcar-all:focus-visible{background:#fff;color:var(--sev-black)}
.sevenality-wcar .wcar-arrow{
	width:44px;min-height:44px;display:grid;place-items:center;
	background:transparent;color:var(--ink-on-dark);border:1px solid rgba(255,255,255,.34);
	cursor:pointer;font-size:var(--t-body);transition:background .25s ease,color .25s ease,opacity .25s ease;
}
.sevenality-wcar .wcar-arrow:hover:not(:disabled),
.sevenality-wcar .wcar-arrow:focus-visible:not(:disabled){background:#fff;color:var(--sev-black)}
/* The carousel does not wrap, so the ends must LOOK unavailable, not just be. */
.sevenality-wcar .wcar-arrow:disabled{opacity:.3;cursor:default}

/* stage: slides share one grid cell so height follows the tallest */
.sevenality-wcar .wcar-stage{display:grid;padding-block-start:var(--sp-4)}
.sevenality-wcar .wcar-slide{
	grid-area:1/1;
	display:grid;gap:var(--sp-4);
	align-items:center;
	opacity:0;visibility:hidden;transform:translateY(12px);
	transition:opacity .5s ease,transform .5s ease,visibility .5s;
}
.sevenality-wcar .wcar-slide.is-current{opacity:1;visibility:visible;transform:none}
@media(min-width:900px){
	.sevenality-wcar .wcar-slide{grid-template-columns:minmax(0,7fr) minmax(0,5fr)}
}

/* EDITORIAL: the tagline is the largest thing on the section */
.sevenality-wcar .wcar-slide__client{
	font-family:var(--wp--preset--font-family--sans);font-weight:300;
	font-size:var(--t-meta);letter-spacing:.2em;text-transform:uppercase;
	color:var(--ink-on-dark-dim);margin:0 0 var(--sp-1);
}
.sevenality-wcar .wcar-slide__lede{
	font-family:var(--wp--preset--font-family--display);font-weight:400;
	font-size:var(--t-h3);
	line-height:1.12;letter-spacing:-.02em;color:var(--ink-on-dark);margin:0;text-wrap:balance;
}
.sevenality-wcar .wcar-slide__lines{
	font-family:var(--wp--preset--font-family--sans);font-weight:300;
	font-size:var(--t-meta);color:var(--ink-on-dark-dim);
	margin:var(--sp-1) 0 0;
}
.sevenality-wcar .wcar-slide__go{
	display:inline-flex;align-items:center;gap:var(--s-xs);min-height:44px;
	margin-block-start:var(--sp-3);
	font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta);
	letter-spacing:.14em;text-transform:uppercase;color:var(--ink-on-dark);text-decoration:none;
	border-block-end:1px solid var(--wcar-accent,#fff);padding-block-end:var(--s-2xs);
	transition:gap .25s ease;
}
.sevenality-wcar .wcar-slide__go:hover,.sevenality-wcar .wcar-slide__go:focus-visible{gap:var(--s-md)}

/* the image plays support, so it is capped rather than full-bleed */
.sevenality-wcar .wcar-slide__plate img{
	display:block;width:100%;height:auto;
	aspect-ratio:4/3;object-fit:cover;
}

@media(prefers-reduced-motion:reduce){
	.sevenality-wcar .wcar-slide,
	.sevenality-wcar .wcar-bg__layer,
	.sevenality-wcar .wcar-slide__go{transition:none}
	.sevenality-wcar .wcar-slide{transform:none}
}

/* The group uses a constrained layout, which emits a max-width rule for every
   direct child. That clamped the absolutely-positioned backdrop to contentSize
   (46rem = 736px), so the blurred image ran as a band down the middle with the
   darkening veil covering only that band — leaving white type on bright,
   unveiled photo either side. Both children opt out explicitly; .wcar-in then
   sets its own measure. */
.sevenality-wcar > .wcar-bg,
.sevenality-wcar > .wcar-in{max-width:none;width:100%;margin-inline:0}
.sevenality-wcar > .wcar-in{margin-inline:auto}

/* ============================================================
   ABOUT
   Sectioned like vividmotion.co/about. Partners and journal are
   Query Loops; see patterns/about.php.
   ============================================================ */
.sevenality-about{--sa-card:light-dark(#F2F0EC,rgba(255,255,255,.05))}
.sevenality-about > *{margin-block:0}
.sevenality-about .sa-micro{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.24em;text-transform:uppercase;color:var(--sev-accent,#306090);margin:0 0 var(--s-lg)}
.sevenality-about .sa-label{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h4);letter-spacing:-.02em;margin:0 0 var(--sp-3)}
.sevenality-about .sa-lede{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-h4);line-height:1.38;max-width:26ch;margin:0}

.sevenality-about .sa-hero{padding-block:var(--sp-7) var(--sp-5)}
.sevenality-about .sa-hero__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h1);line-height:1.02;letter-spacing:-.03em;margin:0;max-width:16ch}
.sevenality-about .sa-hero__s{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-h4);max-width:46ch;margin:var(--sp-3) 0 0}

.sevenality-about .sa-two,
.sevenality-about .sa-vals,
.sevenality-about .sa-partners,
.sevenality-about .sa-journal,
.sevenality-about .sa-close{padding-block:var(--sp-6)}
.sevenality-about .sa-go{color:var(--sev-accent,#306090);text-decoration:none;border-bottom:1px solid currentColor;padding-bottom:.1em;white-space:nowrap}

/* values — the tall card with a deliberate gap is Vivid's device */
.sevenality-about .sa-vals__grid{display:grid;gap:var(--sp-1)}
@media(min-width:720px){.sevenality-about .sa-vals__grid{grid-template-columns:repeat(3,1fr)}}
.sevenality-about .sa-val{background:var(--sa-card);padding:var(--sp-2);display:flex;flex-direction:column;min-height:clamp(15rem,26vw,20rem);transition:background .3s ease}
.sevenality-about .sa-val__n{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-body);margin:0}
.sevenality-about .sa-val__b{font-size:var(--t-small);line-height:1.6;margin:auto 0 0}

/* partners — post-template grid; the role is bound meta, not typed markup */
.sevenality-about .sa-partners__list{gap:clamp(2rem,4vw,3.5rem)!important}
.sevenality-about .sa-partner__ph img{aspect-ratio:4/5;object-fit:cover;width:100%}
.sevenality-about .sa-partner__n{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h4);letter-spacing:-.02em;margin:var(--s-lg) 0 0}
.sevenality-about .sa-partner__r{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-micro);letter-spacing:.18em;text-transform:uppercase;color:var(--sev-accent,#306090);margin:var(--s-2xs) 0 var(--s-md)}
.sevenality-about .sa-partner__b{margin:0;max-width:42ch}

/* journal — rows, no dates (every post is from 2016) */
.sevenality-about .sa-journal__list{display:grid;gap:0}
.sevenality-about .sa-journal__list > li{display:grid;grid-template-columns:auto 1fr;gap:var(--s-lg);align-items:center;padding-block:var(--s-md);border-block-start:1px solid var(--sev-rule,rgba(128,128,128,.28));list-style:none}
.sevenality-about .sa-journal__list > li:last-child{border-block-end:1px solid var(--sev-rule,rgba(128,128,128,.28))}
.sevenality-about .sa-jrow__th img{width:56px;height:56px;object-fit:cover}
.sevenality-about .sa-jrow__t{font-family:var(--wp--preset--font-family--sans);font-weight:300;font-size:var(--t-lead);margin:0}
.sevenality-about .sa-jrow__t a{text-decoration:none}
.sevenality-about .sa-journal__list:hover > li{opacity:.4;transition:opacity .25s ease}
.sevenality-about .sa-journal__list > li:hover{opacity:1}

.sevenality-about .sa-close__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h2);line-height:1.05;letter-spacing:-.03em;margin:0;max-width:18ch}
.sevenality-about .sa-btn{display:inline-flex;align-items:center;gap:var(--s-xs);min-height:44px;margin-top:var(--sp-3);padding:var(--s-md) var(--s-xl);background:#14141a;color:var(--ink-on-dark);text-decoration:none;font-size:var(--t-meta);letter-spacing:.14em;text-transform:uppercase}

/* ---- method brief (homepage; the pinned version lives on About) ---- */
.sevenality-brief{padding-block:var(--sp-6);background:#0c3d5d;color:var(--ink-on-dark)}
.sevenality-brief .sb-micro{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.24em;text-transform:uppercase;color:var(--sev-blue-light);margin:0 0 var(--s-md)}
.sevenality-brief .sb-title{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h3);line-height:1.05;letter-spacing:-.02em;color:var(--ink-on-dark);margin:0 0 var(--sp-3)}
.sevenality-brief .sb-grid{display:grid;gap:var(--sp-3)}
@media(min-width:760px){.sevenality-brief .sb-grid{grid-template-columns:repeat(5,1fr)}}
.sevenality-brief .sb-move{border-block-start:1px solid rgba(255,255,255,.22);padding-block-start:var(--s-md)}
.sevenality-brief .sb-move__k{font-family:var(--wp--preset--font-family--display);font-size:var(--t-h3);line-height:1;color:var(--sev-blue-light);margin:0}
.sevenality-brief .sb-move__n{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-lead);color:var(--ink-on-dark);margin:var(--s-xs) 0 var(--s-2xs);letter-spacing:-.01em}
.sevenality-brief .sb-move__d{font-family:var(--wp--preset--font-family--sans);font-weight:300;font-size:var(--t-small);line-height:1.55;color:var(--ink-on-dark-dim);margin:0}
.sevenality-brief .sb-more{margin:var(--sp-3) 0 0}
.sevenality-brief .sb-more a{color:var(--ink-on-dark);text-decoration:none;border-bottom:1px solid rgba(255,255,255,.45);padding-bottom:var(--s-3xs);font-family:var(--wp--preset--font-family--sans);font-size:var(--t-small)}
.sevenality-brief .sb-more a:hover{border-color:var(--ink-on-dark)}

/* The About wrapper uses a constrained layout, which caps every direct child
   at contentSize (46rem = 736px). That squeezed three values cards into ~180px
   each and wrapped their text to one or two words a line. These sections want
   the wide measure; WP's own rule is :where()-wrapped, so a class selector
   wins without !important. */
.sevenality-about > .sa-hero,
.sevenality-about > .sa-two,
.sevenality-about > .sa-vals,
.sevenality-about > .sa-partners,
.sevenality-about > .sa-journal,
.sevenality-about > .sa-close{
	max-width:var(--wp--style--global--wide-size,86.25rem);
	width:100%;
	margin-inline:auto;
}

/* ============================================================
   PHILANTHROPY
   The 1,600 grid IS the page. It pins, it fills as you scroll,
   and it is the only dark band on a cream page.
   See patterns/philanthropy.php for why it was rebuilt.
   ============================================================ */
.sevenality-phil{--sp-rule:light-dark(#E4E2DE,rgba(255,255,255,.16));--sp-dim:light-dark(#8a8d90,rgba(255,255,255,.45));--sp-card:light-dark(#F1EEE9,rgba(255,255,255,.05))}

/* Section rhythm. Was 112px top AND bottom on every section — 1,344px of a
   4,811px page. Roughly halved, and the bands now use .sev-band for measure. */
.sevenality-phil > .sev-band{padding-block:var(--sp-5)}
.sevenality-phil > .sp-hero{padding-block:var(--sp-6) var(--sp-3)}
.sevenality-phil > .sp-close{padding-block:var(--sp-6)}

.sevenality-phil .sp-micro{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.24em;text-transform:uppercase;color:var(--sev-accent,#306090);margin:0 0 var(--s-lg)}
.sevenality-phil .sp-micro--light{color:var(--sev-blue-light)}
.sevenality-phil .sp-hero__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h1);line-height:1.02;letter-spacing:-.03em;margin:0;max-width:14ch}
.sevenality-phil .sp-hero__s{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-h4);line-height:1.5;max-width:52ch;margin:var(--sp-3) 0 0}
.sevenality-phil .sp-lede{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-h4);line-height:1.38;max-width:30ch;margin:0}
.sevenality-phil .sp-h2{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h3);line-height:1.08;letter-spacing:-.025em;margin:0;max-width:20ch}
.sevenality-phil .sp-note{max-width:58ch;margin:var(--s-lg) 0 0;color:var(--sp-dim)}

/* ------------------------------------------------------------
   THE FIGURE — full-bleed, pinned, filling
   ------------------------------------------------------------
   Full-bleed out of the constrained root: WordPress caps direct children at
   contentSize, so this needs both the width escape and the doubled-weight
   margin reset. Same mechanism documented in WIDTH INTENT at the top. */
.sevenality-phil .sp-count{
	position:relative;
	max-width:none;
	width:100vw;
	margin-inline:calc(50% - 50vw) !important;
	background:#0A1622;
	color:var(--ink-on-dark);
	/* The scroll track. The stage inside is sticky, which is the pin; this
	   height is how long the fill takes. */
	height:300vh;
	view-timeline-name:--sp-marks;
	view-timeline-axis:block;
}
.sevenality-phil .sp-count__stage{position:sticky;top:0;min-height:100svh;display:grid;align-content:center;padding-block:var(--sp-4)}
/* Matches the .sev-band measure rather than inventing its own gutter. With a
   4rem padding the number started at x=64 while every other section on the
   page started at x=30, which read as the dark band being indented. */
.sevenality-phil .sp-count__inner{
	width:min(100% - 2rem, var(--sev-w-wide,86.25rem));
	margin-inline:auto;
	display:grid;gap:var(--sp-5);align-items:center;
	grid-template-columns:minmax(0,1fr);
}
@media(min-width:900px){
	.sevenality-phil .sp-count__inner{grid-template-columns:minmax(0,.85fr) minmax(0,1fr)}
}
.sevenality-phil .sp-count__n{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-mega);line-height:.9;letter-spacing:-.04em;margin:0;color:var(--ink-on-dark)}
.sevenality-phil .sp-count__n sup{font-size:.42em;vertical-align:super;color:var(--sev-blue-light)}
.sevenality-phil .sp-count__l{font-family:var(--wp--preset--font-family--serif-text);font-weight:400;font-size:var(--t-lead);line-height:1.5;margin:var(--sp-2) 0 0;max-width:40ch;color:var(--ink-on-dark-soft)}
.sevenality-phil .sp-count__cap{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-micro);letter-spacing:.16em;text-transform:uppercase;color:var(--ink-on-dark-faint);margin:var(--sp-2) 0 0}
.sevenality-phil .sp-count__grid{display:grid;place-items:center}

/* 40 columns x 40 rows = exactly 1,600. ONE element, tiled radial-gradient —
   not 1,600 DOM nodes. Change --cols and the claim breaks. */
.sevenality-phil .sp-marks{
	--cols:40;
	/* Sized off viewport HEIGHT because the stage is pinned: the grid has to
	   fit the screen it is held on, not the column it sits in. 34rem left it
	   reading as a swatch on a 1440 viewport, which is what the old version
	   got wrong. */
	width:min(100%,min(74vh,42rem));
	aspect-ratio:1/1;
	color:var(--sev-blue-light);
	background-image:radial-gradient(circle at 50% 50%, currentColor 22%, transparent 23%);
	background-size:calc(100% / var(--cols)) calc(100% / var(--cols));
}

/* THE HEART, DRAWN FROM THE SAME DOTS
   A second layer carrying the identical dot pattern in white, masked to a
   heart, sitting exactly on top of the field so the marks register and
   nothing shifts.

   WHY THE MASK IS BLOCKY RATHER THAN A CURVE
   Masking a dot pattern with a smooth heart path slices the dots at the
   boundary into crescent slivers, which reads as a rendering fault. This mask
   is built from WHOLE CELLS on the same 40 x 40 grid — 28 merged rects in a
   0 0 40 40 viewBox at mask-size 100% 100%, so every rect lands exactly on one
   dot cell. 512 of the 1,600 marks fall inside it.

   It needs no reveal logic of its own: the pseudo-element is content of
   .sp-marks, so the parent's scroll sweep clips it too and the heart emerges
   row by row with the field. */
.sevenality-phil .sp-marks{position:relative}
.sevenality-phil .sp-marks::after{
	content:'';
	position:absolute;
	inset:0;
	background-image:radial-gradient(circle at 50% 50%, #fff 22%, transparent 23%);
	background-size:calc(100% / var(--cols)) calc(100% / var(--cols));
	-webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Crect x='12' y='7' width='3' height='1'/%3E%3Crect x='25' y='7' width='3' height='1'/%3E%3Crect x='10' y='8' width='8' height='1'/%3E%3Crect x='22' y='8' width='8' height='1'/%3E%3Crect x='9' y='9' width='22' height='1'/%3E%3Crect x='8' y='10' width='24' height='1'/%3E%3Crect x='7' y='11' width='26' height='1'/%3E%3Crect x='7' y='12' width='26' height='1'/%3E%3Crect x='7' y='13' width='26' height='1'/%3E%3Crect x='7' y='14' width='26' height='1'/%3E%3Crect x='7' y='15' width='26' height='1'/%3E%3Crect x='7' y='16' width='26' height='1'/%3E%3Crect x='7' y='17' width='26' height='1'/%3E%3Crect x='7' y='18' width='26' height='1'/%3E%3Crect x='7' y='19' width='26' height='1'/%3E%3Crect x='8' y='20' width='24' height='1'/%3E%3Crect x='8' y='21' width='24' height='1'/%3E%3Crect x='8' y='22' width='24' height='1'/%3E%3Crect x='9' y='23' width='22' height='1'/%3E%3Crect x='10' y='24' width='20' height='1'/%3E%3Crect x='10' y='25' width='20' height='1'/%3E%3Crect x='11' y='26' width='18' height='1'/%3E%3Crect x='12' y='27' width='16' height='1'/%3E%3Crect x='13' y='28' width='14' height='1'/%3E%3Crect x='14' y='29' width='12' height='1'/%3E%3Crect x='16' y='30' width='8' height='1'/%3E%3Crect x='17' y='31' width='6' height='1'/%3E%3Crect x='19' y='32' width='2' height='1'/%3E%3C/svg%3E");
	mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40'%3E%3Crect x='12' y='7' width='3' height='1'/%3E%3Crect x='25' y='7' width='3' height='1'/%3E%3Crect x='10' y='8' width='8' height='1'/%3E%3Crect x='22' y='8' width='8' height='1'/%3E%3Crect x='9' y='9' width='22' height='1'/%3E%3Crect x='8' y='10' width='24' height='1'/%3E%3Crect x='7' y='11' width='26' height='1'/%3E%3Crect x='7' y='12' width='26' height='1'/%3E%3Crect x='7' y='13' width='26' height='1'/%3E%3Crect x='7' y='14' width='26' height='1'/%3E%3Crect x='7' y='15' width='26' height='1'/%3E%3Crect x='7' y='16' width='26' height='1'/%3E%3Crect x='7' y='17' width='26' height='1'/%3E%3Crect x='7' y='18' width='26' height='1'/%3E%3Crect x='7' y='19' width='26' height='1'/%3E%3Crect x='8' y='20' width='24' height='1'/%3E%3Crect x='8' y='21' width='24' height='1'/%3E%3Crect x='8' y='22' width='24' height='1'/%3E%3Crect x='9' y='23' width='22' height='1'/%3E%3Crect x='10' y='24' width='20' height='1'/%3E%3Crect x='10' y='25' width='20' height='1'/%3E%3Crect x='11' y='26' width='18' height='1'/%3E%3Crect x='12' y='27' width='16' height='1'/%3E%3Crect x='13' y='28' width='14' height='1'/%3E%3Crect x='14' y='29' width='12' height='1'/%3E%3Crect x='16' y='30' width='8' height='1'/%3E%3Crect x='17' y='31' width='6' height='1'/%3E%3Crect x='19' y='32' width='2' height='1'/%3E%3C/svg%3E");
	-webkit-mask-size:100% 100%;
	mask-size:100% 100%;
	-webkit-mask-repeat:no-repeat;
	mask-repeat:no-repeat;
	pointer-events:none;
}

/* Fully drawn is the DEFAULT. Browsers without scroll-driven animation, and
   anyone with reduced motion, get the complete grid rather than an empty box —
   the figure must never depend on the animation to exist. */
@property --p{syntax:'<percentage>';inherits:false;initial-value:100%}

@supports (animation-timeline: view()){
	@media(prefers-reduced-motion:no-preference){
		.sevenality-phil .sp-marks{
			mask-image:linear-gradient(to bottom,#000 0 var(--p),transparent var(--p));
			-webkit-mask-image:linear-gradient(to bottom,#000 0 var(--p),transparent var(--p));
			animation:sp-fill linear both;
			animation-timeline:--sp-marks;
			animation-range:contain 0% contain 92%;
		}
		@keyframes sp-fill{from{--p:0%}to{--p:100%}}
	}
}

/* ---- time / talent / treasure ---- */
.sevenality-phil .sp-ts{display:grid;gap:var(--sp-3);margin-block-start:var(--sp-3)}
@media(min-width:820px){.sevenality-phil .sp-ts{grid-template-columns:repeat(3,1fr)}}
.sevenality-phil .sp-t{display:flex;flex-direction:column}
.sevenality-phil .sp-t__media{display:block;aspect-ratio:4/3;overflow:hidden;background:var(--sp-card);margin-block-end:var(--s-lg)}
.sevenality-phil .sp-t__img{width:100%;height:100%;object-fit:cover;display:block}
.sevenality-phil .sp-t__k{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-micro);letter-spacing:.2em;text-transform:uppercase;color:var(--sev-accent,#306090);margin:0 0 var(--s-xs)}
.sevenality-phil .sp-t__n{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h4);line-height:1.15;letter-spacing:-.015em;margin:0 0 var(--s-xs)}
.sevenality-phil .sp-t__d{font-size:var(--t-small);line-height:1.6;margin:0;max-width:44ch;color:var(--sp-dim)}

/* ---- two hemispheres ---- */
.sevenality-phil .sp-hemis{display:grid;border-block-start:1px solid var(--sp-rule)}
@media(min-width:820px){.sevenality-phil .sp-hemis{grid-template-columns:1fr 1fr;gap:var(--sp-4)}}
.sevenality-phil .sp-hemi{padding-block:var(--sp-3);border-block-end:1px solid var(--sp-rule)}
@media(min-width:820px){.sevenality-phil .sp-hemi{border-block-end:0}}
.sevenality-phil .sp-hemi__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h4);line-height:1.1;letter-spacing:-.02em;margin:0 0 var(--s-sm)}
.sevenality-phil .sp-hemi__b{margin:0;max-width:52ch;color:var(--sp-dim)}

/* ---- organizations supported (partner CPT) ---- */
.sevenality-phil .sp-orgs{display:grid;grid-template-columns:repeat(auto-fill,minmax(12rem,1fr));gap:var(--sp-1);margin-block-start:var(--sp-3)}
.sevenality-phil .sp-gi{display:flex;flex-direction:column;gap:var(--s-xs);padding:var(--sp-1);background:var(--sp-card);color:inherit;transition:background .25s ease}
a.sp-gi:hover,a.sp-gi:focus-visible{background:light-dark(#EAE7E1,rgba(255,255,255,.09))}
/* WHY light-dark() AND A FIXED LOGO PLATE, NOT prefers-color-scheme
   The dark-mode toggle sets `color-scheme` on <html> (see the companion's
   dark-mode-toggle extension). It does NOT change the OS preference, so
   `@media (prefers-color-scheme: dark)` never fires for anyone who switches
   the site to dark while their machine is light — which is most people who use
   the toggle at all.

   Measured with OS light + toggle dark: body was rgb(23,19,11) while
   prefers-color-scheme still reported light, so the buttons stayed
   rgb(20,20,26) on a dark page and every logo kept mix-blend-mode:multiply,
   which erases a dark logo against a dark tile.

   `light-dark()` follows color-scheme, so it is correct for the buttons. Blend
   modes are not colours and cannot use it, so the logo plates are simply light
   in both modes — which is what a logo wall wants anyway, and removes the
   dependency on the mode entirely. */
.sevenality-phil .sp-gi__logo{display:grid;place-items:center;min-height:5rem;background:#F4F2EE;padding:var(--s-sm)}
.sevenality-phil .sp-gi__logo img{max-width:100%;height:auto;max-height:4.5rem;object-fit:contain;mix-blend-mode:multiply}
.sevenality-phil .sp-gi__n{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta);line-height:1.35}
.sevenality-phil .sp-gi__m{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-micro);letter-spacing:.1em;text-transform:uppercase;color:var(--sp-dim)}
/* text-decoration on an ancestor paints across descendants and cannot be
   cancelled by them, so it has to be killed on the anchor itself. */
.sevenality-phil a.sp-gi,
.sevenality-phil a.sp-gi *{text-decoration:none !important}

/* ---- writing ---- */
.sevenality-phil .sp-arts__list{display:grid;gap:0;list-style:none;margin:var(--sp-3) 0 0;padding:0}
@media(min-width:820px){.sevenality-phil .sp-arts__list{grid-template-columns:1fr 1fr;column-gap:var(--sp-4)}}
.sevenality-phil .sp-arts__list > li{padding-block:var(--sp-2);border-block-start:1px solid var(--sp-rule)}
.sevenality-phil .sp-art__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h4);line-height:1.15;letter-spacing:-.015em;margin:0}
.sevenality-phil .sp-art__t a{text-decoration:none;color:inherit}
.sevenality-phil .sp-art__t a:hover{color:var(--sev-accent,#306090)}
.sevenality-phil .sp-art__x{font-size:var(--t-small);line-height:1.6;color:var(--sp-dim);margin:var(--s-xs) 0 0;max-width:46ch}

.sevenality-phil .sp-close__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h2);line-height:1.05;letter-spacing:-.03em;margin:0;max-width:18ch}
.sevenality-phil .sp-btn{display:inline-flex;align-items:center;gap:var(--s-xs);min-height:44px;margin-top:var(--sp-3);padding:var(--s-md) var(--s-xl);background:light-dark(#14141a,#fff);color:light-dark(#fff,#14141a);text-decoration:none !important;font-size:var(--t-meta);letter-spacing:.14em;text-transform:uppercase}

/* Mobile: 300vh of pin is too much on a phone, and a 62vh grid crowds the
   type. Shorten the track and stack. */
@media(max-width:899px){
	.sevenality-phil .sp-count{height:220vh}
	/* 58vw put the grid at 226px on a 390 viewport — cells under 6px, and the
	   heart stopped being legible. The grid is the point of this section, so it
	   takes the whole column. */
	.sevenality-phil .sp-marks{width:min(100%,52vh)}
	.sevenality-phil .sp-count__inner{gap:var(--sp-3)}

	/* Grid above the words when stacked. Side by side there is no reading order
	   to get wrong; stacked there is, and the device should be seen before it
	   is explained rather than after.

	   Visual reorder only — the DOM keeps label, figure, caption, then grid, so
	   a screen reader still hears what the number IS before meeting the image
	   that draws it. Safe here because nothing in this section is focusable;
	   `order` across interactive content would decouple tab order from what is
	   on screen. */
	.sevenality-phil .sp-count__grid{order:-1}
}

/* Short phones. Putting the grid first is what exposed this: stacked on a
   360x640 screen the stage wanted 715px in a 640px viewport, so the bottom of
   the caption fell below the fold WHILE PINNED — the one place a reader cannot
   scroll to reach it.

   The grid yields, because it is the element that can lose size and still do
   its job; the claim and the caption cannot. Keyed to viewport HEIGHT rather
   than width, since height is the axis that actually ran out. */
@media(max-width:899px) and (max-height:780px){
	.sevenality-phil .sp-marks{width:min(100%,36vh)}
	.sevenality-phil .sp-count__n{font-size:var(--t-h3)}
	.sevenality-phil .sp-count__l{font-size:var(--t-body);margin-block-start:var(--s-sm)}
	.sevenality-phil .sp-count__cap{margin-block-start:var(--s-md)}
	.sevenality-phil .sp-count__stage{padding-block:var(--s-lg)}
}

/* About has the same constrained-layout misalignment Philanthropy had — its
   left edges measured 264, 352 and 30 on a single page. Same cause, same fix;
   see the note above for why !important is required here. */
.sevenality-about .sa-hero > *,
.sevenality-about .sa-partners > *,
.sevenality-about .sa-journal > *,
.sevenality-about .sa-close > *{margin-inline:0 !important}
.sevenality-about .sa-partners__q,
.sevenality-about .sa-journal__q,
.sevenality-about .sa-partners__list,
.sevenality-about .sa-journal__list{max-width:none;width:100%}

/* ============================================================
   PRESS — the record
   Talks lead because they have write-ups; the logos support.
   See patterns/press.php for why round that way.
   ============================================================ */
.sevenality-press{--spr-rule:light-dark(#E4E2DE,rgba(255,255,255,.16));--spr-dim:light-dark(#8a8d90,rgba(255,255,255,.45));--spr-card:light-dark(#F2F0EC,rgba(255,255,255,.05))}
.sevenality-press > .spr-hero,
.sevenality-press > .spr-talks-sec,
.sevenality-press > .spr-rec-sec,
.sevenality-press > .spr-close{max-width:var(--wp--style--global--wide-size,86.25rem);width:100%;margin-inline:auto;padding-block:var(--sp-6)}
/* Same constrained-layout override the other pages need; WordPress emits its
   centring margins with !important, so specificity alone cannot win. */
.sevenality-press .spr-hero > *,
.sevenality-press .spr-talks-sec > *,
.sevenality-press .spr-rec-sec > *,
.sevenality-press .spr-close > *{margin-inline:0 !important}
.sevenality-press .spr-talks,
.sevenality-press .spr-kind{max-width:none;width:100%}

.sevenality-press .spr-micro{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.24em;text-transform:uppercase;color:var(--sev-accent,#306090);margin:0 0 var(--s-lg)}
.sevenality-press .spr-lede{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-h4);line-height:1.38;max-width:28ch;margin:0}
.sevenality-press .spr-note{max-width:60ch;margin:0}
.sevenality-press .spr-hero{padding-block:var(--sp-7) var(--sp-4)}
.sevenality-press .spr-hero__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h1);line-height:1.02;letter-spacing:-.03em;margin:0;max-width:15ch}
.sevenality-press .spr-hero__s{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-h4);max-width:52ch;margin:var(--sp-3) 0 0}

/* the talks: a numbered record, not a card grid */
.sevenality-press .spr-talks{list-style:none;margin:var(--sp-4) 0 0;padding:0;counter-reset:none}
.sevenality-press .spr-talk{display:grid;grid-template-columns:auto 1fr;gap:var(--sp-3);padding-block:var(--sp-3);border-block-start:1px solid var(--spr-rule)}
.sevenality-press .spr-talk:last-child{border-block-end:1px solid var(--spr-rule)}
.sevenality-press .spr-talk__n{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-micro);letter-spacing:.18em;color:var(--spr-dim);padding-block-start:var(--s-xs)}
.sevenality-press .spr-talk__venue{display:block;font-family:var(--wp--preset--font-family--sans);font-size:var(--t-micro);letter-spacing:.18em;text-transform:uppercase;color:var(--sev-accent,#306090);margin-block-end:var(--s-xs)}
.sevenality-press .spr-talk__t{display:block;font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h4);line-height:1.12;letter-spacing:-.02em;text-decoration:none;max-width:24ch}
.sevenality-press .spr-talk__t:hover{color:var(--sev-accent,#306090)}
.sevenality-press .spr-talk__d{display:block;margin-block-start:var(--s-sm);max-width:62ch;color:var(--spr-dim)}
.sevenality-press .spr-talks:hover .spr-talk{opacity:.45;transition:opacity .25s ease}
.sevenality-press .spr-talk:hover{opacity:1}

/* recognition, grouped by kind */
.sevenality-press .spr-kind{margin-block-start:var(--sp-4)}
.sevenality-press .spr-kind__h{display:flex;align-items:baseline;gap:var(--s-sm);font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-meta);letter-spacing:.2em;text-transform:uppercase;color:var(--spr-dim);margin:0 0 var(--s-md);padding-block-end:var(--s-sm);border-block-end:1px solid var(--spr-rule)}
.sevenality-press .spr-kind__n{font-size:var(--t-micro);color:var(--sev-accent,#306090)}
.sevenality-press .spr-wall{display:grid;grid-template-columns:repeat(auto-fill,minmax(10rem,1fr));gap:var(--sp-1)}
.sevenality-press .spr-item{position:relative;display:grid;place-items:center;min-height:7rem;padding:var(--s-lg);background:#F4F2EE;text-decoration:none;color:inherit;transition:background .25s ease}
a.spr-item:hover,a.spr-item:focus-visible{background:light-dark(#EAE7E1,rgba(255,255,255,.09))}
.sevenality-press .spr-item img{max-width:100%;height:auto;max-height:4rem;object-fit:contain;mix-blend-mode:multiply}
.sevenality-press .spr-item__f{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-small);text-align:center}
/* Only one of the twelve has a URL, so the arrow marks the one that is
   actually clickable rather than implying they all are. */
.sevenality-press .spr-item__go{position:absolute;top:.6rem;right:.7rem;font-size:var(--t-meta);color:var(--sev-accent,#306090)}

.sevenality-press .spr-close__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h2);line-height:1.05;letter-spacing:-.03em;margin:0;max-width:18ch}
.sevenality-press .spr-btn{display:inline-flex;align-items:center;gap:var(--s-xs);min-height:44px;margin-top:var(--sp-3);padding:var(--s-md) var(--s-xl);background:#14141a;color:var(--ink-on-dark);text-decoration:none;font-size:var(--t-meta);letter-spacing:.14em;text-transform:uppercase}
@media(prefers-reduced-motion:reduce){.sevenality-press .spr-talks:hover .spr-talk{transition:none}}

/* The talk title is a link, so it inherits the theme's blue + underline. It is
   the largest type in the section and needs to read as a heading that happens
   to be clickable, not as body-copy link. Same !important reason as elsewhere. */
.sevenality-press .spr-talk__t{color:inherit;text-decoration:none !important}
.sevenality-press .spr-talk__t:hover,
.sevenality-press .spr-talk__t:focus-visible{color:var(--sev-accent,#306090)}

/* ============================================================
   SERVICES — three lines, each proven by its work
   The hub. Sections render through sevenality_render_service_line()
   so a line can be lifted into a child page unchanged; see
   lib/services-render.php for why that indirection exists.
   ============================================================ */
.sevenality-services{--ssv-rule:light-dark(#E4E2DE,rgba(255,255,255,.16));--ssv-dim:var(--sev-ink-dim);--ssv-card:light-dark(#F1EEE9,rgba(255,255,255,.05))}

/* Sections use .sev-band for their measure and left edge — see WIDTH INTENT
   at the top of this file. Only the block rhythm is set here. */
.sevenality-services > .sev-band{padding-block:var(--sp-6)}
.sevenality-services .ssv-hero{padding-block:var(--sp-7) var(--sp-4)}

.sevenality-services .ssv-micro{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.24em;text-transform:uppercase;color:var(--sev-accent,#306090);margin:0 0 var(--s-lg)}
.sevenality-services .ssv-hero__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h1);line-height:1.02;letter-spacing:-.03em;margin:0;max-width:15ch}
.sevenality-services .ssv-hero__s{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-h4);line-height:1.5;max-width:54ch;margin:var(--sp-3) 0 0}

/* ---- a line ---- */
.sevenality-services .ssv-line{border-block-start:1px solid var(--ssv-rule)}
.sevenality-services .wkc-rail{margin-block-start:var(--sp-3)}
.sevenality-services .ssv-line__head{max-width:none}
.sevenality-services .ssv-line__n{display:flex;align-items:baseline;gap:var(--s-xs);font-family:var(--wp--preset--font-family--sans);font-size:var(--t-micro);letter-spacing:.2em;text-transform:uppercase;margin:0 0 var(--s-lg)}
.sevenality-services .ssv-line__i{color:var(--sev-accent,#306090)}
.sevenality-services .ssv-line__of{color:var(--ssv-dim)}
.sevenality-services .ssv-line__lab{margin-inline-start:var(--s-sm);padding-inline-start:var(--s-md);border-inline-start:1px solid var(--ssv-rule)}
/* The claim leads, so it takes hero-adjacent scale rather than the 4.25rem the
   line NAME used to sit at. */
.sevenality-services .ssv-line__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h2);line-height:1.03;letter-spacing:-.03em;margin:0;max-width:18ch}
.sevenality-services .ssv-line__b{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-lead);line-height:1.5;max-width:52ch;margin:var(--sp-2) 0 0;color:var(--ssv-dim)}

/* Capabilities: a vertical list, names only. Two columns so a line with eleven
   of them does not become a scroll of its own. */
.sevenality-services .ssv-caps{list-style:none;margin:var(--sp-3) 0 0;padding:0;display:grid;gap:0 var(--sp-4);grid-template-columns:1fr;max-width:46rem}
@media(min-width:700px){.sevenality-services .ssv-caps{grid-template-columns:1fr 1fr}}
.sevenality-services .ssv-cap{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-small);padding-block:var(--s-xs);border-block-start:1px solid var(--ssv-rule)}

.sevenality-services .ssv-line__cta{margin:var(--sp-2) 0 0}
.sevenality-services .ssv-line__cta a{display:inline-flex;align-items:center;gap:var(--s-xs);min-height:44px;padding:var(--s-md) var(--s-xl);background:light-dark(#14141a,#fff);color:light-dark(#fff,#14141a);text-decoration:none !important;font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta);letter-spacing:.14em;text-transform:uppercase}
.sevenality-services .ssv-line__cta a:hover{background:var(--sev-accent,#306090);color:var(--ink-on-dark)}

.sevenality-services .ssv-line__more{margin:var(--sp-3) 0 0}
.sevenality-services .ssv-line__more a{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta);letter-spacing:.06em;color:inherit;text-decoration:none !important;border-bottom:1px solid var(--ssv-rule);padding-bottom:var(--s-3xs)}
.sevenality-services .ssv-line__more a:hover{border-color:var(--sev-accent,#306090);color:var(--sev-accent,#306090)}

/* ---- method hand-off ---- */
.sevenality-services .ssv-method{border-block-start:1px solid var(--ssv-rule)}
.sevenality-services .ssv-method__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h3);line-height:1.1;letter-spacing:-.025em;margin:0;max-width:22ch}
.sevenality-services .ssv-method__m{margin:var(--sp-2) 0 0}
.sevenality-services .ssv-method__m a{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta);letter-spacing:.14em;text-transform:uppercase;color:var(--sev-accent,#306090);text-decoration:none !important;border-bottom:1px solid currentColor;padding-bottom:var(--s-3xs)}

/* ---- client words ----
   Quote lengths run 37 to 401 characters. Columns rather than a grid so the
   short one is short instead of padding a cell sized for the long ones. */
.sevenality-services .ssv-said{border-block-start:1px solid var(--ssv-rule)}
.sevenality-services .ssv-quotes{columns:3;column-gap:var(--sp-2);margin-block-start:var(--sp-3)}
.sevenality-services .ssv-quote{break-inside:avoid;margin:0 0 var(--sp-2);padding:var(--sp-2);background:var(--ssv-card)}
.sevenality-services .ssv-quote__b{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-lead);line-height:1.5;margin:0;quotes:none}
.sevenality-services .ssv-quote__b::before{content:'\201C';color:var(--sev-accent,#306090)}
.sevenality-services .ssv-quote__b::after{content:'\201D';color:var(--sev-accent,#306090)}
.sevenality-services .ssv-quote__c{display:flex;flex-wrap:wrap;gap:var(--s-2xs);margin-block-start:var(--s-md);font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta)}
.sevenality-services .ssv-quote__n{font-weight:400}
.sevenality-services .ssv-quote__o{color:var(--ssv-dim)}
.sevenality-services .ssv-quote__o a{color:inherit;text-decoration:none !important;border-bottom:1px solid var(--ssv-rule)}
.sevenality-services .ssv-quote__o a:hover{color:var(--sev-accent,#306090)}
@media(max-width:1100px){.sevenality-services .ssv-quotes{columns:2}}
@media(max-width:720px){.sevenality-services .ssv-quotes{columns:1}}

/* ---- close ---- */
.sevenality-services .ssv-close{border-block-start:1px solid var(--ssv-rule)}
.sevenality-services .ssv-close__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h2);line-height:1.05;letter-spacing:-.03em;margin:0;max-width:20ch}
.sevenality-services .ssv-btn{display:inline-flex;align-items:center;gap:var(--s-xs);min-height:44px;margin-top:var(--sp-3);padding:var(--s-md) var(--s-xl);background:light-dark(#14141a,#fff);color:light-dark(#fff,#14141a);text-decoration:none !important;font-size:var(--t-meta);letter-spacing:.14em;text-transform:uppercase}
@media(max-width:640px){.sevenality-services .ssv-line__head{grid-template-columns:1fr}.sevenality-services .ssv-line__n{grid-row:auto;padding-block-start:0}}
@media(prefers-reduced-motion:reduce){.sevenality-services .ssv-proj__img img{transition:none}}

/* ============================================================
   CONTACT
   The form gets the band. Was 1024px centred with 208px of dead
   margin on a 1440 viewport; see patterns/contact.php.
   ============================================================ */
.sevenality-contact{--sct-rule:light-dark(#E4E2DE,rgba(255,255,255,.16));--sct-dim:light-dark(#8a8d90,rgba(255,255,255,.45));--sct-card:light-dark(#F1EEE9,rgba(255,255,255,.05))}
.sevenality-contact > .sev-band{padding-block:var(--sp-6)}
/* Horizontal inset for the two top-level contact sections.

   These are alignwide groups: theme.json caps them at 1380px, which produces
   margins on a desktop and NOTHING on a phone. Measured at 390px the headline
   and lead sat at left:0 / right:0, flush to both screen edges, while the
   teaser and the ideas index both inset their content by 24px.

   The clamp matches the pattern used elsewhere in this stylesheet, and its
   lower bound resolves to exactly the 24px those pages use (5vw is only
   19.5px at 390, so the 1.5rem floor wins). Everything else on the page nests
   inside these two, so they are the only places it is needed. */
.sevenality-contact .sct-hero,
.sevenality-contact .sct-body{padding-inline:clamp(1.5rem,5vw,5rem)}
.sevenality-contact .sct-hero{padding-block:var(--sp-7) var(--sp-3)}
.sevenality-contact .sct-micro{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.24em;text-transform:uppercase;color:var(--sev-accent,#306090);margin:0 0 var(--s-lg)}
.sevenality-contact .sct-hero__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h1);line-height:1.02;letter-spacing:-.03em;margin:0;max-width:15ch}
.sevenality-contact .sct-hero__s{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-h4);line-height:1.5;max-width:50ch;margin:var(--sp-3) 0 0}
.sevenality-contact .sct-body{padding-block-start:0;border-block-start:1px solid var(--sct-rule)}

/* The aside is a reading column; the form wants room for its fields. */
.sevenality-contact .sct-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.35fr);gap:var(--sp-5);align-items:start}
.sevenality-contact .sct-aside__h{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-meta);letter-spacing:.2em;text-transform:uppercase;color:var(--sct-dim);margin:0 0 var(--s-xl);padding-block-end:var(--s-sm);border-block-end:1px solid var(--sct-rule)}
.sevenality-contact .sct-facts{margin:0}
.sevenality-contact .sct-fact{padding-block:var(--s-md);border-block-end:1px solid var(--sct-rule)}
.sevenality-contact .sct-fact dt{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-micro);letter-spacing:.16em;text-transform:uppercase;color:var(--sev-accent,#306090);margin:0 0 var(--s-xs)}
.sevenality-contact .sct-fact dd{margin:0;font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-body);line-height:1.55;max-width:44ch}
.sevenality-contact .sct-fact a{color:inherit;text-decoration:none;border-bottom:1px solid var(--sev-accent,#306090)}
.sevenality-contact .sct-form{padding:var(--sp-3);background:var(--sct-card)}
/* Gravity Forms ships its own layout; only the type needs to join the site. */
.sevenality-contact .sct-form .gform_wrapper{max-width:none}
.sevenality-contact .sct-form input[type=text],
.sevenality-contact .sct-form input[type=email],
.sevenality-contact .sct-form input[type=tel],
.sevenality-contact .sct-form input[type=url],
.sevenality-contact .sct-form select,
.sevenality-contact .sct-form textarea{width:100%;font-family:var(--wp--preset--font-family--sans);font-size:var(--t-body);min-height:44px;padding:var(--s-sm) var(--s-md);border:1px solid var(--sct-rule);background-color:light-dark(#fff,rgba(0,0,0,.25));color:inherit}
.sevenality-contact .sct-form textarea{min-height:9rem}

/* ── Gravity Forms: two gaps the parent's field-type tiers leave open ──

   The parent styles GF in two deliberate tiers (src/css/integrations/
   gravity-forms.scss): float labels for free-text fields, standard uppercase
   labels for choice fields. Two things on this form fell outside it.

   1. The select chevron. The parent DOES ship one — an inline SVG on
      `.gform_wrapper select` with a 2.5rem right gutter. The rule above used
      the `background` SHORTHAND, which resets background-image to none, and it
      outranks the parent on specificity. Both selects therefore rendered as
      plain boxes — appearance:none, no arrow, nothing marking them as
      dropdowns. Longhand restores the parent's chevron; the padding restores
      the gutter it needs.

   2. The Name fieldset. Nothing in either theme styles `fieldset`, so it fell
      through to the UA default, `2px groove #efefef` — the only browser chrome
      on a designed page. Its padding also inset First/Last to 259px while
      every other field measured 294px. Only the fieldset's own chrome is
      reset here, and deliberately NOT its block margin: GF renders these
      fields AS the fieldset (`<fieldset class="gfield ...">`), so a blanket
      `margin:0` also wipes the parent's 28px field rhythm — which it did,
      on all three fieldset-wrapped fields, until this was narrowed to
      `margin-inline`. The `legend` is left alone too, because the parent
      sets complex-group labels to 1rem/500 on purpose (a third tier
      alongside float and standard).

   A third gap existed while Estimated Budget was a range slider: that field
   type came from a third-party add-on and was in no tier, so its label sat at
   a computed 18.06px beside neighbours at 14px/600. The field is a select now
   and the add-on is deactivated, so the rule that patched it is gone too. */
.sevenality-contact .sct-form select{padding-inline-end:2.5rem}
.sevenality-contact .sct-form fieldset{border:0;padding:0;margin-inline:0;min-inline-size:0}
.sevenality-contact .sct-form .gform_button{min-height:44px;padding:var(--s-md) var(--s-xl);background:light-dark(#14141a,#fff);color:light-dark(#fff,#14141a);border:0;font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta);letter-spacing:.14em;text-transform:uppercase;cursor:pointer}
@media(max-width:900px){.sevenality-contact .sct-grid{grid-template-columns:1fr}}

/* ============================================================
   IDEAS — the writing archive
   Fifteen posts as a dated record. Not sevenality/ideas-index,
   which is a three-row teaser; see patterns/ideas.php.
   ============================================================ */
.sevenality-ideas{--sid-rule:light-dark(#E4E2DE,rgba(255,255,255,.16));--sid-dim:light-dark(#8a8d90,rgba(255,255,255,.45));--sid-card:light-dark(#F1EEE9,rgba(255,255,255,.05))}
.sevenality-ideas > .sev-band{padding-block:var(--sp-6)}
.sevenality-ideas .sid-hero{padding-block:var(--sp-7) var(--sp-3)}
.sevenality-ideas .sid-micro{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.24em;text-transform:uppercase;color:var(--sev-accent,#306090);margin:0 0 var(--s-lg)}
.sevenality-ideas .sid-hero__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h1);line-height:1.02;letter-spacing:-.03em;margin:0;max-width:16ch}
.sevenality-ideas .sid-hero__s{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-h4);line-height:1.5;max-width:52ch;margin:var(--sp-3) 0 0}

/* Categories carry counts, so the empty ones are filtered upstream. */
.sevenality-ideas .sid-cats{list-style:none;display:flex;flex-wrap:wrap;gap:var(--s-xs);margin:var(--sp-3) 0 0;padding:0}
.sevenality-ideas .sid-cat a{display:inline-flex;align-items:baseline;gap:var(--s-xs);padding:var(--s-xs) var(--s-sm);background:var(--sid-card);font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta);color:inherit;text-decoration:none !important}
.sevenality-ideas .sid-cat a:hover{color:var(--sev-accent,#306090)}
.sevenality-ideas .sid-cat__c{font-size:var(--t-micro);color:var(--sev-accent,#306090)}

.sevenality-ideas .sid-list-sec{padding-block-start:0}
.sevenality-ideas .sid-list{list-style:none;margin:0;padding:0}
.sevenality-ideas .sid-item{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:var(--sp-3);align-items:start;padding-block:var(--sp-3);border-block-start:1px solid var(--sid-rule)}
.sevenality-ideas .sid-item:last-child{border-block-end:1px solid var(--sid-rule)}
.sevenality-ideas .sid-item__n{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-micro);letter-spacing:.18em;color:var(--sid-dim);padding-block-start:var(--s-xs)}
.sevenality-ideas .sid-item__k{display:block;font-family:var(--wp--preset--font-family--sans);font-size:var(--t-micro);letter-spacing:.18em;text-transform:uppercase;color:var(--sev-accent,#306090);margin-block-end:var(--s-xs)}
.sevenality-ideas .sid-item__t{display:block;font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h4);line-height:1.12;letter-spacing:-.02em;color:inherit;text-decoration:none !important;max-width:26ch}
.sevenality-ideas .sid-item__t:hover,
.sevenality-ideas .sid-item__t:focus-visible{color:var(--sev-accent,#306090)}
.sevenality-ideas .sid-item__d{display:block;margin-block-start:var(--s-sm);max-width:62ch;color:var(--sid-dim)}
.sevenality-ideas .sid-item__y{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta);color:var(--sid-dim);padding-block-start:var(--s-xs)}
.sevenality-ideas .sid-list:hover .sid-item{opacity:.45;transition:opacity .25s ease}
.sevenality-ideas .sid-item:hover{opacity:1}
@media(max-width:640px){.sevenality-ideas .sid-item{grid-template-columns:auto minmax(0,1fr)}.sevenality-ideas .sid-item__y{grid-column:2}}
@media(prefers-reduced-motion:reduce){.sevenality-ideas .sid-list:hover .sid-item{transition:none}}

/* ============================================================
   LEGAL — privacy policy, terms
   Deliberately NOT widened. See page-legal.php: this is the one
   page type where contentSize is the right answer, so the work
   here is typography and page furniture, not measure.
   ============================================================ */
.sevenality-legal{--sl-rule:light-dark(#E4E2DE,rgba(255,255,255,.16));--sl-dim:light-dark(#8a8d90,rgba(255,255,255,.45))}
.sevenality-legal .sl-hero{padding-block:var(--sp-6) var(--sp-3)}
.sevenality-legal .sl-body{padding-block:0 var(--sp-6)}
.sevenality-legal .sl-micro{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.24em;text-transform:uppercase;color:var(--sev-accent,#306090);margin:0 0 var(--s-lg)}
.sevenality-legal .sl-hero__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h2);line-height:1.04;letter-spacing:-.03em;margin:0;max-width:18ch}
.sevenality-legal .sl-updated{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta);letter-spacing:.08em;color:var(--sl-dim);margin:var(--sp-2) 0 0;padding-block-start:var(--s-lg);border-block-start:1px solid var(--sl-rule)}

/* The reading measure. 68ch rather than the 46rem token because this is set
   in the serif text face, which runs narrower per character than the sans the
   token was tuned against.

   The class is doubled to reach (0,3,0): this element also carries
   `entry-content`, and the parent's `.site-main.full-width .entry-content
   { max-width: none }` sits at (0,3,0) and would otherwise erase the measure.
   See page-legal.php for why the hook has to live on this element. */
.sevenality-legal .sl-prose.sl-prose{max-width:68ch}
.sevenality-legal .sl-prose h2{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h4);line-height:1.15;letter-spacing:-.02em;margin:var(--sp-4) 0 var(--s-sm);padding-block-start:var(--sp-2);border-block-start:1px solid var(--sl-rule)}
.sevenality-legal .sl-prose h2:first-child{margin-block-start:0;padding-block-start:0;border-block-start:0}
.sevenality-legal .sl-prose h3{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-meta);letter-spacing:.18em;text-transform:uppercase;color:var(--sev-accent,#306090);margin:var(--sp-3) 0 var(--s-xs)}
.sevenality-legal .sl-prose p{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-lead);line-height:1.65;margin:0 0 var(--s-md)}
.sevenality-legal .sl-prose ul,
.sevenality-legal .sl-prose ol{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-body);line-height:1.65;margin:0 0 var(--s-md);padding-inline-start:var(--s-xl)}
.sevenality-legal .sl-prose li{margin-block-end:var(--s-2xs)}
.sevenality-legal .sl-prose a{color:inherit;text-decoration:none;border-bottom:1px solid var(--sev-accent,#306090);word-break:break-word}
.sevenality-legal .sl-prose a:hover{color:var(--sev-accent,#306090)}

/* The prose column carries `entry-content`, so the parent's
   `.site-main.full-width .entry-content > *` rule re-caps every heading and
   paragraph inside it at 720px AND centres them. Inside an 828px column that
   offset each line ~54px to the right, so the body copy sat indented from the
   H1 above it. Children should fill the measure their column already sets. */
.sevenality-legal .sl-prose.sl-prose > *{max-width:none;margin-inline:0}

/* ============================================================
   NAV — submenus must open for the keyboard too
   ============================================================
   The parent reveals .sub-menu on :hover, and on .is-focused / .is-open which
   its JS applies. Nothing applies them on keyboard focus, and the closed state
   is `visibility:hidden` — which removes the submenu from the tab order
   entirely. Measured: tabbing the whole of Home never reached Philanthropy,
   Press & Speaking or Brand Development.

   That went from cosmetic to serious when the menu was restructured, because
   Philanthropy and Press & Speaking have no other route into the site.

   :focus-within on the parent <li> resolves it without touching the parent's
   JS. The chicken-and-egg looks worse than it is: the <li> contains BOTH the
   visible top-level link and the hidden submenu, so tabbing to the top-level
   link already puts focus within the <li>, the submenu becomes visible, and
   the next Tab reaches its links. */
.main-navigation .menu-item-has-children:focus-within > .sub-menu{
	opacity:1;
	transform:translateY(0);
	visibility:visible;
}

/* ============================================================
   ONE LOOK
   ============================================================
   The scheme toggle is gone (companion extension `dark-mode-toggle`, disabled
   in settings so it can be switched back on from the admin without a deploy).
   A branding studio offering to render itself two ways quietly says it was not
   sure which one it is, and the art direction here already commits.

   Pinning `color-scheme: light` is what makes that real rather than
   accidental. Every `light-dark()` in this stylesheet and in theme.json
   resolves against color-scheme, NOT against the OS preference — so without
   this line a visitor on a dark machine would still get the dark half of every
   token, with no control to escape it now that the toggle is gone. That is the
   worst of both: an unmaintained second skin nobody asked for and nobody can
   turn off.

   THE DARK SECTIONS ARE NOT AFFECTED, and must not be. Case studies
   (.sevenality-cs.is-dark), the Philanthropy figure (.sp-count), the quote
   band and the footer are art direction with explicit hex values, not theme
   tokens. They stay dark in the one look, which is the point of them.

   The dark token halves are deliberately LEFT IN PLACE rather than stripped:
   unused, harmless, and it keeps the decision reversible.

   WHY `html:root` AND NOT `:root`
   The parent ships build/dark-mode-styles.css, which OPENS with
   `:root{color-scheme:dark; --atm-surface:...}` and is enqueued AFTER this
   stylesheet. Two :root rules at (0,1,0) — theirs wins on load order, and the
   site went dark the moment the toggle was removed. Disabling the toggle is
   what exposed it: ITS JS WAS THE ONLY THING KEEPING THIS SITE LIGHT, by
   writing an inline color-scheme onto <html> on every load.

   That file cannot simply be dequeued. Past its first declaration it defines
   the entire --atm-* token system the parent depends on — surfaces, borders,
   outlines, shadows, scrims. Exactly one property in it is wrong for us.

   `html:root` is (0,1,1) against their (0,1,0), so it wins on specificity
   rather than on load order or !important, and overrides that single
   declaration while leaving every token intact. */
html:root {
	color-scheme: light;

	/* ── THE GROUND, IN BOTH HALVES ──────────────────────────────────────
	   design-pass run 2: three different near-blacks were reachable at once
	   — body #17130b (the parent's warm ground, above), bands #0d0d0d (ours),
	   nav dropdown #000 (--atm-surface-container-lowest). Sevenality declares
	   ONE canvas, --sev-canvas, and these two parent tokens were the only
	   places the page painted anything else.

	   Pointing them at --sev-canvas fixes it by construction rather than by
	   copying a hex twice: change the canvas and the body follows.

	   These live in THIS rule, not the :root block up top, for the reason
	   documented above — build/dark-mode-styles.css declares both at :root
	   and is enqueued after this file, so a plain :root here loses on load
	   order. html:root is (0,1,1) against their (0,1,0).

	   Mostly this is unreachable today: color-scheme is forced light, so the
	   dark halves cannot be selected. It is fixed anyway because the dark
	   values were deliberately kept to hold the decision reversible, and a
	   reversible decision that reverts into three near-blacks is not one. The
	   dropdown is the exception — it was #fff in light and stays #fff here. */
	--atm-surface                   : var(--sev-canvas);
	--atm-surface-container-lowest  : light-dark(#fff, #0d0d0d);
}

/* ============================================================
   WORK CARD RAIL
   Several projects legible at once, the shape ideo.com uses on
   its homepage. See patterns/work-cards.php for the numbers that
   made the old carousel wrong.
   ============================================================ */
.sevenality-wcards{--wkc-rule:light-dark(#E4E2DE,rgba(255,255,255,.16));--wkc-dim:var(--sev-ink-dim);--wkc-card:light-dark(#F1EEE9,rgba(255,255,255,.05));padding-block:var(--wp--preset--spacing--band)}
.sevenality-wcards .wkc-head__row{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s-xl);padding-block-end:var(--s-md);border-block-end:1px solid var(--wkc-rule);margin-block-end:var(--sp-3)}
.sevenality-wcards .wkc-micro{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.24em;text-transform:uppercase;color:var(--sev-accent,#306090);margin:0}
.sevenality-wcards .wkc-h{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h2);line-height:1.04;letter-spacing:-.03em;margin:0;max-width:16ch}
.sevenality-wcards .wkc-all{white-space:nowrap;font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta);letter-spacing:.06em;color:inherit;text-decoration:none !important;border-bottom:1px solid var(--wkc-rule);padding-bottom:var(--s-3xs)}
.sevenality-wcards .wkc-all:hover{border-color:var(--sev-accent,#306090);color:var(--sev-accent,#306090)}

/* THE RAIL IS A SHARED COMPONENT, SO ITS RULES ARE NOT PAGE-SCOPED.
   They were written as `.sevenality-wcards .wkc-*` when the rail existed only
   on the homepage. Reusing the renderer on Services put the same markup under
   `.sevenality-services`, where none of it matched: the rail computed
   grid-auto-flow:row and the cards stacked vertically at 727px each, turning
   one act into 3,172px and the page into 14,153px. Component styles belong to
   the component. The class is doubled on the rail itself so its width escape
   still outranks the constrained-layout cap wherever it is dropped. */

/* The rail runs off the right edge — that overhang is what says "scroll".
   Full-bleed out of the constrained root, then padded back so the FIRST card
   lines up with every other section's left edge at x=30. */
.wkc-rail.wkc-rail{
	max-width:none;
	width:100vw;
	margin-inline:calc(50% - 50vw) !important;
	padding-inline:max(1rem,calc(50vw - var(--sev-w-wide,86.25rem) / 2));
	margin-block-start:var(--sp-3);
	display:grid;
	grid-auto-flow:column;
	/* Fixed width, NOT minmax(...,1fr): with 1fr a rail holding a single card
	   stretched it to the full 100vw bleed, and the 4/3 media made that a
	   1,080px-tall image — Strategy rendered one card and came out taller than
	   Branding's five. Cards are the same size wherever the rail appears. */
	grid-auto-columns:min(82vw,24rem);
	gap:var(--sp-2);
	overflow-x:auto;
	overscroll-behavior-x:contain;
	scroll-snap-type:x mandatory;
	scroll-padding-inline-start:max(1rem,calc(50vw - var(--sev-w-wide,86.25rem) / 2));
	list-style:none;
	/* Room for the focus ring, which would otherwise be clipped by overflow. */
	padding-block:4px;
	scrollbar-width:thin;
}
/* Lead modifier — the rail as a page's centrepiece rather than one act among
   several. Wider cards only where there is room for them; below 1200px the
   base `min(82vw,24rem)` already fills the viewport and widening would just
   show fewer projects. */
@media(min-width:1200px){
	.wkc-rail.wkc-rail--lead{grid-auto-columns:min(82vw,27rem)}
}

.wkc-cell{scroll-snap-align:start;min-width:0}
.wkc-card{display:flex;flex-direction:column;height:100%;color:inherit;text-decoration:none !important}
.wkc-card__media{display:block;aspect-ratio:4/3;overflow:hidden;background:var(--wkc-card);margin-block-end:var(--s-md)}
.wkc-card__img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .6s cubic-bezier(.2,.7,.2,1)}
.wkc-card:hover .wkc-card__img,
.wkc-card:focus-visible .wkc-card__img{transform:scale(1.04)}

/* FOCAL CROP — for projects whose only imagery is a screenshot of a webpage.
   See sevenality_project_hero_crop(). object-fit:cover already fills the box
   and cannot zoom, so the image scales inside the media box's overflow:hidden
   and anchors at a chosen point, showing a detail rather than a page.

   The hover MULTIPLIES the crop rather than replacing it — writing scale(1.04)
   here would snap a 2.2x crop back to almost nothing on hover. */
.wkc-card--crop .wkc-card__img{
	transform:scale(var(--wkc-zoom,1));
	transform-origin:var(--wkc-focal,50% 50%);
}
.wkc-card--crop:hover .wkc-card__img,
.wkc-card--crop:focus-visible .wkc-card__img{
	transform:scale(calc(var(--wkc-zoom,1) * 1.04));
}
.wkc-card__lines{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-micro);letter-spacing:.2em;text-transform:uppercase;color:var(--sev-ink-dim);margin-block-end:var(--s-xs)}
.wkc-card__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h4);line-height:1.1;letter-spacing:-.02em}
.wkc-card:hover .wkc-card__t{color:var(--wkc-accent,var(--sev-accent,#306090))}
.wkc-card__d{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-small);line-height:1.55;color:var(--wkc-dim);margin-block-start:var(--s-xs);max-width:34ch}
/* The client credit, now UNDER the problem rather than over it. Set small and
   in the sans, so the display face is spent on the argument and the name reads
   as attribution — which is what a firm's card does and an agency's does not. */
.wkc-card__client{font-family:var(--wp--preset--font-family--sans);font-weight:300;font-size:var(--t-meta);letter-spacing:.02em;line-height:1.4;color:var(--wkc-dim);margin-block-start:var(--s-xs)}
.wkc-card__go{margin-block-start:auto;padding-block-start:var(--s-md);font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta);letter-spacing:.14em;text-transform:uppercase;color:var(--sev-accent,#306090)}
@media(prefers-reduced-motion:reduce){.wkc-card__img{transition:none}.wkc-card:hover .wkc-card__img{transform:none}}

/* RAIL CONTROLS.
   They sit up on the masthead rule beside the section label, because that is
   where the eye already is when it decides whether the rail is worth
   engaging with — not underneath it, where you only find them after giving
   up. `pointer-events` is released only on the controls themselves so the
   negative margin cannot steal clicks from the heading it overlaps. */
.wkc-nav{display:flex;align-items:center;justify-content:flex-end;gap:var(--s-md);margin-block-start:-2.6rem;margin-block-end:var(--s-sm);pointer-events:none}
.wkc-nav[hidden]{display:none}
.wkc-nav > *{pointer-events:auto}
.wkc-nav__count{font-family:var(--wp--preset--font-family--sans);font-size:var(--t-micro);letter-spacing:.16em;color:var(--wkc-dim);margin:0;font-variant-numeric:tabular-nums}
.wkc-nav__sep{opacity:.5;margin-inline:var(--s-3xs)}
.wkc-nav__btns{display:flex;gap:var(--s-2xs)}
.wkc-nav__b{
	inline-size:2.25rem;block-size:2.25rem;
	display:grid;place-items:center;
	background:transparent;border:1px solid var(--wkc-rule);
	color:inherit;cursor:pointer;border-radius:50%;padding:0;
	transition:border-color .25s ease,color .25s ease,opacity .25s ease;
}
.wkc-nav__b svg{inline-size:1rem;block-size:1rem}
.wkc-nav__b:hover:not(:disabled){border-color:var(--sev-accent,#306090);color:var(--sev-accent,#306090)}
.wkc-nav__b:focus-visible{outline:2px solid var(--sev-accent,#306090);outline-offset:2px}
/* Dimmed, not hidden, at the ends: a control that vanishes shifts the one
   beside it, and the pair stops being a stable target to aim at. */
.wkc-nav__b:disabled{opacity:.3;cursor:default}
@media(max-width:600px){.wkc-nav{margin-block-start:var(--s-3xs);justify-content:space-between}}


/* ------------------------------------------------------------
   HOMEPAGE RHYTHM
   ------------------------------------------------------------
   Every section sat between 68% and 119% of viewport height, so the page read
   as seven blocks of equal importance with the work as just another one of
   them. These pull the supporting sections in so the work can have the room,
   WITHOUT making the page longer — ideo.com's homepage is ~4,500-5,000px
   against this one's 6,747px, so density was the problem, not length.

   Keyed to the block wrapper classes because the paddings are inline block
   attributes; the values here are overridden per-section in Home's content
   where the inline style has to win. */
.home .sevenality-band{padding-block:var(--sp-4)}
.home .sevenality-quoteband{padding-block:var(--sp-5)}

/* ============================================================
   TONE BAND — one anchor per page
   ============================================================
   Measured across the site, three pages had no tonal variation in the body at
   all: Ideas 89% cream, Services 88%, Press 83%, where the only dark was the
   footer. Home (49%), About (47%) and Philanthropy (52%) already had range, so
   this is not a palette problem — those three pages never got an anchor.

   #0c3d5d is the brand blue at full strength, already used for About's pinned
   FLAME covers. It was doing almost nothing elsewhere: the accent #306090
   appeared only as 10px micro labels and link hovers, which makes blue read as
   a highlight rather than as the brand's colour.

   ONE BAND PER PAGE, NOT ALTERNATING STRIPES. Alternating would remove the
   ability to make any single section the peak, which is exactly what the
   Philanthropy figure does well.

   HOW IT RE-SKINS ITS CONTENTS
   Rather than writing light variants for every component that might sit
   inside, the band overrides the CUSTOM PROPERTIES those components already
   read — --ssv-*, --wkc-*, --spr-* and --sev-accent. Anything built on those
   tokens adapts on its own, and anything added later inherits the behaviour
   for free. */
.sev-band.sev-tone,
.sev-tone {
	--ssv-rule: rgba(255,255,255,.24);
	--ssv-dim: rgba(255,255,255,.66);
	--ssv-card: rgba(255,255,255,.08);
	--wkc-rule: rgba(255,255,255,.24);
	--wkc-dim: rgba(255,255,255,.66);
	--wkc-card: rgba(255,255,255,.08);
	--spr-rule: rgba(255,255,255,.24);
	--spr-dim: rgba(255,255,255,.66);
	--spr-card: rgba(255,255,255,.08);
	--sp-rule: rgba(255,255,255,.24);
	--sp-dim: rgba(255,255,255,.66);
	/* The accent has to lift off the blue ground; #306090 on #0c3d5d is
	   nearly invisible. */
	--sev-accent: #80ABD7;
	background: #0c3d5d;
	color:var(--ink-on-dark);
}

/* Full-bleed out of the constrained root, then padded back so the content
   inside still starts at the same x as every other section. Doubled class so
   it outranks .sev-band.sev-band, which it has to replace rather than share. */
.sev-band.sev-tone {
	max-width: none;
	width: 100vw;
	margin-inline: calc(50% - 50vw) !important;
	padding-inline:max(1rem, calc(50vw - var(--sev-w-wide,86.25rem) / 2));
}

.sev-tone h1, .sev-tone h2, .sev-tone h3,
.sev-tone .ssv-line__t, .sev-tone .wkc-card__t, .sev-tone .spr-talk__t { color:var(--ink-on-dark) }
.sev-tone a { color: inherit }

/* The dark-ink CTA disappears on a dark ground; invert it. */
.sev-tone .ssv-line__cta a { background: #fff; color:var(--sev-blue-deep) }
.sev-tone .ssv-line__cta a:hover { background: #80ABD7; color:var(--sev-blue-deep) }

/* The rail bleeds edge-to-edge on cream. Inside a band that already supplies
   its own gutter it must not bleed again, or the cards start off-screen. */
.sev-tone .wkc-rail.wkc-rail {
	width: 100%;
	margin-inline: 0 !important;
	padding-inline:0;
	scroll-padding-inline-start:0;
}

/* Ideas: the "Musings" masthead is the only structural moment the parent's
   blog layout offers, so it carries this page's anchor. */
.blog .editorial-hero,
.editorial-blog .editorial-hero {
	background: #0c3d5d;
	color:var(--ink-on-dark);
	--sev-accent: #80ABD7;
}
.blog .editorial-hero *,
.editorial-blog .editorial-hero * { color:var(--ink-on-dark) }
.blog .editorial-hero__rule,
.editorial-blog .editorial-hero__rule { background: rgba(255,255,255,.4) }

/* TYPE ENTRIES — posts with no featured image
   Seven of the fifteen have none. Rather than filling the slot with a texture
   panel (a picture-shaped hole is still a hole), those entries drop the media
   block entirely and become typography: full width, larger, bracketed by
   rules. See template-parts/editorial-entry-card.php.

   Its own modifier, NOT the parent's `--fullbleed`: that branch sets --light
   modifiers and declares color:var(--ink-on-dark) with no dark ground anywhere, so
   inheriting it would mean inheriting white-on-cream. */
.editorial-entry--type{
	display:block;
	padding-block:var(--sp-3);
	border-block:1px solid light-dark(#E4E2DE,rgba(255,255,255,.16));
	/* Rules on consecutive entries would double up. */
	margin-block-start:-1px;
}
.editorial-entry--type .editorial-entry__body{max-width:none}
/* A clear second voice. The carded title is ALREADY 50px, which a first pass
   at this missed — clamping to 3.25rem landed on 52px and the two shapes were
   indistinguishable. ~71px at 1440 is roughly 1.4x, enough to read as a
   choice without outshouting the featured hero above it.

   22ch rather than 20: at this size the longest title here (66 characters)
   would otherwise run to four lines. */
.editorial-entry--type .editorial-entry__title{
	font-size:var(--t-h2);
	line-height:1.04;
	letter-spacing:-.03em;
	max-width:22ch;
	margin-block:var(--s-sm) 0;
}
.editorial-entry--type .editorial-entry__excerpt{
	max-width:58ch;
	margin-block-start:var(--s-md);
}
.editorial-entry--type .editorial-entry__footer{margin-block-start:var(--s-lg)}

/* ============================================================
   404 — the mark, one stroke short
   The only page whose whole canvas is one treatment. See 404.php
   for why the identity itself carries the argument.
   ============================================================ */
.sevenality-404{
	background:#0c3d5d;
	color:var(--ink-on-dark);
	--sev-accent:#80ABD7;
	--s404-rule:rgba(255,255,255,.24);
	--s404-dim:rgba(255,255,255,.66);
	padding-block:var(--sp-5) var(--sp-6);
	/* main carries a 2rem bottom margin from the parent, which let a 32px band
	   of cream body show between this blue canvas and the dark footer. On a
	   page whose whole point is one uninterrupted ground, that read as a seam. */
	margin-block-end:0;
	min-height:70svh;
	display:grid;
	align-content:center;
}
.sevenality-404 .s404{width:min(100% - 2rem,var(--sev-w-wide,86.25rem));margin-inline:auto}

/* The mark. Both strokes are 749.8 units long — identical by the 2-fold
   symmetry recorded in the SVG — so one dash length keeps them in step. */
.sevenality-404 .s404__mark{width:clamp(4.5rem,7vw,7rem);margin-block-end:var(--sp-3)}
.sevenality-404 .s404__mark svg{display:block;width:100%;height:auto;overflow:visible}
.sevenality-404 .s404__stroke{stroke:#fff}
.sevenality-404 .s404__stroke--b{stroke:#80ABD7}

@media(prefers-reduced-motion:no-preference){
	.sevenality-404 .s404__stroke{
		stroke-dasharray:750;
		/* Drawn state is the DEFAULT so the mark is whole if the animation
		   never runs; the keyframes start it hidden instead. */
		stroke-dashoffset:0;
	}
	.sevenality-404 .s404__stroke--a{animation:s404-draw 1s cubic-bezier(.65,0,.35,1) .15s both}
	/* The second stroke is the point: it arrives late, so the mark is briefly
	   incomplete in exactly the way the page is. */
	.sevenality-404 .s404__stroke--b{animation:s404-draw 1s cubic-bezier(.65,0,.35,1) 1.05s both}
	@keyframes s404-draw{from{stroke-dashoffset:750}to{stroke-dashoffset:0}}
}

.sevenality-404 .s404__micro{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.24em;text-transform:uppercase;color:var(--sev-blue-light);margin:0 0 var(--s-md)}
.sevenality-404 .s404__t{font-family:var(--wp--preset--font-family--display);font-weight:400;font-size:var(--t-h1);line-height:1.02;letter-spacing:-.03em;margin:0;max-width:16ch;color:var(--ink-on-dark)}
.sevenality-404 .s404__sub{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-lead);line-height:1.5;max-width:50ch;margin:var(--sp-2) 0 0;color:var(--s404-dim)}

/* The ways out. Three columns on desktop so none of them dominates — the
   concept leads, these support. */
.sevenality-404 .s404__ways{display:grid;gap:var(--sp-3);margin-block-start:var(--sp-4);padding-block-start:var(--sp-3);border-block-start:1px solid var(--s404-rule)}
@media(min-width:820px){.sevenality-404 .s404__ways{grid-template-columns:1.2fr 1fr 1.4fr}}
.sevenality-404 .s404__lab{font-family:var(--wp--preset--font-family--sans);font-weight:400;font-size:var(--t-micro);letter-spacing:.2em;text-transform:uppercase;color:var(--sev-blue-light);margin:0 0 var(--s-md)}
.sevenality-404 .s404__form{display:flex;gap:var(--s-xs)}
.sevenality-404 .s404__form input{flex:1 1 auto;min-width:0;min-height:44px;padding:var(--s-xs) var(--s-sm);font-family:var(--wp--preset--font-family--sans);font-size:var(--t-body);color:var(--ink-on-dark);background:rgba(255,255,255,.08);border:1px solid var(--s404-rule)}
.sevenality-404 .s404__form input::placeholder{color:var(--ink-on-dark-faint)}
.sevenality-404 .s404__form input:focus-visible{outline:2px solid #80ABD7;outline-offset:2px}
.sevenality-404 .s404__form button{min-height:44px;padding:var(--s-xs) var(--s-md);background:#fff;color:var(--sev-blue-deep);border:0;font-family:var(--wp--preset--font-family--sans);font-size:var(--t-meta);letter-spacing:.14em;text-transform:uppercase;cursor:pointer}
.sevenality-404 .s404__form button:hover{background:#80ABD7}
.sevenality-404 .s404__routes,
.sevenality-404 .s404__writing{list-style:none;margin:0;padding:0}
.sevenality-404 .s404__routes li,
.sevenality-404 .s404__writing li{border-block-start:1px solid var(--s404-rule)}
.sevenality-404 .s404__routes a,
.sevenality-404 .s404__writing a{display:block;padding-block:var(--s-sm);color:var(--ink-on-dark);text-decoration:none !important;font-family:var(--wp--preset--font-family--sans);font-size:var(--t-small)}
.sevenality-404 .s404__writing a{font-family:var(--wp--preset--font-family--serif-text);font-size:var(--t-body);line-height:1.35}
.sevenality-404 .s404__routes a:hover,
.sevenality-404 .s404__writing a:hover{color:var(--sev-blue-light)}

/* ─────────────────────────────────────────────────────────────
   PROGRAMS — the offer band on /services/

   Numbered rows rather than a card grid. Four cards side by side
   would give each program ~330px, which cannot hold a name, a
   situation line, a sentence and up to five case studies without
   the case studies becoming a cramped afterthought — and the
   case studies are the proof, i.e. the reason the band exists.

   A row per program spends horizontal space on the work instead:
   the number and name hold a narrow left column, the argument and
   its evidence run in the wider right one.
   ───────────────────────────────────────────────────────────── */
.ssv-programs { border-block-end: 1px solid var(--sev-rule); }
.ssv-programs__inner {
	width: min(100% - 3rem, 1240px);
	margin-inline:auto;
	padding-block:var(--sp-5);
}
.ssv-programs__t {
	font-size:var(--t-h3);
	line-height: 1.06; letter-spacing: -.02em;
	color: var(--sev-ink); margin:var(--s-3xs) 0 var(--s-sm);
}
.ssv-programs__s { color: var(--sev-ink-dim); max-width: 52ch; margin:0 0 var(--sp-4); }

.ssv-programs__list { list-style: none; margin:0; padding:0; }

/* ── Programs as disclosure ──────────────────────────────────
   The CONSTANT move: detail collapsed until asked for. They reach
   380 words per 1000px without feeling dense because nothing is
   shown that has not been requested.

   Collapsed shows number, program and the SITUATION line — the
   line that does the recruiting, so a reader recognises
   themselves without opening anything.
   ───────────────────────────────────────────────────────────── */
.ssv-program { border-block-start:1px solid var(--sev-rule); }

.ssv-program__sum {
	display:grid; align-items:baseline;
	grid-template-columns:3rem minmax(0,1fr) auto;
	gap:var(--s-3xs) var(--s-md);
	padding-block:clamp(1.25rem, 2.5vw, 2rem);
	cursor:pointer; list-style:none;
}
/* BOTH are needed: ::-webkit-details-marker for Safari, ::marker for
   everything else. Removing only one leaves a stray triangle in the
   browser you did not happen to test in. */
.ssv-program__sum::-webkit-details-marker { display:none; }
.ssv-program__sum::marker { content:''; }
.ssv-program__sum:focus-visible { outline:2px solid var(--sev-ink); outline-offset:4px; border-radius:2px; }

.ssv-program__n {
	font-variant-numeric:tabular-nums; font-size:var(--t-meta);
	letter-spacing:.14em; color:var(--sev-ink-dim);
}
.ssv-program__t {
	grid-column:2; font-size:var(--t-h3); line-height:1.08;
	letter-spacing:-.02em; color:var(--sev-ink);
}
.ssv-program__when {
	grid-column:2; font-size:var(--t-lead); color:var(--sev-ink-dim);
	margin-block-start:var(--s-3xs);
}

/* The marker ROTATES rather than swapping glyphs: no reflow between
   states, and no second character that would need translating. */
.ssv-program__mark {
	grid-column:3; grid-row:1 / span 2; align-self:center;
	inline-size:.7rem; block-size:.7rem;
	border-inline-end:1px solid currentColor; border-block-end:1px solid currentColor;
	transform:rotate(45deg); transform-origin:center; color:var(--sev-ink-dim);
	transition:transform var(--m-base) var(--m-ease), color var(--m-base) var(--m-ease);
}
.ssv-program__dis[open] .ssv-program__mark { transform:rotate(225deg); color:var(--sev-ink); }
.ssv-program__sum:hover .ssv-program__mark { color:var(--sev-ink); }

.ssv-program__panel { padding-block-end:clamp(1.5rem, 3vw, 2.5rem); padding-inline-start:3rem; }
@media (max-width:44rem){ .ssv-program__panel { padding-inline-start:0; } }
.ssv-program__desc { color:var(--sev-ink-dim); max-width:38rem; margin:0 0 var(--s-xl); }
/* The work list. Client and tagline are TWO columns, not one run-on line —
   dropping this rule during the disclosure rebuild produced
   "UnAltrd Its own homepage welcomed you to a different brand." as a single
   sentence, which reads as a typo rather than a layout. */
.ssv-program__work { list-style:none; margin:0; padding:0; display:grid; gap:var(--s-2xs); }
.ssv-program__work a {
	display:grid; grid-template-columns:minmax(0,14rem) minmax(0,1fr);
	gap:var(--s-3xs) var(--s-lg); text-decoration:none;
	padding-block:var(--s-2xs); border-block-start:1px solid var(--sev-rule);
}
@media (max-width:44rem){ .ssv-program__work a { grid-template-columns:1fr; } }
.ssv-program__client { color:var(--sev-ink); font-size:var(--t-small); }
.ssv-program__line { color:var(--sev-ink-dim); font-size:var(--t-small); }
.ssv-program__work a:hover .ssv-program__client { text-decoration:underline; }

/* The program name is an h3 for the outline; it must not inherit heading
   margins inside a summary grid. */
.ssv-program__t { margin:0; font-family:var(--wp--preset--font-family--display); font-weight:400; }

.ssv-program__more { margin:var(--s-xl) 0 0; }
.ssv-program__more a { color:var(--sev-ink); text-decoration:none; border-block-end:1px solid currentColor; padding-block-end:var(--s-3xs); }

/* Everything open in print. A collapsed panel that prints blank is a
   document with holes in it. */
@media print { .ssv-program__dis:not([open]) .ssv-program__panel { display:block; } }

.ssv-programs__all { margin:var(--sp-3) 0 0; }
.ssv-programs__all a { color: var(--sev-ink); text-decoration: none; border-block-end: 1px solid currentColor; padding-block-end:var(--s-3xs); }

/* Phones: the number moves inline above the name rather than
   holding a 4rem column that squeezes the case study list. */
@media (max-width: 700px) {
	.ssv-program { grid-template-columns: 1fr; gap:var(--s-xs); }
	.ssv-program__n { margin:0; }
	.ssv-program__work a { grid-template-columns: 1fr; }
}

/* Disciplines now sit UNDER Programs, so their heading is subordinate to the
   programs heading rather than its equal. It previously inherited a stray
   52px from the block defaults — a size used exactly once on the whole site. */
.ssv-disc-intro__t{ font-size:var(--t-h3); }

/* ─────────────────────────────────────────────────────────────
   PROGRAM SPOKE — /services/reposition/ and siblings

   Every value here comes from the two scales. This is the first
   component authored after them, and it is the test of whether
   they hold: if a new component needs a size or a gap that is not
   already a token, the scale was wrong.
   Nothing new was needed.
   ───────────────────────────────────────────────────────────── */
.sevenality-program{ overflow-x:clip; }
.pgm-wrap{ width:min(100% - var(--s-3xl), 76rem); margin-inline:auto; }
.pgm-micro{
	font-family:var(--wp--preset--font-family--sans);
	font-size:var(--t-micro); letter-spacing:.16em; text-transform:uppercase;
	color:var(--sev-ink-dim); margin:0 0 var(--s-sm);
}
.pgm-micro a{ color:inherit; text-decoration:none; border-block-end:1px solid currentColor; }

.pgm-hero{ padding-block:var(--sp-6) var(--sp-5); border-block-end:1px solid var(--sev-rule); }
.pgm-hero__t{
	font-size:var(--t-h1); line-height:1.02; letter-spacing:-.025em;
	color:var(--sev-ink); margin:0;
}
/* The situation line recruits — it is how a reader recognises themselves —
   so it carries more weight than the explanation beneath it. */
.pgm-hero__when{ font-size:var(--t-h4); color:var(--sev-ink); margin:var(--s-sm) 0 0; opacity:.82; }
.pgm-hero__d{ font-size:var(--t-lead); color:var(--sev-ink-dim); max-width:52ch; margin:var(--s-md) 0 0; }

/* Figures ABOVE the cases, per Bain. Tabular so the row reads as data. */
.pgm-figs{
	display:flex; flex-wrap:wrap; gap:var(--sp-3);
	margin:var(--sp-4) 0 0; padding-block-start:var(--s-xl);
	border-block-start:1px solid var(--sev-rule);
}
.pgm-fig__n{
	font-size:var(--t-h2); line-height:1; letter-spacing:-.02em;
	font-variant-numeric:tabular-nums; color:var(--sev-ink); margin:0;
}
.pgm-fig__l{ font-size:var(--t-meta); letter-spacing:.1em; text-transform:uppercase; color:var(--sev-ink-dim); margin:var(--s-3xs) 0 0; }

.pgm-sig{ padding-block:var(--sp-6); border-block-end:1px solid var(--sev-rule); }
.pgm-sig__grid{ display:grid; gap:var(--sp-4); align-items:start; }
@media (min-width:56rem){ .pgm-sig__grid{ grid-template-columns:minmax(0,1fr) minmax(0,1fr); } }
.pgm-sig__media img{ width:100%; height:auto; display:block; }
/* The accent is the client's own, taken from their artwork — the same colour
   the case study is art-directed in, so the two pages agree. */
.pgm-sig__media{ border-block-start:3px solid var(--pgm-accent, var(--sev-ink)); padding-block-start:var(--s-md); }
.pgm-sig__t{ font-size:var(--t-h3); line-height:1.06; letter-spacing:-.02em; margin:0; }
.pgm-sig__t a{ color:var(--sev-ink); text-decoration:none; }
.pgm-sig__t a:hover{ text-decoration:underline; }
.pgm-sig__line{ font-size:var(--t-lead); color:var(--sev-ink-dim); margin:var(--s-xs) 0 var(--s-xl); }
.pgm-sig__act{ margin-block-start:var(--s-xl); }
.pgm-sig__act-h{
	font-size:var(--t-micro); letter-spacing:.16em; text-transform:uppercase;
	color:var(--pgm-ink, var(--sev-ink)); margin:0 0 var(--s-xs);
}
.pgm-sig__act-b{ color:var(--sev-ink-dim); }
.pgm-sig__act-b p{ margin:0 0 var(--s-md); }
.pgm-sig__act-b p:last-child{ margin-block-end:0; }
.pgm-sig__act-b strong{ color:var(--sev-ink); }
.pgm-sig__more{ margin:var(--sp-3) 0 0; }
.pgm-sig__more a{ color:var(--sev-ink); text-decoration:none; border-block-end:1px solid currentColor; padding-block-end:.15rem; }

.pgm-rest{ padding-block:var(--sp-5); border-block-end:1px solid var(--sev-rule); }
.pgm-rest__list{ list-style:none; margin:0; padding:0; }
.pgm-rest__list a{
	display:grid; gap:var(--s-3xs) var(--sp-3); text-decoration:none;
	padding-block:var(--s-sm); border-block-start:1px solid var(--sev-rule);
}
@media (min-width:56rem){ .pgm-rest__list a{ grid-template-columns:minmax(0,16rem) minmax(0,1fr); } }
.pgm-rest__client{ color:var(--sev-ink); font-size:var(--t-lead); }
.pgm-rest__line{ color:var(--sev-ink-dim); font-size:var(--t-lead); }
.pgm-rest__list a:hover .pgm-rest__client{ text-decoration:underline; }

.pgm-caps{ padding-block:var(--sp-5); border-block-end:1px solid var(--sev-rule); }
.pgm-caps__list{ list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; gap:var(--s-xs); }
.pgm-cap{
	display:inline-flex; align-items:baseline; gap:var(--s-xs);
	border:1px solid var(--sev-rule); padding:var(--s-xs) var(--s-sm);
	font-size:var(--t-meta); letter-spacing:.1em; text-transform:uppercase;
	color:var(--sev-ink-dim);
}
.pgm-cap__c{ font-variant-numeric:tabular-nums; opacity:.6; }

.pgm-cta{ padding-block:var(--sp-6); }
.pgm-cta__t{ font-size:var(--t-h2); line-height:1.05; letter-spacing:-.02em; margin:0; color:var(--sev-ink); }
.pgm-cta__l{ margin:var(--s-xl) 0 0; font-size:var(--t-lead); }
.pgm-cta__l a{ color:var(--sev-ink); text-decoration:none; border-block-end:1px solid currentColor; padding-block-end:.15rem; }

.pgm-warn{
	margin:var(--sp-4) 0; padding:var(--s-md);
	border:1px solid var(--sev-rule); color:var(--sev-ink-dim); font-size:var(--t-small);
}

/* Disciplines strip on the hub — replaces three full sections. See the
   pattern for why they moved to the spokes rather than being deleted. */
.ssv-disc{ padding-block:var(--sp-5); border-block-end:1px solid var(--sev-rule); }
.ssv-disc__t{ font-size:var(--t-h3); line-height:1.08; letter-spacing:-.02em; margin:var(--s-3xs) 0 var(--s-xl); color:var(--sev-ink); }
.ssv-disc__list{ list-style:none; margin:0; padding:0; }
.ssv-disc__item{
	display:grid; gap:var(--s-3xs) var(--sp-3);
	padding-block:var(--s-md); border-block-start:1px solid var(--sev-rule);
}
@media (min-width:56rem){ .ssv-disc__item{ grid-template-columns:minmax(0,14rem) minmax(0,1fr); } }
.ssv-disc__name{ color:var(--sev-ink); font-size:var(--t-lead); }
.ssv-disc__caps{ color:var(--sev-ink-dim); font-size:var(--t-small); }
.ssv-disc__all{ margin:var(--sp-3) 0 0; }
.ssv-disc__all a{ color:var(--sev-ink); text-decoration:none; border-block-end:1px solid currentColor; padding-block-end:.15rem; }

/* Case study figures — in the hero, over the scrim. Tabular so the row reads
   as data rather than as three more headlines. */
.cs-figs{
	display:flex; flex-wrap:wrap; gap:var(--sp-3);
	margin:var(--sp-3) 0 0; padding-block-start:var(--s-md);
	border-block-start:1px solid rgba(255,255,255,.22);
}
.cs-fig__n{
	font-size:var(--t-h3); line-height:1; letter-spacing:-.02em;
	font-variant-numeric:tabular-nums; color:var(--ink-on-dark); margin:0;
}
.cs-fig__l{
	font-size:var(--t-meta); letter-spacing:.12em; text-transform:uppercase;
	color:var(--ink-on-dark-soft); margin:var(--s-3xs) 0 0;
}

/* ── DISCIPLINES INDEX ─────────────────────────────────────── */
.dsc-wrap{ width:min(100% - var(--s-3xl), 76rem); margin-inline:auto; }
.dsc-micro{
	font-family:var(--wp--preset--font-family--sans);
	font-size:var(--t-micro); letter-spacing:.16em; text-transform:uppercase;
	color:var(--sev-ink-dim); margin:0 0 var(--s-sm);
}
.dsc-micro a{ color:inherit; text-decoration:none; border-block-end:1px solid currentColor; }
.dsc-hero{ padding-block:var(--sp-6) var(--sp-5); border-block-end:1px solid var(--sev-rule); }
.dsc-hero__t{ font-size:var(--t-h1); line-height:1.02; letter-spacing:-.025em; color:var(--sev-ink); margin:0; }
.dsc-hero__d{ font-size:var(--t-lead); color:var(--sev-ink-dim); max-width:54ch; margin:var(--s-md) 0 0; }

.dsc-line{ padding-block:var(--sp-4); border-block-end:1px solid var(--sev-rule); }
.dsc-line__head{ display:flex; flex-wrap:wrap; align-items:baseline; gap:var(--s-md); margin-block-end:var(--s-xl); }
.dsc-line__t{ font-size:var(--t-h3); line-height:1.1; letter-spacing:-.02em; color:var(--sev-ink); margin:0; }
.dsc-line__n{ font-size:var(--t-meta); letter-spacing:.1em; text-transform:uppercase; color:var(--sev-ink-dim); margin:0; }

.dsc-caps{ list-style:none; margin:0; padding:0; display:grid; gap:var(--s-xs); }
@media (min-width:44rem){ .dsc-caps{ grid-template-columns:repeat(auto-fill,minmax(15rem,1fr)); } }
.dsc-cap a{
	display:flex; align-items:baseline; justify-content:space-between; gap:var(--s-sm);
	text-decoration:none; padding:var(--s-sm) var(--s-md);
	border:1px solid var(--sev-rule); color:var(--sev-ink);
	font-size:var(--t-small);
}
.dsc-cap a:hover{ border-color:var(--sev-ink); }
.dsc-cap__c{ font-variant-numeric:tabular-nums; color:var(--sev-ink-dim); font-size:var(--t-meta); }

.dsc-copy{ padding-block:var(--sp-5); border-block-end:1px solid var(--sev-rule); color:var(--sev-ink-dim); }
.dsc-copy h2{ color:var(--sev-ink); font-size:var(--t-h3); line-height:1.1; }
.dsc-cta{ padding-block:var(--sp-6); }
.dsc-cta__t{ font-size:var(--t-h2); line-height:1.05; letter-spacing:-.02em; margin:0; color:var(--sev-ink); max-width:22ch; }
.dsc-cta__l{ margin:var(--s-xl) 0 0; font-size:var(--t-lead); }
.dsc-cta__l a{ color:var(--sev-ink); text-decoration:none; border-block-end:1px solid currentColor; padding-block-end:.15rem; }

/* The one line carried over from the page this replaced. */
.dsc-line-quote{ padding-block:var(--sp-5); border-block-end:1px solid var(--sev-rule); }
.dsc-quote{ margin:0; }
.dsc-quote p{
	font-size:var(--t-h3); line-height:1.12; letter-spacing:-.02em;
	color:var(--sev-ink); margin:0; max-width:20ch;
}

/* ─────────────────────────────────────────────────────────────
   MOTION TOKENS

   The arrival GRAMMAR that used to live here has moved to the
   animations plugin — `lvbl-animated lvbl-anim-fadeInUp|fadeIn
   lvbl-anim-ease-cinematic lvbl-anim-scroll-linked`.

   It was a reimplementation of a feature the plugin already had.
   The plugin checks CSS.supports('animation-timeline','view()'),
   takes the CSS scroll-driven path when it is available — the
   same mechanism this hand-rolled — and falls back to anime.js
   when it is not. So the hand-rolled version was identical on
   Chrome and simply dead in Firefox, which has no scroll-driven
   animation support at all.

   Per surface: fadeInUp for singular moments (hero titles,
   figure rows, CTAs), plain fadeIn for repeated items (the
   16-tile work grid, list rows). Movement on sixteen tiles at
   once is where arrival tips into busy.

   The tokens stay: they are still the vocabulary for any
   transition authored in this theme.

   ONE DELIBERATE EXCEPTION. The footer signature keeps its own
   CSS view-timeline. It is a mask sweep across text rather than
   a transform or a fade, and no plugin effect covers that.
   ───────────────────────────────────────────────────────────── */
:root{
	--m-quick : 220ms;
	--m-base  : 420ms;
	--m-slow  : 700ms;
	--m-ease  : cubic-bezier(.22,.61,.36,1);
	--m-soft  : cubic-bezier(.33,1,.68,1);
	--m-lift  : 14px;
}

/* ─────────────────────────────────────────────────────────────
   ONE TYPEFACE, ACTUALLY

   The site declares `prenton` with `Hanken Grotesk` as fallback.
   Measured on the homepage, THIRTEEN elements were rendering in
   the fallback — the entire primary navigation, plus the search
   eyebrow and hint. Not a declaration problem: the Typekit kit
   serves prenton in 300 and 400 only, and the parent theme asks
   for 500 on nav links and 700 on the search eyebrow. A weight
   that is not loaded silently falls to the next family in the
   stack, so the navigation has been rendering in a different
   typeface from the rest of the site.

   Asking only for weights that exist is also the restraint the
   comparison called for: Push runs one family in three weights.
   This theme's own CSS already only used 300 and 400 — the drift
   came from inherited rules, not from here.
   ───────────────────────────────────────────────────────────── */
.site-header .menu-item > a,
.site-header .menu-link,
.site-header nav a,
.search-eyebrow,
.search-hint{
	font-family:var(--wp--preset--font-family--sans);
	font-weight:400;
}

/* ─────────────────────────────────────────────────────────────
   RESTRAINT IN SCALE — display type inside narrow columns

   "A brand is a coherence problem." rendered at 97px inside a
   394px block column and broke MID-WORD: "coheren / ce", with the
   full stop orphaned on its own line. "Tell us what's keeping you
   up at night." did the same at 78px in 411px.

   Neither is styled by this theme — both are h2.wp-block-heading
   taking the global xx-large preset, which is sized for a full
   measure and lands in a third of one. At 97px the word
   "coherence" alone needs ~437px and the column is 394px, so
   there is no break that is not a bad break.

   Display type in a column steps down to the h2 token. This is
   the pushhere.com lesson applied where it belongs: their
   headline is 46px because scale is spent on imagery, not on
   their own words. Ours keeps the hero big and stops shouting
   underneath it.
   ───────────────────────────────────────────────────────────── */
.wp-block-column h2.wp-block-heading,
.wp-block-column h2.has-display-font-family{
	font-size:var(--t-h2);
	line-height:1.06;
	text-wrap:balance;
	/* Safety net: even at the smaller step, never split a word. */
	overflow-wrap:normal;
	hyphens:manual;
}

/* ─────────────────────────────────────────────────────────────
   BAND RHYTHM — one content width, one comfortable measure

   Bands were landing on three different widths (1440, 1325, 736)
   because a specificity bug in the parent theme discarded every
   block's declared contentSize. With that fixed, the widths are
   held here so they cannot drift apart again.

   MEASURE. Prose ran at 41 and 53 characters. 60–68 is the
   readable range and roughly what pushhere.com runs; below ~45 a
   paragraph becomes a ribbon and the eye works harder for it.
   Set in `ch` so it tracks the font rather than a guessed pixel
   width.
   ───────────────────────────────────────────────────────────── */
.sevenality-band > *,
.sevenality-philbrief > *,
.sevenality-quoteband > *{ max-width:1325px; margin-inline:auto; }

/* Caps are in rem, NOT ch. `ch` is the width of the digit zero, which varies
   enough between these faces that one 64ch rule produced 77 real characters
   in one band and 57 in another — measuring the wrong thing precisely. These
   are calibrated against actual glyph widths at each size to land in 60–68. */
.phb__d{ max-width:30rem; }                    /* 16px → ~62 chars */
.sevenality-band p:not([class]),
.sevenality-band .wp-block-column p{ max-width:38rem; }   /* 21px → ~64 chars */
/* The hero standfirst. It sits in a cover block's flex group, not in a
   .sevenality-band, which is why an earlier band-scoped selector missed it
   entirely and it kept measuring 91 characters on one line. The hero itself
   is unchanged — this caps the line length only. */
.wp-block-cover__inner-container p.wp-block-paragraph.has-sans-font-family{ max-width:44rem; }  /* 24px → ~64 chars */

/* The second philanthropy paragraph is the quieter half of the
   thought, so it steps back rather than repeating the weight. */
.phb__d--quiet{ color:var(--ink-on-dark-dim); margin-block-start:var(--s-md); }

/* Dateline on the ideas cards. Quiet — it is a fact about the piece, not a
   headline — but present, because a thought-leadership page that hides when
   it published is arguing against itself. */
.svi-card__date{
	display:block; font-family:var(--wp--preset--font-family--sans);
	font-size:var(--t-micro); letter-spacing:.14em; text-transform:uppercase;
	color:var(--sev-ink-dim); margin-block-end:var(--s-2xs);
}

/* The blog hero's standfirst ran 164 characters at full width — inherited from
   the parent's layout, and only visible once there was enough content to make
   the page worth reading. Capped to the same measure as everything else. */
/* The blog hero subtitle. Ran 164 characters at full width — inherited, and
   invisible until there was enough content to read the page. The class is
   `editorial-hero__subtitle`; two earlier guesses (`__description`,
   `editorial-hero p`) matched nothing, which is why it is worth reading the
   DOM rather than inferring a class name from a sibling template. */
.editorial-hero__subtitle { max-width:44rem; }


/* ── BANDS MEET, THEY DO NOT FLOAT ────────────────────────────────────────────
   Measured on the homepage: a 24px gap between EVERY band — the flow layout's
   block-gap applied to each full-width section in turn.

   On light bands it is invisible, because the gap shows the page ground and the
   band is the same colour. On the two dark bands it becomes a bright seam, and
   it reads as a rendering fault rather than as spacing. The earlier note filed
   this as "two adjacent dark bands"; the adjacency was not the problem, the
   gap was — it had simply never been visible anywhere else.

   Bands carry their own generous padding (the band / band-lg scale), so the
   gap was doing no spacing work either. */
.sevenality-band,
.sevenality-ideas,
.sevenality-wcards,
.sevenality-svcbrief,
.sevenality-philbrief,
.sevenality-quoteband,
.sevenality-hero {
	margin-block: 0;
}

/* The quote band's #161616 is NOT set here — it is an inline block attribute in
   the page content, so a stylesheet rule would need !important to win. It is
   corrected at source instead. See the homepage content migration. */

/* ── ACCENT: TWO KINDS PER BAND ───────────────────────────────────────────────
   design-pass run 2 measured three distinct kinds of accent-coloured thing in
   the Programs and Work bands, against DESIGN.md principle 8's limit of two.
   The rule was already amended once — a repeated LINK colour inside one
   repeating element is fine — and amending it a second time so the page passes
   would make the gate ceremony. The page moved instead. (Rules above: the
   Programs numerals at :445 and the work-card service lines at :2560.)

   Programs keeps the section label and the project COUNTS; the counts are the
   evidence, and this practice does not claim what it cannot show. What went
   dim is the 01–04 numerals — ordinal decoration, and the same tell the
   oneshot-hero evaluation flags when a layout numbers things that are not
   really a sequence.

   The work rail keeps the label and READ MORE — a link, explicitly allowed —
   and drops the accent from the service-line metadata. */

/* ============================================================
   THE TEASER — "The Setting"
   ------------------------------------------------------------
   Type-weave direction: no imagery, no scroll. The page composes
   itself once and rests. Scoped to .sev-soon so none of it can
   reach the site behind the door.

   WARMTH. The brief asked for warm; this brand's canvas is a
   neutral #FBFBFB under a cool #306090. Rather than warm the
   brand — which would make the teaser disagree with every page
   it is hiding — the warmth is a TEASER-SCOPED paper tone, and
   the ink warms with it so the two do not fight. The accent is
   untouched: cool blue on warm paper is one of the oldest
   editorial pairings there is, and it is the only colour on the
   page that has to stay recognisably Sevenality.

   The typeface is doing most of the warming. Utopia Std Headline
   is a transitional serif with real calligraphic modulation; set
   at this size it carries more warmth than any ground tone will.
   ============================================================ */
/* Declared on BODY as well as the wrapper, because the wrapper is inside body
   and a custom property does not travel upward. Defining them only on
   .sev-soon left body resolving var(--soon-paper) to its fallback, so the page
   was dark and the sheet underneath it was still cream — invisible until an
   overscroll bounce, which is exactly how the warm build got this wrong in the
   other direction. */
/* ── Chrome tokens, ground-agnostic ──────────────────────────────────────
   The masthead and colophon are reused on every page when soon mode is on
   (see header.php), but the marble GROUND is not — it stays on the teaser.
   So the chrome's own colours cannot be pinned to that ground. They resolve
   from the brand palette here, which is light-dark() aware, and are
   overridden below for the teaser, whose ground is fixed regardless of the
   visitor's colour scheme.

   Without this split the header and footer render white-on-white the moment
   the chrome appears over a light page. */
.sev-soon {
	--soon-ink   : var(--sev-ink);
	--soon-dim   : var(--sev-ink-dim);
	--soon-rule  : light-dark(rgba(0, 0, 0, .16), rgba(255, 255, 255, .28));
	--soon-accent: var(--sev-accent);
}

body.sev-soon-body,
.sev-soon--teaser {
	/* THE PAGE INVERTED WHEN THE MARBLE ARRIVED. The warm paper was the right
	   answer for a type-only page; it is the wrong answer under a saturated
	   blue ground, where warm ink would sit on the texture as a stain. So the
	   scheme goes dark and the paper survives only as the colour behind the
	   image while it decodes. */
	--soon-paper : #0c3d5d;
	--soon-ink   : #ffffff;
	--soon-dim   : rgba(255, 255, 255, .76);
	--soon-rule  : rgba(255, 255, 255, .28);

	/* The brand's own light blue. It is light-dark(#306090, #80ABD7) and this
	   page forces the light scheme, so the token would resolve to the dark
	   half and vanish into the marble. Named explicitly for that reason, and
	   for that reason only.

	   A gold was tried here, borrowed from the reference piece that prompted
	   the grid and the rotated caps. It was reverted: the brand has an accent
	   already, and importing a second colour from a reference is how a system
	   acquires a colour nobody chose. The contrast argument made for it does
	   not survive checking either — the light blue measured 3.68:1 against a
	   3.0 floor for text this size. Tightest on the page, and passing. */
	--soon-accent: #80ABD7;

	/* The statement is the largest type on this site by a wide margin, which
	   is the point: it is the only thing on the page.

	   SIZED AGAINST BOTH AXES. Keyed to vw alone this overran a 1440x900
	   viewport by ~170px — the paragraph clipped and the colophon fell off the
	   bottom, on the one page whose entire argument is composure. Three lines
	   of display type, a rule, a paragraph, a masthead and a colophon have to
	   agree to fit, so the type yields to whichever axis is scarcer. */
	--soon-display: clamp(1.75rem, min(4.6vw, 7vh), 4.25rem);

	min-height: 100svh;
	display: grid;
	grid-template-rows: auto 1fr auto;
	background: var(--soon-paper);
	color: var(--soon-ink);
}

/* The ground colour behind the marble. Shows for the moment the image is
   decoding, and on an overscroll bounce past the fixed layer. */
/* Only ever present on the teaser — header-soon.php adds the class there
   and nowhere else. */
body.sev-soon-body {
	background: var(--soon-paper);
}

/* ---------- the ground ----------
   Fixed rather than absolute so it cannot be scrolled off on a short viewport,
   and isolated so the drift transform never invalidates the type's layer. */
.sev-soon .soon-ground {
	position: fixed;
	inset: 0;
	z-index: 0;
	overflow: hidden;
	pointer-events: none;
}

.sev-soon .soon-ground__img {
	position: absolute;
	/* Oversized and centred so a few pixels of drift in any direction never
	   pull an edge into view. */
	inset: -5%;
	width: 110%;
	height: 110%;
	/* WordPress themes ship `img { max-width: 100% }` almost universally, and
	   it silently clamped this to 100% of the viewport. The oversize existed in
	   the stylesheet and not on the screen, so the drift exposed 72px of bare
	   ground down the right edge as a hard vertical seam — visible in a capture
	   and invisible in the CSS. */
	max-width: none;
	object-fit: cover;
	/* The drift writes these two, and nothing else. Both are compositor
	   properties, so the ground moves without laying the page out again. */
	transform: translate3d(var(--soon-dx, 0px), var(--soon-dy, 0px), 0);
	transition: transform .9s cubic-bezier(.16, 1, .3, 1);
	will-change: transform;
}

/* The wash carries the contrast. White type over a photograph is a promise you
   cannot keep at every pixel, and the marble runs light in its top-left. This
   is a flat scrim plus a gradient weighted to the corner the type occupies:
   measured, not guessed, at every text element on the page. */
.sev-soon .soon-ground__wash {
	position: absolute;
	inset: 0;
	/* Lightened after measuring. The first wash cleared AA with enormous
	   headroom — the statement at 11.84:1 against a requirement of 3 — and paid
	   for it by burying the marble almost entirely on the left, which is the
	   half the type sits on. A texture nobody can see is not a texture. These
	   values give the ground back its figure while keeping every element above
	   its floor against the LIGHTEST pixel behind it, not the average one. */
	background:
		linear-gradient(105deg, rgba(6, 28, 44, .62) 0%, rgba(6, 28, 44, .34) 52%, rgba(6, 28, 44, .18) 100%),
		rgba(12, 61, 93, .2);
}

/* Everything else rides above the ground. */
.sev-soon .soon-head,
.sev-soon .soon-main,
.sev-soon .soon-foot,
.sev-soon .skip-link { position: relative; z-index: 1; }

/* ---------- the drawn grid ----------
   Above the marble, below the type. Fixed, so it stays registered to the
   viewport rather than to the document, which is what makes it read as a
   sheet the page is printed on. */
.sev-soon .soon-grid {
	position: fixed;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	display: flex;
}

.sev-soon .soon-grid__inner {
	width: 100%;
	max-width: 78rem;
	margin-inline: auto;
	padding-inline: clamp(1.5rem, 5vw, 5rem);
	/* Six columns. Twelve was tested and turned the page into graph paper at
	   the width the statement occupies; six lands one rule near enough to each
	   natural break in the type to look intended. The background is inset by
	   the padding via content-box clipping, so the outermost rules sit exactly
	   on the text's left and right edges. */
	background-image: repeating-linear-gradient(
		to right,
		var(--soon-gridline) 0 1px,
		transparent 1px calc(100% / 6)
	);
	background-clip: content-box;
	-webkit-background-clip: content-box;
}

/* SCORED, NOT DRAWN IN LIGHT. The obvious rule on a dark ground is a pale one,
   and it cost the brand accent its contrast: white lines at 13% raised the
   lightest pixel behind the accent line from rgb(34,76,112) to rgb(58,92,122)
   and took it from 3.56:1 to 2.92:1, under the 3.0 floor. The grid was new and
   the accent is the brand's, so the grid is what moved.

   A dark rule reads exactly as well here — closer to a score line pressed into
   the ground than a line drawn on it — and it can only ever lower the
   luminance behind type, so it cannot take contrast from anything. */
.sev-soon { --soon-gridline: rgba(4, 20, 34, .34); }

/* A shared inset so masthead, statement and colophon sit on ONE left edge.
   Three different gutters is the usual way a page like this stops looking
   composed and starts looking assembled. */
.sev-soon .soon-head__inner,
.sev-soon .soon-stage,
.sev-soon .soon-foot__inner {
	width: 100%;
	max-width: 78rem;
	margin-inline: auto;
	padding-inline: clamp(1.5rem, 5vw, 5rem);
}

/* ---------- masthead ---------- */
.sev-soon .soon-head {
	padding-block: clamp(1.5rem, 3vw, 2.5rem);
	border-bottom: 1px solid var(--soon-rule);
}
.sev-soon .soon-head__inner {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--s-md);
}

/* The nameplate is set in the display serif, not the sans. A small
   wide-tracked sans wordmark is the luxury-brand default, and defaulting is
   the one thing this page cannot afford to do. */
.sev-soon .soon-mark {
	margin: 0;
	line-height: 1;
}
.sev-soon .soon-mark a {
	color: inherit;
	text-decoration: none;
	display: inline-flex;
}

/* The mark is portrait (a 428x574 viewBox), so it is sized by HEIGHT and left
   to find its own width. Sizing by width would make it grow downward past the
   masthead rule as the viewport widens. */
.sev-soon .soon-mark svg {
	display: block;
	/* Larger than the wordmark it replaced. A two-stroke mark carries far less
	   visual weight than seven letters at the same height, so matching the old
	   type size left the masthead looking half-empty. */
	height: clamp(2.4rem, 3.4vw, 3.25rem);
	width: auto;
}

/* The currentColor leg inherits white from the page. The other is drawn in
   the brand blue, which on this ground is close enough to the background to
   read as missing, so it takes the light blue the accent uses. Both legs stay
   distinguishable, which is the whole point of a two-tone mark. */
.sev-soon .soon-mark svg .sev-mark__b { stroke: var(--soon-accent); }

/* The mark is drawn with a 29-unit stroke in a 574-unit viewBox, so it scales
   to under 2px at masthead size and reads as a hairline rather than a mark.
   Thickened here only — the source file stays as traced. */
.sev-soon .soon-mark svg path { stroke-width: 38; }

.sev-soon .soon-nav {
	display: flex;
	gap: clamp(1.25rem, 2.5vw, 2.25rem);
}
.sev-soon .soon-nav a {
	font-family: var(--wp--preset--font-family--sans);
	/* Up from --t-meta (12px). Uppercase at .18em tracking loses a lot of
	   apparent size to the letterspacing, so the nav was reading smaller than
	   its number suggested. */
	font-size: var(--t-small);
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--soon-dim);
	text-decoration: none;
	padding-block-end: .35em;
	border-bottom: 1px solid transparent;
	transition: color .3s ease, border-color .3s ease;
}
/* Hover is where the nav is allowed to touch the accent. At rest the page
   carries exactly one accent-marked thing, and it is the word. */
.sev-soon .soon-nav a:hover,
.sev-soon .soon-nav a:focus-visible {
	color: var(--soon-accent);
	border-bottom-color: var(--soon-accent);
}

/* ---------- tap targets ----------

   Measured on the teaser at 390px: the logo was 29x38 and both nav links were
   27px tall. The floor for a touch target is 44x44, so all three were roughly
   half height — on a page whose entire interaction surface is these three
   links.

   The hit area is grown with an overlay rather than padding. Padding would
   work, but the underline here is a `border-bottom` on the link itself, so
   vertical padding would push the rule away from the word and change the
   design to fix an ergonomics bug. The overlay leaves every visible pixel
   where it was.

   `inset` is negative so the box extends beyond the text on all sides; the
   horizontal gap between the two links (min 1.25rem = 20px) is wider than the
   2 x 8px of horizontal growth, so the targets cannot overlap each other. */
.sev-soon .soon-nav a,
.sev-soon .soon-mark a {
	position: relative;
}
.sev-soon .soon-nav a::after,
.sev-soon .soon-mark a::after {
	content: '';
	position: absolute;
	/* 27px text + 2 x 9px = 45px. Logo 38px + 2 x 4px = 46px. */
	inset: -9px -8px;
}
.sev-soon .soon-mark a::after {
	inset: -4px -8px;
}

/* ---------- the statement ---------- */
.sev-soon .soon-main {
	display: grid;
	align-content: center;
	/* Optical centre, not mathematical: a block of type centred by the box
	   reads as sitting low. The asymmetric padding lifts it. */
	/* A breathing FLOOR, not the spacing itself. The 1fr row already owns the
	   leftover height and align-content centres the block inside it, so large
	   fixed padding here does nothing but push the composition past the fold —
	   which is exactly how the first build overran. The two values stay
	   asymmetric because a block of type centred by the box reads as sitting
	   low; the extra below lifts it to the optical centre. */
	padding-block: clamp(1.5rem, 4vh, 3rem) clamp(2.5rem, 7vh, 5rem);
}

.sev-soon .soon-statement {
	margin: 0;
	/* Explicit, because the theme sets a colour on `h1, h2, h3, h4, h5, h6`
	   and that beats the inherited --soon-ink from .sev-soon. The masthead was
	   picking up the warm ink and the statement was not, so the page carried
	   two near-blacks that were never meant to differ. */
	color: var(--soon-ink);
	font-family: var(--wp--preset--font-family--display);
	font-weight: 400;
	font-size: var(--soon-display);
	line-height: .96;
	letter-spacing: -.035em;
}

/* Each line is its own block so the sentence breaks where the composition
   wants it, not where the measure happens to run out. */
.sev-soon .soon-line {
	display: block;
}

.sev-soon .soon-line--key {
	color: var(--soon-accent);
	/* No indent. This was set at .38em when the accented line was the single
	   word "coherence" and the indent read as deliberate. The line is now a
	   full phrase, and indenting a phrase that already runs the width of the
	   column reads as a mistake rather than a decision. */
}

/* ---------- the rule ---------- */
.sev-soon .soon-rule {
	display: block;
	height: 1px;
	background: var(--soon-ink);
	margin-block: clamp(2rem, 4.5vh, 3.5rem) clamp(1.5rem, 3vh, 2.25rem);
	/* A mark, not a divider. A fixed 22rem is a short rule beside a 1440
	   column and very nearly the full measure on a 390px phone, where it
	   stopped reading as a mark and started reading as a horizontal rule
	   separating two things. The percentage keeps its PROPORTION constant
	   instead of its length. */
	max-width: min(22rem, 52%);
	transform: scaleX(0);
	transform-origin: 0 50%;
	animation: soon-rule-draw 1.1s cubic-bezier(.16, 1, .3, 1) 1.1s forwards;
}
@keyframes soon-rule-draw { to { transform: scaleX(1); } }

/* ---------- the paragraph ---------- */
.sev-soon .soon-lead {
	margin: 0;
	font-family: var(--wp--preset--font-family--sans);
	font-weight: 300;
	/* Up from a flat --t-lead (21px). This is the only prose on the page and
	   it was sitting at the size it would take inside a dense article, next to
	   a 63px statement. Weight 300 also reads lighter than its size, which the
	   ceiling here compensates for. */
	/* Sized against BOTH axes, like the statement. Raising this from 21px to
	   24px is what pushed 1440x620, 1024x640 and 900x700 over the fold: the
	   paragraph is the tallest thing on the page by line count, so every point
	   it gains costs eight times that in height. The vh term hands the gain
	   back on a short window. */
	font-size: clamp(1rem, min(1rem + 0.6vw, 3.2vh), 1.5rem);
	line-height: 1.6;
	color: var(--soon-dim);
	/* A reading measure. Prose set to the full 78rem would be the one
	   un-designed thing on the page. */
	max-width: 46ch;
}

/* The status line. Separated from the argument above it because it answers a
   different question: the paragraph says what this practice believes, this says
   whether the practice is currently running. A reader at a closed door wants
   the second one and should not have to find it at the end of a paragraph. */
.sev-soon .soon-status {
	margin: clamp(1.25rem, 3vh, 2rem) 0 0;
	font-family: var(--wp--preset--font-family--sans);
	font-size: var(--t-small);
	line-height: 1.6;
	color: var(--soon-dim);
	max-width: 46ch;
}

/* Vertical, up the right edge. The aside goes in the margin.
   GUARDED ON HEIGHT AS WELL AS WIDTH. A 97-character line set vertically needs
   a column taller than itself, and a wide but short window (a laptop with the
   dock and a browser chrome, 1440x600) has the width to trigger this and not
   the height to hold it. Guarded on width alone it clipped at both ends
   silently, because the line is nowrap and nothing overflows visibly enough
   to notice in a screenshot. */
/* 54em, not 44em. The line needs a column taller than itself and the column is
   the viewport minus the masthead and colophon, so the threshold is the line's
   length plus that furniture — measured, not guessed: at 1200x800 the guard
   passed and the aside still clipped. */
@media (min-width: 60em) and (min-height: 54em) {
	.sev-soon .soon-main { position: relative; }

	.sev-soon .soon-status {
		position: absolute;
		/* PHYSICAL, not logical. inset-block and inset-inline resolve against
		   this element's own writing mode, and the rule below turns that
		   vertical — so inset-block became the HORIZONTAL axis and pinned both
		   edges, stretching a margin note across the full 1440px. */
		top: 0;
		bottom: 0;
		right: clamp(1.5rem, 5vw, 5rem);
		left: auto;
		margin: 0;
		max-width: none;
		display: flex;
		align-items: flex-start;

		/* vertical-rl lays the line top-to-bottom; the rotation turns it to
		   read bottom-to-top, which is the direction a spine is set and the
		   direction the reference uses. */
		writing-mode: vertical-rl;
		transform: rotate(180deg);

		/* Back to --t-micro. Raised to --t-meta with the nav and the body copy
		   and it overran: at 12px this 97-character line measures longer than
		   the height it has to run in, and being nowrap it clipped at both
		   ends rather than wrapping. The request was for the MENU and the
		   BODY; a margin note is neither. */
		font-size: var(--t-micro);
		/* Down from .24em. Tracking is what made this line long: at .24em it
		   measured 711px against the 650px the column actually has, and 97
		   characters pay for every extra thousandth of an em. */
		letter-spacing: .13em;
		text-transform: uppercase;
		line-height: 1;
		white-space: nowrap;
	}
}

/* ---------- colophon ---------- */
.sev-soon .soon-foot {
	padding-block: clamp(1.5rem, 3vw, 2.5rem);
	border-top: 1px solid var(--soon-rule);
}
/* The tagline carries the footer, so the colophon steps back rather than
   competing with it. Set in the display face: it is the brand's line, not a
   caption about the brand. */
.sev-soon .soon-tagline {
	margin: 0;
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(1rem, 1.3vw, 1.2rem);
	letter-spacing: -.01em;
	color: var(--soon-ink);
}

.sev-soon .soon-foot__inner {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--s-sm);
}

.sev-soon .soon-colophon {
	margin: 0;
	font-family: var(--wp--preset--font-family--sans);
	font-size: var(--t-meta);
	letter-spacing: .06em;
	color: var(--soon-dim);
}

/* ---------- reduced motion ----------
   The animation system returns before element processing under reduced
   motion, so the statement is simply present. The rule is the theme's own
   animation and has to be resolved here — otherwise it stays at scaleX(0)
   and the composition loses a line it was balanced around. */
@media (prefers-reduced-motion: reduce) {
	.sev-soon .soon-rule {
		animation: none;
		transform: none;
	}
	.sev-soon .soon-nav a { transition: none; }
	/* The drift never starts under reduced motion (the script checks), but the
	   transition is removed too so a stale custom property cannot animate. */
	.sev-soon .soon-ground__img { transition: none; }
}

/* ── THE TEASER AT THE NARROW END ─────────────────────────────────────────────
   The copy grew from 40 words to about 100 and stopped fitting a 360x740
   phone, which overflowed by 120px while the display clamp was already sitting
   on its floor and could not give any more. Small Android handsets are not an
   edge case to wave through on a page whose entire argument is composure.

   The paragraph yields rather than the statement: it is the element with the
   most lines to lose, and a statement that shrinks below its floor stops being
   a statement. */
@media (max-width: 30em) {
	.sev-soon {
		--soon-display: clamp(1.5rem, 7.4vh, 1.75rem);
	}
	.sev-soon .soon-lead {
		font-size: 1rem;
		line-height: 1.5;
	}
	.sev-soon .soon-status {
		font-size: var(--t-meta);
	}
	.sev-soon .soon-main {
		padding-block: clamp(1rem, 2.5vh, 1.75rem) clamp(1.25rem, 3.5vh, 2.25rem);
	}
	.sev-soon .soon-rule {
		margin-block: clamp(1.25rem, 3vh, 2rem) clamp(1rem, 2vh, 1.5rem);
	}
}

/* ── THE HERO TAKES THE TEASER'S GRID ─────────────────────────────────────────
   Same device, same reasoning: rules drawn on the ground the type already
   aligns to, so the page reads as measured rather than merely tidy. The hero
   is the only other surface on this site standing on the marble, so it is the
   only other one this belongs on.

   Aligned to the COVER'S OWN padding rather than the teaser's inset. The two
   surfaces do not share a measure — the hero is a full-bleed cover at 4vw and
   the teaser is a 78rem column at 5vw — and copying the teaser's numbers here
   would put the rules somewhere the headline never touches.

   Dark, for the reason the teaser's are: a pale rule raises the luminance
   behind whatever crosses it, and white type on a dimmed photograph has no
   contrast to spare. A dark rule can only ever help.
   ============================================================ */
.sevenality-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	/* Above the cover image and its dim overlay, below the words. Core gives
	   both the overlay and the inner container z-index 1, and this
	   pseudo-element comes last in paint order, so without lifting the inner
	   container the rules would be drawn across the headline. */
	z-index: 1;
	pointer-events: none;
	padding-inline: clamp(1.25rem, 4vw, 4.5rem);
	background-image: repeating-linear-gradient(
		to right,
		rgba(4, 20, 34, .3) 0 1px,
		transparent 1px calc(100% / 6)
	);
	background-clip: content-box;
	-webkit-background-clip: content-box;
}

.sevenality-hero .wp-block-cover__inner-container {
	position: relative;
	z-index: 2;
}

/* ── THE TEASER ON A SHORT WINDOW ─────────────────────────────────────────────
   Everything above scales against width. A 1024x640 or 900x700 window has
   plenty of width and none of the height, and raising the body copy from 21px
   to 24px was enough to push those shapes past the fold — the paragraph is the
   tallest element by line count, so a three-point gain costs roughly eight
   times that in height.

   The FURNITURE gives way here, not the reading sizes. Padding, the rule's
   margins and the mark are all things a reader is not looking at; the
   statement and the paragraph are the things they came for. */
@media (max-height: 50em) and (min-width: 30em) {
	.sev-soon .soon-head,
	.sev-soon .soon-foot { padding-block: clamp(.75rem, 2vh, 1.25rem); }

	.sev-soon .soon-mark svg { height: clamp(1.9rem, 4.4vh, 2.6rem); }

	.sev-soon .soon-main {
		padding-block: clamp(.75rem, 2vh, 1.5rem) clamp(1rem, 3vh, 2rem);
	}

	.sev-soon .soon-rule {
		margin-block: clamp(1rem, 2.5vh, 1.75rem) clamp(.75rem, 2vh, 1.25rem);
	}

	.sev-soon .soon-status { margin-block-start: clamp(.75rem, 2vh, 1.25rem); }
}

/* ── IDEAS: THE HERO BAND TAKES THE GRID ──────────────────────────────────────
   The third surface to carry the scored rules, after the homepage hero and the
   teaser. It stays FLAT — solid #0c3d5d, no marble. Three marble surfaces would
   stop the texture being a moment and make it wallpaper, so this band is tied
   to the others through structure rather than material.

   THE SANS TITLE IS DELIBERATE and stays. Every editorial headline on this site
   is Utopia Std Headline, and "IDEAS" is not one: it is a section title, and
   setting those apart from article headlines is a decision, not drift. Recorded
   here because it reads as an inconsistency to anybody arriving cold, and the
   next person to notice should find this note rather than "fix" it.

   Scoped to this stylesheet, which is the child's, so gflidev keeps the hero it
   has. editorial-hero is a PARENT component — template-parts/editorial-hero.php,
   used by archive, home, category and author — and changing it upstream would
   have redesigned the personal site's blog at the same time.

   Hung off __inner rather than the band, so it aligns itself: the pseudo-element
   inherits the inner's padding and clips the gradient to the content box, which
   puts the first rule exactly on the title's left edge at any width. The band's
   own inset is a vw value against an 1800px cap, and hard-coding that here would
   be a second source of truth that drifts the first time the parent changes.
   ============================================================ */
.editorial-hero__inner {
	position: relative;
}

.editorial-hero__inner::before {
	content: "";
	position: absolute;
	/* Stretched past the inner to the band's own edges. The inner holds only
	   the text block; the band adds padding: 4rem 0 2rem around it (parent
	   blog.scss:44), and rules that stop short of the colour they are drawn on
	   read as a mistake rather than a measure. These two numbers mirror the
	   parent's and are the one place this override duplicates it. */
	inset: -4rem 0 -2rem;
	z-index: 0;
	pointer-events: none;
	padding-inline: inherit;
	/* Dark, as everywhere else this grid appears. A pale rule raises the
	   luminance behind whatever crosses it, and the title here is white on a
	   solid blue with no contrast to spare. A dark rule can only help. */
	background-image: repeating-linear-gradient(
		to right,
		rgba(4, 20, 34, .3) 0 1px,
		transparent 1px calc(100% / 6)
	);
	background-clip: content-box;
	-webkit-background-clip: content-box;
}

/* The band's own content sits above the rules. */
.editorial-hero__inner > * {
	position: relative;
	z-index: 1;
}

@media (max-width: 48em) {
	/* The parent drops the band to padding: 2.5rem 0 1.5rem at this width. */
	.editorial-hero__inner::before { inset: -2.5rem 0 -1.5rem; }
}
