/*
Theme Name: K3Y Theme
Theme URI: https://k3ylabs.com/
Author: K3Y Labs
Author URI: https://k3ylabs.com/
Description: A lightweight, secure, accessibility-minded starter for custom K3Y WordPress builds.
Version: 1.0.0
Update URI: https://k3ylabs.com/themes/k3y-theme/
Requires at least: 6.6
Tested up to: 7.1
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: k3y-theme
Tags: custom-logo, custom-menu, featured-images, threaded-comments, translation-ready, accessibility-ready
*/

/* =============================================================================
 * K3Y design system
 *
 * Art direction: hexagonal system, corporate light.
 * The hexagon and the dark-to-violet gradient are taken from the K3Y logo mark;
 * they are the brand's own geometry, not decoration invented for this site.
 * Brand values #5e009c / #c900ff / #090816 are the ones already used in
 * production on k3ylabs.com.
 * ========================================================================== */

@font-face {
	font-family: "Sora";
	src: url("assets/fonts/sora-var.woff2") format("woff2");
	font-weight: 100 800;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Inter";
	src: url("assets/fonts/inter-var.woff2") format("woff2");
	font-weight: 100 900;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "IBM Plex Mono";
	src: url("assets/fonts/plex-mono-400.woff2") format("woff2");
	font-weight: 400;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "IBM Plex Mono";
	src: url("assets/fonts/plex-mono-500.woff2") format("woff2");
	font-weight: 500;
	font-style: normal;
	font-display: swap;
}

