/* ==========================================================================
   CONTENT LAYOUT: posts (single.php) and content pages (page-content.php)
   Quick 260927-cqn. Enqueued after theme.css (handle njs-content, dep njs-theme)
   on is_singular('post') and is_page_template('page-content.php') only.

   SOURCE OF TRUTH: the LOCKED LAYOUT SPEC in
   .planning/quick/260927-cqn-content-layout-redesign-pages-posts/260927-cqn-DECISIONS.md
   (Jay, 2026-09-27: "lets settle this for good and make sure no more
   deviations"). Changing any locked value needs a new explicit ruling from Jay
   recorded in that file.

     Look ............ Direction C "Photo-Led Field Guide", short photo header
     Text track ...... 720px (--njs-measure: 45rem)
     Body text ....... 18px from 1024px up. Phones keep the theme's 16px.
     Sidebar ......... clamp(280px, 21.5vw, 350px) = 310 @1440, 350 @1920,
                       sticky at top 112px, shown from 1120px up
     Alignment ....... every block on one center line. Media and cards break
                       out symmetrically, bands run full-bleed (landing).

   SUPERSEDED, never bring these back:
     - theme.css --text-measure: 46rem (736px). Now 45rem.
     - 900px content column / 280px fixed sidebar / 1200px shell
       (--njs-content-width, --njs-sidebar-width, --njs-max-width no longer
       govern posts or content pages. The tokens stay for category.php.)
     - sidebar top: 20px (slid under the 88px sticky header)
     - 800px text + 280px sidebar (Blog Writing Framework v12,
       Landing Page Framework v10, PAGE_TEMPLATE_GUIDE.md)
     - 848px / 17px (the staging column before this build)
     - party.css's orange/green tints on 19459 (decision 2, Jay accepted
       losing them for the C look)

   Markup contract (templates, see single.php / page-content.php docblocks):
     main.njs-layout.njs-layout--article (+ --rail) | .njs-layout--landing
       header.njs-hero (--photo | --ink) > .njs-hero__inner > .njs-hero__flow.njs-flow
       div.njs-shell.njs-body (+ .njs-shell--rail) > div.njs-flow + aside.njs-sidebar
       div.njs-flow.njs-flow--landing.njs-body
   .njs-body stays in the markup, so every .njs-body rule in theme.css still
   applies. Where the C skin differs, this file overrides with
   `.njs-layout .njs-flow ...` selectors (0,2,1 and up beat .njs-body x at
   0,1,1). theme.css is never edited to make room for this file, except the
   single --text-measure line.

   Alignment model: one CSS grid per flow with named tracks
   (content / feature / wide / full) that share one center axis. Every child
   defaults to `content`. Breakouts are declared by component, never by page.
   Bands and unclassed wrappers become subgrids, never display: contents.
   ========================================================================== */

:root {
	--njs-measure: 45rem;                            /* 720px, LOCKED */
	--njs-rail: clamp(280px, 21.5vw, 350px);         /* 310 @1440, 350 @1920, LOCKED */
	--njs-rail-gap: 48px;
	--njs-feature-pad: clamp(6rem, 10vw, 14rem);     /* feature track reach past each text edge */
	--njs-gutter: 16px;                              /* phone gutter, today's 390 geometry */
	--njs-shell: min(var(--container-max), 94%);     /* same as .njs-container */
	--njs-orange-text: color-mix(in srgb, var(--color-primary) 55%, black); /* orange TEXT under 24px on light backgrounds (about 6.7:1) */
}

@media (max-width: 767px) {
	:root {
		--njs-shell: calc(100% - 2 * var(--njs-gutter));
	}
}

/* ==========================================================================
   1. PAGE FRAME
   ========================================================================== */

/* theme.css .njs-main adds block padding (and more on phones). The header band
   starts right under the site header. */
.njs-main.njs-layout {
	padding: 0;
	margin-bottom: 0;
}

/* ---- Header band (short C photo header) ----------------------------------
   theme.css styles .njs-hero for the HOMEPAGE (tall, centered, text-shadow,
   96px padding from 1025px). Every one of those is reset here so the content
   header stays the short band Jay approved (dir-cs.css). */
.njs-layout .njs-hero {
	position: relative;
	overflow: hidden;
	padding: 0;
	background: var(--color-ink);
	background-image: none;
	color: #fff;
	/* Decision 10 (2026-09-28, Jay's option A): every content header is at
	   least the blog header's height, measured on 89702 (390: 320.56px,
	   1024: 327.92px, 1440 and 1920: 350.84px). Shorter titles get the same
	   band, with the text centered vertically. Taller titles still grow it. */
	min-height: 320.5625px;
	display: flex;
	flex-direction: column;
	justify-content: center;
}

@media (min-width: 1024px) {
	.njs-layout .njs-hero {
		min-height: 327.921875px;
	}
}

@media (min-width: 1440px) {
	.njs-layout .njs-hero {
		min-height: 350.84375px;
	}
}

@media (min-width: 1025px) {
	.njs-layout .njs-hero {
		padding: 0;
	}
}

.njs-layout .njs-hero *,
.njs-layout .njs-hero *::before,
.njs-layout .njs-hero *::after {
	box-sizing: border-box;
}

/* The photo. No object-position here: the inline style from
   _njs_header_focus (njs_header_focus(), whitelisted) owns the crop. */
.njs-layout .njs-hero__bg {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	max-width: none;
	object-fit: cover;
	opacity: 0.85; /* was 0.55. Jay, 2026-10-09 (HERO-FADE-LIGHTER) */
	display: block;
}

/* Ink scrim, strongest behind the text on the left. Lightened 2026-10-09
   (HERO-FADE-LIGHTER, was 0.92 / 0.55 / 0.15). Measured on all 19 header-photo
   pages: worst 5th-percentile white-text contrast 4.5:1 at 1440, 5.3:1 at 390. */
.njs-layout .njs-hero--photo::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(90deg, rgba(26, 26, 26, 0.80) 0%, rgba(26, 26, 26, 0.45) 55%, rgba(26, 26, 26, 0.10) 100%);
	pointer-events: none;
}

/* Phones: the title runs the full width, so the scrim is even, not left-weighted. */
@media (max-width: 767px) {
	.njs-layout .njs-hero--photo::after {
		background: rgba(26, 26, 26, 0.55);
	}
}

/* A soft shadow keeps the title off any bright patch in the photo. */
.njs-layout .njs-hero--photo .njs-hero__title,
.njs-layout .njs-hero--photo .njs-hero__crumb,
.njs-layout .njs-hero--photo .njs-hero__eyebrow,
.njs-layout .njs-hero--photo .njs-hero__meta {
	text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}

/* No photo: the solid ink band (decision 5, a fallback only). */
.njs-layout .njs-hero--ink {
	background: var(--color-ink);
}

.njs-layout .njs-hero__inner {
	position: relative;
	z-index: 1;
	width: var(--njs-shell);
	margin-inline: auto;
	padding-block: var(--space-2xl) var(--space-xl); /* dir-cs.css, LOCKED header height */
	padding-inline: 0;
	display: block;
	text-align: left;
	align-items: normal;
	gap: 0;
	text-shadow: none;
	color: #fff;
}

/* The hero text uses the SAME flow grid as the body, so the H1's left edge
   is the text column's left edge below it. */
.njs-layout .njs-hero .njs-hero__flow {
	padding-block: 0;
	counter-reset: none;
}

/* Rail pages: from 1120px (the rail breakpoint, never 1100) the hero inner
   takes the shell's two columns, so the title tracks the flow column and not
   the whole shell. No-rail articles and landing pages stay one column. */
@media (min-width: 1120px) {
	.njs-layout--rail .njs-hero__inner {
		display: grid;
		grid-template-columns: minmax(0, 1fr) var(--njs-rail);
		column-gap: var(--njs-rail-gap);
	}

	.njs-layout--rail .njs-hero__flow {
		grid-column: 1;
	}
}

.njs-layout .njs-hero .njs-breadcrumb {
	font-size: 14px;
	margin: 0 0 var(--space-md);
	color: rgba(255, 255, 255, 0.85);
	opacity: 1;
}

.njs-layout .njs-hero .njs-breadcrumb a {
	color: rgba(255, 255, 255, 0.85);
	opacity: 1;
	text-decoration: none;
}

.njs-layout .njs-hero .njs-breadcrumb a:hover,
.njs-layout .njs-hero .njs-breadcrumb a:focus-visible {
	color: #fff;
	text-decoration: underline;
}

/* Orange on a dark ground stays the brand orange (about 7.3:1 on ink).
   Darkening it here would LOWER the contrast. */
.njs-layout .njs-hero .njs-hero__eyebrow {
	color: var(--color-primary);
	font-family: var(--font-heading);
	font-weight: 700;
	font-size: 16px;
	line-height: 1.6;
	letter-spacing: 2px;
	text-transform: uppercase;
	margin: 0 0 var(--space-sm);
}

.njs-layout .njs-hero .njs-hero__title {
	color: #fff;
	font-family: var(--font-heading);
	font-size: clamp(2rem, 1.4rem + 2.2vw, 3.25rem);
	line-height: 1.08;
	font-weight: 700;
	margin: 0;
	max-width: none;
}

