/*
Theme Name: Nurse Leslie
Theme URI: https://nurseleslie.com
Author: Linn Tech Solutions
Author URI: https://linntechsolutions.com
Description: Custom block theme for Nurse Leslie Permanent Makeup & Restorative Tattoo. A medical-luxury aesthetic — warm creams, stone, linen, refined serif typography, large imagery, and calm, subtle movement.
Version: 1.16.0
Requires at least: 6.7
Tested up to: 7.0
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: nurseleslie
*/

/* -------------------------------------------------------------------------
 * Base refinements
 * ---------------------------------------------------------------------- */

body {
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
}

/* -------------------------------------------------------------------------
 * Page ground — warmth instead of flat cream.
 *
 * The sections that carry no background of their own used to sit on an even
 * sheet of #F8F4ED, which read as a lot of empty white. A fixed wash sits
 * behind everything: three very soft linen/stone pools plus a fine grain, so
 * the page has depth and a paper quality without any section losing contrast.
 * Sections with their own colour (linen, ink, the hero cover) paint over it
 * exactly as before.
 *
 * Fixed rather than scrolling so the pools stay put and never band, and
 * z-index -1 so it is behind the content but above the body's own colour.
 * ---------------------------------------------------------------------- */

body::before {
	content: "";
	position: fixed;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	background-color: var(--wp--preset--color--cream);
	background-image:
		radial-gradient(58rem 42rem at 8% -8%, rgba(240, 233, 222, 0.95), transparent 62%),
		radial-gradient(46rem 38rem at 96% 18%, rgba(218, 208, 192, 0.45), transparent 64%),
		radial-gradient(52rem 40rem at 4% 82%, rgba(218, 208, 192, 0.34), transparent 62%),
		radial-gradient(38rem 30rem at 88% 104%, rgba(151, 121, 83, 0.12), transparent 60%);
}

/* Grain, kept separate so it can be layered over the pools at its own
   opacity. Two decimal places on baseFrequency keeps the pattern fine
   enough to read as paper rather than noise. */
body::after {
	content: "";
	position: fixed;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	opacity: 0.035;
	background-image: url( "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E" );
}

::selection {
	background: var(--wp--preset--color--stone);
	color: var(--wp--preset--color--ink);
}

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

/* Eyebrow label — small, spaced, uppercase */
.nl-eyebrow {
	font-family: var(--wp--preset--font-family--subheading);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--wp--preset--color--clay);
}

/* Buttons — quiet luxury: sharp, spaced, unhurried */
.wp-block-button__link {
	transition: background-color 0.35s ease, color 0.35s ease, border-color 0.35s ease;
}

.wp-block-button.is-style-outline .wp-block-button__link {
	border-width: 1px;
}

/* A step up in size for a button that has to pull the eye on its own, with
   no second button beside it to form a pair. */
.nl-button-lg .wp-block-button__link {
	font-size: 0.9375rem;
	letter-spacing: 0.16em;
	padding: 1.2rem 2.6rem;
}

.nl-button-lg.is-style-outline .wp-block-button__link {
	border-width: 1.5px;
}

.nl-button-lg.is-style-outline .wp-block-button__link:hover {
	background: var(--wp--preset--color--ink);
	border-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--cream);
}

/* Links */
a {
	text-underline-offset: 0.2em;
	transition: color 0.3s ease;
}

/* -------------------------------------------------------------------------
 * Page and section headings — espresso, a dark brown a shade warmer than the
 * ink of the body copy. Leslie tried the studio's plant green here and found
 * it did not sit with the rest of the palette (Oct 2026).
 *
 * Scoped to h1 and h2 over light grounds: the page's own headline and the
 * section headlines beneath it, the same line reading the same colour
 * wherever it appears (11.5:1 on cream, 10.5:1 on linen).
 *
 * Two exclusions, both deliberate:
 *   - Card titles. They keep the ink of the card they sit in, so a card reads
 *     as one object. The services archive and blog index render these as h2
 *     post titles.
 *   - Headings on the ink bands and the hero cover. These have no colour of
 *     their own — they inherit cream from the section — so a colour set here
 *     would override that inheritance and drop them to 3.64:1.
 *
 * `:where()` keeps this at element-level specificity so a colour chosen on
 * the block in the editor still wins.
 * ---------------------------------------------------------------------- */

:where(.wp-site-blocks) :is(h1, h2) {
	color: var(--wp--preset--color--espresso);
}

.has-ink-background-color :is(h1, h2),
.wp-block-cover :is(h1, h2),
h2.wp-block-post-title {
	color: inherit;
}

/* At display size on a phone, "Micropigmentation" is wider than the screen
   and was being broken wherever it ran out of room. A hyphen at a syllable
   reads as intended. */
h1.wp-block-post-title {
	hyphens: auto;
}

/* -------------------------------------------------------------------------
 * Image block styles — organic curves
 * ---------------------------------------------------------------------- */

.is-style-arch,
.is-style-arch img {
	border-radius: 100vmax 100vmax 0.75rem 0.75rem;
	overflow: hidden;
}

.is-style-soft,
.is-style-soft img {
	border-radius: 1rem;
	overflow: hidden;
}

.nl-service-photo.wp-block-post-featured-image {
	max-width: min(100%, 30rem);
	margin-inline: auto;
}

.nl-service-photo img {
	display: block;
	width: 100%;
	height: auto;
}

.wp-block-gallery .wp-block-image img {
	border-radius: 0.75rem;
}

/* -------------------------------------------------------------------------
 * Header
 * ---------------------------------------------------------------------- */

header.wp-block-template-part {
	position: sticky;
	top: 0;
	z-index: 50;
}

.nl-header {
	background: rgba(248, 244, 237, 0.86);
	border-bottom: 1px solid var(--wp--preset--color--stone);
	backdrop-filter: blur(12px);
	-webkit-backdrop-filter: blur(12px);
}

/* A backdrop-filter makes an element the containing block for any fixed
   descendant, and the navigation's overlay menu is exactly that. With the blur
   on, "fixed" resolved against the header's own box rather than the viewport,
   so opening the menu on a phone gave a panel one line tall with the whole
   menu scrolling inside it.

   The blur is dropped for as long as the menu is open. Nothing is lost: the
   overlay covers the header at that point, so there is no longer anything
   showing through to blur. */
