/*!
Theme Name: Grandir Theme 1
Theme URI: https://grandirsolutions.com/
Author: Grandir Solutions
Author URI: https://grandirsolutions.com/
Description: A structured, SEO-focused WordPress theme by Grandir Solutions for building lead-generating websites for contractor and home-service companies.
Version: 1.27.0
Tested up to: 6.6
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: LICENSE
Text Domain: grandir-theme-1
Tags: custom-background, custom-logo, custom-menu, featured-images, threaded-comments, translation-ready

This theme, like WordPress, is licensed under the GPL.

Grandir Theme 1 is based on Underscores https://underscores.me/, (C) 2012-2020 Automattic, Inc.
Underscores is distributed under the terms of the GNU GPL v2 or later.

Normalizing styles have been helped along thanks to the fine work of
Nicolas Gallagher and Jonathan Neal https://necolas.github.io/normalize.css/
*/

/*--------------------------------------------------------------
>>> TABLE OF CONTENTS:
----------------------------------------------------------------
# Generic
	- Normalize
	- Box sizing
# Base
	- Typography
	- Elements
	- Links
	- Forms
## Layouts
# Components
	- Navigation
	- Posts and pages
	- Comments
	- Widgets
	- Media
	- Captions
	- Galleries
# plugins
	- Jetpack infinite scroll
# Utilities
	- Accessibility
	- Alignments
# Grandir layout
# Brand color

--------------------------------------------------------------*/

/*--------------------------------------------------------------
# Generic
--------------------------------------------------------------*/

/* Normalize
--------------------------------------------- */

/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */

/* Document
	 ========================================================================== */

/**
 * 1. Correct the line height in all browsers.
 * 2. Prevent adjustments of font size after orientation changes in iOS.
 */
html {
	line-height: 1.15;
	-webkit-text-size-adjust: 100%;
}

/* Sections
	 ========================================================================== */

/**
 * Remove the margin in all browsers.
 */
body {
	margin: 0;
}

/**
 * Render the `main` element consistently in IE.
 */
main {
	display: block;
}

/**
 * Correct the font size and margin on `h1` elements within `section` and
 * `article` contexts in Chrome, Firefox, and Safari.
 */
h1 {
	font-size: 2em;
	margin: 0.67em 0;
}

/* Grouping content
	 ========================================================================== */

/**
 * 1. Add the correct box sizing in Firefox.
 * 2. Show the overflow in Edge and IE.
 */
hr {
	box-sizing: content-box;
	height: 0;
	overflow: visible;
}

/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */
pre {
	font-family: monospace, monospace;
	font-size: 1em;
}

/* Text-level semantics
	 ========================================================================== */

/**
 * Remove the gray background on active links in IE 10.
 */
a {
	background-color: transparent;
}

/**
 * 1. Remove the bottom border in Chrome 57-
 * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
 */
abbr[title] {
	border-bottom: none;
	text-decoration: underline;
	text-decoration: underline dotted;
}

/**
 * Add the correct font weight in Chrome, Edge, and Safari.
 */
b,
strong {
	font-weight: bolder;
}

/**
 * 1. Correct the inheritance and scaling of font size in all browsers.
 * 2. Correct the odd `em` font sizing in all browsers.
 */
code,
kbd,
samp {
	font-family: monospace, monospace;
	font-size: 1em;
}

/**
 * Add the correct font size in all browsers.
 */
small {
	font-size: 80%;
}

/**
 * Prevent `sub` and `sup` elements from affecting the line height in
 * all browsers.
 */
sub,
sup {
	font-size: 75%;
	line-height: 0;
	position: relative;
	vertical-align: baseline;
}

sub {
	bottom: -0.25em;
}

sup {
	top: -0.5em;
}

/* Embedded content
	 ========================================================================== */

/**
 * Remove the border on images inside links in IE 10.
 */
img {
	border-style: none;
}

/* Forms
	 ========================================================================== */

/**
 * 1. Change the font styles in all browsers.
 * 2. Remove the margin in Firefox and Safari.
 */
button,
input,
optgroup,
select,
textarea {
	font-family: inherit;
	font-size: 100%;
	line-height: 1.15;
	margin: 0;
}

/**
 * Show the overflow in IE.
 * 1. Show the overflow in Edge.
 */
button,
input {
	overflow: visible;
}

/**
 * Remove the inheritance of text transform in Edge, Firefox, and IE.
 * 1. Remove the inheritance of text transform in Firefox.
 */
button,
select {
	text-transform: none;
}

/**
 * Correct the inability to style clickable types in iOS and Safari.
 */
button,
[type="button"],
[type="reset"],
[type="submit"] {
	-webkit-appearance: button;
}

/**
 * Remove the inner border and padding in Firefox.
 */
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
	border-style: none;
	padding: 0;
}

/**
 * Restore the focus styles unset by the previous rule.
 */
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
	outline: 1px dotted ButtonText;
}

/**
 * Correct the padding in Firefox.
 */
fieldset {
	padding: 0.35em 0.75em 0.625em;
}

/**
 * 1. Correct the text wrapping in Edge and IE.
 * 2. Correct the color inheritance from `fieldset` elements in IE.
 * 3. Remove the padding so developers are not caught out when they zero out
 *		`fieldset` elements in all browsers.
 */
legend {
	box-sizing: border-box;
	color: inherit;
	display: table;
	max-width: 100%;
	padding: 0;
	white-space: normal;
}

/**
 * Add the correct vertical alignment in Chrome, Firefox, and Opera.
 */
progress {
	vertical-align: baseline;
}

/**
 * Remove the default vertical scrollbar in IE 10+.
 */
textarea {
	overflow: auto;
}

/**
 * 1. Add the correct box sizing in IE 10.
 * 2. Remove the padding in IE 10.
 */
[type="checkbox"],
[type="radio"] {
	box-sizing: border-box;
	padding: 0;
}

/**
 * Correct the cursor style of increment and decrement buttons in Chrome.
 */
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
	height: auto;
}

/**
 * 1. Correct the odd appearance in Chrome and Safari.
 * 2. Correct the outline style in Safari.
 */
[type="search"] {
	-webkit-appearance: textfield;
	outline-offset: -2px;
}

/**
 * Remove the inner padding in Chrome and Safari on macOS.
 */
[type="search"]::-webkit-search-decoration {
	-webkit-appearance: none;
}

/**
 * 1. Correct the inability to style clickable types in iOS and Safari.
 * 2. Change font properties to `inherit` in Safari.
 */
::-webkit-file-upload-button {
	-webkit-appearance: button;
	font: inherit;
}

/* Interactive
	 ========================================================================== */

/*
 * Add the correct display in Edge, IE 10+, and Firefox.
 */
details {
	display: block;
}

/*
 * Add the correct display in all browsers.
 */
summary {
	display: list-item;
}

/* Misc
	 ========================================================================== */

/**
 * Add the correct display in IE 10+.
 */
template {
	display: none;
}

/**
 * Add the correct display in IE 10.
 */
[hidden] {
	display: none;
}

/* Box sizing
--------------------------------------------- */

/* Inherit box-sizing to more easily change it's value on a component level.
@link http://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/ */
*,
*::before,
*::after {
	box-sizing: inherit;
}

html {
	box-sizing: border-box;
}

/*--------------------------------------------------------------
# Base
--------------------------------------------------------------*/

/* Typography
--------------------------------------------- */
body,
button,
input,
select,
optgroup,
textarea {
	color: var(--grandir-color-text);
	font-family: var(--grandir-font-body);
	font-size: 1rem;
	line-height: 1.5;
}

h1,
h2,
h3,
h4,
h5,
h6 {
	clear: both;
	font-family: var(--grandir-font-heading);
}

p {
	margin-bottom: 1.5em;
}

dfn,
cite,
em,
i {
	font-style: italic;
}

blockquote {
	margin: 0 1.5em;
}

address {
	margin: 0 0 1.5em;
}

pre {
	background: #eee;
	font-family: "Courier 10 Pitch", courier, monospace;
	line-height: 1.6;
	margin-bottom: 1.6em;
	max-width: 100%;
	overflow: auto;
	padding: 1.6em;
}

code,
kbd,
tt,
var {
	font-family: monaco, consolas, "Andale Mono", "DejaVu Sans Mono", monospace;
}

abbr,
acronym {
	border-bottom: 1px dotted #666;
	cursor: help;
}

mark,
ins {
	background: #fff9c0;
	text-decoration: none;
}

big {
	font-size: 125%;
}

/* Elements
--------------------------------------------- */
body {
	background: #fff;
}

hr {
	background-color: #ccc;
	border: 0;
	height: 1px;
	margin-bottom: 1.5em;
}

ul,
ol {
	margin: 0 0 1.5em 3em;
}

ul {
	list-style: disc;
}

ol {
	list-style: decimal;
}

li > ul,
li > ol {
	margin-bottom: 0;
	margin-left: 1.5em;
}

dt {
	font-weight: 700;
}

dd {
	margin: 0 1.5em 1.5em;
}

/* Make sure embeds and iframes fit their containers. */
embed,
iframe,
object {
	max-width: 100%;
}

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

figure {
	margin: 1em 0;
}

table {
	margin: 0 0 1.5em;
	width: 100%;
}

/* Links
--------------------------------------------- */
a,
a:visited {
	color: var(--grandir-color-link);
}

a:hover,
a:focus,
a:active {
	color: var(--grandir-color-link);
	text-decoration-thickness: 2px;
}

/* Forms
--------------------------------------------- */
button,
input[type="button"],
input[type="reset"],
input[type="submit"] {
	border: 1px solid;
	border-color: #ccc #ccc #bbb;
	border-radius: 3px;
	background: #e6e6e6;
	color: rgba(0, 0, 0, 0.8);
	line-height: 1;
	padding: 0.6em 1em 0.4em;
}

button:hover,
input[type="button"]:hover,
input[type="reset"]:hover,
input[type="submit"]:hover {
	border-color: #ccc #bbb #aaa;
}

button:active,
button:focus,
input[type="button"]:active,
input[type="button"]:focus,
input[type="reset"]:active,
input[type="reset"]:focus,
input[type="submit"]:active,
input[type="submit"]:focus {
	border-color: #aaa #bbb #bbb;
}

input[type="text"],
input[type="email"],
input[type="url"],
input[type="password"],
input[type="search"],
input[type="number"],
input[type="tel"],
input[type="range"],
input[type="date"],
input[type="month"],
input[type="week"],
input[type="time"],
input[type="datetime"],
input[type="datetime-local"],
input[type="color"],
textarea {
	color: #666;
	border: 1px solid #ccc;
	border-radius: 3px;
	padding: 3px;
}

input[type="text"]:focus,
input[type="email"]:focus,
input[type="url"]:focus,
input[type="password"]:focus,
input[type="search"]:focus,
input[type="number"]:focus,
input[type="tel"]:focus,
input[type="range"]:focus,
input[type="date"]:focus,
input[type="month"]:focus,
input[type="week"]:focus,
input[type="time"]:focus,
input[type="datetime"]:focus,
input[type="datetime-local"]:focus,
input[type="color"]:focus,
textarea:focus {
	color: #111;
}

select {
	border: 1px solid #ccc;
}

textarea {
	width: 100%;
}

/*--------------------------------------------------------------
# Layouts
--------------------------------------------------------------*/

/*--------------------------------------------------------------
# Components
--------------------------------------------------------------*/

/* Header and primary navigation
--------------------------------------------- */

/*
 * Mobile first: logo left, call button + hamburger right, menu in a
 * full-screen overlay. At 60em and up the menu sits inline with dropdowns.
 * Keep the 60em breakpoint in sync with js/navigation.js.
 *
 * Dark brand background, like the footer, so light logos show. The logo
 * follows the footer's rules (grandir_theme_1_site_logo()).
 */
.site-header {
	--grandir-color-focus: #fff;
	background: var(--grandir-color-primary-deep);
	border-block-end: 1px solid rgba(255, 255, 255, 0.15);
	color: #fff;
	position: sticky;
	top: 0;
	z-index: 1000;
}

.admin-bar .site-header {
	top: 32px;
}

@media screen and (max-width: 782px) {

	.admin-bar .site-header {
		top: 46px;
	}
}

@media screen and (max-width: 600px) {

	/* The admin bar scrolls away on small screens. */
	.admin-bar .site-header {
		top: 0;
	}
}

.site-header__inner {
	align-items: center;
	display: flex;
	gap: 1rem;
	margin-inline: auto;
	max-width: calc(var(--grandir-content-width, 72rem) - 2rem + 2 * var(--grandir-gutter, 1rem));
	min-height: 4rem;
	padding: 0.5rem var(--grandir-gutter, 1rem);
}

