/*
 * Chrome: containers, bands, buttons, cards, header, footer.
 *
 * The furniture every page uses, split out of base.css so that file stays
 * bare-element only. Depends on tokens.css.
 *
 * Section-specific rules do not belong here — they go in
 * assets/css/sections/<layout>.css and load only on pages using that layout.
 */

/* ============================================================= LAYOUT == */

.container {
	width: 100%;
	max-width: var(--sq-container);
	margin-inline: auto;
	padding-inline: var(--sq-gutter);
}

/* Body copy caps at the measure, not the container. */
.container--text {
	max-width: calc(var(--sq-measure) + (var(--sq-gutter) * 2));
}

.container--narrow {
	max-width: calc(var(--sq-container-narrow) + (var(--sq-gutter) * 2));
}

/*
 * Every section shares this padding — 40/44 on mobile, 72 on desktop. It used
 * to be repeated in all thirteen section stylesheets; it lives here now, and a
 * section only declares its own when it genuinely differs (hero, which runs
 * tighter under the sticky header).
 */
.section {
	padding-block: var(--sq-section-padding) var(--sq-section-padding-end);
	background-color: var(--sq-bg);
	color: var(--sq-fg);
}

/*
 * Bands. Paper and concrete alternate; the dark three are rationed — cool for
 * the objection block, ink for the footer, black for the closing CTA once per
 * page — and orange is the alternative closing CTA.
 *
 * Each band is declared once for two consumers. `.section--*` is what
 * sharpquery_section_atts() emits; `.sq-band-*` is what the chrome uses, since
 * the header, top bar and footer are not `.section` elements. Sharing the
 * declaration is what stops the two drifting.
 */
.section--paper,
.sq-band-paper {
	--sq-bg: var(--sq-color-paper);
}

.section--concrete,
.sq-band-concrete {
	--sq-bg: var(--sq-color-concrete);
}

.section--cool,
.sq-band-cool {
	--sq-bg: var(--sq-color-cool);
}

.section--ink,
.sq-band-ink {
	--sq-bg: var(--sq-color-ink);
}

.section--black,
.sq-band-black {
	--sq-bg: var(--sq-color-black);
}

/* The one band that is neither paper nor dark. Its roles flip to ink, not
 * paper — see .sq-on-orange in tokens.css for the contrast arithmetic. */
.section--orange,
.sq-band-orange {
	--sq-bg: var(--sq-color-orange);
}

/* The chrome paints itself from the role token, so a band choice is the only
 * thing that has to change. */
.sq-band-paper,
.sq-band-concrete,
.sq-band-cool,
.sq-band-ink,
.sq-band-black,
.sq-band-orange {
	background-color: var(--sq-bg);
	color: var(--sq-fg);
}

/* Per-section spacing overrides, set on the Section tab of every layout.
 *
 * Relative to the responsive padding rather than fixed pixels, so "tight"
 * stays proportionate between mobile and desktop.
 *
 * Doubled class deliberately: section stylesheets load after this file and
 * set their own padding-block at (0,1,0), so these need (0,2,0) to win.
 * Only the edge that was overridden is affected — the other keeps the
 * section's own value. */
.section.section--pt-none {
	padding-top: 0;
}

.section.section--pt-tight {
	padding-top: calc(var(--sq-section-padding) / 2);
}

.section.section--pt-loose {
	padding-top: calc(var(--sq-section-padding) * 1.5);
}

.section.section--pb-none {
	padding-bottom: 0;
}

.section.section--pb-tight {
	padding-bottom: calc(var(--sq-section-padding-end) / 2);
}

.section.section--pb-loose {
	padding-bottom: calc(var(--sq-section-padding-end) * 1.5);
}

/*
 * Per-section font family.
 *
 * Everything in the theme reads --sq-font-display or --sq-font-body, so
 * re-pointing those two properties on the section element changes its whole
 * typography — headings, copy, buttons, labels — without a single
 * per-section rule. Both are inherited from :root, so this is a swap, not a
 * cycle.
 */
.section--font-condensed {
	--sq-font-body: var(--sq-font-display);
}

.section--font-regular {
	--sq-font-display: var(--sq-font-body);
}

/* Two adjacent bands of the same tone would read as one; a rule separates
 * them, per "sections separated by rules, not by air alone". */
.section--paper + .section--paper,
.section--concrete + .section--concrete {
	border-top: var(--sq-border-width) solid var(--sq-border);
}

.section__header {
	margin-bottom: var(--sq-space-6);
}

.section__heading {
	max-width: 20ch;
}

.section__intro {
	margin-top: var(--sq-space-4);
	font-size: var(--sq-text-lead);
	line-height: var(--sq-leading-normal);
	max-width: var(--sq-measure-narrow);
}

.section__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sq-space-4);
	align-items: center;
	margin-top: var(--sq-space-6);
}

/*
 * Eyebrow. Responsive here rather than in each section — hero, cta and process
 * all used to repeat the same 13px/0.12em mobile and 14px/0.14em desktop pair.
 */
.eyebrow {
	margin-bottom: var(--sq-space-3);
	color: var(--sq-accent);
	font-size: var(--sq-text-label-sm);
	font-weight: var(--sq-weight-bold);
	letter-spacing: var(--sq-tracking-label-sm);
	line-height: var(--sq-leading-normal);
	text-transform: uppercase;
}

@media (min-width: 61.25em) {
	.eyebrow {
		font-size: var(--sq-text-label);
		letter-spacing: var(--sq-tracking-label);
	}
}

.lead {
	font-size: var(--sq-text-lead);
	line-height: var(--sq-leading-normal);
}

.small {
	font-size: var(--sq-text-small);
	color: var(--sq-fg-muted);
}