.nl-header:has(.wp-block-navigation__responsive-container.is-menu-open) {
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
}

.nl-header .wp-block-navigation a {
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	font-family: var(--wp--preset--font-family--subheading);
	text-transform: uppercase;
	text-decoration: none;
}

.nl-header .wp-block-navigation a:hover {
	color: var(--wp--preset--color--clay);
}

/* -------------------------------------------------------------------------
 * Service menu — two groups, every service a visible row.
 *
 * Each column is a Query Loop filtered to a Service Group term, so the markup
 * is ordinary blocks and the grouping is a checkbox in wp-admin.
 * ---------------------------------------------------------------------- */

.nl-service-groups {
	gap: var(--wp--preset--spacing--60);
}

.nl-group-title {
	border-top: 2px solid var(--wp--preset--color--espresso);
	padding-top: 1.25rem;
	margin: 0;
	font-weight: 600;
	text-wrap: balance;
}

.nl-group-lede {
	margin: 0.4rem 0 1.25rem;
}

.nl-service-menu .wp-block-post-template {
	display: flex;
	flex-direction: column;
	gap: 0;
	margin: 0;
	padding: 0;
	list-style: none;
}

.nl-service-menu .wp-block-post-template > li,
.nl-service-menu .wp-block-post-template > .wp-block-post {
	margin: 0;
}

.nl-service-menu .wp-block-post-template > li + li,
.nl-service-menu .wp-block-post-template > .wp-block-post + .wp-block-post {
	border-top: 1px solid var(--wp--preset--color--stone);
}

.nl-service-row {
	padding: 1rem 0;
	position: relative;
}

/* Both the photo and the title link to the service; the row itself is not a
   link, so the description stays selectable text. */
.nl-service-row__thumb {
	flex: none;
	width: 84px;
	height: 84px;
	overflow: hidden;
	border-radius: 0.6rem;
	background: var(--wp--preset--color--linen);
	margin: 0;
}

.nl-service-row__thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}

/* A service whose photograph has not arrived yet still gets a warm tile
   rather than a gap, and the row reads as finished. */
.nl-service-row:not(:has(.nl-service-row__thumb))::before,
.nl-service-row__thumb:empty {
	content: "";
	flex: none;
	display: block;
	width: 84px;
	height: 84px;
	border-radius: 0.6rem;
	background: linear-gradient(150deg, var(--wp--preset--color--linen) 0%, var(--wp--preset--color--stone) 100%);
}

.nl-service-row__text {
	min-width: 0;
}

/* These are h4s for correct heading order under the group title, so the
   uppercase h4 treatment from theme.json has to be undone here. */
.nl-service-row__name {
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.3rem;
	font-weight: 400;
	line-height: 1.2;
	letter-spacing: 0.005em;
	text-transform: none;
	margin: 0;
}

.nl-service-row__name a {
	text-decoration: none;
	color: var(--wp--preset--color--ink);
	transition: color 0.3s ease;
}

.nl-service-row__desc {
	margin: 0.2rem 0 0;
	color: var(--wp--preset--color--bark);
	font-size: 0.8125rem;
	line-height: 1.55;
}

/* Arrow is decoration, so it lives in CSS rather than the markup. */
.nl-service-row::after {
	content: "\2192";
	margin-left: auto;
	align-self: center;
	color: var(--wp--preset--color--clay);
	opacity: 0;
	transform: translateX(-6px);
	transition: opacity 0.35s ease, transform 0.35s ease;
}

.nl-service-row:hover .nl-service-row__thumb img,
.nl-service-row:focus-within .nl-service-row__thumb img {
	transform: scale(1.07);
}

.nl-service-row:hover .nl-service-row__name a,
.nl-service-row:focus-within .nl-service-row__name a {
	color: var(--wp--preset--color--clay);
}

.nl-service-row:hover::after,
.nl-service-row:focus-within::after {
	opacity: 1;
	transform: none;
}

@media (max-width: 781px) {
	.nl-service-row__thumb,
	.nl-service-row:not(:has(.nl-service-row__thumb))::before {
		width: 68px;
		height: 68px;
	}

	.nl-service-row__name {
		font-size: 1.1rem;
	}

	.nl-service-row::after {
		display: none;
	}
}

/* Service archive grid cards share the image hover */
.nl-service-card .wp-block-post-featured-image {
	overflow: hidden;
}

/* Stands in for a photograph a service has not been given yet, so the card
   keeps its shape instead of collapsing to a title in a gap.

   The element is drawn by nurseleslie_service_image_placeholder(), which
   carries over the aspect ratio and classes the real photograph would have
   had — so the ratio, the corner radius and the block gap under it are not
   restated here and cannot drift from the templates. */
.nl-service-tile {
	display: grid;
	place-items: center;
	background: linear-gradient(150deg, var(--wp--preset--color--linen) 0%, var(--wp--preset--color--stone) 100%);
}

.nl-service-tile::after {
	content: "Photograph coming soon";
	color: var(--wp--preset--color--bark);
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	font-family: var(--wp--preset--font-family--subheading);
	text-transform: uppercase;
	text-align: center;
}

/* -------------------------------------------------------------------------
 * Service carousel — the same two groups, each column sliding left to right
 * through one large card at a time.
 *
 * The sliding itself is CSS scroll-snap, so without JavaScript the column is
 * still a working horizontal scroller. assets/js/ui.js adds the arrows, the
 * dots, and keyboard support on top.
 * ---------------------------------------------------------------------- */

.nl-service-carousel {
	position: relative;
}

/* Blurbs run to different lengths, so without this the two columns' dots
   land at different heights and the section bottom reads ragged. Letting
   each carousel fill its column pins both dot rows to the same line. */
.nl-service-groups:has(.nl-service-carousel) > .wp-block-column {
	display: flex;
	flex-direction: column;
}

.nl-service-groups:has(.nl-service-carousel) .nl-service-carousel {
	flex: 1;
	display: flex;
	flex-direction: column;
}

