/*
Theme Name: TMoss Law Theme
Theme URI: https://tmosslaw.com
Author: Sebo Marketing
Author URI: https://sebomarketing.com
Description: The custom block theme for TMoss Law, designed and built by Sebo Marketing. Colours, typography, and spacing are managed centrally, so the look of the whole site stays consistent as pages are edited. Edit pages and posts in the normal WordPress editor; the practice-area and location sections are available as reusable patterns under "TMoss Law" in the block inserter.
Requires at least: 6.6
Tested up to: 7.0
Requires PHP: 8.1
Version: 1.0.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: sebo
Tags: block-theme, full-site-editing, e-commerce, one-column, custom-colors, custom-menu, editor-style
*/

/* NOTE FOR WHOEVER MAINTAINS THIS, not for the client.
   `Theme Name` is per-client and was changed to "TMoss Law Theme" on
   4 September 2026. Everything else identifying the starter is deliberately
   unchanged: the directory (`sebo`), the text domain (`sebo`), the PHP prefix
   (`sebo_`/`SEBO_`), the pattern category slug (`sebo`), and the `sb-` class
   names. That is what keeps improvements movable between this site and the
   Sebo Theme starter, and the slug is load-bearing in scripts/config.sh,
   deploy.sh and the live server path. Rename the display name per client;
   leave the slug alone. */

/* -------------------------------------------------------------------------
   1. Base
   ---------------------------------------------------------------------- */

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
	}
}

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
	font-optical-sizing: auto;
}

/* Balance short headings rather than leaving a single orphaned word. */
h1,
h2,
h3,
.wp-block-post-title {
	text-wrap: balance;
}

p,
li {
	text-wrap: pretty;
}

/* Standfirsts — the centred large paragraph under a page's H1 — are display
   type, so they get the same balancing as the headings above them rather than
   `pretty`. `pretty` only protects the last line from an orphan; it leaves the
   lines themselves uneven, which is what the client saw on the practice pages.
   Balance evens the measure so a two-line standfirst reads as two halves. */
p.has-text-align-center.has-large-font-size {
	text-wrap: balance;
}

/* Body copy caps its measure even inside wide containers. */
:where(.entry-content) p:not([class*="has-"]) {
	max-width: 68ch;
}

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

/* WordPress puts a block-gap margin between every top-level block, which
   leaves a white strip between the header and the first full-bleed section,
   and another between the last section and the footer. Sections carry their
   own padding, so those gaps are never wanted here. */
.wp-site-blocks > main,
.wp-site-blocks > .wp-block-template-part {
	margin-block-start: 0;
}

/* -------------------------------------------------------------------------
   2. Focus — a single visible treatment everywhere.
      Never remove this; keyboard users depend on it.
   ---------------------------------------------------------------------- */

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: 3px solid var(--wp--preset--color--action);
	outline-offset: 2px;
	border-radius: 2px;
}

/* Dark grounds need a light ring to stay visible. */
.sb-on-dark :where(a, button, input, select, textarea):focus-visible {
	outline-color: var(--wp--preset--color--accent);
}

.skip-link {
	position: absolute;
	top: -100vh;
	left: 0;
	z-index: 999999;
	padding: 0.85rem 1.5rem;
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--base);
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	text-decoration: none;
	border-bottom-right-radius: 6px;
}

.skip-link:focus {
	top: 0;
}

.screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* -------------------------------------------------------------------------
   3. Links — underlines that sit below the baseline rather than
      slicing through descenders.
   ---------------------------------------------------------------------- */

:where(.entry-content, .wp-block-post-content) a:where(:not(.wp-element-button):not(.wp-block-button__link)) {
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
	text-decoration-color: rgba(44, 97, 63, 0.4);
	transition: text-decoration-color var(--wp--custom--transition--base);
}

:where(.entry-content, .wp-block-post-content) a:where(:not(.wp-element-button)):hover {
	text-decoration-color: currentColor;
}

/* Buttons and nav links must not inherit the content underline. */
.wp-block-navigation a,
.wp-element-button,
.wp-block-button__link {
	text-decoration: none;
}

.wp-element-button,
.wp-block-button__link {
	transition: background-color var(--wp--custom--transition--base),
		color var(--wp--custom--transition--base),
		transform var(--wp--custom--transition--base);
}

.wp-element-button:hover,
.wp-block-button__link:hover {
	transform: translateY(-1px);
}

/* Secondary button: outlined, for lower-priority actions. */
.wp-block-button.is-style-outline > .wp-block-button__link {
	background: transparent;
	color: var(--wp--preset--color--action);
	border: 1.5px solid var(--wp--preset--color--action);
}

.wp-block-button.is-style-outline > .wp-block-button__link:hover {
	background: var(--wp--preset--color--action);
	color: var(--wp--preset--color--base);
}

/* -------------------------------------------------------------------------
   4. Header
   ---------------------------------------------------------------------- */

/* Stickiness has to live on the template-part wrapper, not on .sb-header.
   WordPress renders the header part inside a <div class="wp-block-template-part">
   that is exactly as tall as the header, and a sticky element cannot travel
   beyond its containing block — so sticking it to .sb-header gives it zero
   travel and it scrolls away immediately. */
.wp-site-blocks > .wp-block-template-part:has(.sb-header),
.wp-site-blocks > .wp-block-template-part:first-child {
	position: sticky;
	/* The admin bar is position:fixed at the top of the viewport for logged-in
	   users, so a header stuck to 0 slides underneath it. WordPress exposes the
	   bar's height as a custom property (32px, or 46px under 782px), which also
	   keeps this correct when the bar is absent. */
	top: var(--wp-admin--admin-bar--height, 0px);
	z-index: 100;
}

/* Fallback for WordPress versions that do not set the custom property. */
body.admin-bar .wp-site-blocks > .wp-block-template-part:has(.sb-header),
body.admin-bar .wp-site-blocks > .wp-block-template-part:first-child {
	top: var(--wp-admin--admin-bar--height, 32px);
}

@media screen and (max-width: 782px) {
	body.admin-bar .wp-site-blocks > .wp-block-template-part:has(.sb-header),
	body.admin-bar .wp-site-blocks > .wp-block-template-part:first-child {
		top: var(--wp-admin--admin-bar--height, 46px);
	}
}

/* Below 600px the admin bar stops being fixed and scrolls away with the page,
   so the header must sit flush again or it leaves a 46px gap. */
@media screen and (max-width: 600px) {
	body.admin-bar .wp-site-blocks > .wp-block-template-part:has(.sb-header),
	body.admin-bar .wp-site-blocks > .wp-block-template-part:first-child {
		top: 0;
	}
}

