/* ==========================================================================
   TechTeam — theme styles
   Design tokens live in theme.json. This file carries the things tokens
   cannot express: composite components, state, texture and motion.
   ========================================================================== */

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

:root {
	--tt-ring: 0 0 0 3px rgba(36, 99, 235, .35);
	--tt-ring-dark: 0 0 0 3px rgba(255, 140, 0, .55);
	--tt-hairline: rgba(15, 23, 41, .10);
	--tt-hairline-dark: rgba(255, 255, 255, .12);
	--tt-ease: cubic-bezier(.22, .61, .36, 1);
	--tt-header-h: 122px;
	scroll-behavior: smooth;
}

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

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
	overflow-x: clip;
}

/* The clip has to be on the root as well. The scrollport belongs to <html>,
   so a child that overhangs the right edge escapes a clip set only on <body>
   and produces a horizontal scrollbar. The panels that reveal by sliding in
   from the right sit outside the viewport until their animation fires, which
   is exactly that case, and it showed up as 6px of sideways scroll on the
   contact page at phone width. */
html { overflow-x: clip; }

/* Scroll-margin so anchor jumps clear the sticky header. */
[id] { scroll-margin-top: calc(var(--tt-header-h) + 1.5rem); }

/* Readable measure for body copy inside prose contexts. */
.tt-prose > p,
.tt-prose > ul,
.tt-prose > ol {
	max-inline-size: var(--wp--custom--measure--prose);
	margin-inline: 0 auto;
}

/* --------------------------------------------------------------------------
   2. Focus and skip link — visible, never removed
   -------------------------------------------------------------------------- */

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

.has-ink-background-color :where(a, button, summary):focus-visible,
.tt-section--dark :where(a, button, summary):focus-visible,
.wp-block-cover :where(a, button, summary):focus-visible {
	outline-color: var(--wp--preset--color--brand);
}

.tt-skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 999;
	padding: .75rem 1.25rem;
	background: var(--wp--preset--color--ink);
	color: #fff;
	border-radius: 0 0 var(--wp--custom--radius--sm) 0;
	font-weight: 700;
	text-decoration: none;
}

.tt-skip-link:focus {
	left: 0;
}

/* --------------------------------------------------------------------------
   3. Typographic roles
   -------------------------------------------------------------------------- */

.is-style-tt-eyebrow {
	display: inline-flex;
	align-items: center;
	gap: .55rem;
	margin-bottom: .75rem !important;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--blue);
}

.tt-section--dark .is-style-tt-eyebrow,
.wp-block-cover .is-style-tt-eyebrow,
.has-ink-background-color .is-style-tt-eyebrow {
	color: var(--wp--preset--color--brand);
}

.is-style-tt-eyebrow::before {
	content: "";
	inline-size: 26px;
	block-size: 2px;
	background: currentColor;
	border-radius: 2px;
	flex: none;
}

.is-style-tt-lede {
	font-size: var(--wp--preset--font-size--large);
	line-height: 1.6;
	color: var(--wp--preset--color--slate);
	max-inline-size: 62ch;
	/* The constrained layout centres anything narrower than the content width.
	   A lede under a left-aligned headline must start at the same edge, so the
	   start margin is pinned and only the end margin absorbs the slack. */
	margin-inline: 0 auto;
}

.tt-section--dark .is-style-tt-lede,
.wp-block-cover .is-style-tt-lede {
	color: var(--wp--preset--color--slate-pale);
}

/* Highlighted word inside a heading. */
.tt-accent { color: var(--wp--preset--color--brand); }
.tt-accent-blue { color: var(--wp--preset--color--blue); }

/* Centre-aligned section intro. */
.tt-section-intro {
	max-width: 46rem;
	margin-inline: auto;
	text-align: center;
}

.tt-section-intro .is-style-tt-eyebrow { justify-content: center; }
.tt-section-intro .is-style-tt-lede { margin-inline: auto; }

/* --------------------------------------------------------------------------
   4. Sections
   -------------------------------------------------------------------------- */

.tt-section {
	position: relative;
	padding-block: var(--wp--preset--spacing--60);
}

.tt-section--dark {
	background: var(--wp--preset--gradient--night);
	color: var(--wp--preset--color--slate-pale);
	isolation: isolate;
}

.tt-section--dark :is(h1, h2, h3, h4, h5) { color: #fff; }

/* Subtle engineered grid, drawn in CSS so there is no extra request. */
.tt-section--grid::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background-image:
		linear-gradient(rgba(255, 255, 255, .045) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255, 255, 255, .045) 1px, transparent 1px);
	background-size: 64px 64px;
	mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 30%, transparent 78%);
	pointer-events: none;
}

/* Soft coloured light sources behind dark sections. */
.tt-section--glow::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background:
		radial-gradient(38rem 26rem at 12% 8%, rgba(36, 99, 235, .28), transparent 65%),
		radial-gradient(30rem 22rem at 88% 82%, rgba(255, 140, 0, .18), transparent 65%);
	pointer-events: none;
}

.tt-section--mist { background: var(--wp--preset--color--mist); }

/* Hairline divider between stacked light sections. */
.tt-section--ruled { border-top: 1px solid var(--wp--preset--color--line); }

/* --------------------------------------------------------------------------
   5. Cards
   -------------------------------------------------------------------------- */

.is-style-tt-card,
.is-style-tt-card-dark,
.is-style-tt-panel,
.is-style-tt-glass {
	position: relative;
	border-radius: var(--wp--custom--radius--lg);
	padding: clamp(1.5rem, 3vw, 2rem);
	height: 100%;
	transition: transform var(--wp--custom--transition--base),
	            box-shadow var(--wp--custom--transition--base),
	            border-color var(--wp--custom--transition--base);
}

.is-style-tt-card {
	background: #fff;
	border: 1px solid var(--wp--preset--color--line);
	box-shadow: var(--wp--preset--shadow--soft);
}

.is-style-tt-card-dark,
.is-style-tt-glass {
	background: rgba(255, 255, 255, .04);
	border: 1px solid var(--tt-hairline-dark);
	color: var(--wp--preset--color--slate-pale);
}

.is-style-tt-glass {
	backdrop-filter: blur(14px);
	-webkit-backdrop-filter: blur(14px);
	background: rgba(15, 23, 41, .55);
}

.is-style-tt-panel {
	background: transparent;
	border: 1px solid var(--wp--preset--color--line);
}

/* Hover lift — pointer devices only, so a phone tap does not leave a stuck state. */
@media (hover: hover) and (pointer: fine) {
	.is-style-tt-card:hover {
		transform: translateY(-4px);
		box-shadow: var(--wp--preset--shadow--lift);
		border-color: rgba(36, 99, 235, .35);
	}

	.is-style-tt-card-dark:hover,
	.is-style-tt-glass:hover {
		transform: translateY(-4px);
		border-color: rgba(255, 140, 0, .45);
		background: rgba(255, 255, 255, .07);
	}
}

/* An orange rule that draws itself across the top of a card on hover. */
.is-style-tt-card::after,
.is-style-tt-card-dark::after {
	content: "";
	position: absolute;
	inset-inline: clamp(1.5rem, 3vw, 2rem);
	inset-block-start: 0;
	block-size: 3px;
	border-radius: 0 0 3px 3px;
	background: var(--wp--preset--gradient--ember);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform var(--wp--custom--transition--slow);
}

@media (hover: hover) and (pointer: fine) {
	.is-style-tt-card:hover::after,
	.is-style-tt-card-dark:hover::after { transform: scaleX(1); }
}

/* Card icon chip. */
.tt-icon {
	display: inline-grid;
	place-items: center;
	inline-size: 3rem;
	block-size: 3rem;
	margin-bottom: 1.15rem;
	border-radius: var(--wp--custom--radius--md);
	background: rgba(36, 99, 235, .10);
	color: var(--wp--preset--color--blue);
	line-height: 1;
	transition: transform var(--wp--custom--transition--base), background var(--wp--custom--transition--base);
}

.tt-icon__svg {
	inline-size: 1.5rem;
	block-size: 1.5rem;
	display: block;
}

.tt-section--dark .tt-icon,
.is-style-tt-card-dark .tt-icon {
	background: rgba(255, 140, 0, .14);
	color: var(--wp--preset--color--brand);
}

@media (hover: hover) and (pointer: fine) {
	.is-style-tt-card:hover .tt-icon,
	.is-style-tt-card-dark:hover .tt-icon { transform: translateY(-2px) rotate(-4deg); }
}

/* Card grid — equal heights, no ragged bottoms. */
.is-style-tt-card-grid > .wp-block-column { display: flex; }
.is-style-tt-card-grid > .wp-block-column > * { flex: 1; }

/* --------------------------------------------------------------------------
   6. Buttons
   -------------------------------------------------------------------------- */

.wp-block-button__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: .55rem;
	min-block-size: 48px; /* comfortable touch target */
	transition: transform var(--wp--custom--transition--base),
	            box-shadow var(--wp--custom--transition--base),
	            background-color var(--wp--custom--transition--base),
	            color var(--wp--custom--transition--base),
	            border-color var(--wp--custom--transition--base);
}

/* The pointer pull (--tt-pull-*) and the hover lift (--tt-lift) have to share
   a single transform, or whichever rule wins simply erases the other. */
.wp-block-button__link {
	transform: translate3d(var(--tt-pull-x, 0px), calc(var(--tt-pull-y, 0px) + var(--tt-lift, 0px)), 0);
}

.wp-block-button:not(.is-style-tt-ghost) .wp-block-button__link:hover {
	--tt-lift: -2px;
	box-shadow: var(--wp--preset--shadow--glow);
}

.is-style-tt-ghost .wp-block-button__link {
	background: transparent;
	color: var(--wp--preset--color--ink);
	border: 1.5px solid rgba(15, 23, 41, .22);
	box-shadow: none;
	/* Pull the padding back by the border width so a ghost button sits at
	   exactly the same height as the solid one beside it. */
	padding-block: calc(.95rem - 1.5px);
	padding-inline: calc(1.75rem - 1.5px);
}

.is-style-tt-ghost .wp-block-button__link:hover {
	background: var(--wp--preset--color--ink);
	color: #fff;
	border-color: var(--wp--preset--color--ink);
	transform: translateY(-2px);
}

.tt-section--dark .is-style-tt-ghost .wp-block-button__link,
.wp-block-cover .is-style-tt-ghost .wp-block-button__link {
	color: #fff;
	border-color: rgba(255, 255, 255, .34);
}

.tt-section--dark .is-style-tt-ghost .wp-block-button__link:hover,
.wp-block-cover .is-style-tt-ghost .wp-block-button__link:hover {
	background: #fff;
	color: var(--wp--preset--color--ink);
	border-color: #fff;
}

.is-style-tt-solid-blue .wp-block-button__link {
	background: var(--wp--preset--color--blue);
	color: #fff;
}

.is-style-tt-solid-blue .wp-block-button__link:hover {
	background: var(--wp--preset--color--blue-deep);
	box-shadow: 0 18px 40px -18px rgba(36, 99, 235, .65);
}

/* --------------------------------------------------------------------------
   7. Lists — checklist and location pills
   -------------------------------------------------------------------------- */

.is-style-tt-check {
	list-style: none;
	padding-inline-start: 0;
}

.is-style-tt-check li {
	position: relative;
	padding-inline-start: 2rem;
	margin-block: .65rem;
}

.is-style-tt-check li::before {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	inset-block-start: .42em;
	inline-size: 1.15rem;
	block-size: 1.15rem;
	border-radius: 50%;
	background: rgba(15, 123, 79, .12);
	/* Tick drawn as a mask so it inherits colour and needs no image request. */
	box-shadow: inset 0 0 0 1.5px rgba(15, 123, 79, .35);
}

.is-style-tt-check li::after {
	content: "";
	position: absolute;
	inset-inline-start: .34rem;
	inset-block-start: .72em;
	inline-size: .42rem;
	block-size: .22rem;
	border-inline-start: 2px solid var(--wp--preset--color--green);
	border-block-end: 2px solid var(--wp--preset--color--green);
	transform: rotate(-45deg);
}

