/*
Theme Name: Ollie Child
Theme URI:
Author: Privatenode LLC
Author URI: https://privatenode.io
Description: Child theme of Ollie for NPH Consulting LLC.
Requires at least: 6.9
Tested up to: 7.1
Requires PHP: 7.4
Version: 1.12.1
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Template: ollie
Text Domain: ollie-child
Tags:
*/

/* Colors, fonts, sizes, widths, spacing and buttons live in theme.json and on the blocks. This
   file holds only what a block setting can't express: decorative treatments, component
   internals, overrides of Ollie's own block CSS, and the export's breakpoints (1000px, 760px,
   600px, 520px). Source: export/ollie_export_homepage/styles.css, sections noted in brackets. */

/* 1. Base [export §1, §3]
--------------------------------------------- */

h1, h2, h3 {
	text-wrap: balance;
}

/* Ollie's Source Serif 4 is a variable font with an optical-size axis. Left on auto, headlines get
   the thin, narrow display cut. The export's static 600 file is the opsz 14 cut: at 60px it
   measures 916px for the hero line, and opsz 14 matches it exactly (auto gives 776px). */
h1, h2, h3, h4, h5, h6,
.has-display-font-family {
	font-variation-settings: "opsz" 14;
}

p {
	text-wrap: pretty;
}

.wp-block-heading a {
	color: inherit;
	text-decoration: none;
}

.nph-section-head { max-width: 640px; }
.nph-max-480 { max-width: 480px; }
.nph-max-560 { max-width: 560px; }
.nph-max-620 { max-width: 620px; }
.nph-max-640 { max-width: 640px; }

.nph-break-anywhere { overflow-wrap: anywhere; }

/* 2. Grids [export §2, §6, §8, §9, §12, §13, §15]
   WordPress's grid layout fills spare width with empty tracks (auto-fill), so five services at
   200px sit in six columns. The export collapses them (auto-fit), so the tracks are set here. The
   block's own minimum column width stays set, so the editor preview matches.
--------------------------------------------- */

.wp-block-group.nph-fit-200 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
.wp-block-group.nph-fit-220 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); }
.wp-block-group.nph-fit-240 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); }
.wp-block-group.nph-fit-340 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr)); }
.wp-block-group.nph-fit-360 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 360px), 1fr)); align-items: start; }
.wp-block-group.nph-fit-400 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr)); align-items: start; }
.wp-block-group.nph-fit-380 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr)); }
.wp-block-group.nph-fit-420 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr)); align-items: center; }

/* 3. Links [export §3, §7, §11, §16]
   "Text links" are the standalone "See all services →" kind: 15px semibold, 2px Brass underline.
--------------------------------------------- */

.nph-text-link {
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
}

/* Standalone section links sit in a body-size line in the export (19px x 1.5), not their own. */
.nph-text-link--standalone {
	line-height: calc(var(--wp--preset--font-size--base) * 1.5);
}

.nph-text-link a,
.nph-affiliation a {
	text-decoration: underline;
	text-decoration-color: var(--wp--preset--color--primary-alt);
	text-decoration-thickness: 2px;
	text-underline-offset: 5px;
}

.nph-affiliation a {
	font-weight: 500;
	text-underline-offset: 4px;
}

.has-primary-background-color .nph-text-link a {
	color: var(--wp--preset--color--base);
}

/* 4. Hero [export §6]
   Blueprint grid, two Brass hairlines, one pale hairline and a Harbor fade, all as background
   layers (top layer first), so there are no empty decorative blocks in the content.
--------------------------------------------- */

.nph-hero {
	--nph-brass: var(--wp--preset--color--primary-alt);
	--nph-pale: color-mix(in srgb, var(--wp--preset--color--primary-accent) 28%, transparent);
	--nph-major: color-mix(in srgb, var(--wp--preset--color--primary-accent) 16%, transparent);
	--nph-minor: color-mix(in srgb, var(--wp--preset--color--primary-accent) 7%, transparent);
	--nph-fade: linear-gradient(90deg, var(--wp--preset--color--primary) 0%, color-mix(in srgb, var(--wp--preset--color--primary) 80%, transparent) 30%, transparent 55%);
	background-image:
		linear-gradient(var(--nph-brass), var(--nph-brass)),
		linear-gradient(var(--nph-brass), var(--nph-brass)),
		linear-gradient(var(--nph-pale), var(--nph-pale)),
		var(--nph-fade),
		linear-gradient(var(--nph-major) 1px, transparent 1px),
		linear-gradient(90deg, var(--nph-major) 1px, transparent 1px),
		linear-gradient(var(--nph-minor) 1px, transparent 1px),
		linear-gradient(90deg, var(--nph-minor) 1px, transparent 1px);
	background-size: 1px 100%, 52% 1px, 1px 100%, 100% 100%, 240px 240px, 240px 240px, 48px 48px, 48px 48px;
	background-position: 78% 0, 100% 68%, 62% 0, 0 0, -1px -1px, -1px -1px, -1px -1px, -1px -1px;
	background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, repeat, repeat, repeat, repeat;
}