.nl-service-carousel .wp-block-post-template {
	display: flex;
	flex-wrap: nowrap;
	gap: var(--wp--preset--spacing--40, 1.5rem);
	margin: 0;
	padding: 0;
	list-style: none;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	overscroll-behavior-x: contain;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.nl-service-carousel .wp-block-post-template::-webkit-scrollbar {
	display: none;
}

@media (prefers-reduced-motion: no-preference) {
	.nl-service-carousel .wp-block-post-template {
		scroll-behavior: smooth;
	}
}

/* One card fills the column; the next one is a swipe away. */
.nl-service-carousel .wp-block-post-template > li,
.nl-service-carousel .wp-block-post-template > .wp-block-post {
	flex: 0 0 100%;
	min-width: 0;
	margin: 0;
	scroll-snap-align: start;
}

/* The card is narrower than the column it slides in, which keeps a 4:5
   photograph from towering over the section and leaves the margins clear
   for the arrows. */
.nl-service-slide {
	max-width: 25rem;
	margin-inline: auto;
}

/* The focus ring belongs on the track, which JS makes keyboard-scrollable. */
.nl-service-carousel .wp-block-post-template:focus-visible {
	outline: 2px solid var(--wp--preset--color--clay);
	outline-offset: 6px;
	border-radius: 1rem;
}

/* Post titles here are h4s for correct heading order under the group title,
   so the uppercase h4 treatment from theme.json has to be undone. */
.nl-service-slide__name {
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.5rem;
	font-weight: 400;
	line-height: 1.15;
	letter-spacing: 0.005em;
	text-transform: none;
	margin: 0;
}

.nl-service-slide__name a {
	text-decoration: none;
	color: var(--wp--preset--color--ink);
}

.nl-service-slide__desc {
	margin: 0;
	color: var(--wp--preset--color--bark);
	font-size: 0.875rem;
	line-height: 1.6;
}

/* Controls, all injected by ui.js ------------------------------------- */

/* Centred on the photograph rather than the whole card: ui.js measures the
   image and writes --nl-carousel-arrow-top, falling back to a sensible
   fraction of the card before it runs. */
.nl-carousel__nav {
	position: absolute;
	top: var(--nl-carousel-arrow-top, 38%);
	transform: translateY(-50%);
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	padding: 0;
	border: 1px solid var(--wp--preset--color--stone);
	border-radius: 50%;
	background: rgba(248, 244, 237, 0.94);
	color: var(--wp--preset--color--ink);
	font-size: 1rem;
	line-height: 1;
	cursor: pointer;
	z-index: 3;
	box-shadow: 0 10px 26px -12px rgba(44, 39, 31, 0.5);
	transition: background-color 0.3s ease, color 0.3s ease, opacity 0.3s ease, transform 0.3s ease;
}

.nl-carousel__nav:hover {
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--cream);
}

.nl-carousel__nav--prev {
	left: 0.75rem;
}

.nl-carousel__nav--next {
	right: 0.75rem;
}

/* Disabled at either end rather than removed, so the card never shifts. */
.nl-carousel__nav[disabled] {
	opacity: 0.28;
	cursor: default;
	box-shadow: none;
}

.nl-carousel__nav[disabled]:hover {
	background: rgba(248, 244, 237, 0.94);
	color: var(--wp--preset--color--ink);
}

.nl-carousel__dots {
	display: flex;
	justify-content: center;
	align-items: center;
	gap: 0.5rem;
	margin-top: auto;
	padding-top: 1.25rem;
}

.nl-carousel__dot {
	width: 0.4375rem;
	height: 0.4375rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--wp--preset--color--stone);
	cursor: pointer;
	transition: background-color 0.3s ease, transform 0.3s ease;
}

.nl-carousel__dot:hover {
	background: var(--wp--preset--color--taupe);
}

.nl-carousel__dot.is-active {
	background: var(--wp--preset--color--clay);
	transform: scale(1.45);
}

/* Stacked, the column is narrow enough that a card inset from it would leave
   the arrows hovering in the margin. Let the card fill instead, so the arrows
   sit over the photograph the way a phone carousel is expected to. */
@media (max-width: 781px) {
	.nl-service-slide {
		max-width: none;
	}
}

/* -------------------------------------------------------------------------
 * Navigation — group labels inside the Services dropdown
 * ---------------------------------------------------------------------- */

.nl-header .wp-block-navigation__submenu-container .nl-nav-label > a {
	font-size: 0.625rem;
	font-weight: 700;
	letter-spacing: 0.18em;
	color: var(--wp--preset--color--taupe);
	padding-bottom: 0.15rem;
	cursor: default;
}

.nl-header .wp-block-navigation__submenu-container .nl-nav-label:not(:first-child) > a {
	margin-top: 0.5rem;
	border-top: 1px solid var(--wp--preset--color--linen);
	padding-top: 0.75rem;
}

.nl-header .wp-block-navigation__submenu-container .nl-nav-label > a:hover {
	color: var(--wp--preset--color--taupe);
}

/* -------------------------------------------------------------------------
 * About — the portrait sits in the text rather than beside a block of it.
 *
 * It was a Media & Text block before, which is a two-column grid: the copy
 * that fit beside the portrait went in the column, and the paragraph that did
 * not had to sit under the whole thing. Whenever the column ran shorter than
 * the photograph, that left a band of empty space between the two.
 *
 * A float instead, so the copy wraps the portrait and runs on underneath it
 * as one piece of writing.
 * ---------------------------------------------------------------------- */

.nl-about-portrait.alignleft {
	margin-top: 0.35rem;
	margin-right: var(--wp--preset--spacing--50);
	margin-bottom: var(--wp--preset--spacing--40);
}

/* A float needs a column wide enough to hold a line of text beside it. On a
   phone there is no such column, so the portrait goes back to being its own
   full-width block above the copy. */
@media (max-width: 781px) {
	.nl-about-portrait.alignleft {
		float: none;
		width: 100%;
		max-width: 22rem;
		margin-right: 0;
		margin-inline: auto;
	}

	.nl-about-portrait.alignleft img {
		width: 100%;
	}
}

/* Ends the wrap. Without it a separator following a portrait taller than the
   copy is drawn across the middle of the photograph. */
.nl-clear {
	clear: both;
}