.tt-section--dark .is-style-tt-check li::before { box-shadow: inset 0 0 0 1.5px rgba(255, 140, 0, .45); background: rgba(255, 140, 0, .12); }
.tt-section--dark .is-style-tt-check li::after { border-color: var(--wp--preset--color--brand); }

.is-style-tt-pills {
	list-style: none;
	padding-inline-start: 0;
	display: flex;
	flex-wrap: wrap;
	gap: .6rem;
}

.is-style-tt-pills li {
	margin: 0;
	padding: .5rem 1.1rem;
	border-radius: var(--wp--custom--radius--pill);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	background: rgba(36, 99, 235, .08);
	color: var(--wp--preset--color--blue-deep);
	border: 1px solid rgba(36, 99, 235, .18);
	transition: transform var(--wp--custom--transition--base), background var(--wp--custom--transition--base);
}

.tt-section--dark .is-style-tt-pills li {
	background: rgba(255, 255, 255, .06);
	color: #fff;
	border-color: var(--tt-hairline-dark);
}

@media (hover: hover) and (pointer: fine) {
	.is-style-tt-pills li:hover { transform: translateY(-2px); background: rgba(255, 140, 0, .16); }
}

/* Arrow links — a short list of destinations inside a card. */

.is-style-tt-arrow {
	list-style: none;
	padding-inline-start: 0;
	margin-block: 1.25rem 0;
}

.is-style-tt-arrow li {
	margin-block: .4rem;
	padding-inline-start: 1.4rem;
	position: relative;
}

.is-style-tt-arrow li::before {
	content: "→";
	position: absolute;
	inset-inline-start: 0;
	color: var(--wp--preset--color--brand-text);
	font-weight: 700;
	transition: transform var(--wp--custom--transition--base);
}

.tt-section--dark .is-style-tt-arrow li::before { color: var(--wp--preset--color--brand); }

.is-style-tt-arrow a {
	text-decoration-color: rgba(36, 99, 235, .35);
	text-underline-offset: .2em;
}

@media (hover: hover) and (pointer: fine) {
	.is-style-tt-arrow li:hover::before { transform: translateX(3px); }
}

/* Price list — a service on the left, its figure on the right. */

.is-style-tt-price {
	list-style: none;
	padding-inline-start: 0;
	margin-block: 0;
	border-block-start: 1px solid var(--tt-hairline);
}

.is-style-tt-price li {
	margin: 0;
	padding-block: .95rem;
	border-block-end: 1px solid var(--tt-hairline);
	display: flex;
	flex-wrap: wrap;
	gap: .35rem 1.5rem;
	align-items: baseline;
	justify-content: space-between;
}

.is-style-tt-price li > strong {
	color: var(--wp--preset--color--brand-text);
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

.tt-section--dark .is-style-tt-price { border-block-start-color: var(--tt-hairline-dark); }
.tt-section--dark .is-style-tt-price li { border-block-end-color: var(--tt-hairline-dark); }
.tt-section--dark .is-style-tt-price li > strong { color: var(--wp--preset--color--brand); }

/* The two front doors on the home page. */

.tt-door__price {
	margin-block-start: 1.25rem;
	padding-block: .75rem;
	border-block: 1px solid var(--tt-hairline);
	color: var(--wp--preset--color--slate);
}

.tt-door__price strong { color: var(--wp--preset--color--brand-text); }

/* The three guarantees under the hero buttons sit in a row on wide screens. */

@media (min-width: 40em) {
	.tt-guarantees {
		display: flex;
		flex-wrap: wrap;
		gap: 0 2rem;
	}

	.tt-guarantees li { margin-block: 0; }
}

/* --------------------------------------------------------------------------
   8. Numbered process steps
   -------------------------------------------------------------------------- */

.is-style-tt-step {
	position: relative;
	padding: clamp(1.5rem, 3vw, 2rem);
	padding-block-start: 3.25rem;
	border-radius: var(--wp--custom--radius--lg);
	background: #fff;
	border: 1px solid var(--wp--preset--color--line);
	counter-increment: tt-step;
}

.tt-steps { counter-reset: tt-step; }

.is-style-tt-step::before {
	content: counter(tt-step, decimal-leading-zero);
	position: absolute;
	inset-block-start: 1.35rem;
	inset-inline-start: clamp(1.5rem, 3vw, 2rem);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 800;
	letter-spacing: -.03em;
	color: var(--wp--preset--color--brand-text);
}

.tt-section--dark .is-style-tt-step::before { color: var(--wp--preset--color--brand); }

.tt-section--dark .is-style-tt-step {
	background: rgba(255, 255, 255, .04);
	border-color: var(--tt-hairline-dark);
}

/* --------------------------------------------------------------------------
   9. FAQ (core/details)
   -------------------------------------------------------------------------- */

.is-style-tt-faq {
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--md);
	padding: 0;
	margin-block: .75rem;
	background: #fff;
	overflow: hidden;
	transition: border-color var(--wp--custom--transition--base), box-shadow var(--wp--custom--transition--base);
}

.is-style-tt-faq[open] {
	border-color: rgba(36, 99, 235, .35);
	box-shadow: var(--wp--preset--shadow--soft);
}

.is-style-tt-faq > summary {
	list-style: none;
	cursor: pointer;
	padding: 1.15rem 3.25rem 1.15rem 1.35rem;
	font-weight: 700;
	position: relative;
	min-block-size: 48px;
	display: flex;
	align-items: center;
}

.is-style-tt-faq > summary::-webkit-details-marker { display: none; }

.is-style-tt-faq > summary::after {
	content: "";
	position: absolute;
	inset-inline-end: 1.35rem;
	inline-size: .6rem;
	block-size: .6rem;
	border-inline-end: 2px solid var(--wp--preset--color--blue);
	border-block-end: 2px solid var(--wp--preset--color--blue);
	transform: rotate(45deg) translateY(-25%);
	transition: transform var(--wp--custom--transition--base);
}

.is-style-tt-faq[open] > summary::after { transform: rotate(225deg) translateY(-25%); }

.is-style-tt-faq > :not(summary) {
	padding-inline: 1.35rem;
	margin-block-end: 1.15rem;
	color: var(--wp--preset--color--slate);
}

/* --------------------------------------------------------------------------
   10. Safety notice — used on the device safety check page
   -------------------------------------------------------------------------- */

.is-style-tt-notice {
	border-inline-start: 4px solid var(--wp--preset--color--brand);
	background: rgba(255, 140, 0, .07);
	border-radius: var(--wp--custom--radius--md);
	padding: clamp(1.25rem, 3vw, 1.75rem);
}

.tt-section--dark .is-style-tt-notice {
	background: rgba(255, 140, 0, .10);
	border-inline-start-color: var(--wp--preset--color--brand);
}