.nph-hero__copy {
	max-width: var(--wp--style--global--content-size);
}

/* Compact interior hero [export §18]: a longer, stronger fade behind the text. */
.nph-hero--compact {
	position: relative;
	isolation: isolate;
	--nph-fade: linear-gradient(90deg, var(--wp--preset--color--primary) 0%, color-mix(in srgb, var(--wp--preset--color--primary) 88%, transparent) 38%, transparent 72%);
}

/* Brass ring where the hairlines cross [export v2 §6 .hero__node], interior heroes only. isolation
   lets z-index -1 put it behind the content but above the hero's own background. */
.nph-hero--compact::after {
	content: "";
	position: absolute;
	left: calc(78% - 5px);
	top: calc(68% - 5px);
	width: 11px;
	height: 11px;
	border: 1px solid var(--wp--preset--color--primary-alt);
	border-radius: 50%;
	z-index: -1;
	pointer-events: none;
}

/* Services hero tiles [export §29]: each tile is one link, stretched over the tile. */
.nph-service-tile {
	border: 1px solid var(--wp--preset--color--border-dark);
}

.nph-service-tile:hover,
.nph-service-tile:focus-within {
	border-color: var(--wp--preset--color--primary-alt);
}

.nph-service-tile p {
	margin: 0;
}

.nph-service-tile__title a {
	color: var(--wp--preset--color--base);
	text-decoration: none;
}

/* Photo with a thin Brass frame offset up and to the left, behind it. */
.nph-hero__media {
	position: relative;
	isolation: isolate;
	margin: 0;
}

.nph-hero__media::before {
	content: "";
	position: absolute;
	inset: -14px 14px 14px -14px;
	border: 1px solid var(--wp--preset--color--primary-alt);
	border-radius: var(--wp--preset--border-radius--sm);
	z-index: -1;
}

.nph-hero__media img {
	width: 100%;
}

/* 5. Short Brass rule [export §3 .rule]
   Ollie draws every separator as a 1px bottom border (assets/styles/core-separator.css).
--------------------------------------------- */

/* .has-background is needed to beat Ollie's 1px rule (0,3,0). */
hr.wp-block-separator.nph-rule.has-background {
	border: 0;
	height: 2px;
	width: 56px;
	margin: 0;
}

/* 6. Lists and chips [export §8, §10, §16]
   Ollie gives every list item a bottom margin (theme.json core/list-item); these lists use gaps.
--------------------------------------------- */

.nph-plain-list,
.nph-chips {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
}

.nph-plain-list {
	flex-direction: column;
	gap: 8px;
}

.nph-footer-list {
	gap: 10px;
}

.nph-plain-list--tight {
	gap: 4px;
}

.nph-plain-list > li,
.nph-chips > li {
	margin: 0;
	padding: 0;
}

.nph-chips {
	flex-wrap: wrap;
	gap: 8px;
}

.nph-chips > li {
	background: var(--wp--preset--color--primary-accent);
	color: var(--wp--preset--color--primary);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	padding: 6px 12px;
	border-radius: var(--wp--preset--border-radius--xs);
}

/* Ollie zeroes the first item's top padding and the last item's bottom padding in every list
   (assets/styles/core-list.css, specificity 0,3,1), which knocks the end chips off center. */
ul.nph-chips.wp-block-list > li:nth-child(n) {
	padding: 6px 12px;
}

/* 7. Sections and cards [export §7–§15]
--------------------------------------------- */

.nph-affiliation {
	padding-top: var(--wp--preset--spacing--medium);
	border-top: 1px solid var(--wp--preset--color--border-light);
}

/* Services: hairline above the grid, one below each service. */
.nph-service-grid {
	border-top: 1px solid var(--wp--preset--color--border-light);
}

.nph-service {
	border-bottom: 1px solid var(--wp--preset--color--border-light);
}

/* Service detail [export §19]: hairline above the sub-services, one below each. */
.nph-sub-services {
	border-top: 1px solid var(--wp--preset--color--border-light);
}

.nph-sub-service {
	border-bottom: 1px solid var(--wp--preset--color--border-light);
}

/* Testimonial [export §20]: a large Brass quote mark above the quote. */
.nph-testimonial__quote::before {
	content: "\201C";
	display: block;
	font-size: var(--wp--preset--font-size--xx-large);
	line-height: 1;
	color: var(--wp--preset--color--primary-alt);
}

/* Cards that are one link: the link is stretched over the whole card. */
.nph-card-link {
	position: relative;
}

.nph-card-link .nph-text-link a::after,
.nph-card-link .nph-service-tile__title a::after,
.nph-card-link .nph-related-tile__title a::after,
.nph-card-link .nph-stat-grid__value a::after,
.nph-card-link .nph-case-tile__title a::after,
.nph-card-link .nph-post-card__title a::after,
.nph-card-link .nph-service-index__title a::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
}