.site-branding {
	margin-inline-end: auto;
}

.site-branding .custom-logo-link,
.site-branding .site-title {
	display: block;
}

/*
 * Logo height: 3rem for wide logos, larger for squarer ones by
 * --grandir-logo-scale (inc/brand.php), capped so the header stays slim on
 * phones.
 */
.site-branding .custom-logo {
	display: block;
	height: auto;
	max-height: min(calc(3rem * var(--grandir-logo-scale, 1)), 3.5rem);
	width: auto;
	max-width: 100%;
}

/* SVG logos have no fixed pixel size, so give them an explicit height. */
.site-branding .custom-logo[src$=".svg"] {
	height: min(calc(3rem * var(--grandir-logo-scale, 1)), 3.5rem);
}

@media screen and (min-width: 60em) {

	.site-branding .custom-logo {
		max-height: min(calc(3rem * var(--grandir-logo-scale, 1)), 4.5rem);
	}

	.site-branding .custom-logo[src$=".svg"] {
		height: min(calc(3rem * var(--grandir-logo-scale, 1)), 4.5rem);
	}

	/*
	 * Badge logo (Logo size "Badge", square and tall logos only): up to 150px
	 * wide and tall, hanging from a slim header over the top of the page. A
	 * negative bottom margin keeps the bar at the 3.5rem logo's height. Once
	 * the page is scrolled (js/logo-badge.js), or without JS, it's that size.
	 */
	.has-logo-badge {
		--grandir-logo-bar-height: 3.5rem;
		--grandir-logo-badge-height: calc(9.375rem / max(1, var(--grandir-logo-ratio, 1)));
	}

	.has-logo-badge .site-branding {
		align-self: flex-start;
	}

	.has-logo-badge .site-branding .custom-logo,
	.has-logo-badge .site-branding .custom-logo[src$=".svg"] {
		height: var(--grandir-logo-bar-height);
		max-height: none;
	}

	.js:not(.is-scrolled) .has-logo-badge .site-branding {
		margin-block-end: calc(var(--grandir-logo-bar-height) - var(--grandir-logo-badge-height));
	}

	.js:not(.is-scrolled) .has-logo-badge .site-branding .custom-logo {
		height: var(--grandir-logo-badge-height);
	}

	/*
	 * The hero's text starts below the badge, which hangs over its top. Not
	 * the Home and service heroes (in .hero-intro), which center their text
	 * in a taller hero beside the quote form.
	 */
	.has-logo-badge .site-main > .hero {
		padding-block-start: max(3rem, calc(var(--grandir-logo-badge-height) - var(--grandir-logo-bar-height) + 1.5rem));
	}

	/*
	 * Page titles without a hero (the Services, Areas and Projects index pages,
	 * plain pages, 404, search) start below the badge too. On the index pages
	 * the breadcrumb bar already covers part of the distance.
	 */
	.has-logo-badge .page-title.eyebrow,
	.has-logo-badge .entry-title.eyebrow {
		margin-block-start: calc(var(--grandir-logo-badge-height) - var(--grandir-logo-bar-height) + 1.5rem);
	}

	.has-logo-badge .breadcrumbs ~ .page-header .page-title.eyebrow {
		margin-block-start: calc(var(--grandir-logo-badge-height) - var(--grandir-logo-bar-height) - 0.5rem);
	}

	/* The breadcrumbs start after the badge, which hangs over them. */
	.has-logo-badge .breadcrumbs ol {
		padding-inline-start: calc(9.375rem * min(1, var(--grandir-logo-ratio, 1)) + 3.5rem);
	}
}

@media screen and (min-width: 60em) and (prefers-reduced-motion: no-preference) {

	.has-logo-badge .site-branding {
		transition: margin-block-end 0.2s ease;
	}

	.has-logo-badge .site-branding .custom-logo {
		transition: height 0.2s ease;
	}
}

/* Regular (dark) logo on a white panel, when no dark-background logo is set. */
.site-branding--backed {
	background: #fff;
	border-radius: 6px;
	padding: 0.375rem 0.75rem;
}

.site-branding .site-title {
	color: inherit;
	font-size: 1.25rem;
	font-weight: 700;
	text-decoration: none;
}

.site-header__actions {
	align-items: center;
	display: flex;
	gap: 0.25rem;
}

.icon {
	display: block;
	flex-shrink: 0;
}

.site-header__call,
.menu-toggle,
.submenu-toggle {
	align-items: center;
	background: none;
	border: 0;
	border-radius: 4px;
	color: inherit;
	cursor: pointer;
	display: inline-flex;
	justify-content: center;
	min-height: 44px;
	min-width: 44px;
	padding: 0;
}

.site-header__call {
	gap: 0.5rem;
	text-decoration: none;
}

/* Mobile: icon only, the number stays available to screen readers. */
.site-header__call-number {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
	word-wrap: normal;
}

/* Hamburger morphs into an X when open. */
/* fill-box: each line turns around its own center, not the icon's. */
.icon-menu path {
	transform-box: fill-box;
	transform-origin: center;
	transition: transform 0.2s ease, opacity 0.2s ease;
}

.menu-toggle[aria-expanded="true"] .icon-menu__top {
	transform: translateY(6px) rotate(45deg);
}

.menu-toggle[aria-expanded="true"] .icon-menu__middle {
	opacity: 0;
}

.menu-toggle[aria-expanded="true"] .icon-menu__bottom {
	transform: translateY(-6px) rotate(-45deg);
}

.main-navigation ul {
	list-style: none;
	margin: 0;
	padding: 0;
}

.main-navigation li {
	position: relative;
}

.main-navigation a {
	color: inherit;
	display: block;
	text-decoration: none;
}

.submenu-toggle .icon {
	transition: transform 0.2s ease;
}

.submenu-toggle[aria-expanded="true"] .icon {
	transform: rotate(180deg);
}

/* Without JS the menu is a plain list under the header bar. */
.no-js .site-header__inner {
	flex-wrap: wrap;
}

.no-js .main-navigation {
	order: 3;
	width: 100%;
}

.no-js .menu-toggle,
.no-js .submenu-toggle {
	display: none;
}

/* Mobile overlay */
@media screen and (max-width: 59.9375em) {

	.js .main-navigation {
		background: var(--grandir-color-primary-deep);
		inset: var(--grandir-header-height, 4rem) 0 0 0;
		opacity: 0;
		overflow-y: auto;
		overscroll-behavior: contain;
		padding: 1rem;
		position: fixed;
		transition: opacity 0.2s ease, visibility 0.2s;
		visibility: hidden;
		z-index: 999;
	}

	.js .main-navigation.is-open {
		opacity: 1;
		visibility: visible;
	}

	html.nav-open {
		overflow: hidden;
	}

	.main-navigation .menu-item {
		align-items: center;
		border-block-end: 1px solid rgba(255, 255, 255, 0.15);
		display: flex;
		flex-wrap: wrap;
	}

	.main-navigation .menu > .menu-item > a {
		flex: 1;
		font-size: 1.25rem;
		padding-block: 0.875rem;
	}

	.main-navigation .sub-menu {
		display: none;
		padding-block-end: 0.5rem;
		padding-inline-start: 1rem;
		width: 100%;
	}

	.main-navigation .menu-item.is-open > .sub-menu {
		display: block;
	}

	.main-navigation .sub-menu .menu-item {
		border: 0;
	}

	.main-navigation .sub-menu a {
		flex: 1;
		padding-block: 0.625rem;
	}
}

/* Desktop: inline menu with dropdowns */
@media screen and (min-width: 60em) {

	.menu-toggle {
		display: none;
	}

	.site-header__call {
		font-weight: 700;
		padding-inline: 0.75rem;
	}

	/* Never broken across lines: a wide logo shrinks to make room instead. */
	.site-header__call-number {
		clip: auto;
		clip-path: none;
		height: auto;
		margin: 0;
		overflow: visible;
		position: static;
		white-space: nowrap;
		width: auto;
	}

	.main-navigation .menu {
		align-items: center;
		display: flex;
		gap: 0.25rem;
	}

	.main-navigation .menu > .menu-item {
		align-items: center;
		display: flex;
	}

	.main-navigation .menu > .menu-item > a {
		padding: 0.75rem;
	}

	.main-navigation .menu-item-has-children > a {
		padding-inline-end: 0;
	}

	/*
	 * Dropdowns stay white, with dark text, under the dark bar. They're nudged
	 * sideways to stay on screen (--grandir-dropdown-shift, js/navigation.js),
	 * and a tall one scrolls inside the window instead of running off it.
	 */
	.main-navigation .menu > .menu-item > .sub-menu {
		--grandir-color-focus: #111;
		background: var(--grandir-color-bg);
		border: 1px solid var(--grandir-color-border);
		border-radius: 4px;
		box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
		color: var(--grandir-color-text);
		inset-block-start: 100%;
		inset-inline-start: 0;
		max-height: calc(100vh - var(--grandir-header-height, 4rem) - 1rem);
		min-width: 14rem;
		opacity: 0;
		overflow-y: auto;
		overscroll-behavior: contain;
		padding-block: 0.5rem;
		position: absolute;
		transition: opacity 0.15s ease, visibility 0s linear 0.15s;
		translate: var(--grandir-dropdown-shift, 0);
		visibility: hidden;
		z-index: 1001;
	}

	/*
	 * Mouse users open dropdowns by hovering, keyboard users with the chevron
	 * (js/navigation.js), so Tab skips closed dropdowns. Without JS, keyboard
	 * focus opens them.
	 */
	.main-navigation .menu > .menu-item:hover > .sub-menu,
	.no-js .main-navigation .menu > .menu-item:focus-within > .sub-menu,
	.main-navigation .menu > .menu-item.is-open > .sub-menu {
		opacity: 1;

		/* Visible at once, so a quick Tab right after opening lands inside. */
		transition-delay: 0s;
		visibility: visible;
	}

	.main-navigation .sub-menu a {
		padding: 0.5rem 1rem;
	}

	.main-navigation .sub-menu a[href]:hover,
	.main-navigation .sub-menu a[href]:focus {
		background: var(--grandir-color-primary-tint);
	}

	/*
	 * Three levels: the groups stack in one column, with the third level
	 * always listed under its group, so the second-level chevrons aren't
	 * needed. Every second-level item is a bold heading, with or without
	 * items under it, and a line separates each from the one above.
	 */
	.main-navigation .menu-item--grouped > .sub-menu > .menu-item > a {
		font-weight: 700;
	}

	.main-navigation .menu-item--grouped > .sub-menu > .menu-item + .menu-item {
		border-block-start: 1px solid var(--grandir-color-border);
		margin-block-start: 0.25rem;
		padding-block-start: 0.25rem;
	}

	.main-navigation .sub-menu .sub-menu a {
		padding-inline-start: 1.5rem;
	}

	.main-navigation .sub-menu .submenu-toggle {
		display: none;
	}
}

/*
 * Desktop with a mouse: dropdowns open on hover, so mouse clicks pass through
 * the chevron to the menu item. It still works from the keyboard
 * (js/navigation.js). A label's chevron is its only control, so it stays clickable.
 */
@media screen and (min-width: 60em) and (hover: hover) {

	.submenu-toggle:not(.submenu-toggle--label) {
		pointer-events: none;
	}
}

/* Post and comment navigation
--------------------------------------------- */
.site-main .comment-navigation,
.site-main
.posts-navigation,
.site-main
.post-navigation {
	margin: 0 0 1.5em;
}

.comment-navigation .nav-links,
.posts-navigation .nav-links,
.post-navigation .nav-links {
	display: flex;
}

.comment-navigation .nav-previous,
.posts-navigation .nav-previous,
.post-navigation .nav-previous {
	flex: 1 0 50%;
}

.comment-navigation .nav-next,
.posts-navigation .nav-next,
.post-navigation .nav-next {
	text-align: end;
	flex: 1 0 50%;
}

/* Posts and pages
--------------------------------------------- */
.sticky {
	display: block;
}

/* Articles only: WordPress also puts the "page" class on <body> for every page. */
article.post,
article.page {
	margin: 0 0 1.5em;
}

.updated:not(.published) {
	display: none;
}

.page-content,
.entry-content,
.entry-summary {
	margin: 1.5em 0 0;
}

/* Editor content: a centered column at a readable width, the quote form's (720px). */
.entry-content {
	margin-inline: auto;
	max-width: var(--grandir-text-width);
}

.entry-content ul,
.entry-content ol {
	margin-inline-start: 0;
	padding-inline-start: 20px;
}