/* The frosted background lives on a pseudo-element, not on .sb-header itself.
   backdrop-filter makes an element the containing block for its
   position:fixed descendants, which collapsed the mobile menu overlay to the
   height of the header instead of the viewport. Keeping the filter on a
   childless pseudo-element preserves the effect without that side effect. */
.sb-header {
	position: relative;
	background: transparent;
	border-bottom: var(--wp--custom--rule--hairline);
}

.sb-header::before {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: rgba(255, 255, 255, 0.92);
	backdrop-filter: saturate(180%) blur(12px);
	-webkit-backdrop-filter: saturate(180%) blur(12px);
}

.sb-header__bar {
	position: relative;
	z-index: 1;
}

/* The bar carries the vertical rhythm, and shrinks in the compact state.
   Padding is on the bar rather than the header so the sticky background
   still spans the full viewport width. */
.sb-header__bar {
	padding-block: clamp(0.85rem, 1.6vw, 1.35rem);
	transition: padding-block var(--wp--custom--transition--base);
}

.sb-header .custom-logo-link,
.sb-header .wp-block-site-logo a {
	display: block;
	line-height: 0;
}

.sb-header .wp-block-site-logo img {
	/* The mark is fine line art and the "PUBLISHING" lettering is light, so
	   the logo needs a little more room than a typical wordmark to stay
	   legible at small sizes. */
	width: clamp(156px, 17vw, 198px);
	height: auto;
	transition: opacity var(--wp--custom--transition--base);
}

.sb-header .wp-block-site-logo a:hover img {
	opacity: 0.78;
}

/* -----------------------------------------------------------------
   Compact (scrolled) header.

   The `is-compact` class is toggled by assets/js/header.js past a
   scroll threshold. Only the circular fairy mark shows, and the bar
   loses height, so more of the page stays visible while scrolling.
   ----------------------------------------------------------------- */

.sb-brand__mark {
	display: none;
	margin: 0;
	line-height: 0;
}

.sb-brand__mark img {
	display: block;
	width: 46px;
	height: auto;
	transition: opacity var(--wp--custom--transition--base);
}

.sb-brand__mark a:hover img {
	opacity: 0.78;
}

.sb-header.is-compact .sb-header__bar {
	padding-block: 0.5rem;
}

.sb-header.is-compact .wp-block-site-logo {
	display: none;
}

.sb-header.is-compact .sb-brand__mark {
	display: block;
}

/* Without JS the header simply stays in its full state — the mark is the
   progressive enhancement, not the baseline. */

/* Nav links: an animated rule that grows from the left on hover, and
   stays put for the current page. */
.sb-header .wp-block-navigation-item__content {
	position: relative;
	padding-block: 0.35rem;
	color: var(--wp--preset--color--ink);
}

.sb-header .wp-block-navigation-item__content::after {
	content: "";
	position: absolute;
	left: 0;
	bottom: 0;
	width: 100%;
	height: 2px;
	background: var(--wp--preset--color--accent);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform var(--wp--custom--transition--base);
}

.sb-header .wp-block-navigation-item:hover .wp-block-navigation-item__content::after,
.sb-header .wp-block-navigation-item.current-menu-item .wp-block-navigation-item__content::after,
.sb-header .wp-block-navigation-item.current-menu-ancestor .wp-block-navigation-item__content::after {
	transform: scaleX(1);
}

/* Submenu (the Books dropdown). */
.sb-header .wp-block-navigation__submenu-container {
	border: none;
	border-radius: 10px;
	padding: 0.4rem;
	min-width: 15rem;
	background: var(--wp--preset--color--base);
	box-shadow: var(--wp--preset--shadow--lifted);
}

.sb-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	padding: 0.6rem 0.85rem;
	border-radius: 6px;
	width: 100%;
}

.sb-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content::after {
	display: none;
}

.sb-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content:hover {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--action);
}

/* -----------------------------------------------------------------
   Mobile overlay menu

   Full-screen, translucent so the page stays faintly visible behind
   it, with a large close control. Woo/WP already render the open and
   close buttons; this is presentation only.
   ----------------------------------------------------------------- */

.wp-block-navigation__responsive-container.is-menu-open,
.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
	padding: clamp(1.25rem, 5vw, 2.5rem);
	/* Warm wash — enough to read against, still showing the page beneath.
	   !important because Woo/WP set `background-color: inherit` here at equal
	   specificity, which otherwise picks up the header's opaque white. */
	background-color: rgba(247, 244, 236, 0.9) !important;
	backdrop-filter: blur(16px) saturate(150%);
	-webkit-backdrop-filter: blur(16px) saturate(150%);
	align-items: stretch;
	justify-content: flex-start;
}

/* Give the list room below the close button and centre it in the sheet. */
/* WordPress nests two wrappers between the overlay and the menu list
   (__responsive-close, then __responsive-dialog). Both must grow, or the
   content has no height to be centred within. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-close,
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-dialog {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	width: 100%;
	min-height: 0;
}

.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-content {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	align-items: center;
	padding-block: clamp(2rem, 8vh, 4rem);
	width: 100%;
	min-height: 0;

	/* Scroll instead of clipping when the menu is taller than the sheet.
	   Both submenus render expanded here, so the list is 13 links and about
	   720px tall — taller than the content box on a 667px-high phone, where
	   the old `justify-content: center` pushed "Practice Areas" 47px above the
	   top of the screen with no way to reach it. Measured on an iPhone SE
	   viewport; a 740x360 landscape lost 205px the same way. */
	overflow-y: auto;
	overscroll-behavior: contain;
	-webkit-overflow-scrolling: touch;

	/* Two declarations on purpose. `safe center` centres the list when it fits
	   and falls back to start alignment when it does not, which is exactly the
	   behaviour wanted; browsers that do not understand the `safe` keyword drop
	   that line and keep flex-start, which scrolls from the top and is still
	   entirely usable. Plain `center` can never be used here: it centres
	   overflow too, and half of it lands off-screen. */
	justify-content: flex-start;
	justify-content: safe center;
}

.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__container {
	gap: 0;
	width: 100%;
	max-width: 22rem;
	text-align: center;
	/* flex: 0 0 auto overrides the flex-grow WordPress sets, which would
	   otherwise stretch the list and pin the items to the top. Centring is the
	   parent's job now — auto block margins used to do it here, but they clip
	   an overflowing item the same way `justify-content: center` does, so the
	   first link went off the top of short screens. */
	flex: 0 0 auto;
	margin-block: 0;
}

