/*
Theme Name: TechinSecurity
Author: Dincer Tekin
Author URI: https://dincertekin.com
Description: Custom lightweight theme for techinsecurity.com: landing page with hand-built 3D scenes, contact form, blog and a built-in maintenance page. Scripts are small and optional; the site stays fully usable without them.
Version: 3.2.0
Requires at least: 6.6
Requires PHP: 8.0
Text Domain: techinsecurity
*/

:root {
	--navy: #0B2545;
	--ink: #06152B;       /* Deepest surface: footer and code blocks. */
	--navy-up: #143760;   /* A step lighter than navy, for hover and raised surfaces. */
	--blue: #134074;
	--teal: #1B998B;      /* Decorative only: too light for small text on white. */
	--teal-ink: #127368;
	--mint: #5EE6D4;      /* Accent on navy only. */
	--coral: #FF6B57;     /* Attackers and attention. Large text or fills only on light surfaces. */
	--danger: #FF8A7A;    /* Errors on navy. */
	--alert-ink: #8F1D10; /* Errors on mint. */
	--mist: #EEF3F8;
	--paper: #F6F4EF;     /* The light surface. */
	--paper-deep: #E9E5DB;
	--hair: #D9D4C7;      /* Hairlines on paper. */
	--field-edge: #8A8574;      /* 3:1 on paper. */
	--field-edge-dark: #6E8CAD; /* 3:1 on navy. */
	--line: #CBD8E6;
	--rule: rgba(203, 216, 230, .25);   /* Hairlines on navy. */
	--muted: #4F6178;
	--font-body: "IBM Plex Sans", system-ui, sans-serif;
	--font-heading: "Bricolage Grotesque", system-ui, sans-serif;
	--font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	--ease: cubic-bezier(.16, 1, .3, 1);
	--underline: .25em;
}

/* Base */
*, *::before, *::after { box-sizing: border-box; }
html { overflow-x: clip; scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
	margin: 0;
	display: flex;
	flex-direction: column;
	min-height: 100vh;
	background: var(--paper);
	color: var(--navy);
	font-family: var(--font-body);
	font-size: 1.0625rem;
	line-height: 1.6;
}
.site-main { flex: 1; }
h1, h2, h3, h4 {
	margin: 0;
	font-family: var(--font-heading);
	font-weight: 700;
	line-height: 1.15;
	letter-spacing: -.015em;
	overflow-wrap: break-word;
}
p { margin: 0; }
img { max-width: 100%; height: auto; }
a { color: var(--blue); }
strong, b { font-weight: 500; }
button { font: inherit; }
::selection { background: var(--mint); color: var(--navy); }
:focus-visible { outline: 2px solid var(--teal-ink); outline-offset: 3px; }
[id] { scroll-margin-top: 104px; }
[hidden] { display: none !important; }

.wrap { width: min(1120px, 100% - 48px); margin-inline: auto; }
.wrap--text { width: min(720px, 100% - 48px); }

.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}
.skip-link {
	position: absolute;
	left: 16px;
	top: -64px;
	z-index: 20;
	padding: 10px 16px;
	background: var(--navy);
	color: #fff;
}
.skip-link:focus { top: 16px; }

/* Dark surfaces share their link, focus and text colors. */
.site-header, .stage, .page-head, .article-head, .not-found, .site-footer { --focus: var(--mint); }
.site-header :focus-visible, .stage :focus-visible, .page-head :focus-visible,
.article-head :focus-visible, .not-found :focus-visible, .site-footer :focus-visible { outline-color: var(--focus); }
.site-header .sub-menu :focus-visible { outline-color: var(--teal-ink); }

/* Header: hides while scrolling down, returns on the way up. */
.site-header {
	position: sticky;
	top: var(--wp-admin--admin-bar--height, 0px);
	z-index: 10;
	border-bottom: 1px solid var(--rule);
	background: var(--navy);
	transition: transform .5s var(--ease);
}
/* On the landing page the header and the hero read as one surface. */
.home .site-header { border-bottom-color: transparent; }
.site-header.is-hidden { transform: translateY(-101%); }
.site-header::after {
	content: "";
	position: absolute;
	inset: auto 0 -1px;
	height: 2px;
	background: var(--mint);
	transform: scaleX(0);
	transform-origin: left;
}
@supports (animation-timeline: scroll()) {
	.site-header::after { animation: tis-grow linear both; animation-timeline: scroll(root); }

	/* Articles: a reading progress line that stays visible while the header is away. */
	.single-post .site-header::after { display: none; }
	.single-post::before {
		content: "";
		position: fixed;
		inset: var(--wp-admin--admin-bar--height, 0px) 0 auto;
		z-index: 11;
		height: 3px;
		background: var(--teal);
		transform-origin: left;
		animation: tis-grow linear both;
		animation-timeline: scroll(root);
	}
}
@keyframes tis-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes tis-grow-y { from { transform: scaleY(0); } to { transform: scaleY(1); } }

.site-header__inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0 32px;
}
.brand { display: block; max-width: 100%; padding-block: 20px; }
.brand img { display: block; height: 32px; width: auto; transition: transform .6s var(--ease); }
.brand:hover img { transform: translateX(3px); }

.nav-list {
	display: flex;
	gap: 32px;
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: 1rem;
}
.nav-list > li { position: relative; }
.nav-list > li > a,
.nav-list summary {
	position: relative;
	display: flex;
	align-items: center;
	gap: 8px;
	min-height: 44px;
	color: #fff;
	text-decoration: none;
	cursor: pointer;
}
.nav-list > li > a::before,
.nav-list summary::before {
	content: "";
	position: absolute;
	inset: auto 0 6px;
	height: 1px;
	background: currentColor;
	transform: scaleX(0);
	transform-origin: right;
	transition: transform .5s var(--ease);
}
.nav-list > li > a:hover::before,
.nav-list summary:hover::before,
.nav-list details[open] > summary::before { transform: scaleX(1); transform-origin: left; }