.is-style-tt-notice strong { color: var(--wp--preset--color--ink); }
.tt-section--dark .is-style-tt-notice strong { color: #fff; }

/* --------------------------------------------------------------------------
   11. Images
   -------------------------------------------------------------------------- */

.is-style-tt-framed img {
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: var(--wp--preset--shadow--lift);
}

.is-style-tt-framed {
	position: relative;
}

/* A thin offset frame that reads as deliberate rather than decorative. */
.is-style-tt-framed::before {
	content: "";
	position: absolute;
	inset: 14px -14px -14px 14px;
	border: 1.5px solid rgba(255, 140, 0, .45);
	border-radius: var(--wp--custom--radius--lg);
	z-index: -1;
}

figure img { height: auto; }

/* Images inside cover blocks get a slow, restrained drift on hover. */
.tt-zoom img {
	transition: transform 900ms var(--tt-ease);
	will-change: transform;
}

@media (hover: hover) and (pointer: fine) {
	.tt-zoom:hover img { transform: scale(1.045); }
}

/* --------------------------------------------------------------------------
   12. Header
   -------------------------------------------------------------------------- */

.tt-header {
	position: sticky;
	top: 0;
	z-index: 100;
	background: rgba(11, 18, 33, .94);
	backdrop-filter: saturate(160%) blur(18px);
	-webkit-backdrop-filter: saturate(160%) blur(18px);
	border-block-end: 1px solid rgba(255, 255, 255, .10);
	box-shadow: 0 14px 34px -24px rgba(2, 6, 23, .95);
	transition: background var(--wp--custom--transition--base),
	            border-color var(--wp--custom--transition--base);
}

/* The main row carries the padding now, not the header, so the utility bar
   above it can sit flush against the top of the window. */
.tt-header__bar { padding-block: 1.15rem; transition: padding var(--wp--custom--transition--base); }

.tt-header.is-stuck {
	background: rgba(15, 23, 41, .97);
	border-block-end-color: var(--tt-hairline-dark);
	box-shadow: 0 10px 30px -18px rgba(2, 6, 23, .9);
}

.tt-header.is-stuck .tt-header__bar { padding-block: .6rem; }

/* --- the thin utility bar -------------------------------------------------
   It collapses to nothing on scroll rather than sliding away, so the sticky
   header gets shorter instead of the page appearing to jump. */

.tt-util {
	background: rgba(2, 6, 23, .55);
	border-block-end: 1px solid rgba(255, 255, 255, .07);
	font-size: .8rem;
	overflow: hidden;
	max-block-size: 3rem;
	transition: max-block-size var(--wp--custom--transition--base),
	            opacity var(--wp--custom--transition--base);
}

.tt-header.is-stuck .tt-util {
	max-block-size: 0;
	opacity: 0;
	border-block-end-color: transparent;
}

.tt-util__inner {
	max-inline-size: 1320px;
	margin-inline: auto;
	padding: .5rem var(--wp--custom--gutter, 1rem);
	display: flex;
	align-items: center;
	gap: 1.5rem;
}

.tt-util p { margin: 0; }

.tt-util__where,
.tt-util__hours {
	display: flex;
	align-items: center;
	gap: .45rem;
	color: var(--wp--preset--color--slate-pale);
	font-weight: 500;
	white-space: nowrap;
}

/* A map pin drawn in CSS: a circle with a rotated square under it. No icon
   font, no extra request. */
.tt-util__pin {
	inline-size: .55rem;
	block-size: .55rem;
	border: 2px solid var(--wp--preset--color--brand);
	border-radius: 50% 50% 50% 0;
	transform: rotate(-45deg);
	flex: none;
}

.tt-util__portal {
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	margin-inline-start: auto;
	padding: .3rem .85rem;
	border: 1px solid rgba(255, 255, 255, .22);
	border-radius: 999px;
	color: #fff !important;
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
	transition: border-color var(--wp--custom--transition--base),
	            background var(--wp--custom--transition--base);
}

.tt-util__portal:hover,
.tt-util__portal:focus-visible {
	border-color: var(--wp--preset--color--brand);
	background: rgba(255, 140, 0, .14);
	text-decoration: none;
}

/* A head-and-shoulders glyph, also drawn: circle for the head, a half-round
   block for the shoulders. */
.tt-util__avatar {
	position: relative;
	inline-size: .8rem;
	block-size: .8rem;
	flex: none;
}

.tt-util__avatar::before,
.tt-util__avatar::after {
	content: "";
	position: absolute;
	border: 1.5px solid currentColor;
}

.tt-util__avatar::before {
	inline-size: .38rem;
	block-size: .38rem;
	border-radius: 50%;
	inset-block-start: 0;
	inset-inline-start: .19rem;
}

.tt-util__avatar::after {
	inline-size: .72rem;
	block-size: .34rem;
	border-radius: .36rem .36rem 0 0;
	border-block-end: 0;
	inset-block-end: .04rem;
	inset-inline-start: .02rem;
}

@media (max-width: 60em) {
	/* Hours are the first thing to go: the phone number is in the row below
	   and answers the same question faster. */
	.tt-util__hours { display: none; }
}

@media (max-width: 34em) {
	.tt-util__where { display: none; }
	.tt-util__inner { justify-content: flex-end; }
}

.tt-header a,
.tt-header .wp-block-site-title a { color: #fff; }

.tt-header .wp-block-navigation .wp-block-navigation-item__content,
.tt-header .wp-block-navigation a.wp-block-navigation-item__content,
.tt-header .wp-block-navigation__submenu-icon + .wp-block-navigation-item__content,
.tt-header .wp-block-navigation-item > a:not(.wp-element-button) {
	position: relative;
	padding-block: .4rem;
	color: rgba(255, 255, 255, .88) !important;
	font-weight: 600;
	transition: color var(--wp--custom--transition--base);
}

.tt-header .wp-block-navigation .wp-block-navigation-item__content:hover,
.tt-header .wp-block-navigation-item > a:not(.wp-element-button):hover,
.tt-header .wp-block-navigation .current-menu-item > a { color: #fff !important; }

/* The submenu arrow inherits the same colour or it stays invisible. */
.tt-header .wp-block-navigation__submenu-icon { color: rgba(255, 255, 255, .7); }

/* Underline that grows from the centre. */
.tt-header .wp-block-navigation .wp-block-navigation-item__content::after,
.tt-header .wp-block-navigation-item > a:not(.wp-element-button)::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	inset-block-end: 0;
	block-size: 2px;
	background: var(--wp--preset--color--brand);
	border-radius: 2px;
	transform: scaleX(0);
	transition: transform var(--wp--custom--transition--base);
}

.tt-header .wp-block-navigation .wp-block-navigation-item__content:hover::after,
.tt-header .wp-block-navigation-item > a:not(.wp-element-button):hover::after,
.tt-header .wp-block-navigation .current-menu-item > a::after { transform: scaleX(1); }

.tt-header .wp-block-navigation__responsive-container.is-menu-open {
	background: var(--wp--preset--color--ink) !important;
	padding-top: 5rem;
}

.tt-header .wp-block-navigation__responsive-container.is-menu-open a { color: #fff; }

/* --- the logo lockup ---------------------------------------------------- */

.tt-logo { gap: .85rem !important; }

.tt-logo img {
	/* Was 40px, which left the mark looking like an afterthought next to the
	   wordmark. At 58 it reads as the identity it is. */
	max-block-size: 58px;
	inline-size: auto;
	transition: max-block-size var(--wp--custom--transition--base);
}

.tt-header.is-stuck .tt-logo img { max-block-size: 42px; }

.tt-logo__words { display: flex; flex-direction: column; gap: 0; }

.tt-logo .wp-block-site-title { margin: 0; line-height: 1.1; }

.tt-logo .wp-block-site-title a {
	font-size: 1.28rem;
	font-weight: 800;
	letter-spacing: -.02em;
	text-decoration: none;
}

.tt-logo__tag {
	margin: .1rem 0 0 !important;
	font-size: .7rem;
	font-weight: 600;
	letter-spacing: .13em;
	text-transform: uppercase;
	color: var(--wp--preset--color--brand);
	white-space: nowrap;
}

.tt-header.is-stuck .tt-logo .wp-block-site-title a { font-size: 1.1rem; }
.tt-header.is-stuck .tt-logo__tag { display: none; }

/* Under 40em the mark carries the brand on its own and the words would wrap. */
@media (max-width: 40em) {
	.tt-logo__words { display: none; }
	.tt-logo img { max-block-size: 44px; }
}

/* Give the menu room. The old 1.6rem gap plus a small logo was what made the
   items read as one crowded line. */
.tt-header__right { gap: 2rem !important; }

@media (max-width: 68em) {
	.tt-header__right { gap: 1rem !important; }
}

/* --------------------------------------------------------------------------
   13. Hero
   -------------------------------------------------------------------------- */

.tt-hero {
	position: relative;
	isolation: isolate;
	overflow: clip;
}

.tt-hero img.wp-block-cover__image-background {
	filter: contrast(1.08) brightness(1.12) saturate(1.05);
}

/* The photographs are busy server rooms now rather than a softly lit office,
   so the smaller hero text needs its own contrast at every width, not just on
   a phone. The headline is large enough to hold its own. */
.tt-hero :is(.is-style-tt-lede, .is-style-tt-check, .tt-badge, .tt-guarantees) {
	text-shadow: 0 1px 12px rgba(2, 6, 23, .85), 0 0 3px rgba(2, 6, 23, .6);
}

/* The scrim has two jobs that pull against each other: keep white text
   legible, and let the photograph be visible at all. It stays heavy where the
   words are and thins out where they are not. */
.tt-hero .wp-block-cover__background,
.tt-hero .wp-block-cover__gradient-background {
	background: linear-gradient(112deg, rgba(2, 6, 23, .90) 0%, rgba(15, 23, 41, .72) 38%, rgba(15, 23, 41, .28) 72%, rgba(15, 23, 41, .10) 100%) !important;
}

@media (max-width: 48em) {
	/* At phone width the text runs the full width, so the gradient has to run
	   down the page rather than across it. */
	.tt-hero .wp-block-cover__background,
	.tt-hero .wp-block-cover__gradient-background {
		background: linear-gradient(180deg, rgba(2, 6, 23, .88) 0%, rgba(15, 23, 41, .70) 45%, rgba(15, 23, 41, .34) 100%) !important;
	}

	/* Insurance for the small print low in the hero, where the scrim is
	   thinnest and the photograph underneath could be anything. */
	.tt-hero .is-style-tt-check,
	.tt-hero .is-style-tt-lede,
	.tt-hero h1 {
		text-shadow: 0 1px 14px rgba(2, 6, 23, .8);
	}
}

/* Slowly drifting light sources — the only ambient motion on the page. */
.tt-hero::before,
.tt-hero::after {
	content: "";
	position: absolute;
	z-index: 1;
	border-radius: 50%;
	filter: blur(70px);
	pointer-events: none;
}

.tt-hero::before {
	inline-size: 34rem;
	block-size: 34rem;
	inset-block-start: -12rem;
	inset-inline-start: -10rem;
	background: rgba(36, 99, 235, .34);
	animation: tt-drift-a 22s var(--tt-ease) infinite alternate;
}

.tt-hero::after {
	inline-size: 26rem;
	block-size: 26rem;
	inset-block-end: -10rem;
	inset-inline-end: -6rem;
	background: rgba(255, 140, 0, .22);
	animation: tt-drift-b 26s var(--tt-ease) infinite alternate;
}

@keyframes tt-drift-a {
	from { transform: translate3d(0, 0, 0) scale(1); }
	to   { transform: translate3d(5rem, 3rem, 0) scale(1.14); }
}

@keyframes tt-drift-b {
	from { transform: translate3d(0, 0, 0) scale(1.08); }
	to   { transform: translate3d(-4rem, -3rem, 0) scale(1); }
}

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

/* Trust badge above the hero headline. */
.tt-badge {
	display: inline-flex;
	align-items: center;
	gap: .6rem;
	padding: .5rem 1.1rem;
	border-radius: var(--wp--custom--radius--pill);
	background: rgba(36, 99, 235, .16);
	border: 1px solid rgba(255, 255, 255, .16);
	color: #fff;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	letter-spacing: .12em;
	text-transform: uppercase;
}

.tt-badge::before {
	content: "";
	inline-size: .5rem;
	block-size: .5rem;
	border-radius: 50%;
	background: var(--wp--preset--color--brand);
	box-shadow: 0 0 0 0 rgba(255, 140, 0, .7);
	animation: tt-pulse 2.6s ease-out infinite;
}

@keyframes tt-pulse {
	0%   { box-shadow: 0 0 0 0 rgba(255, 140, 0, .7); }
	70%  { box-shadow: 0 0 0 .7rem rgba(255, 140, 0, 0); }
	100% { box-shadow: 0 0 0 0 rgba(255, 140, 0, 0); }
}

/* --------------------------------------------------------------------------
   14. Stat row
   -------------------------------------------------------------------------- */

.tt-stat { text-align: center; }

.tt-stat__value {
	display: block;
	font-size: var(--wp--preset--font-size--xxx-large);
	font-weight: 800;
	letter-spacing: -.035em;
	line-height: 1;
	/* #FF8C00 on a light ground is only 2.2:1 — below even the large-text
	   threshold. The deeper orange keeps the brand read and clears AA. */
	color: var(--wp--preset--color--brand-text);
	font-variant-numeric: tabular-nums;
}

.tt-section--dark .tt-stat__value { color: var(--wp--preset--color--brand); }

/* A stat whose value is a word, not a figure — the same weight at full display
   size shouts over the numbers beside it. */
.tt-stat__value:not([data-tt-count]) {
	font-size: var(--wp--preset--font-size--xx-large);
	letter-spacing: -0.03em;
}

.tt-stat__label {
	display: block;
	margin-block-start: .5rem;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--slate-soft);
}

/* --------------------------------------------------------------------------
   15. Reviews
   -------------------------------------------------------------------------- */

.tt-section--dark .tt-stars { color: var(--wp--preset--color--brand); }

.tt-reviews__summary {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 1rem 1.5rem;
	margin-block-end: 2.5rem;
}

.tt-stars {
	display: inline-flex;
	gap: .15rem;
	color: var(--wp--preset--color--brand-text);
	font-size: 1.1rem;
	letter-spacing: .1em;
}

.tt-review {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	height: 100%;
}

.tt-review__body { flex: 1; }

.tt-review__meta {
	display: flex;
	align-items: center;
	gap: .75rem;
	font-size: var(--wp--preset--font-size--small);
}

.tt-review__avatar {
	inline-size: 2.5rem;
	block-size: 2.5rem;
	flex: none;
	display: grid;
	place-items: center;
	border-radius: 50%;
	background: rgba(36, 99, 235, .12);
	color: var(--wp--preset--color--blue);
	font-weight: 800;
}

.tt-reviews__empty {
	max-width: 46rem;
	margin-inline: auto;
	text-align: center;
	padding: clamp(2rem, 5vw, 3rem);
	border: 1.5px dashed var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--lg);
	color: var(--wp--preset--color--slate);
}

/* --------------------------------------------------------------------------
   16. Contact form (rendered by the techteam-core plugin)
   -------------------------------------------------------------------------- */

.tt-form { display: grid; gap: 1.1rem; }

.tt-form__row {
	display: grid;
	gap: 1.1rem;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
}

.tt-form__field { display: grid; gap: .45rem; }

.tt-form label {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--ink);
}

.tt-form :is(input, select, textarea) {
	inline-size: 100%;
	min-block-size: 48px;
	padding: .8rem 1rem;
	font: inherit;
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--ink);
	background: #fff;
	border: 1.5px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--md);
	transition: border-color var(--wp--custom--transition--base), box-shadow var(--wp--custom--transition--base);
}

.tt-form textarea { min-block-size: 9rem; resize: vertical; }

.tt-form :is(input, select, textarea):focus {
	outline: none;
	border-color: var(--wp--preset--color--blue);
	box-shadow: var(--tt-ring);
}

.tt-form :is(input, select, textarea)[aria-invalid="true"] {
	border-color: #B42318;
	box-shadow: 0 0 0 3px rgba(180, 35, 24, .18);
}

.tt-form__error {
	font-size: var(--wp--preset--font-size--x-small);
	color: #B42318;
	min-block-size: 1rem;
}

/* Honeypot — kept out of view for sighted users and off the tab order. */
.tt-form__pot {
	position: absolute !important;
	inline-size: 1px;
	block-size: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.tt-form__submit {
	justify-self: start;
	min-block-size: 48px;
	padding: .95rem 2rem;
	font: inherit;
	font-weight: 700;
	color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--brand);
	border: none;
	border-radius: var(--wp--custom--radius--pill);
	cursor: pointer;
	transition: transform var(--wp--custom--transition--base), background var(--wp--custom--transition--base), box-shadow var(--wp--custom--transition--base);
}

.tt-form__submit:hover:not(:disabled) {
	background: var(--wp--preset--color--brand-deep);
	transform: translateY(-2px);
	box-shadow: var(--wp--preset--shadow--glow);
}

.tt-form__submit:disabled { opacity: .6; cursor: progress; transform: none; }

.tt-form__status {
	padding: .9rem 1.15rem;
	border-radius: var(--wp--custom--radius--md);
	font-size: var(--wp--preset--font-size--small);
}