/* Wide content scrolls inside its own box; the page never scrolls sideways. */
.table-scroll {
	max-width: 100%;
	overflow-x: auto;
}


/* ============================================================ BUTTONS == */

.btn {
	display: inline-flex;
	gap: var(--sq-space-3);
	align-items: center;
	justify-content: center;
	min-height: var(--sq-control-height);
	padding-inline: var(--sq-control-padding-x);
	border: var(--sq-border-width) solid var(--sq-color-ink);
	border-radius: var(--sq-radius);
	font-family: var(--sq-font-body);
	font-size: 1.1875rem; /* 19 */
	font-weight: var(--sq-weight-bold);
	letter-spacing: 0.02em;
	line-height: 1;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	transition:
		transform var(--sq-duration) var(--sq-ease),
		box-shadow var(--sq-duration) var(--sq-ease),
		background-color var(--sq-duration) var(--sq-ease);
}

/* Hero and closing CTAs. */
.btn--lg {
	min-height: var(--sq-control-height-lg);
	font-size: var(--sq-text-lead);
}

.btn--primary {
	background-color: var(--sq-color-orange);
	color: var(--sq-color-paper);
	box-shadow: var(--sq-shadow);
}

.btn--primary:hover {
	background-color: var(--sq-color-orange-hover);
	color: var(--sq-color-paper);
	box-shadow: var(--sq-shadow-pressed);
	transform: translate(2px, 2px);
}

.btn--primary:active {
	box-shadow: none;
	transform: translate(4px, 4px);
}

.btn--secondary {
	background-color: var(--sq-color-paper);
	color: var(--sq-color-ink);
}

.btn--secondary:hover {
	background-color: var(--sq-color-concrete);
	color: var(--sq-color-ink);
}

.btn--dark {
	background-color: var(--sq-color-ink);
	color: var(--sq-color-paper);
}

.btn--dark:hover {
	border-color: var(--sq-color-blue);
	background-color: var(--sq-color-blue);
	color: var(--sq-color-paper);
}

/* On a dark band the outline button inverts. */
.sq-on-dark .btn--secondary {
	border-color: var(--sq-color-paper);
}

.sq-on-dark .btn--primary,
.sq-on-dark .btn--dark {
	border-color: var(--sq-color-paper);
	box-shadow: none;
}

/*
 * On the orange band the primary button inverts to ink — an orange fill on an
 * orange field is not a button. The shadow goes with it: 4px of ink under an
 * ink slab is invisible.
 *
 * Hover goes to paper rather than the usual darker orange, which would be the
 * one move that makes the button harder to see than at rest.
 */
.sq-on-orange .btn--primary {
	border-color: var(--sq-color-ink);
	background-color: var(--sq-color-ink);
	color: var(--sq-color-paper);
	box-shadow: none;
}

.sq-on-orange .btn--primary:hover {
	background-color: var(--sq-color-paper);
	color: var(--sq-color-ink);
	box-shadow: none;
	transform: none;
}

.sq-on-orange .btn--primary:active {
	transform: translate(2px, 2px);
}

/* The outline button needs an ink edge here, not the paper one dark bands use. */
.sq-on-orange .btn--secondary {
	border-color: var(--sq-color-ink);
}

/* Standalone text link. Still a 44px target. */
.btn--text {
	min-height: var(--sq-tap-target);
	padding-inline: 0;
	border: 0;
	border-radius: 0;
	background: none;
	box-shadow: none;
	color: var(--sq-link);
	font-size: 1.125rem; /* 18 */
	font-weight: var(--sq-weight-semibold);
	text-decoration: underline;
	text-underline-offset: 3px;
}

.btn--text:hover {
	transform: none;
	color: var(--sq-link-hover);
}

/* A primary button goes full width on mobile, capped so it never spans a
 * tablet edge to edge. */
@media (max-width: 29.99em) {
	.section__actions .btn--primary,
	.hero__actions .btn--primary {
		width: 100%;
		max-width: var(--sq-container-sticky);
		min-height: var(--sq-control-height-lg);
	}
}


/* ============================================================== CARDS == */

/*
 * The shared card grid, consumed by template-parts/partials/card-grid.php.
 * Lives here rather than in a section stylesheet because several sections use
 * it — related-pages, the archives, and the trade cards. `service_list` used
 * to and no longer does: its comp spans featured cells and ends every card in
 * a read-more, both of which this grid rules out. See
 * template-parts/partials/service-grid.php.
 *
 * Collapse is fixed: chosen columns at desktop, always 2 on tablet, 1 on
 * mobile. Four columns of contractor copy on a tablet is unreadable.
 */

.card-grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--sq-space-card-gap);
	margin: 0;
	padding: 0;
	list-style: none;
}

.card-grid__cell {
	display: flex;
	margin: 0; /* base.css spaces li + li; the grid gap owns it here */
}