.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item {
	width: 100%;
	justify-content: center;
	border-bottom: 1px solid rgba(74, 78, 82, 0.12);
}

.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item:last-child {
	border-bottom: 0;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 500;
	color: var(--wp--preset--color--ink);
	/* Comfortable tap target. */
	padding-block: 0.85rem;
	width: 100%;
	justify-content: center;
}

/* The desktop hover rule draws an underline bar; not wanted in the sheet. */
.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item__content::after {
	display: none;
}

.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation-item__content:hover {
	color: var(--wp--preset--color--action);
}

/* Submenu (Books) sits indented and quieter, always expanded in the sheet. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__submenu-container {
	box-shadow: none;
	background: transparent;
	border: 0;
	padding: 0 0 0.5rem;
	min-width: 0;
}

.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__submenu-container
	.wp-block-navigation-item {
	border-bottom: 0;
}

.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__submenu-container
	.wp-block-navigation-item__content {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 400;
	color: var(--wp--preset--color--muted);
	padding-block: 0.6rem;
}

/* Open (hamburger) control. */
.wp-block-navigation__responsive-container-open {
	padding: 0.4rem;
	color: var(--wp--preset--color--ink);
}

.wp-block-navigation__responsive-container-open:hover {
	color: var(--wp--preset--color--action);
}

/* Close (X) control — enlarged and given a visible hit area, since the
   default is a small bare glyph in the corner. */
.wp-block-navigation__responsive-container-close {
	top: clamp(1.25rem, 5vw, 2.5rem);
	right: clamp(1.25rem, 5vw, 2.5rem);
	display: flex;
	align-items: center;
	justify-content: center;
	width: 46px;
	height: 46px;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.9);
	color: var(--wp--preset--color--ink);
	box-shadow: var(--wp--preset--shadow--soft);
	transition: background-color var(--wp--custom--transition--base),
		color var(--wp--custom--transition--base);
}

.wp-block-navigation__responsive-container-close:hover {
	background: var(--wp--preset--color--action);
	color: var(--wp--preset--color--base);
}

.wp-block-navigation__responsive-container-close svg {
	width: 26px;
	height: 26px;
}

/* The overlay is fixed to the viewport, so it must clear the admin bar. */
body.admin-bar .wp-block-navigation__responsive-container.is-menu-open {
	top: var(--wp-admin--admin-bar--height, 46px);
}

/* -------------------------------------------------------------------------
   5. Cart indicator in the header
   ---------------------------------------------------------------------- */

.sb-cart {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.5rem;
	border-radius: 999px;
	color: var(--wp--preset--color--ink);
	text-decoration: none;
	transition: background-color var(--wp--custom--transition--base);
}

.sb-cart:hover {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--action);
}

.sb-cart svg {
	width: 22px;
	height: 22px;
	display: block;
}

.sb-cart__count {
	position: absolute;
	top: -1px;
	right: -3px;
	min-width: 18px;
	height: 18px;
	padding: 0 5px;
	border-radius: 999px;
	background: var(--wp--preset--color--action);
	color: var(--wp--preset--color--base);
	font-family: var(--wp--preset--font-family--body);
	font-size: 11px;
	font-weight: 700;
	line-height: 18px;
	text-align: center;
}

.sb-cart__count:empty,
.sb-cart__count[data-count="0"] {
	display: none;
}

/* -------------------------------------------------------------------------
   6. Footer
   ---------------------------------------------------------------------- */

.sb-footer {
	background: var(--wp--preset--color--ink);
	color: rgba(255, 255, 255, 0.82);
}

/* The stacked lockup's fairy mark is hairline linework. At 200px those
   white strokes fall below a device pixel and alias into looking rough,
   which reads as pixelation even though the source is vector. Giving it
   more room is the actual fix. */
.sb-footer .wp-block-site-logo img,
.sb-footer__logo img {
	width: clamp(215px, 22vw, 275px);
	height: auto;
	/* Nudge the fine strokes away from sub-pixel rendering. */
	shape-rendering: geometricPrecision;
}

.sb-footer :where(h2, h3, h4, h5, h6) {
	color: var(--wp--preset--color--base);
}

.sb-footer a {
	color: rgba(255, 255, 255, 0.82);
	text-decoration: none;
}

.sb-footer a:hover {
	color: var(--wp--preset--color--accent);
	text-decoration: underline;
	text-underline-offset: 0.18em;
}

.sb-footer .wp-block-navigation {
	gap: 0.55rem;
}

.sb-footer__legal {
	border-top: 1px solid rgba(255, 255, 255, 0.14);
}

/* -------------------------------------------------------------------------
   7. Editorial pieces
   ---------------------------------------------------------------------- */

/* Eyebrow label above a section heading. */
.sb-eyebrow {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--action);
}

/* When the eyebrow is a term list (e.g. the product category on a book page)
   its links must not pick up the content underline — at this size and letter
   spacing an underline reads as noise. */
.sb-eyebrow a {
	color: inherit;
	text-decoration: none;
}

/* "We protect your legacies" is a slogan the client wants used more widely, so
   in the home hero it is set larger than the eyebrow default. Scoped to the
   hero: the eyebrow elsewhere is a section label and should stay quiet. */
.sb-hero-home .sb-eyebrow {
	font-size: var(--wp--preset--font-size--medium);
	letter-spacing: 0.12em;
}

.sb-eyebrow a:hover {
	text-decoration: underline;
	text-underline-offset: 0.25em;
}

/* A framed image with depth, for a product shot or cover. */
.sb-object img {
	border-radius: 3px 10px 10px 3px;
	box-shadow: var(--wp--preset--shadow--book);
}

/* -----------------------------------------------------------------
   Immersive hero — artwork behind the copy

   A whole-image dim would flatten the painting, so the scrim is
   left-weighted: dark enough for white type on the copy side, and
   clear on the right where the cover sits.
   ----------------------------------------------------------------- */

.sb-hero-immersive {
	position: relative;
	overflow: hidden;
}

.sb-hero-immersive::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	background:
		linear-gradient(
			100deg,
			rgba(38, 30, 26, 0.88) 0%,
			rgba(38, 30, 26, 0.74) 36%,
			rgba(38, 30, 26, 0.34) 62%,
			rgba(38, 30, 26, 0.12) 100%
		);
}

/* On narrow screens the columns stack, so the copy sits over the middle of
   the image and needs an even wash instead of a side gradient. */
@media (max-width: 781px) {
	.sb-hero-immersive::before {
		background: linear-gradient(
			180deg,
			rgba(38, 30, 26, 0.72) 0%,
			rgba(38, 30, 26, 0.84) 55%,
			rgba(38, 30, 26, 0.72) 100%
		);
	}
}

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