.tt-form__status[data-state="success"] { background: rgba(15, 123, 79, .10); color: #0B5A3A; border: 1px solid rgba(15, 123, 79, .3); }
.tt-form__status[data-state="error"]   { background: rgba(180, 35, 24, .08); color: #8A1C13; border: 1px solid rgba(180, 35, 24, .28); }

.tt-form__consent {
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--slate);
}

/* --------------------------------------------------------------------------
   17. Footer
   -------------------------------------------------------------------------- */

.tt-footer {
	background: var(--wp--preset--color--ink-deep);
	color: var(--wp--preset--color--slate-soft);
	/* Was spacing--60 top. The footer is a footer, not a section: it had grown
	   nearly as tall as the content above it. */
	padding-block: 3.25rem 1.5rem;
}

.tt-footer :is(h2, h3, h4) { color: #fff; }

/* Brand block on the left, three link columns on the right. The brand column
   is wider because it carries the phone number and the blurb; the link columns
   only need enough room for their longest item. */
.tt-footer__grid {
	display: grid;
	grid-template-columns: minmax(20rem, 1.35fr) 2fr;
	gap: 2.5rem 4rem;
	align-items: start;
}

/* Smaller than the header mark on purpose: down here it is a sign-off, not
   the thing doing the work. */
.tt-footer__logo { display: inline-block; margin-block-end: 1.1rem; }

.tt-footer__logo img {
	block-size: 46px;
	inline-size: auto;
	display: block;
}

.tt-footer__blurb {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.6;
	max-inline-size: 34rem;
}

.tt-footer__contact { margin-block-start: 1.35rem; }

.tt-footer__phone {
	display: block;
	font-size: 1.45rem;
	font-weight: 800;
	letter-spacing: -.02em;
	color: #fff !important;
	text-decoration: none;
	line-height: 1.2;
}

.tt-footer__phone:hover { color: var(--wp--preset--color--brand) !important; text-decoration: none; }

.tt-footer__email {
	display: inline-block;
	margin-block-start: .3rem;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
}

.tt-footer__meta {
	margin: .55rem 0 0;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--slate);
}

/* --- social icons ------------------------------------------------------- */

.tt-social {
	display: flex;
	gap: .6rem;
	list-style: none;
	margin: 1.6rem 0 0;
	padding: 0;
}

.tt-social__link {
	position: relative;
	display: grid;
	place-items: center;
	inline-size: 2.5rem;
	block-size: 2.5rem;
	border: 1px solid rgba(255, 255, 255, .16);
	border-radius: 50%;
	color: var(--wp--preset--color--slate-pale) !important;
	transition: border-color var(--wp--custom--transition--base),
	            background var(--wp--custom--transition--base),
	            color var(--wp--custom--transition--base),
	            transform var(--wp--custom--transition--base);
}

.tt-social__link svg { inline-size: 1.15rem; block-size: 1.15rem; display: block; }

.tt-social__link:hover,
.tt-social__link:focus-visible {
	border-color: var(--wp--preset--color--brand);
	background: rgba(255, 140, 0, .15);
	color: #fff !important;
	transform: translateY(-2px);
	text-decoration: none;
}

/* The label the icon replaced, kept for anyone who hovers. The accessible name
   is on the link itself, so this is decoration and stays hidden from readers. */
.tt-social__tip {
	position: absolute;
	inset-block-end: calc(100% + .5rem);
	inset-inline-start: 50%;
	transform: translateX(-50%);
	padding: .3rem .6rem;
	border-radius: 6px;
	background: var(--wp--preset--color--ink);
	border: 1px solid var(--tt-hairline-dark);
	font-size: .7rem;
	font-weight: 600;
	white-space: nowrap;
	color: #fff;
	opacity: 0;
	pointer-events: none;
	transition: opacity var(--wp--custom--transition--base);
}

.tt-social__link:hover .tt-social__tip,
.tt-social__link:focus-visible .tt-social__tip { opacity: 1; }

/* --- link columns ------------------------------------------------------- */

.tt-footer__nav {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 2rem;
}

.tt-footer__col h3 {
	margin: 0 0 .9rem;
	font-size: .75rem;
	font-weight: 700;
	letter-spacing: .13em;
	text-transform: uppercase;
	color: var(--wp--preset--color--brand) !important;
}

.tt-footer__col ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: .5rem;
}

.tt-footer__col a { font-size: var(--wp--preset--font-size--small); }

@media (max-width: 62em) {
	.tt-footer__grid { grid-template-columns: 1fr; gap: 2.25rem; }
}

@media (max-width: 40em) {
	/* Three columns of links at phone width become three single-item-wide
	   slivers, so they stack into two. */
	.tt-footer__nav { grid-template-columns: repeat(2, 1fr); gap: 1.75rem; }
	.tt-footer__phone { font-size: 1.3rem; }
	.tt-footer { padding-block: 2.5rem 1.25rem; }
}

.tt-footer a {
	color: var(--wp--preset--color--slate-pale);
	text-decoration: none;
	transition: color var(--wp--custom--transition--base);
}

.tt-footer a:hover { color: var(--wp--preset--color--brand); text-decoration: underline; }

.tt-footer__legal {
	margin-block-start: var(--wp--preset--spacing--40);
	padding-block-start: var(--wp--preset--spacing--30);
	border-block-start: 1px solid var(--tt-hairline-dark);
	font-size: var(--wp--preset--font-size--x-small);
}

/* --------------------------------------------------------------------------
   18. Floating call button (mobile)
   -------------------------------------------------------------------------- */

.tt-call-fab {
	position: fixed;
	inset-block-end: max(1rem, env(safe-area-inset-bottom));
	inset-inline-end: 1rem;
	z-index: 90;
	display: inline-flex;
	align-items: center;
	gap: .55rem;
	padding: .9rem 1.35rem;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--brand);
	color: var(--wp--preset--color--ink);
	font-weight: 700;
	text-decoration: none;
	box-shadow: 0 14px 34px -14px rgba(2, 6, 23, .8);
	transform: translateY(150%);
	transition: transform 320ms var(--tt-ease);
}

.tt-call-fab.is-visible { transform: translateY(0); }

@media (min-width: 900px) { .tt-call-fab { display: none; } }

/* --------------------------------------------------------------------------
   19. Motion layer
   -------------------------------------------------------------------------- */

/* Elements start hidden only when JS is available to reveal them, so a
   JS failure never leaves the page blank. */
.js .tt-reveal {
	opacity: 0;
	transform: translateY(22px);
	transition: opacity 620ms var(--tt-ease), transform 620ms var(--tt-ease);
	transition-delay: var(--tt-delay, 0ms);
	will-change: opacity, transform;
}

.js .tt-reveal.is-in {
	opacity: 1;
	transform: none;
}

.js .tt-reveal--left  { transform: translateX(-26px); }
.js .tt-reveal--right { transform: translateX(26px); }
.js .tt-reveal--scale { transform: scale(.96); }

.js .tt-reveal--left.is-in,
.js .tt-reveal--right.is-in,
.js .tt-reveal--scale.is-in { transform: none; }

/* Hero parallax, driven by a CSS variable the script writes. */
.js .tt-parallax { transform: translate3d(0, calc(var(--tt-scroll, 0) * 1px), 0); }

/* Marquee for the service-area strip. */
.tt-marquee {
	overflow: hidden;
	mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
	padding-block: .5rem;
}

.tt-marquee__track {
	display: flex;
	gap: 1rem;
	inline-size: max-content;
	animation: tt-marquee 38s linear infinite;
}

.tt-marquee:hover .tt-marquee__track { animation-play-state: paused; }

@keyframes tt-marquee {
	from { transform: translateX(0); }
	to   { transform: translateX(-50%); }
}

/* Scroll progress bar under the header. */
.tt-progress {
	position: fixed;
	inset-block-start: 0;
	inset-inline-start: 0;
	z-index: 101;
	block-size: 3px;
	inline-size: 100%;
	transform-origin: left;
	transform: scaleX(var(--tt-progress, 0));
	background: var(--wp--preset--gradient--ember);
	pointer-events: none;
}

/* --------------------------------------------------------------------------
   20. Reduced motion — everything above degrades to a static page
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: .001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .001ms !important;
		scroll-behavior: auto !important;
	}

	.js .tt-reveal { opacity: 1 !important; transform: none !important; }
	.js .tt-parallax { transform: none !important; }
	.tt-marquee__track { animation: none; transform: none; }
	.tt-hero::before,
	.tt-hero::after { animation: none; }
	.tt-progress { display: none; }
}

/* --------------------------------------------------------------------------
   21. Print
   -------------------------------------------------------------------------- */

@media print {
	.tt-header, .tt-footer, .tt-call-fab, .tt-progress, .wp-block-button { display: none !important; }
	.tt-section--dark { background: #fff !important; color: #000 !important; }
	.tt-section--dark :is(h1,h2,h3,h4,p,li) { color: #000 !important; }
	a[href^="http"]::after { content: " (" attr(href) ")"; font-size: .8em; }
}

/* --------------------------------------------------------------------------
   16. Quick exit — device safety page only
   -------------------------------------------------------------------------- */

.tt-quick-exit-bar {
	position: sticky;
	inset-block-start: 0;
	z-index: 60;
	display: flex;
	flex-wrap: wrap;
	gap: .5rem 1.5rem;
	align-items: center;
	justify-content: space-between;
	padding: .75rem clamp(1rem, 4vw, 2.5rem);
	background: var(--wp--preset--color--ink-deep);
	color: #fff;
}

.tt-quick-exit__note {
	margin: 0;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--slate-pale);
	max-inline-size: 60ch;
}

.tt-quick-exit {
	flex: none;
	padding: .55rem 1.2rem;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--brand);
	color: var(--wp--preset--color--ink);
	font-weight: 700;
	font-size: var(--wp--preset--font-size--small);
	text-decoration: none;
	/* 44px minimum target, the same rule as every other control here. */
	min-block-size: 44px;
	display: inline-flex;
	align-items: center;
}

.tt-quick-exit:hover,
.tt-quick-exit:focus-visible {
	background: var(--wp--preset--color--brand-deep);
	color: var(--wp--preset--color--ink);
}

/* The sticky header would otherwise sit under the exit bar. */
.tt-quick-exit-bar ~ .tt-header { inset-block-start: auto; }

/* --------------------------------------------------------------------------
   17. Booking
   -------------------------------------------------------------------------- */

.tt-booking iframe {
	display: block;
	inline-size: 100%;
}

.tt-booking__fallback {
	margin-block-start: 1rem;
	text-align: center;
	color: var(--wp--preset--color--slate);
}

.tt-booking__pending {
	max-inline-size: 60ch;
	margin-inline: auto;
	text-align: center;
}

.tt-booking__pending + form,
.tt-booking__pending ~ .tt-form {
	margin-block-start: 2rem;
}

/* The header carries a logo, five nav items and two buttons. That fits on a
   desktop and nowhere else, so things come out of it in order of how little
   they are missed: the phone button first (the floating call button and the
   footer both still carry the number), then the nav tightens up. */

.tt-header__actions { flex-wrap: nowrap; }

.tt-header__actions .wp-block-button__link { white-space: nowrap; }

@media (max-width: 68em) {
	/* Two classes, not one: the block layout styles that WordPress emits for
	   .wp-block-buttons children win against a single class selector. */
	.tt-header__actions .tt-header__call { display: none; }
}

@media (max-width: 40em) {
	/* The wordmark is already in the logo mark. The text beside it wraps to
	   three lines at phone width and takes the header with it. */
	.tt-header .wp-block-site-title { display: none; }
	.tt-header__actions .wp-block-button__link { padding-inline: 1.1rem; }
	.tt-header .wp-block-group { column-gap: .75rem; }
}

@media (max-width: 80em) {
	.tt-header .wp-block-navigation { --wp--style--block-gap: 1rem; gap: 1rem; }
	.tt-header .wp-block-navigation-item__content { font-size: .92rem; }
}