@media (min-width: 30em) {
	.card-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (min-width: 61.25em) {
	.card-grid--2 {
		grid-template-columns: repeat(2, 1fr);
	}

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

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

/*
 * Equal heights: the cell stretches to the tallest row (grid default), the
 * card fills the cell, and the body takes the slack. A three-word description
 * and a four-line one produce the same card.
 */
.card {
	position: relative; /* anchor for the stretched link */
	display: flex;
	flex: 1;
    flex-direction: column;
	border: var(--sq-border-width) solid var(--sq-color-ink);
	border-radius: var(--sq-radius);
	background-color: var(--sq-color-paper);
	color: var(--sq-color-ink);
	transition:
		transform var(--sq-duration) var(--sq-ease),
		box-shadow var(--sq-duration) var(--sq-ease);
}

.card__body {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: var(--sq-space-3);
	align-items: flex-start;
	padding: var(--sq-space-card-padding);
}

.card__title {
	margin: 0;
}

.card__summary {
	margin: 0;
	/* Pushes nothing; the body's flex:1 already equalises. */
	max-width: none;
}

.card__meta {
	margin: 0;
}

/*
 * Icon slot.
 *
 * Reserved on every card in a grid where any card has an icon, so titles line
 * up across the row. Empty slots are aria-hidden in the markup.
 */
.card-grid--icons .card__icon {
	display: flex;
	align-items: center;
	min-height: 4rem;
	padding: var(--sq-space-card-padding) var(--sq-space-card-padding) 0;
}

.card__icon-image {
	width: auto;
	max-height: 3rem;
}

/*
 * Featured.
 *
 * Priority comes from the design system's raised treatment, not from spanning
 * columns — the cell keeps its size, so the grid stays aligned however many
 * cards are featured.
 */
.card--featured {
	box-shadow: var(--sq-shadow-raised);
}

.sq-on-dark .card--featured {
	box-shadow: none;
	border-color: var(--sq-accent);
}

/*
 * Whole-card link.
 *
 * A real anchor in the title, stretched over the card by this pseudo-element.
 * One tab stop, middle-clickable, copyable, and no click handler on a div.
 *
 * Cards without a link are visually identical at rest — there is no "Read
 * more" affordance to be conspicuously missing. The difference only appears
 * on hover and focus, which is a state rather than a permanent gap.
 */
.card__title a {
	color: inherit;
	text-decoration: none;
}

.card--linked .card__link::after {
	position: absolute;
	inset: 0;
	z-index: 1;
	content: '';
}

.card--linked:hover {
	transform: translate(-2px, -2px);
	box-shadow: var(--sq-shadow);
}

.card--featured.card--linked:hover {
	box-shadow: var(--sq-shadow-raised);
}

.card--linked:hover .card__title {
	color: var(--sq-color-blue);
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* Ring the whole card, not just the title text. */
.card--linked:has(.card__link:focus-visible) {
	outline: 3px solid var(--sq-color-blue);
	outline-offset: 2px;
}

.sq-on-dark .card--linked:has(.card__link:focus-visible) {
	outline-color: var(--sq-color-paper);
}

/* Text after the stretched link must stay selectable and clickable. */
.card__summary,
.card__meta {
	position: relative;
	z-index: 2;
}

/* Media cards (archive listings) keep their existing treatment. */
.card__media {
	display: block;
	border-bottom: var(--sq-border-width) solid var(--sq-color-ink);
}

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


/* ============================================================= HEADER == */

/*
 * TOP BAR
 *
 * Outside the header, so a sticky header sticks on its own and the bar scrolls
 * away. Keeping it on screen would cost the hero another 40px on a phone for a
 * line nobody re-reads.
 *
 * Paints from --sq-bg via its .sq-band-* class; nothing here names a colour.
 */
.site-topbar {
	border-bottom: var(--sq-border-width-hair) solid var(--sq-rule);
	font-size: var(--sq-text-small);
}

.site-topbar__inner {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sq-space-2) var(--sq-space-5);
	align-items: center;
	justify-content: center;
	padding-block: var(--sq-space-2);
}

.site-topbar__meta {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sq-space-2) var(--sq-space-5);
	align-items: center;
}

.site-topbar__text {
	margin: 0;
	max-width: none;
}

.site-topbar__link {
	min-height: var(--sq-tap-target);
	display: inline-flex;
	align-items: center;
	color: inherit;
	font-weight: var(--sq-weight-semibold);
}

@media (min-width: 48em) {
	.site-topbar__inner {
		justify-content: space-between;
	}
}


/* The band class supplies the background; the header only owns its edge. */
.site-header {
	position: relative;
	z-index: var(--sq-z-header);
	border-bottom: var(--sq-border-width) solid var(--sq-border);
}

.site-header--sticky {
	position: sticky;
	top: 0;
}

.site-header__inner {
	position: relative; /* anchor for the open mobile nav */
	display: flex;
	gap: var(--sq-space-4);
	align-items: center;
	min-height: var(--sq-header-height);
}

/*
 * Height steps, not a free pixel value. The Customizer offers three so a
 * header cannot be set shorter than the 44px tap-target floor its buttons
 * need, which a number field would happily allow.
 */
.site-header--space-tight .site-header__inner {
	min-height: 3.5rem; /* 56 */
}

.site-header--space-loose .site-header__inner {
	min-height: 5.5rem; /* 88 */
}

.site-header__logo,
.custom-logo {
	width: auto;
	max-height: 2.75rem;
}

.site-header__title {
	font-family: var(--sq-font-display);
	font-size: 1.625rem; /* 26 */
	font-weight: var(--sq-weight-bold);
	letter-spacing: 0.01em;
	text-decoration: none;
	text-transform: uppercase;
	color: var(--sq-color-ink);
}

.site-header__toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: var(--sq-tap-target);
	height: var(--sq-tap-target);
	min-height: 0;
	margin-left: auto;
	padding: 0;
	background: none;
}

.site-header__toggle-bar,
.site-header__toggle-bar::before,
.site-header__toggle-bar::after {
	display: block;
	width: 1.25rem;
	height: 2px;
	background-color: var(--sq-color-ink);
	content: '';
}

.site-header__toggle-bar::before {
	transform: translateY(-6px);
}

.site-header__toggle-bar::after {
	transform: translateY(4px);
}

/*
 * NAVIGATION
 *
 * Colours, spacing and the separator are read through custom properties with
 * the design-system value as the fallback, so an untouched site emits no extra
 * CSS at all and a customised one overrides exactly what it set. The values
 * come from inc/customizer.php.
 */