.nph-icon-well {
	width: 44px;
	height: 44px;
	flex-shrink: 0;
}

/* Service pages [export §22, §26]
   Breadcrumb eyebrow: the link takes the eyebrow's pale color, not Harbor (invisible on Harbor). */
.nph-breadcrumb a,
.nph-breadcrumb a:hover {
	color: inherit;
}

/* The separator in breadcrumbs that come from a binding (case studies, posts). The static ones
   on service pages use an inline color instead. */
.nph-breadcrumb__sep {
	color: var(--wp--preset--color--primary-alt);
}

/* The latest-post loop sits between full-width sections: no block gap, so no white band when it's
   empty or above it when it isn't (as .nph-case-featured). */
.wp-block-query.nph-post-latest {
	margin-block: 0;
}

/* Accent panel beside the overview [export §29]: as tall as its content; chips turn white on it. */
.nph-service-aside {
	align-self: start;
}

.nph-chips--on-accent > li {
	background: var(--wp--preset--color--base);
}

/* Pull quote: a large Brass quote mark above the text, half its height. */
.nph-pull-quote__text::before {
	content: "\201C";
	display: block;
	height: .5em;
	font-size: var(--wp--preset--font-size--xx-large);
	line-height: 1;
	color: var(--wp--preset--color--primary-alt);
}

.nph-case-card__body {
	max-width: var(--wp--style--global--content-size);
}

/* Related services: each tile is one link, stretched over the tile (see .nph-card-link). */
.nph-related-tile {
	align-items: center;
}

.nph-related-tile > p {
	margin: 0;
}

.nph-related-tile > .nph-related-tile__title {
	flex: 1;
}

.nph-related-tile__title a,
.nph-related-tile__title a:hover {
	color: var(--wp--preset--color--main);
	text-decoration: none;
}

/* Case studies [export §28, 2026-10-19 export]. The fields come from inc/case-studies.php through
   block bindings. Post Title sets word-break: break-word (0,1,0), which changes where text-wrap:
   balance breaks long titles and adds a line on phones. Headings elsewhere use normal. */
.nph-section .wp-block-post-title {
	word-break: normal;
}

/* The featured loop sits between full-width sections, so it takes no block gap, and an empty loop
   leaves no white band under the hero. */
.wp-block-query.nph-case-featured {
	margin-block: 0;
}

/* Light hero (list, single and service archives): the copy column is wider than the side. */
.wp-block-group.nph-case-hero__inner {
	grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
	align-items: center;
}

.wp-block-group.nph-case-hero__inner--single {
	grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
	align-items: end;
}

/* No result figure: the copy runs full width (the export's .case-hero__inner--text). */
.wp-block-group.nph-case-hero__inner--single:not(:has(.nph-result-stack)) {
	grid-template-columns: minmax(0, 1fr);
}

.nph-case-hero .nph-breadcrumb a,
.nph-case-hero .nph-breadcrumb a:hover {
	color: var(--wp--preset--color--primary);
}

/* Stat grid: hairlines between the four cells; each cell is one link (see .nph-card-link). */
.nph-stat-grid {
	border-top: 1px solid var(--wp--preset--color--border-light);
}

.nph-stat-grid__item {
	border-bottom: 1px solid var(--wp--preset--color--border-light);
}

.nph-stat-grid__item:nth-child(odd) {
	border-right: 1px solid var(--wp--preset--color--border-light);
}

.nph-stat-grid__item p {
	margin: 0;
}

/* Base on hover, since the hero is Tint. The stretched link has no outline, so the cell shows focus. */
.nph-stat-grid__item:hover {
	background: var(--wp--preset--color--base);
}

.nph-stat-grid__item:focus-within,
.nph-case-tile:focus-within,
.nph-post-card:focus-within {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}

.nph-stat-grid__value a,
.nph-stat-grid__value a:hover {
	color: inherit;
	text-decoration: none;
	outline: 0;
}

/* Featured case: a Harbor panel, copy beside the result. */
.wp-block-group.nph-case-feature {
	grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
	align-items: center;
}

.nph-case-feature .wp-block-buttons {
	margin-top: 8px;
}

/* Result figure beside a Brass rule; at 1000px the rule moves on top. */
.nph-result-stack {
	border-left: 1px solid var(--wp--preset--color--primary-alt);
	padding-left: var(--wp--preset--spacing--large);
}

.nph-result-stack p {
	margin: 0;
}

/* Service filter: pill links, the current one filled (aria-current, set in inc/case-studies.php). */
.nph-filter-links {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 0;
}

.nph-filter-links a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 0 18px;
	border-radius: 5px;
	background: var(--wp--preset--color--primary-accent);
	color: var(--wp--preset--color--primary);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	text-decoration: none;
}

.nph-filter-links a:hover {
	background: var(--wp--preset--color--border-light);
	color: var(--wp--preset--color--primary);
}