.njs-layout .njs-hero .njs-hero__meta {
	font-size: 14px;
	line-height: 1.6;
	margin: var(--space-sm) 0 0;
	color: rgba(255, 255, 255, 0.8);
}

/* ---- Article shell: flow column + sticky rail ------------------------------ */
.njs-layout .njs-shell {
	width: var(--njs-shell);
	margin-inline: auto;
	display: grid;
	grid-template-columns: minmax(0, 1fr); /* below 1120px, and on landing pages: one column */
	align-items: start;
}

/* theme.css L2357 .njs-sidebar is unscoped (280px, top 20px). Override it
   explicitly, never rely on the grid column alone. */
.njs-layout .njs-sidebar {
	display: none;
	width: var(--njs-rail);
	max-width: none;
	flex-shrink: 0;
	position: sticky;
	top: 112px; /* clears the sticky condensed header */
	max-height: calc(100vh - 112px - var(--space-lg));
	overflow-y: auto;
	padding-top: var(--space-xl);
	align-self: start;
}

@media (min-width: 1120px) {
	.njs-layout .njs-shell--rail {
		grid-template-columns: minmax(0, 1fr) var(--njs-rail);
		column-gap: var(--njs-rail-gap);
	}

	.njs-layout .njs-sidebar {
		display: block;
	}
}

/* ==========================================================================
   2. THE FLOW GRID
   ========================================================================== */

.njs-layout .njs-flow {
	display: grid;
	grid-template-columns:
		[full-start wide-start] minmax(0, 1fr)
		[feature-start] minmax(0, var(--njs-feature-pad))
		[content-start] min(var(--njs-measure), 100%)
		[content-end] minmax(0, var(--njs-feature-pad))
		[feature-end] minmax(0, 1fr)
		[wide-end full-end];
	padding-block: var(--space-xl) var(--space-3xl);
	counter-reset: njs-sec;
}

/* Landing mode: the flow spans the viewport and adds a full track. */
.njs-layout .njs-flow--landing {
	grid-template-columns:
		[full-start] minmax(var(--njs-gutter), 1fr)
		[wide-start] minmax(0, calc((min(var(--container-max), 94vw) - var(--njs-measure)) / 2 - var(--njs-feature-pad)))
		[feature-start] minmax(0, var(--njs-feature-pad))
		[content-start] min(var(--njs-measure), 100% - 2 * var(--njs-gutter))
		[content-end] minmax(0, var(--njs-feature-pad))
		[feature-end] minmax(0, calc((min(var(--container-max), 94vw) - var(--njs-measure)) / 2 - var(--njs-feature-pad)))
		[wide-end] minmax(var(--njs-gutter), 1fr)
		[full-end];
	/* 24px top, not 32 (Task 4C): 19459 stores no dek, so its intro sits in
	   the flow under the hero instead of inside it. Tight spacing lands the
	   intro and the ink jump bar as high as the locked markup allows. */
	padding-block: var(--space-lg) 0;
}

/* The intro directly above the landing jump bar sits 24px off it (Task 4C). */
.njs-layout .njs-flow--landing > .njs-answer-capsule:has(+ :is(.njs-jump, .njs-party-jump)) {
	margin-bottom: var(--space-lg);
}

/* DEFAULT TRACK: everything is text-width unless it declares otherwise. This
   is the safety net that lands an unknown legacy block on the text edge. */
.njs-layout .njs-flow > * {
	grid-column: content;
	min-width: 0;
	margin-inline: 0; /* UA figure/blockquote margins and theme list margins would pull a block off its track */
}

/* Plain lists keep their bullet indent inside the box, not as a margin.
   Classed lists (checks, tiles, steps) own their padding. */
.njs-layout .njs-flow > :is(ul, ol):not([class]),
.njs-layout .njs-flow > :is(.njs-band, .njs-party-band, section, div:not([class])) > :is(ul, ol):not([class]) {
	padding-left: var(--space-lg);
}

/* Declared breakouts, by component. */
.njs-layout .njs-flow > :is(figure, img, iframe, video, .njs-video, .njs-content-image, .njs-table-wrapper,
	.njs-tiles, .njs-media-row, .njs-hero-photo, .njs-wide-photo, .njs-shop,
	.njs-party-video, .njs-party-slots, .njs-party-row, .njs-party-split, .njs-party-wide-img, .njs-party-hero) {
	grid-column: feature;
}

.njs-layout .njs-flow > :is(.njs-cards, .njs-review-cards, .njs-proof-cards, .njs-projects-grid, .njs-gallery,
	.njs-party-packages, .njs-party-bring-grid, .njs-party-gallery) {
	grid-column: wide;
}

/* An EMPTY unclassed wrapper renders nothing but its inline padding: 87449
   stores three 16:9 video wrappers whose iframes are gone, each a 560px
   blank hole on the wide track (Task 4 review). Scoped to wrappers that
   reserve height through inline padding, so an ordinary empty div (and
   the gate's own track probe) is untouched. The content defect is flagged
   for Jay. This only stops the layout drawing the hole. */
.njs-layout .njs-flow div:not([class])[style*="padding-bottom"]:empty {
	display: none;
}

/* Bands and unclassed wrappers join the grid as subgrids, so their own
   children snap back onto the same tracks. Article: wide. Landing: full. */
.njs-layout .njs-flow > :is(.njs-band, .njs-party-band, section, div:not([class])) {
	grid-column: wide;
	display: grid;
	grid-template-columns: subgrid;
}

.njs-layout .njs-flow--landing > :is(.njs-band, .njs-party-band, section, div:not([class])) {
	grid-column: full;
}

.njs-layout .njs-flow > :is(.njs-band, .njs-party-band, section, div:not([class])) > * {
	grid-column: content;
	min-width: 0;
	margin-inline: 0;
}

.njs-layout .njs-flow > :is(.njs-band, .njs-party-band, section, div:not([class])) > :is(figure, img, iframe, video,
	.njs-video, .njs-table-wrapper, .njs-tiles, .njs-media-row, .njs-cards, .njs-gallery, .njs-hero-photo, .njs-wide-photo,
	.njs-shop, .njs-party-video, .njs-party-slots, .njs-party-row, .njs-party-split, .njs-party-wide-img,
	.njs-party-packages, .njs-party-bring-grid, .njs-party-gallery) {
	grid-column: feature;
}

/* Two-photo gallery captions (Jay, 2026-10-12, layout decision 18): the pair
   stays on the wide track, and each caption sits centered under its own photo
   with no left rule, so it reads as part of the photo instead of hanging at
   the photo's outer corner. Supersedes decision 17 (pairs on the text column). */
.njs-layout .njs-flow .njs-gallery--two figcaption {
	text-align: center;
	border-left: 0;
	padding-left: 0;
}

/* Photo rows (Jay, 2026-10-03, DECISIONS.md "Photo rows"): the row text stays
   on the text column's edges, and only the photo reaches into the margin, on
   its own side. Photo left: feature-start to content-end. Photo right (--flip):
   content-start to feature-end. Phones are unchanged, since the row stacks. */
.njs-layout .njs-flow > :is(.njs-media-row, .njs-party-row),
.njs-layout .njs-flow > :is(.njs-band, .njs-party-band, section, div:not([class])) > :is(.njs-media-row, .njs-party-row) {
	grid-column: feature-start / content-end;
}

.njs-layout .njs-flow > :is(.njs-media-row--flip, .njs-party-row--flip),
.njs-layout .njs-flow > :is(.njs-band, .njs-party-band, section, div:not([class])) > :is(.njs-media-row--flip, .njs-party-row--flip) {
	grid-column: content-start / feature-end;
}

/* Media fills its track. */
.njs-layout .njs-flow > :is(img, iframe, video),
.njs-layout .njs-flow > :is(.njs-band, .njs-party-band, section, div:not([class])) > :is(img, iframe, video),
.njs-layout .njs-flow :is(figure, .njs-video, .njs-party-video) > :is(img, iframe, video) {
	width: 100%;
	max-width: 100%;
	height: auto;
	display: block;
}

.njs-layout .njs-flow iframe {
	aspect-ratio: 16 / 9;
	height: auto;
	border: 0;
}

/* Feature photos never run taller than 3:2, so a portrait phone photo cannot
   take a whole screen (layout.css). */
.njs-layout .njs-flow > figure img,
.njs-layout .njs-flow > :is(.njs-band, .njs-party-band, section, div:not([class])) > figure img {
	aspect-ratio: 3 / 2;
	object-fit: cover;
}

/* A bare <img> placed directly in the flow (legacy posts, 19499) gets the
   same rhythm as a figure, so the next paragraph does not sit flush on it
   (Task 4 review). */
.njs-layout .njs-flow > img {
	margin-block: var(--space-lg);
}

/* Every boxed block gets the same vertical rhythm. */
.njs-layout .njs-flow > :is(figure, .njs-table-wrapper, .njs-cards, .njs-tiles, .njs-stats, .njs-party-packages, .njs-party-bring-grid, .njs-party-slots, .njs-party-stats),
.njs-layout .njs-flow > :is(.njs-band, .njs-party-band) > :is(figure, .njs-table-wrapper, .njs-cards, .njs-tiles, .njs-stats, .njs-party-packages, .njs-party-bring-grid, .njs-party-slots, .njs-party-stats) {
	margin-block: var(--space-lg);
}