.site-nav {
	display: none;
}

.site-nav.is-open {
	position: absolute;
	inset-inline: 0;
	top: 100%;
	display: block;
	padding: var(--sq-gutter);
	border-bottom: var(--sq-border-width) solid var(--sq-border);
	background-color: var(--sq-bg);
}

.site-nav__list,
.site-nav .sub-menu {
	display: flex;
	flex-direction: column;
	gap: var(--sq-space-1);
	margin: 0;
	padding: 0;
	list-style: none;
}

.site-nav__list li {
	position: relative; /* anchor for the desktop dropdown */
	margin: 0;
}

.site-nav__list a {
	display: flex;
	align-items: center;
	min-height: var(--sq-tap-target);
	color: var(--sq-nav-color, var(--sq-fg));
	font-size: 1.0625rem; /* 17 */
	font-weight: var(--sq-weight-semibold);
	text-decoration: none;
}

.site-nav__list a:hover,
.site-nav__list a:focus-visible {
	color: var(--sq-nav-hover, var(--sq-color-blue));
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* The current page is marked, not just coloured — colour alone is not a state
 * an assistive technology can report. */
.site-nav__list .current-menu-item > a,
.site-nav__list .current_page_item > a {
	text-decoration: underline;
	text-underline-offset: 3px;
}

/*
 * Submenus on mobile: inline and always open, indented under their parent.
 * Nothing to tap to reveal them — the panel is already a deliberate action,
 * and a second layer of toggles inside it is one more thing to get wrong.
 */
.site-nav .sub-menu {
	padding-left: var(--sq-space-4);
	border-left: var(--sq-border-width-hair) solid var(--sq-rule);
}

.site-nav .sub-menu a {
	font-weight: var(--sq-weight-regular);
}

.site-header__actions {
	display: none;
}

/*
 * Header buttons.
 *
 * Both read their colours through custom properties over the .btn defaults, so
 * the Customizer can repaint them without a second button variant and an
 * untouched site keeps the design system exactly.
 */
.site-header__phone {
	min-height: var(--sq-control-height-nav);
	padding-inline: var(--sq-control-padding-x-sm);
	font-size: 1.0625rem; /* 17 */
	border-color: var(--sq-header-phone-bg, var(--sq-color-ink));
	background-color: var(--sq-header-phone-bg, var(--sq-color-ink));
	color: var(--sq-header-phone-fg, var(--sq-color-paper));
}

.site-header__phone:hover {
	border-color: var(--sq-header-phone-hover-bg, var(--sq-color-blue));
	background-color: var(--sq-header-phone-hover-bg, var(--sq-color-blue));
	color: var(--sq-header-phone-hover-fg, var(--sq-color-paper));
}

.site-header__actions .btn--primary {
	background-color: var(--sq-header-cta-bg, var(--sq-color-orange));
	color: var(--sq-header-cta-fg, var(--sq-color-paper));
}

.site-header__actions .btn--primary:hover {
	background-color: var(--sq-header-cta-hover-bg, var(--sq-color-orange-hover));
	color: var(--sq-header-cta-hover-fg, var(--sq-color-paper));
}

@media (min-width: 61.25em) {
	.site-header__toggle {
		display: none;
	}

	.site-nav {
		display: block;
		margin-left: auto;
	}

	.site-nav__list {
		flex-direction: row;
		align-items: center;
		gap: var(--sq-nav-gap, var(--sq-space-5));
	}

	/*
	 * THE DROPDOWN.
	 *
	 * Was missing entirely: wp_nav_menu runs at depth 2, so a submenu was
	 * being emitted and rendered in flow — the second-level items stacked
	 * under their parent and stretched the header. This is the fix.
	 *
	 * Revealed on :hover AND :focus-within, which is what makes it reachable
	 * by keyboard with no JavaScript. visibility rather than display so the
	 * transition has something to animate and so the items stay out of the tab
	 * order while hidden.
	 */
	.site-nav .sub-menu {
		position: absolute;
		top: 100%;
		left: 0;
		z-index: var(--sq-z-header);
		visibility: hidden;
		gap: 0;
		min-width: 14rem;
		padding: var(--sq-space-2);
		border: var(--sq-border-width) solid var(--sq-border);
		background-color: var(--sq-bg);
		opacity: 0;
		transition:
			opacity var(--sq-duration) var(--sq-ease),
			visibility var(--sq-duration) var(--sq-ease);
	}

	.site-nav__list > li:hover > .sub-menu,
	.site-nav__list > li:focus-within > .sub-menu {
		visibility: visible;
		opacity: 1;
	}

	/*
	 * A parent with children keeps a hit area between the label and the panel,
	 * so the pointer can travel down without the menu closing under it. The
	 * border sits on the list item, not the padding, so it cannot be clicked
	 * through to the page behind.
	 */
	.site-nav__list > li.menu-item-has-children > a {
		padding-right: var(--sq-space-4);
	}

	/* Drawn, not written into the markup. */
	.site-nav__list > li.menu-item-has-children > a::after {
		width: 0.4rem;
		height: 0.4rem;
		margin-left: var(--sq-space-2);
		border-right: 2px solid currentColor;
		border-bottom: 2px solid currentColor;
		transform: translateY(-2px) rotate(45deg);
		content: '';
	}

	.site-nav .sub-menu a {
		min-height: 2.5rem;
		padding-inline: var(--sq-space-3);
		white-space: nowrap;
	}

	/*
	 * Separators. Drawn on the item rather than written into the markup, and
	 * never on the last one. `none` is the default and costs nothing.
	 */
	.site-nav--sep-dot > .site-nav__list > li:not(:last-child)::after,
	.site-nav--sep-pipe > .site-nav__list > li:not(:last-child)::after {
		position: absolute;
		top: 50%;
		right: calc(var(--sq-nav-gap, var(--sq-space-5)) / -2);
		color: var(--sq-nav-color, var(--sq-fg));
		line-height: 1;
		transform: translate(50%, -50%);
		opacity: 0.5;
		content: '\00b7';
	}

	.site-nav--sep-pipe > .site-nav__list > li:not(:last-child)::after {
		content: '|';
	}

	.site-nav--sep-rule > .site-nav__list > li:not(:last-child) {
		padding-right: var(--sq-nav-gap, var(--sq-space-5));
		border-right: var(--sq-border-width-hair) solid var(--sq-rule);
	}

	.site-header__actions {
		display: flex;
		gap: var(--sq-space-3);
		align-items: center;
	}
}

.skip-link {
	position: absolute;
	top: 0;
	left: var(--sq-gutter);
	z-index: var(--sq-z-skip-link);
	padding: var(--sq-space-3) var(--sq-space-5);
	border: var(--sq-border-width) solid var(--sq-color-ink);
	background-color: var(--sq-color-paper);
	color: var(--sq-color-ink);
	text-decoration: none;
}


/* ============================================================= FOOTER ==
 *
 * Design: _design/SharpQuery Footer.dc.html, both artboards.
 *
 * Three stacked bands — masthead, columns, legal strip. Background and text
 * colour come from the band class the Customizer picks, so nothing below names
 * a colour that only works on ink; the role tokens do that work.
 *
 * Lives in chrome.css because the footer renders on every page.
 */

.site-footer__inner {
	display: flex;
	flex-direction: column;
	gap: 1.625rem; /* 26 */
	padding-block: 2.25rem 1.75rem; /* 36 28 */
}

.site-footer--space-tight .site-footer__inner {
	padding-block: 1.5rem 1.25rem;
}

.site-footer--space-loose .site-footer__inner {
	padding-block: 3.5rem 2.5rem;
}


/* ---------------------------------------------------------- MASTHEAD -- */

.site-footer__masthead {
	display: flex;
	flex-direction: column;
	gap: 0.875rem; /* 14 */
}

.site-footer__identity {
	display: flex;
	flex-direction: column;
	gap: 0.875rem;
}

.site-footer__brand-link {
	display: flex;
	gap: 0.625rem;
	align-items: center;
	color: inherit;
	text-decoration: none;
}

/*
 * The lettermark. A filled square rather than an outline so it reads as a mark
 * and not as another button in a footer that already has one.
 */
.site-footer__mark {
	display: flex;
	flex: 0 0 auto;
	align-items: center;
	justify-content: center;
	width: 2.375rem; /* 38 */
	height: 2.375rem;
	background-color: var(--sq-fg);
	color: var(--sq-bg);
	font-family: var(--sq-font-display);
	font-size: 1.375rem; /* 22 */
	font-weight: var(--sq-weight-bold);
	line-height: 1;
}

.site-footer__logo {
	width: auto;
	max-height: 2.375rem;
}

.site-footer__name {
	font-family: var(--sq-font-display);
	font-size: 1.625rem; /* 26 */
	font-weight: var(--sq-weight-bold);
	line-height: 1;
	text-transform: uppercase;
}

.site-footer__blurb {
	margin: 0;
	max-width: 35rem; /* 560 */
	color: var(--sq-fg-muted);
	line-height: var(--sq-leading-normal);
}

/*
 * Click-to-call. Full width on mobile, shrink-wrapped beside the blurb at
 * desktop. An outline rather than a fill: the closing CTA above it owns the
 * one filled button on the page.
 */
.site-footer__call {
	display: flex;
	gap: 0.625rem;
	align-items: center;
	justify-content: center;
	min-height: 3.375rem; /* 54 */
	padding-inline: 1.375rem;
	border: var(--sq-border-width) solid var(--sq-border);
	color: inherit;
	font-size: 1.1875rem; /* 19 */
	font-weight: var(--sq-weight-bold);
	text-decoration: none;
	transition:
		background-color var(--sq-duration) var(--sq-ease),
		color var(--sq-duration) var(--sq-ease);
}

.site-footer__call:hover {
	background-color: var(--sq-fg);
	color: var(--sq-bg);
}

.site-footer__call-icon {
	font-size: 1.375rem;
	line-height: 1;
}


/* ----------------------------------------------------------- COLUMNS -- */

/*
 * Mobile: each column is its own block under a rule. The rule is what keeps
 * four stacked lists from reading as one very long list.
 */
.site-footer__columns {
	display: grid;
	grid-template-columns: 1fr;
	gap: 1.375rem;
}

.site-footer__column {
	display: flex;
	flex-direction: column;
	gap: var(--sq-space-3);
	padding-top: 1.375rem;
	border-top: var(--sq-border-width) solid var(--sq-rule);
}

.site-footer__heading {
	margin: 0;
	color: var(--sq-accent);
	font-family: var(--sq-font-body);
	font-size: var(--sq-text-label-sm);
	font-weight: var(--sq-weight-bold);
	letter-spacing: var(--sq-tracking-label);
	line-height: 1.2;
	text-transform: uppercase;
}


/* -------------------------------------------------- FOOTER LINK LISTS --
 *
 * Three renderers, one appearance: footer-links.php (services), the trade-list
 * `links` variant (industries) and wp_nav_menu (company). They differ only in
 * the rule behind them — see the note in footer-links.php — so the styling is
 * shared here and the columns look identical.
 *
 * Two-up on mobile, because sixteen full-width trades is a ribbon of sixteen
 * taps. Each link holds a 44px row whatever the density.
 */

.footer-links,
.trade-links {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 2px var(--sq-space-4);
	margin: 0;
	padding: 0;
	list-style: none;
}

.footer-links__item,
.trade-links__item,
.site-footer__list li {
	margin: 0;
}

/*
 * wp_nav_menu emits its own markup, so the menu column is matched on the
 * descendant anchor rather than on a BEM class it will never carry.
 */
.footer-links__link,
.trade-links__link,
.trade-links__text,
.site-footer__list a {
	display: inline-flex;
	align-items: center;
	min-height: var(--sq-tap-target);
	padding-block: var(--sq-space-1);
	color: var(--sq-link);
	font-size: var(--sq-text-small);
	line-height: 1.25;
	text-decoration: none;
}

.footer-links__link:hover,
.trade-links__link:hover,
.site-footer__list a:hover {
	color: var(--sq-link-hover);
	text-decoration: underline;
	text-underline-offset: 3px;
}


/* ----------------------------------------------------------- CONTACT -- */

.site-footer__contact {
	display: flex;
	flex-direction: column;
	gap: var(--sq-space-2);
	color: var(--sq-fg-muted);
	font-size: var(--sq-text-small);
	line-height: 1.45;
}

.site-footer__contact-line,
.site-footer__contact-pair {
	margin: 0;
	max-width: none;
}

.site-footer__contact-pair {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sq-space-2);
	/* align-items: center; */
}