/* A page or post's title, featured image and edit link share that column. */
article:has(> .entry-content) > :is(.entry-header, .post-thumbnail, .entry-footer) {
	margin-inline: auto;
	max-width: var(--grandir-text-width);
}

.page-links {
	clear: both;
	margin: 0 0 1.5em;
}

/* Comments
--------------------------------------------- */
.comment-content a {
	word-wrap: break-word;
}

.bypostauthor {
	display: block;
}

/* Widgets
--------------------------------------------- */
.widget {
	margin: 0 0 1.5em;
}

.widget select {
	max-width: 100%;
}

/* Media
--------------------------------------------- */
.page-content .wp-smiley,
.entry-content .wp-smiley,
.comment-content .wp-smiley {
	border: none;
	margin-bottom: 0;
	margin-top: 0;
	padding: 0;
}

/* Make sure logo link wraps around logo image. */
.custom-logo-link {
	display: inline-block;
}

/* Captions
--------------------------------------------- */
.wp-caption {
	margin-bottom: 1.5em;
	max-width: 100%;
}

.wp-caption img[class*="wp-image-"] {
	display: block;
	margin-left: auto;
	margin-right: auto;
}

.wp-caption .wp-caption-text {
	margin: 0.8075em 0;
}

.wp-caption-text {
	text-align: center;
}

/* Galleries
--------------------------------------------- */
.gallery {
	margin-bottom: 1.5em;
	display: grid;
	grid-gap: 1.5em;
}

.gallery-item {
	display: inline-block;
	text-align: center;
	width: 100%;
}

.gallery-columns-2 {
	grid-template-columns: repeat(2, 1fr);
}

.gallery-columns-3 {
	grid-template-columns: repeat(3, 1fr);
}

.gallery-columns-4 {
	grid-template-columns: repeat(4, 1fr);
}

.gallery-columns-5 {
	grid-template-columns: repeat(5, 1fr);
}

.gallery-columns-6 {
	grid-template-columns: repeat(6, 1fr);
}

.gallery-columns-7 {
	grid-template-columns: repeat(7, 1fr);
}

.gallery-columns-8 {
	grid-template-columns: repeat(8, 1fr);
}

.gallery-columns-9 {
	grid-template-columns: repeat(9, 1fr);
}

.gallery-caption {
	display: block;
}

/*--------------------------------------------------------------
# Plugins
--------------------------------------------------------------*/

/* Jetpack infinite scroll
--------------------------------------------- */

/* Hide the Posts Navigation and the Footer when Infinite Scroll is in use. */
.infinite-scroll .posts-navigation,
.infinite-scroll.neverending .site-footer {
	display: none;
}

/* Re-display the Theme Footer when Infinite Scroll has reached its end. */
.infinity-end.neverending .site-footer {
	display: block;
}

/*--------------------------------------------------------------
# Utilities
--------------------------------------------------------------*/

/* Accessibility
--------------------------------------------- */

/* Text meant only for screen readers. */
.screen-reader-text {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute !important;
	width: 1px;
	word-wrap: normal !important;
}

.screen-reader-text:focus {
	background-color: #f1f1f1;
	border-radius: 3px;
	box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6);
	clip: auto !important;
	clip-path: none;
	color: #21759b;
	display: block;
	font-size: 0.875rem;
	font-weight: 700;
	height: auto;
	left: 5px;
	line-height: normal;
	padding: 15px 23px 14px;
	text-decoration: none;
	top: 5px;
	width: auto;
	z-index: 100000;
}

/* Do not show the outline on the skip link target. */
#primary[tabindex="-1"]:focus {
	outline: 0;
}

/* Alignments
--------------------------------------------- */
.alignleft {

	/*rtl:ignore*/
	float: left;

	/*rtl:ignore*/
	margin-right: 1.5em;
	margin-bottom: 1.5em;
}

.alignright {

	/*rtl:ignore*/
	float: right;

	/*rtl:ignore*/
	margin-left: 1.5em;
	margin-bottom: 1.5em;
}

.aligncenter {
	clear: both;
	display: block;
	margin-left: auto;
	margin-right: auto;
	margin-bottom: 1.5em;
}

/*--------------------------------------------------------------
# Grandir layout
Structural styles for the page-type templates. Visual design
(colors, typography, spacing scale) is layered on later.
Uses logical properties so the same rules work in RTL.
--------------------------------------------------------------*/
:root {
	--grandir-content-width: 72rem;
	/* Side spacing at the screen edge; doubles on desktop (below). Centered
	   content keeps a 70rem text area whatever the gutter. */
	--grandir-gutter: 1rem;
	--grandir-text-width: 45rem;
	--grandir-gap: 1.5rem;

	/*
	 * Design tokens. Style with these, never with hardcoded colors or fonts.
	 * Neutrals are fixed. Brand values are overridden from Appearance →
	 * Customize → Brand (inc/brand.php), which derives readable variants:
	 * - on-primary / on-accent: text on a primary / accent background (4.5:1+);
	 * - primary-hover: primary buttons on hover. Darker under white text,
	 *   lighter under dark text, and lighter for a near-black primary
	 *   (on-primary 4.5:1+);
	 * - primary-deep: dark brand background for white text (7:1+);
	 * - primary-tint: light brand background for any text (4.5:1+);
	 * - link: primary as text on bg, surface or tint (4.5:1+);
	 * - accent-ui: accent for borders and icons on bg, surface or tint (3:1+);
	 * - accent-text: accent as text on bg, surface or tint (4.5:1+);
	 * - accent-on-deep: accent for text and icons on primary-deep (the
	 *   footer), or white when the accent is too dark there (4.5:1+);
	 * - charcoal: charcoal tinted with primary-deep, for the breadcrumb bar
	 *   under the deep header (white text 7:1+, a visible step from deep);
	 * - hero-overlay: the overlay on hero photos, from the Hero Overlay
	 *   setting: brand (default), white, black or none. The tints are strong
	 *   enough for the hero text (4.5:1+) even over the worst part of the
	 *   photo (pure white under the brand and black tints, pure black under
	 *   the white one);
	 * - hero-text, hero-eyebrow: the hero's text and eyebrow h1 on a photo;
	 * - hero-btn-fill, hero-btn-on-fill, hero-btn-line: its buttons;
	 * - hero-text-shadow: none, except with no overlay, where nothing can
	 *   be guaranteed.
	 */
	--grandir-color-text: #404040;
	--grandir-color-text-muted: #595959;
	--grandir-color-bg: #fff;
	--grandir-color-surface: #f5f5f5;
	--grandir-color-border: #d9d9d9;
	--grandir-color-focus: #111;
	--grandir-color-primary: #1f4e79;
	--grandir-color-on-primary: #fff;
	--grandir-color-primary-hover: #1a4267;
	--grandir-color-primary-deep: #1f4e79;
	--grandir-color-primary-tint: #e4eaef;
	--grandir-color-link: #1f4e79;
	--grandir-color-accent: #1f4e79;
	--grandir-color-on-accent: #fff;
	--grandir-color-accent-ui: #1f4e79;
	--grandir-color-accent-text: #1f4e79;
	--grandir-color-accent-on-deep: #fff;
	--grandir-color-accent-on-primary: #fff;
	--grandir-color-charcoal: #273642;
	--grandir-hero-overlay: rgba(31, 78, 121, 0.75);
	--grandir-hero-text: #fff;
	--grandir-hero-eyebrow: #fff;
	--grandir-hero-btn-fill: #fff;
	--grandir-hero-btn-on-fill: #1f4e79;
	--grandir-hero-btn-line: #fff;
	--grandir-hero-text-shadow: none;
	--grandir-font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
	--grandir-font-heading: var(--grandir-font-body);

	/* Motion: hover and state changes. Only used under prefers-reduced-motion: no-preference. */
	--grandir-motion-fast: 150ms;
	--grandir-motion: 200ms;
	--grandir-ease: ease-out;
}

@media screen and (min-width: 60em) {

	:root {
		--grandir-gutter: 2rem;
	}
}

/*
 * One focus ring for everything: a dark ring with a white gap, visible on any
 * background. The button selectors outrank normalize's -moz-focusring rule.
 */
:focus-visible,
button:focus-visible,
[type="button"]:focus-visible,
[type="reset"]:focus-visible,
[type="submit"]:focus-visible {
	box-shadow: 0 0 0 2px var(--grandir-color-bg);
	outline: 3px solid var(--grandir-color-focus);
	outline-offset: 2px;
}

/* Keep the footer at the bottom of the screen on short pages. */
.site {
	display: flex;
	flex-direction: column;
	min-height: 100vh;

	/* Stops full-bleed sections causing sideways scroll. clip (unlike hidden) keeps the sticky header working. */
	overflow-x: clip;
}

.site-main {
	flex-grow: 1;
	margin-inline: auto;
	max-width: calc(var(--grandir-content-width) - 2rem + 2 * var(--grandir-gutter));
	padding-block-end: 3rem;
	padding-inline: var(--grandir-gutter);
	width: 100%;
}

.site-main > * + * {
	margin-block-start: 2.5rem;
}

/* Hero */
.hero {
	padding-block: 3rem;
	text-align: center;
}

.hero__heading {
	margin-block: 0 0.5em;
}

.hero__subheading {
	font-size: 1.25em;
	margin-block: 0 1em;
	margin-inline: auto;
	max-width: 37.5rem; /* 600px */
}

/*
 * Page titles: the <h1> is a small eyebrow (it keeps the SEO heading) and the
 * tagline under it carries the large heading look the h1 used to have.
 */
.eyebrow {
	color: var(--grandir-color-accent-text);
	font-family: var(--grandir-font-body);
	font-size: 1rem;
	font-weight: 700;
	letter-spacing: 0.12em;
	line-height: 1.4;
	margin-block: 0 0.5rem;
	text-transform: uppercase;
}

/* Page headers without a hero keep the space the h1 had above it. */
.page-title.eyebrow,
.entry-title.eyebrow {
	margin-block-start: 1.34rem;
}

.hero--image .eyebrow {
	color: var(--grandir-hero-eyebrow);
}

.hero:not(.hero--image) .eyebrow {
	color: var(--grandir-color-accent-on-primary);
}

.tagline {
	font-family: var(--grandir-font-heading);
	font-size: 2em;
	font-weight: 700;
	margin-block: 0 0.67em;
}

/*
 * Sits right above the subheading, which reads as its second line. Larger
 * than other taglines: 3em on phones, 3.5em on tablets, 4em on desktop.
 */
.hero__tagline {
	font-size: 3em;
	line-height: 1;
	margin-block: 0 0.25em;
	margin-inline: auto;
	max-width: 50rem; /* 800px */
}

@media screen and (min-width: 48em) {

	.hero__tagline {
		font-size: 3.5em;
	}
}

@media screen and (min-width: 60em) {

	.hero__tagline {
		font-size: 4em;
	}
}

/* Hero with the Featured Image behind the text, full width of the screen. */
.hero--image {
	align-items: center;
	color: var(--grandir-hero-text);
	display: flex;
	isolation: isolate;
	justify-content: center;
	margin-inline: calc(50% - 50vw);
	min-height: clamp(18rem, 55vh, 34rem);
	padding-inline: var(--grandir-gutter);
	position: relative;
}

.hero--image::before {
	background: var(--grandir-hero-overlay);
	content: "";
	inset: 0;
	position: absolute;
	z-index: -1;
}

/* With no overlay, a soft shadow in the opposite tone helps the text read. */
.hero--image :is(.hero__heading, .hero__tagline, .hero__subheading) {
	text-shadow: var(--grandir-hero-text-shadow);
}

.hero__image {
	height: 100%;
	inset: 0;
	object-fit: cover;
	position: absolute;
	width: 100%;
	z-index: -2;
}

.hero__inner {
	max-width: var(--grandir-content-width);
}

/* On a photo hero: the overlay's button colors (white on the brand and dark overlays). */
.hero--image .button {
	color: var(--grandir-hero-btn-line);
}

/* Buttons */
.button {
	border: 2px solid currentColor;
	border-radius: 4px;
	display: inline-block;
	font-weight: 700;
	padding: 0.75em 1.5em;
	text-decoration: none;
}

.button--primary,
.button--primary:visited,
.button--primary:hover,
.button--primary:focus {
	background: var(--grandir-color-primary);
	border-color: var(--grandir-color-primary);
	color: var(--grandir-color-on-primary);
}

.hero--image .button--primary {
	background: var(--grandir-hero-btn-fill);
	border-color: var(--grandir-hero-btn-fill);
	color: var(--grandir-hero-btn-on-fill);
}

.hero__actions,
.cta__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	justify-content: center;
}