/* Dropdowns. Closing animates where ::details-content exists; elsewhere it is instant. */
.nav-list summary { list-style: none; -webkit-tap-highlight-color: transparent; }
.nav-list summary::-webkit-details-marker { display: none; }
.nav-list summary::after {
	content: "";
	width: 6px;
	height: 6px;
	margin-top: -3px;
	border-right: 1px solid currentColor;
	border-bottom: 1px solid currentColor;
	transform: rotate(45deg);
	transition: transform .4s var(--ease), margin .4s var(--ease);
}
.nav-list details[open] > summary::after { margin-top: 3px; transform: rotate(225deg); }
.nav-list details::details-content { transition: content-visibility .14s allow-discrete; }

/* The panel fades and settles as one piece, so it never shows as an empty bright box. */
.sub-menu {
	position: absolute;
	top: 100%;
	right: 0;
	width: 376px;
	margin: 14px 0 0;
	padding: 8px;
	background: var(--paper);
	box-shadow: 0 16px 32px rgba(6, 21, 43, .35);
	list-style: none;
	opacity: 0;
	transform: translateY(-6px);
	transition: opacity .14s, transform .14s;
}
/* A closing panel must not catch the mouse, or passing over it would reopen it. */
.nav-list details:not([open]) .sub-menu { pointer-events: none; }
.nav-list details[open] .sub-menu {
	opacity: 1;
	transform: none;
	transition: opacity .18s ease-out, transform .35s var(--ease);
}
@starting-style {
	.nav-list details[open] .sub-menu { opacity: 0; transform: translateY(-6px); }
}
/* Panels open from their label wherever they fit inside the page width, and otherwise from
   its right edge. Counted from the end, so the last items are the ones that stay right-aligned. */
@media (min-width: 768px) {
	.nav-list > li:nth-last-child(n+4) .sub-menu { left: 0; right: auto; }
	/* Keeps the pointer inside the menu while crossing the gap from the label. */
	.nav-list details[open]::after {
		content: "";
		position: absolute;
		inset: 100% 0 auto;
		height: 16px;
	}
}
@media (min-width: 1340px) {
	.nav-list > li:nth-last-child(n+3) .sub-menu { left: 0; right: auto; }
}
/* Short screens, such as a phone on its side: the panel scrolls rather than running off. */
@media (max-height: 520px) {
	.sub-menu { max-height: calc(100svh - 120px); overflow-y: auto; overscroll-behavior: contain; }
}
/* Moving from one open menu to another swaps the panels with no animation (see site.js). */
.is-switching .sub-menu,
.is-switching .sub-menu li,
.is-switching .sub-menu .icon > *,
.is-switching details::details-content { transition: none !important; }
.sub-menu li {
	opacity: 0;
	transition: opacity .1s;
}
.nav-list details[open] .sub-menu li {
	opacity: 1;
	transition: opacity .22s ease-out;
}
.nav-list details[open] .sub-menu li:nth-child(2) { transition-delay: 25ms; }
.nav-list details[open] .sub-menu li:nth-child(3) { transition-delay: 50ms; }
.nav-list details[open] .sub-menu li:nth-child(n+4) { transition-delay: 75ms; }
@starting-style {
	.nav-list details[open] .sub-menu li { opacity: 0; }
}
.sub-menu a {
	display: flex;
	align-items: center;
	gap: 16px;
	padding: 12px;
	color: var(--navy);
	text-decoration: none;
	transition: background-color .25s;
}
.sub-menu a:hover { background: var(--paper-deep); }
.sub-menu a:focus-visible { outline-offset: -2px; }
.sub-menu__icon {
	flex: none;
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	background: var(--navy);
	color: var(--mint);
	transition: background-color .3s, color .3s;
}
.sub-menu a:hover .sub-menu__icon { background: var(--mint); color: var(--navy); }
.sub-menu__icon .icon { transition: transform .6s var(--ease); }
.sub-menu a:hover .icon { transform: scale(1.12) rotate(-4deg); }
/* Icons draw their own lines as the panel opens. */
.sub-menu .icon > * {
	stroke-dasharray: 1;
	stroke-dashoffset: 1;
	transition: stroke-dashoffset .1s;
}
.nav-list details[open] .icon > * {
	stroke-dashoffset: 0;
	transition: stroke-dashoffset .5s .04s var(--ease);
}
@starting-style {
	.nav-list details[open] .icon > * { stroke-dashoffset: 1; }
}
/* No transform here: moving text onto its own layer makes it visibly re-render on hover. */
.sub-menu__text { min-width: 0; }
.sub-menu__title { display: block; font-size: .9375rem; font-weight: 500; line-height: 1.3; }
.sub-menu__note { display: block; margin-top: 2px; color: var(--muted); font-size: .8125rem; line-height: 1.35; }

/* Fades content in as it scrolls into view. No script, and browsers without support just show it. */
@supports (animation-timeline: view()) {
	[data-reveal] { animation: tis-in linear both; animation-timeline: view(); animation-range: entry 0% entry 40%; }
}
@keyframes tis-in { from { opacity: 0; transform: translateY(28px); } }