/* --------------------------------------------------------------------------
   18. First impression — signal field, headline reveal, pointer response

   The brief was "simple, tech, modern". The restraint is the point: one idea
   — a signal moving through a grid — expressed only in opacity and transform
   so it stays on the compositor and costs nothing measurable, and switched
   off completely under prefers-reduced-motion.

   The .tt-signal element is injected into every .tt-hero cover by the theme
   (see inc/hero-signal.php) rather than typed into each pattern, because the
   cover's own ::before and ::after are already spent on the drifting glows.
   -------------------------------------------------------------------------- */

.tt-signal {
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	overflow: hidden;
}

.tt-signal__grid,
.tt-signal__sweep {
	position: absolute;
	display: block;
}

.tt-signal__grid {
	inset: 0;
	background-image:
		linear-gradient(rgba(255, 255, 255, .055) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255, 255, 255, .055) 1px, transparent 1px);
	background-size: 72px 72px;
	mask-image: radial-gradient(ellipse 85% 70% at 18% 34%, #000 8%, transparent 70%);
	-webkit-mask-image: radial-gradient(ellipse 85% 70% at 18% 34%, #000 8%, transparent 70%);
}

.tt-signal__sweep {
	inset: -40% -30%;
	background: linear-gradient(
		104deg,
		transparent 44%,
		rgba(255, 140, 0, .09) 48%,
		rgba(36, 99, 235, .13) 52%,
		transparent 57%
	);
	animation: tt-sweep 12s var(--tt-ease) infinite;
}

@keyframes tt-sweep {
	0%   { transform: translate3d(-38%, 0, 0); }
	55%  { transform: translate3d(38%, 0, 0); }
	100% { transform: translate3d(-38%, 0, 0); }
}

/* A live indicator on the hero eyebrow — the smallest possible signal that
   there is a person at the other end of this. */

.tt-hero .tt-badge::before {
	content: "";
	inline-size: .5rem;
	block-size: .5rem;
	border-radius: 50%;
	background: var(--wp--preset--color--brand);
	box-shadow: 0 0 0 0 rgba(255, 140, 0, .6);
	animation: tt-pulse 2.4s ease-out infinite;
	flex: none;
}

@keyframes tt-pulse {
	0%   { box-shadow: 0 0 0 0 rgba(255, 140, 0, .55); }
	70%  { box-shadow: 0 0 0 .55rem rgba(255, 140, 0, 0); }
	100% { box-shadow: 0 0 0 0 rgba(255, 140, 0, 0); }
}

/* Headline reveal. The words are wrapped by the script; without it the
   heading is plain text and perfectly visible, which is the whole point. */

.tt-word {
	display: inline-block;
	overflow: hidden;
	/* Descenders would be clipped by the overflow without this. */
	padding-block-end: .12em;
	margin-block-end: -.12em;
	vertical-align: bottom;
}

.tt-word__in {
	display: inline-block;
	/* An animation, not a transition toggled by a class. It starts the moment
	   the element exists, so nothing here depends on a callback firing — and
	   if the script never runs, these elements never exist and the heading is
	   just a heading. */
	animation: tt-word-in .7s var(--tt-ease) var(--tt-word-delay, 0ms) both;
}

@keyframes tt-word-in {
	from { transform: translate3d(0, 105%, 0); opacity: 0; }
	to   { transform: translate3d(0, 0, 0); opacity: 1; }
}

/* Pointer-reactive card light. With the custom properties unset — every
   touch device — this resolves to a centred gradient at zero opacity, so
   it costs nothing and shows nothing. */

.is-style-tt-card,
.is-style-tt-card-dark,
.tt-door { overflow: hidden; }

.is-style-tt-card::before,
.is-style-tt-card-dark::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	opacity: 0;
	transition: opacity .35s var(--tt-ease);
	background: radial-gradient(
		20rem 20rem at var(--tt-mx, 50%) var(--tt-my, 50%),
		rgba(36, 99, 235, .10),
		transparent 70%
	);
}

.is-style-tt-card-dark::before {
	background: radial-gradient(
		20rem 20rem at var(--tt-mx, 50%) var(--tt-my, 50%),
		rgba(255, 140, 0, .14),
		transparent 70%
	);
}

@media (hover: hover) and (pointer: fine) {
	.is-style-tt-card:hover::before,
	.is-style-tt-card-dark:hover::before { opacity: 1; }
}

/* Card children sit above the light. */
.is-style-tt-card > *,
.is-style-tt-card-dark > * { position: relative; z-index: 1; }

/* Scroll cue under the hero — tells a first-time visitor there is more,
   which is the one thing a tall hero otherwise hides. */

.tt-scroll-cue {
	position: absolute;
	inset-block-end: 1.6rem;
	inset-inline-start: 50%;
	transform: translateX(-50%);
	z-index: 3;
	display: inline-flex;
	flex-direction: column;
	align-items: center;
	gap: .55rem;
	font-size: var(--wp--preset--font-size--x-small);
	letter-spacing: .14em;
	text-transform: uppercase;
	font-weight: 700;
	color: var(--wp--preset--color--slate-pale);
	text-decoration: none;
}

.tt-scroll-cue__rail {
	inline-size: 1px;
	block-size: 2.25rem;
	background: rgba(255, 255, 255, .22);
	position: relative;
	overflow: hidden;
}

.tt-scroll-cue__rail::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	block-size: 45%;
	background: var(--wp--preset--color--brand);
	animation: tt-rail 2.2s var(--tt-ease) infinite;
}

@keyframes tt-rail {
	0%   { transform: translateY(-110%); opacity: 0; }
	35%  { opacity: 1; }
	100% { transform: translateY(240%); opacity: 0; }
}

.tt-scroll-cue:hover { color: #fff; }

@media (max-width: 48em) {
	.tt-scroll-cue { display: none; }
}

/* Everything above, off. */

@media (prefers-reduced-motion: reduce) {
	.tt-signal__sweep,
	.tt-hero .tt-badge::before,
	.tt-scroll-cue__rail::after { animation: none; }

	.tt-word__in { animation: none; transform: none; opacity: 1; }
	.wp-block-button__link { transform: none; }

	.is-style-tt-card::before,
	.is-style-tt-card-dark::before { display: none; }
}

/* --------------------------------------------------------------------------
   19. Managed plans — pricing cards and the comparison table

   A pricing page has one job: let someone work out which column is theirs in
   about five seconds. Everything here serves that — the middle plan is the
   recommendation and looks like it, the prices are the largest thing on the
   card, and the comparison table exists because a card grid alone never quite
   answers "but what's the actual difference".
   -------------------------------------------------------------------------- */

.tt-plans {
	display: grid;
	gap: 1.5rem;
	grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
	align-items: stretch;
	margin-block-start: 3rem;
}

.tt-plan {
	position: relative;
	display: flex;
	flex-direction: column;
	background: #fff;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--lg);
	padding: clamp(1.75rem, 3vw, 2.25rem);
	box-shadow: var(--wp--preset--shadow--soft);
	transition: transform var(--wp--custom--transition--base),
	            box-shadow var(--wp--custom--transition--base),
	            border-color var(--wp--custom--transition--base);
}

@media (hover: hover) and (pointer: fine) {
	.tt-plan:hover {
		transform: translateY(-4px);
		box-shadow: var(--wp--preset--shadow--lift);
		border-color: rgba(36, 99, 235, .35);
	}
}

/* The recommended plan. Dark, so the eye lands on it first, and lifted a
   little on wide screens so the row has a centre of gravity. */

.tt-plan--featured {
	background: var(--wp--preset--gradient--night, linear-gradient(160deg, #0F1729, #020617));
	border-color: rgba(255, 140, 0, .55);
	color: var(--wp--preset--color--slate-pale);
	box-shadow: 0 24px 60px -24px rgba(2, 6, 23, .55);
}

.tt-plan--featured :is(h3, .tt-plan__price, .tt-plan__amount) { color: #fff; }
.tt-plan--featured .tt-plan__for,
.tt-plan--featured .tt-plan__note { color: var(--wp--preset--color--slate-pale); }

@media (min-width: 62em) {
	.tt-plan--featured { transform: translateY(-14px); }

	@media (hover: hover) and (pointer: fine) {
		.tt-plan--featured:hover { transform: translateY(-20px); }
	}
}

/* An engineered grid inside the featured card, echoing the hero. */
.tt-plan--featured::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	border-radius: inherit;
	background-image:
		linear-gradient(rgba(255, 255, 255, .05) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255, 255, 255, .05) 1px, transparent 1px);
	background-size: 44px 44px;
	mask-image: radial-gradient(ellipse 80% 60% at 70% 0%, #000 10%, transparent 75%);
	-webkit-mask-image: radial-gradient(ellipse 80% 60% at 70% 0%, #000 10%, transparent 75%);
}

.tt-plan > * { position: relative; z-index: 1; }

.tt-plan__badge {
	position: absolute;
	inset-block-start: -.85rem;
	inset-inline-start: 50%;
	transform: translateX(-50%);
	z-index: 2;
	padding: .35rem 1rem;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--brand);
	color: var(--wp--preset--color--ink);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 800;
	letter-spacing: .1em;
	text-transform: uppercase;
	white-space: nowrap;
}

.tt-plan__name {
	font-size: var(--wp--preset--font-size--large);
	font-weight: 800;
	letter-spacing: -.01em;
	margin: 0;
}

.tt-plan__for {
	margin: .5rem 0 0;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--slate);
	min-block-size: 3.2em;
}

.tt-plan__price {
	display: flex;
	align-items: baseline;
	gap: .3rem;
	margin-block: 1.5rem .25rem;
	color: var(--wp--preset--color--ink);
}

/* The amount carries its own dollar sign, because the token resolves to a
   complete string — "$89" when a price is set, "on request" when it isn't.
   Splitting the $ into its own element would leave a stranded "$ on request"
   on any field Michael hasn't filled in yet. */
.tt-plan__amount {
	font-size: clamp(2.4rem, 5.6vw, 3.4rem);
	font-weight: 800;
	line-height: 1;
	letter-spacing: -.03em;
	font-variant-numeric: tabular-nums;
	overflow-wrap: anywhere;
}

.tt-plan__unit {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--slate);
}

.tt-plan--featured .tt-plan__unit { color: var(--wp--preset--color--slate-pale); }

.tt-plan__note {
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--slate);
	margin: 0 0 1.5rem;
}

.tt-plan__list {
	list-style: none;
	margin: 0 0 2rem;
	padding: 0;
	border-block-start: 1px solid var(--tt-hairline);
	padding-block-start: 1.5rem;
	flex: 1;
}

.tt-plan--featured .tt-plan__list { border-block-start-color: var(--tt-hairline-dark); }

.tt-plan__list li {
	position: relative;
	padding-inline-start: 1.85rem;
	margin-block: .7rem;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.55;
}

.tt-plan__list li::before {
	content: "";
	position: absolute;
	inset-inline-start: 0;
	inset-block-start: .3em;
	inline-size: 1.1rem;
	block-size: 1.1rem;
	border-radius: 50%;
	background: rgba(15, 123, 79, .12);
	box-shadow: inset 0 0 0 1.5px rgba(15, 123, 79, .35);
}

.tt-plan__list li::after {
	content: "";
	position: absolute;
	inset-inline-start: .32rem;
	inset-block-start: .58em;
	inline-size: .4rem;
	block-size: .2rem;
	border-inline-start: 2px solid var(--wp--preset--color--green);
	border-block-end: 2px solid var(--wp--preset--color--green);
	transform: rotate(-45deg);
}

.tt-plan--featured .tt-plan__list li::before {
	background: rgba(255, 140, 0, .14);
	box-shadow: inset 0 0 0 1.5px rgba(255, 140, 0, .45);
}

.tt-plan--featured .tt-plan__list li::after { border-color: var(--wp--preset--color--brand); }

/* "Everything in X, plus" — a divider that carries meaning. */
.tt-plan__inherits {
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--brand-text);
	margin: 0 0 1rem;
}

.tt-plan--featured .tt-plan__inherits { color: var(--wp--preset--color--brand); }

.tt-plan .wp-block-button__link,
.tt-plan .tt-plan__cta {
	display: flex;
	inline-size: 100%;
	justify-content: center;
	text-align: center;
}