/*
 * On page load the tagline and subheading fade in together from the right,
 * the eyebrow h1 is revealed from the top down and the button (when shown)
 * rises from below just after. The image stays still.
 */
@keyframes grandir-hero-in {

	from {
		opacity: 0;
		transform: translateX(4rem);
	}
}

@keyframes grandir-hero-up {

	from {
		opacity: 0;
		transform: translateY(2rem);
	}
}

@keyframes grandir-hero-reveal {

	from {
		clip-path: inset(0 0 100% 0);
	}

	to {
		clip-path: inset(0);
	}
}

@media (prefers-reduced-motion: no-preference) {

	.hero__inner > * {
		animation: grandir-hero-in 250ms var(--grandir-ease) both;
	}

	/* backwards, not both: the clip is dropped when the reveal ends. */
	.hero__inner > .hero__heading {
		animation: grandir-hero-reveal 400ms var(--grandir-ease) backwards;
	}

	.hero__inner > .hero__actions {
		animation-delay: 90ms;
		animation-name: grandir-hero-up;
	}
}

/* In-page anchors (e.g. "Get a quote" → #quote) land below the sticky header. */
section[id] {
	scroll-margin-top: calc(var(--grandir-header-height, 4rem) + 1rem);
}

@media (prefers-reduced-motion: no-preference) {

	html {
		scroll-behavior: smooth;
	}
}

/* Home: quote form */
.quote-form {
	margin-inline: auto;
	max-width: var(--grandir-text-width);
	text-align: center;
}

.quote-form__form {
	text-align: start;
}

/* Sits flush under the hero: the section gap between main's children would leave a white strip between the two bands. */
.site-main > .quote-form {
	margin-block-start: 0;
}

/* Home: service cards with a quote button at the bottom */
.card {
	display: flex;
	flex-direction: column;
}

.card__cta {
	margin-block: auto 0;
	padding-block-start: 1rem;
}

/* Full card width, and wrapped button text stays centered. */
.card__cta .button {
	display: block;
	text-align: center;
}

.card-grid-section__intro {
	margin-block-end: 1.5rem;
}

/* Home: page content (#about), centered at the quote form's width. */
.home-about {
	margin-inline: auto;
	max-width: var(--grandir-text-width);
	text-align: center;
}

.home-about img,
.home-about figure {
	margin-inline: auto;
}

/* Bullets sit beside their centered text instead of at the far left. */
.home-about ul,
.home-about ol {
	list-style-position: inside;
	padding-inline-start: 0;
}

/* Home: featured project. On wider screens the photo sits beside the text, which centers on it. */
@media screen and (min-width: 48em) {

	.home-project__item--image {
		column-gap: 2.5rem;
		display: grid;
		grid-template-areas:
			"image ."
			"image heading"
			"image summary"
			"image link"
			"image .";
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
		grid-template-rows: 1fr auto auto auto 1fr;
	}

	.home-project__item--image .home-project__image {
		grid-area: image;
	}

	.home-project__item--image .home-project__heading {
		grid-area: heading;
		margin-block-start: 0;
	}

	.home-project__item--image .home-project__summary {
		grid-area: summary;
	}

	.home-project__item--image .home-project__link {
		grid-area: link;
		margin-block-end: 0;
	}
}

/* Home: service areas */
.areas-list {
	display: grid;
	gap: 0 1.5rem;
	grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
	list-style: none;
	margin: 0;
	padding: 0;
}

.areas-list a {
	display: inline-block;
	padding-block: 0.5rem;
}

/* Area sections (Home and service pages): heading and intro centered over the area buttons. */
.home-areas__heading,
.service-areas__heading {
	text-align: center;
}

/*
 * The service-area image fills a landscape frame at the quote form's width,
 * like the featured project photo, so any upload stays landscape. A portrait
 * or square one is cropped from the center.
 */
.areas-image {
	aspect-ratio: 3 / 2;
	border-radius: 8px;
	margin: 1.5rem auto 0;
	max-width: var(--grandir-text-width);
	overflow: hidden;
}

.areas-image img {
	display: block;
	height: 100%;
	object-fit: cover;
	object-position: center;
	width: 100%;
}

/* Google reviews: the Trustindex widget between the label and the links */
.reviews__heading {
	margin-block-end: 0.25rem;
}

.reviews__source {
	color: var(--grandir-color-text-muted);
	font-size: 0.875rem;
	margin: 0 0 1.5rem;
}

.reviews__widget {
	min-width: 0;
}

.reviews__more {
	align-items: center;
	display: flex;
	flex-wrap: wrap;
	gap: 1rem 1.5rem;
	margin: 1.5rem 0 0;
}

/* Process steps: number badge above each step */
.process__steps {
	display: grid;
	gap: 2rem;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
	list-style: none;
	margin: 0;
	padding: 0;
}

/* Each step is a white card at every size, also readable on the tinted band. */
.process__step {
	background: var(--grandir-color-bg);
	border: 1px solid var(--grandir-color-border);
	border-radius: 8px;
	padding: 1.25rem;
}