/*
 * Email and phone each on their own row with an icon. Stacked rather than
 * inline: the comp's "[email] · [phone]" pair fits placeholder text, but a
 * real address and a real number on one line wrap mid-value in a 1.2fr column,
 * and a phone number broken across two lines is unreadable and untappable.
 */
.site-footer__contact-pair {
	display: flex;
	flex-direction: column;
	gap: 0;
}

.site-footer__contact-pair a {
	display: inline-flex;
	gap: var(--sq-space-2);
	align-items: center;
	min-height: var(--sq-tap-target);
	color: var(--sq-link);
	font-weight: var(--sq-weight-semibold);
	overflow-wrap: anywhere; /* a long address wraps rather than widening the column */
}

.site-footer__contact-icon {
	flex: 0 0 auto;
	width: 1.125rem; /* 18 */
	height: 1.125rem;
	color: var(--sq-accent);
}

/*
 * Social tiles. The comp draws a #4A4A47 edge, which is 2.09:1 on ink and
 * under the 3:1 floor WCAG 1.4.11 sets for a control whose boundary is the
 * only thing identifying it. --sq-fg-muted is 7.18:1 there and still reads as
 * secondary.
 */
.site-footer__column--contact .social-links {
	margin-top: var(--sq-space-2);
	gap: var(--sq-space-2);
}