/* ==========================================================================
   3. TYPE (C skin) and the locked body size
   ========================================================================== */

.njs-layout .njs-flow :is(p, li) {
	line-height: 1.7;
}

/* LOCKED: body text 18px from 1024px up, INCLUDING p/li inside the capsule,
   quick answer, notes and cards. Nothing below 1024 raises p/li (phones keep
   the theme's 16px). */
@media (min-width: 1024px) {
	.njs-layout .njs-flow :is(p, li):not(:where(figcaption, table, .njs-toc, .njs-mobile-toc) *) {
		font-size: 18px;
	}
}

/* GATE-FORCED (G-TYPE @390 and layout-lock-gate L2, 260927-cqn): below 1024px
   theme components set p/li to 14px (fact block, CTA phone line, procurement
   strip, proof cards) or heading sizes on p (h4-replacement, CTA heading, the
   statement line). Body text below 1024 is the theme body size (16px on
   phones), the same rule the desktop 18px already applies. Labels, table
   cells, captions and the TOC keep their own sizes. */
@media (max-width: 1023px) {
	.njs-layout .njs-flow :is(p, li):not(:where(figcaption, table, .njs-toc, .njs-mobile-toc) *) {
		font-size: var(--step-body);
	}
}

/* Inline font sizes baked into migrated post_content (87449 carries 0.9em,
   1.05em and 1.2em paragraphs) would otherwise escape the locked body size.
   The only CSS that outranks an inline style is !important, so it is used
   here and nowhere else, for p/li that carry an inline font-size. */
@media (min-width: 1024px) {
	.njs-layout .njs-flow :is(p, li)[style*="font-size"]:not(:where(figcaption, table, .njs-toc, .njs-mobile-toc, .njs-author-info) *) {
		font-size: 18px !important;
	}
}

@media (max-width: 1023px) {
	.njs-layout .njs-flow :is(p, li)[style*="font-size"]:not(:where(figcaption, table, .njs-toc, .njs-mobile-toc, .njs-author-info) *) {
		font-size: var(--step-body) !important;
	}
}

/* Numbered H2s (orange Barlow numerals). */
.njs-layout .njs-flow h2 {
	counter-increment: njs-sec;
	font-size: clamp(1.7rem, 1.2rem + 1.5vw, 2.5rem);
	font-weight: 700;
	line-height: 1.1;
	margin: var(--space-2xl) 0 var(--space-md);
	padding-top: var(--space-lg);
	border-top: 3px solid var(--color-ink);
}

/* theme.css .njs-body h2:first-of-type drops the rule. C keeps it. */
.njs-layout .njs-flow h2:first-of-type {
	border-top: 3px solid var(--color-ink);
	padding-top: var(--space-lg);
}

.njs-layout .njs-flow h2::before {
	content: counter(njs-sec, decimal-leading-zero);
	display: block;
	font-size: 1rem;
	letter-spacing: 2px;
	color: var(--njs-orange-text);
	margin-bottom: 6px;
}

.njs-layout .njs-flow h3 {
	font-size: 1.3rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.5px;
	margin: var(--space-xl) 0 var(--space-sm);
}

/* Content links: a darkened shade of the brand green (#416b2f, about 6.2:1
   on white). Only unclassed links: a component that owns its link styling
   (buttons, badges, the About review CTA, jump links) keeps it. */
.njs-layout .njs-flow:not(.njs-hero__flow) a:not([class]),
.njs-layout .njs-flow:not(.njs-hero__flow) a:not([class]):visited {
	color: #416b2f;
	text-decoration: underline;
}

.njs-layout .njs-flow:not(.njs-hero__flow) a:not([class]):hover,
.njs-layout .njs-flow:not(.njs-hero__flow) a:not([class]):focus-visible {
	color: #2c4a20;
	text-decoration: underline;
}

/* Bare .njs-btn (the converter's cta-button): theme.css draws it outlined in
   #76c355 (about 2.2:1). Same outline, in the darkened green. */
.njs-layout .njs-flow a.njs-btn:not(.njs-btn-primary):not(.njs-btn-secondary):not(.njs-btn-disabled),
.njs-layout .njs-flow a.njs-btn:not(.njs-btn-primary):not(.njs-btn-secondary):not(.njs-btn-disabled):visited {
	color: #416b2f;
	border-color: #416b2f;
	background-color: transparent;
}

.njs-layout .njs-flow a.njs-btn:not(.njs-btn-primary):not(.njs-btn-secondary):not(.njs-btn-disabled):hover,
.njs-layout .njs-flow a.njs-btn:not(.njs-btn-primary):not(.njs-btn-secondary):not(.njs-btn-disabled):focus-visible {
	color: #fff;
	background-color: #416b2f;
	border-color: #416b2f;
}

/* CTA phone links: theme.css means them to inherit the ink text (bold), but
   `.njs-body a` (0,1,1) out-ranks `.njs-cta-phone-link` (0,1,0) and paints
   them #76c355. Restore the ink. */
.njs-layout .njs-flow a.njs-cta-phone-link,
.njs-layout .njs-flow a.njs-cta-phone-link:visited,
.njs-layout .njs-flow a.njs-cta-phone-link:hover,
.njs-layout .njs-flow a.njs-cta-phone-link:focus-visible {
	color: var(--color-ink);
	font-weight: 700;
}

/* ...except on the dark CTA block (19517), whose background IS the ink, so
   the rule above painted the number ink on ink (1.00:1). Use the block's own
   light text color there. Scoped to .njs-cta-dark, so no other page moves. */
.njs-layout .njs-flow .njs-cta-dark a.njs-cta-phone-link,
.njs-layout .njs-flow .njs-cta-dark a.njs-cta-phone-link:visited,
.njs-layout .njs-flow .njs-cta-dark a.njs-cta-phone-link:hover,
.njs-layout .njs-flow .njs-cta-dark a.njs-cta-phone-link:focus-visible {
	color: var(--color-bg);
}

/* Faded text blocks: theme.css sets opacity 0.85 on .njs-cta-soft p and 0.8
   on the trust bar, which drops the links inside them under 4.5:1. */
.njs-layout .njs-flow .njs-cta-soft p,
.njs-layout .njs-flow .njs-trust-bar {
	opacity: 1;
}

/* In-body trust bar (87449): as a flex box its bare "from" text node became
   its own item, and theme.css's phone column rule stacked every fragment
   on its own line, a lone "·" included (Task 4 review). Inline text
   wraps as one centered sentence. The site-header trust bar is outside
   the flow and untouched. */
.njs-layout .njs-flow > .njs-trust-bar {
	display: block;
	line-height: 1.8;
}

.njs-layout .njs-flow > .njs-trust-bar .njs-trust-bar-divider {
	margin-inline: var(--space-sm);
}

/* CTA block (Task 4 visual review): the flow h3 rule's 32px top margin
   outranked theme.css's `.njs-cta-block h3 { margin: 0 ... }` and left a
   blank band above the heading. A line after the button sat flush on it. */
.njs-layout .njs-flow .njs-cta-block > :first-child {
	margin-top: 0;
}

.njs-layout .njs-flow .njs-cta-block > .njs-btn + p {
	margin-top: var(--space-sm);
}

/* Primary button text in ink (white on #f48e2e is about 2.4:1, ink about 7.3:1).
   The button form covers the quote form's Send (quick 261006-fcj). */
.njs-layout .njs-flow a.njs-btn-primary,
.njs-layout .njs-flow a.njs-btn-primary:visited,
.njs-layout .njs-flow a.njs-btn-primary:hover,
.njs-layout .njs-flow a.njs-btn-primary:focus-visible,
.njs-layout .njs-flow button.njs-btn-primary,
.njs-layout .njs-flow button.njs-btn-primary:hover,
.njs-layout .njs-flow button.njs-btn-primary:focus-visible {
	color: var(--color-ink);
	font-weight: 600;
}

/* Secondary buttons: theme.css paints them #76c355 text (about 2.2:1). */
.njs-layout .njs-flow a.njs-btn-secondary,
.njs-layout .njs-flow a.njs-btn-secondary:visited {
	color: #416b2f;
	border-color: #416b2f;
}

.njs-layout .njs-flow a.njs-btn-secondary:hover,
.njs-layout .njs-flow a.njs-btn-secondary:focus-visible {
	color: #fff;
	background: #416b2f;
	border-color: #416b2f;
}

.njs-layout .njs-flow figure img {
	border-radius: 4px;
}

.njs-layout .njs-flow figcaption {
	font-size: 14px;
	color: #5f5f5f;
	border-left: 3px solid var(--color-primary);
	padding-left: 10px;
	margin-top: var(--space-sm);
	/* theme.css centers .njs-content-image captions, which parted the text
	   from its left rule by ~140px on a feature-width photo (Task 4 review). */
	text-align: left;
	opacity: 1;
}

/* An inline `padding: 8px 0 0` (87449's Psagot caption) zeroes the gap to
   the rule. !important is the only CSS that outranks an inline style. */