/* -------------------------------------------------------------------------
 * Subtle reveal-on-scroll (progressive enhancement via assets/js/reveal.js)
 * ---------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
	html.nl-js .nl-reveal {
		opacity: 0;
		transform: translateY(28px);
		transition: opacity 0.9s ease, transform 0.9s cubic-bezier(0.22, 1, 0.36, 1);
	}

	html.nl-js .nl-reveal.is-visible {
		opacity: 1;
		transform: none;
	}

	/* Children of a `.nl-stagger` element cascade in after their section */
	html.nl-js .nl-reveal .nl-stagger > * {
		opacity: 0;
		transform: translateY(26px);
		transition: opacity 0.8s ease, transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
	}

	html.nl-js .nl-reveal.is-visible .nl-stagger > * {
		opacity: 1;
		transform: none;
	}

	html.nl-js .nl-reveal.is-visible .nl-stagger > :nth-child(2) { transition-delay: 0.12s; }
	html.nl-js .nl-reveal.is-visible .nl-stagger > :nth-child(3) { transition-delay: 0.24s; }
	html.nl-js .nl-reveal.is-visible .nl-stagger > :nth-child(4) { transition-delay: 0.36s; }
	html.nl-js .nl-reveal.is-visible .nl-stagger > :nth-child(5) { transition-delay: 0.48s; }
	html.nl-js .nl-reveal.is-visible .nl-stagger > :nth-child(6) { transition-delay: 0.6s; }
	html.nl-js .nl-reveal.is-visible .nl-stagger > :nth-child(7) { transition-delay: 0.72s; }
	html.nl-js .nl-reveal.is-visible .nl-stagger > :nth-child(8) { transition-delay: 0.84s; }

	/* Headings with `.nl-words` surface one word at a time (spans are
	   JS-created, so this never hides static markup). */
	.nl-word {
		display: inline-block;
		opacity: 0;
		transform: translateY(0.4em);
		transition: opacity 0.8s ease, transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
	}

	.nl-words.is-visible .nl-word {
		opacity: 1;
		transform: none;
	}
}

/* -------------------------------------------------------------------------
 * Entrance veil — Lanserhof-style "stepping through the door": the cream
 * cover opens from the center as an expanding arch (the theme's signature
 * shape) that grows until the page fills the screen. The wordmark holds
 * on the cover, then slips away as the arch opens.
 *
 * The aperture is an invisible centered box whose enormous box-shadow
 * paints the cover; animating the box's size opens the "doorway".
 * Markup lives in the hero pattern; an inline script removes the veil for
 * repeat views in the same session. Pointer-events stay off throughout,
 * so a stuck veil can never block the page.
 * ---------------------------------------------------------------------- */

.nl-veil {
	position: fixed;
	inset: 0;
	z-index: 200;
	display: grid;
	place-items: center;
	overflow: hidden;
	pointer-events: none;
	opacity: 0;
	visibility: hidden;
}

.nl-veil::before {
	content: "";
	grid-area: 1 / 1;
	width: 0;
	height: 0;
	border-radius: 100vmax 100vmax 0 0;
	box-shadow: 0 0 0 160vmax var(--wp--preset--color--cream);
}

/* The brand mark holds on the cover — the uploaded Site Logo when there is
   one, else the copy bundled with the theme. If the image is ever missing the
   veil simply opens on empty cream and the animation still runs. */
.nl-veil__mark {
	grid-area: 1 / 1;
	width: clamp(160px, 24vw, 260px);
	height: auto;
	object-fit: contain;
}

/* Timeline: wordmark rises in and holds (0–0.95s), slips away (by 1.25s),
   then the arch doorway opens (1.25–2.75s). */
@media (prefers-reduced-motion: no-preference) {
	.nl-veil {
		animation: nl-veil-stage 2.8s steps(1, end) both;
	}

	.nl-veil::before {
		animation: nl-veil-open 1.5s cubic-bezier(0.77, 0, 0.175, 1) 1.25s both;
	}

	.nl-veil__mark {
		animation: nl-veil-brand 1.25s ease both;
	}
}

/* Veil stays fully present while the arch opens, then releases. */
@keyframes nl-veil-stage {
	0%, 99% {
		opacity: 1;
		visibility: visible;
	}
	100% {
		opacity: 0;
		visibility: hidden;
	}
}

@keyframes nl-veil-open {
	0% {
		width: 0;
		height: 0;
		border-radius: 100vmax 100vmax 0 0;
	}
	70% {
		border-radius: 100vmax 100vmax 0 0;
	}
	100% {
		width: 130vw;
		height: 140vh;
		border-radius: 0;
	}
}

@keyframes nl-veil-brand {
	0% {
		opacity: 0;
		transform: translateY(14px);
	}
	24%, 76% {
		opacity: 1;
		transform: none;
	}
	100% {
		opacity: 0;
		transform: translateY(-10px);
	}
}

.editor-styles-wrapper .nl-veil {
	display: none;
}

/* -------------------------------------------------------------------------
 * Navigation submenu — arrow rotates, panel and items ease in left-to-right.
 * Scoped to the closed (desktop) responsive container so the mobile
 * overlay menu keeps its plain, always-visible list.
 * ---------------------------------------------------------------------- */

/* Desktop only, like the motion below it. In the overlay the submenu is part
   of one plain list, so the panel chrome would draw a bordered, shadowed card
   inside an already-cream full-screen menu — and its 250px floor is wider than
   the content box on a narrow phone, which pushes the menu into a sideways
   scroll. */
.nl-header .wp-block-navigation__responsive-container:not(.is-menu-open) .wp-block-navigation__submenu-container {
	background: var(--wp--preset--color--cream);
	border: 1px solid var(--wp--preset--color--stone);
	border-radius: 2px;
	box-shadow: 0 22px 48px -20px rgba(44, 39, 31, 0.3);
	padding: 0.4rem 0;
	min-width: 250px;
}

.nl-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	padding: 0.55rem 1.2rem;
}

.nl-header .wp-block-navigation__submenu-icon {
	transition: transform 0.3s ease;
}

.nl-header .has-child:hover .wp-block-navigation__submenu-icon,
.nl-header .has-child:focus-within .wp-block-navigation__submenu-icon,
.nl-header button[aria-expanded="true"] .wp-block-navigation__submenu-icon {
	transform: rotate(180deg);
}