/* Tablets: two steps across. Phones get the carousel, wider screens fit up to 4. */
@media screen and (min-width: 48em) and (max-width: 59.9375em) {

	.process__steps {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	/* An odd last step spans the row and centers at one column's width. */
	.process__step:last-child:nth-child(odd) {
		grid-column: 1 / -1;
		justify-self: center;
		width: calc((100% - 2rem) / 2);
	}
}

.process__number {
	align-items: center;
	border: 2px solid currentColor;
	border-radius: 50%;
	display: inline-flex;
	font-size: 1.25rem;
	font-weight: 700;
	height: 3rem;
	justify-content: center;
	width: 3rem;
}

.process__title {
	margin-block: 0.75rem 0.25rem;
}

.process__text {
	margin: 0;
}

/* What to Expect (service pages): intro, a callout for a paid or qualifying step, quote button */
.process__intro {
	margin: -0.5rem 0 1.5rem;
	max-width: var(--grandir-text-width);
}

.process__callout {
	background: var(--grandir-color-bg);
	border-inline-start: 4px solid var(--grandir-color-accent-ui);
	border-radius: 8px;
	margin-block-start: 2rem;
	max-width: var(--grandir-text-width);
	padding: 1.25rem 1.5rem;
}

.process__callout-heading {
	margin: 0 0 0.5rem;
}

.process__callout-text > :last-child {
	margin-block-end: 0;
}

.process__cta {
	margin: 1.5rem 0 0;
}

/* Service video: heading, click-to-play YouTube thumbnail and text, centered */
.service-video {
	margin-inline: auto;
	max-width: var(--grandir-text-width);
	text-align: center;
}

.service-video__heading {
	margin-block-start: 0;
}

.service-video__link,
.service-video__iframe {
	aspect-ratio: 16 / 9;
	border: 0;
	border-radius: 8px;
	display: block;
	width: 100%;
}

.service-video__link {
	background: #000;
	overflow: hidden;
	position: relative;
}

/* hqdefault thumbnails are 4:3 with black bars; cover crops them to 16:9. */
.service-video__thumbnail {
	display: block;
	height: 100%;
	object-fit: cover;
	width: 100%;
}

.service-video__play {
	align-items: center;
	background: var(--grandir-color-primary);
	border-radius: 50%;
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
	color: var(--grandir-color-on-primary);
	display: flex;
	height: 4rem;
	inset: 0;
	justify-content: center;
	margin: auto;
	position: absolute;
	width: 4rem;
}

.service-video__link:hover .service-video__play,
.service-video__link:focus-visible .service-video__play {
	background: var(--grandir-color-primary-hover);
}

.service-video__text {
	margin-block-start: 1.5rem;
}

.service-video__text > :last-child {
	margin-block-end: 0;
}

@media (prefers-reduced-motion: no-preference) {

	.service-video__play {
		transition: background-color var(--grandir-motion-fast) var(--grandir-ease), transform var(--grandir-motion) var(--grandir-ease);
	}

	.service-video__link:hover .service-video__play,
	.service-video__link:focus-visible .service-video__play {
		transform: scale(1.1);
	}
}

/* Service description: text and fact bullets, image beside them on wider screens */
.service-description {
	display: grid;
	gap: 2rem;
}

.service-description__body {
	max-width: var(--grandir-text-width);
}

.service-description__facts {
	border-block-start: 1px solid var(--grandir-color-border);
	display: grid;
	gap: 0.5rem;
	list-style: none;
	margin: 1.5rem 0 0;
	padding: 1.25rem 0 0;
}

.service-description__image {
	border-radius: 8px;
	display: block;
	height: auto;
	width: 100%;
}

@media screen and (min-width: 48em) {

	.service-description--image {
		align-items: center;
		grid-template-columns: 1fr 1fr;
	}
}

/* Why Choose: data point tiles, the job line and the Google reviews link */
.why-choose__heading {
	margin-block-start: 0;
}

.why-choose__points {
	display: grid;
	gap: 1rem;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
	list-style: none;
	margin: 1.5rem 0 0;
	padding: 0;
}

.why-choose__point,
.project-details__item {
	background: var(--grandir-color-bg);
	border: 1px solid var(--grandir-color-border);
	border-radius: 8px;
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
	padding: 1.25rem;
}

.why-choose__value {
	color: var(--grandir-color-accent-text);
	font-size: 2rem;
	font-weight: 700;
	line-height: 1.1;
}

.why-choose__value--text {
	font-size: 1.25rem;
}

.why-choose__label {
	color: var(--grandir-color-text-muted);
}

.why-choose__process {
	font-weight: 700;
	margin: 1.5rem 0 0;
}

.why-choose__reviews {
	margin: 1rem 0 0;
}

.review-badge {
	align-items: center;
	color: var(--grandir-color-link);
	display: inline-flex;
	font-weight: 700;
	gap: 0.5rem;
}

.review-badge .icon {
	color: var(--grandir-color-accent-ui);
	fill: currentColor;
}

/* Why It Matters: local context beside the common problems on wider screens */
.service-matters {
	display: grid;
	gap: 1.5rem 3rem;
}

.service-matters__heading {
	margin: 0;
}

.service-matters__context {
	max-width: var(--grandir-text-width);
}

.service-matters__context > :first-child,
.service-matters__problems-heading {
	margin-block-start: 0;
}

.service-matters__problems,
.area-problems__group {
	background: var(--grandir-color-surface);
	border-radius: 8px;
	padding: 1.25rem 1.5rem;
}

.service-matters__problems ul,
.area-problems__list {
	margin: 0;
	padding-inline-start: 1.25rem;
}

.service-matters__problems li + li,
.area-problems__list li + li {
	margin-block-start: 0.5rem;
}

.service-matters__problems li::marker,
.area-problems__list li::marker {
	color: var(--grandir-color-accent-ui);
}

@media screen and (min-width: 48em) {

	.service-matters--split {
		grid-template-columns: 3fr 2fr;
	}

	.service-matters--split .service-matters__heading {
		grid-column: 1 / -1;
	}
}

/* What's Included: sub-service cards on a light band, then a quote button */
.service-includes__heading {
	margin-block-start: 0;
}

/* Cards are laid out like the text-only service and area cards (see Card grid). */
.card-grid.service-includes__cards {
	list-style: none;
	margin: 1.5rem 0 0;
	padding: 0;
}

.card--include {
	padding-block-start: 1.25rem;
}

/* Square photo in the card's top corner, text below: small on phones, a third of the card on desktop. */
.card__thumb img {
	aspect-ratio: 1;
	border-radius: 8px;
	display: block;
	height: auto;
	object-fit: cover;
	width: 4rem;
}

@media screen and (min-width: 48em) {

	.card__thumb img {
		width: 33%;
	}
}

.card--include .card__title {
	margin-block-start: 0.75rem;
}

.card--include > .card__title:first-child {
	margin-block-start: 0;
}

.service-includes__cta {
	margin: 1.5rem 0 0;
}

/* Recent project: before/after photos, the project name and a link to the service's projects */
.service-project {
	text-align: center;
}

.service-project__heading {
	margin-block-start: 0;
}

/* The slider (or the single after photo) at the quote form's width, centered. */
.service-project .compare,
.service-project__image {
	margin-inline: auto;
	max-width: var(--grandir-text-width);
}

.service-project__image img,
.compare__img {
	border-radius: 8px;
	display: block;
	height: auto;
	width: 100%;
}

.service-project__title {
	margin-block: 1rem 0;
}

.service-project__more {
	margin: 1.5rem 0 0;
}

/* Without JS: before above after, each labelled. */
.compare {
	display: grid;
	gap: 1rem;
	margin: 0;
}

.compare__frame {
	display: grid;
	gap: 1rem;
}

.compare__before,
.compare__after {
	position: relative;
}

.compare__tag {
	background: rgb(0 0 0 / 0.65);
	border-radius: 4px;
	color: #fff;
	font-size: 0.875rem;
	font-weight: 700;
	inset-block-start: 0.75rem;
	inset-inline-start: 0.75rem;
	padding: 0.2em 0.6em;
	position: absolute;
}

/* With JS: the before photo sits on the after photo, clipped at the divider. */
.compare.is-enhanced .compare__frame {
	--position: 50%;
	aspect-ratio: 3 / 2;
	border-radius: 8px;
	cursor: ew-resize;
	direction: ltr;
	display: block;
	overflow: hidden;
	position: relative;
	touch-action: pan-y;
	user-select: none;
}

.compare.is-enhanced .compare__before,
.compare.is-enhanced .compare__after {
	height: 100%;
	inset: 0;
	position: absolute;
}

.compare.is-enhanced .compare__before {
	/*rtl:ignore*/
	clip-path: inset(0 calc(100% - var(--position)) 0 0);
	z-index: 1;
}

.compare.is-enhanced .compare__img {
	border-radius: 0;
	height: 100%;
	object-fit: cover;
}

.compare.is-enhanced .compare__tag--after {
	inset-inline: auto 0.75rem;
}

.compare.is-enhanced .compare__tag {
	z-index: 2;
}

/* The range input stays focusable for the keyboard but isn't seen; the handle shows its position. */
.compare__range {
	clip-path: inset(50%);
	height: 1px;
	margin: 0;
	overflow: hidden;
	position: absolute;
	width: 1px;
}

.compare__handle {
	background: #fff;
	box-shadow: 0 0 0 1px rgb(0 0 0 / 0.3);
	inset-block: 0;
	/*rtl:ignore*/
	left: var(--position);
	pointer-events: none;
	position: absolute;
	/*rtl:ignore*/
	transform: translateX(-50%);
	width: 3px;
	z-index: 2;
}

.compare__handle::after {
	background: #fff;
	border-radius: 50%;
	box-shadow: 0 1px 4px rgb(0 0 0 / 0.35);
	content: "";
	height: 2.5rem;
	/*rtl:ignore*/
	left: 50%;
	position: absolute;
	top: 50%;
	/*rtl:ignore*/
	transform: translate(-50%, -50%);
	width: 2.5rem;
}

.compare__range:focus-visible + .compare__handle::after {
	outline: 3px solid var(--grandir-color-focus);
	outline-offset: 2px;
}

/* Project pages: details cards, like the Why Choose tiles */
.project-details__heading,
.project-compare__heading,
.project-gallery__heading {
	margin-block-start: 0;
}

.project-details__items {
	display: grid;
	gap: 1rem;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
	margin: 1.5rem 0 0;
}

.project-details__label {
	color: var(--grandir-color-text-muted);
	font-size: 0.875rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

.project-details__value {
	color: var(--grandir-color-text);
	font-size: 1.125rem;
	font-weight: 700;
	margin: 0;
	overflow-wrap: anywhere;
}

.project-details__services {
	list-style: none;
	margin: 0;
	padding: 0;
}

/* Project pages: before/after slider (or the after photo alone), centered at the quote form's width like a service's Recent project */
.project-compare {
	text-align: center;
}

.project-compare .compare,
.project-compare__image {
	margin-inline: auto;
	max-width: var(--grandir-text-width);
}

.project-compare__image img {
	border-radius: 8px;
	display: block;
	height: auto;
	width: 100%;
}

/* Project pages: the summary lines up with the write-up's column. */
.project-summary {
	font-size: 1.125rem;
	margin-inline: auto;
	max-width: var(--grandir-text-width);
}

/* Project pages: gallery grid, 2 columns on phones and 3 from 768px */
.project-gallery__grid {
	display: grid;
	gap: 1rem;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	list-style: none;
	margin: 1.5rem 0 0;
	padding: 0;
}

@media screen and (min-width: 48em) {

	.project-gallery__grid {
		gap: 1.5rem;
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

.project-gallery__figure {
	margin: 0;
}

.project-gallery__link {
	border-radius: 8px;
	cursor: zoom-in;
	display: block;
}

.project-gallery__img {
	aspect-ratio: 4 / 3;
	border-radius: 8px;
	display: block;
	height: auto;
	object-fit: cover;
	width: 100%;
}

.project-gallery__caption {
	color: var(--grandir-color-text-muted);
	font-size: 0.9375rem;
	margin-block-start: 0.5rem;
}

/* Lightbox: the photo as large as fits, its caption over the bottom of the photo. */
.lightbox {
	--grandir-color-focus: #fff;
	background: none;
	border: 0;
	color: #fff;
	height: 100%;
	margin: 0;
	max-height: none;
	max-width: none;
	padding: 4rem 1rem;
	touch-action: pinch-zoom;
	width: 100%;
}

.lightbox[open] {
	align-items: center;
	display: flex;
	justify-content: center;
}

.lightbox::backdrop {
	background: rgb(0 0 0 / 0.9);
}

.lightbox__figure {
	margin: 0;
	position: relative;
	width: fit-content;
}

.lightbox__img {
	display: block;
	height: auto;
	max-height: calc(100vh - 8rem);
	max-height: calc(100dvh - 8rem);
	max-width: 100%;
	width: auto;
}

.lightbox__caption {
	background: linear-gradient(transparent, rgb(0 0 0 / 0.8));
	inset-block-end: 0;
	inset-inline: 0;
	padding: 2rem 1rem 0.75rem;
	position: absolute;
	text-align: center;
}

.lightbox__button {
	align-items: center;
	background: rgb(0 0 0 / 0.6);
	border: 1px solid rgb(255 255 255 / 0.5);
	border-radius: 50%;
	color: #fff;
	display: inline-flex;
	height: 3rem;
	justify-content: center;
	padding: 0;
	position: absolute;
	width: 3rem;
	z-index: 1;
}

.lightbox__button:hover {
	background: rgb(0 0 0 / 0.85);
	border-color: #fff;
}

.lightbox__button:focus-visible {
	outline: 3px solid var(--grandir-color-focus);
	outline-offset: 2px;
}

.lightbox__button--close {
	/*rtl:ignore*/
	right: 0.75rem;
	top: 0.75rem;
}

/* Previous on the left and next on the right in every language, matching the arrow keys. */
.lightbox__button--prev,
.lightbox__button--next {
	top: 50%;
	transform: translateY(-50%);
}

.lightbox__button--prev {
	/*rtl:ignore*/
	left: 0.75rem;
}

.lightbox__button--next {
	/*rtl:ignore*/
	right: 0.75rem;
}

.lightbox__button--next svg {
	transform: scaleX(-1);
}

.lightbox__count {
	font-size: 0.9375rem;
	inset-block-end: 1.25rem;
	inset-inline: 0;
	margin: 0;
	position: absolute;
	text-align: center;
}

/* Financing: a coupon-style box on the band, the terms beside a button to the partner */
.service-financing__coupon {
	align-items: center;
	background: var(--grandir-color-bg);
	border: 2px dashed var(--grandir-color-accent-ui);
	border-radius: 12px;
	display: flex;
	flex-wrap: wrap;
	gap: 1rem 2rem;
	justify-content: space-between;
	padding: 1.5rem;
}

@media screen and (min-width: 48em) {

	.service-financing__coupon {
		padding: 2rem 2.5rem;
	}
}

.service-financing__text {
	max-width: var(--grandir-text-width);
}

.service-financing__heading {
	margin-block: 0 0.5rem;
}

.service-financing__terms {
	font-size: 1.125rem;
	font-weight: 700;
	margin: 0;
}

.service-financing__partner {
	color: var(--grandir-color-text-muted);
	margin: 0.25rem 0 0;
}

.service-financing__action {
	margin: 0;
}

/* Service Area: where the service is offered */
.service-areas__heading {
	margin-block-end: 0.5rem;
}

.service-areas__intro {
	margin: 0 auto 1.25rem;
	max-width: var(--grandir-text-width);
	text-align: center;
}

/* FAQ intro (service pages), centered under the heading. */
.faqs__intro {
	margin: -0.25rem auto 1.25rem;
	max-width: var(--grandir-text-width);
	text-align: center;
}

/* Projects index filters: dropdowns side by side, stacked on phones. */
.project-filters {
	align-items: flex-end;
	display: flex;
	flex-wrap: wrap;
	gap: 1rem var(--grandir-gap);
	margin-block-end: var(--grandir-gap);
}

.project-filters__field {
	display: flex;
	flex: 1 1 14rem;
	flex-direction: column;
	gap: 0.25rem;
	max-width: 20rem;
}

/*
 * Labels use .eyebrow, a little smaller than the page title's; the field's
 * gap spaces them instead of its margin.
 */
.project-filters__field .eyebrow {
	font-size: 0.875rem;
	margin-block: 0;
}

.project-filters__field select {
	background-color: var(--grandir-color-bg);
	border: 1px solid var(--grandir-color-border);
	border-radius: 4px;
	color: var(--grandir-color-text);
	padding: 0.625em 0.75em;
	width: 100%;
}

.project-filters__submit {
	background: none;
	color: var(--grandir-color-link);
	cursor: pointer;
}

.project-filters--auto .project-filters__submit {
	display: none;
}

@media screen and (max-width: 37.4375em) {

	.project-filters__field {
		max-width: none;
	}
}

/* Card grid */
.card-grid {
	display: grid;
	gap: var(--grandir-gap);
	grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr));
}

.card__image--placeholder {
	aspect-ratio: 4 / 3;
	background: var(--grandir-color-surface);
}

.card__image img {
	aspect-ratio: 4 / 3;
	display: block;
	object-fit: cover;
	width: 100%;
}

.card__title {
	margin-block: 0.75em 0.25em;
}

/*
 * Text-only cards (services, areas and What's Included): 3 across, with a
 * short last row centered (flex, since a grid can't center a partial row).
 */
.card-grid--no-image,
.service-includes__cards {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
}

.card-grid--no-image > *,
.service-includes__cards > * {
	flex: 0 0 calc((100% - 2 * var(--grandir-gap)) / 3);
}

/*
 * Below the width where 3 cards fit (3 × 14rem + 2 gaps, plus main's 2rem
 * padding), 2 across down to 600px.
 */
@media screen and (max-width: 46.9375em) {

	.card-grid--no-image > *,
	.service-includes__cards > * {
		flex-basis: calc((100% - var(--grandir-gap)) / 2);
	}
}

/* Then one column, 340px at most and centered: card photos stay short. */
@media screen and (max-width: 37.4375em) {

	.card-grid--no-image > *,
	.service-includes__cards > * {
		flex-basis: 100%;
		max-width: 21.25rem;
	}
}

/* Two cards share the row; a lone card takes half of it (one column on phones). */
@media screen and (min-width: 37.5em) {

	.card-grid--no-image:has(> :nth-child(2):last-child) > *,
	.service-includes__cards:has(> :nth-child(2):last-child) > * {
		flex-basis: calc((100% - var(--grandir-gap)) / 2);
	}

	.card-grid--no-image > :only-child,
	.service-includes__cards > :only-child {
		flex-basis: 50%;
	}
}

.card--no-image {
	padding-block-start: 1.25rem;
}

.card--no-image > .card__title:first-child {
	margin-block-start: 0;
}

/* Cross-link lists */
.related-list__items {
	columns: 3 12rem;
	padding-inline-start: 1.25em;
}

/* Cross-links and area links (Home and service pages): each one is a button-like box with an icon (a chevron, or a pin for areas) that nudges on hover. */
.related-list--buttons .related-list__items,
.areas-list--buttons {
	columns: auto;
	display: grid;
	gap: 0.75rem;
	grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
	list-style: none;
	margin: 0;
	padding: 0;
}

.related-list--buttons .related-list__items a,
.areas-list--buttons a {
	align-items: center;
	background: var(--grandir-color-bg);
	border: 1px solid var(--grandir-color-border);
	border-radius: 8px;
	color: var(--grandir-color-link);
	display: flex;
	font-weight: 700;
	gap: 1rem;
	height: 100%;
	justify-content: space-between;
	padding: 1rem 1.25rem;
	text-decoration: none;
}

.related-list--buttons .related-list__items a:hover,
.areas-list--buttons a:hover {
	border-color: var(--grandir-color-accent-ui);
}

/* The cross-link heading centers over its buttons, like the area sections. */
.related-list--buttons .related-list__heading {
	text-align: center;
}

/*
 * On wider screens the buttons keep a set width and every row centers,
 * including a short last one; phones stack them full width.
 */
@media screen and (min-width: 48em) {

	.related-list--buttons .related-list__items,
	.areas-list--buttons {
		display: flex;
		flex-wrap: wrap;
		justify-content: center;
	}

	.related-list--buttons .related-list__items > li,
	.areas-list--buttons > li {
		flex: 0 1 16rem;
	}
}

/* The chevron icon points down; turn it to point right (rtlcss mirrors it for RTL). */
.related-list--buttons .icon-chevron {
	transform: rotate(-90deg);
}

/* Area links get a map pin instead, since they're places. */
.related-list--buttons .icon-chevron,
.areas-list--buttons .icon-pin {
	color: var(--grandir-color-accent-ui);
	flex-shrink: 0;
}

@media (prefers-reduced-motion: no-preference) {

	.related-list--buttons .related-list__items a,
	.areas-list--buttons a {
		transition: border-color var(--grandir-motion-fast) var(--grandir-ease);
	}

	.related-list--buttons .icon-chevron,
	.areas-list--buttons .icon-pin {
		transition: transform var(--grandir-motion) var(--grandir-ease);
	}

	/* translateY runs along the rotated icon, so this nudges it toward where it points. */
	.related-list--buttons .related-list__items a:hover .icon-chevron,
	.related-list--buttons .related-list__items a:focus-visible .icon-chevron {
		transform: rotate(-90deg) translateY(4px);
	}

	/* The pin lifts a little. */
	.areas-list--buttons a:hover .icon-pin,
	.areas-list--buttons a:focus-visible .icon-pin {
		transform: translateY(-3px);
	}
}

/*
 * Area pages: common problems, a list under each service's name in the
 * service page's grey box (see .service-matters__problems). One full-width
 * column up to desktop, then up to 3 across.
 */
.area-problems__intro {
	margin-block-end: 1.25rem;
	max-width: var(--grandir-text-width);
}

.area-problems__intro > :last-child {
	margin-block-end: 0;
}

.area-problems__groups {
	display: grid;
	gap: var(--grandir-gap);
}

@media screen and (min-width: 60em) {

	.area-problems__groups {
		grid-template-columns: repeat(auto-fit, minmax(max(16rem, (100% - 2 * var(--grandir-gap)) / 3), 1fr));
	}
}

.area-problems__service {
	font-size: 1.125rem;
	margin: 0 0 0.75rem;
}

/* Area pages: the map at the quote form's width, like the Contact map. */
.area-map__frame {
	border-radius: 8px;
	margin-inline: auto;
	max-width: var(--grandir-text-width);
	overflow: hidden;
}

.area-map__frame iframe {
	aspect-ratio: 16 / 9;
	border: 0;
	display: block;
	width: 100%;
}

/* Areas hub map, framed to fit every area (inc/area-map.php) */
.areas-map iframe {
	aspect-ratio: 4 / 3;
	border: 0;
	border-radius: 8px;
	display: block;
	width: 100%;
}

@media screen and (min-width: 48em) {

	/* Wide, to show a spread of towns. inc/area-map.php frames the map for this shape. */
	.areas-map iframe {
		aspect-ratio: 21 / 9;
	}
}

/* FAQs */
.faqs__heading {
	text-align: center;
}

.faq {
	border-block-end: 1px solid var(--grandir-color-border);
	padding-block: 1em;
}

/* A chevron at the end replaces the default triangle and turns when open. */
.faq__question {
	align-items: center;
	cursor: pointer;
	display: flex;
	font-weight: 700;
	gap: 1rem;
	justify-content: space-between;
	list-style: none;
}

.faq__question::-webkit-details-marker {
	display: none;
}

.faq__question::after {
	border-block-end: 2px solid currentColor;
	border-inline-end: 2px solid currentColor;
	content: "";
	flex-shrink: 0;
	height: 0.5em;
	margin-inline-end: 0.25em;
	transform: translateY(-25%) rotate(45deg);
	width: 0.5em;
}

/* Contains its paragraphs' margins, so its height is the same while it slides (js/faqs.js) and after. */
.faq__answer {
	display: flow-root;
}

/* While an answer slides shut (js/faqs.js), the chevron already points closed. */
.faq[open]:not(.is-closing) > .faq__question::after {
	transform: translateY(25%) rotate(-135deg);
}

/* Call to action */
.cta {
	padding-block: 3rem;
	text-align: center;
}

/*
 * Closing call to action (Home and service pages): heading, optional text and
 * buttons, with an accent rule above the footer.
 */
.cta--closing {
	border-block-end: 4px solid var(--grandir-color-accent);
}

/* Right after the tinted process band, the two bands meet without a gap. */
.process + .cta--closing {
	margin-block-start: 0;
}

.cta--closing .cta__heading {
	margin-block-start: 0;
}

.cta--closing .cta__actions {
	margin-block-end: 0;
}

.cta--closing .cta__text {
	margin-inline: auto;
	max-width: var(--grandir-text-width);
}

.cta__form {
	margin-inline: auto;
	max-width: var(--grandir-text-width);
	text-align: start;
}

/*
 * Breadcrumbs: a full-width bar in brand-tinted charcoal (white text at 7:1
 * or more), set apart from the deep brand header above it.
 */
.breadcrumbs {
	--grandir-color-focus: #fff;
	background: var(--grandir-color-charcoal);
	color: #fff;
	font-size: 0.875rem;
	margin-inline: calc(50% - 50vw);
	padding-block: 0.375rem;
	padding-inline: max(var(--grandir-gutter), calc((100vw - var(--grandir-content-width)) / 2 + 1rem));
}

.breadcrumbs a,
.breadcrumbs a:visited,
.breadcrumbs a:hover,
.breadcrumbs a:focus,
.breadcrumbs a:active {
	color: inherit;
}

/* The hero sits right under the bar. */
.site-main > .breadcrumbs ~ .hero,
.site-main > .breadcrumbs ~ .hero-intro {
	margin-block-start: 0;
}

.breadcrumbs ol {
	display: flex;
	flex-wrap: wrap;
	list-style: none;
	margin: 0;
	padding: 0;
}

.breadcrumbs li + li::before {
	content: "\203A";
	padding-inline: 0.5em;
}

/* Opening hours (footer and Contact): one row per day, times aligned. */
.hours {
	column-gap: 1em;
	display: grid;
	grid-template-columns: max-content 1fr;
	margin: 0;
	row-gap: 0.125rem;
}

/* The row wrappers group each day with its times for assistive technology; the grid lays out their cells. */
.hours__row {
	display: contents;
}

.hours__day {
	font-weight: 600;
}

.hours__time {
	margin: 0;
}

.hours__note,
.site-footer__detail .hours__note {
	margin-block: 0.5rem 0;
}

/* Contact */
.contact {
	display: grid;
	gap: var(--grandir-gap);
}

/* The section gap under the hero (article.page would otherwise zero it). */
.site-main > .contact {
	margin-block-start: 2.5rem;
}

@media screen and (min-width: 48em) {

	/* Form (60%) beside the hours and map (40%); with neither, the form takes the full width. */
	.contact--has-details {
		gap: calc(var(--grandir-gap) * 2);
		grid-template-columns: 3fr 2fr;
	}

	/* The map fills the column below the hours, down to the bottom of the form. */
	.contact__details {
		display: flex;
		flex-direction: column;
	}

	/*
	 * The Hours heading's letters line up with the top of the form card:
	 * text-box trims the space above the capitals (Chrome, Edge, Safari;
	 * other browsers leave it a few pixels lower).
	 */
	.contact__details > h2:first-child {
		margin-block-start: 0;
		text-box: trim-start cap alphabetic;
	}

	/* Flex items' margins don't collapse: keep the heading-to-hours space as it was. */
	.contact__hours {
		margin-block-start: 0;
	}

	.contact__map {
		flex: 1;
		min-height: 18rem;
		position: relative;
	}

	.contact__map iframe {
		aspect-ratio: auto;
		height: 100%;
		inset: 0;
		position: absolute;
	}
}

.contact__map iframe {
	aspect-ratio: 16 / 9;
	border: 0;
	border-radius: 8px;
	display: block;
	width: 100%;
}

/* Utility pages */
.site-main--utility {
	max-width: var(--grandir-text-width);
}

.utility__updated {
	font-size: 0.875em;
}

/* Footer
 * Mobile: everything stacked. 48em+: business details beside quick links,
 * and the bottom bar in one row.
 */
.site-footer {
	background: var(--grandir-color-primary-deep);
	color: #fff;
}

.site-footer__inner,
.site-footer__bottom-inner {
	margin-inline: auto;
	max-width: calc(var(--grandir-content-width) - 2rem + 2 * var(--grandir-gutter));
	padding-inline: var(--grandir-gutter);
}

.site-footer__inner {
	display: grid;
	gap: 2rem;
	padding-block: 2.5rem;
}

.site-footer__logo {
	display: inline-block;
	margin-block-end: 1rem;
}

.site-footer__logo .custom-logo {
	display: block;
	height: auto;
	max-height: min(calc(4rem * var(--grandir-logo-scale, 1)), 6rem);
	width: auto;
	max-width: 100%;
}

.site-footer__logo .custom-logo[src$=".svg"] {
	height: min(calc(4rem * var(--grandir-logo-scale, 1)), 6rem);
}

.site-footer .site-title {
	color: inherit;
	font-size: 1.25rem;
	font-weight: 700;
	text-decoration: none;
}

.site-footer__name {
	font-weight: 700;
	margin-block: 0 0.75rem;
}

.site-footer__detail {
	align-items: flex-start;
	display: flex;
	gap: 0.625rem;
	margin-block-end: 0.75rem;
}

.site-footer__detail .icon {
	height: 1.25rem;
	margin-block-start: 0.15em;
	width: 1.25rem;
}

.site-footer__detail address,
.site-footer__detail p {
	font-style: normal;
	margin: 0;
}

.site-footer__heading {
	font-size: 1rem;
	margin-block: 0 0.75rem;
}

.site-footer__links,
.site-footer__social,
.site-footer__legal {
	list-style: none;
	margin: 0;
	padding: 0;
}

.site-footer__links a {
	color: inherit;
	display: inline-block;
	padding-block: 0.5rem;
}

.site-footer__bottom {
	border-block-start: 1px solid rgba(255, 255, 255, 0.25);
	font-size: 0.875rem;
}

.site-footer__bottom-inner {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	padding-block: 1.25rem;
}

.site-footer__license,
.site-footer__copyright {
	margin: 0;
}

.site-footer__social {
	display: flex;
	flex-wrap: wrap;
	gap: 0.25rem;
}

.site-footer__social a {
	align-items: center;
	color: inherit;
	display: inline-flex;
	justify-content: center;
	min-height: 44px;
	min-width: 44px;
}

.site-footer__legal {
	display: flex;
	flex-wrap: wrap;
	gap: 0.25rem 1rem;
	margin-block-end: 0.5rem;
}

.site-footer__legal a {
	color: inherit;
	display: inline-block;
	padding-block: 0.25rem;
}

@media screen and (min-width: 48em) {

	.site-footer__inner {
		grid-template-columns: 2fr 1fr;
	}

	.site-footer__links {
		columns: 2;
	}

	.site-footer__bottom-inner {
		align-items: center;
		flex-direction: row;
		flex-wrap: wrap;
	}

	.site-footer__social {
		margin-inline-start: auto;
	}

	.site-info {
		flex-basis: 100%;
	}
}

/*
 * Balanced line breaks: text-wrap: pretty avoids a lone word on the last
 * line. It's inherited, so containers cover the paragraphs and list items
 * inside them. Browsers without it wrap as before.
 */

/* Page titles */
.eyebrow,
.tagline,
/* Hero and quote form */
.hero__heading,
.hero__subheading,
.quote-form__heading,
.quote-form__text,
/* Service cards' quote buttons */
.card__cta .button,
/* Service areas */
.home-areas__heading,
.service-areas__heading,
/* FAQs */
.faqs__heading,
.faq__question,
.faq__answer,
/* Process */
.process__heading,
.process__title,
.process__callout-heading,
.process__intro,
.process__text,
.process__callout-text,
/* Home: featured project and page content */
.home-project__heading,
.home-project__summary,
.home-about,
/* Service pages: financing */
.service-financing__heading,
.service-financing__text,
.service-financing__coupon,
.service-financing__partner,
.service-financing__terms,
/* Service pages: video */
.service-video__heading,
.service-video__text,
/* Service pages: description */
.service-description__heading,
.service-description__text,
/* Service pages: why choose */
.why-choose__heading,
.why-choose__point,
/* Service pages: why it matters */
.service-matters__heading,
.service-matters__context,
.service-matters__problems,
/* Service pages: what's included */
.service-includes__heading,
.card--include .card__title,
.card--include .card__excerpt {
	text-wrap: pretty;
}

/*--------------------------------------------------------------
# Brand color
Where the brand colors become backgrounds. Every pairing here uses a
derived token from inc/brand.php, so it meets WCAG AA for any brand.
Forms always sit in a white card (WPForms styles its own labels).
--------------------------------------------------------------*/

/*
 * A page that ends with a band meets the footer directly; otherwise main's
 * bottom padding keeps the last content off the footer.
 */
.site-main:has(> :is(.hero:not(.hero--image), .quote-form, .cta, .home-project, .home-areas, .why-choose, .service-includes, .service-financing, .process):last-child) {
	padding-block-end: 0;
}

/* Full-width bands, content realigned to the page width. */
.hero:not(.hero--image),
.quote-form,
.cta,
.home-project,
.home-areas,
.why-choose,
.project-details,
.service-includes,
.service-financing,
.process {
	margin-inline: calc(50% - 50vw);
	max-width: none;
	padding-block: 3rem;
	padding-inline: max(var(--grandir-gutter), calc((100vw - var(--grandir-content-width)) / 2 + 1rem));
}

.quote-form > * {
	margin-inline: auto;
	max-width: var(--grandir-text-width);
}

/* Light brand bands. */
.quote-form,
.home-project,
.home-areas,
.why-choose,
.project-details,
.service-includes,
.service-financing,
.process {
	background: var(--grandir-color-primary-tint);
}

/*
 * Home, below 960px: the quote form is its own tinted band, so Why Choose
 * continues it as one band instead of adding a second gap. Only when the form
 * is there (the .hero-intro wrapper); without it Why Choose follows the hero.
 */
@media screen and (max-width: 59.9375em) {

	.site-main--home > .hero-intro + .why-choose {
		margin-block-start: 0;
		padding-block-start: 0;
	}
}

/* Project pages: the details band sits right under the hero. */
.site-main--project > .hero + .project-details {
	margin-block-start: 0;
}

/* Solid brand bands: plain hero and the call to action. */
.hero:not(.hero--image),
.cta {
	--grandir-color-focus: currentColor;
	background: var(--grandir-color-primary);
	color: var(--grandir-color-on-primary);
}

.hero:not(.hero--image) .button,
.hero:not(.hero--image) .button:visited,
.cta__actions .button,
.cta__actions .button:visited {
	color: var(--grandir-color-on-primary);
}

/* Primary button on a primary background: same pair, inverted. */
.hero:not(.hero--image) .button--primary,
.hero:not(.hero--image) .button--primary:visited,
.cta__actions .button--primary,
.cta__actions .button--primary:visited {
	background: var(--grandir-color-on-primary);
	border-color: var(--grandir-color-on-primary);
	color: var(--grandir-color-primary);
}

/* Form card on any band, and on the Contact page. */
.quote-form__form,
.cta__form,
.contact__form {
	--grandir-color-focus: #111;
	background: var(--grandir-color-bg);
	border-block-start: 4px solid var(--grandir-color-primary);
	border-radius: 8px;
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
	color: var(--grandir-color-text);
	padding: 1.5rem;
	text-align: start;
}

/*
 * Hero intro (Home and service pages): on desktop the quote form's card sits
 * in the hero's right column (40%), hanging 4rem below the hero, and the hero
 * text moves to the left 60%. Both sections stack in one grid cell; the form
 * section is transparent and lets clicks through except on its card. Below
 * 60em nothing here applies: the hero and the form band stack as before.
 */
@media screen and (min-width: 60em) {

	/* On main, so the section after the intro can use the overlap too. */
	.site-main {
		--grandir-intro-overlap: 4rem;
		--grandir-intro-gap: 2.5rem;
	}

	.hero-intro {
		display: grid;
	}

	.hero-intro > .hero,
	.hero-intro > .quote-form {
		grid-area: 1 / 1;
	}

	/* Both hero styles center their text block vertically and align it left. */
	/*
	 * The hero's side padding is the same as the form band's, so the text
	 * column and the card measure against one box and line up with each other
	 * and the page content at every width (photo heroes otherwise use 1rem).
	 */
	.hero-intro > .hero {
		align-items: center;
		display: flex;
		justify-content: center;
		padding-block: 3rem;
		padding-inline: max(var(--grandir-gutter), calc((100vw - var(--grandir-content-width)) / 2 + 1rem));
		text-align: start;
	}

	.hero-intro .hero__inner {
		box-sizing: border-box;
		max-width: none;
		padding-inline-end: calc(40% + var(--grandir-intro-gap));
		width: 100%;
	}

	/* Left-aligned with the text column, not centered in it. */
	.hero-intro .hero__tagline,
	.hero-intro .hero__subheading {
		margin-inline: 0;
	}

	/* The form is right there, so the hero's quote button (its only action) goes. */
	.hero-intro .hero__actions {
		display: none;
	}

	.hero-intro > .quote-form {
		align-self: end;
		background: none;
		margin-block-end: calc(-1 * var(--grandir-intro-overlap));
		padding-block: 3rem 0;
		pointer-events: none;
		position: relative;
		text-align: start;
		z-index: 1;
	}

	.hero-intro .quote-form > .quote-form__card {
		margin-inline: auto 0;
		max-width: none;
		width: 40%;
	}

	/* The card: heading, text and fields together, styled like the form card. */
	.hero-intro .quote-form__card {
		--grandir-color-focus: #111;
		background: var(--grandir-color-bg);
		border-block-start: 4px solid var(--grandir-color-primary);
		border-radius: 8px;
		box-shadow: 0 8px 28px rgba(0, 0, 0, 0.18);
		box-sizing: border-box;
		color: var(--grandir-color-text);
		padding: 1.5rem;
		pointer-events: auto;
	}

	.hero-intro .quote-form__heading {
		margin-block-start: 0;
	}

	.hero-intro .quote-form__form {
		background: none;
		border: 0;
		border-radius: 0;
		box-shadow: none;
		padding: 0;
	}

	/* Room for the card's overhang above the next section. */
	.hero-intro + * {
		margin-block-start: calc(2.5rem + var(--grandir-intro-overlap));
	}

	/*
	 * Home: Why Choose's tinted band starts right under the hero, with the
	 * card hanging over it (the card is positioned, so it stays on top), and
	 * its own top padding clears the overhang: 100px, 36px below the card.
	 */
	.site-main--home > .hero-intro + .why-choose {
		margin-block-start: 0;
		padding-block-start: calc(var(--grandir-intro-overlap) + 2.25rem);
	}
}

/*
 * WPForms lead form (Home quote form, CTA and Contact). Brand colors go in
 * through WPForms' own variables, which it defines on :root. Field borders
 * keep WPForms' darker default, because --grandir-color-border is too faint
 * to mark an input.
 */
.lead-form {
	--wpforms-button-background-color: var(--grandir-color-primary);
	--wpforms-button-border-color: var(--grandir-color-primary);
	--wpforms-button-text-color: var(--grandir-color-on-primary);
	--wpforms-button-border-radius: 4px;
	--wpforms-field-border-radius: 4px;
	--wpforms-field-text-color: var(--grandir-color-text);
	--wpforms-label-color: var(--grandir-color-text);
	--wpforms-label-sublabel-color: var(--grandir-color-text-muted);
}

/* The card already spaces the form. */
.lead-form div.wpforms-container-full:not(:empty) {
	margin: 0;
}

/* Every field spans the card, not WPForms' 60% "medium" size. */
.lead-form div.wpforms-container .wpforms-form .wpforms-field .wpforms-field-medium {
	max-width: 100%;
}

.lead-form div.wpforms-container-full .wpforms-form button[type="submit"] {
	font-weight: 700;
}

/* WPForms sets outline: none on focus. Bring back the theme's one ring. */
.lead-form div.wpforms-container-full .wpforms-form :is(input, select, textarea, button):focus-visible {
	box-shadow: 0 0 0 2px var(--grandir-color-bg);
	outline: 3px solid var(--grandir-color-focus);
	outline-offset: 2px;
}

/*
 * Floating labels: the label rests inside its field like a placeholder, and
 * moves up onto the top border when the field is focused or filled. "Filled"
 * is :not(:placeholder-shown), so inc/lead-form.php gives each field a blank
 * placeholder. Leave the builder's placeholders empty. Browsers without
 * :has() keep the label above the field.
 */
@supports selector(:has(*)) {

	.lead-form div.wpforms-container-full .wpforms-field .wpforms-field-label {
		background: var(--grandir-color-bg);
		color: var(--grandir-color-text-muted);
		font-weight: 400;
		left: calc(var(--wpforms-field-size-padding-h) - 3px);
		margin: 0;
		max-width: calc(100% - 2 * var(--wpforms-field-size-padding-h));
		overflow: hidden;
		padding-inline: 4px;
		pointer-events: none;
		position: absolute;
		text-overflow: ellipsis;
		top: calc(15px + (var(--wpforms-field-size-input-height) - var(--wpforms-label-size-line-height)) / 2);
		transform-origin: left center;
		white-space: nowrap;
		z-index: 1;
	}

	/* Focused, filled, or a dropdown (which always shows a choice). */
	.lead-form div.wpforms-container-full .wpforms-field:is(:has(:focus), :has(:is(input, textarea):not(:placeholder-shown)), :has(select)) .wpforms-field-label {
		color: var(--grandir-color-text);
		font-weight: 700;
		transform: translateY(calc(var(--wpforms-field-size-input-height) / -2)) scale(0.8);
	}

	.lead-form div.wpforms-container-full .wpforms-field:has(:focus) .wpforms-field-label {
		color: var(--grandir-color-link);
	}
}

@media (prefers-reduced-motion: no-preference) {

	.lead-form div.wpforms-container-full .wpforms-field .wpforms-field-label {
		transition: transform 150ms ease, color 150ms ease;
	}
}

/* Header call link: white on the dark header (link colors are for light backgrounds). */
.site-header__call {
	color: inherit;
}

/* Process: filled accent numbers. */
.process__number {
	background: var(--grandir-color-accent);
	border-color: var(--grandir-color-accent);
	color: var(--grandir-color-on-accent);
}

/*
 * Carousels (js/carousel.js): process steps on phones. The list is a swipe carousel
 * of white cards, the next one peeking in, bleeding to the screen edges. The
 * script adds the controls and mouse drag. Without JS, mouse users get a thin
 * scrollbar instead, so it still moves; touch never shows it since swiping
 * works there.
 */
@media screen and (max-width: 47.9375em) {

	.process__steps {
		gap: 1rem;
		grid-auto-columns: 85%;
		grid-auto-flow: column;
		grid-template-columns: none;
		margin-inline: -1rem;
		overflow-x: auto;
		overscroll-behavior-x: contain;
		padding-block-end: 0.75rem;
		padding-inline: 1rem;
		scroll-padding-inline: 1rem;
		scroll-snap-type: x mandatory;
		scrollbar-color: var(--grandir-color-accent-ui) transparent;
		scrollbar-width: thin;
	}

	.process__step {
		scroll-snap-align: start;
	}
}

/* Touch swipes, so it never needs the scrollbar. */
@media (hover: none) {

	[data-carousel] {
		scrollbar-width: none;
	}

	.process__steps {
		padding-block-end: 0;
	}

	[data-carousel]::-webkit-scrollbar {
		display: none;
	}
}

/* With the script running, the arrows and drag replace the scrollbar. */
[data-carousel].is-enhanced {
	padding-block-end: 0;
	scrollbar-width: none;
}

[data-carousel].is-enhanced::-webkit-scrollbar {
	display: none;
}

@media (prefers-reduced-motion: no-preference) {

	[data-carousel] {
		scroll-behavior: smooth;
	}
}

/* Mouse drag: snapping pauses while dragging and while settling on a card. */
[data-carousel].is-draggable {
	cursor: grab;
}

[data-carousel].is-dragging,
[data-carousel].is-settling {
	scroll-snap-type: none;
}

[data-carousel].is-dragging {
	cursor: grabbing;
	scroll-behavior: auto;
	user-select: none;
}

/* Controls: shown by the script only while the list scrolls sideways. */
.carousel__nav {
	align-items: center;
	display: flex;
	gap: 0.5rem;
	justify-content: center;
	margin-block-start: 1rem;
}

.carousel__nav[hidden] {
	display: none;
}

.carousel__dots {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
}

.carousel__dot,
.carousel__arrow {
	align-items: center;
	background: none;
	border: 0;
	display: inline-flex;
	justify-content: center;
	padding: 0;
}

.carousel__dot {
	height: 2rem;
	width: 2rem;
}

/* Hollow dots, the current one filled: shape and color both mark it. */
.carousel__dot::before {
	border: 2px solid var(--grandir-color-text-muted);
	border-radius: 50%;
	box-sizing: border-box;
	content: "";
	height: 0.875rem;
	width: 0.875rem;
}

.carousel__dot[aria-current]::before {
	background: var(--grandir-color-accent-ui);
	border-color: var(--grandir-color-accent-ui);
}

/* Prev/next arrows: mouse and trackpad only; touch swipes. */
.carousel__arrow {
	background: var(--grandir-color-bg);
	border: 1px solid var(--grandir-color-border);
	border-radius: 50%;
	color: var(--grandir-color-accent-ui);
	display: none;
	flex-shrink: 0;
	height: 2.5rem;
	width: 2.5rem;
}

.carousel__arrow svg {
	height: 1.25rem;
	width: 1.25rem;
}

.carousel__arrow--next svg,
[dir="rtl"] .carousel__arrow--prev svg {
	transform: scaleX(-1);
}

[dir="rtl"] .carousel__arrow--next svg {
	transform: none;
}

.carousel__arrow:hover,
.carousel__arrow:focus {
	border-color: var(--grandir-color-border);
}

.carousel__arrow:not([aria-disabled="true"]):hover {
	border-color: var(--grandir-color-accent-ui);
}

.carousel__arrow[aria-disabled="true"] {
	cursor: default;
	opacity: 0.4;
}

@media (hover: hover) and (pointer: fine) {

	.carousel__arrow {
		display: inline-flex;
	}
}

/* Cards: white panels, also readable on tinted bands. */
.card {
	background: var(--grandir-color-bg);
	border: 1px solid var(--grandir-color-border);
	border-radius: 8px;
	overflow: hidden;
	padding-block-end: 1rem;
}

.card > :not(.card__image) {
	padding-inline: 1rem;
}

.card__title a {
	color: var(--grandir-color-link);
}

/*
 * Service cards (Home and Services page): the service's hero photo as a band
 * at the top with the white title over its bottom edge, then the excerpt and
 * the quote button on the white card.
 */
.card--bg {
	border-color: #333;
	display: grid;
	grid-template-rows: auto auto 1fr;
	padding-block-start: 0;
}

/* Grows with a title taller than the band; cropped from the center. */
.card > .card__bg {
	align-self: stretch;
	aspect-ratio: 16 / 10;
	display: block;
	grid-area: 1 / 1;
	height: auto;
	object-fit: cover;
	padding: 0;
	width: 100%;
}

/*
 * The title sits on its own dark fade over the photo: the text always has at
 * least 60% black behind it, about 5.7:1 for white text even over pure white.
 */
.card--bg .card__title {
	--grandir-color-focus: #fff;
	align-self: end;
	background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.6) 3rem);
	font-size: 2em;
	grid-area: 1 / 1;
	margin: 0;
	padding: 3rem 1rem 0.75rem;
	position: relative;
}