.tt-plan__cta {
	padding: .95rem 1.5rem;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--ink);
	color: #fff;
	font-weight: 700;
	text-decoration: none;
	min-block-size: 48px;
	align-items: center;
	transition: background var(--wp--custom--transition--base), color var(--wp--custom--transition--base);
}

.tt-plan__cta:hover { background: var(--wp--preset--color--blue); color: #fff; }

.tt-plan--featured .tt-plan__cta { background: var(--wp--preset--color--brand); color: var(--wp--preset--color--ink); }
.tt-plan--featured .tt-plan__cta:hover { background: var(--wp--preset--color--brand-deep); color: var(--wp--preset--color--ink); }

/* --------------------------------------------------------------------------
   The comparison table

   A real table, because it is real tabular data and a screen reader should
   read it as one. On a phone it scrolls sideways with the feature column
   pinned, which is the only pattern that stays usable at 360px without
   hiding a column.
   -------------------------------------------------------------------------- */

.tt-compare {
	margin-block-start: 3rem;
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--lg);
	background: #fff;
}

.tt-compare table {
	inline-size: 100%;
	border-collapse: collapse;
	min-inline-size: 34rem;
	font-size: var(--wp--preset--font-size--small);
}

.tt-compare th,
.tt-compare td {
	padding: .95rem 1.1rem;
	text-align: center;
	border-block-end: 1px solid var(--tt-hairline);
	vertical-align: middle;
}

.tt-compare thead th {
	position: sticky;
	inset-block-start: 0;
	background: var(--wp--preset--color--ink);
	color: #fff;
	font-weight: 700;
	white-space: nowrap;
}

.tt-compare thead th:first-child,
.tt-compare tbody th {
	text-align: start;
	position: sticky;
	inset-inline-start: 0;
	z-index: 1;
}

.tt-compare tbody th {
	background: #fff;
	font-weight: 600;
	color: var(--wp--preset--color--ink);
	border-inline-end: 1px solid var(--tt-hairline);
}

.tt-compare thead th:first-child { z-index: 2; }

.tt-compare tbody tr:nth-child(even) th,
.tt-compare tbody tr:nth-child(even) td { background: rgba(15, 23, 41, .025); }

.tt-compare tbody tr:last-child th,
.tt-compare tbody tr:last-child td { border-block-end: 0; }

/* A tick, a dash, or a value. Drawn rather than typed so it never depends on
   an emoji font being present. */
.tt-tick,
.tt-none {
	display: inline-block;
	inline-size: 1.25rem;
	block-size: 1.25rem;
	border-radius: 50%;
	position: relative;
}

.tt-tick { background: rgba(15, 123, 79, .12); box-shadow: inset 0 0 0 1.5px rgba(15, 123, 79, .35); }

.tt-tick::after {
	content: "";
	position: absolute;
	inset-inline-start: .36rem;
	inset-block-start: .36rem;
	inline-size: .46rem;
	block-size: .23rem;
	border-inline-start: 2px solid var(--wp--preset--color--green);
	border-block-end: 2px solid var(--wp--preset--color--green);
	transform: rotate(-45deg);
}

.tt-none { background: rgba(100, 116, 139, .12); }

.tt-none::after {
	content: "";
	position: absolute;
	inset-inline: .32rem;
	inset-block-start: .58rem;
	block-size: 2px;
	border-radius: 2px;
	background: var(--wp--preset--color--slate);
}

.tt-compare__hint {
	display: none;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--slate);
	text-align: center;
	margin-block-start: .75rem;
}

@media (max-width: 48em) {
	.tt-compare__hint { display: block; }
}

@media (prefers-reduced-motion: reduce) {
	.tt-plan,
	.tt-plan--featured { transition: none; }
	@media (min-width: 62em) {
		.tt-plan--featured { transform: none; }
	}
}


/* ---------------------------------------------------------------------------
   20. Hourly rate cards (pricing page)
   ------------------------------------------------------------------------
   Three rates, side by side, above the itemised lists. Someone who only
   wants to know "what do you charge an hour" should never have to scroll.
   --------------------------------------------------------------------- */

.tt-rates__grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
	gap: 1rem;
}

.tt-rate {
	background: #fff;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--lg);
	padding: 1.5rem 1.4rem;
	transition: border-color .25s var(--tt-ease), transform .25s var(--tt-ease);
}

@media (hover: hover) and (pointer: fine) {
	.tt-rate:hover {
		border-color: rgba(255, 140, 0, .45);
		transform: translateY(-3px);
	}
}

.tt-rate__label {
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--slate);
	margin: 0;
}

.tt-rate__figure {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: .45rem;
	margin: .6rem 0 .5rem;
	font-size: clamp(1.9rem, 4.5vw, 2.5rem);
	font-weight: 800;
	line-height: 1.05;
	letter-spacing: -.03em;
	color: var(--wp--preset--color--ink);
	font-variant-numeric: tabular-nums;
	overflow-wrap: anywhere;
}

.tt-rate__figure span {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	letter-spacing: 0;
	color: var(--wp--preset--color--slate);
}

.tt-rate__note {
	margin: 0;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--slate);
	line-height: 1.5;
}

.tt-rates__basis {
	margin: 1.25rem 0 0;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--slate);
	text-align: center;
}

@media (prefers-reduced-motion: reduce) {
	.tt-rate { transition: none; }
	.tt-rate:hover { transform: none; }
}


/* ---------------------------------------------------------------------------
   21. Client portal doors
   ------------------------------------------------------------------------
   Three equal doors, not a hierarchy. Whichever one someone needs is the
   right one, so none of them is styled as the primary action — the only
   difference between them is the accent stripe, which exists so the eye can
   tell them apart at a glance rather than to rank them.
   --------------------------------------------------------------------- */

.tt-portal__doors {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
	gap: 1.25rem;
	margin-block-start: 3rem;
}

.tt-portal__door {
	position: relative;
	display: flex;
	flex-direction: column;
	background: #fff;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--lg);
	padding: clamp(1.5rem, 3vw, 2rem);
	box-shadow: var(--wp--preset--shadow--soft);
	overflow: hidden;
	transition: transform var(--wp--custom--transition--base),
	            box-shadow var(--wp--custom--transition--base),
	            border-color var(--wp--custom--transition--base);
}

/* The accent stripe. Drawn, not an image, so it costs nothing to load. */
.tt-portal__door::before {
	content: "";
	position: absolute;
	inset-block-start: 0;
	inset-inline: 0;
	block-size: 4px;
	background: var(--wp--preset--color--blue);
}

.tt-portal__door--ticket::before { background: var(--wp--preset--color--brand); }
.tt-portal__door--remote::before { background: var(--wp--preset--color--ink); }

@media (hover: hover) and (pointer: fine) {
	.tt-portal__door:hover {
		transform: translateY(-4px);
		box-shadow: var(--wp--preset--shadow--lift);
		border-color: rgba(36, 99, 235, .35);
	}
}

.tt-portal__title {
	margin: 0 0 .75rem;
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 700;
	letter-spacing: -.02em;
	color: var(--wp--preset--color--ink);
}

.tt-portal__body {
	margin: 0 0 1.75rem;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.65;
	color: var(--wp--preset--color--slate);
	/* Pushes every button onto the same line regardless of how much copy sits
	   above it, so the three doors read as a set rather than a ragged row. */
	flex: 1;
}

.tt-portal__cta {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: .5rem;
	align-self: flex-start;
	padding: .85rem 1.6rem;
	border-radius: 999px;
	background: var(--wp--preset--color--ink);
	color: #fff;
	font-weight: 700;
	font-size: var(--wp--preset--font-size--small);
	text-decoration: none;
	transition: background var(--wp--custom--transition--base),
	            transform var(--wp--custom--transition--base);
}

.tt-portal__door--ticket .tt-portal__cta { background: var(--wp--preset--color--brand); }

.tt-portal__cta:hover,
.tt-portal__cta:focus-visible {
	transform: translateY(-2px);
	text-decoration: none;
}

/* A drawn arrow marking the link as leaving this site, so nobody is surprised
   to land on a Zoho page. */
.tt-portal__cta::after {
	content: "";
	inline-size: .5rem;
	block-size: .5rem;
	border-block-start: 2px solid currentColor;
	border-inline-end: 2px solid currentColor;
	transform: rotate(45deg);
	flex: none;
}

/* The state before any URL has been entered. */
.tt-portal__pending {
	max-inline-size: 42rem;
	margin-inline: auto;
	text-align: center;
	margin-block-end: 2.5rem;
}

.tt-portal__pending h2 { margin-block-end: .75rem; }

@media (prefers-reduced-motion: reduce) {
	.tt-portal__door,
	.tt-portal__cta { transition: none; }
	.tt-portal__door:hover,
	.tt-portal__cta:hover { transform: none; }
}


/* ---------------------------------------------------------------------------
   22. The free-call offer panel
   ------------------------------------------------------------------------
   This was the fourth card in a three-card row, which made the one genuinely
   free thing on the page look like the least important. It is now a wide panel
   with its own colour, so it reads as an offer rather than a leftover.
   --------------------------------------------------------------------- */

.tt-offer {
	position: relative;
	display: grid;
	grid-template-columns: auto 1fr auto;
	gap: 1.75rem 2rem;
	align-items: center;
	margin-block-start: 2rem;
	padding: clamp(1.75rem, 4vw, 2.75rem);
	border-radius: var(--wp--custom--radius--lg);
	background: var(--wp--preset--gradient--night);
	border: 1px solid rgba(255, 140, 0, .35);
	color: var(--wp--preset--color--slate-pale);
	overflow: hidden;
	isolation: isolate;
}

/* Same drawn grid as the dark sections, masked so it fades out to the right. */
.tt-offer::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background-image:
		linear-gradient(rgba(255, 255, 255, .05) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255, 255, 255, .05) 1px, transparent 1px);
	background-size: 48px 48px;
	mask-image: linear-gradient(100deg, #000 0%, transparent 70%);
	pointer-events: none;
}

.tt-offer__mark {
	display: grid;
	place-items: center;
	inline-size: 3.75rem;
	block-size: 3.75rem;
	border-radius: 50%;
	background: rgba(255, 140, 0, .16);
	border: 1px solid rgba(255, 140, 0, .45);
	color: var(--wp--preset--color--brand);
	flex: none;
}

.tt-offer__mark svg { inline-size: 1.65rem; block-size: 1.65rem; }

.tt-offer__tag {
	margin: 0 0 .4rem;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	letter-spacing: .13em;
	text-transform: uppercase;
	color: var(--wp--preset--color--brand);
}

.tt-offer__title {
	margin: 0 0 .6rem;
	font-size: clamp(1.4rem, 3vw, 1.85rem);
	font-weight: 800;
	letter-spacing: -.02em;
	color: #fff;
}

.tt-offer__text {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.65;
	max-inline-size: 48ch;
}

.tt-offer__points {
	list-style: none;
	margin: 1rem 0 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: .4rem 1.4rem;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	color: #fff;
}

.tt-offer__points li { display: flex; align-items: center; gap: .45rem; }

/* Drawn tick: a rotated corner, same construction as the plan lists. */
.tt-offer__points li::before {
	content: "";
	inline-size: .45rem;
	block-size: .78rem;
	border: solid var(--wp--preset--color--brand);
	border-width: 0 2px 2px 0;
	transform: rotate(45deg) translateY(-.12rem);
	flex: none;
}

.tt-offer__act { display: grid; gap: .6rem; justify-items: center; }

.tt-offer__cta {
	display: inline-block;
	padding: .95rem 1.9rem;
	border-radius: 999px;
	background: var(--wp--preset--color--brand);
	color: var(--wp--preset--color--ink) !important;
	font-weight: 800;
	font-size: var(--wp--preset--font-size--small);
	text-decoration: none;
	white-space: nowrap;
	transition: transform var(--wp--custom--transition--base),
	            box-shadow var(--wp--custom--transition--base);
}

.tt-offer__cta:hover,
.tt-offer__cta:focus-visible {
	transform: translateY(-2px);
	box-shadow: var(--wp--preset--shadow--glow);
	text-decoration: none;
}