.site-footer__column--contact .social-links__link {
	width: 3rem; /* 48 */
	height: 3rem;
	border: var(--sq-border-width) solid var(--sq-fg-muted);
	transition:
		background-color var(--sq-duration) var(--sq-ease),
		border-color var(--sq-duration) var(--sq-ease),
		color var(--sq-duration) var(--sq-ease);
}

.site-footer__column--contact .social-links__link:hover {
	border-color: var(--sq-fg);
	background-color: var(--sq-fg);
	color: var(--sq-bg);
}


/* ------------------------------------------------------- LEGAL STRIP -- */

.site-footer__legal {
	border-top: var(--sq-border-width) solid var(--sq-rule);
}

.site-footer__legal .container {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sq-space-3) var(--sq-space-5);
	justify-content: space-between;
	padding-block: 1.125rem;
	color: var(--sq-fg-muted);
	font-size: var(--sq-text-small);
}

.site-footer__legal-list {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sq-space-5);
	margin: 0;
	padding: 0;
	list-style: none;
}

.site-footer__legal-list li {
	margin: 0;
}

.site-footer__legal a {
	display: inline-flex;
	align-items: center;
	min-height: var(--sq-tap-target);
	color: inherit;
	text-decoration: none;
}

.site-footer__legal a:hover {
	color: var(--sq-link-hover);
	text-decoration: underline;
}

.site-footer__copyright {
	margin: 0;
	max-width: none;
}


/* ----------------------------------------------------------- DESKTOP -- */