:root {
	/* Brand — lifted directly from the production K3Y stylesheet and logo. */
	--k3y-brand: #5e009c;
	--k3y-brand-vivid: #c900ff;
	--k3y-brand-deep: #3d0066;
	--k3y-brand-ink: #090816;
	--k3y-gradient: linear-gradient(135deg, #090816 0%, #5e009c 55%, #c900ff 100%);
	--k3y-gradient-soft: linear-gradient(135deg, #5e009c 0%, #c900ff 100%);
	/* Text-safe gradient: white stays AA on every stop. #c900ff is for fills only. */
	--k3y-gradient-btn: linear-gradient(135deg, #5e009c 0%, #a000ec 100%);
	/* Band gradient stops short of #c900ff so body text stays AA over every stop. */
	--k3y-gradient-band: linear-gradient(135deg, #090816 0%, #5e009c 58%, #9500e0 100%);
	--k3y-gradient-btn-hover: linear-gradient(135deg, #7a00c8 0%, #a000ec 100%);

	/* Ground */
	--k3y-ground: #faf9fc;
	--k3y-surface: #ffffff;
	--k3y-surface-2: #f4f2f9;
	--k3y-line: #e7e3f0;
	--k3y-line-strong: #d5cee6;

	/* Ink */
	--k3y-ink: #0d0a1f;
	--k3y-ink-2: #2a2540;
	--k3y-body: #4a4560;
	--k3y-muted: #6b6584;
	--k3y-on-brand: #ffffff;

	/* Type */
	--k3y-font-display: "Sora", "Inter", system-ui, sans-serif;
	--k3y-font-body: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
	--k3y-font-mono: "IBM Plex Mono", ui-monospace, Consolas, monospace;

	/* Measure */
	--k3y-content: 720px;
	--k3y-wide: 1280px;
	--k3y-gutter: clamp(1.25rem, 4vw, 3rem);
	--k3y-radius: 14px;
	--k3y-radius-lg: 22px;
	--k3y-section: clamp(4.5rem, 10vw, 9rem);
	/* Rendered height of .site-header (1.4rem padding-block + the pill's 3.9rem
	 * min-height + its 2px border). The header floats over the hero on its
	 * negative margin, so anything sitting directly under it pads its top by
	 * this much instead. */
	--k3y-header-h: 5.425rem;

	/* Elevation — soft, purple-tinted, never grey. */
	--k3y-shadow-sm: 0 1px 2px rgb(13 10 31 / 4%), 0 2px 8px rgb(94 0 156 / 5%);
	--k3y-shadow: 0 2px 6px rgb(13 10 31 / 5%), 0 12px 32px rgb(94 0 156 / 8%);
	--k3y-shadow-lg: 0 4px 12px rgb(13 10 31 / 6%), 0 28px 64px rgb(94 0 156 / 14%);

	/* Honeycomb texture, built from the same hexagon as the logo mark. */
	--k3y-honeycomb: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='34' height='30' viewBox='0 0 34 30'%3E%3Cpath d='M17 1 32 9.5v17L17 35 2 26.5v-17z' fill='none' stroke='%23c900ff' stroke-opacity='.38' stroke-width='1.1'/%3E%3Cpath d='M0 -14 15 -5.5v17L0 20l-15-8.5v-17z' fill='none' stroke='%23c900ff' stroke-opacity='.3' stroke-width='1.1'/%3E%3C/svg%3E");

	/* Motion */
	--k3y-ease: cubic-bezier(0.22, 1, 0.36, 1);
	--k3y-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
	--k3y-dur: 480ms;
	--k3y-dur-fast: 220ms;

	color-scheme: light;
}

[data-theme="dark"] {
	--k3y-ground: #08070f;
	--k3y-surface: #100d1c;
	--k3y-surface-2: #16121f;
	--k3y-line: #251f36;
	--k3y-line-strong: #342c4a;

	--k3y-ink: #f4f2fa;
	--k3y-ink-2: #ded9ec;
	--k3y-body: #b3adc7;
	--k3y-muted: #8a83a3;

	--k3y-brand: #b26bff;
	--k3y-brand-vivid: #d98cff;
	--k3y-brand-deep: #c9a3ff;

	--k3y-shadow-sm: 0 1px 2px rgb(0 0 0 / 40%);
	--k3y-shadow: 0 2px 6px rgb(0 0 0 / 45%), 0 12px 32px rgb(0 0 0 / 35%);
	--k3y-shadow-lg: 0 4px 12px rgb(0 0 0 / 50%), 0 28px 64px rgb(0 0 0 / 45%);

	color-scheme: dark;
}

/* =============================================================================
 * Base
 * ========================================================================== */

*,
*::before,
*::after {
	box-sizing: border-box;
}

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

body {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
	margin: 0;
	color: var(--k3y-body);
	background: var(--k3y-ground);
	font-family: var(--k3y-font-body);
	font-size: 1rem;
	font-synthesis-weight: none;
	line-height: 1.7;
	-webkit-font-smoothing: antialiased;
	transition: background var(--k3y-dur-fast) linear, color var(--k3y-dur-fast) linear;
}

main {
	display: block;
	flex: 1 0 auto;
}

img,
picture,
svg,
video {
	display: block;
	max-width: 100%;
	height: auto;
}

/* The JS loop drives the scroll position directly, so native smoothing must be
 * off while it is active or the two animations fight each other. */
html.has-eased-scroll {
	scroll-behavior: auto;
}

/* Anchor targets clear the floating header. */
:target,
#primary {
	scroll-margin-top: 7rem;
}

/* =============================================================================
 * Typography
 * ========================================================================== */

h1,
h2,
h3,
h4,
h5,
h6 {
	margin-block: 0 0.6em;
	color: var(--k3y-ink);
	font-family: var(--k3y-font-display);
	font-weight: 600;
	line-height: 1.12;
	letter-spacing: -0.028em;
	text-wrap: balance;
}

h1 {
	font-size: clamp(2.4rem, 5.6vw, 4.5rem);
	letter-spacing: -0.038em;
}

h2 {
	font-size: clamp(1.85rem, 3.8vw, 3rem);
}

h3 {
	font-size: clamp(1.2rem, 2.2vw, 1.6rem);
	letter-spacing: -0.02em;
}

p,
ul,
ol,
blockquote,
table {
	margin-block: 0 1.25rem;
}

a {
	color: var(--k3y-brand);
	text-decoration-thickness: 0.08em;
	text-underline-offset: 0.2em;
	transition: color var(--k3y-dur-fast) var(--k3y-ease);
}

:focus-visible {
	outline: 3px solid var(--k3y-brand);
	outline-offset: 3px;
	border-radius: 4px;
}

code,
kbd,
samp,
pre {
	font-family: var(--k3y-font-mono);
	font-size: 0.9em;
}

/* Small technical label — protocol names, grant numbers, certification codes.
 * Monospace here is semantic: these are identifiers, not prose. */
.eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 0.55rem;
	margin: 0 0 1.15rem;
	color: var(--k3y-brand);
	font-family: var(--k3y-font-mono);
	font-size: 0.76rem;
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.eyebrow::before {
	width: 9px;
	height: 10px;
	background: var(--k3y-gradient-soft);
	clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
	content: "";
}

.lede {
	max-width: 60ch;
	color: var(--k3y-muted);
	font-size: clamp(1.05rem, 1.5vw, 1.25rem);
	line-height: 1.65;
}

/* Gradient text, used once or twice per page at most. */
.grad-text {
	background: var(--k3y-gradient-soft);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
}

/* =============================================================================
 * Layout
 * ========================================================================== */

.container {
	width: min(100%, calc(var(--k3y-wide) + (2 * var(--k3y-gutter))));
	margin-inline: auto;
	padding-inline: var(--k3y-gutter);
}

.container--narrow {
	width: min(100%, calc(var(--k3y-content) + (2 * var(--k3y-gutter))));
}

.section {
	padding-block: var(--k3y-section);
}

/* A flat fill of --k3y-surface-2 read as a grey slab dropped into the page,
 * with hard seams top and bottom. This washes the tint in and back out so the
 * band's edges melt into the ground, and lays the logo's own honeycomb over it
 * at low opacity for texture. Both layers are token-driven, so the dark theme
 * gets the same treatment in its own palette. */
.section--tint {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	background:
		radial-gradient(ellipse 90% 60% at 82% 0%, rgb(201 0 255 / 5%), transparent 62%),
		linear-gradient(
			180deg,
			var(--k3y-ground) 0%,
			var(--k3y-surface-2) 18%,
			var(--k3y-surface-2) 82%,
			var(--k3y-ground) 100%
		);
}

.section--tint::before {
	position: absolute;
	z-index: -1;
	inset: 0;
	background-image: var(--k3y-honeycomb);
	background-size: 46px 40px;
	opacity: 0.4;
	-webkit-mask-image: radial-gradient(ellipse 70% 90% at 88% 12%, #000 0%, transparent 72%);
	mask-image: radial-gradient(ellipse 70% 90% at 88% 12%, #000 0%, transparent 72%);
	pointer-events: none;
	content: "";
}

/* The dark theme has more room for the texture before it turns noisy. */
[data-theme="dark"] .section--tint::before {
	opacity: 0.55;
}

.section__head {
	max-width: 46rem;
	margin-bottom: clamp(2.5rem, 5vw, 4rem);
}

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

.screen-reader-text:focus {
	top: 0.75rem;
	left: 0.75rem;
	z-index: 100000;
	width: auto;
	height: auto;
	padding: 0.75rem 1.25rem;
	margin: 0;
	clip-path: none;
	color: var(--k3y-on-brand);
	background: var(--k3y-brand);
	white-space: normal;
}

/* =============================================================================
 * Icons
 *
 * The set is drawn as open stroke paths, so an icon with no rule at all falls
 * back to the SVG default of fill:black / stroke:none and renders as nothing.
 * Every icon printed by k3y_icon() carries .icon for exactly this reason.
 * ========================================================================== */

.icon {
	flex: 0 0 auto;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.7;
	stroke-linecap: round;
	stroke-linejoin: round;
}

/* =============================================================================
 * Hexagon — the brand's geometry, taken from the logo mark.
 * One shape, reused at every scale: bullets, icon frames, media crops.
 * ========================================================================== */

.hex {
	display: grid;
	flex: 0 0 auto;
	place-items: center;
	width: var(--hex-size, 3.5rem);
	aspect-ratio: 0.866;
	color: var(--k3y-on-brand);
	background: var(--k3y-gradient);
	clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
	transition: transform var(--k3y-dur) var(--k3y-ease);
}

.hex svg {
	width: 46%;
	height: auto;
	stroke: currentColor;
	fill: none;
	stroke-width: 1.6;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.hex--lg {
	--hex-size: 5rem;
}

.hex--sm {
	--hex-size: 2.25rem;
}

/* Outline variant for quieter contexts. */
.hex--ghost {
	color: var(--k3y-brand);
	background: var(--k3y-surface-2);
}

/* =============================================================================
 * Buttons
 * ========================================================================== */

.btn {
	position: relative;
	display: inline-flex;
	gap: 0.6rem;
	align-items: center;
	padding: 0.95rem 1.6rem;
	overflow: hidden;
	color: var(--k3y-on-brand);
	background: var(--k3y-gradient-btn);
	border: 1px solid transparent;
	border-radius: 999px;
	font-family: var(--k3y-font-body);
	font-size: 0.95rem;
	font-weight: 550;
	line-height: 1;
	text-decoration: none;
	cursor: pointer;
	transition: transform var(--k3y-dur-fast) var(--k3y-ease), box-shadow var(--k3y-dur) var(--k3y-ease);
}

.btn::before {
	position: absolute;
	inset: 0;
	background: var(--k3y-gradient-btn-hover);
	opacity: 0;
	transition: opacity var(--k3y-dur) var(--k3y-ease);
	content: "";
}

.btn > * {
	position: relative;
}

.btn:hover,
.btn:focus-visible {
	color: var(--k3y-on-brand);
	transform: translateY(-2px);
	box-shadow: 0 10px 28px rgb(94 0 156 / 32%);
}

.btn:hover::before,
.btn:focus-visible::before {
	opacity: 1;
}

.btn__arrow {
	transition: transform var(--k3y-dur) var(--k3y-ease);
}

.btn:hover .btn__arrow {
	transform: translateX(3px);
}

.btn--ghost {
	color: var(--k3y-brand);
	background: transparent;
	border-color: var(--k3y-line-strong);
}

.btn--ghost::before {
	display: none;
}

.btn--ghost:hover,
.btn--ghost:focus-visible {
	color: var(--k3y-brand);
	background: var(--k3y-surface);
	border-color: var(--k3y-brand);
	box-shadow: var(--k3y-shadow);
}

/* Inline arrow link. */
.link-arrow {
	display: inline-flex;
	gap: 0.45rem;
	align-items: center;
	color: var(--k3y-brand);
	font-weight: 550;
	text-decoration: none;
}

.link-arrow svg {
	transition: transform var(--k3y-dur) var(--k3y-ease);
}

.link-arrow:hover svg,
.link-arrow:focus-visible svg {
	transform: translateX(4px);
}

/* =============================================================================
 * Card — white surface floating on the off-white ground.
 * Hover draws a gradient edge rather than changing the fill, so the card keeps
 * its weight and only its outline reacts.
 * ========================================================================== */

.card {
	position: relative;
	display: flex;
	flex-direction: column;
	padding: clamp(1.5rem, 2.6vw, 2.25rem);
	background: var(--k3y-surface);
	border: 1px solid var(--k3y-line);
	border-radius: var(--k3y-radius-lg);
	box-shadow: var(--k3y-shadow-sm);
	transition: transform var(--k3y-dur) var(--k3y-ease), box-shadow var(--k3y-dur) var(--k3y-ease);
}

.card::after {
	position: absolute;
	inset: -1px;
	padding: 1px;
	background: var(--k3y-gradient-soft);
	border-radius: inherit;
	opacity: 0;
	-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	-webkit-mask-composite: xor;
	mask-composite: exclude;
	transition: opacity var(--k3y-dur) var(--k3y-ease);
	pointer-events: none;
	content: "";
}

.card:hover,
.card:focus-within {
	transform: translateY(-6px);
	box-shadow: var(--k3y-shadow-lg);
}

.card:hover::after,
.card:focus-within::after {
	opacity: 1;
}

.card:hover .hex,
.card:focus-within .hex {
	transform: rotate(30deg) scale(1.06);
}

.card__title {
	margin-block: 1.25rem 0.6rem;
	font-size: 1.25rem;
}

.card__title a {
	color: inherit;
	text-decoration: none;
}

/* Whole-card click target without nesting interactive elements. */
.card__title a::after {
	position: absolute;
	inset: 0;
	border-radius: inherit;
	content: "";
}

/* --- Post card -----------------------------------------------------------
 * Lives here rather than in content.css: that sheet is only enqueued for
 * pages and the K3Y post types, so it is absent on the blog, category and
 * search views where these cards actually render. */

.card--post {
	padding: 0;
	overflow: hidden;
}

.card--post__media {
	aspect-ratio: 16 / 9;
	overflow: hidden;
	background: var(--k3y-surface-2);
	border-bottom: 1px solid var(--k3y-line);
}

/* cover, not contain: these are photographs, unlike the partner logos on the
 * project cards. */
.card--post__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 700ms var(--k3y-ease);
}

.card--post:hover .card--post__media img,
.card--post:focus-within .card--post__media img {
	transform: scale(1.04);
}

.card--post__body {
	display: flex;
	flex: 1;
	flex-direction: column;
	padding: clamp(1.5rem, 2.6vw, 2.25rem);
}

/* Compound selector on purpose: .tags resets margin and is declared further
 * down this file, so a lone .card--post__tags rule loses to it and the badge
 * ends up flush against the title. */
.tags.card--post__tags {
	margin-bottom: 0.8rem;
}

/* The base rule's top margin exists to clear a hex icon; the tag row does
 * that job on this card. */
.card--post .card__title {
	margin-block: 0 0.6rem;
}

/* Tighter than the default card foot, and set smaller: it is a timestamp, the
 * least important line on the card. */
.card--post .card__foot {
	padding-top: 0.9rem;
	color: var(--k3y-muted);
	font-family: var(--k3y-font-mono);
	font-size: 0.72rem;
}

/* --- Pagination ----------------------------------------------------------
 * Global, not content.css: the blog, category and search views are exactly
 * where pagination appears, and that sheet is not enqueued on any of them --
 * unstyled, the links collapsed under the cards, which are positioned and so
 * paint above static content. */

.pagination {
	margin-top: clamp(2.5rem, 5vw, 3.5rem);
}

.pagination .nav-links {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	align-items: center;
	justify-content: center;
}

.pagination .page-numbers {
	display: grid;
	place-items: center;
	min-width: 2.5rem;
	height: 2.5rem;
	padding-inline: 0.6rem;
	color: var(--k3y-ink-2);
	background: var(--k3y-surface);
	border: 1px solid var(--k3y-line);
	border-radius: 999px;
	font-family: var(--k3y-font-mono);
	font-size: 0.85rem;
	text-decoration: none;
	transition: color var(--k3y-dur-fast) var(--k3y-ease), border-color var(--k3y-dur-fast) var(--k3y-ease);
}

.pagination .page-numbers:hover {
	color: var(--k3y-brand);
	border-color: var(--k3y-brand);
}

.pagination .page-numbers.current {
	color: var(--k3y-on-brand);
	background: var(--k3y-gradient-btn);
	border-color: transparent;
}

.pagination .page-numbers.dots {
	background: transparent;
	border-color: transparent;
}

/* --- Blog category filter ------------------------------------------------ */

.blog-filter {
	margin-bottom: clamp(2rem, 4vw, 3rem);
}

.blog-filter__list {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	padding: 0;
	margin: 0;
	list-style: none;
}

.blog-filter__link {
	display: inline-flex;
	gap: 0.45rem;
	align-items: center;
	padding: 0.5rem 1rem;
	color: var(--k3y-muted);
	background: var(--k3y-surface);
	border: 1px solid var(--k3y-line);
	border-radius: 999px;
	font-family: var(--k3y-font-mono);
	font-size: 0.78rem;
	text-decoration: none;
	transition:
		color var(--k3y-dur-fast) var(--k3y-ease),
		border-color var(--k3y-dur-fast) var(--k3y-ease),
		background var(--k3y-dur-fast) var(--k3y-ease);
}

.blog-filter__link:hover {
	color: var(--k3y-brand);
	border-color: var(--k3y-line-strong);
}

.blog-filter__link.is-current {
	color: var(--k3y-on-brand);
	background: var(--k3y-gradient-btn);
	border-color: transparent;
}

.blog-filter__count {
	opacity: 0.7;
	font-size: 0.72rem;
}

.card__text {
	margin: 0;
	color: var(--k3y-muted);
	font-size: 0.97rem;
}

.card__foot {
	margin-top: auto;
	padding-top: 1.5rem;
}

/* .tags resets padding and margin and is declared further down this file, so
 * on the one element that carries both classes (the solution card's domain
 * pills) it silently cancelled the foot's gap -- the pills ended up flush
 * against the description. Compound selector so the foot wins. */
.tags.card__foot {
	margin-top: auto;
	padding-top: 1.5rem;
}

/* Product card head + feature list.
 *
 * These belong to the card component, not to the homepage: the same partials
 * render on the products archive and on every single entry, neither of which
 * loads home.css. Component styles go in the global sheet. */
.card--product__head {
	display: flex;
	flex-wrap: wrap;
	gap: 0.85rem 1rem;
	align-items: center;
	justify-content: space-between;
	margin-bottom: 1.5rem;
}

.card--product__head .tag {
	margin-left: auto;
}

.card--product .card__title {
	margin-block: 0 0.6rem;
}

.feature-list {
	padding: 0;
	margin: 1.5rem 0 0;
	list-style: none;
}

.feature-list li {
	position: relative;
	padding-left: 1.5rem;
	color: var(--k3y-muted);
	font-size: 0.92rem;
	line-height: 1.6;
}

.feature-list li + li {
	margin-top: 0.6rem;
}

.feature-list li::before {
	position: absolute;
	top: 0.55em;
	left: 0;
	width: 8px;
	height: 9px;
	background: var(--k3y-gradient-soft);
	clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
	content: "";
}

.grid {
	display: grid;
	gap: clamp(1rem, 2vw, 1.75rem);
}

.grid--3 {
	grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
}

.grid--2 {
	grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr));
}

/* =============================================================================
 * Tags
 * ========================================================================== */

.tags {
	display: flex;
	flex-wrap: wrap;
	gap: 0.45rem;
	padding: 0;
	margin: 0;
	list-style: none;
}

.tag {
	padding: 0.35rem 0.7rem;
	color: var(--k3y-brand);
	background: var(--k3y-surface-2);
	border: 1px solid var(--k3y-line);
	border-radius: 999px;
	font-family: var(--k3y-font-mono);
	font-size: 0.72rem;
	letter-spacing: 0.02em;
}

/* =============================================================================
 * Header
 * ========================================================================== */

.site-header {
	position: sticky;
	top: 0;
	z-index: 100;
	margin-bottom: calc(-1 * var(--k3y-header-h));
	padding-block: 0.7rem;
	background: transparent;
}

/* The pill's shape -- width, height, padding, radius -- is fixed. Only its
 * fill crossfades in on scroll (see .is-scrolled below), and only through
 * paint-only properties: opacity, border-color, box-shadow.
 *
 * Keep it that way. Animating any layout property here runs a layout
 * animation against the eased-scroll loop in app.js, which drives scrollTo
 * every frame, and the header visibly hitches mid-scroll. */
.site-header__inner {
	position: relative;
	display: flex;
	gap: 1.5rem;
	align-items: center;
	width: min(100% - (2 * var(--k3y-gutter)), 75rem);
	min-height: 3.9rem;
	padding-inline: 1.35rem;
	border: 1px solid transparent;
	border-radius: 999px;
	box-shadow: 0 14px 44px rgb(13 10 31 / 0%), 0 2px 6px rgb(13 10 31 / 0%);
	transition: border-color 320ms var(--k3y-ease), box-shadow 320ms var(--k3y-ease);
}

.site-header.is-scrolled .site-header__inner {
	border-color: var(--k3y-line);
	box-shadow: 0 14px 44px rgb(13 10 31 / 12%), 0 2px 6px rgb(13 10 31 / 5%);
}

/* The pill's own surface. On a pseudo-element so that backdrop-filter never
 * lands on an ancestor of the position:fixed drawer. Translucent + blurred so
 * the hero/honeycomb behind it still reads through softly -- and fully
 * transparent (opacity crossfade only) until the page has actually scrolled. */
.site-header__inner::before {
	position: absolute;
	z-index: -1;
	inset: 0;
	background: var(--k3y-surface);
	border-radius: inherit;
	opacity: 0;
	transition: opacity 320ms var(--k3y-ease);
	content: "";
}

.site-header.is-scrolled .site-header__inner::before {
	opacity: 1;
}

@supports (backdrop-filter: blur(1px)) {
	.site-header__inner::before {
		background: color-mix(in srgb, var(--k3y-surface) 82%, transparent);
		backdrop-filter: blur(18px) saturate(1.5);
	}
}


.site-branding {
	display: flex;
	flex: 0 0 auto;
	gap: 0.7rem;
	align-items: center;
	text-decoration: none;
}

.site-branding__mark {
	width: 2.1rem;
	height: auto;
}

.site-branding__text {
	display: grid;
	gap: 3px;
}

.site-title {
	margin: 0;
	color: var(--k3y-ink);
	font-family: var(--k3y-font-display);
	font-size: 1.4rem;
	font-weight: 700;
	letter-spacing: 0.02em;
	line-height: 1;
	text-transform: uppercase;
}

.site-tagline {
	color: var(--k3y-muted);
	font-family: var(--k3y-font-mono);
	font-size: 0.55rem;
	font-weight: 500;
	letter-spacing: 0.17em;
	line-height: 1;
	text-transform: uppercase;
}

.site-title a {
	color: inherit;
	text-decoration: none;
}

.site-description {
	display: none;
}

/* Navigation */
.main-navigation {
	margin-left: auto;
}

.main-navigation .menu,
.main-navigation .sub-menu {
	padding: 0;
	margin: 0;
	list-style: none;
}

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

.main-navigation li {
	position: relative;
}

/* Scoped to .menu on purpose: `.main-navigation a` would out-specify .btn and
 * repaint the drawer's call-to-action with body ink on a purple fill. Keep
 * broad descendant selectors off anything that contains a component. */
.main-navigation .menu a {
	position: relative;
	display: block;
	padding: 0.6rem 0.85rem;
	color: var(--k3y-ink-2);
	border-radius: 999px;
	font-size: 0.925rem;
	font-weight: 500;
	text-decoration: none;
	transition: color var(--k3y-dur-fast) var(--k3y-ease), background var(--k3y-dur-fast) var(--k3y-ease);
}

.main-navigation .menu > li > a:hover,
.main-navigation .menu > li > a:focus-visible,
.main-navigation .menu > li:focus-within > a {
	color: var(--k3y-brand);
	background: var(--k3y-surface-2);
}

.main-navigation .current-menu-item > a,
.main-navigation .current-menu-ancestor > a {
	color: var(--k3y-brand);
}

/* Dropdown panel */
.main-navigation .menu-item-has-children > a::after {
	display: inline-block;
	width: 0.4em;
	height: 0.4em;
	margin-left: 0.45em;
	border-right: 1.5px solid currentColor;
	border-bottom: 1.5px solid currentColor;
	transform: translateY(-0.15em) rotate(45deg);
	content: "";
}

.main-navigation .sub-menu {
	position: absolute;
	top: calc(100% + 0.5rem);
	left: 0;
	min-width: 15rem;
	padding: 0.5rem;
	background: var(--k3y-surface);
	border: 1px solid var(--k3y-line);
	border-radius: var(--k3y-radius);
	box-shadow: var(--k3y-shadow-lg);
	opacity: 0;
	visibility: hidden;
	transform: translateY(-6px);
	transition: opacity var(--k3y-dur-fast) var(--k3y-ease), transform var(--k3y-dur-fast) var(--k3y-ease), visibility var(--k3y-dur-fast);
}

.main-navigation li:hover > .sub-menu,
.main-navigation li:focus-within > .sub-menu {
	opacity: 1;
	visibility: visible;
	transform: none;
}

.main-navigation .sub-menu a {
	padding: 0.6rem 0.75rem;
	border-radius: 8px;
	font-size: 0.9rem;
}

.main-navigation .sub-menu a:hover,
.main-navigation .sub-menu a:focus-visible {
	color: var(--k3y-brand);
	background: var(--k3y-surface-2);
}

.nav-backdrop,
.nav-drawer__foot {
	display: none;
}

/* Header actions */
.site-header__actions {
	display: flex;
	flex: 0 0 auto;
	gap: 0.6rem;
	align-items: center;
}

.theme-toggle {
	display: grid;
	place-items: center;
	width: 2.4rem;
	height: 2.4rem;
	padding: 0;
	color: var(--k3y-ink-2);
	background: transparent;
	border: 1px solid var(--k3y-line);
	border-radius: 999px;
	cursor: pointer;
	transition: color var(--k3y-dur-fast) var(--k3y-ease), border-color var(--k3y-dur-fast) var(--k3y-ease);
}

.theme-toggle:hover {
	color: var(--k3y-brand);
	border-color: var(--k3y-brand);
}

.theme-toggle svg {
	width: 1.05rem;
	height: 1.05rem;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.7;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.theme-toggle__moon {
	display: none;
}

[data-theme="dark"] .theme-toggle__sun {
	display: none;
}

[data-theme="dark"] .theme-toggle__moon {
	display: block;
}

.site-header .btn {
	padding: 0.7rem 1.25rem;
	font-size: 0.9rem;
}

.menu-toggle {
	display: none;
	place-items: center;
	width: 2.6rem;
	height: 2.6rem;
	padding: 0;
	color: var(--k3y-ink);
	background: transparent;
	border: 1px solid var(--k3y-line);
	border-radius: 999px;
	cursor: pointer;
}

.menu-toggle__icon,
.menu-toggle__icon::before,
.menu-toggle__icon::after {
	display: block;
	width: 1.05rem;
	height: 1.6px;
	background: currentColor;
	border-radius: 2px;
	transition: transform var(--k3y-dur-fast) var(--k3y-ease), opacity var(--k3y-dur-fast) linear;
}

.menu-toggle__icon {
	position: relative;
}

.menu-toggle__icon::before,
.menu-toggle__icon::after {
	position: absolute;
	left: 0;
	content: "";
}

.menu-toggle__icon::before {
	top: -0.35rem;
}

.menu-toggle__icon::after {
	top: 0.35rem;
}

[aria-expanded="true"] .menu-toggle__icon {
	background: transparent;
}

[aria-expanded="true"] .menu-toggle__icon::before {
	transform: translateY(0.35rem) rotate(45deg);
}

[aria-expanded="true"] .menu-toggle__icon::after {
	transform: translateY(-0.35rem) rotate(-45deg);
}

/* =============================================================================
 * Footer — deliberately dark in both themes. It closes the page with the
 * dark end of the logo gradient, so the brand bookends the site.
 * ========================================================================== */

.site-footer {
	position: relative;
	overflow: hidden;
	color: #b9b2cc;
	background: var(--k3y-brand-ink);
	font-size: 0.94rem;
}

.site-footer__mesh {
	position: absolute;
	inset: 0;
	background-image: var(--k3y-honeycomb);
	background-size: 40px 35px;
	opacity: 0.33;
	-webkit-mask-image: radial-gradient(ellipse 70% 90% at 88% 8%, #000 0%, transparent 70%);
	mask-image: radial-gradient(ellipse 70% 90% at 88% 8%, #000 0%, transparent 70%);
	pointer-events: none;
}

.site-footer::before {
	position: absolute;
	top: -30%;
	right: -10%;
	width: 45rem;
	height: 45rem;
	background: radial-gradient(circle, rgb(201 0 255 / 16%) 0%, transparent 62%);
	pointer-events: none;
	content: "";
}

.site-footer__inner {
	position: relative;
	display: grid;
	grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
	gap: clamp(2rem, 4vw, 3.5rem);
	padding-block: clamp(3.5rem, 7vw, 5.5rem) 2.5rem;
}

.site-footer h2 a {
	color: inherit;
	text-decoration: none;
}

.site-footer h2 a:hover,
.site-footer h2 a:focus-visible {
	color: var(--k3y-brand-vivid);
}

.site-footer h2 {
	margin-bottom: 1.25rem;
	color: #fff;
	font-size: 0.78rem;
	font-family: var(--k3y-font-mono);
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.site-footer :is(.footer-brand, .footer-menu, .office, .social, .site-footer__bar) a {
	color: #b9b2cc;
	text-decoration: none;
	transition: color var(--k3y-dur-fast) var(--k3y-ease);
}

.site-footer :is(.footer-brand, .footer-menu, .office, .social, .site-footer__bar) a:hover,
.site-footer :is(.footer-brand, .footer-menu, .office, .social, .site-footer__bar) a:focus-visible {
	color: #fff;
}

.footer-brand__lockup {
	width: 9.5rem;
	height: auto;
	margin-bottom: 1.35rem;
}

.footer-brand__text {
	max-width: 32ch;
	margin: 0 0 1.5rem;
	color: #9a93ad;
}

.footer-menu {
	padding: 0;
	margin: 0;
	list-style: none;
}

.footer-menu li + li {
	margin-top: 0.6rem;
}

.footer-offices {
	position: relative;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
	gap: 1.5rem;
	padding-block: 2.5rem;
	border-top: 1px solid rgb(255 255 255 / 9%);
}

.office__label {
	margin: 0 0 0.5rem;
	color: #fff;
	font-family: var(--k3y-font-mono);
	font-size: 0.72rem;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

.office address {
	color: #9a93ad;
	font-style: normal;
	line-height: 1.75;
}

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

.social a {
	display: grid;
	place-items: center;
	width: 2.4rem;
	height: 2.4rem;
	border: 1px solid rgb(255 255 255 / 14%);
	border-radius: 999px;
	transition: background var(--k3y-dur-fast) var(--k3y-ease), border-color var(--k3y-dur-fast) var(--k3y-ease);
}

.social a:hover {
	background: var(--k3y-gradient-soft);
	border-color: transparent;
}

.social svg {
	width: 1rem;
	height: 1rem;
	fill: currentColor;
}

.site-footer__bar {
	position: relative;
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem 1.5rem;
	align-items: center;
	justify-content: space-between;
	padding-block: 1.5rem;
	border-top: 1px solid rgb(255 255 255 / 9%);
	color: #7d7691;
	font-family: var(--k3y-font-mono);
	font-size: 0.74rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

/* =============================================================================
 * Scroll reveal. One motion idea: content rises and settles, staggered by
 * position. Scoped to html.js so nothing is ever hidden without scripting.
 * ========================================================================== */

html.js .reveal {
	opacity: 0;
	transform: translateY(22px) scale(0.995);
	transition: opacity 0.5s var(--k3y-ease-out), transform 0.5s var(--k3y-ease-out);
	transition-delay: calc(var(--i, 0) * 40ms);
}

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

/* Cards lift a touch further so a grid reads as dealing out, one by one. */
html.js .grid .reveal,
html.js .people .reveal,
html.js .hub .reveal,
html.js .cert-wall .reveal {
	transform: translateY(30px) scale(0.985);
}

/* =============================================================================
 * Responsive
 * ========================================================================== */

@media (max-width: 64rem) {
	.site-footer__inner {
		grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
	}
}

@media (max-width: 60rem) {
	.js .menu-toggle {
		display: grid;
	}

	.site-header__inner {
		gap: 0.75rem;
	}

	/* .main-navigation is position:fixed here, so its margin-left:auto no longer
	 * pushes anything. The actions have to claim the free space themselves. */
	.site-header__actions {
		margin-left: auto;
	}

	.site-header__actions .btn {
		display: none;
	}

	/* Dimmer behind the drawer. Sits below the header so the close button in
	 * the header stays reachable while the drawer is open. */
	.nav-backdrop {
		display: block;
		position: fixed;
		inset: 0;
		z-index: 95;
		background: rgb(9 8 22 / 48%);
		opacity: 0;
		visibility: hidden;
		transition: opacity var(--k3y-dur-fast) var(--k3y-ease), visibility var(--k3y-dur-fast);
	}

	.nav-backdrop.is-open {
		opacity: 1;
		visibility: visible;
	}

	/* Right-hand drawer. */
	.main-navigation {
		position: fixed;
		top: 0;
		right: 0;
		bottom: 0;
		z-index: 96;
		width: min(23rem, 86vw);
		padding: 5.75rem 1.75rem 2.5rem;
		margin: 0;
		overflow-y: auto;
		overscroll-behavior: contain;
		background: var(--k3y-surface);
		border-left: 1px solid var(--k3y-line);
		box-shadow: -28px 0 70px rgb(13 10 31 / 22%);
		visibility: hidden;
		transform: translateX(100%);
		transition: transform 400ms var(--k3y-ease-out), visibility 400ms;
	}

	.main-navigation.is-open {
		visibility: visible;
		transform: none;
	}

	.main-navigation .menu {
		display: block;
	}

	/* Links arrive one after another once the drawer is open. */
	.main-navigation .menu > li {
		opacity: 0;
		transform: translateX(14px);
		transition: opacity 340ms var(--k3y-ease-out), transform 340ms var(--k3y-ease-out);
	}

	.main-navigation.is-open .menu > li {
		opacity: 1;
		transform: none;
		transition-delay: calc(90ms + var(--i, 0) * 45ms);
	}

	.main-navigation .menu > li > a {
		padding: 0.85rem 0;
		border-bottom: 1px solid var(--k3y-line);
		border-radius: 0;
		font-family: var(--k3y-font-display);
		font-size: 1.12rem;
		font-weight: 600;
	}

	.main-navigation .menu > li > a:hover,
	.main-navigation .menu > li > a:focus-visible {
		background: transparent;
	}

	.main-navigation .menu-item-has-children > a::after {
		float: right;
		margin-top: 0.5em;
	}

	.main-navigation .sub-menu {
		position: static;
		min-width: 0;
		padding: 0.35rem 0 0.9rem 0.9rem;
		background: transparent;
		border: 0;
		box-shadow: none;
		opacity: 1;
		visibility: visible;
		transform: none;
	}

	.main-navigation .sub-menu a {
		padding: 0.5rem 0;
		color: var(--k3y-muted);
		font-size: 0.95rem;
	}

	.nav-drawer__foot {
		display: block;
		margin-top: 2rem;
	}

	.nav-drawer__foot .btn {
		display: inline-flex;
		width: 100%;
		justify-content: center;
	}
}

@media (max-width: 40rem) {
	.site-footer__bar {
		justify-content: flex-start;
	}
}

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

	html.js .reveal {
		opacity: 1;
		transform: none;
		transition: none;
	}

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

.site-footer__copy {
	margin: 0;
}

.site-footer__meta {
	display: flex;
	gap: 1.25rem;
	align-items: center;
}

/* Cookie notice link will slot in here alongside the privacy link. */
.site-footer__meta a {
	white-space: nowrap;
}

/* Colour-scheme switch, parked in the footer bar. */
.site-footer .theme-toggle {
	color: #b9b2cc;
	border-color: rgb(255 255 255 / 16%);
}

.site-footer .theme-toggle:hover,
.site-footer .theme-toggle:focus-visible {
	color: #fff;
	border-color: rgb(255 255 255 / 45%);
}

.site-footer__bar p {
	margin: 0;
}

@media (max-width: 30rem) {
	.site-tagline {
		display: none;
	}
}

/* =============================================================================
 * Page hero — shared partial, used by archives, singles, pages, search and 404,
 * so it lives in the global sheet rather than a context-specific one.
 * ========================================================================== */

.page-hero {
	position: relative;
	overflow: hidden;
	padding-top: calc(var(--k3y-header-h) + clamp(3rem, 7vw, 5.5rem));
	padding-bottom: clamp(2rem, 4vw, 3rem);
	background: var(--k3y-surface-2);
	border-bottom: 1px solid var(--k3y-line);
}

.page-hero__glow {
	position: absolute;
	top: -55%;
	right: -5%;
	width: 38rem;
	height: 38rem;
	background: radial-gradient(circle, rgb(201 0 255 / 12%) 0%, transparent 62%);
	pointer-events: none;
}

.page-hero__inner {
	position: relative;
	max-width: 52rem;
}

/* Deliberately below the global h1 scale: an inner page's title introduces the
 * content under it, where the homepage hero is the statement. */
.page-hero__title {
	margin-bottom: 1.1rem;
	font-size: clamp(1.85rem, 3.3vw, 2.6rem);
}

.page-hero .tags {
	margin-top: 1.5rem;
}

.section--flush {
	padding-block: clamp(3rem, 6vw, 5rem);
}

.page-hero--tall {
	padding-top: calc(var(--k3y-header-h) + clamp(4rem, 9vw, 7rem));
	padding-bottom: clamp(3rem, 6vw, 4.5rem);
	overflow: hidden;
}

.page-hero__field {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	opacity: 0.88;
	-webkit-mask-image: radial-gradient(ellipse 85% 95% at 72% 42%, #000 18%, transparent 76%);
	mask-image: radial-gradient(ellipse 85% 95% at 72% 42%, #000 18%, transparent 76%);
}

.page-hero--tall .page-hero__inner {
	position: relative;
	z-index: 1;
	max-width: 46rem;
}

.bracket span::before,
.bracket span::after {
	color: var(--k3y-brand-vivid);
	font-weight: 300;
}

.bracket span::before {
	margin-right: 0.32em;
	content: "{";
}

.bracket span::after {
	margin-left: 0.32em;
	content: "}";
}

.page-hero__inner--center {
	margin-inline: auto;
	text-align: center;
}

.page-hero__inner--center .lede {
	margin-inline: auto;
}

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

input[type="search"],
input[type="text"],
input[type="email"],
input[type="url"],
input[type="tel"],
textarea {
	width: 100%;
	padding: 0.9rem 1.15rem;
	color: var(--k3y-ink);
	background: var(--k3y-surface);
	border: 1px solid var(--k3y-line-strong);
	border-radius: 999px;
	font-family: inherit;
	font-size: 1rem;
	transition: border-color var(--k3y-dur-fast) var(--k3y-ease), box-shadow var(--k3y-dur-fast) var(--k3y-ease);
}

textarea {
	border-radius: var(--k3y-radius);
	resize: vertical;
}

input:focus,
textarea:focus {
	border-color: var(--k3y-brand);
	box-shadow: 0 0 0 4px rgb(94 0 156 / 12%);
	outline: none;
}

::placeholder {
	color: var(--k3y-muted);
	opacity: 1;
}

.search-form {
	display: flex;
	gap: 0.6rem;
	align-items: stretch;
	width: min(100%, 32rem);
}

.search-submit {
	flex: 0 0 auto;
	padding: 0.9rem 1.5rem;
	color: var(--k3y-on-brand);
	background: var(--k3y-gradient-btn);
	border: 1px solid transparent;
	border-radius: 999px;
	font-family: inherit;
	font-size: 0.95rem;
	font-weight: 550;
	cursor: pointer;
	transition: box-shadow var(--k3y-dur) var(--k3y-ease), transform var(--k3y-dur-fast) var(--k3y-ease);
}

.search-submit:hover,
.search-submit:focus-visible {
	transform: translateY(-2px);
	box-shadow: 0 10px 28px rgb(94 0 156 / 30%);
}

/* =============================================================================
 * 404
 * ========================================================================== */

.error-hero {
	position: relative;
	overflow: hidden;
	padding-top: calc(var(--k3y-header-h) + clamp(3rem, 8vw, 6rem));
	padding-bottom: clamp(2.5rem, 5vw, 4rem);
}

/* .container already centres the box; these centre the contents inside it.
 * Without them the copy stacked up against the box's left edge, which read as
 * neither centred nor aligned with the section below. Same treatment as
 * .page-hero__inner--center, plus the two flex children that need their own
 * centring: .error-code is a flex row, and .search-form is a fixed-width
 * block. */
.error-hero__inner {
	position: relative;
	max-width: 46rem;
	margin-inline: auto;
	text-align: center;
}

.error-hero__inner .lede,
.error-hero__inner .search-form {
	margin-inline: auto;
}

.error-hero__inner .error-code {
	justify-content: center;
}

/* The zero is the K3Y hexagon. */
.error-code {
	--code-size: clamp(4.5rem, 15vw, 10rem);

	display: flex;
	gap: clamp(0.4rem, 1.2vw, 0.9rem);
	align-items: center;
	margin: 0 0 1.75rem;
	line-height: 1;
}

.error-code__digit {
	color: transparent;
	font-family: var(--k3y-font-display);
	font-size: var(--code-size);
	font-weight: 800;
	letter-spacing: -0.04em;
	-webkit-text-stroke: 2px var(--k3y-line-strong);
}

.error-code__hex {
	position: relative;
	width: calc(var(--code-size) * 0.66);
	height: calc(var(--code-size) * 0.78);
	background: var(--k3y-gradient);
	clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

.error-code__hex::after {
	position: absolute;
	inset: 26%;
	background: var(--k3y-ground);
	clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
	content: "";
}

.error-title {
	margin-bottom: 1rem;
	font-size: clamp(1.8rem, 4.4vw, 3rem);
}

.error-search {
	margin-top: 2.25rem;
}

/* Destination list */
.route-list {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
	gap: 0 clamp(1.5rem, 4vw, 3.5rem);
	padding: 0;
	margin: 1.5rem 0 0;
	list-style: none;
}

.route {
	border-bottom: 1px solid var(--k3y-line);
}

.route__link {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	gap: 1rem;
	align-items: center;
	padding: 1.1rem 0;
	color: var(--k3y-ink);
	text-decoration: none;
	transition: padding var(--k3y-dur) var(--k3y-ease), background var(--k3y-dur) var(--k3y-ease);
}

.route__link:hover,
.route__link:focus-visible {
	padding-inline: 1rem;
	background: var(--k3y-surface);
}

.route__body {
	display: grid;
	gap: 0.15rem;
}

.route__title {
	font-family: var(--k3y-font-display);
	font-size: 1.05rem;
	font-weight: 600;
	letter-spacing: -0.02em;
}

.route__desc {
	color: var(--k3y-muted);
	font-size: 0.88rem;
}

.route__arrow {
	color: var(--k3y-line-strong);
	transition: color var(--k3y-dur) var(--k3y-ease), transform var(--k3y-dur) var(--k3y-ease);
}

.route__link:hover .route__arrow,
.route__link:focus-visible .route__arrow {
	color: var(--k3y-brand);
	transform: translateX(4px);
}

.route__link:hover .hex,
.route__link:focus-visible .hex {
	transform: rotate(30deg);
}

@media (max-width: 40rem) {
	.search-form {
		flex-wrap: wrap;
	}

	.search-submit {
		width: 100%;
	}

	.route__link:hover,
	.route__link:focus-visible {
		padding-inline: 0;
		background: transparent;
	}
}

/* =============================================================================
 * Homepage composition
 *
 * Was assets/css/home.css.
 * ========================================================================== */

.site-main--home {
	padding-block: 0;
}

/* --- Hero ----------------------------------------------------------------- */

.hero {
	position: relative;
	padding-top: calc(var(--k3y-header-h) + clamp(3.5rem, 8vw, 7rem));
	padding-bottom: clamp(2.5rem, 5vw, 4rem);
	overflow: hidden;
}

.hero__field {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	opacity: 0.92;
	-webkit-mask-image: radial-gradient(ellipse 88% 100% at 70% 40%, #000 20%, transparent 78%);
	mask-image: radial-gradient(ellipse 88% 100% at 70% 40%, #000 20%, transparent 78%);
	pointer-events: auto;
}

.hero__fade {
	position: absolute;
	inset: auto 0 0;
	height: 40%;
	background: linear-gradient(to bottom, transparent, var(--k3y-ground));
	pointer-events: none;
}

.hero__inner {
	position: relative;
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: clamp(2rem, 5vw, 4rem);
	align-items: center;
}

.hero__copy {
	max-width: 56rem;
}

/* The mark is decoration, and on a phone it would push the call to action
 * below the fold to earn nothing -- so it only appears once there is a second
 * column to put it in. */
.hero__mark {
	display: none;
	margin: 0;
}

/* Only split into two columns once there is genuinely room for both -- below
 * this the headline starts wrapping mid-phrase to make space for decoration,
 * which is the wrong trade. */
@media (min-width: 75rem) {
	.hero__inner {
		grid-template-columns: minmax(0, 1.4fr) minmax(0, 0.6fr);
	}

	.hero__copy {
		max-width: 46rem;
	}

	/* Slightly off the full display scale so "We break systems." still holds
	 * one line beside the mark. */
	.hero__title {
		font-size: clamp(2.5rem, 4.2vw, 4.05rem);
	}

	.hero__mark {
		display: block;
		justify-self: center;
	}

	.hero__mark img {
		width: min(100%, 24rem);
		height: auto;
	}
}

.hero__title {
	margin-bottom: 1.5rem;
	font-size: clamp(2.5rem, 6.2vw, 5rem);
	line-height: 1.05;
}

.hero .lede {
	margin-bottom: 2.5rem;
}

.hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.9rem;
}

/* Certification strip */
.trust {
	position: relative;
	margin-top: clamp(3rem, 7vw, 5rem);
	padding-top: 2rem;
	border-top: 1px solid var(--k3y-line);
}

.trust__label {
	margin: 0 0 1.25rem;
	color: var(--k3y-muted);
	font-family: var(--k3y-font-mono);
	font-size: 0.72rem;
	letter-spacing: 0.14em;
	text-align: center;
	text-transform: uppercase;
}

.trust__list {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: clamp(1.25rem, 4vw, 3rem);
	align-items: center;
	padding: 0;
	margin: 0;
	list-style: none;
}

.trust__list img {
	width: 3.25rem;
	height: auto;
	opacity: 0.62;
	filter: saturate(0.75);
	transition: opacity var(--k3y-dur) var(--k3y-ease), filter var(--k3y-dur) var(--k3y-ease), transform var(--k3y-dur) var(--k3y-ease);
}

.trust__list li:hover img {
	opacity: 1;
	filter: none;
	transform: translateY(-3px);
}

/* --- Split + stats -------------------------------------------------------- */

.split {
	display: grid;
	grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
	gap: clamp(2.5rem, 6vw, 5rem);
	align-items: center;
}

.split__text h2 {
	max-width: 16ch;
}

.split__text p {
	max-width: 46ch;
	color: var(--k3y-muted);
}

.stats {
	display: grid;
	gap: 1rem;
	padding: 0;
	margin: 0;
	list-style: none;
}

.stat {
	display: flex;
	gap: 1.25rem;
	align-items: baseline;
	padding: 1.5rem 1.75rem;
	background: var(--k3y-surface);
	border: 1px solid var(--k3y-line);
	border-radius: var(--k3y-radius);
	box-shadow: var(--k3y-shadow-sm);
}

.stat__value {
	min-width: 3ch;
	background: var(--k3y-gradient-soft);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	font-family: var(--k3y-font-display);
	font-size: clamp(2.2rem, 4vw, 3.1rem);
	font-weight: 700;
	letter-spacing: -0.04em;
	line-height: 1;
}

.stat__label {
	color: var(--k3y-muted);
	font-size: 0.95rem;
}

/* --- Team ---------------------------------------------------------------- */

.team-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
	gap: clamp(1.5rem, 3vw, 2.5rem);
}

/* --- Closing band --------------------------------------------------------- */

.cta-band {
	position: relative;
	overflow: hidden;
	background: var(--k3y-gradient-band);
	color: #fff;
}

.cta-band__mesh {
	position: absolute;
	inset: 0;
	background-image: var(--k3y-honeycomb);
	background-size: 40px 35px;
	opacity: 0.41;
	-webkit-mask-image: linear-gradient(105deg, transparent 30%, #000 100%);
	mask-image: linear-gradient(105deg, transparent 30%, #000 100%);
	pointer-events: none;
}

.cta-band::before {
	position: absolute;
	top: -60%;
	left: 55%;
	width: 40rem;
	height: 40rem;
	background: radial-gradient(circle, rgb(255 255 255 / 12%) 0%, transparent 62%);
	pointer-events: none;
	content: "";
}

.cta-band__inner {
	position: relative;
	display: flex;
	flex-wrap: wrap;
	gap: 2rem;
	align-items: center;
	justify-content: space-between;
	padding-block: clamp(3.5rem, 7vw, 5.5rem);
}

.cta-band h2 {
	max-width: 20ch;
	margin-bottom: 0.6rem;
	color: #fff;
}

.cta-band p {
	max-width: 46ch;
	margin: 0;
	color: rgb(255 255 255 / 86%);
}

.btn--on-dark {
	color: var(--k3y-brand);
	background: #fff;
	border-color: #fff;
}

.btn--on-dark::before {
	display: none;
}

.btn--on-dark:hover,
.btn--on-dark:focus-visible {
	color: var(--k3y-brand);
	background: #fff;
	box-shadow: 0 12px 32px rgb(0 0 0 / 28%);
}

/* --- Responsive ----------------------------------------------------------- */

@media (max-width: 60rem) {
	.split {
		grid-template-columns: minmax(0, 1fr);
	}

	.hero__field {
		opacity: 0.5;
		-webkit-mask-image: radial-gradient(ellipse 110% 60% at 50% 20%, #000 10%, transparent 78%);
		mask-image: radial-gradient(ellipse 110% 60% at 50% 20%, #000 10%, transparent 78%);
	}
}

@media (max-width: 40rem) {
	.hero__actions .btn {
		flex: 1 1 100%;
		justify-content: center;
	}

	.trust__list {
		gap: 1.25rem;
	}

	.trust__list img {
		width: 2.75rem;
	}
}

/* =============================================================================
 * Archive and single templates for the K3Y content types
 *
 * Was assets/css/content.css.
 * ========================================================================== */

/* --- Page hero ------------------------------------------------------------ */







/* --- Project card --------------------------------------------------------- */

.card--project__head {
	display: flex;
	gap: 1rem;
	align-items: flex-start;
	justify-content: space-between;
}

.card--project .card__title {
	margin-block: 0 0.5rem;
	font-family: var(--k3y-font-mono);
	font-size: 1.05rem;
	font-weight: 500;
	letter-spacing: 0;
}

/* --- Job list ------------------------------------------------------------- */

.job-list {
	padding: 0;
	margin: 0 0 clamp(2.5rem, 5vw, 4rem);
	list-style: none;
	border-top: 1px solid var(--k3y-line);
}

.job {
	border-bottom: 1px solid var(--k3y-line);
}

.job__link {
	display: grid;
	grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) auto;
	gap: 0.4rem 1.5rem;
	align-items: center;
	padding: 1.25rem 0;
	color: var(--k3y-ink);
	text-decoration: none;
	transition: padding var(--k3y-dur) var(--k3y-ease), background var(--k3y-dur) var(--k3y-ease);
}

.job__link:hover,
.job__link:focus-visible {
	padding-inline: 1.1rem;
	background: var(--k3y-surface);
}

.job__title {
	font-family: var(--k3y-font-display);
	font-size: 1.08rem;
	font-weight: 600;
	letter-spacing: -0.02em;
}

.job__meta {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem 1.1rem;
	color: var(--k3y-muted);
	font-size: 0.86rem;
}

.badge {
	justify-self: end;
	padding: 0.3rem 0.7rem;
	margin: 0;
	border-radius: 999px;
	font-family: var(--k3y-font-mono);
	font-size: 0.7rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

.badge--open {
	color: #0b6b3a;
	background: #e4f7ec;
	border: 1px solid #b9e7cd;
}

.badge--closed {
	color: var(--k3y-muted);
	background: var(--k3y-surface-2);
	border: 1px solid var(--k3y-line);
}

[data-theme="dark"] .badge--open {
	color: #7ee2ab;
	background: rgb(18 92 54 / 35%);
	border-color: rgb(126 226 171 / 30%);
}

.callout {
	display: flex;
	flex-wrap: wrap;
	gap: 1.5rem;
	align-items: center;
	justify-content: space-between;
	padding: clamp(1.75rem, 4vw, 2.75rem);
	background: var(--k3y-surface);
	border: 1px solid var(--k3y-line);
	border-radius: var(--k3y-radius-lg);
	box-shadow: var(--k3y-shadow-sm);
}

.callout h2 {
	margin-bottom: 0.4rem;
	font-size: 1.4rem;
}

.callout p {
	max-width: 44ch;
	margin: 0;
	color: var(--k3y-muted);
}

/* --- Single entry layout -------------------------------------------------- */

.entry-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
	gap: clamp(2rem, 5vw, 4.5rem);
	align-items: start;
}

/* Blog posts carry no aside (see single.php), so the prose takes the whole
 * grid rather than leaving a 20rem column of nothing beside it. */
.entry-layout > .entry-content:only-child {
	grid-column: 1 / -1;
}

.entry-content {
	max-width: 68ch;
	color: var(--k3y-body);
	font-size: 1.05rem;
}

.entry-content > *:last-child {
	margin-bottom: 0;
}

/* Body-copy headings, not display type: at the global h2 scale a section
 * label like "Project Objective" came out larger than the page's own h1. */
.entry-content h2,
.entry-content h3 {
	margin-top: 2.25rem;
}

.entry-content h2 {
	font-size: clamp(1.3rem, 2vw, 1.6rem);
}

.entry-content h3 {
	font-size: clamp(1.1rem, 1.6vw, 1.28rem);
}

.entry-aside {
	position: sticky;
	top: 6.5rem;
	display: grid;
	gap: 1.5rem;
	padding: clamp(1.5rem, 3vw, 2rem);
	background: var(--k3y-surface);
	border: 1px solid var(--k3y-line);
	border-radius: var(--k3y-radius-lg);
	box-shadow: var(--k3y-shadow-sm);
}

.entry-aside .btn {
	justify-content: center;
}

.fact {
	display: grid;
	gap: 0.4rem;
}

.fact__label {
	margin: 0;
	color: var(--k3y-muted);
	font-family: var(--k3y-font-mono);
	font-size: 0.7rem;
	letter-spacing: 0.13em;
	text-transform: uppercase;
}

.fact__value {
	margin: 0;
	color: var(--k3y-ink);
	font-weight: 550;
}

.fact .feature-list {
	margin-top: 0;
}

.fact .badge {
	justify-self: start;
}

/* --- Team profile --------------------------------------------------------- */

/* This page has no page-hero canvas, so unlike the other templates it needs
 * its own compensation for the header's overlap (see --k3y-header-h). */
.profile-hero {
	padding-top: calc(var(--k3y-header-h) + var(--k3y-section));
}

.profile {
	display: grid;
	grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
	gap: clamp(2rem, 5vw, 4rem);
	align-items: start;
}

.profile__media {
	display: grid;
	place-items: center;
	aspect-ratio: 4 / 5;
	overflow: hidden;
	background: var(--k3y-surface-2);
	border-radius: var(--k3y-radius-lg);
}

.profile__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.profile__role {
	margin-bottom: 2rem;
	color: var(--k3y-brand);
	font-family: var(--k3y-font-mono);
	font-size: 0.9rem;
}

.profile__certs {
	padding-top: 2rem;
	margin-top: 2.25rem;
	border-top: 1px solid var(--k3y-line);
}

.profile__certs .fact__label {
	margin-bottom: 1rem;
}

.profile__certs .tag {
	padding: 0.5rem 0.9rem;
	font-size: 0.76rem;
}

.profile__certs .tags {
	gap: 0.6rem;
}

/* Pagination lives in style.css: it is needed on the blog, category and search
 * views, and this sheet is not enqueued there. */

/* --- Responsive ----------------------------------------------------------- */

@media (max-width: 62rem) {
	.entry-layout,
	.profile {
		grid-template-columns: minmax(0, 1fr);
	}

	.entry-aside {
		position: static;
	}
}

@media (max-width: 48rem) {
	.job__link {
		grid-template-columns: minmax(0, 1fr) auto;
		padding-block: 1.1rem;
	}

	.job__title {
		grid-column: 1;
	}

	.badge {
		grid-row: 1;
		grid-column: 2;
	}

	.job__meta {
		grid-column: 1 / -1;
	}

	.job__link:hover,
	.job__link:focus-visible {
		padding-inline: 0;
		background: transparent;
	}
}

/* --- R&D hub -------------------------------------------------------------- */




.hub {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr));
	gap: clamp(1rem, 2vw, 1.75rem);
}

.hub-card {
	position: relative;
	display: flex;
	flex-direction: column;
	padding: clamp(1.75rem, 3vw, 2.5rem);
	overflow: hidden;
	background: var(--k3y-surface);
	border: 1px solid var(--k3y-line);
	border-radius: var(--k3y-radius-lg);
	box-shadow: var(--k3y-shadow-sm);
	transition: transform var(--k3y-dur) var(--k3y-ease), box-shadow var(--k3y-dur) var(--k3y-ease);
}

/* Honeycomb bleeding out of the corner of every hub card. */
.hub-card::before {
	position: absolute;
	top: -3rem;
	right: -3rem;
	width: 13rem;
	height: 13rem;
	background-image: var(--k3y-honeycomb);
	background-size: 34px 30px;
	opacity: 0.49;
	transition: opacity var(--k3y-dur) var(--k3y-ease), transform 1.1s var(--k3y-ease);
	pointer-events: none;
	content: "";
}

.hub-card:hover {
	transform: translateY(-6px);
	box-shadow: var(--k3y-shadow-lg);
}

.hub-card:hover::before {
	opacity: 1;
	transform: rotate(12deg) scale(1.12);
}

.hub-card__top {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: space-between;
	margin-bottom: 1.5rem;
}

.hub-card__count {
	background: var(--k3y-gradient-soft);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	font-family: var(--k3y-font-display);
	font-size: 2.6rem;
	font-weight: 700;
	letter-spacing: -0.05em;
	line-height: 1;
}

.hub-card__title {
	position: relative;
	margin-bottom: 0.6rem;
	font-size: 1.6rem;
}

.hub-card__title a {
	color: inherit;
	text-decoration: none;
}

.hub-card__title a::after {
	position: absolute;
	inset: 0;
	content: "";
}

.hub-card__text {
	position: relative;
	margin-bottom: 1.5rem;
	color: var(--k3y-muted);
	font-size: 0.95rem;
}

.hub-card__list {
	position: relative;
	padding: 0;
	margin: 0 0 1.5rem;
	list-style: none;
	border-top: 1px solid var(--k3y-line);
}

.hub-card__list li {
	padding-block: 0.6rem;
	border-bottom: 1px solid var(--k3y-line);
	font-size: 0.92rem;
}

.hub-card__more {
	color: var(--k3y-brand);
	font-family: var(--k3y-font-mono);
	font-size: 0.8rem !important;
}

.hub-card__foot {
	position: relative;
	margin: auto 0 0;
}

/* --- Brace heading -------------------------------------------------------- */






/* --- Company / Vision / Mission flow -------------------------------------- */

.flow-section {
	position: relative;
	overflow: hidden;
}

.flow-section__mesh {
	position: absolute;
	inset: 0;
	background-image: var(--k3y-honeycomb);
	background-size: 38px 33px;
	opacity: 0.25;
	-webkit-mask-image: radial-gradient(ellipse 60% 60% at 50% 50%, #000 0%, transparent 72%);
	mask-image: radial-gradient(ellipse 60% 60% at 50% 50%, #000 0%, transparent 72%);
	pointer-events: none;
}

.flow {
	position: relative;
	padding: 0;
	margin: 0;
	list-style: none;
}

.flow::before {
	position: absolute;
	top: 0;
	bottom: 0;
	left: 50%;
	width: 1px;
	background: linear-gradient(to bottom, transparent, var(--k3y-brand) 12%, var(--k3y-brand-vivid) 88%, transparent);
	opacity: 0.45;
	transform: translateX(-50%);
	content: "";
}

.flow__item {
	position: relative;
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
	gap: clamp(1rem, 3vw, 2.5rem);
	align-items: center;
	padding-block: clamp(1.25rem, 3vw, 2.25rem);
}

.flow__node {
	position: relative;
	z-index: 1;
	display: grid;
	grid-column: 2;
	place-items: center;
	padding: 0.5rem;
	background: var(--k3y-ground);
	border-radius: 999px;
}

.flow__body {
	grid-column: 1;
	text-align: right;
}

.flow__item:nth-child(even) .flow__body {
	grid-column: 3;
	text-align: left;
}

.flow__label {
	margin-bottom: 0.9rem;
	font-size: clamp(1.25rem, 2.4vw, 1.75rem);
}

.flow__card {
	position: relative;
	padding: clamp(1.35rem, 2.6vw, 2rem);
	background: var(--k3y-surface);
	border: 1px solid var(--k3y-line);
	border-radius: var(--k3y-radius-lg);
	box-shadow: var(--k3y-shadow-sm);
	transition: transform var(--k3y-dur) var(--k3y-ease), box-shadow var(--k3y-dur) var(--k3y-ease), border-color var(--k3y-dur) var(--k3y-ease);
}

.flow__card p {
	margin: 0;
	color: var(--k3y-body);
}

.flow__card::after {
	position: absolute;
	top: 1.75rem;
	bottom: 1.75rem;
	width: 2px;
	background: var(--k3y-gradient-soft);
	border-radius: 2px;
	content: "";
}

.flow__item .flow__card::after {
	right: -1px;
}

.flow__item:nth-child(even) .flow__card::after {
	right: auto;
	left: -1px;
}

.flow__card:hover {
	transform: translateY(-4px);
	border-color: transparent;
	box-shadow: var(--k3y-shadow-lg);
}

/* --- Pull quote ----------------------------------------------------------- */

.pull-quote {
	margin: 0;
	text-align: center;
}

.pull-quote blockquote {
	margin: 0 0 1.25rem;
	padding: 0;
	border: 0;
}

.pull-quote p {
	margin: 0;
	color: var(--k3y-ink);
	font-family: var(--k3y-font-display);
	font-size: clamp(1.35rem, 3.2vw, 2.15rem);
	font-weight: 500;
	line-height: 1.35;
	letter-spacing: -0.025em;
	text-wrap: balance;
}

.pull-quote figcaption {
	color: var(--k3y-brand);
	font-family: var(--k3y-font-mono);
	font-size: 0.8rem;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

/* --- Certification wall --------------------------------------------------- */

.cert-wall {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
	gap: 1rem;
	padding: 0;
	margin: 0;
	list-style: none;
}

.cert-wall li {
	display: grid;
	place-items: center;
	padding: 1.75rem 1rem;
	background: var(--k3y-surface);
	border: 1px solid var(--k3y-line);
	border-radius: var(--k3y-radius);
	transition: transform var(--k3y-dur) var(--k3y-ease), box-shadow var(--k3y-dur) var(--k3y-ease);
}

.cert-wall li:hover {
	transform: translateY(-5px);
	box-shadow: var(--k3y-shadow);
}

.cert-wall img {
	width: 4.25rem;
	height: auto;
}

/* --- Watermark band ------------------------------------------------------- */

.watermark-band {
	padding-block: clamp(1rem, 3vw, 2.5rem) clamp(2.5rem, 6vw, 5rem);
	overflow: hidden;
	user-select: none;
}

.watermark-band__row {
	display: flex;
	gap: 3rem;
	width: max-content;
	color: transparent;
	font-family: var(--k3y-font-display);
	font-size: clamp(2.75rem, 10vw, 8rem);
	font-weight: 800;
	letter-spacing: -0.045em;
	line-height: 1.05;
	white-space: nowrap;
	-webkit-text-stroke: 1px var(--k3y-line-strong);
	animation: k3y-drift 46s linear infinite;
}

.watermark-band__row + .watermark-band__row {
	margin-top: 0.15em;
}

.watermark-band__row--alt {
	animation-duration: 64s;
	-webkit-text-stroke-color: var(--k3y-brand);
	opacity: 0.3;
}

/* Exactly half: the second pass of the sequence is identical, so the reset is
 * invisible. Both rows start at 0 so their left edges line up. */
@keyframes k3y-drift {
	from { transform: translateX(0); }
	to { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
	.watermark-band__row {
		animation: none !important;
	}
}

@media (max-width: 48rem) {
	.flow::before {
		left: 1.25rem;
	}

	.flow__item,
	.flow__item:nth-child(even) {
		grid-template-columns: auto minmax(0, 1fr);
		gap: 1.25rem;
	}

	.flow__node {
		grid-column: 1;
		align-self: start;
	}

	.flow__body,
	.flow__item:nth-child(even) .flow__body {
		grid-column: 2;
		text-align: left;
	}

	.flow__item .flow__card::after,
	.flow__item:nth-child(even) .flow__card::after {
		right: auto;
		left: -1px;
	}
}

/* --- People --------------------------------------------------------------- */

.people {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
	gap: clamp(1.75rem, 3.5vw, 3rem);
}

.person-card {
	position: relative;
	text-align: center;
}

.person-card__portrait {
	position: relative;
	width: min(12.5rem, 72%);
	margin: 0 auto 1.4rem;
	aspect-ratio: 0.866;
}

/* Gradient hexagon sitting just behind the portrait, revealed on hover. */
.person-card__ring {
	position: absolute;
	inset: -5px;
	background: var(--k3y-gradient);
	clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
	opacity: 0;
	transform: rotate(0deg);
	transition: opacity var(--k3y-dur) var(--k3y-ease), transform 900ms var(--k3y-ease);
}

.person-card__hex {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	overflow: hidden;
	background: var(--k3y-surface-2);
	clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

.person-card__hex img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 900ms var(--k3y-ease);
}

.person-card__initials {
	background: var(--k3y-gradient-soft);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	font-family: var(--k3y-font-display);
	font-size: 2.6rem;
	font-weight: 700;
	letter-spacing: -0.02em;
}

.person-card:hover .person-card__ring,
.person-card:focus-within .person-card__ring {
	opacity: 1;
	transform: rotate(-8deg);
}

.person-card:hover .person-card__hex img,
.person-card:focus-within .person-card__hex img {
	transform: scale(1.07);
}

.person-card__name {
	margin: 0 0 0.25rem;
	font-size: 1.12rem;
}

.person-card__name a {
	color: inherit;
	text-decoration: none;
}

.person-card__name a::after {
	position: absolute;
	inset: 0;
	content: "";
}

.person-card__role {
	margin: 0 0 0.9rem;
	color: var(--k3y-brand);
	font-family: var(--k3y-font-mono);
	font-size: 0.78rem;
	letter-spacing: 0.02em;
}

.person-card__bio {
	margin: 0 0 1rem;
	color: var(--k3y-muted);
	font-size: 0.9rem;
	line-height: 1.6;
}

.person-card__certs {
	justify-content: center;
}

/* --- Contact -------------------------------------------------------------- */

.contact-layout {
	display: grid;
	grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
	gap: clamp(1.5rem, 3.5vw, 3rem);
	align-items: start;
}

.contact-form-card {
	position: relative;
	overflow: hidden;
	padding: clamp(1.75rem, 3.5vw, 3rem);
	background: var(--k3y-surface);
	border: 1px solid var(--k3y-line);
	border-radius: var(--k3y-radius-lg);
	box-shadow: var(--k3y-shadow);
}

.contact-form-card::before {
	position: absolute;
	top: -4rem;
	right: -4rem;
	width: 15rem;
	height: 15rem;
	background-image: var(--k3y-honeycomb);
	background-size: 36px 32px;
	opacity: 0.45;
	pointer-events: none;
	content: "";
}

.contact-form-card__title {
	position: relative;
	margin-bottom: 1.75rem;
	font-size: clamp(1.35rem, 2.4vw, 1.75rem);
}

.contact-form {
	position: relative;
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 1.15rem;
}

.field {
	display: grid;
	gap: 0.45rem;
	margin: 0;
}

.field--full {
	grid-column: 1 / -1;
}

.field label {
	color: var(--k3y-ink-2);
	font-family: var(--k3y-font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

/* Honeypot: off-screen but not display:none, so bots still fill it. */
.field-trap {
	position: absolute !important;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.contact-form__actions {
	margin-top: 0.5rem;
}

.notice {
	position: relative;
	padding: 0.9rem 1.15rem;
	margin-bottom: 1.5rem;
	border-radius: var(--k3y-radius);
	font-size: 0.94rem;
}

.notice--ok {
	color: #0b6b3a;
	background: #e4f7ec;
	border: 1px solid #b9e7cd;
}

.notice--bad {
	color: #96271a;
	background: #fdecea;
	border: 1px solid #f5c6bf;
}

[data-theme="dark"] .notice--ok {
	color: #7ee2ab;
	background: rgb(18 92 54 / 35%);
	border-color: rgb(126 226 171 / 30%);
}

[data-theme="dark"] .notice--bad {
	color: #ff9c8b;
	background: rgb(120 32 20 / 35%);
	border-color: rgb(255 156 139 / 30%);
}

.contact-aside {
	display: grid;
	gap: 1rem;
}

.office-card {
	display: flex;
	gap: 1rem;
	align-items: flex-start;
	padding: clamp(1.25rem, 2.4vw, 1.6rem);
	background: var(--k3y-surface);
	border: 1px solid var(--k3y-line);
	border-radius: var(--k3y-radius-lg);
	box-shadow: var(--k3y-shadow-sm);
	transition: transform var(--k3y-dur) var(--k3y-ease), box-shadow var(--k3y-dur) var(--k3y-ease);
}

.office-card:hover {
	transform: translateY(-4px);
	box-shadow: var(--k3y-shadow);
}

.office-card--accent {
	background: var(--k3y-surface-2);
	border-color: var(--k3y-line-strong);
}

.office-card__label {
	margin: 0 0 0.5rem;
	color: var(--k3y-ink);
	font-family: var(--k3y-font-mono);
	font-size: 0.72rem;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

.office-card address {
	color: var(--k3y-muted);
	font-size: 0.94rem;
	font-style: normal;
	line-height: 1.7;
}

.office-card address a {
	color: var(--k3y-brand);
	text-decoration: none;
}

.office-card address a:hover {
	text-decoration: underline;
}

.social--light a {
	color: var(--k3y-brand);
	border-color: var(--k3y-line-strong);
}

.social--light a:hover {
	color: #fff;
	background: var(--k3y-gradient-btn);
	border-color: transparent;
}

@media (max-width: 62rem) {
	.contact-layout {
		grid-template-columns: minmax(0, 1fr);
	}
}

@media (max-width: 40rem) {
	.contact-form {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* --- Project cards -------------------------------------------------------- */

.card--project {
	gap: 1.25rem;
	padding: 0;
	overflow: hidden;
}

.card--project__mark {
	--mark-pad: clamp(1.25rem, 2.6vw, 2rem);

	display: grid;
	/* An explicit row is what makes the track definite, so the logo's
	 * height:100% has something real to resolve against. Left as an auto row,
	 * a percentage height has no basis, tall logos fall back to their intrinsic
	 * ratio and overflow the tile. */
	grid-template-rows: minmax(0, 1fr);
	place-items: center;
	/* min-height:0 matters too: without it the automatic minimum content size
	 * of a square or portrait logo beats aspect-ratio and that one card's tile
	 * grows taller than its neighbours', breaking the row's alignment. */
	min-height: 0;
	aspect-ratio: 16 / 10;
	padding: var(--mark-pad);
	overflow: hidden;
	background: var(--k3y-surface-2);
	border-bottom: 1px solid var(--k3y-line);
}

/* Supplied logos range from 200px squares to 7881px wordmarks, so each one
 * fills the same box and letterboxes inside it -- that is what makes 31
 * unrelated brand files read as one wall instead of a size lottery. */
.card--project__mark img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	transition: transform 700ms var(--k3y-ease);
}

/* White/pale artwork (the "-white" and "DarkBackground" brand variants) gets
 * the ground it was drawn for, textured with the logo's own honeycomb so the
 * flip reads as deliberate next to the light tiles. */
.card--project__mark--dark {
	background-color: var(--k3y-brand-ink);
	background-image: var(--k3y-honeycomb);
	background-size: 34px 30px;
	border-bottom-color: var(--k3y-brand-deep);
}

.card--project:hover .card--project__mark img {
	transform: scale(1.05);
}

.card--project__initials {
	background: var(--k3y-gradient-soft);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	font-family: var(--k3y-font-display);
	font-size: 2.4rem;
	font-weight: 700;
}

.card--project__body {
	display: flex;
	flex: 1;
	flex-direction: column;
	padding: 0 clamp(1.25rem, 2.4vw, 1.75rem) clamp(1.25rem, 2.4vw, 1.75rem);
}

.card--project__tags {
	margin-bottom: 0.85rem;
}

.card--project .card__title {
	margin-block: 0 0.5rem;
	font-family: var(--k3y-font-display);
	font-size: 1.2rem;
	font-weight: 600;
	letter-spacing: -0.02em;
}

/* The project's real title, sitting under the acronym the way it does on the
 * project page itself. */
.card--project__subline {
	margin: 0 0 1.25rem;
	color: var(--k3y-body);
	font-size: 0.92rem;
	line-height: 1.5;
}

.card--project__facts {
	display: grid;
	gap: 0.55rem;
	margin: auto 0 0;
	padding-top: 1rem;
	border-top: 1px solid var(--k3y-line);
}

/* Stacked rather than label-left/value-right: the durations run to
 * "1 January 2023 to 31 December 2025 (36 months)", which ragged-rights badly
 * in a two-column row. */
.card--project__fact dt {
	color: var(--k3y-muted);
	font-family: var(--k3y-font-mono);
	font-size: 0.64rem;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

.card--project__fact dd {
	margin: 0.15rem 0 0;
	color: var(--k3y-ink-2);
	font-family: var(--k3y-font-mono);
	font-size: 0.74rem;
	line-height: 1.4;
}

.project-mark {
	display: grid;
	place-items: center;
	padding: 1.25rem;
	background: var(--k3y-surface-2);
	border: 1px solid var(--k3y-line);
	border-radius: var(--k3y-radius);
}

/* Same reasoning as the card tile: the white/pale brand variants need the
 * ground they were drawn for, or they vanish on the light theme's surface. */
.project-mark--dark {
	background-color: var(--k3y-brand-ink);
	background-image: var(--k3y-honeycomb);
	background-size: 34px 30px;
	border-color: var(--k3y-brand-deep);
}

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