.tt-offer__alt {
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--slate-pale) !important;
	white-space: nowrap;
}

@media (max-width: 62em) {
	.tt-offer {
		grid-template-columns: auto 1fr;
		gap: 1.25rem 1.5rem;
	}
	/* The button drops under the copy and spans both columns rather than
	   squeezing into a third one. */
	.tt-offer__act {
		grid-column: 1 / -1;
		justify-items: start;
	}
}

@media (max-width: 40em) {
	.tt-offer { grid-template-columns: 1fr; }
	.tt-offer__act { justify-items: stretch; }
	.tt-offer__cta { text-align: center; }
}

@media (prefers-reduced-motion: reduce) {
	.tt-offer__cta { transition: none; }
	.tt-offer__cta:hover { transform: none; }
}


/* ---------------------------------------------------------------------------
   23. Contact page
   ------------------------------------------------------------------------
   Three routes in, then the form. The phone card is deliberately the loud one:
   someone arriving here with a machine that will not boot should be able to
   start a call in one tap without reading a word.
   --------------------------------------------------------------------- */

.tt-routes {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
	gap: 1.1rem;
	margin-block-start: 3rem;
}

.tt-route {
	display: grid;
	gap: .35rem;
	padding: 1.6rem;
	border-radius: var(--wp--custom--radius--lg);
	background: rgba(255, 255, 255, .045);
	border: 1px solid var(--tt-hairline-dark);
	color: var(--wp--preset--color--slate-pale) !important;
	text-decoration: none;
	transition: transform var(--wp--custom--transition--base),
	            border-color var(--wp--custom--transition--base),
	            background var(--wp--custom--transition--base);
}

.tt-route--now {
	background: rgba(255, 140, 0, .1);
	border-color: rgba(255, 140, 0, .45);
}

@media (hover: hover) and (pointer: fine) {
	.tt-route:hover {
		transform: translateY(-4px);
		border-color: rgba(255, 140, 0, .55);
		background: rgba(255, 255, 255, .075);
		text-decoration: none;
	}
	.tt-route--now:hover { background: rgba(255, 140, 0, .16); }
}

.tt-route__glyph {
	display: grid;
	place-items: center;
	inline-size: 2.7rem;
	block-size: 2.7rem;
	margin-block-end: .6rem;
	border-radius: 12px;
	background: rgba(255, 255, 255, .07);
	border: 1px solid var(--tt-hairline-dark);
	color: var(--wp--preset--color--brand);
}

.tt-route--now .tt-route__glyph {
	background: var(--wp--preset--color--brand);
	border-color: transparent;
	color: var(--wp--preset--color--ink);
}

.tt-route__glyph svg { inline-size: 1.3rem; block-size: 1.3rem; display: block; }

.tt-route__tag {
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--wp--preset--color--brand);
}

.tt-route__title {
	font-size: 1.2rem;
	font-weight: 800;
	letter-spacing: -.02em;
	color: #fff;
}

.tt-route__value {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: #fff;
	/* Long email address on a narrow card would otherwise widen the grid. */
	overflow-wrap: anywhere;
}

.tt-route__note {
	margin-block-start: .5rem;
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.6;
	color: var(--wp--preset--color--slate);
}

.tt-route--now .tt-route__note { color: var(--wp--preset--color--slate-pale); }

/* --- the details list --------------------------------------------------- */

.tt-details {
	padding: clamp(1.5rem, 3vw, 2rem);
	border-radius: var(--wp--custom--radius--lg);
	border: 1px solid var(--wp--preset--color--line);
	background: #fff;
}

.tt-details__head {
	margin: 0 0 1.25rem;
	font-size: 1.35rem;
	font-weight: 800;
	letter-spacing: -.02em;
}

.tt-details__list { margin: 0; display: grid; gap: 1rem; }

.tt-details__list > div {
	display: grid;
	grid-template-columns: 6.5rem 1fr;
	gap: .5rem 1rem;
	align-items: baseline;
	padding-block-end: 1rem;
	border-block-end: 1px solid var(--tt-hairline);
}

.tt-details__list > div:last-child { padding-block-end: 0; border-block-end: 0; }

.tt-details dt {
	margin: 0;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--wp--preset--color--slate);
}

.tt-details dd {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.55;
	overflow-wrap: anywhere;
}

.tt-details__soft { color: var(--wp--preset--color--slate); }
.tt-details__mono { font-variant-numeric: tabular-nums; letter-spacing: .02em; }

@media (max-width: 30em) {
	.tt-details__list > div { grid-template-columns: 1fr; gap: .2rem; }
}

/* --- service area map --------------------------------------------------- */

.tt-map { margin-block-start: 2.5rem; }

.tt-map__frame {
	border-radius: var(--wp--custom--radius--lg);
	overflow: hidden;
	border: 1px solid var(--wp--preset--color--line);
	box-shadow: var(--wp--preset--shadow--soft);
	/* The iframe is a block child, so line-height on the wrapper would
	   otherwise leave a few stray pixels under it. */
	line-height: 0;
	background: var(--wp--preset--color--mist);
}

.tt-map__frame iframe { display: block; inline-size: 100%; }

.tt-map__areas {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
	margin: 1.5rem 0 0;
	padding: 0;
}

.tt-map__areas li {
	padding: .4rem .9rem;
	border-radius: 999px;
	border: 1px solid var(--wp--preset--color--line);
	background: #fff;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	color: var(--wp--preset--color--slate);
}

.tt-map__areas li:has(a) { padding: 0; border: 0; background: none; }

.tt-map__areas a {
	display: block;
	padding: .4rem .9rem;
	border-radius: 999px;
	border: 1px solid rgba(36, 99, 235, .3);
	background: rgba(36, 99, 235, .06);
	color: var(--wp--preset--color--blue);
	text-decoration: none;
	transition: background var(--wp--custom--transition--base),
	            border-color var(--wp--custom--transition--base);
}

.tt-map__areas a:hover {
	background: rgba(36, 99, 235, .12);
	border-color: var(--wp--preset--color--blue);
	text-decoration: none;
}

.tt-map__note {
	margin: 1.25rem 0 0;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--slate);
	text-align: center;
}

@media (max-width: 48em) {
	.tt-map__frame iframe { height: 340px; }
}

@media (prefers-reduced-motion: reduce) {
	.tt-route { transition: none; }
	.tt-route:hover { transform: none; }
}



/* ---------------------------------------------------------------------------
   24. Header and hero seam
   ------------------------------------------------------------------------
   The block template gives <main> a default top margin, which left a 24px
   white strip between the bottom of the sticky header and the top of the hero
   photograph. Nothing should sit in that gap.
   --------------------------------------------------------------------- */

.tt-header + main,
main.wp-block-group:first-of-type { margin-block-start: 0 !important; }

body > .wp-site-blocks > main:first-of-type { margin-block-start: 0 !important; }


/* ---------------------------------------------------------------------------
   25. reCAPTCHA
   ------------------------------------------------------------------------
   The floating badge sits over the bottom-right of every page it loads on and
   collides with the call button on a phone. Google allow hiding it as long as
   the attribution shows near the form instead, which the form renders.
   --------------------------------------------------------------------- */

.grecaptcha-badge {
	visibility: hidden !important;
}

.tt-form__recaptcha {
	margin: .9rem 0 0;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--slate);
	line-height: 1.5;
}

.tt-form__recaptcha a { color: var(--wp--preset--color--blue); }


/* ---------------------------------------------------------------------------
   27. Ghost button inside the dark header
   ------------------------------------------------------------------------
   is-style-tt-ghost is drawn for light sections: ink text, a faint ink border.
   Dropped onto the near-black header it becomes ink on ink, which is what made
   the phone number look washed out next to the Book online button. Same class
   of bug as the menu links, same fix.
   --------------------------------------------------------------------- */

.tt-header .is-style-tt-ghost .wp-block-button__link,
.tt-header .tt-header__call .wp-block-button__link {
	color: #fff !important;
	border-color: rgba(255, 255, 255, .32) !important;
	background: rgba(255, 255, 255, .05) !important;
	font-weight: 700;
}

.tt-header .is-style-tt-ghost .wp-block-button__link:hover,
.tt-header .tt-header__call .wp-block-button__link:hover {
	border-color: var(--wp--preset--color--brand) !important;
	background: rgba(255, 140, 0, .16) !important;
	color: #fff !important;
}

/* ---------------------------------------------------------------------------
   26. Portfolio cards
   ------------------------------------------------------------------------
   Screenshot first, name second, nothing else. A visitor deciding whether to
   trust the work looks at the picture; a paragraph about what the project
   needed is for me, not for them. Everything that used to be written out is
   one click away on the live site.
   --------------------------------------------------------------------- */

.tt-work {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
	gap: 1.75rem;
	margin-block-start: 3.5rem;
}

.tt-work__card {
	display: block;
	border-radius: var(--wp--custom--radius--lg);
	overflow: hidden;
	background: #fff;
	border: 1px solid var(--wp--preset--color--line);
	box-shadow: var(--wp--preset--shadow--soft);
	text-decoration: none;
	color: inherit;
	transition: transform .45s var(--tt-ease),
	            box-shadow .45s var(--tt-ease),
	            border-color .45s var(--tt-ease);
}

.tt-work__shot {
	position: relative;
	display: block;
	aspect-ratio: 16 / 10;
	overflow: hidden;
	background: var(--wp--preset--color--mist);
}

.tt-work__shot img {
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
	object-position: top center;
	display: block;
	transition: transform .7s var(--tt-ease);
}

/* The veil and the button live behind the image edge until hover. */
.tt-work__veil {
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(2, 6, 23, .05) 0%, rgba(2, 6, 23, .78) 100%);
	opacity: 0;
	transition: opacity .4s var(--tt-ease);
}

.tt-work__open {
	position: absolute;
	inset-block-end: 1.1rem;
	inset-inline-start: 1.1rem;
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	padding: .6rem 1.15rem;
	border-radius: 999px;
	background: var(--wp--preset--color--brand);
	color: var(--wp--preset--color--ink);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 800;
	opacity: 0;
	transform: translateY(12px);
	transition: opacity .4s var(--tt-ease), transform .4s var(--tt-ease);
}

.tt-work__open::after {
	content: "";
	inline-size: .4rem;
	block-size: .4rem;
	border-block-start: 2px solid currentColor;
	border-inline-end: 2px solid currentColor;
	transform: rotate(45deg);
}

@media (hover: hover) and (pointer: fine) {
	.tt-work__card:hover {
		transform: translateY(-6px);
		box-shadow: var(--wp--preset--shadow--lift);
		border-color: rgba(255, 140, 0, .5);
	}

	.tt-work__card:hover .tt-work__shot img { transform: scale(1.06); }
	.tt-work__card:hover .tt-work__veil { opacity: 1; }
	.tt-work__card:hover .tt-work__open { opacity: 1; transform: translateY(0); }
}

/* Keyboard users get the same reveal, since :hover never fires for them. */
.tt-work__card:focus-visible .tt-work__veil { opacity: 1; }
.tt-work__card:focus-visible .tt-work__open { opacity: 1; transform: translateY(0); }

.tt-work__foot {
	display: block;
	padding: 1.15rem 1.35rem 1.35rem;
}

.tt-work__name {
	display: block;
	font-size: 1.1rem;
	font-weight: 800;
	letter-spacing: -.02em;
	line-height: 1.3;
	color: var(--wp--preset--color--ink);
}

.tt-work__domain {
	display: block;
	margin-block-start: .2rem;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--slate);
	font-variant-numeric: tabular-nums;
}

.tt-work__cat {
	display: inline-block;
	margin-block-start: .7rem;
	padding: .22rem .65rem;
	border-radius: 999px;
	background: rgba(36, 99, 235, .08);
	border: 1px solid rgba(36, 99, 235, .22);
	font-size: .68rem;
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--blue);
}

@media (prefers-reduced-motion: reduce) {
	.tt-work__card,
	.tt-work__shot img,
	.tt-work__veil,
	.tt-work__open { transition: none; }
	.tt-work__card:hover { transform: none; }
	.tt-work__card:hover .tt-work__shot img { transform: none; }
}