.njs-layout .njs-flow figcaption[style*="padding"] {
	padding-left: 10px !important;
}

/* Single-photo captions (Jay, 2026-10-14, layout decision 21): a lone figure
   sits on the feature track, wider than the text, so a left-ruled caption
   hung at the photo's outer corner, far left of the text column. On a product
   render on white the photo's edge is invisible and the caption looked
   stranded. Same treatment as photo pairs (decision 18): centered under the
   photo, no left rule. Photo rows and media-row captions are unchanged. */
.njs-layout .njs-flow > figure > figcaption,
.njs-layout .njs-flow > :is(.njs-band, .njs-party-band, section, div:not([class])) > figure > figcaption,
.njs-layout .njs-flow > figure > figcaption[style*="padding"],
.njs-layout .njs-flow > :is(.njs-band, .njs-party-band, section, div:not([class])) > figure > figcaption[style*="padding"] {
	text-align: center;
	border-left: 0;
	padding-left: 0 !important;
}

/* Small orange text on light backgrounds (the About review stars) uses the
   darkened orange. */
.njs-layout .njs-flow :is(.njs-stars, .njs-trust-bar-stars, .njs-trust-star) {
	color: var(--njs-orange-text);
}

/* ==========================================================================
   4. C SKIN COMPONENTS (theme components, restyled)
   ========================================================================== */

/* ---- Answer capsule ----
   GATE-FORCED (layout-lock-gate L2 @390 on 19465, 260927-cqn): C's 1.15rem
   capsule text reached its <p> at 18.4px on phones. The capsule takes the body
   size (16px phones, 18px from 1024px) and keeps C's weight 500 and bold
   first line. See render/out/derived-adjustments.json. */
.njs-layout .njs-flow .njs-answer-capsule {
	background: transparent;
	border: 0;
	padding: 0;
	font-size: var(--step-body);
	line-height: 1.65;
	font-weight: 500;
	margin: 0 0 var(--space-xl);
}

@media (min-width: 1024px) {
	.njs-layout .njs-flow .njs-answer-capsule {
		font-size: 18px;
	}
}

.njs-layout .njs-flow .njs-answer-capsule::first-line {
	font-weight: 700;
}

/* Grid items do not collapse margins: the capsule's last <p> margin stacked
   on the capsule's own and the next H2's, a ~96px gap on About (Task 4). */
.njs-layout .njs-flow .njs-answer-capsule > p:last-child {
	margin-bottom: 0;
}

/* ---- Quick answer: ink border and an ink label ---- */
.njs-layout .njs-flow .njs-quick-answer {
	background: #fff;
	border: 2px solid var(--color-ink);
	padding: var(--space-md) var(--space-lg);
	margin: 0 0 var(--space-lg);
}

.njs-layout .njs-flow .njs-quick-answer::before {
	content: "Quick Answer";
	display: inline;
	background: var(--color-ink);
	color: #fff;
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	padding: 2px 8px;
	margin-right: 8px;
}

/* ---- Author box: 88px photo, neutral, orange top rule, ink badges ---- */
.njs-layout .njs-flow .njs-author-box {
	display: grid;
	grid-template-columns: 88px minmax(0, 1fr);
	gap: var(--space-lg);
	align-items: start;
	background: var(--color-neutral);
	border: 0;
	border-top: 3px solid var(--color-primary);
	padding: var(--space-lg);
	margin: 0 0 var(--space-xl);
}

.njs-layout .njs-flow .njs-author-box .njs-author-photo {
	width: 88px;
	height: 88px;
}

.njs-layout .njs-flow .njs-author-box .njs-author-info p {
	opacity: 1;
	color: var(--color-ink);
}

.njs-layout .njs-flow a.njs-credential-badge,
.njs-layout .njs-flow a.njs-credential-badge:visited,
.njs-layout .njs-flow a.njs-credential-badge:hover,
.njs-layout .njs-flow a.njs-credential-badge:focus-visible {
	background: var(--color-ink);
	color: #fff;
	opacity: 1;
	border-radius: 2px;
	padding: 5px 12px;
	letter-spacing: 0.4px;
	text-decoration: none;
}

.njs-layout .njs-flow a.njs-credential-badge:hover,
.njs-layout .njs-flow a.njs-credential-badge:focus-visible {
	text-decoration: underline;
}

/* ---- End-of-guide "About Jay" bio (decision 8) ----
   The converter only renames existing tokens, so the bare <img> and the
   unclassed wrapper <div> are styled structurally. CSS only. */
.njs-layout .njs-flow .njs-author-bio-extended {
	display: grid;
	grid-template-columns: 88px minmax(0, 1fr);
	gap: var(--space-lg);
	align-items: start;
	background: var(--color-neutral);
	border: 0;
	border-top: 3px solid var(--color-primary);
	padding: var(--space-lg);
	margin: var(--space-2xl) 0 var(--space-xl);
	text-align: left;
}

.njs-layout .njs-flow .njs-author-bio-extended > img {
	width: 88px;
	height: 88px;
	max-width: none;
	border-radius: 50%;
	object-fit: cover;
	object-position: center top;
	background: var(--color-divider);
}

.njs-layout .njs-flow .njs-author-bio-extended > div:not([class]) {
	min-width: 0;
}

.njs-layout .njs-flow .njs-author-bio-extended h3 {
	margin: 0 0 var(--space-sm);
	font-size: 1.35rem;
	text-transform: none;
	letter-spacing: 0;
}

.njs-layout .njs-flow .njs-author-bio-extended p {
	margin: 0 0 var(--space-sm);
	opacity: 1;
	color: var(--color-ink);
}

/* ---- Tables: ink rule under the header, no zebra ---- */
.njs-layout .njs-flow .njs-table th {
	background: var(--color-neutral);
	color: var(--color-ink);
	border-bottom: 3px solid var(--color-ink);
	font-family: var(--font-heading);
	font-size: 1rem;
	letter-spacing: 0.5px;
	text-transform: uppercase;
	padding: 12px 16px;
	white-space: normal;
}

.njs-layout .njs-flow .njs-table td {
	padding: 12px 16px;
	border-bottom: 1px solid var(--color-divider);
	overflow-wrap: anywhere;
}

.njs-layout .njs-flow .njs-table tr:nth-child(even) {
	background: transparent;
}

/* Row-header cells (About "Key Facts": a th per row, no thead) take the
   row hairline, not the 3px ink header rule, so label and value share one
   line per row (Task 4 review). */
.njs-layout .njs-flow .njs-table tbody th,
.njs-layout .njs-flow .njs-table tr > th + td {
	border-bottom: 1px solid var(--color-divider);
}

/* Phones: wide tables fit the column instead of running past the viewport
   (GATE-FORCED, layout-lock-gate L5 @390 on 87495's 6-column table). Fixed
   layout splits the width evenly and long words wrap inside their cell.
   Task 4 review: cell padding drops to 6px a side and the header label to
   0.85rem on phones, which gives each column back about 20px, so fewer words
   break mid-letter. Auto layout was tried and starved the short columns. */
@media (max-width: 767px) {
	.njs-layout .njs-flow .njs-table {
		table-layout: fixed;
		width: 100%;
	}

	.njs-layout .njs-flow .njs-table :is(th, td, caption) {
		overflow-wrap: anywhere;
		hyphens: auto;
	}

	.njs-layout .njs-flow .njs-table th {
		letter-spacing: 0;
		font-size: 0.85rem;
	}

	/* Tables under 5 columns (2026-10-03): auto layout and whole-word wrapping.
	   Equal split starved the long column of 82035's 3-column table into
	   "mini-mum" / "con-struction". Measured on all 9 published table pages at
	   390: no overflow, no mid-word breaks. 5+ columns keep the rule above. */
	.njs-layout .njs-flow .njs-table:not(:has(tr > :nth-child(5))) {
		table-layout: auto;
	}

	.njs-layout .njs-flow .njs-table:not(:has(tr > :nth-child(5))) :is(th, td, caption) {
		overflow-wrap: break-word;
		hyphens: manual;
	}
}

/* Commercial proof cards (template-parts/project-proof-cards.php): theme.css
   sets the blurb to 14px. GATE-FORCED (layout-lock-gate L2 @390 on 87449): it
   takes the body size below 1024px. From 1024px the locked 18px rule applies. */
@media (max-width: 1023px) {
	.njs-layout .njs-flow .njs-proof-card__blurb {
		font-size: var(--step-body);
	}
}

/* ---- Mobile TOC: shown in the flow below 1120px, hidden where the rail shows ---- */
.njs-layout .njs-mobile-toc {
	display: block;
	background: #fff;
	border: 2px solid var(--color-ink);
	margin: 0 0 var(--space-lg);
}

@media (min-width: 1120px) {
	.njs-layout .njs-mobile-toc {
		display: none;
	}
}

/* ---- Rail: numbered TOC and the ink "Ready to Start?" box ---- */
.njs-layout .njs-sidebar .njs-toc {
	background: transparent;
	border: 0;
	padding: 0;
	margin: 0;
}