.nph-filter-links a[aria-current],
.nph-filter-links a[aria-current]:hover {
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
}

/* Case tiles: three columns, two from 1000px, one from 600px. Each tile is one link. */
.nph-case-grid .wp-block-post-template {
	grid-template-columns: repeat(3, minmax(0, 1fr));
}

.nph-case-grid .wp-block-post-template > li > .nph-case-tile {
	height: 100%;
}

.nph-case-tile:hover {
	border-color: var(--wp--preset--color--primary) !important; /* Beats the block's border-light class, which core marks !important. */
}

.nph-case-tile__top {
	align-items: baseline;
}

.nph-case-tile p {
	margin: 0;
}

.nph-case-tile__title a {
	color: var(--wp--preset--color--main);
	text-decoration: none;
	outline: 0;
}

.nph-case-tile:hover .nph-case-tile__title a {
	color: var(--wp--preset--color--primary);
	text-decoration: underline;
}

/* Pinned to the tile's foot. Two classes to beat the flex layout's margin reset. */
.nph-case-tile > .nph-case-tile__more {
	margin-top: auto;
	padding-top: 8px;
}

/* Single: the description beside a 340px "At a glance" panel. */
.wp-block-group.nph-case-body__grid {
	grid-template-columns: minmax(0, 1fr) 340px;
	align-items: start;
}

.nph-case-body__main {
	max-width: var(--wp--style--global--content-size);
}

.nph-case-body__text > * {
	margin-block: 0;
}

.nph-case-body__text > * + * {
	margin-block-start: var(--wp--preset--spacing--small);
}

/* Sub-projects (UNCG): a hairline between groups, none above the first. */
.nph-sub-project + .nph-sub-project {
	padding-top: var(--wp--preset--spacing--medium);
	border-top: 1px solid var(--wp--preset--color--border-light);
}

.nph-glance p {
	margin: 0;
}

/* Clients, one per line (the binding wraps each in a span). */
.nph-fact-list span {
	display: block;
}

.nph-fact-list span + span {
	margin-top: 6px;
}

/* Service chips: links styled as .nph-chips items, filling Harbor on hover. */
.nph-service-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.nph-service-chips a {
	padding: 8px 14px;
	border-radius: var(--wp--preset--border-radius--xs);
	background: var(--wp--preset--color--primary-accent);
	color: var(--wp--preset--color--primary);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	text-decoration: none;
}

.nph-service-chips a:hover {
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
}

/* Quote band: a Brass quote mark above the quote. */
.nph-case-quote__figure {
	max-width: var(--wp--style--global--content-size);
	margin-inline: auto;
}

.nph-case-quote__text {
	text-wrap: balance;
}

.nph-case-quote__text::before {
	content: "\201C";
	display: block;
	height: .6em;
	font-size: var(--wp--preset--font-size--xx-large);
	line-height: 1;
	color: var(--wp--preset--color--primary-alt);
}

/* With no quote the band is left out, and the CTA section would double the gap below the body. */
.nph-case-body + .nph-case-cta {
	padding-top: 0 !important; /* The section's padding is set on the block. */
}

/* Blog [export §30, §31]. Post values come from inc/blog.php through block bindings. */

/* Latest post: copy beside the button, bottom-aligned. */
.wp-block-group.nph-post-feature {
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: end;
}

.nph-post-feature__body {
	max-width: var(--wp--style--global--content-size);
}

.nph-post-meta-row,
.nph-post-card__top {
	align-items: baseline;
}

.nph-post-meta-row p,
.nph-post-card__top p,
.nph-date-row p,
.nph-post-card p,
.nph-post-hero-meta p {
	margin: 0;
}

/* Date and read time in one line: "October 15, 2026 · 6 min read". */
.nph-date-row .wp-block-post-date,
.nph-post-hero-meta .wp-block-post-date,
.nph-post-hero-meta .wp-block-post-author-name {
	font-size: inherit;
}

.nph-read-time::before {
	content: "\00a0·\00a0";
}

/* Post cards: three columns, two from 1000px, one from 600px. Each card is one link. */
.nph-post-grid .wp-block-post-template {
	grid-template-columns: repeat(3, minmax(0, 1fr));
}

.nph-post-grid .wp-block-post-template > li > .nph-post-card {
	height: 100%;
}

.nph-post-card:hover {
	border-color: var(--wp--preset--color--primary) !important; /* Beats the block's border-light class, which core marks !important. */
}

/* The optional photo runs to the card's edges. Two classes to beat the flex layout's margin reset. */
.nph-post-card > .nph-post-card__thumb {
	margin: calc(var(--wp--preset--spacing--medium) * -1) calc(var(--wp--preset--spacing--medium) * -1) 0;
}

.nph-post-card__thumb img {
	border-radius: calc(var(--wp--preset--border-radius--sm) - 1px) calc(var(--wp--preset--border-radius--sm) - 1px) 0 0;
}