.sb-hero-immersive__eyebrow {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	/* Brand green reads well against the dark scrim; it is only unusable
	   on light grounds. */
	color: var(--wp--preset--color--accent);
}

.sb-hero-immersive__meta {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.72);
}

.sb-hero-immersive h1 em {
	font-style: italic;
}

/* Lift the cover off the artwork so it reads as a physical object rather
   than part of the painting. */
.sb-object--floating img {
	box-shadow: 0 4px 12px rgba(20, 28, 25, 0.3), 0 28px 64px rgba(20, 28, 25, 0.45);
}

/* Outline button on a dark ground. */
.sb-btn-on-dark .wp-block-button__link,
.wp-block-button.is-style-outline.sb-btn-on-dark > .wp-block-button__link {
	color: var(--wp--preset--color--base);
	border-color: rgba(255, 255, 255, 0.65);
	background: transparent;
}

.sb-btn-on-dark .wp-block-button__link:hover,
.wp-block-button.is-style-outline.sb-btn-on-dark > .wp-block-button__link:hover {
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--action);
	border-color: var(--wp--preset--color--base);
}

/* A soft rounded frame for photography and artwork. */
.sb-media img {
	border-radius: 14px;
}

/* Emphasised pull quote, for a tagline or short testimonial. */
.sb-lede-quote {
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 500;
	font-style: italic;
	line-height: 1.55;
	color: var(--wp--preset--color--action);
	text-align: center;
}

/* Decorative divider: a hairline rule either side of a small glyph. */
.sb-divider {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.75rem;
	color: var(--wp--preset--color--accent);
}

.sb-divider::before,
.sb-divider::after {
	content: "";
	height: 1px;
	flex: 1 1 auto;
	max-width: 7rem;
	background: currentColor;
}

/* Cards */
.sb-card {
	background: var(--wp--preset--color--base);
	border-radius: 16px;
	box-shadow: var(--wp--preset--shadow--soft);
	overflow: hidden;
	transition: box-shadow var(--wp--custom--transition--base),
		transform var(--wp--custom--transition--base);
}

.sb-card:hover {
	box-shadow: var(--wp--preset--shadow--lifted);
	transform: translateY(-3px);
}

/* -------------------------------------------------------------------------
   8. Blog
   ---------------------------------------------------------------------- */

/* The post grid is declared as a fixed 3-up in the templates, because
   combining columnCount with minimumColumnWidth made WordPress emit an
   unpredictable 2-up. Collapsing for narrower screens is done here. */
.wp-block-post-template.is-layout-grid {
	gap: var(--wp--preset--spacing--30);
}

@media (max-width: 1024px) {
	.wp-block-post-template.is-layout-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
	}
}

@media (max-width: 660px) {
	.wp-block-post-template.is-layout-grid {
		grid-template-columns: minmax(0, 1fr) !important;
	}
}

/* The blog intro sits in a wide container so its rule spans the grid; its
   text should start at the same left edge as the first card, not be centred
   inside it. */
.sb-blog-intro > * {
	margin-inline: 0;
}

.sb-blog-intro p {
	max-width: 58ch;
}

/* Cards stretch to the row height so the "Keep reading" link lands on a
   consistent baseline instead of floating wherever the excerpt ends. */
.sb-post-card {
	display: flex;
	flex-direction: column;
	height: 100%;
}

.sb-post-card .wp-block-post-excerpt {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
}

.sb-post-card .wp-block-post-excerpt__more-text {
	margin-top: auto;
	padding-top: 0.75rem;
}

.sb-post-card .wp-block-post-excerpt__more-text a {
	font-weight: 600;
	text-decoration: none;
	border-bottom: 1px solid rgba(44, 97, 63, 0.35);
}

.sb-post-card .wp-block-post-excerpt__more-text a:hover {
	border-bottom-color: currentColor;
}

.sb-post-card .wp-block-post-featured-image img {
	border-radius: 12px;
	aspect-ratio: 3 / 2;
	object-fit: cover;
	width: 100%;
}

.sb-post-card .wp-block-post-title {
	font-size: var(--wp--preset--font-size--large);
	line-height: 1.25;
}

.sb-post-card .wp-block-post-title a {
	text-decoration: none;
	color: var(--wp--preset--color--ink);
}

.sb-post-card .wp-block-post-title a:hover {
	color: var(--wp--preset--color--action);
}

.sb-meta {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
}

.wp-block-query-pagination {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
}

/* -------------------------------------------------------------------------
   9. Forms — Gravity Forms and core inputs share one look
   ---------------------------------------------------------------------- */

input:where([type="text"], [type="email"], [type="url"], [type="tel"], [type="number"], [type="password"], [type="search"], [type="date"]),
select,
textarea,
.wp-block-search__input {
	width: 100%;
	padding: 0.8rem 1rem;
	background: var(--wp--preset--color--base);
	border: 1.5px solid rgba(74, 78, 82, 0.22);
	border-radius: 8px;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--ink);
	transition: border-color var(--wp--custom--transition--base),
		box-shadow var(--wp--custom--transition--base);
}

/* The glow is derived from the action token, not written out. It used to be a
   literal rgba(44, 97, 63, 0.14) carried over from the starter's default green
   palette, so every input on this teal site glowed green on focus. The Gravity
   rule further down had the same bug; both now come from the same token. */
input:where([type="text"], [type="email"], [type="url"], [type="tel"], [type="number"], [type="password"], [type="search"]):focus,
select:focus,
textarea:focus {
	border-color: var(--wp--preset--color--action);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--wp--preset--color--action) 22%, transparent);
	outline: none;
}

::placeholder {
	color: rgba(74, 78, 82, 0.5);
	opacity: 1;
}

label {
	display: block;
	margin-bottom: 0.4rem;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--ink);
}

/* -----------------------------------------------------------------
   Gravity Forms

   ONE block, deliberately. There used to be two — this one and a later
   "15. Gravity Forms" — each styling the same controls with different
   values: 8px radius against 10px, a hard-coded rgba glow against a
   token color-mix, three separate reds for validation. The more
   specific selector won property by property, so what shipped was a
   blend of the two and neither block described it. Anything Gravity
   belongs here now.

   Gravity's own stylesheet loads before this file, so load order is on
   our side and only specificity decides. Where a selector below looks
   over-qualified, it is because a shorter one measurably lost. Confirm
   with getComputedStyle rather than trusting the selector, and do not
   shorten them to tidy up.

   Two things Gravity's legacy stylesheet still owns, deliberately left
   alone because changing them would be a design decision rather than a
   consolidation: label typography (its `.top_label .gfield_label` rule
   outranks ours, so labels render 18px/700, not the small/600 below),
   and the border colour on a field in an error state (its own #790000
   beats the token). Both are noted where they appear.
   ----------------------------------------------------------------- */