@media (prefers-reduced-motion: no-preference) {
	.nl-header .wp-block-navigation__responsive-container:not(.is-menu-open) .wp-block-navigation__submenu-container {
		transition: opacity 0.3s ease, transform 0.35s ease, visibility 0.3s;
		transform: translateY(10px);
	}

	.nl-header .wp-block-navigation__responsive-container:not(.is-menu-open) .has-child:hover > .wp-block-navigation__submenu-container,
	.nl-header .wp-block-navigation__responsive-container:not(.is-menu-open) .has-child:focus-within > .wp-block-navigation__submenu-container {
		transform: none;
	}

	.nl-header .wp-block-navigation__responsive-container:not(.is-menu-open) .wp-block-navigation__submenu-container > .wp-block-navigation-item {
		opacity: 0;
		transform: translateX(-12px);
		transition: opacity 0.3s ease, transform 0.35s ease;
	}

	.nl-header .wp-block-navigation__responsive-container:not(.is-menu-open) .has-child:hover > .wp-block-navigation__submenu-container > .wp-block-navigation-item,
	.nl-header .wp-block-navigation__responsive-container:not(.is-menu-open) .has-child:focus-within > .wp-block-navigation__submenu-container > .wp-block-navigation-item {
		opacity: 1;
		transform: none;
	}

	.nl-header .wp-block-navigation__submenu-container > .wp-block-navigation-item:nth-child(2) { transition-delay: 0.05s; }
	.nl-header .wp-block-navigation__submenu-container > .wp-block-navigation-item:nth-child(3) { transition-delay: 0.1s; }
	.nl-header .wp-block-navigation__submenu-container > .wp-block-navigation-item:nth-child(4) { transition-delay: 0.15s; }
	.nl-header .wp-block-navigation__submenu-container > .wp-block-navigation-item:nth-child(5) { transition-delay: 0.2s; }
	.nl-header .wp-block-navigation__submenu-container > .wp-block-navigation-item:nth-child(6) { transition-delay: 0.25s; }
}

/* -------------------------------------------------------------------------
 * Crossfading slides (`.nl-slides` on a group of images; assets/js/ui.js
 * rotates them). Without JS only the first image shows — a clean static
 * fallback and what the editor previews.
 * ---------------------------------------------------------------------- */

.nl-slides {
	position: relative;
}

.nl-slides:not(.is-ready) figure:not(:first-child) {
	display: none;
}

.nl-slides:not(.is-ready) img,
.nl-slides.is-ready img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.nl-slides:not(.is-ready) figure:first-child,
.nl-slides.is-ready figure {
	position: absolute;
	inset: 0;
	margin: 0;
}

.nl-slides.is-ready {
	overflow: hidden;
}

.nl-slides.is-ready img {
	opacity: 0;
	transition: opacity 1.4s ease;
}

.nl-slides.is-ready img.is-active {
	opacity: 1;
}

.nl-slides__dots {
	position: absolute;
	bottom: 1.1rem;
	left: 50%;
	transform: translateX(-50%);
	display: flex;
	gap: 0.5rem;
	z-index: 2;
}

.nl-slides__dot {
	width: 0.5rem;
	height: 0.5rem;
	border-radius: 50%;
	border: 0;
	padding: 0;
	cursor: pointer;
	background: rgba(248, 244, 237, 0.55);
	transition: background-color 0.3s ease, transform 0.3s ease;
}

.nl-slides__dot.is-active {
	background: var(--wp--preset--color--cream);
	transform: scale(1.3);
}

/* The extra hero slides are a data source, not a visible gallery: assets/js/
   ui.js promotes them to cover backgrounds and removes the gallery. Hiding it
   means a no-JS visitor sees just the Cover's own background image. */
.nl-hero-extra-slides {
	display: none;
}

/* Hero variant — the cover's own background images are the slides.
   Before JS readies (or without JS) only the first image shows. */
.nl-hero-slides:not(.is-ready) .wp-block-cover__image-background:nth-of-type(n+2) {
	display: none;
}

.nl-hero-slides.is-ready .wp-block-cover__image-background {
	opacity: 0;
	transition: opacity 1.8s ease;
}

.nl-hero-slides.is-ready .wp-block-cover__image-background.is-active {
	opacity: 1;
}

.nl-hero-slides .nl-slides__dots {
	bottom: 2rem;
	z-index: 3;
}

/* -------------------------------------------------------------------------
 * Hero parallax — the cover media drifts slower than the page scroll.
 * The base scale leaves headroom for the JS translate; reduced-motion
 * users get a static hero. Both are kept small (6%, and a drift of 2.5% of
 * the viewport) because the scale is a zoom, and the slides are meant to show
 * the whole of Leslie at work.
 * ---------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
	html.nl-js .nl-parallax .wp-block-cover__image-background,
	html.nl-js .nl-parallax .wp-block-cover__video-background {
		transform: scale(1.06);
		will-change: transform;
	}
}

/* -------------------------------------------------------------------------
 * Service card hover — image warms and an "Explore" pill rises in.
 * ---------------------------------------------------------------------- */

.nl-service-card .wp-block-post-featured-image {
	position: relative;
	overflow: hidden;
}

.nl-service-card .wp-block-post-featured-image a::before {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, transparent 55%, rgba(44, 39, 31, 0.38) 100%);
	opacity: 0;
	transition: opacity 0.5s ease;
	z-index: 1;
}