.nph-post-card__title a {
	color: var(--wp--preset--color--main);
	text-decoration: none;
	outline: 0;
}

/* The latest post's title links to it too (the export's doesn't), styled like a card title. */
.nph-post-feature__title a {
	color: var(--wp--preset--color--main);
}

.nph-post-feature__title a:hover,
.nph-post-card:hover .nph-post-card__title a {
	color: var(--wp--preset--color--primary);
	text-decoration: underline;
}

/* "Read the post →" looks like a text link but isn't one (the title is the link). */
.nph-post-card > .nph-post-card__more {
	margin-top: auto;
	align-self: flex-start;
	text-decoration: underline;
	text-decoration-color: var(--wp--preset--color--primary-alt);
	text-decoration-thickness: 2px;
	text-underline-offset: 5px;
}

/* Pagination: 44px boxes, the current page filled. Ollie styles these links in theme.json and
   core-query-pagination-numbers.css; these rules replace both. */
.wp-block-query-pagination.nph-pagination {
	gap: 8px;
	margin-top: var(--wp--preset--spacing--large);
}

.nph-pagination .wp-block-query-pagination-numbers {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.nph-pagination a,
.nph-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	min-height: 44px;
	padding: 0 14px;
	border: 1px solid var(--wp--preset--color--border-light);
	border-radius: 5px;
	background: none;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	color: var(--wp--preset--color--primary);
	text-decoration: none;
}

.nph-pagination a:hover {
	border-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--primary);
	text-decoration: none;
}

.nph-pagination [aria-current],
.nph-pagination [aria-current]:hover {
	background: var(--wp--preset--color--primary);
	border-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
}

.nph-pagination .dots {
	border-color: transparent;
}

/* Post body: the export's rhythm for paragraphs, H2s, lists and pull quotes. */
.wp-block-post-content.nph-post-body > * + * {
	margin-block-start: var(--wp--preset--spacing--small);
}

.wp-block-post-content.nph-post-body > h2 {
	margin-block-start: var(--wp--preset--spacing--large);
}

.nph-post-body ul {
	list-style: disc;
	padding-left: 1.25em;
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.nph-post-body ol {
	padding-left: 1.25em;
}

.nph-post-body li {
	margin: 0;
	padding: 0;
}

.nph-post-body a {
	text-decoration-color: var(--wp--preset--color--primary-alt);
	text-decoration-thickness: 2px;
	text-underline-offset: 4px;
}

/* Pull quote: a Brass rule on the left, not Ollie's Harbor rule on top. */
.wp-block-post-content.nph-post-body > .wp-block-pullquote {
	margin-block: var(--wp--preset--spacing--large);
	padding: 8px 0 8px var(--wp--preset--spacing--medium);
	border: 0;
	border-left: 2px solid var(--wp--preset--color--primary-alt);
	text-align: left;
}

.nph-post-body .wp-block-pullquote blockquote {
	margin: 0;
	font-family: var(--wp--preset--font-family--display);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--medium);
	line-height: 1.5;
	text-wrap: balance;
}

.nph-post-body .wp-block-pullquote p {
	margin: 0;
	font-size: inherit;
	line-height: inherit;
}

.wp-block-post-content.nph-post-body > .wp-block-pullquote + * {
	margin-block-start: 0;
}

/* About the author: photo beside the name and bio. */
.nph-author-box__photo {
	flex: none;
	margin: 0;
}

.nph-author-box__photo img {
	object-position: 50% 20%;
}

.nph-author-box__body {
	flex: 1 1 280px;
	min-width: 0;
}

.nph-author-box__body p,
.nph-author-box__body h2 {
	margin: 0;
}

.nph-author-box__body > .nph-text-link {
	margin-top: 8px;
}

/* About [export §23]. Nancy's photo is cropped toward her face, as in the export. */
.nph-bio__photo {
	flex: none;
	margin: 0;
}

.nph-bio__photo img {
	object-position: 50% 20%;
}

/* The facts box floats right and the bio wraps around it, then runs under it at full width. 45%
   of the row (less the gap) leaves room for "Nancy Parks Hunter, MPA" on one line from 1280px up.
   flow-root keeps the float inside the section. Beats core's alignright margin (0,1,0). */
.nph-bio__body {
	display: flow-root;
}

.nph-bio__body > .nph-facts.alignright {
	width: calc((100% - var(--wp--preset--spacing--large)) * .45);
	margin-left: var(--wp--preset--spacing--large);
	margin-bottom: var(--wp--preset--spacing--small);
}

/* The box is first in the markup so it starts level with the head, which then needs no gap above. */
.nph-bio__body > .nph-facts + .nph-bio__head {
	margin-block-start: 0;
}

/* Service index: each row is one link, stretched over the row (see .nph-card-link). */
.nph-service-index__row > p {
	margin: 0;
}

.nph-service-index__number {
	min-width: 40px;
}

.nph-service-index__row > .nph-service-index__title {
	flex: 1;
}