/* ---------------------------------------------------------------------------
   27. Three layout bugs
   --------------------------------------------------------------------- */

/* (a) The full-width sections inside a template part were being capped.
   A template part wrapper carries max-inline-size from the block layout, so
   an alignfull section inside it stopped short of the window and read as a
   narrow inset band on a wide screen. */
.wp-block-template-part { max-inline-size: none !important; }

/* (b) The select rendered taller than the text inputs beside it, because the
   inputs compute as content-box and the select as border-box. Same declared
   height, different box model, so they never lined up. */
.tt-form :is(input, select, textarea) {
	box-sizing: border-box !important;
	block-size: auto;
	min-block-size: 3.4rem;
	line-height: 1.5;
}

.tt-form select {
	/* The native arrow sizes itself differently again, so it is replaced with
	   a drawn one and the control is given room for it. */
	appearance: none;
	-webkit-appearance: none;
	padding-inline-end: 2.75rem;
	background-image:
		linear-gradient(45deg, transparent 50%, currentColor 50%),
		linear-gradient(135deg, currentColor 50%, transparent 50%);
	background-position:
		calc(100% - 1.15rem) calc(50% + 2px),
		calc(100% - 0.8rem) calc(50% + 2px);
	background-size: 6px 6px, 6px 6px;
	background-repeat: no-repeat;
}

/* Fields stack from the top so a taller control never drags its label down. */
.tt-form__field { align-content: start; }
.tt-form__field > label { align-self: start; }
.tt-form__row { align-items: start; }

/* (c) The footer was capped narrower than the widest sections above it. */
.tt-footer { --wp--style--global--content-size: 1560px; }
.tt-footer > .tt-footer__grid,
.tt-footer > .tt-footer__legal {
	max-inline-size: 1560px;
	margin-inline: auto;
}


/* ---------------------------------------------------------------------------
   28. Reviews slider
   ------------------------------------------------------------------------
   Scroll-snap does the work. The track is a real scroll container, so it
   swipes on a phone, takes a trackpad gesture, and responds to arrow keys
   when focused, all without a line of JavaScript. The buttons added by the
   script are a convenience on top of something that already works.
   --------------------------------------------------------------------- */

.tt-rev { position: relative; margin-block-start: 2.5rem; }

.tt-rev__track {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: minmax(min(100%, 21rem), 1fr);
	gap: 1.25rem;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	/* Room for the cards' shadow, and for the focus ring not to be clipped. */
	padding: .5rem .35rem 1.25rem;
	margin-inline: -.35rem;
	scrollbar-width: thin;
}

.tt-rev__track:focus-visible {
	outline: 2px solid var(--wp--preset--color--blue);
	outline-offset: 4px;
	border-radius: var(--wp--custom--radius--lg);
}

@media (min-width: 60em) {
	/* A fixed track size, not minmax(0, …). With a minmax the columns happily
	   shrink to share the container and the track never overflows, so it never
	   scrolls and the arrows stay hidden. Three across, and the rest overflow
	   into the scroll, which is the entire point of a slider. */
	.tt-rev__track { grid-auto-columns: calc((100% - 2.5rem) / 3); }
}

.tt-rev__slide {
	scroll-snap-align: start;
	display: flex;
	flex-direction: column;
	gap: .9rem;
	padding: clamp(1.4rem, 3vw, 1.9rem);
	border-radius: var(--wp--custom--radius--lg);
	background: #fff;
	border: 1px solid var(--wp--preset--color--line);
	box-shadow: var(--wp--preset--shadow--soft);
	transition: border-color var(--wp--custom--transition--base),
	            box-shadow var(--wp--custom--transition--base);
}

.tt-rev__slide:hover {
	border-color: rgba(255, 140, 0, .4);
	box-shadow: var(--wp--preset--shadow--lift);
}

.tt-rev__text {
	flex: 1;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.65;
	color: var(--wp--preset--color--slate);
	/* The longest review here runs to fifteen lines. Capping it keeps the
	   slides a sane height; the full text is a click away on Google. */
	max-block-size: 15.5rem;
	overflow: hidden;
	-webkit-mask-image: linear-gradient(180deg, #000 78%, transparent 100%);
	mask-image: linear-gradient(180deg, #000 78%, transparent 100%);
}

.tt-rev__text p { margin: 0 0 .7rem; }
.tt-rev__text p:last-child { margin-block-end: 0; }

.tt-rev__by {
	display: flex;
	align-items: center;
	gap: .7rem;
	padding-block-start: .9rem;
	border-block-start: 1px solid var(--tt-hairline);
	font-size: var(--wp--preset--font-size--x-small);
}

.tt-rev__when { color: var(--wp--preset--color--slate); }

/* --- controls ----------------------------------------------------------- */

.tt-rev__controls {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 1rem;
	margin-block-start: .25rem;
}

.tt-rev__controls[hidden] { display: none; }

.tt-rev__btn {
	inline-size: 2.6rem;
	block-size: 2.6rem;
	border-radius: 50%;
	border: 1px solid var(--wp--preset--color--line);
	background: #fff;
	cursor: pointer;
	position: relative;
	transition: border-color var(--wp--custom--transition--base),
	            background var(--wp--custom--transition--base),
	            transform var(--wp--custom--transition--base);
}

.tt-rev__btn::before {
	content: "";
	position: absolute;
	inset-block-start: 50%;
	inset-inline-start: 50%;
	inline-size: .5rem;
	block-size: .5rem;
	border-block-start: 2px solid var(--wp--preset--color--ink);
	border-inline-end: 2px solid var(--wp--preset--color--ink);
}

.tt-rev__btn[data-dir="next"]::before { transform: translate(-65%, -50%) rotate(45deg); }
.tt-rev__btn[data-dir="prev"]::before { transform: translate(-35%, -50%) rotate(-135deg); }

.tt-rev__btn:hover:not(:disabled) {
	border-color: var(--wp--preset--color--brand);
	background: rgba(255, 140, 0, .1);
	transform: translateY(-2px);
}

.tt-rev__btn:disabled { opacity: .35; cursor: default; }

.tt-rev__dots { display: flex; gap: .45rem; }

.tt-rev__dot {
	inline-size: .5rem;
	block-size: .5rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--wp--preset--color--line);
	cursor: pointer;
	transition: background var(--wp--custom--transition--base),
	            inline-size var(--wp--custom--transition--base);
}

.tt-rev__dot[aria-current="true"] {
	background: var(--wp--preset--color--brand);
	inline-size: 1.5rem;
	border-radius: 999px;
}

@media (prefers-reduced-motion: reduce) {
	.tt-rev__track { scroll-behavior: auto; }
	.tt-rev__btn, .tt-rev__dot, .tt-rev__slide { transition: none; }
	.tt-rev__btn:hover { transform: none; }
}


/* ---------------------------------------------------------------------------
   29. Pricing panels
   ------------------------------------------------------------------------
   Two priced lists side by side. The previous version was a plain bulleted
   list, which meant the price floated at the end of a sentence and your eye
   had to hunt for it on every line. Here the name and its caveat sit left,
   the figure sits hard right in a tabular column, and a hairline separates
   the rows, so the prices read down the page as a single column of numbers.
   --------------------------------------------------------------------- */

.tt-pricecols {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(25rem, 1fr));
	gap: 1.75rem;
	margin-block-start: 3.5rem;
	align-items: start;
}

.tt-price {
	background: #fff;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--lg);
	padding: clamp(1.6rem, 3vw, 2.4rem);
	box-shadow: var(--wp--preset--shadow--soft);
}

/* The business panel is the one with the recurring revenue behind it, so it
   gets the accent. Not a hard sell, just a nudge. */
.tt-price--biz { border-color: rgba(36, 99, 235, .3); }

.tt-price__head { margin-block-end: 1.75rem; }

.tt-price__tag {
	display: inline-block;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 700;
	letter-spacing: .13em;
	text-transform: uppercase;
	color: var(--wp--preset--color--blue);
}

.tt-price--biz .tt-price__tag { color: var(--wp--preset--color--brand-text); }

.tt-price__title {
	margin: .5rem 0 .6rem;
	font-size: clamp(1.9rem, 4vw, 2.5rem);
	font-weight: 800;
	letter-spacing: -.03em;
	line-height: 1.1;
}

.tt-price__blurb {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.6;
	color: var(--wp--preset--color--slate);
	max-inline-size: 42ch;
}

.tt-price__list {
	list-style: none;
	margin: 0;
	padding: 0;
	border-block-start: 1px solid var(--tt-hairline);
}

.tt-price__row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1.5rem;
	padding: .95rem .6rem;
	margin-inline: -.6rem;
	border-block-end: 1px solid var(--tt-hairline);
	border-radius: 8px;
	transition: background var(--wp--custom--transition--base);
}

.tt-price__row:hover { background: var(--wp--preset--color--mist); }

.tt-price__what { display: block; }

.tt-price__name {
	display: block;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--ink);
	line-height: 1.45;
}

.tt-price__note {
	display: block;
	margin-block-start: .2rem;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--slate);
	line-height: 1.45;
}

.tt-price__cost {
	flex: none;
	font-size: 1.05rem;
	font-weight: 800;
	letter-spacing: -.02em;
	color: var(--wp--preset--color--brand-text);
	font-variant-numeric: tabular-nums;
	text-align: end;
	white-space: nowrap;
}

.tt-price__unit {
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	color: var(--wp--preset--color--slate);
	margin-inline-start: .25rem;
}

.tt-price__acts {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .9rem;
	margin-block-start: 1.9rem;
}

.tt-price__cta {
	display: inline-block;
	padding: .85rem 1.6rem;
	border-radius: 999px;
	background: var(--wp--preset--color--brand);
	color: var(--wp--preset--color--ink) !important;
	font-weight: 800;
	font-size: var(--wp--preset--font-size--small);
	text-decoration: none;
	transition: transform var(--wp--custom--transition--base),
	            box-shadow var(--wp--custom--transition--base);
}

.tt-price__cta:hover {
	transform: translateY(-2px);
	box-shadow: var(--wp--preset--shadow--glow);
	text-decoration: none;
}

.tt-price__alt {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--blue);
}

/* Under about 30em the price cannot sit beside a long service name without
   one of them wrapping badly, so the row stacks. */
@media (max-width: 30em) {
	.tt-price__row {
		flex-direction: column;
		align-items: flex-start;
		gap: .3rem;
	}
	.tt-price__cost { text-align: start; }
}

@media (prefers-reduced-motion: reduce) {
	.tt-price__row, .tt-price__cta { transition: none; }
	.tt-price__cta:hover { transform: none; }
}


/* --------------------------------------------------------------------------
   14. Mobile menu — header blur vs the navigation overlay
   --------------------------------------------------------------------------
   .tt-header carries backdrop-filter. Any element with a backdrop-filter
   becomes the containing block for its position:fixed descendants, so the
   navigation overlay - which is fixed, inset 0 - was being sized against the
   header instead of the screen. On a phone that meant a strip the height of
   the header with only the first item, "Home", inside it.

   The blur is dropped at the widths where the overlay is used, and while it
   is open at any width. The header background is already 94% opaque, so
   nothing looks different. */

@media (max-width: 600px) {
	.tt-header {
		backdrop-filter: none;
		-webkit-backdrop-filter: none;
		background: rgba(11, 18, 33, .98);
	}
}

html.has-modal-open .tt-header {
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
}

.tt-header .wp-block-navigation__responsive-container.is-menu-open {
	inset: 0;
	overflow-y: auto;
}

/* The open-menu icon inherited the ink colour, which is the navy it sits on,
   so it was all but invisible. White, and a 44px target for a thumb. */

.tt-header .wp-block-navigation__responsive-container-open,
.tt-header .wp-block-navigation__responsive-container-open svg,
.tt-header .wp-block-navigation__responsive-container-close,
.tt-header .wp-block-navigation__responsive-container-close svg {
	color: #fff;
	fill: currentColor;
}

.tt-header .wp-block-navigation__responsive-container-open {
	min-inline-size: 44px;
	min-block-size: 44px;
	align-items: center;
	justify-content: center;
}