@media (min-width: 48em) {

	.site-footer__inner {
		gap: 2.25rem; /* 36 */
		padding-block: 3.5rem 2rem; /* 56 32 */
	}

	.site-footer--space-tight .site-footer__inner {
		padding-block: 2.25rem 1.5rem;
	}

	.site-footer--space-loose .site-footer__inner {
		padding-block: 5rem 3rem;
	}

	/* Masthead becomes one row, the rule under it closing the band. */
	.site-footer__masthead {
		flex-direction: row;
		flex-wrap: wrap;
		gap: var(--sq-space-5);
		align-items: flex-end;
		justify-content: space-between;
		padding-bottom: 1.75rem; /* 28 */
		border-bottom: var(--sq-border-width) solid var(--sq-rule);
	}

	.site-footer__identity {
		gap: var(--sq-space-3);
	}

	.site-footer__mark {
		width: 2.75rem; /* 44 */
		height: 2.75rem;
		font-size: 1.625rem;
	}

	.site-footer__logo {
		max-height: 2.75rem;
	}

	.site-footer__name {
		font-size: 1.875rem; /* 30 */
	}

	.site-footer__blurb {
		font-size: 1.1875rem; /* 19 */
	}

	.site-footer__call {
		justify-content: flex-start;
	}

	/*
	 * The comp's track sizes. Industries is the widest because it carries
	 * sixteen items in two sub-columns; Company is the narrowest because it is
	 * four short words.
	 *
	 * NAMED AREAS, not auto-placement. Every column is pinned to its own area,
	 * so hiding one leaves that area empty and nothing else moves. With
	 * auto-placement, switching off Company slid Contact left into its track
	 * and left the dead space at the right-hand edge instead — the column that
	 * was turned off is the one that should leave the gap.
	 */
	.site-footer__columns {
		grid-template-columns: 1fr 1.5fr 0.7fr 1.2fr;
		grid-template-areas: 'services industries menu contact';
		gap: 2.5rem; /* 40 */
	}

	.site-footer__column--services   { grid-area: services; }
	.site-footer__column--industries { grid-area: industries; }
	.site-footer__column--menu       { grid-area: menu; }
	.site-footer__column--contact    { grid-area: contact; }

	/* The rule was the mobile separator between stacked blocks. Side by side
	 * they need no divider, and four of them would read as a table. */
	.site-footer__column {
		gap: 0.875rem;
		padding-top: 0;
		border-top: 0;
	}

	.site-footer__heading {
		font-size: var(--sq-text-label);
	}

	/* One column each, except Industries — sixteen trades in a single column
	 * would set the footer twice the height of everything beside it. */
	.footer-links,
	.trade-links {
		grid-template-columns: 1fr;
		gap: 2px var(--sq-space-5);
	}

	.site-footer__column--industries .trade-links {
		grid-template-columns: 1fr 1fr;
	}

	.footer-links__link,
	.trade-links__link,
	.trade-links__text,
	.site-footer__list a {
		min-height: 2.125rem; /* 34 */
		font-size: 1.125rem; /* 18 */
	}

	.site-footer__contact {
		font-size: 1.125rem;
	}

	/*
	 * Visual order only — the two lists swap areas. The DOM order never
	 * changes, so a screen reader and a crawler always meet the columns in the
	 * same sequence. The track widths swap with them, so Industries keeps the
	 * wide track it needs for sixteen trades wherever it lands.
	 */
	.site-footer--order-industries-services .site-footer__columns {
		grid-template-columns: 1.5fr 1fr 0.7fr 1.2fr;
		grid-template-areas: 'industries services menu contact';
	}

	.site-footer__legal .container {
		padding-block: var(--sq-space-5);
	}
}

/* ======================================================= SOCIAL LINKS ==
 *
 * Deliberately its own block, OUTSIDE the footer section above. It lived
 * inside it once and a footer rewrite took the whole thing out with it, which
 * left the list as an unstyled <ul> — icons stacked down the column with their
 * borders collapsed to hairlines. It is used by the top bar as well as the
 * footer, so it was never footer-only to begin with.
 *
 * The icons inherit currentColor, so a band change repaints them with no
 * per-band rule. The link is a 44px box, not a 24px glyph — the icon is the
 * smallest thing anyone taps in the chrome and the tap target is the floor.
 */

.social-links {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sq-space-2);
	margin: 0;
	padding: 0;
	list-style: none;
}

.social-links__item {
	margin: 0;
}

.social-links--icons .social-links__link {
	display: inline-flex;
	flex: 0 0 auto;
	align-items: center;
	justify-content: center;
	width: var(--sq-tap-target);
	height: var(--sq-tap-target);
	color: inherit;
	text-decoration: none;
	transition: color var(--sq-duration) var(--sq-ease);
}

.social-links--icons .social-links__link:hover {
	color: var(--sq-link-hover);
}

.social-links__icon {
	flex: 0 0 auto;
	width: 1.375rem; /* 22 */
	height: 1.375rem;
}

.social-links--text {
	gap: var(--sq-space-2) var(--sq-space-5);
}

.social-links--text .social-links__link {
	display: inline-flex;
	align-items: center;
	min-height: var(--sq-tap-target);
	color: var(--sq-link);
	font-weight: var(--sq-weight-semibold);
}


/* ========================================================= TRADE LIST ==
 *
 * Shared by all three trade components — the pillar grid, the homepage block
 * and the footer column — via template-parts/partials/trade-list.php. It lives
 * in chrome.css rather than a section stylesheet because the footer renders on
 * every page, and a section stylesheet only loads for its own layout.
 *
 * The pending treatment is the visual half of the link rule: a trade whose
 * page is not written yet is dashed, muted and labelled, and carries no <a>
 * at all. Deliberately not reduced opacity — that reads as accidentally
 * disabled and drops the text under the contrast floor.
 */

/* ==================================================== NOT PUBLISHED YET ==
 *
 * A trade whose page is not written yet still belongs in the hub — it tells a
 * visitor the trade is covered. It must read as a roadmap entry, not as a
 * link that failed.
 *
 * Three things make it deliberate: a stated label, a visibly different but
 * still solid card, and a cursor that never suggests it is clickable.
 * Deliberately NOT reduced opacity — that reads as "disabled by accident" and
 * takes the text below the contrast floor.
 */

.card--pending {
	border-style: dashed;
	background-color: transparent;
}


.card--pending .card__title {
	color: var(--sq-fg-muted);
}


.card__badge {
	display: inline-flex;
	align-items: center;
	margin: 0;
	padding: 0.125rem var(--sq-space-2);
	border: var(--sq-border-width-hair) solid currentColor;
	color: var(--sq-fg-muted);
	font-size: var(--sq-text-label-sm);
	font-weight: var(--sq-weight-bold);
	letter-spacing: var(--sq-tracking-label-sm);
	line-height: 1.4;
	text-transform: uppercase;
}


/* The badge sits at the foot of the card so every card's title starts at the
 * same height whatever its state. */