.nph-service-index__title a,
.nph-service-index__title a:hover {
	color: var(--wp--preset--color--main);
	text-decoration: none;
}

/* Contact page [export §27]. Rows of the contact methods and the stacked "What happens next"
   steps: paragraphs sit flush in their flex rows, and step numbers get the export's 48px column. */
.nph-contact-method__text > p,
.nph-step-stack > p {
	margin: 0;
}

.nph-step-stack > .nph-step-stack__number {
	flex: 0 0 48px;
}

/* Contact form: Gravity Forms (Orbital) restyled to the export's fields [export §15, §27].
   Colors are the block's own settings: Gravity Forms writes them to an ID rule on the wrapper
   that a class can't beat. Sizes are set here on the form body instead, where they win by
   inheritance. Ollie's own input rule doesn't reach these (Gravity Forms resets it). */
.nph-contact-form .gform_wrapper.gform-theme--orbital {
	--gf-color-danger: var(--wp--preset--color--error);
	--gf-color-danger-rgb: 166, 67, 46;
}

.nph-contact-form .gform-theme--orbital :is(.gform_body, .gform_footer) {
	--gf-form-gap-x: var(--wp--preset--spacing--medium);
	--gf-form-gap-y: var(--wp--preset--spacing--medium);
	--gf-ctrl-size: 52px;
	--gf-ctrl-padding-x: 14px;
	--gf-ctrl-border-width: 1.5px;
	--gf-ctrl-radius: 5px;
	--gf-ctrl-font-size: var(--wp--preset--font-size--small);
	--gf-ctrl-placeholder-font-size: var(--wp--preset--font-size--small);
	--gf-ctrl-textarea-height: 177px; /* the export's rows="6" */
	--gf-ctrl-textarea-radius: 5px;
	--gf-ctrl-label-font-size-primary: var(--wp--preset--font-size--x-small);
	--gf-ctrl-label-font-weight-primary: 500;
	--gf-ctrl-btn-size: 48px; /* the theme button: 13px padding + 15px text at 1.5 */
	--gf-ctrl-btn-padding-x: 26px;
	--gf-ctrl-btn-radius: 5px;
	--gf-ctrl-btn-font-size: var(--wp--preset--font-size--x-small);
	--gf-ctrl-btn-font-weight: 600;
}

/* The export marks optional fields, not required ones ("Fields marked optional can be left
   blank."). Required inputs keep aria-required, so screen readers still announce them. */
.nph-contact-form .gform-theme--orbital .gfield_required {
	display: none;
}

.nph-contact-form .gform-theme--orbital .gfield:not(.gfield_contains_required) > .gfield_label::after {
	content: " (optional)";
	font-weight: 400;
	color: var(--wp--preset--color--secondary);
}

/* Radio choices as pill chips [export .choice-chip]. The radio stays in place, transparent and
   covering its chip, so clicks and keyboard work as normal. Row direction and auto widths
   undo the field's gf_list_2col_vertical class. */
.nph-contact-form .gform-theme--orbital .gfield--type-choice .gfield_radio {
	display: flex;
	flex-flow: row wrap;
	gap: 8px;
}

.nph-contact-form .gform-theme--orbital .gfield--type-choice .gfield_radio .gchoice {
	position: relative;
	inline-size: auto;
	margin: 0;
}

.nph-contact-form .gform-theme--orbital .gfield--type-choice .gfield-choice-input {
	position: absolute;
	inset: 0;
	margin: 0;
	opacity: 0;
}

.nph-contact-form .gform-theme--orbital .gfield--type-choice .gchoice label {
	display: inline-block;
	margin: 0;
	padding: 8px 14px;
	border: 1.5px solid var(--wp--preset--color--secondary);
	border-radius: 999px;
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.5;
	cursor: pointer;
}

.nph-contact-form .gform-theme--orbital .gfield--type-choice .gchoice label::before,
.nph-contact-form .gform-theme--orbital .gfield--type-choice .gchoice label::after {
	content: none;
}

.nph-contact-form .gform-theme--orbital .gfield-choice-input:checked + label {
	background: var(--wp--preset--color--primary);
	border-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
}

.nph-contact-form .gform-theme--orbital .gfield-choice-input:focus-visible + label {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}

/* Client name tiles (names, not logos, since 2026-10-26): four to a row (two on tablets), in a
   centered wrapping row so a short last row centers, as in Claude Design's mockup. Stretched, so
   a three-line name doesn't leave its row uneven (flex groups center by default). */
.wp-block-group.nph-client-grid {
	align-items: stretch;
}

.nph-client-grid > .nph-client-tile {
	flex: 0 0 calc((100% - 3 * var(--wp--preset--spacing--small)) / 4);
}

.wp-block-group.nph-client-tile {
	min-height: 112px;
	padding: var(--wp--preset--spacing--medium);
}

/* Case study quote. Ollie gives every quote a 5px Harbor left border with !important
   (theme.json core/quote), so changing the border widths needs !important too. Ollie also sets
   quotes at 26px; the design uses body size. */