.njs-layout .njs-toc-title {
	font-family: var(--font-heading);
	font-size: 14px;
	font-weight: 700;
	letter-spacing: 2px;
	text-transform: uppercase;
	color: var(--njs-orange-text);
	opacity: 1; /* theme.css 0.65 drops the dark orange from about 6.7:1 to about 3.1:1 */
	margin: 0 0 var(--space-sm);
	padding-bottom: 0;
	border-bottom: 0;
}

.njs-layout .njs-toc-list {
	counter-reset: njs-toc;
}

.njs-layout .njs-toc-list li {
	counter-increment: njs-toc;
	margin-bottom: 2px;
}

.njs-layout .njs-toc-list a,
.njs-layout .njs-toc-list a:visited {
	display: block;
	color: #3a3a3a;
	opacity: 1;
	font-size: 14px;
	line-height: 1.45;
	padding: 6px 0 6px 10px;
	border-left: 3px solid transparent;
	text-decoration: none;
}

.njs-layout .njs-toc-list a::before {
	content: counter(njs-toc, decimal-leading-zero) "  ";
	white-space: pre;
	font-family: var(--font-heading);
	color: #666;
}

.njs-layout .njs-toc-list a:hover,
.njs-layout .njs-toc-list a:focus-visible {
	color: var(--color-ink);
	background: var(--color-neutral);
	border-left-color: var(--color-primary);
	opacity: 1;
	text-decoration: none;
}

.njs-layout .njs-mobile-toc summary {
	font-family: var(--font-heading);
	font-size: 14px;
	font-weight: 700;
	letter-spacing: 1.2px;
	text-transform: uppercase;
	padding: var(--space-md) var(--space-lg);
}

.njs-layout .njs-mobile-toc .njs-toc-list {
	list-style: none;
	margin: 0;
	padding: 0 var(--space-lg) var(--space-md);
}

/* ---- 261012-ptb: phone TOC summary row, label + muted section count + chevron (Jay's option A,
   2026-10-12; design = .planning/quick/261012-ptb-phone-on-this-page-box-arrow-section-cou/evidence/mock.html .b) ---- */
.njs-layout .njs-mobile-toc__bar {
	display: flex;
	align-items: center;
}

.njs-layout .njs-mobile-toc__count {
	margin-left: auto;
	margin-right: 12px;
	font-size: 14px;
	font-weight: 500;
	letter-spacing: 0.5px;
	text-transform: none;
	color: #666;
	white-space: nowrap;
}

.njs-layout .njs-mobile-toc__bar::after {
	content: "";
	flex: none;
	box-sizing: content-box;
	width: 9px;
	height: 9px;
	border-right: 2.5px solid var(--color-ink);
	border-bottom: 2.5px solid var(--color-ink);
	transform: rotate(45deg) translateY(-3px);
}

.njs-layout .njs-mobile-toc[open] .njs-mobile-toc__bar::after {
	transform: rotate(-135deg) translateY(-1px);
}

@media (prefers-reduced-motion: no-preference) {
	.njs-layout .njs-mobile-toc__bar::after {
		transition: transform 0.15s;
	}
}

/* List links in the phone box match the rail and the approved mock (Jay
   2026-10-12): grey, no underline. The box sits inside .njs-flow, so the
   content-link rule (0,4,1) would otherwise turn them green and underlined. */
.njs-layout .njs-flow .njs-mobile-toc .njs-toc-list a:not([class]),
.njs-layout .njs-flow .njs-mobile-toc .njs-toc-list a:not([class]):visited {
	color: #3a3a3a;
	text-decoration: none;
}

.njs-layout .njs-flow .njs-mobile-toc .njs-toc-list a:not([class]):hover,
.njs-layout .njs-flow .njs-mobile-toc .njs-toc-list a:not([class]):focus-visible {
	color: var(--color-ink);
	background: var(--color-neutral);
	border-left-color: var(--color-primary);
	text-decoration: none;
}
/* ---- end 261012-ptb ---- */

/* The rail scrolls inside itself when a long TOC outgrows the viewport
   (87473: 11 sections). Pin the call box to the bottom of that scroll box
   so the phone number never sits below the fold of the rail. */
.njs-layout .njs-sidebar .njs-sidebar-cta {
	position: sticky;
	bottom: 0;
}

.njs-layout .njs-sidebar-cta {
	margin-top: var(--space-xl);
	padding: var(--space-lg);
	background: var(--color-ink);
	color: #fff;
	border: 0;
	text-align: left;
}

.njs-layout .njs-sidebar-cta .njs-sidebar-cta-heading {
	color: #fff;
	font-family: var(--font-heading);
	font-weight: 700;
	font-size: 1.15rem;
	letter-spacing: 0.5px;
	margin: 0 0 var(--space-sm);
	opacity: 1;
}

.njs-layout .njs-sidebar-cta a:not(.njs-btn),
.njs-layout .njs-sidebar-cta a:not(.njs-btn):visited,
.njs-layout .njs-sidebar-cta a:not(.njs-btn):hover,
.njs-layout .njs-sidebar-cta a:not(.njs-btn):focus-visible {
	color: #fff;
	font-weight: 600;
	opacity: 1;
	margin: 0 0 var(--space-sm);
}

.njs-layout .njs-sidebar-cta a:not(.njs-btn):hover,
.njs-layout .njs-sidebar-cta a:not(.njs-btn):focus-visible {
	text-decoration: underline;
}

.njs-layout .njs-sidebar-cta .njs-sidebar-cta-note {
	color: rgba(255, 255, 255, 0.85);
	opacity: 1; /* theme.css 0.65 */
	font-size: 14px;
	margin: var(--space-sm) 0 0;
}

/* ==========================================================================
   5. SHARED LANDING COMPONENTS (promoted from party.css, decision 2)
   Generic njs-* names for new content. The .njs-party-* names are selector
   ALIASES only, so the locked 19459 markup keeps rendering with no content
   write. C-skin values, not party.css's orange/green tints.
   Example markup: docs/frameworks/WORDPRESS_CONTENT_AUTHORING_SPEC.md,
   "Landing components (content.css, 260927-cqn)".
   ========================================================================== */

/* ---- Band (section background) ---- */
.njs-layout .njs-flow > :is(.njs-band, .njs-party-band) {
	background: var(--color-neutral);
	padding-block: var(--space-2xl);
	margin-block: var(--space-2xl);
	border: 0;
	border-radius: 0;
}

.njs-layout .njs-flow--landing > :is(.njs-band, .njs-party-band) {
	margin-block: 0;
}

/* Variants. C drops party.css's tints: --orange and --neutral are the neutral
   ground, --green is white, so three bands in a row alternate (the homepage
   rhythm), and --ink is the dark band. */
.njs-layout .njs-flow > :is(.njs-band--orange, .njs-party-band--party, .njs-band--neutral, .njs-party-band--group) {
	background: var(--color-neutral);
}

.njs-layout .njs-flow > :is(.njs-band--green, .njs-party-band--play) {
	background: #fff;
}

.njs-layout .njs-flow > :is(.njs-band--ink) {
	background: var(--color-ink);
	color: #fff;
}

/* Band head: a normal numbered C heading with its own padding (never
   party.css's negative-margin banner, which breaks inside a subgrid). */
.njs-layout .njs-flow > :is(.njs-band, .njs-party-band) > h2:first-child {
	margin-top: 0;
	background: transparent;
	color: var(--color-ink);
	border-radius: 0;
	font-size: clamp(1.7rem, 1.2rem + 1.5vw, 2.5rem);
}

.njs-layout .njs-flow > :is(.njs-band, .njs-party-band) > :last-child {
	margin-bottom: 0;
}

.njs-layout .njs-flow > .njs-band--ink :is(h2, h3) {
	color: #fff;
}

.njs-layout .njs-flow > .njs-band--ink h2 {
	border-top-color: var(--color-primary);
}

.njs-layout .njs-flow > .njs-band--ink h2::before {
	color: var(--color-primary);
}

.njs-layout .njs-flow > .njs-band--ink a:not([class]) {
	color: #fff;
}

.njs-layout .njs-flow > .njs-band--ink :is(.njs-card, .njs-stat, .njs-tile) {
	color: var(--color-ink);
}

/* White blocks inside a neutral band. */
.njs-layout .njs-flow > :is(.njs-band, .njs-party-band) :is(.njs-quick-answer, .njs-cta-soft) {
	background: #fff;
}

/* ---- Jump bar: ink, sticky under the header ---- */
.njs-layout .njs-flow > :is(.njs-jump, .njs-party-jump) {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-sm) var(--space-md);
	align-items: center;
	background: var(--color-ink);
	margin: 0 0 var(--space-lg);
	padding: 10px var(--space-md);
	position: sticky;
	top: 88px;
	z-index: 5;
}

/* Landing: the bar runs full-bleed, its links start on the text edge. */
.njs-layout .njs-flow--landing > :is(.njs-jump, .njs-party-jump) {
	grid-column: full;
	margin: 0;
	padding-inline: max(var(--njs-gutter), calc((100% - var(--njs-measure)) / 2));
}