/* Buttons */
.btn {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 14px;
	min-height: 44px;
	padding: 10px 20px;
	border: 1px solid var(--navy);
	background: var(--navy);
	color: #fff;
	font: 500 1rem/1.3 var(--font-body);
	text-decoration: none;
	cursor: pointer;
	transition: color .4s var(--ease);
}
.btn::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: var(--mint);
	transform: translateY(101%);
	transition: transform .6s var(--ease);
}
.btn:hover { color: var(--navy); }
.btn:hover::before { transform: none; }
.btn svg { width: 18px; height: 18px; transition: transform .6s var(--ease); }
.btn:hover svg { transform: translateX(5px); }
.btn[disabled] { opacity: .6; cursor: progress; }
.btn--light { padding: 15px 24px; border-color: #fff; background: #fff; color: var(--navy); }

.text-link {
	color: inherit;
	text-decoration-thickness: 1px;
	text-underline-offset: var(--underline);
}
.text-link:hover { color: var(--teal-ink); }

.section { padding-block: clamp(56px, 8vw, 96px); }
.section-title { font-size: clamp(1.5rem, 2.6vw, 2rem); letter-spacing: -.02em; }
.section-head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 8px 24px;
}

/* Word-by-word headline rise, in CSS so it runs before any script. Short, to protect LCP. */
.rise { text-wrap: balance; }
.rise .w {
	display: inline-block;
	overflow: clip;
	padding: 0 .05em .16em 0;
	margin: 0 -.05em -.16em 0;
	vertical-align: top;
}
.rise .w > span {
	display: inline-block;
	animation: tis-rise .8s var(--ease) both;
	animation-delay: calc(var(--i) * 45ms);
}
@keyframes tis-rise { from { transform: translateY(115%); } }

/* Landing: the stage. The scene stays pinned while the hero and each service scroll past. */
.stage {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1.12fr);
	background: var(--navy);
	color: #fff;
}
.stage__copy { min-width: 0; padding-inline: max(24px, calc((100vw - 1120px) / 2)) 32px; }
.stage__scene {
	position: sticky;
	top: 0;
	order: 2;
	height: 100vh;
	height: 100svh;
	contain: strict;
	/* Soft edge where the scene meets the copy, for when the camera moves in close. */
	mask-image: linear-gradient(90deg, transparent, #000 8%);
}
.stage__scene canvas,
.stage__scene img,
.not-found__scene canvas { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: contain; }

.hero {
	display: flex;
	flex-direction: column;
	justify-content: center;
	min-height: calc(100vh - 73px);
	min-height: calc(100svh - 73px);
	padding-block: 48px;
}
.hero h1 { font-size: clamp(2.75rem, 6vw, 5.5rem); line-height: 1.02; letter-spacing: -.03em; }
/* "They" takes the colour of the attackers in the scene beside it. */
.hero h1 .w--alert > span { color: var(--coral); }
.hero__lead { margin-top: 28px; max-width: 46ch; color: var(--line); font-size: 1.125rem; line-height: 1.5; }
.hero__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 28px; margin-top: 36px; }
.hero__more {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	color: #fff;
	text-decoration-thickness: 1px;
	text-underline-offset: var(--underline);
	transition: color .25s;
}
.hero__more:hover { color: var(--mint); }

.steps { padding-bottom: 12vh; }
.steps__label { padding-top: 32px; border-top: 1px solid var(--rule); color: var(--mint); font: 500 1rem/1.5 var(--font-body); letter-spacing: 0; }
.step {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 14px;
	min-height: 74vh;
	min-height: 74svh;
	transition: opacity .6s var(--ease);
}
.step h3 { font-size: clamp(1.625rem, 3vw, 2.5rem); line-height: 1.08; letter-spacing: -.02em; }
.step p { max-width: 46ch; color: var(--line); font-size: 1.125rem; line-height: 1.5; }
.step__scope { max-width: 46ch; margin: 10px 0 0; padding: 0; list-style: none; font-size: .9375rem; }
.step__scope li { display: flex; align-items: center; gap: 12px; padding-block: 9px; border-top: 1px solid var(--rule); }
.step__scope li:last-child { border-bottom: 1px solid var(--rule); }
.step__more {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	width: fit-content;
	min-height: 44px;
	color: #fff;
	text-decoration-thickness: 1px;
	text-underline-offset: var(--underline);
	transition: color .25s;
}
.step__more:hover { color: var(--mint); }
.step__more .icon { width: 18px; height: 18px; transition: transform .6s var(--ease); }
.step__more:hover .icon { transform: translateX(5px); }
.step__scope .icon { flex: none; width: 16px; height: 16px; color: var(--mint); }
.is-live .step:not(.is-active) { opacity: .32; }

.section--plain .text-link { display: inline-flex; align-items: center; min-height: 44px; }