.wp-block-quote.nph-quote {
	position: relative;
	margin: 0;
	padding: var(--wp--preset--spacing--medium) 0 0 34px;
	border-width: 1px 0 0 !important;
	border-color: var(--wp--preset--color--border-light);
	color: var(--wp--preset--color--secondary);
	font-size: var(--wp--preset--font-size--base);
	line-height: 1.5;
}

.wp-block-quote.nph-quote::before {
	content: "\201C";
	position: absolute;
	left: 0;
	top: calc(var(--wp--preset--spacing--medium) - .1em);
	font-family: var(--wp--preset--font-family--display);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--x-large);
	font-variation-settings: "opsz" 14;
	line-height: 1;
	color: var(--wp--preset--color--primary-alt);
}

.wp-block-quote.nph-quote cite {
	display: block;
	margin-top: var(--wp--preset--spacing--small);
	font-size: var(--wp--preset--font-size--x-small);
	font-style: normal;
	color: var(--wp--preset--color--secondary);
}

.wp-block-quote.nph-quote cite mark {
	font-weight: 600;
	letter-spacing: .06em;
	text-transform: uppercase;
}

/* Homepage team feature [export §29]: Nancy's photo (up to 320px, cropped toward her face) beside
   her name; the body wraps under the photo when it would drop below 380px. */
.nph-team-feature > .nph-team-feature__photo {
	flex: 0 1 320px;
	max-width: 320px;
	min-width: 0;
	margin: 0;
}

.nph-team-feature__photo img {
	width: 100%;
	object-position: 50% 20%;
}

.nph-team-feature > .nph-team-feature__body {
	flex: 1 1 380px;
	max-width: 640px;
}


/* 8. Header [export §5]
--------------------------------------------- */

.nph-header .wp-block-image {
	margin: 0;
}

.nph-header .wp-block-navigation .wp-block-buttons {
	margin: 0;
}

/* Services dropdown: same size as the nav. Ollie sets dropdowns to small (0,3,0), in its inline
   navigation CSS. The open mobile menu sizes everything itself, so it's left alone. */
.nph-header .wp-block-navigation__responsive-container:not(.is-menu-open) .wp-block-navigation__submenu-container {
	font-size: inherit;
}

/* Services dropdown colors (not in the export; option 2, chosen 2026-10-14): Main Accent, a step
   lighter than the header so it lifts off it, with Border Dark rows on hover and focus.
   !important because the color comes from the nav's overlay setting as the has-main-background-color
   preset class, which WordPress marks !important. Changing that setting would recolor the open
   mobile menu too, which stays Ink. */
.nph-header .wp-block-navigation__responsive-container:not(.is-menu-open) .wp-block-navigation__submenu-container {
	background-color: var(--wp--preset--color--main-accent) !important;
	overflow: hidden; /* keeps the hover rows inside the rounded corners */
}

.nph-header .wp-block-navigation__responsive-container:not(.is-menu-open) .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	display: block;
	width: 100%;
}

.nph-header .wp-block-navigation__responsive-container:not(.is-menu-open) .wp-block-navigation__submenu-container .wp-block-navigation-item__content:is(:hover, :focus-visible) {
	background-color: var(--wp--preset--color--border-dark);
}

/* Current page [export §5]: Brass underline; in the open mobile menu, pale and semibold. Ollie's
   own current-item rule (0,4,1) resets the underline color with the text-decoration shorthand. */
.nph-header .wp-block-navigation .current-menu-item > .wp-block-navigation-item__content[aria-current="page"] {
	text-decoration: underline;
	text-decoration-color: var(--wp--preset--color--primary-alt);
	text-decoration-thickness: 2px;
	text-underline-offset: 8px;
}

/* Service pages are children of Services (page 209), and case studies are entries under
   /case-studies/. WordPress marks neither parent as current.
   If the Services page is ever recreated, update the ID here and in tools/build_homepage.py. */
.parent-pageid-209 .nph-header .wp-block-navigation .wp-block-navigation-item > .wp-block-navigation-item__content[href$="/services/"],
.single-case_study .nph-header .wp-block-navigation .wp-block-navigation-item > .wp-block-navigation-item__content[href$="/case-studies/"] {
	text-decoration: underline;
	text-decoration-color: var(--wp--preset--color--primary-alt);
	text-decoration-thickness: 2px;
	text-underline-offset: 8px;
}

.nph-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content[aria-current="page"],
.parent-pageid-209 .nph-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content[href$="/services/"],
.single-case_study .nph-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content[href$="/case-studies/"] {
	color: var(--wp--preset--color--primary-accent);
	font-weight: 600;
	text-decoration: none;
}

.nph-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-button__link {
	display: block;
	text-align: center;
}

/* Open mobile menu: the nav's right justification aligns the menu column to the right. The links
   fill the column, but "Get in touch" is only as wide as its text and sat flush right. Left-align
   it with the links. */