.card--bg .card__title a {
	color: #fff;
	text-decoration: none;
}

/* Without a photo the title sits on the white card in the link color. */
.card--bg:not(:has(> .card__bg)) .card__title {
	--grandir-color-focus: inherit;
	background: none;
	padding-block-start: 1.25rem;
}

.card--bg:not(:has(> .card__bg)) .card__title a {
	color: var(--grandir-color-link);
}

.card--bg .card__excerpt {
	margin-block: 1rem 0;
}

.card--bg .card__cta {
	align-self: end;
}

/* Dark brand footer. */
.site-footer {
	--grandir-color-focus: #fff;
}

.site-footer a,
.site-footer a:visited {
	color: inherit;
}

/* Regular (dark) logo on a white panel, when no dark-background logo is set. */
.site-footer__logo--backed {
	background: #fff;
	border-radius: 8px;
	display: inline-block;
	padding: 0.75rem 1rem;
}

/*--------------------------------------------------------------
# Hover polish
Small, brand-colored feedback on things people can click. Hover styles
only apply on devices that can hover, so a tap never leaves a card
lifted. Keyboard focus gets the same effect. Movement stays at 1–2px
and only runs without prefers-reduced-motion. Colors still change there.
--------------------------------------------------------------*/

/* The card and featured project photos zoom inside their own frame. */
.card__image,
.home-project__image {
	display: block;
	overflow: hidden;
}