.gform_wrapper .gform_fields {
	grid-row-gap: var(--wp--preset--spacing--20);
	grid-column-gap: var(--wp--preset--spacing--20);
}

/* Gravity's `.top_label .gfield_label` is (0,3,0) and outranks this, so the
   size and weight here do not currently apply — the margin and letter-spacing
   do. Kept as the fallback if that rule ever goes away; to actually change
   label typography, mirror Gravity's depth the way the input rule below does. */
.gform_wrapper .gfield_label,
.gform_wrapper legend.gfield_label {
	display: block;
	margin-bottom: 0.45rem;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	letter-spacing: 0.02em;
	color: var(--wp--preset--color--ink);
}

/* Gravity's default asterisk is a bare red character. Tinting it with the
   action colour reads as emphasis rather than as an error already happening. */
.gform_wrapper .gfield_required,
.gform_wrapper .gfield_required .gfield_required_asterisk {
	color: var(--wp--preset--color--action);
	font-weight: 600;
	margin-inline-start: 0.15rem;
	text-decoration: none;
}

.gform_wrapper .gfield_description {
	padding-top: 0.35rem;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--muted);
	line-height: 1.5;
}

/* Fields: match the rest of the site's inputs.

   `.gform_fields` is in the chain to buy one class of specificity, and it is
   in the chain rather than a markup-version class because it exists in BOTH
   legacy and modern markup. Gravity's modern sheet owns these with
   `.gform_wrapper.gravity-theme input[type="text"]` — (0,3,1), exactly what
   this rule used to be — and theme.min.css loads after style.css, so it won
   on source order alone and fields rendered at 8px/15px. With `.gform_fields`
   the input arm is (0,4,1) and the select/textarea arms (0,3,1), which beat
   Gravity's (0,3,1) and (0,2,1) on specificity rather than on load order. */
.gform_wrapper .gform_fields .ginput_container input[type="text"],
.gform_wrapper .gform_fields .ginput_container input[type="email"],
.gform_wrapper .gform_fields .ginput_container input[type="tel"],
.gform_wrapper .gform_fields .ginput_container input[type="url"],
.gform_wrapper .gform_fields .ginput_container input[type="number"],
.gform_wrapper .gform_fields .ginput_container select,
.gform_wrapper .gform_fields .ginput_container textarea {
	width: 100%;
	padding: 0.8rem 1rem;
	background: var(--wp--preset--color--base);
	border: 1px solid rgba(74, 78, 82, 0.22);
	border-radius: 8px;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--ink);
	line-height: 1.5;
	transition: border-color var(--wp--custom--transition--base),
		box-shadow var(--wp--custom--transition--base);
}

/* The rule above sets one padding for inputs, selects and textareas, and only
   the selects and textareas got it. That asymmetry is the whole diagnosis:
   Gravity's legacy stylesheet owns text inputs with

     .gform_legacy_markup_wrapper input:not([type=radio]):not([type=checkbox])
       :not([type=submit]):not([type=button]):not([type=image]):not([type=file])
       { padding: 5px 4px }

   which is (0,7,1) — one class plus six attribute selectors inside :not(),
   each of which counts. The rule above is (0,3,1) and loses, and load order
   never entered into it. Because that selector names `input` and nothing
   else, selects and textareas were never contested, which is why the form
   rendered with 16px of padding on two field types and 4px on the rest.

   Mirroring Gravity's :not() chain wins at (0,9,1) with no !important. The
   font declarations repeat here because Gravity sets font-family and
   font-size to `inherit` in the same rule, so winning the padding means
   winning those too.

   This used to name `.gform_legacy_markup_wrapper` for its third class. It
   now uses `.gform_fields`, which is present in both markup modes, so the
   rule survived the move to modern markup on 4 September 2026 — the
   legacy-keyed version simply stopped matching and fields fell back to
   Gravity's 8px. Do not reintroduce a markup-version class here. */
.gform_wrapper .gform_fields .ginput_container input:not([type="radio"]):not([type="checkbox"]):not([type="submit"]):not([type="button"]):not([type="image"]):not([type="file"]) {
	padding: 0.8rem 1rem;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--medium);
	letter-spacing: normal;
}

.gform_wrapper .ginput_container textarea {
	min-height: 9rem;
	resize: vertical;
}

/* Focus. The glow was a hard-coded rgba(44, 97, 63, 0.14) inherited from the
   starter's default green palette, so it stayed green on a teal site — the
   exact thing the no-hard-coded-colours rule exists to prevent. Derived from
   the action token instead. */
.gform_wrapper .ginput_container input:focus,
.gform_wrapper .ginput_container select:focus,
.gform_wrapper .ginput_container textarea:focus {
	border-color: var(--wp--preset--color--action);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--wp--preset--color--action) 22%, transparent);
	outline: none;
}

/* A keyboard user needs more than a 22%-alpha glow, and the accessibility
   statement claims the focused element is visibly outlined. The `outline:
   none` above is (0,3,1), so this has to add a class to win.

   That class was `.gform_legacy_markup_wrapper` until 4 September 2026, which
   made this the sharpest edge in the legacy-to-modern move: the selector
   stopped matching, `outline: none` won unopposed, and form fields lost their
   focus ring entirely while every other page kept one. The site-wide
   `:where(a, button, input, ...):focus-visible` rule cannot save it — :where()
   contributes no specificity, so it loses to anything with a class. Measured,
   not assumed: `input.matches(':focus-visible')` was true with
   `outline-style: none` computed. `.gform_fields` exists in both markup
   modes, so this now holds either way. */
.gform_wrapper .gform_fields .ginput_container input:focus-visible,
.gform_wrapper .gform_fields .ginput_container select:focus-visible,
.gform_wrapper .gform_fields .ginput_container textarea:focus-visible {
	outline: 3px solid var(--wp--preset--color--action);
	outline-offset: 2px;
}

.gform_wrapper ::placeholder {
	color: var(--wp--preset--color--muted);
	opacity: 1;
}

/* Native select needs its own chevron once the default look is replaced. */
.gform_wrapper .ginput_container select {
	appearance: none;
	-webkit-appearance: none;
	background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234A4E52' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 0.9rem center;
	background-size: 18px 18px;
	padding-right: 2.6rem;
}