.nl-service-card .wp-block-post-featured-image a::after {
	content: "Explore →";
	position: absolute;
	left: 50%;
	bottom: 1.1rem;
	transform: translate(-50%, 10px);
	z-index: 2;
	background: rgba(248, 244, 237, 0.94);
	color: var(--wp--preset--color--ink);
	font-family: var(--wp--preset--font-family--subheading);
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	padding: 0.6rem 1.3rem;
	border-radius: 999px;
	white-space: nowrap;
	opacity: 0;
	transition: opacity 0.45s ease, transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

.nl-service-card:hover .wp-block-post-featured-image a::before,
.nl-service-card:focus-within .wp-block-post-featured-image a::before,
.nl-service-card:hover .wp-block-post-featured-image a::after,
.nl-service-card:focus-within .wp-block-post-featured-image a::after {
	opacity: 1;
}

.nl-service-card:hover .wp-block-post-featured-image a::after,
.nl-service-card:focus-within .wp-block-post-featured-image a::after {
	transform: translate(-50%, 0);
}

/* -------------------------------------------------------------------------
 * Before / after comparison (`.nl-ba` on a group holding exactly two
 * images: before first, after second). assets/js/ui.js adds the range
 * control; without JS the two photos simply sit side by side.
 * ---------------------------------------------------------------------- */

.nl-ba {
	--nl-ba: 50%;
	position: relative;
}

.nl-ba.is-ready {
	overflow: hidden;
	border-radius: 1rem;
}

.nl-ba.is-ready figure {
	margin: 0;
	position: relative;
}

.nl-ba.is-ready figure img {
	display: block;
	width: 100%;
}

.nl-ba.is-ready figure:last-of-type {
	position: absolute;
	inset: 0;
	clip-path: inset(0 0 0 var(--nl-ba));
}

.nl-ba.is-ready figure:last-of-type img {
	height: 100%;
	object-fit: cover;
}

/* Before and After sit above the slider as column titles (added by ui.js
   with the range control), not as pills on the photographs, where they hid
   part of the result. */
.nl-ba__labels {
	display: grid;
	grid-template-columns: 1fr 1fr;
	margin: 0 0 0.6rem;
	color: var(--wp--preset--color--ink);
	font-family: var(--wp--preset--font-family--subheading);
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	text-align: center;
}

.nl-ba.is-ready::before {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	left: var(--nl-ba);
	width: 2px;
	background: var(--wp--preset--color--cream);
	box-shadow: 0 0 14px rgba(44, 39, 31, 0.35);
	pointer-events: none;
	z-index: 2;
}

.nl-ba.is-ready::after {
	content: "↔";
	position: absolute;
	top: 50%;
	left: var(--nl-ba);
	transform: translate(-50%, -50%);
	width: 2.5rem;
	height: 2.5rem;
	display: grid;
	place-items: center;
	background: var(--wp--preset--color--cream);
	color: var(--wp--preset--color--ink);
	border-radius: 50%;
	box-shadow: 0 8px 20px -6px rgba(44, 39, 31, 0.45);
	pointer-events: none;
	z-index: 2;
}

.nl-ba__caption {
	text-align: center;
	margin: 1rem 0 0;
}

.nl-ba__range {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	margin: 0;
	opacity: 0;
	cursor: ew-resize;
	z-index: 3;
	-webkit-appearance: none;
	appearance: none;
}

/* -------------------------------------------------------------------------
 * Before / after gallery (`.nl-ba-grid`) — a page of results, each
 * pair shown whole rather than behind a drag handle. The two photographs are
 * always side by side, phones included: splitting them across a scroll would
 * cost the comparison that is the whole point of the pair.
 * ---------------------------------------------------------------------- */

.nl-ba-gallery__title {
	text-align: center;
	margin: 0 0 var(--wp--preset--spacing--50);
}

.nl-ba-grid {
	--nl-ba-grid-columns: 2;
	display: grid;
	grid-template-columns: repeat(var(--nl-ba-grid-columns), minmax(0, 1fr));
	gap: var(--wp--preset--spacing--50);
	list-style: none;
	margin: 0;
	padding: 0;
}

@media (max-width: 781px) {
	.nl-ba-grid {
		grid-template-columns: 1fr;
	}
}

.nl-ba-pair {
	margin: 0;
}

.nl-ba-pair__frames {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 2px;
	border-radius: 1rem;
	overflow: hidden;
	background: var(--wp--preset--color--stone);
}

.nl-ba-pair__frame {
	position: relative;
	margin: 0;
	/* A common box for both halves: an unequal pair reads as a difference in
	   the result rather than in the framing. The shape comes from the pair
	   itself — see nurseleslie_pair_aspect_ratio() — because the studio shoots
	   mostly portrait but not always, and cropping a landscape frame to
	   portrait takes the result out of the picture. Portrait is the fallback,
	   being the common case. */
	aspect-ratio: var(--nl-pair-ratio, 3 / 4);
	background: var(--wp--preset--color--linen);
}

.nl-ba-pair__frame img {
	display: block;
	width: 100%;
	height: 100%;
	/* "contain" where the two halves are not the same shape, so neither is
	   cropped to match the other; the frame's own background fills the rest. */
	object-fit: var(--nl-pair-fit, cover);
}

/* Column titles over each pair, rendered by the block rather than drawn on
   the photographs, so no part of either half is covered. */
.nl-ba-pair__labels {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 2px;
	margin: 0 0 0.5rem;
	color: var(--wp--preset--color--ink);
	font-family: var(--wp--preset--font-family--subheading);
	font-size: 0.625rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	text-align: center;
}

.nl-ba-pair__caption {
	text-align: center;
	margin: 0.85rem 0 0;
}

/* Enlarging is offered only where it works: assets/js/ui.js adds the button
   and this cursor together, so a no-JS visitor is never invited to click a
   photograph that cannot open. */
.nl-ba-pair__frames.is-zoomable {
	cursor: zoom-in;
}

/* -------------------------------------------------------------------------
 * Lightbox — opens a pair at full size, both halves together. Core's own
 * lightbox works on single images and would break the pair apart.
 * ---------------------------------------------------------------------- */

.nl-lightbox {
	position: fixed;
	inset: 0;
	z-index: 200;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: clamp(1rem, 4vw, 3rem);
	border: 0;
	width: 100%;
	height: 100%;
	max-width: none;
	max-height: none;
	background: rgba(44, 39, 31, 0.94);
	opacity: 0;
	transition: opacity 0.25s ease;
}

/* The UA stylesheet hides a closed dialog, but an author rule outranks it —
   without this the overlay would sit over the page from the moment it is
   built. */
.nl-lightbox:not([open]) {
	display: none;
}

.nl-lightbox.is-shown {
	opacity: 1;
}

.nl-lightbox::backdrop {
	background: rgba(44, 39, 31, 0.94);
}

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

.nl-lightbox__figures {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 0.75rem;
	width: 100%;
	max-width: 1100px;
}

.nl-lightbox__figures figure {
	margin: 0;
	position: relative;
}

.nl-lightbox__figures img {
	display: block;
	width: 100%;
	height: auto;
	max-height: 78vh;
	object-fit: contain;
	border-radius: 0.5rem;
}

.nl-lightbox__label {
	display: block;
	text-align: center;
	margin-top: 0.6rem;
	color: var(--wp--preset--color--cream);
	font-family: var(--wp--preset--font-family--subheading);
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

.nl-lightbox__caption {
	margin: 1.25rem 0 0;
	text-align: center;
	color: var(--wp--preset--color--stone);
	font-family: var(--wp--preset--font-family--body);
	font-size: 0.875rem;
}

.nl-lightbox__close {
	position: absolute;
	top: 1rem;
	right: 1rem;
	width: 2.75rem;
	height: 2.75rem;
	display: grid;
	place-items: center;
	background: var(--wp--preset--color--cream);
	color: var(--wp--preset--color--ink);
	border: 0;
	border-radius: 50%;
	font-size: 1.25rem;
	line-height: 1;
	cursor: pointer;
}

.nl-lightbox__close:hover {
	background: var(--wp--preset--color--stone);
}

/* -------------------------------------------------------------------------
 * Floating book pill — small screens only (the sticky header CTA already
 * covers desktop). Injected by assets/js/ui.js after scrolling past
 * the hero.
 * ---------------------------------------------------------------------- */

.nl-book-float {
	position: fixed;
	right: 1.1rem;
	bottom: 1.1rem;
	z-index: 90;
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--cream);
	text-decoration: none;
	font-family: var(--wp--preset--font-family--subheading);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	padding: 0.95rem 1.7rem;
	border-radius: 999px;
	box-shadow: 0 18px 40px -14px rgba(44, 39, 31, 0.55);
	opacity: 0;
	transform: translateY(14px);
	pointer-events: none;
	transition: opacity 0.4s ease, transform 0.4s ease;
}

.nl-book-float.is-shown {
	opacity: 1;
	transform: none;
	pointer-events: auto;
}

/* The pill is appended to the body at z-index 90, above the header's 50, so it
   would otherwise float over the open menu — and it only ever appears at the
   widths the overlay menu is used at. */
body:has(.wp-block-navigation__responsive-container.is-menu-open) .nl-book-float {
	display: none;
}

.nl-book-float:hover {
	color: var(--wp--preset--color--cream);
	background: var(--wp--preset--color--bark);
}

@media (min-width: 900px) {
	.nl-book-float {
		display: none;
	}
}

.editor-styles-wrapper .nl-book-float {
	display: none;
}

/* -------------------------------------------------------------------------
 * 18+ age gate — blur-by-default; assets/js/age-gate.js reveals on consent.
 * Without JavaScript the gallery stays blurred with a notice (safe default).
 *
 * Keyed on "is-gated", which PHP adds to the wrapper as the content renders
 * (nurseleslie_arm_age_gate). The editor canvas never runs that filter, so a
 * gated gallery stays legible while Leslie is editing it.
 * ---------------------------------------------------------------------- */

.nl-gated.is-gated {
	position: relative;
}

body:not(.nl-age-confirmed) .nl-gated.is-gated > :not(.nl-gate-overlay) {
	filter: blur(30px) saturate(0.5);
	pointer-events: none;
	user-select: none;
}

body:not(.nl-age-confirmed) .nl-gated.is-gated {
	overflow: hidden;
	border-radius: 1rem;
	min-height: 320px;
}

/* No-JS fallback notice. Scoped to documents where the JS flag never landed,
   so it does not sit behind the consent panel that replaces it. */
html:not(.nl-js) body:not(.nl-age-confirmed) .nl-gated.is-gated::after {
	content: attr(data-nl-nojs);
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	padding: 2rem;
	font-size: 0.9375rem;
	color: var(--wp--preset--color--ink);
	background: color-mix(in srgb, var(--wp--preset--color--linen) 72%, transparent);
}

/* JS-injected consent overlay sits above the fallback */
.nl-gate-overlay {
	position: absolute;
	inset: 0;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 1.5rem;
	background: color-mix(in srgb, var(--wp--preset--color--linen) 80%, transparent);
}

.nl-gate-overlay__panel {
	max-width: 26rem;
	text-align: center;
	background: var(--wp--preset--color--cream);
	border: 1px solid var(--wp--preset--color--stone);
	border-radius: 1rem;
	padding: clamp(1.5rem, 4vw, 2.5rem);
	box-shadow: 0 24px 60px -24px rgba(44, 39, 31, 0.35);
}

.nl-gate-overlay__title {
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.5rem;
	font-weight: 400;
	margin: 0 0 0.5rem;
	color: var(--wp--preset--color--ink);
}

.nl-gate-overlay__text {
	font-size: 0.9375rem;
	margin: 0 0 1.25rem;
	color: var(--wp--preset--color--bark);
}

.nl-gate-overlay__confirm {
	display: inline-block;
	cursor: pointer;
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--cream);
	border: 1px solid var(--wp--preset--color--ink);
	border-radius: 2px;
	font-family: var(--wp--preset--font-family--subheading);
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	padding: 0.9rem 1.9rem;
	transition: background-color 0.35s ease;
}