/*
 * The featured project photo fills a landscape frame, capped in height, so it
 * never takes over the section. A portrait upload is cropped from the center.
 */
.home-project__image {
	aspect-ratio: 3 / 2;
	border-radius: 8px;
	max-height: 24rem;
	width: 100%;
}

.home-project__image img {
	display: block;
	height: 100%;
	object-fit: cover;
	object-position: center;
	width: 100%;
}

/* "View all": an arrow that nudges on hover. */
.card-grid-section__more a::after {
	content: "\2192";
	content: "\2192" / "";
	display: inline-block;
	margin-inline-start: 0.35em;
}

/* Header phone icon: a short ring on hover. */
@keyframes grandir-ring {

	0%,
	100% {
		transform: rotate(0);
	}

	20% {
		transform: rotate(-14deg);
	}

	40% {
		transform: rotate(12deg);
	}

	60% {
		transform: rotate(-8deg);
	}

	80% {
		transform: rotate(4deg);
	}
}

/* Desktop nav: a brand bar under the link, always shown on the current page. */
@media screen and (min-width: 60em) {

	.main-navigation .menu > .menu-item > a {
		position: relative;
	}

	.main-navigation .menu > .menu-item > a::after {
		background: var(--grandir-color-accent-on-deep);
		content: "";
		height: 2px;
		inset-block-end: 0.35rem;
		inset-inline: 0.75rem;
		position: absolute;
		transform: scaleX(0);
	}

	.main-navigation .menu-item-has-children > a::after {
		inset-inline-end: 0;
	}

	.main-navigation .menu > .menu-item > a:focus-visible::after,
	.main-navigation .menu > .current-menu-item > a::after,
	.main-navigation .menu > .current-menu-ancestor > a::after {
		transform: scaleX(1);
	}
}