/* Submit button — the brand pill.

   The control is a <button class="gform_button button">, so the theme's
   wp-element-button styling never reaches it, and selectors written for
   input[type=submit] match nothing on a GFAPI-built form. Both spellings are
   listed because Gravity has shipped both footer class names. */
.gform_wrapper .gform_footer input[type="submit"],
.gform_wrapper .gform_footer button[type="submit"],
.gform_wrapper .gform_footer .gform_button,
.gform_wrapper .gform-footer .gform_button,
.gform_wrapper .gform_page_footer input[type="button"],
.gform_wrapper .gform_page_footer input[type="submit"] {
	width: auto;
	background: var(--wp--preset--color--action);
	color: var(--wp--preset--color--base);
	border: 0;
	border-radius: 999px;
	padding: 0.95rem 2.1rem;
	margin: 0;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	letter-spacing: 0.03em;
	line-height: 1.2;
	text-transform: none;
	cursor: pointer;
	transition: background-color var(--wp--custom--transition--base),
		transform var(--wp--custom--transition--base);
}

.gform_wrapper .gform_footer input[type="submit"]:hover,
.gform_wrapper .gform_footer button[type="submit"]:hover,
.gform_wrapper .gform_footer .gform_button:hover,
.gform_wrapper .gform-footer .gform_button:hover {
	background: var(--wp--preset--color--ink);
	transform: translateY(-1px);
}

.gform_wrapper .gform_footer {
	padding: var(--wp--preset--spacing--20) 0 0;
	margin: 0;
	justify-content: flex-start;
}

/* Validation. Gravity's default is a red block that fights the palette.
   The three hard-coded reds this used to carry (#a4341f, #8f2d1b, #fdf3f1)
   are now all derived from the one status token, so a rebrand moves them
   together. The tint measures 6.9:1 against the text on it. */
.gform_wrapper .gfield_description.validation_message,
.gform_wrapper .gfield_validation_message,
.gform_wrapper .validation_message,
/* Modern markup. Gravity's `.gform_wrapper.gravity-theme
   .gfield_validation_message` is (0,3,0) — level with the three selectors
   above — and theme.min.css loads later, so it took the whole block and the
   messages rendered as its pink 1px boxes instead of the tinted 3px rule
   whose contrast is measured above. `.gfield_error` is the meaningful
   ancestor and exists in both markup modes; adding it makes these (0,4,0). */
.gform_wrapper .gfield_error .gfield_description.validation_message,
.gform_wrapper .gfield_error .gfield_validation_message.gfield_validation_message,
.gform_wrapper .gfield_error .validation_message.validation_message {
	margin-top: 0.4rem;
	padding: 0.5rem 0.75rem;
	background: color-mix(in srgb, var(--wp--custom--status--error) 7%, var(--wp--preset--color--base));
	border: 0;
	border-left: 3px solid var(--wp--custom--status--error);
	border-radius: 6px;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--custom--status--error);
}

/* Gravity's own `#790000` on an errored field outranks this, so the field
   border stays its red rather than the token. Left as-is on purpose:
   overriding it is a design call, not part of merging two blocks. */
/* Errored field border. Three rules compete for this and the depths matter:
   the base field rule above is (0,4,1) since `.gform_fields` was added to it,
   and Gravity's modern `.gform_wrapper.gravity-theme .gfield_error
   [aria-invalid="true"]` is (0,4,0). At (0,2,1) this rule lost to both, and
   an invalid field rendered with the ordinary grey border — measured, after
   submitting the form empty.

   `.gform_fields` and `.ginput_container` bring it to (0,4,1): it beats
   Gravity on the element in the third column, and ties the base field rule
   while sitting later in this file. That tie is why this block must stay
   BELOW the base field rule. */
.gform_wrapper .gform_fields .gfield_error .ginput_container input,
.gform_wrapper .gform_fields .gfield_error .ginput_container select,
.gform_wrapper .gform_fields .gfield_error .ginput_container textarea {
	border-color: var(--wp--custom--status--error);
}

/* The validation banner, twice over, deliberately.

   Gravity's modern sheet owns it with `.gform_wrapper.gravity-theme
   .gform_validation_errors` at (0,3,0) and loads after this file, so the
   (0,2,0) rule below lost every declaration and the banner rendered in
   Gravity's pink with a 1.5px border instead of the site's surface token and
   3px rule. The doubled class in the second selector buys (0,4,0), which wins
   on specificity rather than load order.

   The plain rule is kept as well: it is the one that applies under legacy
   markup, where the wrapper has no `gform_validation_error` class to hang the
   higher-specificity selector on. Keep both declaration blocks identical. */
.gform_wrapper .gform_validation_errors {
	padding: 1rem 1.25rem;
	border: 0;
	border-left: 3px solid var(--wp--custom--status--error);
	border-radius: 10px;
	background: var(--wp--preset--color--surface);
	box-shadow: none;
}

.gform_wrapper.gform_validation_error .gform_validation_errors.gform_validation_errors {
	padding: 1rem 1.25rem;
	border: 0;
	border-left: 3px solid var(--wp--custom--status--error);
	border-radius: 10px;
	background: var(--wp--preset--color--surface);
	box-shadow: none;
}

.gform_wrapper .gform_validation_errors > h2 {
	margin: 0;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--ink);
}

.gform_wrapper .gform_validation_errors > h2::before {
	display: none;
}

/* Inline confirmation, for any form not routed to a Thank You page. */
.gform_confirmation_message {
	padding: var(--wp--preset--spacing--30);
	background: var(--wp--preset--color--surface);
	border-left: 3px solid var(--wp--preset--color--action);
	border-radius: 10px;
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--large);
	color: var(--wp--preset--color--ink);
}

/* -------------------------------------------------------------------------
   10. Utilities
   ---------------------------------------------------------------------- */

/* Let a wide/full block bleed to the viewport edge on small screens. */
@media (max-width: 600px) {
	.sb-bleed-mobile {
		margin-left: calc(var(--wp--preset--spacing--20) * -1);
		margin-right: calc(var(--wp--preset--spacing--20) * -1);
		border-radius: 0;
	}
}

/* Overlay text needs a scrim to stay readable over artwork. */
.sb-scrim::before {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(
		180deg,
		rgba(74, 78, 82, 0.55) 0%,
		rgba(74, 78, 82, 0.2) 45%,
		rgba(74, 78, 82, 0.5) 100%
	);
	pointer-events: none;
}

.sb-scrim > * {
	position: relative;
	z-index: 1;
}

/* A monochrome logo can serve both the light header and the dark footer by
   being inverted, rather than needing a separate reversed asset. Only sound for
   single-colour marks — a full-colour logo must have its own reversed file. */