.nph-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-buttons {
	align-self: flex-start;
}

/* The export collapses the menu at 760px; WordPress's navigation collapses at 600px. Between the
   two, show the menu button and hide the inline links. Unverified live. */
@media (min-width: 600px) and (max-width: 760px) {
	.nph-header .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}

	.nph-header .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none;
	}
}

/* The logo's 64px height is set on the image block, so the phone size needs !important. */
@media (max-width: 760px) {
	.nph-header .nph-logo img {
		height: 48px !important;
	}
}

/* Services hero tiles stack [export §29]. */
@media (max-width: 760px) {
	.wp-block-group.nph-service-tiles {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* 9. Footer [export §16]
--------------------------------------------- */

.nph-footer .wp-block-image {
	margin: 0;
}

.nph-footer a:where(:not(.wp-element-button)) {
	color: inherit;
	text-decoration: none;
}

.nph-footer .nph-credit a {
	color: var(--wp--preset--color--base);
	text-decoration: underline;
	text-decoration-color: var(--wp--preset--color--primary-alt);
	text-decoration-thickness: 2px;
	text-underline-offset: 4px;
}

.nph-footer-top {
	border-bottom: 1px solid var(--wp--preset--color--border-dark);
}

.nph-footer-legal {
	border-top: 1px solid var(--wp--preset--color--border-dark);
}

.nph-flag {
	display: inline-block;
	width: 16px;
	height: 16px;
	vertical-align: -3px;
	margin: 0 2px;
}

/* 10. Tablet (1000px and down) [export §17]
--------------------------------------------- */

@media (max-width: 1000px) {
	.wp-block-group.nph-case-hero__inner,
	.wp-block-group.nph-case-hero__inner--single,
	.wp-block-group.nph-case-feature,
	.wp-block-group.nph-case-body__grid {
		grid-template-columns: minmax(0, 1fr);
	}

	.nph-result-stack {
		border-left: 0;
		border-top: 1px solid var(--wp--preset--color--primary-alt);
		padding: var(--wp--preset--spacing--medium) 0 0;
	}

	.nph-case-grid .wp-block-post-template,
	.nph-post-grid .wp-block-post-template {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.wp-block-group.nph-post-feature {
		grid-template-columns: minmax(0, 1fr);
	}

	.nph-client-grid > .nph-client-tile {
		flex-basis: calc((100% - var(--wp--preset--spacing--small)) / 2);
	}

	.wp-block-group.nph-footer-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* About: below 860px the box would drop under 340px (the export's narrowest column) and the name
   would take three lines. It stops floating and moves after the bio, as in the export. */
@media (max-width: 860px) {
	.nph-bio__body {
		display: flex;
		flex-direction: column;
	}

	.nph-bio__body > .nph-facts.alignright {
		order: 1;
		float: none;
		width: auto;
		margin: var(--wp--preset--spacing--medium) 0 0;
	}
}

/* 11. Phones (600px and down) [export §17]
   The hero H1 and the card padding are set on the blocks, and WordPress's preset classes and
   inline styles beat a plain rule, so these few overrides need !important.
--------------------------------------------- */

@media (max-width: 600px) {
	.nph-hero h1.has-xx-large-font-size,
	.nph-case-hero h1.has-xx-large-font-size {
		font-size: var(--wp--preset--font-size--x-large) !important;
	}

	.nph-hero {
		background-size: 0 0, 0 0, 0 0, 100% 100%, 240px 240px, 240px 240px, 48px 48px, 48px 48px;
	}

	.nph-hero--compact::after {
		display: none;
	}

	.nph-case-study,
	.nph-case-card,
	.nph-case-feature,
	.nph-post-feature,
	.nph-pull-quote,
	.nph-form-placeholder,
	.nph-cta-panel {
		padding: var(--wp--preset--spacing--medium) !important;
	}

	.wp-block-group.nph-case-card {
		flex-direction: column;
	}

	.nph-case-grid .wp-block-post-template,
	.nph-post-grid .wp-block-post-template {
		grid-template-columns: minmax(0, 1fr);
	}

	.wp-block-post-content.nph-post-body > .wp-block-pullquote {
		padding-left: var(--wp--preset--spacing--small);
	}

	.nph-stat-grid__item {
		padding: var(--wp--preset--spacing--small) !important;
	}

	.wp-block-group.nph-client-tile {
		min-height: 88px;
		padding: var(--wp--preset--spacing--small);
	}

	/* About and author-box photos 120 → 88px [export §17], so the name takes three lines, not four. The 120px is
	   set inline on the image block, so this needs !important (as the header logo does). */
	.nph-bio__photo img,
	.nph-author-box__photo img {
		width: 88px !important;
		height: 88px !important;
	}
}

/* 12. Small phones (520px and down) [export §17]
--------------------------------------------- */

@media (max-width: 520px) {
	.wp-block-group.nph-footer-grid {
		grid-template-columns: minmax(0, 1fr);
	}
}