/* Keyboard focus: the same effects as hover. */
.button:focus-visible {
	transform: translateY(-1px);
}

.card-grid-section__more a:focus-visible::after {
	transform: translateX(3px);
}

.home-project__item:has(.home-project__link a:focus-visible) .home-project__image img {
	transform: scale(1.03);
}

.site-footer__social a:focus-visible {
	color: var(--grandir-color-accent-on-deep);
	transform: translateY(-2px);
}

.card:focus-within {
	border-color: var(--grandir-color-accent-ui);
	box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
	transform: translateY(-2px);
}

@media (hover: hover) {

	/* Buttons lift, and a soft shadow appears. */
	.button:hover,
	.lead-form div.wpforms-container-full .wpforms-form button[type="submit"]:hover {
		box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
		transform: translateY(-1px);
	}

	/* Primary buttons: a shade darker (or lighter under dark text). */
	.button--primary:hover,
	.lead-form div.wpforms-container-full .wpforms-form button[type="submit"]:hover {
		background: var(--grandir-color-primary-hover);
		border-color: var(--grandir-color-primary-hover);
		color: var(--grandir-color-on-primary);
	}

	/* Hero and CTA band primary buttons are already inverted: keep colors. */
	.hero--image .button--primary:hover {
		background: var(--grandir-hero-btn-fill);
		border-color: var(--grandir-hero-btn-fill);
		color: var(--grandir-hero-btn-on-fill);
	}

	.hero:not(.hero--image) .button--primary:hover,
	.cta__actions .button--primary:hover {
		background: var(--grandir-color-on-primary);
		border-color: var(--grandir-color-on-primary);
		color: var(--grandir-color-primary);
	}

	/* Outline buttons (the phone button) fill in solid. */
	.button:not(.button--primary):hover {
		background: var(--grandir-color-primary);
		border-color: var(--grandir-color-primary);
		color: var(--grandir-color-on-primary);
	}

	.hero--image .button:not(.button--primary):hover {
		background: var(--grandir-hero-btn-fill);
		border-color: var(--grandir-hero-btn-fill);
		color: var(--grandir-hero-btn-on-fill);
	}

	.hero:not(.hero--image) .button:not(.button--primary):hover,
	.cta__actions .button:not(.button--primary):hover {
		background: var(--grandir-color-on-primary);
		border-color: var(--grandir-color-on-primary);
		color: var(--grandir-color-primary);
	}

	/* Cards lift, the border turns the accent color, and the photo zooms. */
	.card:hover {
		border-color: var(--grandir-color-accent-ui);
		box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
		transform: translateY(-2px);
	}

	.card:hover .card__image img {
		transform: scale(1.04);
	}

	/* Text links turn the accent color. The nav has its own bar instead. */
	a:hover {
		color: var(--grandir-color-accent-text);
	}

	/* The dark header: the nav has its own bar, the call link its ring animation. */
	.site-header a:hover {
		color: inherit;
	}

	/* accent-text is only checked on light backgrounds. */
	.hero a:not(.button):hover,
	.cta a:not(.button):hover {
		color: inherit;
	}

	.site-footer a:hover {
		color: var(--grandir-color-accent-on-deep);
	}

	/* Footer social icons lift and turn the accent color. */
	.site-footer__social a:hover {
		color: var(--grandir-color-accent-on-deep);
		transform: translateY(-2px);
	}

	/* Arrow links nudge forward. */
	.card-grid-section__more a:hover::after {
		transform: translateX(3px);
	}

	/* The featured project photo zooms while its link is hovered. */
	.home-project__item:has(.home-project__link a:hover) .home-project__image img {
		transform: scale(1.03);
	}

	/* Form fields: the border darkens a little before focus takes over. */
	.lead-form div.wpforms-container-full .wpforms-form :is(input, select, textarea):hover:not(:focus) {
		border-color: var(--grandir-color-text-muted);
	}

	.faq__question:hover {
		color: var(--grandir-color-link);
	}
}

@media screen and (min-width: 60em) and (hover: hover) {

	.main-navigation .menu > .menu-item > a:hover::after {
		transform: scaleX(1);
	}

	/* Dropdown items: a brand tint, and the text slides in slightly. */
	.main-navigation .sub-menu a:hover {
		padding-inline-start: calc(1rem + 3px);
	}
}

@media (prefers-reduced-motion: no-preference) {

	.button,
	.lead-form div.wpforms-container-full .wpforms-form button[type="submit"] {
		transition:
			background-color var(--grandir-motion-fast) var(--grandir-ease),
			border-color var(--grandir-motion-fast) var(--grandir-ease),
			box-shadow var(--grandir-motion-fast) var(--grandir-ease),
			color var(--grandir-motion-fast) var(--grandir-ease),
			transform var(--grandir-motion-fast) var(--grandir-ease);
	}

	.card {
		transition:
			border-color var(--grandir-motion) var(--grandir-ease),
			box-shadow var(--grandir-motion) var(--grandir-ease),
			transform var(--grandir-motion) var(--grandir-ease);
	}

	.card__image img {
		transition: transform 400ms var(--grandir-ease);
	}

	a {
		transition: color var(--grandir-motion-fast) var(--grandir-ease);
	}

	.main-navigation .menu > .menu-item > a::after {
		transition: transform var(--grandir-motion) var(--grandir-ease);
	}

	.main-navigation .sub-menu a {
		transition:
			background-color var(--grandir-motion-fast) var(--grandir-ease),
			padding var(--grandir-motion-fast) var(--grandir-ease);
	}

	.faq__question {
		transition: color var(--grandir-motion-fast) var(--grandir-ease);
	}

	/* Turns in step with the answer's 300ms slide (js/faqs.js). */
	.faq__question::after {
		transition: transform 300ms var(--grandir-ease);
	}

	.card-grid-section__more a::after {
		transition: transform var(--grandir-motion-fast) var(--grandir-ease);
	}

	.home-project__image img {
		transition: transform 400ms var(--grandir-ease);
	}

	.site-footer__social a {
		transition:
			color var(--grandir-motion-fast) var(--grandir-ease),
			transform var(--grandir-motion-fast) var(--grandir-ease);
	}

	.lead-form div.wpforms-container-full .wpforms-form :is(input, select, textarea) {
		transition:
			border-color var(--grandir-motion-fast) var(--grandir-ease),
			box-shadow var(--grandir-motion-fast) var(--grandir-ease);
	}
}

@media (hover: hover) and (prefers-reduced-motion: no-preference) {

	.site-header__call:hover .icon-phone {
		animation: grandir-ring 500ms var(--grandir-ease);
	}
}