.nl-gate-overlay__confirm:hover {
	background: var(--wp--preset--color--bark);
}

.nl-gate-overlay__decline {
	display: block;
	margin-top: 1rem;
	font-size: 0.8125rem;
	color: var(--wp--preset--color--taupe);
}

/* -------------------------------------------------------------------------
 * Quotes / testimonials
 * ---------------------------------------------------------------------- */

.wp-block-quote {
	border: none;
	padding: 0;
}

/* The reviews are set in the body face rather than the heading one. Gilda
   Display has no italic — a browser asked for one slants the roman
   mechanically, which reads as a rendering fault — and it is a display type
   besides, cut for a line rather than for sixty words of someone talking.
   Karla's italic is drawn, and carries the quote at length. */
.wp-block-quote p {
	font-family: var(--wp--preset--font-family--body);
	font-size: 1.1875rem;
	font-style: italic;
	line-height: 1.6;
}

.wp-block-quote cite {
	display: block;
	margin-top: 1rem;
	font-family: var(--wp--preset--font-family--subheading);
	font-size: 0.75rem;
	font-style: normal;
	font-weight: 600;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--wp--preset--color--taupe);
}

/* -------------------------------------------------------------------------
 * Client reviews on a service page.
 *
 * In the body copy a quote block reads as more description in a different
 * font. Every quote inside a service's content is a review, so each one is
 * given a card of its own with a label above it — the break between "what
 * this service is" and "what a client said about it" is then unmistakable at
 * a glance.
 *
 * The label names the work as well ("Brows Client"): --nl-review-label is set
 * per service by nurseleslie_review_label_style(), and the fallback here
 * covers a page rendered without it.
 *
 * Scoped to the service post content, so quotes used for anything else on
 * pages or posts keep their plain treatment.
 * ---------------------------------------------------------------------- */