.sb-footer__logo--invert img {
	filter: invert(1) brightness(1.9);
}

/* -------------------------------------------------------------------------
   13. Counter band, case results, attorney profile
   ---------------------------------------------------------------------- */

/* Tabular figures stop the count-up from reflowing the line as digits change
   width — without this the number visibly jitters while it animates. */
.sb-counter {
	font-variant-numeric: tabular-nums;
	font-feature-settings: "tnum" 1;
}

/* Measured on the rendered page, not derived from the brief.
   `muted` is chosen to clear 4.5:1 on base, surface and tint — all light
   grounds. On the dark band it lands at 1.99:1, so any .sb-meta inside
   .sb-on-dark has to be re-stated rather than inherited. This affects the
   stock stat-band pattern too, which is why the rule is scoped to .sb-on-dark
   and not to the counter band alone.
   #DCEAEC on ink = 10.24:1. */
.sb-on-dark .sb-meta {
	color: var(--wp--preset--color--tint);
}

/* The brand teal is a fill, never a text ground — and it is not a text colour
   on a dark ground either: #0096a9 on ink is 3.57:1. Lightening the token
   itself keeps the teal reading, clears AA at 6.39:1, and survives a rebrand:
   there is no second hex to update when the palette changes.
   Scoped to .sb-on-dark deliberately — this mix is 1.98:1 on white. */
.sb-on-dark .sb-eyebrow {
	color: var(--wp--preset--color--tint); /* fallback where color-mix is absent */
	color: color-mix(in srgb, var(--wp--preset--color--accent) 55%, white);
}

/* Results are rows divided by rules rather than cards. A card per result reads
   as a promotional tile; a rule reads as a record, which is the tone wanted
   next to money figures. */
.sb-result + .sb-result {
	border-top: 1px solid var(--wp--preset--color--tint);
}

.sb-result {
	align-items: baseline;
}

/* Fix the figure column rather than setting a minimum on it. Not every result
   is a number — "Multi-million" and "Protected" are real entries — and with
   `min-width` a long one grows its column and shunts that row's summary out of
   line with all the others. A fixed basis lets the long ones wrap instead. */
/* 9rem clears the longest label currently in use ("Protected", 131px at
   x-large). A flex item defaults to min-width:auto, so a single unbreakable
   word wider than the basis still pushes the column out — hence sizing to the
   content rather than relying on the basis alone. A longer label than this
   would need the value raised, or the label shortened. */
.sb-result__figure {
	flex: 0 0 9rem;
	font-variant-numeric: tabular-nums;
	hyphens: auto;
	margin: 0;
}

.sb-result__body {
	flex: 1 1 22rem;
}

@media (max-width: 600px) {
	.sb-result__figure {
		min-width: 0;
	}
}

/* Headshots arrive at whatever aspect the client had to hand — one square, one
   tall. Fixing the ratio here keeps a row of profiles even, and object-fit
   crops rather than distorting. */
.sb-portrait img {
	width: 100%;
	aspect-ratio: 4 / 5;
	object-fit: cover;
	object-position: center top;
	border-radius: 12px;
}

/* The utility strip carries the descriptor the firm wants to be found by, so it
   sits above the masthead on every page. Hidden below 782px: at phone widths it
   competes with the logo for the only line that matters. */
.sb-utility {
	border-bottom: 1px solid var(--wp--preset--color--tint);
	padding-block: 0.4rem;
	color: var(--wp--preset--color--muted);
}

.sb-utility p {
	margin: 0;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

.sb-utility__brand {
	color: var(--wp--preset--color--action);
	font-weight: 600;
}

@media (max-width: 781px) {
	.sb-utility {
		display: none;
	}
}

/* -------------------------------------------------------------------------
   14. Vertical rhythm — tightened after design review
   ---------------------------------------------------------------------- */

/* The masthead was carrying more air than it earned, which pushed the H1 of
   every page below a comfortable first view. */
.sb-header__bar {
	padding-block: clamp(0.55rem, 1vw, 0.9rem);
}

.sb-utility {
	padding-block: 0.25rem;
}

/* A heading that opens a band does not need its own top margin as well as the
   band's padding — the two stack and read as a gap rather than as rhythm. */
.wp-block-group > .wp-block-heading:first-child,
.wp-block-group > .sb-eyebrow:first-child,
.wp-block-column > .wp-block-heading:first-child,
.wp-block-column > .sb-eyebrow:first-child {
	margin-block-start: 0;
}

/* Close the gap between an H1 and the lead paragraph under it. */
.wp-block-group > h1.wp-block-heading {
	margin-block-end: var(--wp--preset--spacing--10);
}

/* And between a page header and the first paragraph of the band below it. */
.wp-block-group > .wp-block-heading + p {
	margin-block-start: var(--wp--preset--spacing--10);
}

/* -------------------------------------------------------------------------
   15. Header phone, home-page result cards, mobile submenu
   ---------------------------------------------------------------------- */

/* The utility strip above the masthead is gone — it cost 30px of vertical space
   to repeat the descriptor already set under the wordmark in the logo. The
   phone moved into the bar itself. Hidden on small screens, where the logo and
   the menu button are the only things that earn the width. */
.sb-header__phone {
	margin: 0;
	white-space: nowrap;
	/* Size comes from the block's fontSize preset, because WordPress emits
	   .has-*-font-size with !important and a rule here would never win. */
	font-weight: 700;
	letter-spacing: 0.01em;
}

/* No underline: it is the most prominent thing in the bar and the underline
   made it read as body copy that happened to be a link. */
.sb-header__phone a {
	text-decoration: none;
	color: var(--wp--preset--color--action);
}

.sb-header__phone a:hover {
	color: var(--wp--preset--color--ink);
}

/* Kept on phones too — for a law firm the number is the point of the header.
   Below 1024px the nav collapses to a hamburger, which frees the width. */
@media (max-width: 400px) {
	.sb-header__phone .has-medium-font-size,
	.sb-header__phone {
		font-size: var(--wp--preset--font-size--small) !important;
	}
}

/* Home-page result cards. A rule above each figure rather than a card border:
   the same device as the row list on /case-results/, so the two read as one
   family. */
.sb-result-cards .sb-result-card {
	border-top: 2px solid var(--wp--preset--color--tint);
	padding-top: var(--wp--preset--spacing--20);
}

.sb-result-card__figure {
	margin: 0;
	font-variant-numeric: tabular-nums;
}

/* Below 600px the nav collapses to a hamburger. The phone sits after the nav in
   the DOM so it reads to the right of "Contact" on desktop — but that would put
   it to the right of the hamburger on a phone, where the menu button should be
   the last thing in the bar. Reorder rather than duplicate the markup. */
/* Whenever the nav is a hamburger, the phone sits to its left — the menu button
   should be the last thing in the bar. Matches the overlay breakpoint below. */
@media (max-width: 849px) {
	.sb-header__end {
		gap: 0.75rem;
	}

	.sb-header__phone {
		order: -1;
	}
}

/* Mobile menu: centre the submenu items on the same axis as their parent.
   WordPress indents them with

     .wp-block-navigation__responsive-container.is-menu-open:where(...)
     .wp-block-navigation__responsive-container-content
     .has-child .wp-block-navigation__submenu-container
       { padding-left: 2rem; padding-right: 2rem; min-width: 200px }

   which is five classes, and it sets the anchor padding at four. Shorter
   selectors lose regardless of load order — the earlier attempt here set
   `display` successfully and `padding` not at all, from the same rule block,
   which is the tell. These selectors mirror WordPress's depth and add a tag to
   win by one. Keep them long. */
.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-content
	.has-child
	ul.wp-block-navigation__submenu-container {
	display: block;
	box-sizing: border-box;
	width: 100%;
	min-width: 0;
	padding-left: 0;
	padding-right: 0;
	margin-inline: 0;
	text-align: center;
}

.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-content
	.has-child
	ul.wp-block-navigation__submenu-container
	> li.wp-block-navigation-item {
	display: block;
	width: 100%;
	margin-inline: 0;
	border-bottom: 0;
}

.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-content
	.has-child
	ul.wp-block-navigation__submenu-container
	> li.wp-block-navigation-item
	> a.wp-block-navigation-item__content {
	display: block;
	box-sizing: border-box;
	width: 100%;
	padding-left: 0;
	padding-right: 0;
	margin-inline: 0;
	text-align: center;
}

/* -------------------------------------------------------------------------
   17. Move the nav overlay breakpoint from 600px to 850px
   ---------------------------------------------------------------------- */

/* The nav has six top-level items plus the phone, which starts wrapping onto a
   second line a little above 800px. WordPress hard-codes the overlay switch for
   `overlayMenu: "mobile"` at 600px in two `@media (min-width: 600px)` blocks —
   one turns the fixed overlay into a static list, the other hides the hamburger.
   There is no setting for it, so both are reverted across 600-849px. Keep these
   in step with the max-width: 849px rules above. */
@media (min-width: 600px) and (max-width: 849px) {
	.wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none;
		position: fixed;
		width: 100%;
		z-index: 100000;
		background-color: inherit;
	}

	.wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}
}