.njs-layout .njs-flow :is(.njs-jump, .njs-party-jump) a,
.njs-layout .njs-flow :is(.njs-jump, .njs-party-jump) a:visited,
.njs-layout .njs-flow a:is(.njs-jump__link, .njs-party-jump__link) {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 8px 4px;
	color: #fff;
	font-family: var(--font-heading);
	font-size: 15px;
	font-weight: 700;
	letter-spacing: 1px;
	text-transform: uppercase;
	text-decoration: none;
	border: 0;
	border-bottom: 3px solid transparent;
	border-radius: 0;
	background: transparent;
	box-shadow: none;
}

.njs-layout .njs-flow :is(.njs-jump, .njs-party-jump) a:first-child {
	border-bottom-color: var(--color-primary);
}

.njs-layout .njs-flow :is(.njs-jump, .njs-party-jump) a:hover,
.njs-layout .njs-flow :is(.njs-jump, .njs-party-jump) a:focus-visible {
	color: #fff;
	border-bottom-color: var(--color-primary);
}

/* ---- Cards ---- */
.njs-layout :is(.njs-cards, .njs-party-packages, .njs-party-bring-grid) {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--space-lg);
	align-items: stretch;
}

.njs-layout :is(.njs-card, .njs-party-card, .njs-party-bring-card) {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: #fff;
	border: 0;
	border-top: 3px solid var(--color-ink);
	border-radius: 0;
	box-shadow: none;
}

.njs-layout :is(.njs-card--accent, .njs-party-card--diy) {
	border-top-color: var(--color-ink);
}

.njs-layout :is(.njs-card--primary, .njs-party-card--full) {
	border-top-color: var(--color-primary);
}

.njs-layout :is(.njs-card__img, .njs-party-card__img, .njs-party-bring-card__img) {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 3 / 2;
	object-fit: cover;
	border-radius: 0;
}

.njs-layout :is(.njs-card__body, .njs-party-card__body) {
	padding: var(--space-lg);
}

.njs-layout .njs-party-bring-card > p {
	margin: 0;
	padding: var(--space-md);
}

.njs-layout .njs-party-bring-card--text {
	justify-content: center;
}

.njs-layout .njs-flow :is(.njs-card, .njs-party-card) h3 {
	margin-top: 0;
	text-transform: none;
	letter-spacing: 0;
	font-size: 1.35rem;
}

/* ---- Project cards (job tiles). Jay, 2026-10-09 (JOB-TILES-RESTYLE):
   category label, bold job name, town tag, one-line scope. Same words as
   the plain card, the markup just separates them. ---- */
.njs-layout .njs-cards--projects .njs-card__body {
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding: var(--space-md) var(--space-lg) var(--space-lg);
}

.njs-layout .njs-cards--projects .njs-card__label {
	margin: 0;
	font-family: var(--font-heading);
	font-size: 0.85rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: #416b2f;
}

.njs-layout .njs-cards--projects .njs-card__title {
	margin: 0;
	font-family: var(--font-heading);
	font-size: 1.6rem;
	font-weight: 700;
	line-height: 1.1;
	color: var(--color-ink);
}

.njs-layout .njs-cards--projects .njs-card__meta {
	margin: 0 0 6px;
	font-size: 0.9rem;
	color: #5f5f5f;
}

.njs-layout .njs-cards--projects .njs-card__text {
	margin: 0;
}

/* ---- Price ---- */
.njs-layout :is(.njs-price, .njs-party-price) {
	display: flex;
	flex-direction: column;
	gap: 4px;
	margin: 0 0 var(--space-md);
	padding: 10px 14px;
	background: var(--color-neutral);
	border-left: 4px solid var(--color-primary);
	border-radius: 0;
	font-weight: 600;
}

.njs-layout :is(.njs-price__row, .njs-party-price__row) {
	display: flex;
	gap: 8px;
	align-items: baseline;
}

.njs-layout :is(.njs-price__amount, .njs-party-price__amount) {
	font-family: var(--font-heading);
	font-size: 1.6rem;
	line-height: 1.1;
	min-width: 3.2em;
}

/* ---- Checks ---- */
.njs-layout :is(.njs-checks, .njs-party-checks) {
	list-style: none;
	margin: 0;
	padding: 0;
}

.njs-layout :is(.njs-checks, .njs-party-checks) li {
	position: relative;
	padding-left: 30px;
	margin-bottom: var(--space-sm);
}

.njs-layout :is(.njs-checks, .njs-party-checks) li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 5px;
	width: 18px;
	height: 18px;
	border-radius: 50%;
	background: var(--color-ink);
	-webkit-mask: none;
	mask: none;
}

.njs-layout :is(.njs-checks, .njs-party-checks) li::after {
	content: "";
	position: absolute;
	left: 6px;
	top: 8px;
	width: 6px;
	height: 10px;
	border: solid #fff;
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
}

/* ---- Stats ---- */
.njs-layout :is(.njs-stats, .njs-party-stats) {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--space-md);
}

.njs-layout :is(.njs-stat, .njs-party-stat) {
	margin: 0;
	padding: var(--space-md);
	text-align: center;
	background: #fff;
	border: 0;
	border-bottom: 4px solid var(--color-primary);
	border-radius: 0;
	font-weight: 600;
	line-height: 1.3;
}

.njs-layout :is(.njs-stat__big, .njs-party-stat__big) {
	display: block;
	font-family: var(--font-heading);
	font-size: 3rem;
	line-height: 1.05;
}

/* ---- Tiles (time slots) ---- */
.njs-layout :is(.njs-tiles, .njs-party-slots) {
	list-style: none;
	margin: 0 0 var(--space-lg);
	padding: 0;
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--space-sm);
}

.njs-layout :is(.njs-tile, .njs-party-slot) {
	margin: 0;
	padding: var(--space-md) var(--space-sm);
	text-align: center;
	background: #fff;
	border: 0;
	border-top: 3px solid var(--color-ink);
	border-radius: 0;
	box-shadow: none;
}

.njs-layout :is(.njs-tile--am, .njs-party-slot--morning) {
	border-top-color: var(--color-primary);
}

.njs-layout :is(.njs-tile__time, .njs-party-slot__time) {
	display: block;
	font-family: var(--font-heading);
	font-size: 1.2rem;
	line-height: 1.25;
}

.njs-layout :is(.njs-tile__tag, .njs-party-slot__tag) {
	display: inline-block;
	margin-top: 6px;
	padding: 0;
	background: transparent;
	color: #5f5f5f;
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.5px;
	text-transform: uppercase;
}

/* ---- Media row (photo + text) ---- */
.njs-layout :is(.njs-media-row, .njs-party-row, .njs-party-split) {
	display: grid;
	grid-template-columns: 2fr 3fr;
	gap: var(--space-lg);
	align-items: center;
	margin: var(--space-md) 0 var(--space-lg);
}

.njs-layout :is(.njs-media-row--flip, .njs-party-row--flip) {
	grid-template-columns: 3fr 2fr;
}

.njs-layout :is(.njs-media-row--flip, .njs-party-row--flip) > :is(.njs-media-row__img, .njs-party-row__img) {
	order: 2;
}

.njs-layout :is(.njs-media-row__img, .njs-party-row__img, .njs-party-split__img) {
	display: block;
	width: 100%;
	height: 280px;
	object-fit: cover;
	border: 0;
	border-radius: 4px;
	box-shadow: none;
}

.njs-layout :is(.njs-media-row__body, .njs-party-row__body) > p:last-child {
	margin-bottom: 0;
}

/* Wrap photo rows (Jay, 2026-10-14, DECISIONS.md decision 20). The text flows
   around the photo, then continues under it at full width, so a photo never
   leaves a gap after short text. The row sits on the text column, and only the
   photo reaches into the margin on its own side (decision 16 still holds).
   Paragraph spacing is the normal 16px, and the text starts level with the photo
   top. The markup groups a photo with every paragraph of its topic, up to the
   next photo or heading. Opt-in: rows without --wrap render as before. */
.njs-layout .njs-flow > .njs-media-row--wrap,
.njs-layout .njs-flow > :is(.njs-band, section, div:not([class])) > .njs-media-row--wrap {
	grid-column: content-start / content-end;
}

.njs-layout .njs-media-row--wrap {
	display: flow-root;
	margin: 0 0 var(--space-md);
}

.njs-layout .njs-media-row--wrap > .njs-media-row__img {
	float: left;
	width: calc(var(--njs-feature-pad) + 11rem);
	height: 280px;
	margin: 6px var(--space-lg) var(--space-sm) calc(-1 * var(--njs-feature-pad));
}

.njs-layout .njs-media-row--wrap.njs-media-row--flip > .njs-media-row__img {
	float: right;
	margin: 6px calc(-1 * var(--njs-feature-pad)) var(--space-sm) var(--space-lg);
}

@media (max-width: 700px) {
	.njs-layout .njs-media-row--wrap > .njs-media-row__img,
	.njs-layout .njs-media-row--wrap.njs-media-row--flip > .njs-media-row__img {
		float: none;
		width: 100%;
		height: 230px;
		margin: 0 0 var(--space-md);
	}
}

/* ---- Notes ---- */
.njs-layout :is(.njs-note, .njs-party-note, .njs-party-card-extra, .njs-party-where) {
	padding: var(--space-md) var(--space-lg);
	margin: 0 0 var(--space-lg);
	background: #fff;
	border-left: 4px solid var(--color-primary);
	border-radius: 0;
}