/* Landing: open-source projects. */
.projects-band { padding-block: clamp(72px, 10vw, 128px); background: var(--ink); color: #fff; }
.projects-band :focus-visible { outline-color: var(--mint); }
.projects-band__all { display: inline-flex; align-items: center; min-height: 44px; color: #fff; text-decoration-thickness: 1px; text-underline-offset: var(--underline); transition: color .25s; }
.projects-band__all:hover { color: var(--mint); }
.projects-band .process__title { max-width: 18ch; }

/* Project cards. The name's link covers the whole card. */
.project-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
	gap: 24px;
	margin: clamp(32px, 5vw, 56px) 0 0;
	padding: 0;
	list-style: none;
}
.project-card {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 12px;
	min-width: 0;
	padding: 28px;
	border: 1px solid var(--hair);
	background: #fff;
	transition: border-color .3s, transform .6s var(--ease);
}
.project-card:hover { border-color: var(--navy); transform: translateY(-4px); }
.project-card:focus-within { outline: 2px solid var(--teal-ink); outline-offset: 3px; }
.project-card a:focus-visible { outline: none; }
.project-card__icon { display: grid; place-items: center; width: 44px; height: 44px; background: var(--navy); color: var(--mint); }
.project-card h2, .project-card h3 { margin-top: 8px; font-size: 1.625rem; letter-spacing: -.02em; }
.project-card h2 a, .project-card h3 a { color: inherit; text-decoration: none; }
.project-card h2 a::before, .project-card h3 a::before { content: ""; position: absolute; inset: 0; }
.project-card p { flex: 1; color: var(--muted); font-size: 1rem; line-height: 1.5; }
.project-meta { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: 4px 0 0; padding: 0; color: var(--muted); font-size: .875rem; list-style: none; }
.project-meta__status { color: var(--teal-ink); font-weight: 500; }
.projects-band .project-card { border-color: var(--rule); background: var(--navy); color: #fff; }
.projects-band .project-card:hover { border-color: var(--mint); }
.projects-band .project-card:focus-within { outline-color: var(--mint); }
.projects-band .project-card__icon { background: var(--ink); }
.projects-band .project-card p, .projects-band .project-meta { color: var(--line); }
.projects-band .project-meta__status { color: var(--mint); }

/* Landing: how an engagement runs */
.process { padding-block: clamp(72px, 10vw, 128px); }
.process__title { max-width: 16ch; font-size: clamp(2.25rem, 4.6vw, 3.75rem); line-height: 1.03; letter-spacing: -.03em; text-wrap: balance; }
.process__list {
	position: relative;
	display: grid;
	grid-template-columns: repeat(5, minmax(0, 1fr));
	gap: 32px;
	margin: clamp(40px, 6vw, 72px) 0 0;
	padding: 0;
	list-style: none;
}
/* The line that joins the steps, drawn in as the section scrolls past. */
.process__list::before,
.process__list::after {
	content: "";
	position: absolute;
	/* Stops at the last icon: one column short of the right edge. */
	inset: 22px calc((100% - 128px) / 5) auto 0;
	height: 1px;
	background: var(--hair);
}
.process__list::after {
	height: 2px;
	background: var(--teal-ink);
	transform-origin: left;
}
@supports (animation-timeline: view()) {
	.process__list::after {
		animation: tis-grow linear both;
		animation-timeline: view();
		animation-range: entry 60% cover 55%;
	}
}
.process__step { position: relative; z-index: 1; min-width: 0; }
.process__icon {
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	margin-bottom: 20px;
	background: var(--navy);
	color: var(--mint);
}
/* Testing is the attack, so it takes the attackers' colour from the 3D scene. */
.process__step--attack .process__icon { background: var(--coral); color: var(--navy); }
.process__step h3 { font-family: var(--font-body); font-size: 1.25rem; font-weight: 500; letter-spacing: 0; line-height: 1.3; }
.process__step p { margin-top: 8px; color: var(--muted); font-size: 1rem; line-height: 1.5; }

/* Landing: latest writing, when there is enough of it. */
.section--plain { border-top: 1px solid var(--hair); }

/* Landing: contact. The one full-colour surface on the site. */
.contact {
	padding-block: clamp(72px, 10vw, 128px) clamp(56px, 7vw, 88px);
	background: var(--mint);
	color: var(--navy);
}
.contact ::selection { background: var(--navy); color: #fff; }
.contact :focus-visible { outline-color: var(--navy); }
.contact__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	gap: 48px clamp(40px, 7vw, 96px);
}
.contact__intro { min-width: 0; }
.contact__title { font-size: clamp(2.25rem, 4.6vw, 3.75rem); line-height: 1.03; letter-spacing: -.03em; text-wrap: balance; }
.contact__lead { margin-top: 24px; max-width: 42ch; font-size: 1.125rem; line-height: 1.5; }
.contact__promise {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-top: 28px;
	font-weight: 500;
}
.contact__promise .icon { flex: none; width: 20px; height: 20px; }
.contact__mail { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; margin-top: 8px; }
.contact__mail a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	color: inherit;
	text-decoration-thickness: 1px;
	text-underline-offset: var(--underline);
	overflow-wrap: anywhere;
}
.contact__mail a:hover { text-decoration-thickness: 2px; }
.copy-button {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-height: 44px;
	padding: 0 12px;
	border: 1px solid var(--navy);
	background: none;
	color: var(--navy);
	font-size: .875rem;
	cursor: pointer;
	transition: color .25s, background-color .25s;
}
.copy-button:hover, .copy-button.is-done { background: var(--navy); color: var(--mint); }
.copy-button .icon { width: 16px; height: 16px; }
.contact-form {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	align-content: start;
	gap: 24px;
}
.contact-form__trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.field { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.field:nth-of-type(2), .field--wide { grid-column: 1 / -1; }
.field label { font-size: .9375rem; font-weight: 500; }
.field__optional { font-weight: 400; }
/* 16px text stops iPhones zooming the page when a field gets focus. */
.field input,
.field textarea {
	width: 100%;
	min-height: 48px;
	padding: 12px 14px;
	border: 1px solid var(--navy);
	border-radius: 0;
	background: #fff;
	color: var(--navy);
	font: 400 1rem/1.5 var(--font-body);
	transition: box-shadow .25s;
}
.field textarea { resize: vertical; }
.field input:hover, .field textarea:hover { box-shadow: inset 0 0 0 1px var(--navy); }
.field input:focus, .field textarea:focus { outline: 2px solid var(--navy); outline-offset: 0; }
.field [aria-invalid="true"] { border-color: var(--alert-ink); box-shadow: inset 0 0 0 1px var(--alert-ink); }
.field__error { color: var(--alert-ink); font-size: .875rem; font-weight: 500; }
.contact .btn { padding: 15px 24px; }
.contact .btn::before { background: #fff; }
.contact-form__foot { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px; }
.contact-form__privacy { flex: 1 1 200px; font-size: .875rem; }
.contact-form__privacy a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: var(--underline); white-space: nowrap; }
.contact-form__privacy a:hover { text-decoration-thickness: 2px; }
.contact-form__status { grid-column: 1 / -1; font-weight: 500; }
.contact-form__status:empty { display: none; }
.contact-form__status:focus { outline: none; }
.contact-form__status.is-ok { color: var(--navy); animation: tis-note .7s var(--ease); }
.contact-form__status.is-error { color: var(--alert-ink); animation: tis-note .7s var(--ease); }
@keyframes tis-note { from { opacity: 0; transform: translateY(8px); } }

/* Service and project pages */
.section-head-page { padding-block: clamp(40px, 6vw, 72px) clamp(48px, 7vw, 88px); background: var(--navy); color: #fff; }
.section-head-page :focus-visible { outline-color: var(--mint); }
.section-head-page__back { display: inline-flex; align-items: center; min-height: 44px; margin-bottom: 20px; color: var(--line); font-size: .9375rem; text-decoration: none; transition: color .25s; }
.section-head-page__back::before { content: "\2190"; margin-right: 8px; transition: transform .5s var(--ease); }
.section-head-page__back:hover { color: #fff; }
.section-head-page__back:hover::before { transform: translateX(-4px); }
.section-head-page__icon { display: grid; place-items: center; width: 56px; height: 56px; margin-bottom: 24px; background: var(--mint); color: var(--navy); }
.section-head-page h1 { max-width: 18ch; font-size: clamp(2.5rem, 6vw, 4.5rem); line-height: 1.02; letter-spacing: -.03em; }
.section-head-page__lead { margin-top: 24px; max-width: 58ch; color: var(--line); font-size: 1.25rem; line-height: 1.45; }
.section-head-page__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; margin-top: 32px; }
.section-head-page .btn { padding: 15px 24px; border-color: #fff; background: #fff; color: var(--navy); }
.section-head-page .project-meta { margin-top: 24px; color: var(--line); font-size: .9375rem; }
.section-head-page .project-meta__status { color: var(--mint); }

.page-split {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 300px;
	gap: 24px clamp(40px, 7vw, 96px);
	align-items: start;
}
.page-split .prose { max-width: 720px; }
.page-aside { position: sticky; top: 96px; /* Clear of the header when it returns. */ margin-block: clamp(40px, 6vw, 72px); padding-top: 20px; border-top: 2px solid var(--navy); }
.page-aside h2 { font-family: var(--font-body); font-size: 1rem; font-weight: 500; letter-spacing: 0; }
.page-aside ul { margin: 12px 0 0; padding: 0; list-style: none; font-size: .9375rem; }
.page-aside li { display: flex; gap: 10px; padding-block: 10px; border-top: 1px solid var(--hair); line-height: 1.4; }
.page-aside li .icon { flex: none; width: 16px; height: 16px; margin-top: 3px; color: var(--teal-ink); }
.page-aside .btn { width: 100%; margin-top: 20px; }

.service-list { margin: 0; padding: 0; border-top: 1px solid var(--navy); list-style: none; }
.service-row {
	position: relative;
	display: grid;
	grid-template-columns: 44px minmax(0, 1fr) 24px;
	gap: 8px 28px;
	align-items: start;
	padding-block: 32px;
	border-bottom: 1px solid var(--hair);
}
.service-row__icon { display: grid; place-items: center; width: 44px; height: 44px; background: var(--navy); color: var(--mint); transition: background-color .3s, color .3s; }
.service-row:hover .service-row__icon { background: var(--mint); color: var(--navy); }
.service-row h2 { font-size: clamp(1.375rem, 2.6vw, 1.875rem); letter-spacing: -.02em; }
.service-row h2 a { color: inherit; text-decoration: none; }
.service-row h2 a::before { content: ""; position: absolute; inset: 0; }
.service-row p { grid-column: 2; max-width: 62ch; color: var(--muted); }
.service-row__arrow { grid-column: 3; grid-row: 1; align-self: center; color: var(--teal-ink); opacity: 0; transform: translateX(-10px); transition: opacity .3s, transform .6s var(--ease); }
.service-row:hover .service-row__arrow { opacity: 1; transform: none; }
.service-row__arrow .icon { display: block; }

.other-services { padding-block: clamp(40px, 6vw, 64px); border-top: 1px solid var(--hair); }
.other-services h2 { font-family: var(--font-body); font-size: 1rem; font-weight: 500; letter-spacing: 0; }
.other-services ul { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: 4px 32px; margin: 12px 0 0; padding: 0; list-style: none; }
.other-services a { display: flex; align-items: center; gap: 12px; min-height: 44px; color: var(--navy); text-decoration: none; transition: color .25s; }
.other-services a:hover { color: var(--teal-ink); }
.other-services .icon { flex: none; width: 20px; height: 20px; color: var(--teal-ink); }

.cta-band { padding-block: clamp(48px, 7vw, 80px); background: var(--mint); color: var(--navy); }
.cta-band ::selection { background: var(--navy); color: #fff; }
.cta-band :focus-visible { outline-color: var(--navy); }
.cta-band__inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 24px 48px; }
.cta-band h2 { flex: 1 1 340px; max-width: 22ch; font-size: clamp(1.75rem, 3.4vw, 2.75rem); line-height: 1.05; letter-spacing: -.025em; text-wrap: balance; }
.cta-band .btn { padding: 15px 24px; }
.cta-band .btn::before { background: #fff; }

/* Post lists */
.entry-list { border-top: 1px solid var(--navy); margin-top: 28px; }
.page-head + .section .entry-list { margin-top: 0; }
.entry-row {
	position: relative;
	display: grid;
	grid-template-columns: 150px minmax(0, 1fr) 24px;
	gap: 8px 32px;
	padding-block: 28px;
	border-bottom: 1px solid var(--hair);
}
.entry-row.has-post-thumbnail { grid-template-columns: 150px minmax(0, 1fr) 200px 24px; }
/* The rule draws across the row on hover. */
.entry-row::after {
	content: "";
	position: absolute;
	inset: auto 0 -1px;
	height: 1px;
	background: var(--teal-ink);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform .7s var(--ease);
}
.entry-row:hover::after { transform: scaleX(1); }
.entry-row__date { color: var(--muted); font-size: .9375rem; padding-top: 4px; }
.entry-row__title { font-size: 1.375rem; letter-spacing: -.01em; }
.entry-row__title a { color: var(--navy); text-decoration: none; transition: color .3s; }
/* The title's link covers the row, so the whole row is one big target. */
.entry-row__title a::before { content: ""; position: absolute; inset: 0; }
.entry-row:hover .entry-row__title a { color: var(--teal-ink); }
.entry-row__excerpt { margin-top: 8px; color: var(--muted); }
.entry-row__thumb img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
.entry-row__arrow { align-self: center; color: var(--teal-ink); opacity: 0; transform: translateX(-10px); transition: opacity .3s, transform .6s var(--ease); }
.entry-row:hover .entry-row__arrow { opacity: 1; transform: none; }
.entry-row__arrow .icon { display: block; }
.entry-meta {
	display: flex;
	flex-wrap: wrap;
	gap: 2px 16px;
	margin-top: 8px;
	color: var(--muted);
	font-size: .9375rem;
}
.entry-meta span:empty { display: none; }
.entry-meta__cat { position: relative; z-index: 1; color: var(--teal-ink); text-decoration: none; }
.entry-meta__cat:hover { text-decoration: underline; }
.empty { color: var(--muted); }

/* Blog header */
.page-head { padding-block: clamp(56px, 8vw, 104px) clamp(32px, 4vw, 48px); background: var(--navy); color: #fff; }
.page-head h1 { font-size: clamp(2.5rem, 6vw, 4.5rem); line-height: 1.02; letter-spacing: -.03em; }
.page-head__intro { margin-top: 16px; max-width: 60ch; color: var(--line); font-size: 1.125rem; }
.page-head__tools {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 16px 32px;
	margin-top: 36px;
}
.page-head__tools .search-form { margin-left: auto; }

.chips { display: flex; flex-wrap: wrap; gap: 4px 20px; margin: 0; padding: 0; list-style: none; font-size: .9375rem; }
.chips a { display: inline-flex; align-items: center; min-height: 44px; color: var(--muted); text-decoration: none; transition: color .25s; }
.chips a:hover { color: var(--teal-ink); }
.page-head .chips a { color: var(--line); }
.page-head .chips a:hover { color: var(--mint); }
.page-head .chips a[aria-current] { color: #fff; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: var(--underline); }

.search-form { display: flex; gap: 8px; max-width: 100%; }
.search-form input {
	min-width: 0;
	width: 220px;
	min-height: 44px;
	flex: 1 1 auto;
	padding: 9px 12px;
	border: 1px solid var(--field-edge);
	border-radius: 0;
	background: #fff;
	color: var(--navy);
	font: inherit;
	font-size: 1rem;
}
.page-head .search-form input, .not-found .search-form input { border-color: var(--field-edge-dark); background: var(--navy-up); color: #fff; }
.page-head .search-form input::placeholder, .not-found .search-form input::placeholder { color: var(--line); opacity: 1; }
.page-head .search-form input:focus, .not-found .search-form input:focus { border-color: var(--mint); outline: 1px solid var(--mint); outline-offset: 0; }
.page-head .btn, .not-found .btn { border-color: #fff; background: #fff; color: var(--navy); }

.pagination { margin-top: 36px; }
.pagination .nav-links { display: flex; flex-wrap: wrap; gap: 4px 16px; }
.pagination .page-numbers { display: inline-flex; align-items: center; min-height: 44px; min-width: 24px; color: var(--navy); text-decoration: none; }
.pagination a.page-numbers:hover { color: var(--teal-ink); }
.pagination .current { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: var(--underline); }

/* Article */
.article-head { padding-block: clamp(32px, 5vw, 56px) clamp(48px, 7vw, 88px); background: var(--navy); color: #fff; }
.article-head h1 { font-size: clamp(2.25rem, 5.4vw, 3.75rem); line-height: 1.04; letter-spacing: -.03em; }
.article-head .entry-meta { margin-top: 24px; color: var(--line); }
.article-head__back,
.article-head__cat {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	margin-bottom: 20px;
	color: var(--line);
	font-size: .9375rem;
	text-decoration: none;
	transition: color .25s;
}
.article-head__back::before { content: "\2190"; margin-right: 8px; transition: transform .5s var(--ease); }
.article-head__back:hover::before { transform: translateX(-4px); }
.article-head__cat { margin-left: 20px; color: var(--mint); }
.article-head__back:hover, .article-head__cat:hover { color: #fff; }
.article-image { margin-top: clamp(-64px, -5vw, -32px); }
.article-image img { display: block; width: 100%; }

.prose { padding-block: clamp(40px, 6vw, 72px); font-size: 1.1875rem; line-height: 1.7; }
.prose > * + * { margin-top: 1.4em; }
.prose h2 { margin-top: 2.2em; font-size: 1.875rem; line-height: 1.15; letter-spacing: -.02em; }
.prose h3 { margin-top: 1.9em; font-size: 1.4375rem; }
.prose h4 { margin-top: 1.6em; font-size: 1.1875rem; }
.prose h2 + *, .prose h3 + *, .prose h4 + * { margin-top: .7em; }
.prose ul, .prose ol { padding-left: 1.4em; }
.prose li + li { margin-top: .4em; }
.prose li::marker { color: var(--teal-ink); }
.prose a { color: var(--blue); text-decoration-thickness: 1px; text-underline-offset: 3px; transition: color .25s; }
.prose a:hover { color: var(--teal-ink); }
.prose blockquote {
	margin-inline: 0;
	padding-left: 24px;
	border-left: 3px solid var(--teal);
	font-family: var(--font-heading);
	font-size: 1.3125rem;
	font-weight: 700;
	line-height: 1.35;
	letter-spacing: -.01em;
}
.prose blockquote > * + * { margin-top: .8em; }
.prose hr { border: 0; border-top: 1px solid var(--hair); margin-block: 2.4em; }
.prose figure { margin-inline: 0; }
.prose figcaption, .prose .wp-element-caption { margin-top: 8px; color: var(--muted); font-size: .9375rem; }

.prose code {
	padding: .12em .36em;
	background: var(--paper-deep);
	font-family: var(--font-mono);
	font-size: .86em;
}
.prose pre {
	margin: 0;
	padding: 24px;
	overflow-x: auto;
	background: var(--ink);
	color: var(--mist);
	font-family: var(--font-mono);
	font-size: .9375rem;
	line-height: 1.65;
	tab-size: 4;
}
.prose pre code { padding: 0; background: none; color: inherit; font-size: inherit; }
/* Code colours, from the brand palette. All at least 7:1 on the code background. */
.t-k { color: var(--mint); }
.t-s { color: #FFB8AB; }
.t-f { color: #9CCBF7; }
.t-n { color: #F4DFA6; }
.t-c { color: #9DB0C5; }
.t-d { color: #FF9C8F; }
.prose > pre, .prose .wp-block-code, .code-frame { margin-block: 1.8em; }
.code-frame { position: relative; }
.code-frame pre { margin: 0; padding-right: 88px; }
.code-copy {
	position: absolute;
	top: 8px;
	right: 8px;
	min-height: 44px;
	padding: 0 14px;
	border: 1px solid var(--rule);
	background: var(--navy-up);
	color: var(--line);
	font-size: .8125rem;
	cursor: pointer;
	transition: color .25s, border-color .25s;
}
.code-copy:hover, .code-copy:focus-visible { border-color: var(--mint); color: var(--mint); outline-color: var(--mint); }

.prose table, .prose .wp-block-table table { width: 100%; border-collapse: collapse; font-size: 1rem; }
.prose .wp-block-table { overflow-x: auto; }
.prose th, .prose td { padding: 10px 12px; border: 0; border-bottom: 1px solid var(--hair); text-align: left; }
.prose th { border-bottom: 1px solid var(--navy); font-weight: 500; }

.prose .alignwide {
	width: min(1120px, 100vw - 48px);
	max-width: none;
	margin-inline: calc(50% - min(560px, 50vw - 24px));
}
.prose .alignfull { width: 100vw; max-width: none; margin-inline: calc(50% - 50vw); }
.prose .alignleft { float: left; margin: .3em 1.5em 1em 0; max-width: 50%; }
.prose .alignright { float: right; margin: .3em 0 1em 1.5em; max-width: 50%; }
.prose .aligncenter { margin-inline: auto; }
.prose::after { content: ""; display: table; clear: both; }

.article-tags { margin-bottom: 32px; }

.post-navigation { border-top: 1px solid var(--hair); padding-block: 24px; }
.post-navigation .nav-links {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
	gap: 20px 32px;
}
.post-navigation .nav-next { text-align: right; }
.post-navigation a { display: block; color: var(--navy); font-weight: 500; text-decoration: none; transition: color .25s; }
.post-navigation a:hover { color: var(--teal-ink); }
.post-nav__label { display: block; color: var(--muted); font-size: .875rem; font-weight: 400; }

.article-cta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 20px 32px;
	margin-block: 16px clamp(56px, 8vw, 96px);
	padding-top: 32px;
	border-top: 1px solid var(--navy);
}
.article-cta__title { flex: 1 1 280px; font-family: var(--font-heading); font-size: 1.5rem; font-weight: 700; line-height: 1.15; letter-spacing: -.02em; }

/* 404 */
.not-found {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
	min-height: calc(100vh - 73px);
	min-height: calc(100svh - 73px);
	background: var(--navy);
	color: #fff;
}
.not-found__copy {
	align-self: center;
	min-width: 0;
	padding-block: 48px;
	padding-inline: max(24px, calc((100vw - 1120px) / 2)) 32px;
}
.not-found__code { margin-bottom: 16px; color: var(--mint); font-weight: 500; }
.not-found h1 { font-size: clamp(2.5rem, 5.6vw, 4.75rem); line-height: 1.02; letter-spacing: -.03em; }
.not-found__text { margin-top: 20px; max-width: 42ch; color: var(--line); font-size: 1.125rem; line-height: 1.5; }
.not-found .search-form { margin-top: 28px; max-width: 440px; }
.not-found__home {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	margin-top: 12px;
	color: #fff;
	text-decoration-thickness: 1px;
	text-underline-offset: var(--underline);
	transition: color .25s;
}
.not-found__home:hover { color: var(--mint); }
.not-found__scene { position: relative; min-height: 320px; contain: strict; }

/* Footer */
.site-footer { padding-block: clamp(48px, 6vw, 72px) 24px; background: var(--ink); color: var(--line); font-size: .9375rem; }
.site-footer__inner {
	display: grid;
	grid-template-columns: 1.5fr 1.2fr 1fr 1.1fr;
	gap: 40px 32px;
}
.site-footer__brand > a { display: inline-block; margin-bottom: 8px; padding-block: 8px; }
.site-footer__brand img { display: block; height: 28px; width: auto; }
.site-footer__motto { color: #fff; }
.site-footer__title { margin-bottom: 8px; color: #fff; font-weight: 500; }
.site-footer ul { margin: 0; padding: 0; list-style: none; }
.site-footer a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: var(--underline); transition: color .25s; }
.site-footer a:hover { color: var(--mint); }
.site-footer__col li a { display: inline-block; padding-block: 5px; text-decoration: none; }
.site-footer__col li a:hover { text-decoration: underline; }
.site-footer__note { display: inline-block; padding-block: 5px; color: var(--mint); }
.site-footer__copy { grid-column: 1 / -1; padding-top: 24px; border-top: 1px solid var(--rule); font-size: .875rem; }

/* Touch screens: every link gets a comfortable target. */
@media (pointer: coarse) {
	.site-footer__col li a,
	.site-footer__brand p a,
	.contact-form__privacy a,
	.text-link {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
		padding-block: 0;
	}
}

@media (max-width: 960px) {
	.site-footer__inner { grid-template-columns: 1fr 1fr; }
	.site-footer__brand { grid-column: 1 / -1; }
	.site-footer__col:last-of-type { grid-column: 1 / -1; }
}

@media (max-width: 820px) {
	/* The scene pins to the top of the screen and the copy scrolls beneath it. */
	.stage { grid-template-columns: minmax(0, 1fr); }
	.stage__scene { z-index: 1; order: -1; height: 42vh; height: 42svh; background: var(--navy); mask-image: none; }
	.stage__copy { padding-inline: 24px; }
	.hero { min-height: 0; padding-block: 8px 72px; }
	.steps { padding-bottom: 28vh; }
	.step { justify-content: flex-start; min-height: 46vh; min-height: 46svh; padding-top: 36px; }
	.step, .steps { scroll-margin-top: 44svh; }

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

	.page-split { grid-template-columns: minmax(0, 1fr); }
	.page-aside { position: static; order: -1; margin-block: 40px 0; }
	.page-split .prose { padding-top: 32px; }

	/* The process stacks, and its line runs down through the icons. */
	.process__list { grid-template-columns: minmax(0, 1fr); gap: 28px; }
	.process__list::before, .process__list::after { inset: 0 auto 0 22px; width: 1px; height: auto; }
	.process__list::after { width: 2px; transform-origin: top; animation-name: tis-grow-y; }
	.process__step { display: grid; grid-template-columns: 44px minmax(0, 1fr); column-gap: 20px; }
	.process__step:last-child { background: var(--paper); } /* Ends the line at the last icon. */
	.process__icon { grid-row: span 2; margin-bottom: 0; }
	.process__step h3 { align-self: center; }
	.process__step p { grid-column: 2; }

	.not-found { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(240px, 36svh) auto; min-height: 0; }
	.not-found__scene { order: -1; min-height: 0; }
	.not-found__copy { padding: 8px 24px 56px; }

	.entry-row, .entry-row.has-post-thumbnail { grid-template-columns: minmax(0, 1fr); }
	.entry-row__date { padding-top: 0; }
	.entry-row__thumb { order: -1; }
	.entry-row__arrow { display: none; }
	.post-navigation .nav-next { text-align: left; }
	.page-head__tools .search-form { margin-left: 0; width: 100%; }
	.search-form input { width: auto; }
	.prose { font-size: 1.125rem; }
	.code-frame pre { padding-top: 60px; padding-right: 24px; } /* Code scrolls sideways here, so it must clear the copy button. */
	.prose .alignleft, .prose .alignright { float: none; margin: 1.3em 0 0; max-width: 100%; }
}

/* Logo and menu stack once four menu items no longer fit beside the logo. Dropdowns then span
   the header, so they always fit the screen. */
@media (max-width: 767px) {
	.brand { padding-block: 14px 0; }
	.site-nav { width: 100%; padding-bottom: 4px; }
	.nav-list { gap: 0 18px; font-size: .9375rem; }
	.nav-list summary { gap: 5px; }
	.nav-list > li { position: static; }
	.sub-menu {
		left: 0;
		right: 0;
		width: auto;
		margin: 0;
		padding: 8px 12px;
		box-shadow: 0 24px 32px rgba(6, 21, 43, .4);
	}
}

@media (max-width: 640px) {
	.contact-form { grid-template-columns: minmax(0, 1fr); }
	.field:nth-of-type(n) { grid-column: 1 / -1; }
	.contact-form .btn { width: 100%; }
	.site-footer__inner { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 380px) {
	.nav-list { gap: 0 14px; font-size: .875rem; }
}

/* The narrowest phones: the arrows go, so all four items still fit one line. */
@media (max-width: 345px) {
	.nav-list { gap: 0 12px; }
	.nav-list summary::after { display: none; }
}

@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	*, *::before, *::after {
		animation: none !important;
		transition: none !important;
	}
	.site-header.is-hidden { transform: none; }
	.single-post::before { display: none; }
}