/* City lists under each county on Areas Served. Tighter than a default list,
   and the county heading above carries the visual weight. */
.sb-city-list {
	margin-top: 0.35rem;
	margin-bottom: var(--wp--preset--spacing--20);
}

.sb-city-list li {
	margin-bottom: 0.15rem;
}

/* Attorney cards on the About page. A rule above each portrait ties them to the
   case-result cards on the home page, so the two grids read as one system. */
.sb-person {
	border-top: 2px solid var(--wp--preset--color--tint);
	padding-top: var(--wp--preset--spacing--20);
}

.sb-person .sb-portrait {
	margin-bottom: var(--wp--preset--spacing--10);
}

.sb-person h3 {
	margin-block: 0.1rem 0.4rem;
}

/* "Read full bio" — a quiet directional cue rather than a second button. */
.sb-more {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
}

.sb-more a {
	text-decoration: none;
}

.sb-more a::after {
	content: " \2192";
}

.sb-more a:hover {
	text-decoration: underline;
}

/* -------------------------------------------------------------------------
   18. Practice-area cards

   The /practice-areas/ index exists to route people to the four detail
   pages, so each area is a card: icon, name, one sentence, and its own
   link. The icons are inline SVG from assets/icons/ and are drawn in
   `currentColor`, so their colour comes from the token below rather than
   from anything baked into the file — a rebrand moves them with everything
   else.
   ---------------------------------------------------------------------- */

.sb-practice-card {
	display: flex;
	flex-direction: column;
	height: 100%;
	padding: var(--wp--preset--spacing--30);
	background: var(--wp--preset--color--base);
	border: var(--wp--custom--rule--hairline);
	border-radius: 12px;
	transition: border-color var(--wp--custom--transition--base),
		transform var(--wp--custom--transition--base),
		box-shadow var(--wp--custom--transition--base);
}

.sb-practice-card:hover,
.sb-practice-card:focus-within {
	border-color: var(--wp--preset--color--action);
	transform: translateY(-2px);
	box-shadow: 0 14px 30px -20px var(--wp--preset--color--ink);
}

@media (prefers-reduced-motion: reduce) {
	.sb-practice-card:hover,
	.sb-practice-card:focus-within {
		transform: none;
	}
}

/* The disc keeps the icon a consistent size whatever the glyph's own
   proportions are, and gives the line art something to sit on. */
.sb-practice-card__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 4rem;
	height: 4rem;
	border-radius: 50%;
	background: var(--wp--preset--color--tint);
	color: var(--wp--preset--color--action);
}

.sb-practice-card__icon svg {
	width: 2.1rem;
	height: 2.1rem;
}

/* The button is the card's call to action; underlining the heading as well
   gives one card two competing affordances. The theme's content-link rule is
   effectively (0,0,1) because its :where() contributes nothing, so this wins
   comfortably without needing to be long. */
.sb-practice-card h2 a,
.sb-practice-card h3 a {
	text-decoration: none;
}

.sb-practice-card h2 a:hover,
.sb-practice-card h3 a:hover {
	text-decoration: underline;
}

/* The card is a flex column so the link sits on the baseline of every card
   in the row, whatever the sentence above it wraps to. */
.sb-practice-card .wp-block-buttons {
	margin-top: auto;
	padding-top: var(--wp--preset--spacing--20);
}

/* -------------------------------------------------------------------------
   19. Intro paragraph spanning the practice-page grid

   Section 1 caps an unclassed paragraph in .entry-content at 68ch so body
   copy keeps a readable measure inside a wide container. That is right almost
   everywhere and wrong for this one block: on /real-estate-litigation/ the
   second intro paragraph is meant to run the full width of the grid beneath
   the image, and the cap held it to 700px inside a 1216px group.

   Named rather than dodged. The section-1 selector exempts anything carrying
   a `has-` class, so a font-size preset would have "fixed" this by accident —
   and left nobody able to see why.
   ---------------------------------------------------------------------- */

.sb-intro-below p {
	max-width: none;
}