/* A note directly in the (white) flow gets the neutral ground. */
.njs-layout .njs-flow > :is(.njs-note, .njs-party-note, .njs-party-card-extra, .njs-party-where) {
	background: var(--color-neutral);
}

.njs-layout :is(.njs-note--rule, .njs-party-note--rule) {
	border-left-color: var(--color-ink);
}

.njs-layout :is(.njs-note--no, .njs-party-note--no) {
	border-left-color: var(--color-sale);
}

.njs-layout :is(.njs-note--play, .njs-party-note--play, .njs-party-where) {
	border-left-color: var(--color-accent);
}

.njs-layout :is(.njs-note, .njs-party-note, .njs-party-card-extra, .njs-party-where) > p:last-child {
	margin-bottom: 0;
}

.njs-layout .njs-party-where__address strong {
	font-size: 1.1em;
}

/* ---- Statement (a display line) ---- */
.njs-layout :is(.njs-statement, .njs-party-callout) {
	font-family: var(--font-heading);
	font-size: var(--step-heading);
	line-height: 1.3;
	padding: var(--space-md) 0 var(--space-md) var(--space-lg);
	margin: var(--space-lg) 0;
	background: transparent;
	border-left: 4px solid var(--color-ink);
	border-radius: 0;
}

/* ---- Quote ---- */
.njs-layout :is(.njs-quote, .njs-party-quote) {
	position: relative;
	margin: var(--space-xl) 0;
	padding: var(--space-lg) var(--space-lg) var(--space-lg) calc(var(--space-lg) + 36px);
	background: #fff;
	border: 0;
	border-left: 3px solid var(--color-ink);
	border-radius: 0;
	box-shadow: none;
	font-style: normal;
}

.njs-layout .njs-flow > :is(.njs-quote, .njs-party-quote) {
	background: var(--color-neutral);
}

.njs-layout :is(.njs-quote, .njs-party-quote)::before {
	content: "\201C";
	position: absolute;
	left: 14px;
	top: 6px;
	font-family: var(--font-heading);
	font-size: 4rem;
	line-height: 1;
	color: var(--color-primary);
}

.njs-layout :is(.njs-quote__who, .njs-party-quote__who) {
	margin: 0;
	font-weight: 700;
}

/* ---- Fact grid (not the bordered .njs-fact-block list) ---- */
.njs-layout :is(.njs-fact-grid, .njs-party-facts) {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--space-md);
	margin: var(--space-md) 0 var(--space-lg);
}

.njs-layout :is(.njs-fact-grid--two, .njs-party-facts--two) {
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

.njs-layout :is(.njs-fact-tile, .njs-party-fact) {
	padding: var(--space-md);
	background: #fff;
	border: 0;
	border-top: 3px solid var(--color-ink);
	border-radius: 0;
	box-shadow: none;
}

.njs-layout :is(.njs-fact-tile, .njs-party-fact) > p:last-child {
	margin-bottom: 0;
}

.njs-layout .njs-flow :is(.njs-fact-tile__label, .njs-party-fact__label) {
	display: inline-block;
	font-family: var(--font-heading);
	font-size: 1.2rem;
	font-weight: 700;
	letter-spacing: 1px;
	text-transform: uppercase;
	margin-bottom: var(--space-sm);
	padding-bottom: 6px;
	border-bottom: 3px solid var(--color-primary);
}

/* ---- Photos, gallery, video, list tiles ---- */
.njs-layout :is(.njs-hero-photo, .njs-party-hero) {
	margin: 0 0 var(--space-lg);
	border: 0;
	border-radius: 0;
	box-shadow: none;
	overflow: hidden;
}

.njs-layout :is(.njs-hero-photo, .njs-party-hero) img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 1920 / 1012;
	object-fit: cover;
}

.njs-layout :is(.njs-wide-photo, .njs-party-wide-img) {
	display: block;
	width: 100%;
	height: auto;
	margin: 0 0 var(--space-lg);
	border-radius: 4px;
	box-shadow: none;
}

.njs-layout :is(.njs-gallery, .njs-party-gallery) {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--space-sm);
	margin: var(--space-md) 0 var(--space-lg);
}

.njs-layout :is(.njs-gallery, .njs-party-gallery) img {
	display: block;
	width: 100%;
	height: 220px;
	object-fit: cover;
	border-radius: 4px;
}

.njs-layout :is(.njs-gallery, .njs-party-gallery) img:is(.njs-gallery__wide, .njs-party-gallery__wide) {
	grid-column: 1 / -1;
	height: 320px;
}

/* Two-photo gallery: a pair of equal photos on one row (24-07). */
.njs-layout .njs-gallery--two {
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

.njs-layout .njs-gallery--two img {
	height: 260px;
}

.njs-layout :is(.njs-video, .njs-party-video) {
	margin: var(--space-lg) 0;
	border-radius: 0;
	box-shadow: none;
	overflow: hidden;
	line-height: 0;
}

.njs-layout :is(.njs-list-tiles, .njs-party-bring) {
	list-style: none;
	margin-left: 0;
	padding: 0;
}

.njs-layout :is(.njs-list-tiles, .njs-party-bring) li {
	padding: var(--space-sm) var(--space-md);
	margin-bottom: var(--space-sm);
	background: #fff;
	border-left: 4px solid var(--color-accent);
	border-radius: 0;
}

.njs-layout :is(.njs-list-tiles, .njs-party-bring) li:is(.njs-list-tiles__no, .njs-party-bring__no) {
	border-left-color: var(--color-sale);
}

/* party.css kept only padding on the numbered list. */
.njs-layout ol.njs-party-numbered li {
	padding-left: 4px;
}

/* ---- Shop box, "Shelf" (Jay chose design B, quick 261006-shp) ----
   A short row of category links between the capsule and the first H2. Each
   link is a product cut-out on a neutral tile with the category name under
   it. It sits on the feature track (declared breakouts, section 3), so it
   breaks out symmetrically on the text column's center line. 2 to 6 links:
   up to 4 sit on one row, 5 or 6 go in rows of 3 (5 reads 3 + 2, the short
   row centered). multiply blends the white product backgrounds into the tile.
   Markup: WORDPRESS_CONTENT_AUTHORING_SPEC.md, "Shop box". */
/* Bottom margin = the capsule's (--space-xl): on rail pages the theme puts the
   author box right after the shop box, and margin 0 left the two touching. */
.njs-layout .njs-flow .njs-shop {
	margin: 0 0 var(--space-xl);
	display: grid;
	justify-items: center;
}

.njs-layout .njs-flow .njs-shop__label {
	display: block;
	margin: 0 0 var(--space-md);
	font-family: var(--font-heading);
	font-size: 26px;
	font-weight: 600;
	line-height: 1.1;
	letter-spacing: 0.01em;
	color: var(--color-ink);
	text-align: center;
}

.njs-layout .njs-flow .njs-shop__links {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--space-md);
	width: 100%;
}

.njs-layout .njs-flow .njs-shop__link {
	flex: 0 1 232px;
	min-width: 0;
}

.njs-layout .njs-flow .njs-shop__links:has(> :nth-child(5)) > .njs-shop__link {
	flex-basis: 290px;
}

.njs-layout .njs-flow a.njs-shop__link,
.njs-layout .njs-flow a.njs-shop__link:visited {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-sm);
	padding: var(--space-md) var(--space-md) var(--space-lg);
	background: var(--color-neutral);
	border-radius: var(--radius-sm);
	color: var(--color-ink);
	text-decoration: none;
	overflow: hidden;
}

.njs-layout .njs-flow .njs-shop__img {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 3;
	height: auto;
	max-width: none;
	object-fit: contain;
	padding: 4%;
	mix-blend-mode: multiply;
	transition: transform 0.35s cubic-bezier(.2, .7, .2, 1);
}

.njs-layout .njs-flow .njs-shop__name {
	font-family: var(--font-heading);
	font-size: 21px;
	font-weight: 600;
	line-height: 1.15;
	letter-spacing: 0.01em;
	text-align: center;
	text-decoration: underline;
	text-decoration-color: transparent;
	text-decoration-thickness: 2px;
	text-underline-offset: 4px;
	transition: text-decoration-color 0.2s ease;
}

.njs-layout .njs-flow a.njs-shop__link:hover .njs-shop__img {
	transform: scale(1.06);
}

.njs-layout .njs-flow a.njs-shop__link:hover .njs-shop__name {
	text-decoration-color: currentColor;
}

.njs-layout .njs-flow a.njs-shop__link:focus-visible {
	outline: 3px solid var(--color-ink);
	outline-offset: 3px;
}