.card--pending .card__badge {
	margin-top: auto;
}


/* Trade names are the scan target: set them larger than a generic card title
 * and keep every card the same height so the eye can run down a column. */
.card-grid--trades .card__title {
	font-size: var(--sq-text-h3);
}


/* ============================================== TRADE CARDS, AT REST ==
 *
 * The Local SEO comp draws each trade as a raised card with a blue underlined
 * name and an arrow, rather than as the fused tiles the Who We Help comp uses.
 * `trades_grid` picks between them per section; these rules are the card half
 * and they apply wherever trade cards render, the archive included, so the two
 * cannot drift.
 *
 * The shared card grid keeps linked and unlinked cards identical at rest, so
 * that no card can look conspicuously unfinished. That rule is about a
 * PERMANENT absence. Here the absence is temporary and already stated — a
 * pending trade is dashed and carries a "Coming soon" badge — so a resting
 * affordance on the live ones adds nothing that is not already said, and it is
 * what makes a published trade read as somewhere to go.
 */

.card-grid--trades .card--linked {
	box-shadow: 3px 3px 0 var(--sq-color-ink);
}

.card-grid--trades .card--linked:hover {
	border-color: var(--sq-color-orange);
	box-shadow: 3px 3px 0 var(--sq-color-orange);
	transform: translate(-1px, -1px);
}

.card-grid--trades .card__link {
	color: var(--sq-color-blue);
	text-decoration: underline;
	text-decoration-thickness: 2px;
	text-underline-offset: 3px;
}

/*
 * The arrow, drawn here rather than written into the markup — it is decoration,
 * and the trade name already names the destination. It cannot go on
 * .card__link::after: that pseudo-element is the stretched hit area for the
 * whole card.
 */
.card-grid--trades .card--linked .card__title::after {
	content: ' \2192';
	color: var(--sq-accent);
	text-decoration: none;
}


/* compact — homepage. Name only, so the card can be tight and the grid can
 * carry sixteen without becoming a page of its own. */
.card-grid--compact .card__body {
	gap: var(--sq-space-2);
	padding: var(--sq-space-4);
}


/*
 * links — footer.
 *
 * The layout of this list is in the FOOTER block above, shared with the
 * services and menu columns so the four footer columns are indistinguishable.
 * What stays here is the half that belongs to the *link rule* rather than to
 * the footer: how an unpublished trade looks. That is what must travel if this
 * list is ever rendered anywhere else.
 */

.trade-links__item {
	display: flex;
	gap: var(--sq-space-2);
	align-items: center;
	margin: 0;
}


.trade-links__item--pending .trade-links__text {
	display: flex;
	align-items: center;
	min-height: var(--sq-tap-target);
	color: var(--sq-fg-muted);
	/* No pointer, no underline: nothing here suggests a link. */
	cursor: default;
}


.trade-links__badge {
	padding: 0.0625rem 0.375rem;
	border: var(--sq-border-width-hair) solid currentColor;
	color: var(--sq-fg-muted);
	font-size: var(--sq-text-micro);
	font-weight: var(--sq-weight-bold);
	letter-spacing: var(--sq-tracking-label-sm);
	text-transform: uppercase;
}

@media (min-width: 30em) {
	/* Three up on tablet rather than two: the cards hold one word. */
	.card-grid--compact {
		grid-template-columns: repeat(3, 1fr);
	}}

@media (min-width: 61.25em) {
	/* compact carries more per row than the chosen column count, because the
	 * cards hold a single word. */
	.card-grid--compact {
		grid-template-columns: repeat(4, 1fr);
	}}

/* ====================================================== RELATED PAGES ==
 *
 * Quiet by design: this is wayfinding at the end of a page, not a feature.
 * Lives in chrome.css because the component is callable from a template
 * (single-trade, single-service) as well as from its section layout, and a
 * section stylesheet would only load for the latter.
 */

.related-pages {
	display: flex;
	flex-direction: column;
	gap: var(--sq-space-5);
}

.related-pages__heading {
	margin: 0;
	font-size: var(--sq-text-h2);
	line-height: 0.98;
}

.related-pages__group {
	display: flex;
	flex-direction: column;
	gap: var(--sq-space-4);
}

.related-pages__label {
	margin: 0;
	font-size: var(--sq-text-label);
	font-weight: var(--sq-weight-bold);
	letter-spacing: var(--sq-tracking-label);
	text-transform: uppercase;
	color: var(--sq-fg-muted);
}

/* Related cards sit lower in the hierarchy than the page's own content. */
.card-grid--related .card__title {
	font-size: var(--sq-text-h3);
}

/* ========================================================= BREADCRUMBS ==
 *
 * Quiet: this is orientation, not navigation people came for. Small, muted,
 * and it never wraps into a second line of visual weight.
 */

.breadcrumbs {
	padding-block: var(--sq-space-3);
	border-bottom: var(--sq-border-width-hair) solid var(--sq-rule);
	background-color: var(--sq-color-paper);
}

.breadcrumbs__list {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sq-space-2);
	align-items: baseline;
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: var(--sq-text-small);
}

.breadcrumbs__item {
	display: flex;
	gap: var(--sq-space-2);
	align-items: baseline;
	margin: 0;
}

/* Separator is drawn, so it is never read out as content. */
.breadcrumbs__item:not(:first-child)::before {
	color: var(--sq-fg-muted);
	content: '/';
}

.breadcrumbs__link {
	color: var(--sq-link);
	text-decoration: none;
}

.breadcrumbs__link:hover {
	color: var(--sq-link-hover);
	text-decoration: underline;
	text-underline-offset: 3px;
}

.breadcrumbs__current {
	color: var(--sq-fg-muted);
}