/* The service hero is alignwide, which on a phone is simply the screen and
   reads well, but on a desktop is 1240px of 16:9 — over 690px tall, so the
   photograph fills the window and the service's own words start below the
   fold. Capped to something a headline and an image can share. */
@media (min-width: 900px) {
	.single-service .wp-block-post-featured-image.alignwide {
		max-width: 780px;
		margin-inline: auto;
	}
}

.single-service .wp-block-post-content .wp-block-quote {
	position: relative;
	margin: 1.5rem 0 0;
	padding: clamp(2.25rem, 5vw, 2.75rem) clamp(1.4rem, 4vw, 2.25rem) clamp(1.4rem, 4vw, 2rem);
	background: var(--wp--preset--color--linen);
	border: 1px solid var(--wp--preset--color--stone);
	border-radius: 1rem;
}

/* The label rides on the card's top edge, cut into the border. */
.single-service .wp-block-post-content .wp-block-quote::before {
	content: var(--nl-review-label, "Client Review");
	position: absolute;
	top: 0;
	left: clamp(1.4rem, 4vw, 2.25rem);
	transform: translateY(-50%);
	padding: 0.35rem 0.9rem;
	background: var(--wp--preset--color--cream);
	border: 1px solid var(--wp--preset--color--stone);
	border-radius: 999px;
	font-family: var(--wp--preset--font-family--subheading);
	font-size: 0.625rem;
	font-weight: 700;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--wp--preset--color--clay);
}

/* First card in the run carries a little more air above it, separating the
   reviews from the description that precedes them. */
.single-service .wp-block-post-content .wp-block-quote:first-of-type {
	margin-top: var(--wp--preset--spacing--60);
}

.single-service .wp-block-post-content .wp-block-quote p {
	font-size: 1.25rem;
	color: var(--wp--preset--color--ink);
}

.single-service .wp-block-post-content .wp-block-quote p:last-of-type {
	margin-bottom: 0;
}

.single-service .wp-block-post-content .wp-block-quote cite {
	color: var(--wp--preset--color--bark);
}

/* -------------------------------------------------------------------------
 * Service techniques (`.nl-techniques`) — the ways one service can be done,
 * as a column of disclosures. The teaser stays on the row whether or not it
 * is open, so the five brow techniques can be compared without opening any of
 * them; only the full description is behind the click.
 *
 * The rows are `<details>`, so the open/closed state, the keyboard handling
 * and find-in-page all come from the browser. Nothing here is load-bearing —
 * with the stylesheet gone the list is still a readable set of headings.
 * ---------------------------------------------------------------------- */

.nl-techniques__title {
	text-align: center;
	margin: 0 0 var(--wp--preset--spacing--50);
}

.nl-techniques__list {
	list-style: none;
	margin: 0;
	padding: 0;
	border-top: 1px solid var(--wp--preset--color--stone);
}

.nl-technique {
	border-bottom: 1px solid var(--wp--preset--color--stone);
}

.nl-technique__summary {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1.25rem;
	padding: 1.4rem 0;
	cursor: pointer;
	list-style: none;
}

/* Safari draws its own triangle through ::-webkit-details-marker rather than
   honouring `list-style: none` on the summary. */
.nl-technique__summary::-webkit-details-marker {
	display: none;
}

.nl-technique__summary.is-static {
	cursor: default;
}

.nl-technique__summary:focus-visible {
	outline: 2px solid var(--wp--preset--color--espresso);
	outline-offset: 3px;
}

.nl-technique__heading {
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
	min-width: 0;
}

.nl-technique__name {
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.25rem;
	line-height: 1.25;
	color: var(--wp--preset--color--ink);
}

.nl-technique__teaser {
	font-size: 0.9rem;
	line-height: 1.6;
	color: var(--wp--preset--color--bark);
	max-width: 54ch;
}

/* A plus that becomes a minus. Two rules rather than a glyph so it stays
   centred at any font size and inherits the row's colour. */
.nl-technique__marker {
	position: relative;
	flex: none;
	width: 0.85rem;
	height: 0.85rem;
	align-self: center;
}

.nl-technique__marker::before,
.nl-technique__marker::after {
	content: "";
	position: absolute;
	inset: 50% 0 auto 0;
	height: 1px;
	background: var(--wp--preset--color--clay);
}

.nl-technique__marker::after {
	transform: rotate(90deg);
}

.nl-technique__disclosure[open] .nl-technique__marker::after {
	transform: rotate(0deg);
}

.nl-technique__body {
	padding: 0 0 1.6rem;
	max-width: 62ch;
}

.nl-technique__body p {
	color: var(--wp--preset--color--bark);
	margin: 0 0 1rem;
}

.nl-technique__body p:last-child {
	margin-bottom: 0;
}

@media (prefers-reduced-motion: no-preference) {
	.nl-technique__marker::after {
		transition: transform 0.3s ease;
	}

	.nl-technique__disclosure[open] .nl-technique__body {
		animation: nl-technique-open 0.35s ease both;
	}

	@keyframes nl-technique-open {
		from {
			opacity: 0;
			transform: translateY(-4px);
		}
	}
}

@media (max-width: 600px) {
	.nl-technique__summary {
		gap: 0.9rem;
		padding: 1.15rem 0;
	}

	.nl-technique__name {
		font-size: 1.1rem;
	}
}

/* Service questions (`.nl-faqs`) reuse the technique rows above. A question
   runs longer than a technique's name, so it is set a step smaller to keep
   most of them to one line. */
.nl-faqs .nl-technique__name {
	font-size: 1.1rem;
}

@media (max-width: 600px) {
	.nl-faqs .nl-technique__name {
		font-size: 1rem;
	}
}

/* -------------------------------------------------------------------------
 * Misc
 * ---------------------------------------------------------------------- */

.wp-block-separator {
	border-color: var(--wp--preset--color--stone);
	opacity: 1;
}

.wp-site-blocks > main {
	display: block;
}