/* Phones: two tiles per row. */
@media (max-width: 599px) {
	.njs-layout .njs-flow .njs-shop__label {
		font-size: 23px;
	}

	.njs-layout .njs-flow .njs-shop__links {
		gap: 12px;
	}

	.njs-layout .njs-flow .njs-shop__links > .njs-shop__link,
	.njs-layout .njs-flow .njs-shop__links:has(> :nth-child(5)) > .njs-shop__link {
		flex-basis: calc(50% - 6px);
	}

	.njs-layout .njs-flow a.njs-shop__link,
	.njs-layout .njs-flow a.njs-shop__link:visited {
		padding: 12px 12px var(--space-md);
	}

	.njs-layout .njs-flow .njs-shop__name {
		font-size: 19px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.njs-layout .njs-flow .njs-shop__img,
	.njs-layout .njs-flow .njs-shop__name {
		transition: none;
	}
}

/* ---- Quote form (quick 261006-fcj) ----
   [njs_quote_form] (inc/quote-form.php), open inside a .njs-cta-soft box after
   .njs-cta-buttons, as in Jay's approved mockup (form-mockup-approved.jpg,
   2026-09-30): a divider, a plain heading, Name / School, town or organization /
   Email / Phone in two columns when the box is wide enough (one column on
   phones), the message across the full row, orange Send, the note under it.
   Contrast (AA): labels ink, the asterisk #b3261e (5.9:1 on --color-neutral),
   placeholder #6b6b6b (5.3:1 on white), input borders #858585 (3.7:1 on white,
   3.4:1 on the box), so the borders are darker than the mockup's light grey on
   purpose. No width or max-width anywhere: the theme owns layout.
   Markup and rules: WORDPRESS_CONTENT_AUTHORING_SPEC.md, "Quote form". */
.njs-layout .njs-flow .njs-quote-form {
	container-type: inline-size;
	position: relative;
	margin: var(--space-lg) 0 0;
	padding: var(--space-lg) 0 0;
	border-top: 1px solid rgba(26, 26, 26, 0.18);
	text-align: left;
}

.njs-layout .njs-flow .njs-quote-form .njs-quote-form__heading {
	margin: 0 0 var(--space-md);
	font-family: var(--font-body);
	font-weight: 400; /* size: the locked body p size (18px from 1024px, 16px below) */
	line-height: 1.4;
	color: var(--color-ink);
}

.njs-layout .njs-flow .njs-quote-form__form {
	margin: 0;
}

.njs-layout .njs-flow .njs-quote-form .njs-quote-form__fields {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--space-md);
}

@container (min-width: 34rem) {
	.njs-layout .njs-flow .njs-quote-form .njs-quote-form__fields {
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	}

	.njs-layout .njs-flow .njs-quote-form .njs-quote-form__field--full {
		grid-column: 1 / -1;
	}
}

.njs-layout .njs-flow .njs-quote-form .njs-quote-form__field {
	display: flex;
	flex-direction: column;
	gap: 6px;
	min-width: 0;
}

.njs-layout .njs-flow .njs-quote-form label {
	font-family: var(--font-body);
	font-size: var(--step-label);
	font-weight: 400;
	line-height: 1.3;
	color: var(--color-ink);
}

.njs-layout .njs-flow .njs-quote-form .njs-quote-form__req {
	color: #b3261e;
}

.njs-layout .njs-flow .njs-quote-form :is(input[type="text"], input[type="email"], input[type="tel"], textarea) {
	box-sizing: border-box;
	width: 100%;
	min-height: 48px;
	margin: 0;
	padding: 10px 12px;
	border: 1px solid #858585;
	border-radius: var(--radius-sm);
	background: var(--color-bg);
	color: var(--color-ink);
	font-family: var(--font-body);
	font-size: 16px; /* 16px or iOS zooms on focus */
	line-height: 1.5;
}

/* About 7 lines of 16px text, like the mockup. height (not min-height): the
   rows attribute would otherwise set a taller intrinsic size. */
.njs-layout .njs-flow .njs-quote-form textarea {
	height: 7em;
	resize: vertical;
}

.njs-layout .njs-flow .njs-quote-form :is(input, textarea)::placeholder {
	color: #6b6b6b;
	opacity: 1;
}

.njs-layout .njs-flow .njs-quote-form :is(input, textarea):focus-visible,
.njs-layout .njs-flow .njs-quote-form button:focus-visible {
	outline: 3px solid var(--color-ink);
	outline-offset: 2px;
}

/* quote-form.js focuses the status message after the redirect so screen
   readers announce it. It is not a control and is not in the tab order, so
   it gets no focus ring. */
.njs-layout .njs-flow .njs-quote-form .njs-quote-form__status:focus {
	outline: none;
}

.njs-layout .njs-flow .njs-quote-form .njs-quote-form__send {
	margin-top: var(--space-lg);
}

.njs-layout .njs-flow .njs-quote-form .njs-quote-form__note {
	margin: var(--space-sm) 0 0;
	color: var(--color-ink);
}

.njs-layout .njs-flow .njs-quote-form .njs-quote-form__status {
	margin: 0 0 var(--space-md);
	padding: 12px 16px;
	border-left: 4px solid #416b2f;
	background: var(--color-bg);
	color: var(--color-ink);
}

.njs-layout .njs-flow .njs-quote-form .njs-quote-form__status--error {
	border-left-color: #b3261e;
}

/* Honeypot: off-screen for people, still in the form for bots. */
.njs-layout .njs-flow .njs-quote-form .njs-quote-form__hp {
	position: absolute;
	left: -10000px;
	top: auto;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* ==========================================================================
   6. PHONES AND TABLETS
   ========================================================================== */

@media (max-width: 767px) {
	.njs-layout .njs-flow {
		padding-block: var(--space-lg) var(--space-2xl);
	}

	.njs-layout .njs-flow--landing {
		padding-block: var(--space-lg) 0;
	}

	.njs-layout .njs-flow .njs-author-box,
	.njs-layout .njs-flow .njs-author-bio-extended {
		grid-template-columns: 64px minmax(0, 1fr);
		gap: var(--space-md);
		padding: var(--space-md);
		/* theme.css centers the phone author box for its old stacked layout;
		   in the photo-left grid centered text floats off the photo edge. */
		text-align: left;
		align-items: start;
	}

	.njs-layout .njs-flow .njs-author-box .njs-author-credentials {
		justify-content: flex-start;
	}

	.njs-layout .njs-flow .njs-author-box .njs-author-photo,
	.njs-layout .njs-flow .njs-author-bio-extended > img {
		width: 64px;
		height: 64px;
	}

	.njs-layout .njs-flow .njs-table th,
	.njs-layout .njs-flow .njs-table td {
		padding: 10px 6px;
	}

	.njs-layout :is(.njs-stats, .njs-party-stats) {
		gap: var(--space-sm);
	}

	.njs-layout :is(.njs-stat, .njs-party-stat) {
		padding: var(--space-sm);
	}

	.njs-layout :is(.njs-stat__big, .njs-party-stat__big) {
		font-size: 1.8rem;
	}

	.njs-layout :is(.njs-tiles, .njs-party-slots) {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.njs-layout :is(.njs-gallery, .njs-party-gallery) {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.njs-layout :is(.njs-gallery, .njs-party-gallery) img {
		height: 170px;
	}

	.njs-layout :is(.njs-statement, .njs-party-callout) {
		font-size: 1.2rem;
	}

	.njs-layout :is(.njs-quote, .njs-party-quote) {
		padding-left: calc(var(--space-md) + 30px);
	}
}

@media (max-width: 700px) {
	.njs-layout :is(.njs-cards, .njs-party-packages, .njs-party-bring-grid),
	.njs-layout :is(.njs-fact-grid, .njs-party-facts, .njs-fact-grid--two, .njs-party-facts--two),
	.njs-layout :is(.njs-media-row, .njs-party-row, .njs-party-split, .njs-media-row--flip, .njs-party-row--flip) {
		grid-template-columns: minmax(0, 1fr);
	}

	.njs-layout :is(.njs-media-row--flip, .njs-party-row--flip) > :is(.njs-media-row__img, .njs-party-row__img) {
		order: 0;
	}

	.njs-layout :is(.njs-media-row__img, .njs-party-row__img, .njs-party-split__img) {
		height: 230px;
	}
}

/* 260927-cqn-02 ruling 2: a long unbroken string in the flow (19507's bare
   URL link, 6px past the viewport at 390) wraps inside the text column.
   break-word only breaks a word that cannot fit on its own line, so ordinary
   prose and min-content sizing are unchanged. Links inherit it from their p
   or li. Table cells are left out: they already use `anywhere`, and a
   different value there would move the table's column widths. */
.njs-layout .njs-flow :is(p, li):not(table *) {
	overflow-wrap: break-word;
}

/* 260927-cqn-02 ruling 3: 19457's legacy customer-type grid carries an inline
   `grid-template-columns: repeat(3,1fr)`, whose auto minimums ran 73px past a
   390 viewport. On phones it takes two shrinkable columns, so !important is
   needed to beat the inline style. The desktop three-column look is untouched. */
@media (max-width: 767px) {
	.njs-layout .njs-flow .customer-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
		gap: 12px !important;
	}

	.njs-layout .njs-flow .customer-grid .customer-type {
		min-width: 0;
		padding: 16px 10px !important;
		overflow-wrap: break-word;
	}
}

/* Decision 11 (2026-09-28): every article page has the rail, and a page with
   no sections (83798, 19503) shows the call box alone. It sits at the top of
   the rail, without the gap that normally separates it from the TOC. */
.njs-layout .njs-sidebar > .njs-sidebar-cta:first-child {
	margin-top: 0;
}
