/* =========================================================================
   Emre Portfolio — Heritage Futurism / M3 Expressive / CRT screen presence
   Mirrors project/Emre Portfolio.dc.html and project/Case Study.dc.html
   ========================================================================= */

/* ---------- Reset & tokens ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
	margin: 0;
	background: var(--body-bg);
	font-family: 'Archivo', sans-serif;
	color: var(--fg);
}
/* Desktop: the app IS the viewport and the CRT screen (.site-scroll) scrolls
   internally. Lock the document so the browser window itself can never scroll —
   without this, anything that adds page height (a plugin banner, an injected
   node, the logged-in admin bar) spawns a SECOND browser scrollbar right next
   to the screen's own thin one. Phones re-enable native window scroll below
   (they don't use the inner scroller). */
html, body { height: 100%; overflow: hidden; }
h1, h2, h3, p { margin: 0; }
a { color: inherit; }
img { max-width: 100%; display: block; }
button { font-family: inherit; }

/* Theme tokens live on :root (the <html> element) so a tiny head script can
   set data-theme before first paint — no theme flash for returning visitors. */
:root {
	--body-bg: #0c1310;
	--fg: #f4f8f5;
	--body: #d2e2db;
	--muted: #c4d4cc;
	--faint: #9cb6a9;
	--card: linear-gradient(150deg, #2c4034 0%, #21332a 100%);
	--shell: linear-gradient(180deg, rgba(34,54,46,0.36) 0%, rgba(40,60,51,0.36) 40%, rgba(34,54,46,0.36) 100%);
	--app-bg: linear-gradient(180deg, #17231d 0%, #0d1310 100%);
	/* Section backgrounds — lifted off near-black so it reads warm, not somber.
	   Kept a touch translucent so the (behind-content) aperture grille can still
	   show through when a visitor turns it up. */
	--sec-hero: rgba(36,58,49,0.95);      /* teal-green */
	--sec-projects: rgba(31,62,51,0.95);  /* green */
	--sec-about: rgba(72,57,33,0.95);     /* amber — grouped with journey/CV */
	--sec-services: rgba(58,47,84,0.95);  /* violet */
	--sec-cv: rgba(74,60,35,0.95);        /* amber */
	--sec-contact: rgba(35,58,76,0.95);   /* blue */
	--mint: #7fd9c4;
	--cyan: #7cc4e8;
	--violet: #b3a5f2;
	--amber: #e5c37c;
	--coral: #eda184;
}
/* Genuine light theme — light, airy surfaces (not an inverted dark theme). */
/* "Warm Archive Futurism" — museum paper, green-black type, mint accents.
   Illuminated, not bleached: the dark mode caught in daylight, not inverted. */
:root[data-theme="light"] {
	--body-bg: #e6e0d1;               /* soft stone behind the tube */
	--fg: #14241d;                    /* deep green-black — primary text */
	--body: #4a564d;                  /* secondary */
	--muted: #57635a;                 /* body copy — darker for comfortable contrast */
	--faint: #78847b;                 /* mono micro-labels */
	--card: linear-gradient(180deg, #ffffff 0%, #fbf9f2 100%); /* clean elevated card */
	--shell: linear-gradient(180deg, rgba(250,248,241,0.7) 0%, rgba(244,240,230,0.7) 40%, rgba(250,248,241,0.7) 100%);
	--app-bg: linear-gradient(180deg, #e9e4d6 0%, #ddd7c8 100%);
	--gold: #9a7a34;                  /* richer archive gold for kickers */
	--border-hair: #d7d1c3;
	/* Section surfaces — one cohesive warm-paper family with only a whisper of
	   hue (no jarring lavender/blue bands); structure comes from the cards. */
	--sec-hero: #f5f1e7;
	--sec-projects: #efeadf;
	--sec-about: #eef1ee;
	--sec-services: #f2eee3;
	--sec-cv: #f3efe3;
	--sec-contact: #ecf0ea;
}

/* Light-mode variants of the decorative radial glows (the dark-teal ellipses
   would read as smudges on a light surface). */
:root[data-theme="light"] .hero {
	background-image: radial-gradient(ellipse 90% 70% at 50% 30%, rgba(127,217,196,0.16) 0%, rgba(255,255,255,0) 70%);
}
:root[data-theme="light"] .section--contact,
:root[data-theme="light"] .case-footer-cta {
	background-image: radial-gradient(ellipse 70% 60% at 50% 100%, rgba(127,217,196,0.16) 0%, rgba(255,255,255,0) 70%);
}
:root[data-theme="light"] .hero__hud-grid,
:root[data-theme="light"] .case-hero__grid {
	background-image: linear-gradient(rgba(20,60,50,0.06) 1px, transparent 1px), linear-gradient(90deg, rgba(20,60,50,0.06) 1px, transparent 1px);
}
/* The deep corner vignette reads as grime on a light surface — lift it. */
:root[data-theme="light"] .crt-vignette {
	background:
		radial-gradient(ellipse 76% 78% at 50% 50%, rgba(40,50,44,0) 58%, rgba(40,50,44,0.06) 84%, rgba(40,50,44,0.13) 100%),
		radial-gradient(ellipse 120% 90% at 50% 45%, rgba(143,214,200,0.05) 0%, rgba(0,0,0,0) 60%);
	box-shadow: inset 0 0 120px rgba(28,42,36,0.1), inset 0 0 40px rgba(28,42,36,0.07), inset 0 0 28px rgba(143,214,200,0.06);
}

/* --- Category cards: light, with their own colour temperature + dark hue label
   (per the Warm Archive spec — legible, not pastel). --- */
:root[data-theme="light"] .domain-tile { border-color: var(--border-hair) !important; }
:root[data-theme="light"] .domain-tile--branding { background: #dde8df !important; }
:root[data-theme="light"] .domain-tile--rendering { background: #dde5ea !important; }
:root[data-theme="light"] .domain-tile--multimedia-design { background: #e4e0f0 !important; }
:root[data-theme="light"] .domain-tile--engineering { background: #eee4cf !important; }
:root[data-theme="light"] .domain-tile--3d-modelling { background: #e8d8ce !important; }
:root[data-theme="light"] .domain-tile:hover { border-color: rgba(16,35,29,0.28) !important; }
:root[data-theme="light"] .domain-tile--branding .domain-tile__label { color: #2f6f5d !important; }
:root[data-theme="light"] .domain-tile--rendering .domain-tile__label { color: #355b6a !important; }
:root[data-theme="light"] .domain-tile--multimedia-design .domain-tile__label { color: #5a4e86 !important; }
:root[data-theme="light"] .domain-tile--engineering .domain-tile__label { color: #8a6a2e !important; }
:root[data-theme="light"] .domain-tile--3d-modelling .domain-tile__label { color: #8a4f35 !important; }

/* --- Buttons --- */
:root[data-theme="light"] .btn--primary { background: #8fd6c8; color: #10231d; box-shadow: 0 16px 50px rgba(143,214,200,0.35); }
:root[data-theme="light"] .btn--primary:hover { background: #72c7b6; }
:root[data-theme="light"] .btn--secondary { background: transparent; color: #10231d; border-color: #9baa9f; }
:root[data-theme="light"] .btn--secondary:hover { background: #72c7b6; color: #10231d; border-color: #72c7b6; }
:root[data-theme="light"] .btn--outline { background: rgba(16,35,29,0.04); color: #2f6f5d; border-color: #9baa9f; }
:root[data-theme="light"] .btn--outline:hover { background: rgba(143,214,200,0.25); color: #10231d; }

/* --- Nav / brand seal / gold labels --- */
:root[data-theme="light"] .site-nav__mark { background: #10231d; color: #8fd6c8; border-color: rgba(16,35,29,0.2); box-shadow: 0 0 20px rgba(16,35,29,0.12); }
:root[data-theme="light"] .site-nav__link:hover { background: rgba(143,214,200,0.22); color: #10231d; }
:root[data-theme="light"] .section-kicker { color: var(--gold) !important; }

/* --- Ribbon + hairlines + form fields on paper --- */
:root[data-theme="light"] .ribbon__item { background: rgba(16,35,29,0.02); border-color: var(--border-hair); color: #66756c; }
:root[data-theme="light"] .cv-list { border-left-color: rgba(16,35,29,0.16); }
:root[data-theme="light"] .service-card { border-color: var(--border-hair); }
:root[data-theme="light"] .training-card { border-color: rgba(90,78,134,0.25); }
:root[data-theme="light"] .project-card__frame { border-color: rgba(16,35,29,0.12); }
:root[data-theme="light"] .cv-detail, :root[data-theme="light"] .contact-panel { border-color: var(--border-hair); }
:root[data-theme="light"] .form-field input, :root[data-theme="light"] .form-field select, :root[data-theme="light"] .form-field textarea { background: rgba(16,35,29,0.03); border-color: var(--border-hair); }
:root[data-theme="light"] .form-field input:focus, :root[data-theme="light"] .form-field select:focus, :root[data-theme="light"] .form-field textarea:focus { border-color: #72c7b6; background: rgba(143,214,200,0.12); }
:root[data-theme="light"] .contact-email { color: #2f6f5d; }
:root[data-theme="light"] .section-head, :root[data-theme="light"] .cv-footer, :root[data-theme="light"] .ribbon { border-color: var(--border-hair); }
/* Bright neon accents get muted so they read on warm paper. */
:root[data-theme="light"] .hero__kicker span,
:root[data-theme="light"] .services-row-head__label,
:root[data-theme="light"] .case-brief-col__kicker { filter: brightness(0.6) saturate(1.35); }
:root[data-theme="light"] .hero__tagline-accent { color: #2f6f5d; }
:root[data-theme="light"] .cv-detail__org, :root[data-theme="light"] .cv-list__item.is-active .cv-list__years { color: #2f6f5d; }

/* --- Elevation on paper: replace the dark-mode shadows with soft warm ones so
   cards genuinely float instead of smudging grey, and give them crisp borders. --- */
:root[data-theme="light"] .service-card,
:root[data-theme="light"] .training-card,
:root[data-theme="light"] .cv-detail,
:root[data-theme="light"] .contact-panel {
	box-shadow: 0 1px 2px rgba(40,50,44,0.04), 0 14px 34px rgba(40,50,44,0.09);
	border-color: var(--border-hair);
}
:root[data-theme="light"] .service-card:hover,
:root[data-theme="light"] .training-card:hover {
	box-shadow: 0 2px 4px rgba(40,50,44,0.06), 0 22px 46px rgba(40,50,44,0.15);
	border-color: rgba(31,143,118,0.4);
}
:root[data-theme="light"] .project-card__frame { box-shadow: 0 1px 2px rgba(40,50,44,0.05), 0 10px 26px rgba(40,50,44,0.08); }
:root[data-theme="light"] .project-card:hover .project-card__frame { box-shadow: 0 3px 6px rgba(40,50,44,0.08), 0 24px 52px rgba(40,50,44,0.18); }
:root[data-theme="light"] .cv-detail { border-radius: 28px 28px 96px 28px; }
:root[data-theme="light"] .contact-success__icon { background: rgba(31,143,118,0.1); border-color: rgba(31,143,118,0.35); color: #1f8f76; }
/* Service/training accent chips + arrows, readable on paper. */
:root[data-theme="light"] .service-card__arrow { background: rgba(31,143,118,0.12) !important; color: #1f8f76 !important; }
:root[data-theme="light"] .training-card__arrow { background: rgba(90,78,134,0.14); color: #5a4e86; }
:root[data-theme="light"] .services-row-head__line { background: rgba(31,143,118,0.22) !important; }
:root[data-theme="light"] .contact-email__dot { background: #1f8f76; box-shadow: 0 0 10px rgba(31,143,118,0.5); }
:root[data-theme="light"] .cv-detail__years { color: var(--gold); }
:root[data-theme="light"] .cv-list__item:hover, :root[data-theme="light"] .cv-list__item.is-active { background: rgba(31,143,118,0.1); }
/* Services matrix on paper: paper-readable accents + floating tier cards. */
:root[data-theme="light"] .svc-col--a { --svc-accent: #2f6f5d; }
:root[data-theme="light"] .svc-col--b { --svc-accent: #8a6a2e; }
:root[data-theme="light"] .svc-col--c { --svc-accent: #5a4e86; }
:root[data-theme="light"] .svc-tier { background: var(--card); box-shadow: 0 1px 2px rgba(40,50,44,0.04), 0 10px 26px rgba(40,50,44,0.07); }
:root[data-theme="light"] .svc-group__line { background: var(--border-hair); }
:root[data-theme="light"] .svc-group__foot { color: #78847b; }
:root[data-theme="light"] .svc-group--think .svc-group__line { background: rgba(90,78,134,0.22); }
/* Softer, warmer inner scroll shadow than the dark-mode teal-on-black glow. */
:root[data-theme="light"] .site-scroll { box-shadow: 0 0 0 1px rgba(40,50,44,0.04), 0 20px 60px rgba(40,50,44,0.1); }

/* ---------- Keyframes ---------- */
@keyframes floatSoft { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }
@keyframes marqueeX { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes riseIn { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: translateY(0); } }
@keyframes riseInSoft { from { opacity: 0; transform: translateY(40px) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes scanSweep { 0% { transform: translateY(-120%); opacity: 0; } 12% { opacity: 0.9; } 60%, 100% { transform: translateY(240%); opacity: 0; } }
@keyframes nameReveal { 0% { clip-path: inset(0 100% 0 0); opacity: 0; } 8% { opacity: 1; } 100% { clip-path: inset(0 0 0 0); opacity: 1; } }
@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
@keyframes navDrop { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: translateY(0); } }
@keyframes driftGrid { from { background-position: 0 0; } to { background-position: 44px 44px; } }

/* ---------- App shell / CRT chrome ---------- */
.emre-app {
	font-family: 'Archivo', sans-serif;
	color: var(--fg);
	background: var(--app-bg);
	/* Fill the locked document exactly (html/body are 100% of the viewport and
	   overflow-hidden). Using 100% — not 100dvh — means when the shell has to
	   shrink (admin bar) the app follows the document instead of overflowing it. */
	height: 100%;
	overflow: hidden;
	position: relative;
	/* Full-bleed: the CRT screen fills the whole viewport (no bezel inset), so the
	   glass/curvature overlay never crops across content like the old framed warp
	   did. Phones re-add a small safe-area inset below. */
	padding: 0;
}
.emre-screen { height: 100%; border-radius: 0; overflow: hidden; position: relative; z-index: 2; }
.site-scroll {
	height: 100%;
	overflow-y: auto;
	overflow-x: hidden;
	border-radius: 0;
	background: var(--shell);
	/* Content is never filtered — the CRT character comes from the fixed glass /
	   curvature / scanline overlays composited on top, all GPU-cheap gradients. */
	filter: none;
}
/* Inner scrollbar: a slim, themed bar instead of the clunky OS default. Because
   the content is no longer filtered, the scrollbar renders normally again. */
.site-scroll { scrollbar-width: thin; scrollbar-color: rgba(127,217,196,0.32) transparent; }
.site-scroll::-webkit-scrollbar { width: 10px; }
.site-scroll::-webkit-scrollbar-track { background: transparent; }
.site-scroll::-webkit-scrollbar-thumb {
	background: rgba(127,217,196,0.28); border-radius: 999px;
	border: 3px solid transparent; background-clip: padding-box;
}
.site-scroll::-webkit-scrollbar-thumb:hover { background: rgba(127,217,196,0.5); background-clip: padding-box; }

/* --- Logged-in admin bar ---
   WordPress adds `margin-top:32px` to <html> for the fixed admin bar, which
   pushes the locked document 32px past the viewport bottom. Shrink the document
   by that much (the app fills it via height:100%) so the window still fits with
   no second scrollbar, and drop the viewport-anchored CRT overlays down 32px so
   the frame lines up with the shifted screen. `:has()` lets us reach <html>
   from the `.admin-bar` class WordPress puts on <body>. Desktop-only: phones
   (≤860px) scroll the window natively and need no compensation. */
@media screen and (min-width: 861px) {
	:root:has(body.admin-bar) { height: calc(100% - 32px); }
	.admin-bar .crt-lines,
	.admin-bar .crt-vignette,
	.admin-bar .crt-bulge,
	.admin-bar .crt-gloss,
	.admin-bar .crt-fringe { top: 32px; }
	.admin-bar .case-topbar { top: 32px; }
}

/* Fixed, full-screen glass overlays composited over the content. All are cheap
   gradients (no SVG/displacement filter, no per-frame work) so the "curved tube"
   read costs nothing to scroll. z-order: 60 curvature · 61 glass · 62 edge glow.
   They start neutral so first paint matches the saved state with no flash. */

/* Cadence §11: five static layers, one paint, no animation. Ported from
   assets/css/styleguide.css, where they sit on a bordered panel; here they are
   fixed to the viewport because the whole screen IS the tube. Values are the
   guide's, unchanged — only positioning and z-index are ours.

   What went: the animated flicker and rolling refresh bar (the guide's "no
   animation" rules them out, and they were the two layers that made the effect
   read as a costume), the RGB aperture grille, the separate edge glow, and the
   old glass reflection — bulge + gloss cover that read more quietly. */
.crt-lines {
	position: fixed; inset: 0; pointer-events: none; z-index: 60;
	/* 1px on 3px in the theme's own mint, not black: a tint rather than a mask,
	   which is why it reads as phosphor instead of as a dark grille. */
	background: repeating-linear-gradient(180deg, rgba(127,217,196,0.055) 0 1px, transparent 1px 3px);
}
/* The guide's values were authored against a wide panel. On a phone the same
   ellipse is far narrower than it is tall, so the dark edge closes in on text
   that has nowhere else to go — hence a weaker, later-starting falloff below
   860px, and a slightly stronger one on desktop where the darkening lands on
   margin rather than on words. */
.crt-vignette {
	position: fixed; inset: 0; pointer-events: none; z-index: 61;
	background: radial-gradient(ellipse 92% 82% at 50% 46%, transparent 52%, rgba(4,9,7,0.5) 100%);
}
@media (min-width: 861px) {
	.crt-vignette { background: radial-gradient(ellipse 94% 86% at 50% 46%, transparent 50%, rgba(4,9,7,0.62) 100%); }
}
@media (max-width: 860px) {
	.crt-vignette { background: radial-gradient(ellipse 120% 100% at 50% 48%, transparent 66%, rgba(4,9,7,0.3) 100%); }
	/* The bulge reads as a second vignette on a narrow screen; halve it. */
	.crt-bulge { box-shadow: inset 0 0 14px 3px rgba(4,9,7,0.2), inset 0 0 48px 8px rgba(4,9,7,0.09); }
}
.crt-bulge {
	position: fixed; inset: 0; pointer-events: none; z-index: 62;
	/* Two inset shadows, tight then wide — the glass thickening toward the
	   frame. This is what carries the curvature now that nothing warps content. */
	box-shadow: inset 0 0 20px 4px rgba(4,9,7,0.34), inset 0 0 70px 12px rgba(4,9,7,0.16);
}
.crt-gloss {
	position: fixed; inset: 0; pointer-events: none; z-index: 63;
	background: radial-gradient(ellipse 34% 20% at 28% 13%, rgba(244,248,245,0.13) 0%, transparent 68%);
}
.crt-fringe {
	position: fixed; inset: 0; pointer-events: none; z-index: 64;
	/* Chromatic split at the edges: cool one side, warm the other. Static tint,
	   so no content is ever displaced per-pixel. */
	background: linear-gradient(90deg, rgba(124,196,232,0.16) 0%, transparent 12%, transparent 88%, rgba(237,161,132,0.14) 100%);
}
/* Light theme ("Warm Archive") — same five layers, warmer and weaker, straight
   from the guide. The dark values read as grime on a light surface. */
:root[data-theme="light"] .crt-lines {
	background: repeating-linear-gradient(180deg, rgba(20,36,29,0.045) 0 1px, transparent 1px 3px);
}
:root[data-theme="light"] .crt-bulge {
	box-shadow: inset 0 0 20px 4px rgba(122,110,84,0.2), inset 0 0 70px 12px rgba(122,110,84,0.1);
}
:root[data-theme="light"] .crt-gloss {
	background: radial-gradient(ellipse 34% 20% at 28% 13%, rgba(255,255,255,0.42) 0%, transparent 68%);
}
:root[data-theme="light"] .crt-fringe {
	background: linear-gradient(90deg, rgba(42,111,150,0.12) 0%, transparent 12%, transparent 88%, rgba(160,77,42,0.1) 100%);
}
.crt-cursor-glow {
	position: fixed; top: 0; left: 0; z-index: 90; pointer-events: none; opacity: 0;
	transition: opacity .6s ease; will-change: transform; mix-blend-mode: screen;
}
.crt-cursor-glow__outer {
	position: absolute; transform: translate(-50%, -50%); width: 300px; height: 300px; border-radius: 50%;
	background: radial-gradient(circle, rgba(143,227,207,0.05) 0%, rgba(143,227,207,0.03) 26%, rgba(143,227,207,0.012) 48%, rgba(127,217,196,0.004) 64%, rgba(127,217,196,0) 80%);
	filter: blur(16px);
}
.crt-cursor-glow__inner {
	position: absolute; transform: translate(-50%, -50%); width: 120px; height: 120px; border-radius: 50%;
	background: radial-gradient(circle, rgba(170,240,222,0.06) 0%, rgba(143,227,207,0.03) 45%, rgba(143,227,207,0.008) 70%, rgba(143,227,207,0) 88%);
	filter: blur(10px);
}
/* Theme switch-over. A colour cross-fade alone reads as a repaint rather than
   as a switch, so the tube gets a moment: a phosphor bloom washes across the
   screen and settles. Opacity only, on a layer that already exists, so nothing
   reflows and the cost is one composite. main.js adds .is-theme-switching for
   700ms; reduced motion never gets the class, and this rule is inert without it. */
@keyframes crtThemeBloom {
	0%   { opacity: 0; }
	14%  { opacity: 1; }
	100% { opacity: 0; }
}
/* Deliberately outlasts nothing and undercuts nothing: the bloom rises fast,
   then decays across the whole 1.1s colour cross-fade above, so the flash and
   the change are one gesture instead of a flash followed by a change. */
.is-theme-switching .crt-gloss {
	animation: crtThemeBloom 1.15s cubic-bezier(.22,.9,.3,1) both;
}
.is-theme-switching .crt-lines {
	animation: crtThemeBloom .9s ease both;
}

/* Master CRT toggle — hide the whole screen-presence stack in one rule. */
.crt-hidden .crt-layer { display: none !important; }

/* ---------- Layout primitives ---------- */
.section { padding: 68px 48px; box-sizing: border-box; position: relative; --sec-fade: 170px; }
/* Skip rendering below-the-fold sections until they're scrolled near — big win
   for scroll smoothness + first paint on a long one-pager. (Hero excluded.) */
.section--projects, .section--about, .section--services, .section--cv, .section--contact,
.case-section { content-visibility: auto; contain-intrinsic-size: auto 720px; }

/* Soft section seams. Each coloured section fades in from the PREVIOUS section's
   colour over its top ~200px, so neighbours meet in the same tone instead of a
   hard line. Painted as a background layer (behind content); the hard stop to
   transparent lets each section's own inline colour fill the rest. Contact adds
   its glow layer in its own rule above. */
.section--projects { background-image: linear-gradient(180deg, var(--sec-hero) 0%, var(--sec-projects) var(--sec-fade), rgba(0,0,0,0) var(--sec-fade)); }
.section--services { background-image: linear-gradient(180deg, var(--sec-projects) 0%, var(--sec-services) var(--sec-fade), rgba(0,0,0,0) var(--sec-fade)); }
.section--about    { background-image: linear-gradient(180deg, var(--sec-services) 0%, var(--sec-about) var(--sec-fade), rgba(0,0,0,0) var(--sec-fade)); }
.section--cv       { background-image: linear-gradient(180deg, var(--sec-about) 0%, var(--sec-cv) var(--sec-fade), rgba(0,0,0,0) var(--sec-fade)); }
/* Copy starts BELOW the fade so headings never sit inside the colour transition.
   (Placed after the per-section padding rules below via .svc-fade-pad.) */

.section__inner { max-width: min(1760px, 92vw); margin: 0 auto; }
.section-kicker { font-family: 'IBM Plex Mono', monospace; font-size: 12px; letter-spacing: 0.3em; }
.section-title { font-size: 52px; font-weight: 800; letter-spacing: -0.02em; color: var(--fg); }
.section-head { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; margin-bottom: 40px; }
.section-head--baseline { align-items: baseline; margin-bottom: 48px; }

/* Off the full pill.
   A 999px radius on every button is the default of every AI-built and
   template-built site of the last two years, and it is the first thing that
   makes a page look generic. The site already has its own shape language: one
   corner softer than the other three (--r-*). Buttons now use it, so they read
   as belonging to this design rather than to the era. */
.btn {
	cursor: pointer; border: none; border-radius: 14px 14px 26px 14px; font-family: 'Archivo', sans-serif;
	font-weight: 700; letter-spacing: 0.02em;
	/* NB: border-radius is deliberately NOT transitioned. The bouncy easing below
	   overshoots, and on a radius that overshoot dips toward 0 — which flashed the
	   pill into a rectangle for a moment mid-hover. Animate only transform/shadow/
	   colour; the pill shape stays constant. */
	transition: transform .4s var(--ease-bouncy), box-shadow .4s var(--ease-bouncy), background .3s ease, color .3s ease, border-color .3s ease;
	text-decoration: none; display: inline-flex; align-items: center; justify-content: center;
}
.btn--primary {
	padding: 20px 48px; font-size: 17px; color: #0a100e;
	background: linear-gradient(135deg, #8fe3cf, #6cc9b2);
	box-shadow: 0 10px 34px rgba(127,217,196,0.3);
}
.btn--primary:hover { transform: translateY(-3px) scale(1.04); box-shadow: 0 18px 46px rgba(127,217,196,0.4); }
.btn--primary:active { transform: scale(0.955); }
/* Cadence §04 — press = the Fast spring on every button (scale ≈0.955). */
.btn--secondary:active, .btn--outline:active { transform: scale(0.955); }
.btn--secondary {
	padding: 20px 44px; font-size: 17px; font-weight: 600; color: var(--body);
	border: 1px solid rgba(127,217,196,0.4); background: rgba(127,217,196,0.06);
}
.btn--secondary:hover { transform: translateY(-3px); border-color: rgba(127,217,196,0.8); color: #8fe3cf; }
.btn--outline {
	border: 1px solid rgba(127,217,196,0.4); background: rgba(127,217,196,0.1); color: #7fd9c4;
	padding: 13px 28px; font-family: 'IBM Plex Mono', monospace; font-size: 12px; letter-spacing: 0.14em;
}
.btn--outline:hover { background: rgba(127,217,196,0.2); transform: translateY(-2px); }
.btn--block { width: 100%; padding: 18px; font-size: 16px; box-shadow: 0 10px 30px rgba(127,217,196,0.25); }
.btn--block:hover { box-shadow: 0 16px 40px rgba(127,217,196,0.4); }
.btn--small { padding: 11px 22px; font-family: 'IBM Plex Mono', monospace; font-size: 12px; letter-spacing: 0.16em; }
.btn--small:hover { transform: translateY(-2px); }
.btn--large { margin-top: 8px; padding: 20px 52px; font-size: 17px; box-shadow: 0 10px 30px rgba(127,217,196,0.25); }
.btn--large:hover { transform: translateY(-3px) scale(1.04); }

/* ---------- Site nav (sticky) ----------
   Pinned to the top of the scroll shell so the menu stays reachable from any
   section, not just the hero. The translucent backdrop keeps the links legible
   as the coloured sections scroll underneath. */
.site-nav {
	position: sticky; top: 0; z-index: 40;
	display: flex; justify-content: space-between; align-items: center; gap: 20px;
	padding: 11px 64px;
	background: rgba(10,16,14,0.72);
	backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
	border-bottom: 1px solid rgba(127,217,196,0.12);
}
:root[data-theme="light"] .site-nav {
	background: rgba(244,247,245,0.78);
	border-bottom-color: var(--border-hair);
}
.site-nav__brand { display: flex; align-items: center; gap: 14px; }
.site-nav__mark {
	width: 48px; height: 48px; border-radius: 15px 15px 15px 25px;
	background: linear-gradient(135deg, #16241f, #0f1a16); border: 1px solid rgba(127,217,196,0.28);
	display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 18px;
	color: #7fd9c4; box-shadow: 0 0 20px rgba(127,217,196,0.14);
}
.site-nav__lockup { display: flex; flex-direction: column; gap: 2px; }
.site-nav__name { font-size: 15px; font-weight: 800; letter-spacing: 0.04em; color: var(--fg); }
.site-nav__role { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.22em; color: var(--faint); }
.site-nav__links { display: flex; gap: 6px; }
.site-nav__link {
	cursor: pointer; padding: 11px 22px; border-radius: 11px 11px 20px 11px; font-family: 'IBM Plex Mono', monospace;
	font-size: 14px; letter-spacing: 0.14em; color: var(--body); text-decoration: none;
	transition: all .3s var(--ease-bouncy);
}
.site-nav__link:hover { background: rgba(127,217,196,0.12); color: #7fd9c4; transform: translateY(-2px); }
.site-nav__link--contact { padding: 11px 24px; color: #0a100e; background: linear-gradient(135deg, #8fe3cf, #6cc9b2); }
.site-nav__link--contact:hover { transform: translateY(-2px); box-shadow: 0 10px 24px rgba(127,217,196,0.3); background: linear-gradient(135deg, #8fe3cf, #6cc9b2); color: #0a100e; }
/* Hamburger toggle — injected by main.js, shown only on mobile (see media query). */
.site-nav__toggle { display: none; }
/* Scrollspy: the current section's link carries a persistent, subtle highlight. */
.site-nav__link.is-current:not(.site-nav__link--contact) { color: #8fe3cf; background: rgba(127,217,196,0.10); }
:root[data-theme="light"] .site-nav__link.is-current:not(.site-nav__link--contact) { color: #2f6f5d; background: rgba(31,143,118,0.10); }

/* ---------- Hero ---------- */
.hero {
	min-height: calc(100vh - var(--nav-h, 71px) - 20px); min-height: calc(100dvh - var(--nav-h, 71px) - 20px);
	display: flex; flex-direction: column; padding: 20px 64px 18px;
	overflow: hidden; background-image: radial-gradient(ellipse 90% 70% at 50% 30%, rgba(30,52,45,0.55) 0%, rgba(10,16,14,0) 70%);
}
.hero__hud-grid {
	position: absolute; inset: 0; pointer-events: none; opacity: 0.5;
	background-image: linear-gradient(rgba(127,217,196,0.05) 1px, transparent 1px), linear-gradient(90deg, rgba(127,217,196,0.05) 1px, transparent 1px);
	background-size: 44px 44px; animation: driftGrid 14s linear infinite;
	-webkit-mask-image: radial-gradient(ellipse 80% 70% at 50% 42%, #000 0%, transparent 78%);
	mask-image: radial-gradient(ellipse 80% 70% at 50% 42%, #000 0%, transparent 78%);
}
.hero__scan-sweep {
	position: absolute; left: 0; right: 0; top: 0; height: 38%; pointer-events: none;
	background: linear-gradient(180deg, rgba(143,227,207,0.10) 0%, rgba(143,227,207,0) 100%);
	animation: scanSweep 7s cubic-bezier(.4,0,.2,1) infinite;
}
/* Optional hero background media (Portfolio Content → Hero) — sits behind the
   HUD grid, scan sweep and content. Layer opacity is set inline from the option,
   so the owner controls how present it is; content stays z-index 2. */
.hero__bg { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.hero__bg-slides { position: absolute; inset: 0; }
.hero__bg-slide {
	position: absolute; inset: 0; background-size: cover; background-position: center;
	opacity: 0; transition: opacity 1.4s ease;
}
.hero__bg-slide.is-active { opacity: 1; }
/* A single image (no rotation) is always shown. */
.hero__bg-slides:not(.hero__bg-slides--rotate) .hero__bg-slide { opacity: 1; }
/* Sequence mode: the video and the image set are two phases that cross-fade
   between each other (JS toggles .is-active); inside the image phase the slides
   still cross-fade among themselves. */
.hero__bg-phase { position: absolute; inset: 0; opacity: 0; transition: opacity 1s ease; }
.hero__bg-phase.is-active { opacity: 1; }
.hero__bg-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Cover-fit a 16:9 YouTube/Vimeo iframe to the hero (oversize + clip). */
.hero__bg-embed { position: absolute; inset: 0; overflow: hidden; }
.hero__bg-embed iframe {
	position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); border: 0;
	width: 100vw; height: 56.25vw; min-height: 100vh; min-width: 177.78vh;
}
@media (prefers-reduced-motion: reduce) {
	.hero__bg-slide, .hero__bg-phase { transition: none; }
}

/* A scrim between the footage and the words.
   Text was sitting straight on moving video, so legibility depended on which
   frame happened to be playing: fine over a dark passage, gone over a bright
   one. A background you do not control cannot be trusted to stay out of the
   way, and the fix is not to dim the whole video (that wastes the image) but to
   darken the middle band where the copy actually lives, leaving the edges of
   the frame at full strength. Sits above the media and below .hero__content,
   which is z-index 2. */
.hero__bg::after {
	content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
	background:
		radial-gradient(ellipse 78% 62% at 50% 52%, rgba(8,14,12,0.68) 0%, rgba(8,14,12,0.42) 55%, rgba(8,14,12,0) 82%),
		linear-gradient(180deg, rgba(8,14,12,0.5) 0%, rgba(8,14,12,0.12) 34%, rgba(8,14,12,0.12) 66%, rgba(8,14,12,0.55) 100%);
}
/* Warm Archive needs the opposite treatment: the page is pale, so the copy is
   dark, and it is a BRIGHT frame that erases it. Lift the band toward white
   instead of pushing it toward black. */
:root[data-theme="light"] .hero__bg::after {
	background:
		radial-gradient(ellipse 78% 62% at 50% 52%, rgba(247,246,240,0.82) 0%, rgba(247,246,240,0.55) 55%, rgba(247,246,240,0) 82%),
		linear-gradient(180deg, rgba(247,246,240,0.6) 0%, rgba(247,246,240,0.2) 34%, rgba(247,246,240,0.2) 66%, rgba(247,246,240,0.65) 100%);
}
/* Last-resort separation for the two lines that must always read, whatever is
   underneath them. A shadow rather than a heavier scrim, so the footage keeps
   its contrast everywhere the text is not. */
.hero__name, .hero__tagline {
	text-shadow: 0 1px 2px rgba(6,12,10,0.45), 0 2px 18px rgba(6,12,10,0.35);
}
:root[data-theme="light"] .hero__name,
:root[data-theme="light"] .hero__tagline {
	text-shadow: 0 1px 2px rgba(255,255,255,0.7), 0 2px 18px rgba(247,246,240,0.75);
}

.hero__content {
	position: relative; z-index: 2; flex: 1; display: flex; flex-direction: column; align-items: center;
	justify-content: center; gap: 24px; text-align: center; padding: 32px 0 28px;
}
/* Name lockup: a small courtesy title (Ing. = ingenieur) sits to the LEFT of
   the name, dropped to sit near its cap height. */
.hero__namelock { display: flex; align-items: baseline; justify-content: center; gap: 12px; width: 100%; }
/* The invisible mirror of "Ing." on the right balances the real title on the
   left, so the NAME stays centred on screen instead of being pushed right. */
.hero__ing, .hero__namelock::after {
	font-family: 'Archivo', sans-serif; font-size: clamp(15px, 1.6vw, 24px); font-weight: 700;
	letter-spacing: 0.04em; white-space: nowrap;
}
.hero__ing { color: #8fe3cf; animation: riseIn .7s ease .15s both; }
.hero__namelock::after { content: "Ing."; visibility: hidden; }
:root[data-theme="light"] .hero__ing { color: #2f6f5d; }
.hero__kicker {
	font-family: 'IBM Plex Mono', monospace; font-size: 13px; letter-spacing: 0.32em; color: var(--faint);
	display: flex; gap: 12px; animation: riseIn .7s ease .1s both;
}

/* Hero theme chooser — a prominent, first-in-view light/dark switch. Larger and
   more legible than the twin in the Display panel; icons + words so the choice
   reads instantly. Wired via [data-theme-choice] alongside the panel control. */
.hero-theme {
	position: relative; z-index: 2;
	display: inline-flex; align-items: center; gap: 5px; padding: 5px;
	border-radius: 14px 14px 24px 14px;
	background: rgba(10,16,14,0.55);
	border: 1px solid rgba(127,217,196,0.28);
	backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
	box-shadow: 0 8px 26px rgba(0,0,0,0.32), 0 0 20px rgba(127,217,196,0.10);
	animation: riseIn .7s ease .04s both;
}
.hero-theme__btn {
	display: inline-flex; align-items: center; gap: 9px; cursor: pointer;
	border: none; background: transparent; color: var(--muted);
	font-family: 'IBM Plex Mono', monospace; font-size: 13px; letter-spacing: 0.16em; text-transform: uppercase;
	padding: 11px 22px; border-radius: 11px 11px 20px 11px; min-height: 44px;
	transition: color .25s ease, background .3s ease, box-shadow .3s ease;
}
.hero-theme__btn:hover { color: var(--fg); }
.hero-theme__glyph { display: inline-flex; width: 17px; height: 17px; }
.hero-theme__glyph svg { width: 100%; height: 100%; display: block; }
.hero-theme__btn.is-active {
	background: linear-gradient(135deg, #8fe3cf, #6cc9b2); color: #0a100e;
	box-shadow: 0 4px 14px rgba(127,217,196,0.32);
}
:root[data-theme="light"] .hero-theme {
	background: rgba(255,255,255,0.72);
	border-color: rgba(31,143,118,0.30);
	box-shadow: 0 8px 26px rgba(40,50,44,0.12);
}
:root[data-theme="light"] .hero-theme__btn.is-active {
	background: linear-gradient(135deg, #2f9e83, #1f8f76); color: #ffffff;
	box-shadow: 0 4px 14px rgba(31,143,118,0.28);
}
.hero__name {
	font-size: clamp(3.25rem, 12vw, 168px); font-weight: 900; letter-spacing: -0.035em; line-height: 0.98;
	max-width: 100%; overflow-wrap: break-word; padding-bottom: 0.08em;
	color: var(--fg); animation: nameReveal 1.1s cubic-bezier(.16,1,.3,1) .2s both;
}
.hero__tagline {
	max-width: 760px; font-size: clamp(20px, 1.9vw, 28px); font-weight: 500; line-height: 1.4;
	color: var(--body); letter-spacing: 0.01em; text-wrap: pretty; animation: riseIn .7s ease .6s both;
}
.hero__tagline-accent { color: #8fe3cf; font-weight: 700; }
.hero__cursor-blink { display: inline-block; width: 10px; margin-left: 4px; color: #8fe3cf; animation: blink 1.1s steps(1) infinite; }
.hero__ctas { display: flex; gap: 14px; margin-top: 12px; animation: riseIn .7s ease .78s both; }

/* ---------- Hero intent router — "What brings you here?" (v3.24 "Compass") ----
   Replaces the decorative domain band + generic CTAs: ask the visitor what they
   came for and route them to the matching section. Calm, not pushy — four equal
   doors, one accent each, no photos (those live on the Services page/section). */
.hero-intent { position: relative; z-index: 2; width: 100%; max-width: min(1240px, 100%); display: flex; flex-direction: column; align-items: center; gap: 24px; margin-top: 40px; animation: riseIn .7s ease .82s both; }
.hero-intent__ask { font-size: clamp(22px, 2.4vw, 34px); font-weight: 800; color: var(--fg); letter-spacing: -0.015em; }
.hero-intent__grid { width: 100%; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 22px; }
/* The doors wear their palette colour boldly: a solid accent icon chip, a stronger
   tinted panel, a firm accent border and a soft colour glow — clearly distinct and
   prominent, while the panel stays dark enough for the white goal text to pop. */
.intent {
	--intent-accent: #7fd9c4;
	display: flex; align-items: center; gap: 22px; padding: 30px 34px; border-radius: var(--r-card); text-decoration: none; text-align: left;
	background: color-mix(in srgb, var(--intent-accent) 18%, transparent);
	border: 1.5px solid color-mix(in srgb, var(--intent-accent) 60%, transparent);
	box-shadow: 0 10px 30px color-mix(in srgb, var(--intent-accent) 16%, transparent);
	transition: transform .35s var(--ease-bouncy), border-color .3s ease, background .3s ease, box-shadow .3s ease;
}
/* Each door's accent matches the background colour of the section it leads to,
   so the colour previews where you'll land: work→projects (green),
   hire→services (violet), about→about (blue), contact→contact (teal). */
.intent--work    { --intent-accent: #7fd9c4; }
.intent--hire    { --intent-accent: #b3a5f2; }
.intent--about   { --intent-accent: #e5c37c; }
.intent--contact { --intent-accent: #7cc4e8; }
.intent:hover {
	transform: translateY(-6px);
	border-color: color-mix(in srgb, var(--intent-accent) 90%, transparent);
	background: color-mix(in srgb, var(--intent-accent) 26%, transparent);
	box-shadow: 0 18px 44px color-mix(in srgb, var(--intent-accent) 30%, transparent);
}
/* Solid accent chip — the strongest colour carrier — with a dark glyph. */
.intent__icon { flex: 0 0 auto; width: 74px; height: 74px; border-radius: 20px 20px 20px 34px; display: flex; align-items: center; justify-content: center; color: #0a100e; background: var(--intent-accent); box-shadow: 0 4px 14px color-mix(in srgb, var(--intent-accent) 45%, transparent); }
.intent__icon svg { width: 36px; height: 36px; display: block; }
.intent__text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.intent__goal { font-size: clamp(20px, 1.7vw, 26px); font-weight: 800; color: var(--fg); letter-spacing: -0.01em; }
.intent__sub { font-size: 15.5px; color: var(--body); }
.intent__arrow { flex: 0 0 auto; color: var(--intent-accent); font-size: 26px; transition: transform .3s ease; }
.intent:hover .intent__arrow { transform: translateX(5px); }
/* Paper theme: keep the colour prominent too — tinted panel, accent border, solid
   chip — remapped to the darker light-mode accents so text and glyph stay legible. */
:root[data-theme="light"] .intent {
	background: color-mix(in srgb, var(--intent-accent) 16%, transparent);
	border: 1.5px solid color-mix(in srgb, var(--intent-accent) 55%, transparent);
	box-shadow: 0 10px 26px color-mix(in srgb, var(--intent-accent) 16%, transparent);
}
:root[data-theme="light"] .intent:hover { background: color-mix(in srgb, var(--intent-accent) 26%, transparent); }
:root[data-theme="light"] .intent__icon { color: #ffffff; }
:root[data-theme="light"] .intent__goal { color: #10231d; }
:root[data-theme="light"] .intent--work    { --intent-accent: #2f6f5d; }
:root[data-theme="light"] .intent--hire    { --intent-accent: #5a4e86; }
:root[data-theme="light"] .intent--about   { --intent-accent: #8a6a2e; }
:root[data-theme="light"] .intent--contact { --intent-accent: #355b6a; }

/* ---------- Domain band ---------- */
.domain-band { position: relative; z-index: 2; display: flex; gap: 12px; height: clamp(210px, 30vh, 340px); animation: riseInSoft .9s cubic-bezier(.16,1,.3,1) .9s both; }
.domain-tile {
	cursor: pointer; flex: 1 1 0; box-sizing: border-box; border-radius: 14px; display: flex; align-items: center;
	justify-content: center; padding: 24px; transition: all .5s cubic-bezier(.34,1.56,.64,1);
}
.domain-tile__label { font-family: 'IBM Plex Mono', monospace; font-size: clamp(15px, 1.25vw, 21px); letter-spacing: 0.2em; line-height: 1.6; text-align: center; }
/* Category colours brought back up — vivid tints of each hue, not near-black. */
.domain-tile--branding { border-radius: 56px 14px 14px 56px; background: linear-gradient(160deg, #294a3b 0%, #1c3529 100%); border: 1px solid rgba(127,217,196,0.28); }
.domain-tile--branding:hover { flex-grow: 1.5; border-radius: 56px 32px 32px 56px; border-color: rgba(127,217,196,0.6); background: linear-gradient(160deg, #316152 0%, #244539 100%); }
.domain-tile--rendering { background: linear-gradient(160deg, #223d4e 0%, #172c3a 100%); border: 1px solid rgba(124,196,232,0.28); }
.domain-tile--rendering:hover { flex-grow: 1.5; border-radius: 32px; border-color: rgba(124,196,232,0.6); background: linear-gradient(160deg, #2c5064 0%, #1f3a49 100%); }
.domain-tile--multimedia-design { background: linear-gradient(160deg, #2e2952 0%, #201c3c 100%); border: 1px solid rgba(179,165,242,0.28); }
.domain-tile--multimedia-design:hover { flex-grow: 1.5; border-radius: 32px; border-color: rgba(179,165,242,0.6); background: linear-gradient(160deg, #3d376b 0%, #2a2650 100%); }
.domain-tile--engineering { background: linear-gradient(160deg, #43371c 0%, #2c2512 100%); border: 1px solid rgba(229,195,124,0.28); }
.domain-tile--engineering:hover { flex-grow: 1.5; border-radius: 32px; border-color: rgba(229,195,124,0.6); background: linear-gradient(160deg, #5a4926 0%, #3c3219 100%); }
.domain-tile--3d-modelling { border-radius: 14px 56px 56px 14px; background: linear-gradient(160deg, #45291d 0%, #2c1a12 100%); border: 1px solid rgba(237,161,132,0.28); }
.domain-tile--3d-modelling:hover { flex-grow: 1.5; border-radius: 32px 56px 56px 32px; border-color: rgba(237,161,132,0.6); background: linear-gradient(160deg, #5c3626 0%, #3d2418 100%); }
.domain-tile.is-dimmed { opacity: 0.45; }

/* ---------- Ribbon ---------- */
.ribbon { position: relative; z-index: 2; margin-top: 22px; padding-top: 22px; border-top: 1px solid rgba(127,217,196,0.12); }
.ribbon__viewport {
	height: 92px; display: flex; align-items: center; overflow: hidden;
	-webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 8%, #000 92%, transparent 100%);
	mask-image: linear-gradient(90deg, transparent 0%, #000 8%, #000 92%, transparent 100%);
}
.ribbon__track { display: flex; width: max-content; animation: marqueeX 38s linear infinite; }
.ribbon__item {
	height: 72px; min-width: 210px; margin-right: 26px; padding: 0 40px; box-sizing: border-box;
	display: flex; align-items: center; justify-content: center; border: 1px dashed rgba(127,217,196,0.18);
	border-radius: 16px; background: rgba(127,217,196,0.03); font-family: 'IBM Plex Mono', monospace;
	font-size: 20px; font-weight: 500; letter-spacing: 0.2em; color: var(--faint); white-space: nowrap;
}

/* ---------- Projects ---------- */
.filter-clear {
	cursor: pointer; display: inline-flex; align-items: center; gap: 10px; border: 1px solid var(--mint);
	background: rgba(127,217,196,0.06); border-radius: 999px; padding: 9px 16px 9px 18px;
	font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.14em; color: var(--mint);
	transition: all .3s;
}
.filter-clear:hover { background: rgba(127,217,196,0.14); }
.filter-clear__x { font-size: 14px; opacity: 0.8; }
.projects-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 28px; }
@media (max-width: 1280px) { .projects-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 900px) { .projects-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.project-card { text-decoration: none; color: inherit; display: flex; flex-direction: column; gap: 16px; }
.project-card__frame {
	position: relative; overflow: hidden; border-radius: var(--r-card); aspect-ratio: 4 / 3; background: var(--card);
	border: 1px solid rgba(127,217,196,0.14); cursor: pointer; transition: all .45s var(--ease-bouncy);
}
.project-card:hover .project-card__frame { transform: translateY(-8px) scale(1.03); border-color: var(--project-accent, #7fd9c4); box-shadow: 0 24px 58px rgba(0,0,0,0.55); }
.project-card__logo {
	position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
	background-image: repeating-linear-gradient(135deg, rgba(127,217,196,0.05) 0px, rgba(127,217,196,0.05) 2px, rgba(0,0,0,0) 2px, rgba(0,0,0,0) 12px);
}
/* Logos fill the whole card — 0% bezel (no padding), edge to edge. */
.project-card__logo img { width: 100%; height: 100%; object-fit: contain; padding: 0; }
.project-card__hover {
	position: absolute; inset: 0; opacity: 0; transition: opacity .45s ease;
	display: flex; align-items: center; justify-content: center;
}
.project-card__hover--placeholder {
	background-color: #0e1815;
	background-image: repeating-linear-gradient(135deg, rgba(127,217,196,0.12) 0px, rgba(127,217,196,0.12) 2px, rgba(0,0,0,0) 2px, rgba(0,0,0,0) 11px);
}
.project-card__hover img { width: 100%; height: 100%; object-fit: cover; }
.project-card:hover .project-card__hover { opacity: 1; }
.project-card__placeholder-label { font-family: 'IBM Plex Mono', monospace; font-size: 13px; letter-spacing: 0.26em; color: var(--faint); }
.project-card__meta { display: flex; align-items: center; gap: 12px; padding-left: 2px; }
.project-card__dot { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.project-card__name { font-size: 27px; font-weight: 700; letter-spacing: -0.01em; color: var(--fg); }
.project-card.is-hidden { display: none; }

/* ---------- About ---------- */
/* A portrait treated like a lit CRT screen: a mint halo behind it, a subtle
   scanline tone on the photo, and floating mono details — all feathered so no
   rectangular edge is ever visible. */
.section--about { padding-top: 72px; padding-bottom: 72px; }
.about-grid { display: grid; grid-template-columns: minmax(480px, 1.55fr) minmax(300px, 1fr); gap: 56px; align-items: center; }
.about-portrait-col { display: flex; flex-direction: column; gap: 20px; }
/* Framed like a screen, per the styleguide (§05 shape + §11 CRT), instead of
   feathered into the background. The feather was doing two jobs badly: it hid
   the photo's own edges, but it also dissolved the subject and left the
   portrait looking like a ghost rather than a picture. A frame states that this
   IS a photograph, and the soft corner ties it to every other panel on the
   site. */
.about-portrait {
	position: relative; isolation: isolate; overflow: hidden;
	height: clamp(420px, 64vh, 720px);
	border-radius: var(--r-panel);
	border: 1px solid rgba(127,217,196,0.22);
	background: #0c1512;
}
:root[data-theme="light"] .about-portrait { border-color: rgba(31,143,118,0.22); background: #e9eee7; }
/* Lit-from-behind mint halo, now outside the frame so it reads as the screen
   glowing rather than as fog on the photo. */
.about-portrait::before {
	content: ""; position: absolute; inset: -12%; z-index: -1;
	background: radial-gradient(ellipse 58% 56% at 50% 46%, rgba(127,217,196,0.24), rgba(127,217,196,0) 70%);
	filter: blur(40px);
}
.about-portrait img {
	width: 100%; height: 100%; object-fit: cover;
	/* Where the crop holds. Set from Portfolio Content → About, because the
	   right value depends entirely on the photo and nobody should need a
	   developer to move a face back into the middle of its own frame. */
	object-position: var(--portrait-focus, 50% 28%);
	/* Duotone, graded into the theme's own mint. The photo was the last element
	   on the page still speaking in its own colours, which is what made it read
	   as a stock portrait dropped into a designed site. Done with filters rather
	   than a blended overlay because the overlay here is already carrying the
	   raster and the bottom fade, and blending those too would tint the raster
	   instead of the face. sepia() supplies a single hue for hue-rotate() to
	   aim; the result lands on the same mint as --accent. */
	filter: grayscale(1) sepia(0.55) hue-rotate(112deg) saturate(1.55) contrast(1.06) brightness(0.97);
	display: block;
}
/* CRT tone on the portrait — faint scanlines + a grounding bottom fade, clipped
   to the same feather so it never introduces an edge. */
/* The same CRT layers the screen wears, on the frame: raster, a grounding
   bottom fade, the glass gloss in the top-left, and the bulge as an inset
   shadow. Clipped by the frame's own overflow, so no mask is needed any more. */
.about-portrait::after {
	content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
	border-radius: inherit;
	background:
		radial-gradient(ellipse 34% 20% at 28% 13%, rgba(244,248,245,0.13) 0%, transparent 68%),
		linear-gradient(180deg, rgba(10,16,14,0) 52%, rgba(10,16,14,0.5) 100%),
		/* Same raster as the screen stack — Cadence §11's mint tint, not a black
		   mask, so the portrait and the screen agree about what a scanline is. */
		repeating-linear-gradient(180deg, rgba(127,217,196,0.055) 0 1px, transparent 1px 3px);
	box-shadow: inset 0 0 20px 4px rgba(4,9,7,0.34), inset 0 0 70px 12px rgba(4,9,7,0.16);
}
:root[data-theme="light"] .about-portrait::after {
	background:
		radial-gradient(ellipse 34% 20% at 28% 13%, rgba(255,255,255,0.42) 0%, transparent 68%),
		linear-gradient(180deg, rgba(20,36,29,0) 55%, rgba(20,36,29,0.22) 100%),
		repeating-linear-gradient(180deg, rgba(20,36,29,0.045) 0 1px, transparent 1px 3px);
	box-shadow: inset 0 0 20px 4px rgba(122,110,84,0.2), inset 0 0 70px 12px rgba(122,110,84,0.1);
}
/* Warm Archive keeps the duotone but pulls it back: the same strength on paper
   turns a portrait into a green cast rather than a graded one. */
:root[data-theme="light"] .about-portrait img {
	filter: grayscale(1) sepia(0.4) hue-rotate(118deg) saturate(1.1) contrast(1.04) brightness(1.02);
}
.about-portrait__label { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.2em; color: var(--faint); }

/* --- Manifesto -------------------------------------------------------------
   The statement carries the argument, so it gets display weight; the paragraph
   under it is support and stays at reading size. Capped at 20ch/50ch so the
   line breaks land where the sense does rather than wherever the column ends. */
/* Scoped through .about-copy so they outrank `.about-copy p` on specificity
   rather than on !important — same outcome, and the next person editing this
   can still override it normally. */
/* A statement, not a second heading. At 800-weight display size it competed
   with the section title directly above it — same family, same weight, nearly
   the same size, so the eye read two titles and neither won. It is now clearly
   subordinate in size and weight, and marked as a quoted position by an accent
   rule rather than by shouting: different JOB, so it needs a different voice,
   not a smaller version of the same one. */
.about-copy p.about-statement {
	font-size: clamp(19px, 1.55vw, 25px); font-weight: 500; line-height: 1.45;
	letter-spacing: 0; color: var(--fg); max-width: 34ch; text-wrap: balance;
	margin: 0; padding-left: 20px; border-left: 2px solid #7fd9c4;
}
:root[data-theme="light"] .about-copy p.about-statement { border-left-color: #2f9c85; }
.about-copy > p:not(.about-statement):not(.about-facts) { max-width: 54ch; }
.about-copy p.about-facts {
	font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.16em;
	line-height: 1.7; color: var(--faint);
	padding-top: 18px; border-top: 1px solid var(--border-hair); margin: 6px 0 0;
}

/* The beliefs. Four cards, but deliberately not card-shaped — a rule and a
   number, so they read as positions taken rather than as features listed. */
.beliefs {
	display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
	gap: 34px 40px; margin-top: 68px;
}
.belief { display: flex; flex-direction: column; gap: 10px; padding-top: 18px; border-top: 1px solid var(--border-hair); }
.belief__num {
	font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.2em; color: #c9a95c;
}
.belief__title { font-size: 19px; font-weight: 800; line-height: 1.3; color: var(--fg); text-wrap: balance; }
.belief__body { font-size: 15px; line-height: 1.65; color: var(--muted); margin: 0; text-wrap: pretty; }
@media (max-width: 860px) {
	.beliefs { grid-template-columns: 1fr; gap: 26px; margin-top: 44px; }
	.about-copy p.about-statement { max-width: none; }
}
.about-copy { display: flex; flex-direction: column; gap: 22px; }
.about-copy p { font-size: 19px; line-height: 1.65; color: var(--muted); text-wrap: pretty; }

/* ---------- Snake (contact column filler) ----------------------------------
   Sits under the booking panel, in the space that column left empty. Styled a
   step quieter than the panels around it — smaller label, hairline border, no
   fill — because it must never out-shout the contact CTA beside it. Colours are
   exposed as custom properties: the canvas is painted in JS, which can only
   read tokens that are declared here. */
.snake {
	--snake-body: #7fd9c4;
	--snake-head: #d9fff2;
	--snake-food: #e5c37c;
	--snake-grid: rgba(127,217,196,0.06);
	margin-top: 22px; display: flex; flex-direction: column; gap: 10px;
}
:root[data-theme="light"] .snake {
	--snake-body: #2f9c85;
	--snake-head: #10231d;
	--snake-food: #b98420;
	--snake-grid: rgba(16,35,29,0.05);
}
.snake[hidden] { display: none; }
/* Desktop placement, stated explicitly rather than left to auto-placement.
   Pinning the game to column 1 was not enough: the grid's rows are sized by
   their tallest item, so row 1 took the height of the FORM, and row 2 — the
   game — began below it. It sat halfway down an empty column instead of
   directly under the booking panel.
   The fix is to let the form and the OR rail SPAN both rows. Row 1 is then only
   as tall as the booking panel, row 2 starts immediately under it, and the game
   is back where it was — while still being the last child in source order, so
   the single-column phone layout keeps it after the form. */
@media (min-width: 981px) {
	.contact-grid--split > .contact-col--book { grid-column: 1; grid-row: 1; }
	.contact-grid--split > .contact-or { grid-column: 2; grid-row: 1 / span 2; }
	.contact-grid--split > .contact-panel { grid-column: 3; grid-row: 1 / span 2; }
	.contact-grid--split > .snake { grid-column: 1; grid-row: 2; align-self: start; }
}
.snake__head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.snake__label, .snake__scores, .snake__hint {
	font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.16em; color: var(--muted);
}
.snake__scores { display: flex; gap: 14px; }
.snake__scores b { color: var(--fg); font-weight: 600; }
.snake__screen {
	position: relative; border: 1px solid var(--border-hair); border-radius: var(--r-sm);
	background: rgba(127,217,196,0.04); overflow: hidden;
}
:root[data-theme="light"] .snake__screen { background: rgba(16,35,29,0.03); }
.snake__screen canvas {
	display: block; width: 100%; height: auto;
	/* The canvas is 240x150 internally and stretched by CSS. Nearest-neighbour
	   keeps the squares hard-edged at any width — smoothing would turn an 8-bit
	   board into a blurry one. */
	image-rendering: pixelated; image-rendering: crisp-edges;
}
.snake__overlay {
	position: absolute; inset: 0; display: flex; flex-direction: column;
	align-items: center; justify-content: center; gap: 12px;
	background: rgba(10,16,14,0.72); backdrop-filter: blur(2px);
}
:root[data-theme="light"] .snake__overlay { background: rgba(240,243,238,0.78); }
.snake__overlay[hidden] { display: none; }
.snake__msg {
	margin: 0; font-family: 'IBM Plex Mono', monospace; font-size: 13px;
	letter-spacing: 0.28em; color: var(--fg);
}
.snake__btn {
	font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.18em;
	padding: 9px 20px; border-radius: 999px; cursor: pointer;
	border: 1px solid rgba(127,217,196,0.45); background: rgba(127,217,196,0.12); color: var(--fg);
	transition: transform .35s var(--ease-bouncy), background .3s ease, border-color .3s ease;
}
.snake__btn:hover { background: rgba(127,217,196,0.2); border-color: rgba(127,217,196,0.7); transform: translateY(-2px); }
.snake__btn:active { transform: scale(.955); }
.snake__hint { font-size: 10px; letter-spacing: 0.12em; color: var(--faint); margin: 0; }
/* Focus is load-bearing here: the arrow keys only steer while the board holds
   focus (so they still scroll the page for someone merely reading), which makes
   "is it focused?" the difference between a working game and a dead one. It has
   to be unmistakable, hence a ring rather than a tint. */
.snake__screen {
	outline: none; cursor: pointer;
	/* Without this a swipe meant for the snake scrolls the page instead — the
	   touch listeners are passive and cannot cancel it, and making them
	   non-passive to call preventDefault would cost scroll performance
	   everywhere. Declaring the intent in CSS is both cheaper and honest. */
	touch-action: none;
}
.snake__screen:focus-visible,
.snake__screen:focus {
	border-color: rgba(127,217,196,0.85);
	box-shadow: 0 0 0 3px rgba(127,217,196,0.22);
}

@media (max-width: 980px) {
	/* Kept on phones after all. The columns stack here so there is no hole to
	   fill, but the game is the reason someone stays a minute longer and that
	   is worth as much on a phone as on a desktop. It sits under the booking
	   panel, above the form, and the board gets a taller aspect so the cells
	   stay thumb-sized. */
	.snake { margin-top: 26px; }
	.snake__hint { font-size: 9.5px; }
}

/* ---------- Cookie banner + legal pages -------------------------------------
   The banner is a bottom sheet, not a full-screen wall: it must be dismissible
   and must never block reading, or the "choice" becomes a toll gate. Decline
   and Accept sit side by side at the same weight — the regulator's test, and
   the honest one. */
/* Sized to be answered, not read. One line, bottom-left, only as wide as its
   own content — it sits beside the settings button rather than across the
   footer, so the page underneath stays usable while the question is open. */
.consent {
	position: fixed; left: 16px; bottom: 16px; z-index: 95;
	max-width: calc(100vw - 32px);
	transform: translateY(140%); transition: transform .4s cubic-bezier(.22,.9,.3,1);
}
.consent.is-open { transform: translateY(0); }
.consent[hidden] { display: none; }
.consent__inner {
	display: inline-flex; align-items: center; gap: 14px;
	padding: 8px 10px 8px 16px; box-sizing: border-box;
	background: var(--card, #101a15); border: 1px solid var(--border-hair);
	border-radius: 999px; box-shadow: 0 10px 34px rgba(0,0,0,0.4);
}
:root[data-theme="light"] .consent__inner { background: #ffffff; box-shadow: 0 10px 30px rgba(40,50,44,0.14); }
.consent__text {
	margin: 0; font-size: 13px; line-height: 1.4; color: var(--muted); white-space: nowrap;
}
.consent__text strong { color: var(--fg); font-weight: 700; }
.consent__text a { color: inherit; text-decoration: underline; text-underline-offset: 3px; margin-left: 4px; }
.consent__actions { display: flex; gap: 6px; flex-shrink: 0; }
/* Both answers are the same shape and the same size. Only the fill differs, and
   only enough to tell them apart — never enough to steer the answer. */
.consent__btn {
	font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.12em;
	padding: 7px 16px; border-radius: 999px; cursor: pointer; min-width: 62px;
	border: 1px solid var(--border-hair); background: transparent; color: var(--fg);
	transition: background .25s ease, border-color .25s ease, transform .3s var(--ease-bouncy);
}
.consent__btn:hover { border-color: rgba(127,217,196,0.6); background: rgba(127,217,196,0.1); }
.consent__btn:active { transform: scale(.95); }
.consent__btn--yes { background: rgba(127,217,196,0.16); border-color: rgba(127,217,196,0.45); }
.consent__btn--yes:hover { background: rgba(127,217,196,0.26); }
@media (max-width: 620px) {
	/* ABOVE the settings button, not beside it. Full width down here, and the
	   settings FAB is fixed at right:16 bottom:16 with z-index 120 — twenty-five
	   higher than this — so "Yes", as the rightmost control in the row, sat
	   directly underneath it and could not be pressed at all. A banner where
	   refusing works and accepting does not is the same broken choice as a
	   buried decline, only in the other direction. 16 + 56 + 16 = 88. */
	.consent { left: 12px; right: 12px; bottom: 88px; max-width: none; }
	.consent__inner { display: flex; width: 100%; gap: 10px; padding: 8px 10px 8px 14px; }
	/* The only thing that may wrap on a narrow screen is the sentence — the two
	   answers stay side by side, so neither can end up below the fold. */
	.consent__text { white-space: normal; font-size: 12px; }
}
@media (prefers-reduced-motion: reduce) {
	.consent { transition: none; }
}

.site-footer-line__legal { display: inline-flex; gap: 14px; margin-left: 18px; }
.site-footer-line__legal a { color: inherit; opacity: .75; text-decoration: none; border-bottom: 1px solid currentColor; }
.site-footer-line__legal a:hover { opacity: 1; }
@media (max-width: 560px) {
	.site-footer-line__legal { display: flex; margin: 10px 0 0; justify-content: center; }
}

/* Legal pages. Measure capped at 68ch per the styleguide — these are the
   longest continuous prose on the site and the only pages people read rather
   than scan. */
.legal { display: flex; flex-direction: column; gap: 34px; }
.legal__kicker { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.24em; color: var(--muted); }
.legal__title { font-size: clamp(38px, 5vw, 68px); font-weight: 900; letter-spacing: -0.02em; margin: 10px 0 6px; color: var(--fg); }
.legal__updated { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.1em; color: var(--faint); margin: 0; }
.legal__body { max-width: 68ch; display: flex; flex-direction: column; gap: 6px; }
.legal__lede { font-size: 19px; line-height: 1.6; color: var(--fg); margin: 0 0 12px; }
.legal__body h2 {
	font-size: 24px; font-weight: 800; color: var(--fg);
	margin: 30px 0 6px; padding-top: 18px; border-top: 1px solid var(--border-hair);
}
.legal__body h3 { font-size: 17px; font-weight: 700; color: var(--fg); margin: 18px 0 2px; }
.legal__body p, .legal__body li { font-size: 16px; line-height: 1.7; color: var(--muted); }
.legal__body p { margin: 8px 0; }
.legal__body ul { margin: 8px 0; padding-left: 20px; display: flex; flex-direction: column; gap: 6px; }
.legal__body a { color: var(--fg); text-decoration: underline; text-underline-offset: 3px; }
.legal__body code { font-family: 'IBM Plex Mono', monospace; font-size: 13px; color: var(--fg); }
/* A gap in a legal text has to be impossible to miss — see emre_legal_detail(). */
.legal__todo { background: rgba(229,195,124,0.22); color: var(--fg); padding: 1px 6px; border-radius: 4px; }
.legal__table { width: 100%; border-collapse: collapse; margin: 12px 0; font-size: 14px; display: block; overflow-x: auto; }
.legal__table th, .legal__table td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--border-hair); vertical-align: top; }
.legal__table th { font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: 0.14em; color: var(--muted); font-weight: 500; }
.legal__table td { color: var(--muted); }
.legal__cross a { font-family: 'IBM Plex Mono', monospace; font-size: 12px; letter-spacing: 0.12em; color: var(--fg); }

/* ---------- Services ---------- */
.services-block { display: flex; flex-direction: column; gap: 40px; }
.services-grid, .trainings-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px; }
.trainings-grid { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.service-card, .training-card {
	border-radius: var(--r-panel); min-height: 200px; background: var(--card); padding: 24px;
	display: flex; flex-direction: column; justify-content: space-between; gap: 16px;
	transition: all .45s cubic-bezier(.34,1.56,.64,1); cursor: pointer;
}
.service-card { border: 1px solid rgba(127,217,196,0.12); }
.service-card:hover { transform: translateY(-5px) scale(1.02); border-color: rgba(127,217,196,0.4); box-shadow: 0 18px 44px rgba(0,0,0,0.45); }
.training-card { border: 1px solid rgba(179,165,242,0.16); }
.training-card:hover { transform: translateY(-5px) scale(1.02); border-color: rgba(179,165,242,0.5); box-shadow: 0 18px 44px rgba(0,0,0,0.45); }
/* These now carry real content — trigger, description, deliverables, duration —
   so they stop being teasers that space out to fill a fixed box and become
   panels whose height follows their text. justify-content:space-between would
   otherwise strand the deliverables list at the bottom of the tallest card. */
.trainings-grid { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.training-card { justify-content: flex-start; gap: 12px; padding: 26px; cursor: default; }
.training-card:hover { transform: none; box-shadow: 0 14px 36px rgba(0,0,0,0.35); }
.service-card__name { font-family: 'IBM Plex Mono', monospace; font-size: 13px; letter-spacing: 0.18em; color: var(--fg); }
.service-card__desc, .training-card__desc { font-size: 15px; line-height: 1.55; color: var(--muted); text-wrap: pretty; }
.service-card__arrow, .training-card__arrow {
	align-self: flex-end; width: 36px; height: 36px; border-radius: 999px; display: flex;
	align-items: center; justify-content: center; font-size: 16px;
}
.training-card__arrow { background: rgba(179,165,242,0.14); color: var(--violet); }
.training-card__head { display: flex; flex-direction: column; gap: 4px; }
.training-card__tag { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.22em; color: var(--faint); }
.training-card__name { font-size: 25px; font-weight: 800; color: var(--fg); line-height: 1.2; letter-spacing: -0.01em; text-wrap: balance; }
/* The trigger is the hook, so it gets the weight the name used to hoard. Set in
   the accent rather than in muted grey: it is the line that has to be READ, not
   the one that has to be skimmed past. */
.training-card__trigger {
	font-size: 15.5px; font-weight: 600; line-height: 1.45; color: #8fe3cf;
	margin: 2px 0 0; text-wrap: pretty;
}
:root[data-theme="light"] .training-card__trigger { color: #1f8f76; }
/* Scannability. These cards are three paragraphs deep and were read as one
   block of grey, so the eye had nowhere to land between the hook and the list.
   The prose is now visibly SECONDARY to the two things a skimmer needs: the
   trigger at the top and the deliverables at the bottom. Anyone reading at
   speed gets "is this me?" and "what do I get?" without touching the middle,
   and the middle is still there for whoever slows down. */
.training-card__desc {
	font-size: 14px; line-height: 1.6; color: var(--faint);
	padding-left: 14px; border-left: 1px solid var(--border-hair);
}
.training-card__takeaway { margin-top: auto; padding-top: 14px; border-top: 1px solid var(--border-hair); }
.training-card__takeaway-label {
	display: block; font-family: 'IBM Plex Mono', monospace; font-size: 10px;
	letter-spacing: 0.2em; color: var(--faint); margin-bottom: 8px;
}
.training-card__takeaway ul { margin: 0; padding-left: 16px; display: flex; flex-direction: column; gap: 5px; }
.training-card__takeaway li { font-size: 14.5px; line-height: 1.5; color: var(--fg); }
.training-card__takeaway ul { padding-left: 18px; gap: 7px; }
.training-card__foot {
	display: flex; flex-wrap: wrap; gap: 4px 14px; align-items: baseline;
	padding-top: 12px;
}
.training-card__meta {
	font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: 0.14em;
	color: var(--faint);
}
/* The disqualification. Quiet on purpose — it has to be findable, not shouted;
   it is there for the person who needs permission to walk away. */
.training-card__notfor {
	margin: 0; font-size: 12.5px; line-height: 1.5; font-style: italic;
	color: var(--faint); text-wrap: pretty;
}

/* --- Services section rail -------------------------------------------------
   Sticks under the top bar for the whole page. --nav-h is published by main.js
   from the bar's REAL measured height, so the two never overlap at any
   breakpoint. Scrolls horizontally on a phone rather than wrapping, because a
   rail that grows to two rows stops being a rail. */
.svc-rail {
	position: sticky; top: var(--nav-h, 71px); z-index: 40;
	backdrop-filter: blur(10px);
	background: color-mix(in srgb, var(--bg, #0c1310) 82%, transparent);
	border-bottom: 1px solid var(--border-hair);
}
@supports not (backdrop-filter: blur(10px)) {
	.svc-rail { background: var(--bg, #0c1310); }
}
.svc-rail__inner {
	display: flex; gap: 6px; align-items: center;
	max-width: 1400px; margin: 0 auto; padding: 8px 48px;
	overflow-x: auto; scrollbar-width: none;
}
.svc-rail__inner::-webkit-scrollbar { display: none; }
.svc-rail__link {
	flex: 0 0 auto; text-decoration: none;
	font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.16em;
	color: var(--muted); padding: 9px 15px; border-radius: 12px 12px 20px 12px;
	border: 1px solid transparent;
	transition: color .3s ease, background .3s ease, border-color .3s ease;
}
.svc-rail__link:hover { color: var(--fg); background: rgba(127,217,196,0.08); }
/* Set by the same scroll-spy that drives the top bar. */
.svc-rail__link.is-current {
	color: var(--fg); background: rgba(127,217,196,0.14); border-color: rgba(127,217,196,0.35);
}
.svc-rail__link--cta { margin-left: auto; color: #8fe3cf; border-color: rgba(127,217,196,0.3); }
:root[data-theme="light"] .svc-rail__link--cta { color: #1f8f76; }
@media (max-width: 860px) {
	.svc-rail__inner { padding: 6px 16px; }
	.svc-rail__link { font-size: 10px; padding: 8px 11px; letter-spacing: 0.12em; }
	/* On a phone the CTA rides along in the scroll instead of pinning right,
	   where it would sit on top of the last section link. */
	.svc-rail__link--cta { margin-left: 0; }
}

/* Why this person. Hairline rules, no cards — evidence set beside the offer,
   not a fourth thing being sold. */
.svc-credibility { margin-top: 44px; display: flex; flex-direction: column; gap: 18px; }
.svc-credibility__label {
	font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.22em; color: var(--muted);
}
.svc-credibility__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 26px 36px; }
.svc-cred { display: flex; flex-direction: column; gap: 8px; padding-top: 16px; border-top: 1px solid var(--border-hair); }
.svc-cred__label { font-size: 16px; font-weight: 800; line-height: 1.3; color: var(--fg); text-wrap: balance; }
.svc-cred__text { font-size: 14px; line-height: 1.6; color: var(--muted); margin: 0; text-wrap: pretty; }

/* Homepage services — grouped matrix (v3.22 "Grid").
   A + B ("Design & build") share a two-column matrix; C ("Purpose & method")
   sits in its own panel below, set apart. Each column is anchored by a category
   thumbnail (dashboard-uploadable, icon fallback). Package tiers show the
   OUTCOME (result), not a truncated feature list — and nothing here is a button;
   the single filled CTA below is the only actionable element. */
.svc-group { display: flex; flex-direction: column; gap: 22px; }
.svc-group__head { display: flex; align-items: center; gap: 12px; }
.svc-group__dots { display: inline-flex; gap: 5px; flex: 0 0 auto; }
.svc-group__dots span { width: 9px; height: 9px; border-radius: 999px; display: block; }
.svc-group__label { font-size: 21px; font-weight: 800; color: var(--fg); letter-spacing: -0.01em; }
.svc-group__note { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--faint); }
.svc-group__line { flex: 1; height: 1px; background: rgba(127,217,196,0.14); }
.svc-group__foot { margin: 2px 0 0; font-size: 14px; color: var(--faint); }
.svc-group--think .svc-group__line { background: rgba(179,165,242,0.22); }

.svc-cols { display: grid; gap: 20px; }
.svc-cols--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.svc-cols--single { grid-template-columns: minmax(0, 460px); justify-content: center; }

/* Three domains side-by-side (v3.32). The two group headers span row 1 above
   their panels; the three framed panels sit in row 2; the retainer note in row 3
   under the build pair. Phones collapse it to one column (see the media query). */
.svc-matrix { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px 20px; align-items: start; }
.svc-matrix__head { margin: 0; }
.svc-matrix__head--build { grid-column: 1 / 3; grid-row: 1; }
.svc-matrix__head--think { grid-column: 3 / 4; grid-row: 1; }
.svc-matrix .svc-col--a { grid-column: 1; grid-row: 2; }
.svc-matrix .svc-col--b { grid-column: 2; grid-row: 2; }
.svc-matrix .svc-col--c { grid-column: 3; grid-row: 2; }
.svc-matrix__foot { grid-column: 1 / 3; grid-row: 3; margin: 4px 0 0; }

/* Per-column accent — set by class so light mode can remap to paper-readable
   values (inline custom props can't be overridden by the stylesheet). */
/* Each domain sits in its own framed panel (accent-tinted), so Branding,
   Product & 3D and Strategy are all clearly distinguished from one another. */
.svc-col {
	--svc-accent: #7fd9c4; display: flex; flex-direction: column; gap: 14px;
	background: color-mix(in srgb, var(--svc-accent) 4%, transparent);
	border: 1px solid color-mix(in srgb, var(--svc-accent) 20%, transparent);
	border-radius: var(--r-card); padding: 22px;
}
:root[data-theme="light"] .svc-col { background: color-mix(in srgb, var(--svc-accent) 6%, #ffffff); }
.svc-col--a { --svc-accent: #7fd9c4; }
.svc-col--b { --svc-accent: #e5c37c; }
.svc-col--c { --svc-accent: #b3a5f2; }
.svc-col__thumb {
	position: relative; aspect-ratio: 16 / 9; border-radius: var(--r-md); overflow: hidden;
	display: flex; align-items: center; justify-content: center;
	background: color-mix(in srgb, var(--svc-accent) 10%, transparent);
	border: 1px solid color-mix(in srgb, var(--svc-accent) 32%, transparent);
}
.svc-col__thumb img { width: 100%; height: 100%; object-fit: cover; }
.svc-col__icon { color: var(--svc-accent); display: block; }
.svc-col__icon svg { width: 46px; height: 46px; display: block; opacity: 0.92; }
.svc-col__name { font-size: 21px; font-weight: 800; color: var(--fg); letter-spacing: -0.01em; }
.svc-col__line { margin: 4px 0 0; font-size: 14px; line-height: 1.5; color: var(--muted); text-wrap: pretty; }
.svc-col__tiers { display: flex; flex-direction: column; gap: 10px; margin-top: 2px; }

.svc-tier {
	display: flex; flex-direction: column; gap: 5px; padding: 14px 16px; border-radius: var(--r-sm);
	background: rgba(127,217,196,0.03); border: 1px solid color-mix(in srgb, var(--svc-accent) 14%, transparent);
}
.svc-tier--featured {
	border-color: color-mix(in srgb, var(--svc-accent) 55%, transparent);
	background: color-mix(in srgb, var(--svc-accent) 8%, transparent);
}
.svc-tier__top { display: flex; align-items: center; gap: 10px; min-height: 16px; }
.svc-tier__size { font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: 0.16em; color: var(--faint); }
.svc-tier__badge {
	font-family: 'IBM Plex Mono', monospace; font-size: 10px; letter-spacing: 0.08em;
	color: var(--svc-accent); background: color-mix(in srgb, var(--svc-accent) 15%, transparent);
	padding: 2px 9px; border-radius: 999px;
}
.svc-tier__name { font-size: 16px; font-weight: 700; color: var(--fg); }
.svc-tier__result { font-size: 13px; line-height: 1.5; color: var(--muted); text-wrap: pretty; }

/* The one, unmistakable call to action under the services. */
.services-cta { margin-top: 8px; display: flex; justify-content: center; }

/* ---------- CV Timeline ---------- */

/* --- CV as facts -----------------------------------------------------------
   The number leads because a number is read without effort; the label above it
   says what is being counted and the line below turns it back into something
   meaningful. Hairline rules rather than boxes — these are entries in a record,
   not four more cards. */
.cv-facts {
	display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
	gap: 28px 40px; margin-bottom: 54px;
}
.cv-fact { display: flex; flex-direction: column; gap: 6px; padding-top: 16px; border-top: 1px solid var(--border-hair); }
.cv-fact__label { font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: 0.2em; color: var(--muted); }
.cv-fact__value { font-size: clamp(30px, 3.4vw, 46px); font-weight: 900; line-height: 1; letter-spacing: -0.02em; color: var(--fg); }
.cv-fact__sub { font-size: 13px; line-height: 1.5; color: var(--faint); text-wrap: pretty; }

/* The chronology, still here but as one line each: readable in a single pass
   rather than six clicks, and it costs less room than the panel it replaced. */
.cv-roles { display: flex; flex-direction: column; }
.cv-role {
	display: grid; grid-template-columns: 130px minmax(180px, 1fr) 1.4fr; gap: 20px; align-items: baseline;
	padding: 14px 0; border-top: 1px solid var(--border-hair);
}
.cv-role__years { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.12em; color: #c9a95c; }
.cv-role__name { font-size: 16px; font-weight: 700; color: var(--fg); }
.cv-role__org { font-size: 13.5px; color: var(--muted); text-wrap: pretty; }
@media (max-width: 760px) {
	.cv-facts { grid-template-columns: 1fr 1fr; gap: 22px 24px; margin-bottom: 38px; }
	.cv-role { grid-template-columns: 1fr; gap: 3px; padding: 12px 0; }
}
.cv-footer {
	display: flex; gap: 48px; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
	border-top: 1px solid rgba(127,217,196,0.14); padding-top: 32px; margin-top: 40px;
}
.cv-education { display: flex; gap: 48px; flex-wrap: wrap; }
.cv-education__row { display: flex; flex-direction: column; gap: 4px; }
.cv-education__degree { font-size: 16px; font-weight: 700; color: var(--fg); }
.cv-education__org { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.12em; color: var(--faint); }

/* ---------- Contact ---------- */
/* Top blend from the CV colour (see "Soft section seams" below), then the
   existing bottom glow layer. */
.section--contact { padding: 120px 64px 80px; background-image: linear-gradient(180deg, var(--sec-cv) 0%, var(--sec-contact) var(--sec-fade), rgba(0,0,0,0) var(--sec-fade)), radial-gradient(ellipse 70% 60% at 50% 100%, rgba(30,52,45,0.5) 0%, rgba(10,16,14,0) 70%); }
/* Copy clears the colour fade — headings start below the transition on every seam. */
.section--projects, .section--services, .section--about, .section--cv, .section--contact { padding-top: calc(var(--sec-fade) + 14px); }
/* About → CV was ~250px of nothing: the beliefs ended, About's own 68px bottom
   padding ran out, and then CV opened with a further 184px to clear its colour
   fade. Two sections that continue one argument should not be separated like
   two unrelated chapters, so the seam is closed from both sides — a shorter
   fade on CV and almost no tail on About. The fade still reads; it just no
   longer costs a screen's worth of scrolling to get past. */
.section--about { padding-bottom: 20px; }
.section--cv { --sec-fade: 96px; }
/* Contact: a header, then two side-by-side columns — Book a call (left) | Send a
   message (right) — then a details footer. Split = both columns; solo = just the
   form, centred (when no Setmore link is set). */
.contact-head { display: flex; flex-direction: column; gap: 18px; max-width: 760px; margin-bottom: 44px; }
.contact-grid { display: grid; gap: 44px; align-items: start; }
.contact-grid--split { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 36px; }
.contact-grid--solo { grid-template-columns: minmax(0, 620px); justify-content: center; }
.contact-col { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.contact-col__label { display: block; font-family: 'IBM Plex Mono', monospace; font-size: 12px; letter-spacing: 0.2em; text-transform: uppercase; color: #8fe3cf; }
:root[data-theme="light"] .contact-col__label { color: #2f6f5d; }
.contact-panel > .contact-col__label { margin-bottom: 20px; }
.contact-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 32px; margin-top: 44px; }
.contact-title { font-size: clamp(48px, 5.5vw, 84px); font-weight: 900; letter-spacing: -0.02em; line-height: 0.98; color: var(--fg); }
.contact-intro { font-size: 20px; line-height: 1.6; color: var(--muted); max-width: 460px; text-wrap: pretty; }
/* Embedded Setmore booking widget (the left "Book a call" column). */
.contact-setmore { width: 100%; height: 720px; max-height: 84vh; border: 0; border-radius: 14px; background: #fff; display: block; }
.contact-book__fallback { margin: 2px 0 0; font-size: 12.5px; color: var(--faint); }
.contact-book__fallback a { color: #8fe3cf; }
:root[data-theme="light"] .contact-book__fallback a { color: #2f6f5d; }
.contact-email { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; font-family: 'IBM Plex Mono', monospace; font-size: 15px; letter-spacing: 0.06em; color: #8fe3cf; }
.contact-email__dot { width: 7px; height: 7px; border-radius: 50%; background: #8fe3cf; box-shadow: 0 0 10px rgba(127,217,196,0.8); }
.contact-availability { font-family: 'IBM Plex Mono', monospace; font-size: 13px; letter-spacing: 0.14em; color: var(--faint); }
.contact-panel { border-radius: var(--r-panel); background: var(--card); border: 1px solid rgba(127,217,196,0.18); padding: 40px; box-shadow: 0 22px 60px rgba(0,0,0,0.5); }
.contact-form { display: flex; flex-direction: column; gap: 20px; }
.form-row--split { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.form-field { display: flex; flex-direction: column; gap: 8px; }
.form-field label { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.16em; color: var(--muted); }
.form-field input, .form-field select, .form-field textarea {
	width: 100%; box-sizing: border-box; background: rgba(127,217,196,0.05); border: 1px solid rgba(127,217,196,0.2);
	border-radius: var(--r-field); padding: 14px 16px; font-family: 'Archivo', sans-serif; font-size: 15px; color: var(--fg);
	outline: none; transition: all .3s;
}
.form-field input:focus, .form-field select:focus, .form-field textarea:focus { border-color: rgba(127,217,196,0.7); background: rgba(127,217,196,0.08); }
/* Selects inherit the field styling above; only the native chrome needs
   overriding. The arrow is an inline SVG in currentColor so it follows the
   theme (and the high-contrast switch) instead of staying an OS-grey triangle,
   and the right padding keeps long package names off it. The option list
   itself is drawn by the OS — colour-scheme keeps that popup dark on the dark
   theme, which is as far as styling options can be trusted to go. */
.form-field select {
	appearance: none; -webkit-appearance: none;
	padding-right: 42px; cursor: pointer; color-scheme: dark;
	--select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%237fd9c4' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
}
:root[data-theme="light"] .form-field select {
	color-scheme: light;
	--select-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%23107a63' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
}
/* The arrow's repeat/size/position have to be restated for EVERY state that
   sets `background` as a shorthand — the field rules above and their :focus
   partners all do, and a shorthand silently resets background-repeat to
   `repeat` and background-size to `auto`. That is what tiled the chevron across
   the whole control in light mode. Each selector below matches the specificity
   of the shorthand rule it has to beat and sits later in the file, so the arrow
   survives in both themes, focused or not. Keep them in sync if a new state
   ever sets `background` on a select. */
.form-field select,
.form-field select:focus,
:root[data-theme="light"] .form-field select,
:root[data-theme="light"] .form-field select:focus {
	background-image: var(--select-arrow);
	background-repeat: no-repeat;
	background-position: right 16px center;
	background-size: 12px 8px;
}
/* The option list is drawn by the OS, not by us, and it does NOT reliably
   follow color-scheme — Windows/Chrome paints a light popup while the theme's
   --fg is near-white, which is white-on-white: unreadable until the highlight
   bar passes over an item. So set background AND colour together as a pair,
   with literals rather than tokens, because a token that resolves against the
   page can't be trusted inside a popup the page doesn't own. */
.form-field select option { background-color: #10231d; color: #e8f3ef; }
.form-field select option[value=""] { color: #9fb3ad; }
:root[data-theme="light"] .form-field select option { background-color: #ffffff; color: #10231d; }
:root[data-theme="light"] .form-field select option[value=""] { color: #6b7f79; }
/* Locked until a category is chosen — see initScopeFilter() in main.js. */
.form-field select:disabled { opacity: .55; cursor: not-allowed; }
.contact-form__honeypot { position: absolute !important; left: -9999px !important; width: 1px; height: 1px; opacity: 0; }
.contact-form__status { margin: 0; font-family: 'IBM Plex Mono', monospace; font-size: 13px; letter-spacing: 0.05em; min-height: 1em; }
.contact-form__status.is-error { color: #e58a8a; }
.contact-success { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; text-align: center; min-height: 340px; }
.contact-success__icon {
	width: 64px; height: 64px; border-radius: 999px; background: rgba(127,217,196,0.12); border: 1px solid rgba(127,217,196,0.4);
	display: flex; align-items: center; justify-content: center; font-size: 30px; color: #8fe3cf;
}
.contact-success__icon svg { width: 38px; height: 38px; overflow: visible; }
.contact-success__ring, .contact-success__tick { stroke: currentColor; }
/* Drawn, not shown. Both paths start fully "unwritten" (dash length == path
   length, offset the same) and animate their offset to zero, so the ring closes
   and the tick then writes itself in. The panel is display:flex and only
   revealed on success, so these run exactly once, when the message lands. */
.contact-success__ring { stroke-dasharray: 145; stroke-dashoffset: 145; opacity: .55; }
.contact-success__tick { stroke-dasharray: 44; stroke-dashoffset: 44; }
.contact-success:not([hidden]) .contact-success__ring {
	animation: successDraw .55s cubic-bezier(.22,.9,.3,1) .05s forwards;
}
.contact-success:not([hidden]) .contact-success__tick {
	animation: successDraw .4s cubic-bezier(.22,.9,.3,1) .42s forwards;
}
.contact-success:not([hidden]) .contact-success__icon {
	animation: successPop .5s var(--ease-bouncy) both;
}
@keyframes successDraw { to { stroke-dashoffset: 0; } }
@keyframes successPop {
	0%   { transform: scale(.72); opacity: 0; }
	100% { transform: scale(1); opacity: 1; }
}
/* The panel itself arrives from below, per §04: one overshoot, from below. */
.contact-success:not([hidden]) h3,
.contact-success:not([hidden]) p,
.contact-success:not([hidden]) .btn {
	animation: successRise .5s cubic-bezier(.22,.9,.3,1) both;
}
.contact-success:not([hidden]) h3 { animation-delay: .18s; }
.contact-success:not([hidden]) p { animation-delay: .26s; }
.contact-success:not([hidden]) .btn { animation-delay: .34s; }
@keyframes successRise {
	from { opacity: 0; transform: translateY(14px); }
	to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
	.contact-success:not([hidden]) .contact-success__ring,
	.contact-success:not([hidden]) .contact-success__tick,
	.contact-success:not([hidden]) .contact-success__icon,
	.contact-success:not([hidden]) h3,
	.contact-success:not([hidden]) p,
	.contact-success:not([hidden]) .btn { animation: none; stroke-dashoffset: 0; opacity: 1; transform: none; }
}
.a11y-reduce-motion .contact-success * { animation: none !important; stroke-dashoffset: 0 !important; }
.contact-success h3 { font-size: 28px; font-weight: 800; color: var(--fg); }
.contact-success p { font-size: 16px; color: var(--muted); }
.site-footer-line { margin: 64px auto 0; font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.2em; color: var(--faint); }

/* ---------- Case study ---------- */
/* A grounded, full-width nav BAR (fixed outside the scroller — crisp + reliably
   clickable). A backdrop bar — not floating pills — so visitors immediately read
   it as "the navigation" and never hunt for the way back or to contact. Matches
   the homepage sticky nav's language. */
.case-topbar {
	position: fixed; top: 0; left: 0; right: 0; z-index: 110;
	display: flex; justify-content: space-between; align-items: center; gap: 16px;
	padding: 14px 34px;
	background: rgba(10,16,14,0.72);
	-webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
	border-bottom: 1px solid rgba(127,217,196,0.14);
}
:root[data-theme="light"] .case-topbar { background: rgba(244,247,245,0.82); border-bottom-color: var(--border-hair); }
.case-back {
	display: inline-flex; align-items: center; gap: 10px; text-decoration: none;
	padding: 12px 22px 12px 16px; border-radius: 999px;
	font-family: 'IBM Plex Mono', monospace; font-size: 13px; letter-spacing: 0.12em; font-weight: 700;
	/* Mint-tinted and clearly outlined so it reads as a button against the bar,
	   not a faint label that blends into the dark hero. */
	color: #d7f5ec; background: linear-gradient(135deg, rgba(127,217,196,0.2), rgba(127,217,196,0.09));
	border: 1px solid rgba(127,217,196,0.55);
	box-shadow: 0 6px 20px rgba(0,0,0,0.4), 0 0 16px rgba(127,217,196,0.16);
	transition: all .3s cubic-bezier(.34,1.56,.64,1);
}
.case-back:hover { transform: translateX(-3px); border-color: rgba(127,217,196,0.95); color: #8fe3cf; background: linear-gradient(135deg, rgba(127,217,196,0.3), rgba(127,217,196,0.14)); box-shadow: 0 12px 30px rgba(0,0,0,0.5), 0 0 26px rgba(127,217,196,0.34); }
.case-back__arrow { font-size: 17px; line-height: 1; transition: transform .3s ease; }
.case-back:hover .case-back__arrow { transform: translateX(-3px); }
:root[data-theme="light"] .case-back { color: #0f2b23; background: linear-gradient(135deg, rgba(31,143,118,0.16), rgba(31,143,118,0.07)); border-color: rgba(31,143,118,0.5); box-shadow: 0 6px 20px rgba(20,40,34,0.14); }
.case-topbar__counter {
	font-family: 'IBM Plex Mono', monospace; font-size: 12px; letter-spacing: 0.24em; color: var(--muted);
}
/* Push the hero below the fixed bar. */
/* Compact hero: less padding, a slightly smaller title and a WIDER intro so the
   paragraph fills the space that used to sit empty to the right — fewer lines,
   less height, so the actual work comes into view sooner. */
.case-hero { position: relative; overflow: hidden; padding: 60px 64px 40px; }
.case-hero--offset { padding-top: 84px; }
.case-hero__grid { opacity: 0.4; -webkit-mask-image: radial-gradient(ellipse 90% 80% at 50% 40%, #000 0%, transparent 80%); mask-image: radial-gradient(ellipse 90% 80% at 50% 40%, #000 0%, transparent 80%); }
.case-hero__inner { position: relative; z-index: 2; max-width: 1760px; margin: 0 auto; display: flex; flex-direction: column; gap: 30px; }
.case-hero__text { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.case-hero__kicker { display: flex; align-items: center; gap: 14px; font-family: 'IBM Plex Mono', monospace; font-size: 12px; letter-spacing: 0.28em; color: #7fd9c4; animation: riseIn .6s ease .05s both; }
.case-hero__dot { width: 7px; height: 7px; border-radius: 50%; }
.case-hero__title { font-size: clamp(2.4rem, 6.4vw, 104px); font-weight: 900; letter-spacing: -0.035em; line-height: 0.96; padding-bottom: 0.04em; color: #f2f7f4; overflow-wrap: anywhere; hyphens: auto; animation: nameReveal 1.1s cubic-bezier(.16,1,.3,1) .15s both; }
.case-hero__intro { max-width: 1040px; font-size: clamp(18px, 1.55vw, 24px); font-weight: 500; line-height: 1.5; color: #c3d7cf; text-wrap: pretty; animation: riseIn .7s ease .5s both; }

.case-section { padding: 48px 64px; box-sizing: border-box; }
/* Wider, fewer columns (~3-up on desktop) so the long comma-lists — Role and
   especially Services — run wide-and-short instead of a tall narrow stack. Wide
   tracks that divide the 6 cells evenly avoid phantom empty cells. */
.case-meta-grid {
	max-width: 1760px; margin: 0 auto; display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 480px), 1fr)); gap: 2px;
	border: 1px solid rgba(127,217,196,0.14); border-radius: var(--r-md); overflow: hidden; background: rgba(127,217,196,0.14);
}
.case-meta-cell { background: #101a15; padding: 24px 26px; display: flex; flex-direction: column; gap: 10px; }
.case-meta-cell__key { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.2em; color: #8fab9f; }
.case-meta-cell__value { font-size: 16px; font-weight: 600; color: #eef4f1; line-height: 1.4; }

/* The meta card now rides inside the hero (see below), so it sits on the hero's
   own surface — dark green, or cream in light mode. The old connected near-black
   card would vanish there, so each field becomes a light-bordered chip on a
   transparent grid: it reads on both themes, and an empty track (odd field counts,
   e.g. a project with a Client) just shows the hero background — no phantom cell. */
.case-hero__meta .case-meta-grid { max-width: none; margin: 0; background: transparent; border: 0; border-radius: 0; overflow: visible; gap: 8px; }
/* Bigger than they were. These cells carry the facts a visitor scans for first
   (who, what, when, where) and they were set smaller than the body text they
   sit beside, which put the most-wanted information at the bottom of the
   hierarchy. */
.case-hero__meta .case-meta-cell { background: rgba(127,217,196,0.06); border: 1px solid rgba(127,217,196,0.16); border-radius: var(--r-sm); padding: 16px 18px; gap: 9px; }
.case-hero__meta .case-meta-cell__key { font-size: 11px; letter-spacing: 0.22em; }
.case-hero__meta .case-meta-cell__value { font-size: 17.5px; line-height: 1.4; }
:root[data-theme="light"] .case-hero__meta .case-meta-cell { background: #ffffff; border-color: rgba(31,143,118,0.2); box-shadow: 0 1px 2px rgba(40,50,44,0.05); }
:root[data-theme="light"] .case-hero__meta .case-meta-cell__value { color: var(--fg); }
:root[data-theme="light"] .case-hero__meta .case-meta-cell__key { color: var(--muted); }

/* Desktop: text left, a compact 2-up meta card right (filling the space that used
   to sit empty beside the title) — so the brief and the work rise up, with no
   separate full-width meta band. The long lists (Role, Services) span both cols.
   Below 1100px the hero stacks: text, then the meta chips below (1-up). */
@media (min-width: 1100px) {
	.case-hero--split .case-hero__inner {
		display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(380px, 0.9fr);
		column-gap: clamp(40px, 4vw, 76px); align-items: start;
	}
	.case-hero__meta { align-self: start; }
	.case-hero__meta .case-meta-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.case-hero__meta .case-meta-cell { padding: 13px 16px; }
	.case-hero__meta .case-meta-cell__key { font-size: 10.5px; }
	.case-hero__meta .case-meta-cell__value { font-size: 15px; line-height: 1.45; }
	.case-hero__meta .case-meta-cell--wide { grid-column: 1 / -1; }
}
.case-brief-grid { max-width: 1520px; margin: 0 auto; display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 56px; }
.case-brief-col { display: flex; flex-direction: column; gap: 16px; }
.case-brief-col__kicker { font-family: 'IBM Plex Mono', monospace; font-size: 12px; letter-spacing: 0.22em; }
.case-brief-col p { font-size: 19px; line-height: 1.65; color: #b7cdc5; text-wrap: pretty; }
/* Paper theme: several case-study text colours were tuned for the dark tube and
   wash out on the cream section surfaces. Remap the ones that sit directly on the
   paper (the meta grid keeps its own dark cells, so it's left alone) to the
   theme's ink vars so brief / challenge / solution / outcome, the hero intro, the
   credits and body links all read with comfortable contrast. */
:root[data-theme="light"] .case-brief-col p { color: #47564f; }
:root[data-theme="light"] .case-hero__intro { color: var(--body); }
:root[data-theme="light"] .case-credits__value { color: var(--fg); }
:root[data-theme="light"] .case-credits__key { color: var(--muted); }
:root[data-theme="light"] .case-body a { color: #1a7d68; }
.case-brief-col p + p { margin-top: 14px; }
/* Case-study close — the Solution / Outcome block reuses the brief grid, but a
   hairline above sets it apart so it reads as the resolution after the visuals,
   not more setup. Numbering (03/04) continues the arc that 01/02 opened. */
.case-section--outcome { padding-top: 8px; }
.case-outcome-grid { border-top: 1px solid rgba(127,217,196,0.14); padding-top: 52px; }
:root[data-theme="light"] .case-outcome-grid { border-top-color: var(--border-hair); }
/* Key visual — big and ADAPTIVE. No forced 16:9: the media keeps its own shape
   (a vertical video shows tall, not pillarboxed) and fills the width up to the
   point where it would get taller than ~86vh, so it stays screen-filling but
   never taller than the viewport. */
.case-hero-visual {
	width: 100%; max-width: 1760px; margin: 0 auto;
	border-radius: var(--r-panel); overflow: hidden; background-color: #0e1815;
	display: flex; justify-content: center;
}
/* Default (landscape / wide media): FILL the width — big and screen-filling —
   even for a low-resolution file, capped at 90vh so it never exceeds the screen
   (cover-crops rather than distorts if it would). */
.case-hero-visual__img,
.case-hero-visual video { display: block; width: 100%; height: auto; max-height: 90vh; object-fit: cover; }
.case-hero-visual iframe { display: block; border: 0; width: 100%; aspect-ratio: 16 / 9; }
.case-hero-visual--video { background-image: none; }
/* Portrait media (detected server-side): hug it — tall and centred, not stretched
   across the full width — so it stays its own shape without cropping. */
.case-hero-visual--portrait { width: -moz-fit-content; width: fit-content; }
.case-hero-visual--portrait .case-hero-visual__img,
.case-hero-visual--portrait video { width: auto; max-width: 100%; height: auto; max-height: 90vh; object-fit: contain; }
.case-placeholder-label { font-family: 'IBM Plex Mono', monospace; font-size: 13px; letter-spacing: 0.26em; color: #8fab9f; }
/* Credit / caption under a visual (who made it, whose property it is). */
.case-visual-figure { max-width: 1760px; margin: 0 auto; }
.case-visual-credit,
.case-media-credit {
	margin: 12px 2px 0; font-family: 'IBM Plex Mono', monospace; font-size: 12px;
	letter-spacing: 0.12em; color: var(--faint); line-height: 1.5; text-align: center;
}
.case-media-credit { text-align: left; margin: 8px 4px 0; font-size: 11px; }
.case-section--collage { padding: 20px clamp(16px, 2.4vw, 40px) 56px; }
/* Masonry mosaic — big, near-full-bleed columns for a screen-filling case study.
   Each tile keeps its media's own shape (a vertical video makes a tall tile); the
   masonry packs the mixed orientations. Fewer, larger columns = bold presentation. */
/* At most TWO items side by side (big). column-count caps it at 2; column-width
   drops it to 1 on narrow screens (phones) automatically. */
.case-collage { column-count: 2; column-width: 22rem; column-gap: 20px; }
/* .case-collage__tile = the masonry cell (media frame + optional caption). */
.case-collage__tile { break-inside: avoid; margin: 0 0 20px; }
.case-collage__media {
	border-radius: var(--r-md); overflow: hidden; border: 1px solid rgba(127,217,196,0.16); background-color: #0e1815;
}
.case-credits { max-width: 1520px; margin: 0 auto; border-top: 1px solid rgba(127,217,196,0.14); padding-top: 40px; display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 32px; }
.case-credits__cell { display: flex; flex-direction: column; gap: 6px; }
.case-credits__key { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.2em; color: #8fab9f; }
.case-credits__value { font-size: 16px; font-weight: 600; color: #eef4f1; }
.case-prevnext { max-width: 1520px; margin: 0 auto; display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px; }
.case-prevnext__card {
	text-decoration: none; border-radius: var(--r-card); border: 1px solid rgba(127,217,196,0.14);
	background: linear-gradient(150deg, #1b2a23 0%, #14211b 100%); padding: 30px; display: flex; flex-direction: column;
	gap: 10px; transition: all .4s cubic-bezier(.34,1.56,.64,1);
}
.case-prevnext__card:hover { transform: translateY(-4px); border-color: rgba(127,217,196,0.4); }
.case-prevnext__card--next { align-items: flex-end; text-align: right; }
.case-prevnext__label { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.2em; color: #8fab9f; }
.case-prevnext__name { font-size: 24px; font-weight: 800; color: #f2f7f4; }
.case-prevnext__tag { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.16em; }
.case-footer-cta {
	padding: 100px 64px 90px; box-sizing: border-box; display: flex; flex-direction: column; align-items: center;
	gap: 26px; text-align: center; background-image: radial-gradient(ellipse 70% 60% at 50% 100%, rgba(30,52,45,0.5) 0%, rgba(10,16,14,0) 70%);
}
.case-footer-cta__title { font-size: clamp(40px, 4.6vw, 72px); font-weight: 900; letter-spacing: -0.02em; color: #f2f7f4; }
.case-footer-cta .site-footer-line { margin-top: 40px; color: #4f645c; }

/* --- Light theme: case study ------------------------------------------------
   These three were hardcoded to near-white for the dark tube and never got a
   Warm-Archive counterpart, so on paper they were white-on-cream: the case
   title, the closing CTA headline, and the prev/next tag line. The tag is the
   subtle one — those CARDS stay dark in light mode, so its text has to stay
   light too. Fixing it by flipping the card would have been the wrong end. */
:root[data-theme="light"] .case-hero__title,
:root[data-theme="light"] .case-footer-cta__title { color: #16261f; }
:root[data-theme="light"] .case-footer-cta {
	background-image: radial-gradient(ellipse 70% 60% at 50% 100%, rgba(31,143,118,0.09) 0%, rgba(255,255,255,0) 70%);
}
:root[data-theme="light"] .case-footer-cta .site-footer-line { color: #6b7f79; }
/* Explicit in BOTH themes: it had no colour at all and simply inherited, which
   is why it followed the page to dark text while its card stayed dark. */
.case-prevnext__tag { color: #7fd9c4; }
:root[data-theme="light"] .case-prevnext__tag { color: #8fd6c8; }
:root[data-theme="light"] .case-prevnext__name { color: #f2f7f4; }
:root[data-theme="light"] .case-prevnext__label { color: #a8c2b7; }

/* =========================================================================
   Display settings panel — visitor-facing effect + theme controls
   ========================================================================= */
.emre-display-controls { position: fixed; right: 22px; bottom: 22px; z-index: 120; }

.emre-display-toggle {
	width: 56px; height: 56px; border-radius: 999px; cursor: pointer;
	background: linear-gradient(135deg, #16241f, #0f1a16);
	border: 1px solid rgba(127,217,196,0.35);
	box-shadow: 0 8px 26px rgba(0,0,0,0.5), 0 0 18px rgba(127,217,196,0.14);
	display: flex; align-items: center; justify-content: center;
	transition: transform .35s cubic-bezier(.34,1.56,.64,1), box-shadow .35s ease, border-color .35s ease;
}
.emre-display-toggle:hover { transform: translateY(-2px); border-color: rgba(127,217,196,0.7); box-shadow: 0 12px 30px rgba(0,0,0,0.55), 0 0 26px rgba(127,217,196,0.28); }
.emre-display-toggle__icon { display: flex; flex-direction: column; gap: 4px; width: 22px; }
.emre-display-toggle__icon span { height: 2px; border-radius: 2px; background: #8fe3cf; display: block; }
.emre-display-toggle__icon span:nth-child(1) { width: 100%; }
.emre-display-toggle__icon span:nth-child(2) { width: 60%; }
.emre-display-toggle__icon span:nth-child(3) { width: 85%; }
.is-open .emre-display-toggle { border-color: rgba(127,217,196,0.7); }

.emre-display-panel {
	position: absolute; right: 0; bottom: calc(100% + 14px); width: 340px; max-width: calc(100vw - 44px);
	max-height: min(74vh, 620px); overflow-y: auto;
	background: linear-gradient(180deg, rgba(20,32,27,0.98), rgba(14,22,18,0.98));
	border: 1px solid rgba(127,217,196,0.22); border-radius: var(--r-card); padding: 22px;
	box-shadow: 0 26px 70px rgba(0,0,0,0.6), 0 0 40px rgba(127,217,196,0.08);
	-webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
	color: var(--fg);
	animation: riseIn .3s ease both;
}
:root[data-theme="light"] .emre-display-panel {
	background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(238,244,240,0.98));
	border-color: rgba(31,143,118,0.3);
	box-shadow: 0 26px 70px rgba(20,40,34,0.25);
}
:root[data-theme="light"] .emre-display-toggle {
	background: linear-gradient(135deg, #ffffff, #e9f0ec);
	border-color: rgba(31,143,118,0.35);
}
:root[data-theme="light"] .emre-display-toggle__icon span { background: #1f8f76; }

.emre-display-panel__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.emre-display-panel__title { font-size: 16px; font-weight: 800; letter-spacing: -0.01em; color: var(--fg); }
.emre-display-panel__close {
	cursor: pointer; width: 30px; height: 30px; border-radius: 999px; flex: none;
	background: rgba(127,217,196,0.08); border: 1px solid rgba(127,217,196,0.2); color: var(--body);
	font-size: 13px; transition: all .25s ease;
}
.emre-display-panel__close:hover { background: rgba(127,217,196,0.18); color: var(--fg); }
.emre-display-panel__sub { margin: 8px 0 4px; font-size: 12.5px; line-height: 1.5; color: var(--muted); }

.emre-ctrl-group { padding: 16px 0; border-top: 1px solid rgba(127,217,196,0.12); margin-top: 6px; }
.emre-ctrl-group:first-of-type { border-top: none; }
.emre-ctrl-group__label { display: block; font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.22em; color: var(--faint); margin-bottom: 12px; }

.emre-ctrl { margin-bottom: 16px; }
.emre-ctrl:last-child { margin-bottom: 0; }
.emre-ctrl--row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.emre-ctrl label { font-size: 14px; font-weight: 600; color: var(--body); }
.emre-ctrl__top { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 9px; }
.emre-ctrl__top output { font-family: 'IBM Plex Mono', monospace; font-size: 12px; letter-spacing: 0.06em; color: #8fe3cf; }
:root[data-theme="light"] .emre-ctrl__top output { color: #1f8f76; }

/* Range slider — themed track + thumb, comfortable hit area */
.emre-ctrl input[type="range"] {
	-webkit-appearance: none; appearance: none; width: 100%; height: 6px; border-radius: 999px;
	background: rgba(127,217,196,0.16); outline-offset: 4px; cursor: pointer;
}
.emre-ctrl input[type="range"]::-webkit-slider-thumb {
	-webkit-appearance: none; appearance: none; width: 20px; height: 20px; border-radius: 50%;
	background: linear-gradient(135deg, #8fe3cf, #6cc9b2); border: 2px solid #0f1a16;
	box-shadow: 0 2px 8px rgba(0,0,0,0.4); cursor: pointer;
}
.emre-ctrl input[type="range"]::-moz-range-thumb {
	width: 20px; height: 20px; border-radius: 50%; border: 2px solid #0f1a16;
	background: linear-gradient(135deg, #8fe3cf, #6cc9b2); box-shadow: 0 2px 8px rgba(0,0,0,0.4); cursor: pointer;
}
:root[data-theme="light"] .emre-ctrl input[type="range"]::-webkit-slider-thumb { border-color: #ffffff; }
:root[data-theme="light"] .emre-ctrl input[type="range"]::-moz-range-thumb { border-color: #ffffff; }

/* Toggle switch */
.emre-switch {
	position: relative; width: 46px; height: 26px; border-radius: 999px; cursor: pointer; flex: none;
	background: rgba(127,217,196,0.14); border: 1px solid rgba(127,217,196,0.22); transition: background .25s ease, border-color .25s ease;
}
.emre-switch__thumb {
	position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; border-radius: 50%;
	background: var(--body); transition: transform .28s cubic-bezier(.34,1.56,.64,1), background .25s ease;
}
.emre-switch[aria-checked="true"] { background: linear-gradient(135deg, #8fe3cf, #6cc9b2); border-color: transparent; }
.emre-switch[aria-checked="true"] .emre-switch__thumb { transform: translateX(20px); background: #0f1a16; }

/* Segmented (theme) control */
.emre-segmented { display: inline-flex; padding: 3px; gap: 3px; border-radius: 999px; background: rgba(127,217,196,0.1); border: 1px solid rgba(127,217,196,0.18); }
.emre-segmented__btn {
	cursor: pointer; border: none; background: transparent; color: var(--muted);
	font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.1em; padding: 8px 16px; border-radius: 999px;
	transition: all .25s ease; min-height: 34px;
}
.emre-segmented__btn.is-active { background: linear-gradient(135deg, #8fe3cf, #6cc9b2); color: #0a100e; }

.emre-display-reset {
	width: 100%; margin-top: 6px; cursor: pointer; padding: 13px; border-radius: 12px;
	background: rgba(127,217,196,0.08); border: 1px solid rgba(127,217,196,0.22); color: var(--body);
	font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.14em; transition: all .25s ease;
}
.emre-display-reset:hover { background: rgba(127,217,196,0.16); color: var(--fg); }

/* Phone: dock the panel as a bottom sheet so it never overflows a small screen */
@media (max-width: 560px) {
	.emre-display-controls { right: 16px; bottom: 16px; }
	.emre-display-panel {
		position: fixed; right: 0; left: 0; bottom: 0; width: auto; max-width: none;
		max-height: 82vh; border-radius: 22px 22px 0 0; padding: 20px 20px calc(20px + env(safe-area-inset-bottom));
	}
}
@media (prefers-reduced-motion: reduce) {
	.emre-display-panel { animation: none; }
}

/* =========================================================================
   Accessibility — skip link + visible keyboard focus on every interactive el.
   ========================================================================= */
.site-main { display: block; }
/* Skip-to-content: off-screen until focused, then a pill in the top-left. */
.emre-skip-link {
	position: fixed; top: 12px; left: 12px; z-index: 200;
	transform: translateY(-140%); transition: transform .2s ease;
	padding: 12px 20px; border-radius: 999px;
	background: linear-gradient(135deg, #8fe3cf, #6cc9b2); color: #0a100e;
	font-family: 'IBM Plex Mono', monospace; font-size: 12px; letter-spacing: 0.12em; font-weight: 600;
	text-decoration: none; box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}
.emre-skip-link:focus { transform: translateY(0); outline: none; }
:where(a, button, input, textarea, [role="button"], [tabindex]):focus-visible {
	outline: 2px solid #8fe3cf;
	outline-offset: 3px;
	border-radius: 8px;
}
.domain-tile:focus-visible { outline-offset: -3px; }
[data-theme="light"] :where(a, button, input, textarea, [role="button"], [tabindex]):focus-visible {
	outline-color: #1f8f76;
}

/* =========================================================================
   Reduced motion — kill the infinite CRT/marquee/flicker loops and the
   scroll-heavy displacement filter for users who ask for calm.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
		scroll-behavior: auto !important;
	}
	/* The CRT stack is entirely static since v73 (Cadence §11 — "one paint, no
	   animation"), so there is nothing left in it to silence here. */
	.hero__scan-sweep,
	.hero__hud-grid, .ribbon__track, .hero__cursor-blink { animation: none !important; }
}

/* =========================================================================
   Touch devices — hover lifts "stick" after a tap on touch (the :hover state
   latches until you tap elsewhere). Neutralise the movement so cards/buttons
   don't stay raised or expanded after being tapped. Colour/shadow hovers are
   left alone — only the layout-shifting transforms are reset.
   ========================================================================= */
@media (hover: none) {
	.project-card:hover .project-card__frame,
	.service-card:hover, .training-card:hover,
	.case-prevnext__card:hover, .case-back:hover,
	.btn:hover, .site-nav__link--contact:hover,
	.emre-display-toggle:hover { transform: none; }
	.domain-tile:hover { flex-grow: 1; }
}

/* =========================================================================
   Responsive — mobile-first refinements. Desktop rules above are the
   baseline; these progressively adapt down without degrading large screens.
   ========================================================================= */

/* --- Tablet / small laptop --- */
@media (max-width: 1100px) {
	.section { padding: 96px 40px; }
	.about-grid, .cv-grid, .contact-grid, .case-brief-grid { grid-template-columns: 1fr; }
	.about-portrait { height: clamp(380px, 62vh, 520px); }
	/* Five domains reflow to a 2-column field; the 5th spans full width so the
	   band still reads as one connected system rather than an orphaned tile. */
	.domain-band { flex-wrap: wrap; height: auto; gap: 10px; }
	.domain-tile { flex: 1 1 calc(50% - 5px); min-height: 128px; border-radius: 24px !important; }
	.domain-tile--3d-modelling { flex-basis: 100%; }
	.contact-grid { gap: 48px; }
}

/* --- Phone: switch the CRT "TV" from a nested inner-scroller to native page
   scroll. The glowing bezel/vignette stay as fixed decorative overlays framing
   the viewport, so the identity is preserved while the address bar collapses,
   momentum scrolling returns, and the per-frame warp filter is dropped. --- */
@media (max-width: 860px) {
	/* Undo the desktop document lock: phones scroll the window natively.
	   html stays the page scroller (overflow-x:hidden ⇒ overflow-y:auto), but body
	   must NOT become a scroll container — overflow-x:hidden on body would make it a
	   content-height scrollport and kill the sticky nav. overflow-x:clip pairs with
	   overflow-y:visible so body clips sideways WITHOUT scrolling, restoring
	   position:sticky on .site-nav. */
	html { height: auto; overflow-x: hidden; overflow-y: visible; }
	body { height: auto; overflow-x: clip; overflow-y: visible; }
	/* Phones fill the screen edge-to-edge (no bezel frame) — only inset for the
	   notch / home indicator so nothing hides under them. */
	.emre-app { height: auto; min-height: 100dvh; overflow: visible; padding: 0; }
	@supports (padding: max(0px, env(safe-area-inset-left))) {
		.emre-app {
			padding: max(0px, env(safe-area-inset-top)) max(0px, env(safe-area-inset-right))
			         max(0px, env(safe-area-inset-bottom)) max(0px, env(safe-area-inset-left));
		}
	}
	.emre-screen { height: auto; overflow: visible; border-radius: 0; }
	/* Native page scroll on phones. */
	.site-scroll { height: auto; overflow: visible; border-radius: 0; }
	/* Full-bleed CRT overlays, top-anchored to the LARGE viewport (lvh never
	   changes when the address bar collapses, so the fixed layers don't jump). */
	.crt-lines, .crt-vignette, .crt-bulge,
	.crt-gloss, .crt-fringe {
		top: 0; right: 0; left: 0; bottom: auto;
		height: 100vh; height: 100lvh;
		border-radius: 0;
		transform: translateZ(0); backface-visibility: hidden;
	}

	.section { padding: 64px 20px; }
	.hero { min-height: calc(100dvh - 20px); padding: 18px 20px 24px; }

	/* Compact mobile nav: just the ES logo + a hamburger. The redundant name is
	   dropped (it's already the giant hero title below); the links drop down. */
	/* Trimmed again: the bar was still eating a fifth of a phone screen before
	   any content appeared. Padding does the work — the 44px tap targets are
	   the accessible minimum and stay untouched. */
	.site-nav { flex-wrap: nowrap; gap: 10px; padding: 5px 14px; }
	.site-nav__brand { gap: 12px; }
	.site-nav__lockup { display: none; }
	.site-nav__mark { width: 40px; height: 40px; border-radius: 13px 13px 13px 20px; font-size: 16px; }
	.site-nav__toggle {
		display: flex; flex-direction: column; justify-content: center; gap: 5px;
		width: 44px; height: 44px; padding: 0; border: 1px solid rgba(127,217,196,0.28);
		border-radius: 13px; background: rgba(127,217,196,0.06); cursor: pointer;
	}
	.site-nav__toggle-bar { width: 20px; height: 2px; margin: 0 auto; background: #7fd9c4; border-radius: 2px; transition: transform .25s ease, opacity .2s ease; }
	.site-nav.is-menu-open .site-nav__toggle-bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
	.site-nav.is-menu-open .site-nav__toggle-bar:nth-child(2) { opacity: 0; }
	.site-nav.is-menu-open .site-nav__toggle-bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
	.site-nav__links {
		position: absolute; top: 100%; left: 0; right: 0; display: none; flex-direction: column; align-items: stretch; gap: 4px;
		margin: 0; padding: 10px 16px calc(16px + env(safe-area-inset-bottom));
		background: rgba(10,16,14,0.94); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
		border-bottom: 1px solid rgba(127,217,196,0.14);
		animation: navDrop .22s ease both;
	}
	.site-nav.is-menu-open .site-nav__links { display: flex; }
	:root[data-theme="light"] .site-nav__links { background: rgba(244,247,245,0.96); border-bottom-color: var(--border-hair); }
	.site-nav__link { text-align: center; padding: 14px 18px; font-size: 13px; min-height: 44px; display: flex; align-items: center; justify-content: center; }

	.hero { min-height: auto; padding: 20px 22px 18px; }
	.hero__content { gap: 18px; padding: 14px 0; }
	.hero__kicker { font-size: 11px; letter-spacing: 0.24em; gap: 8px; flex-wrap: wrap; justify-content: center; }
	.hero__namelock { gap: 10px; }
	/* Keep the four choices as a compact 2x2 (never a tall stack) so the whole
	   hero — name, tagline, question and all four doors — fits one screen. */
	.hero-intent { margin-top: 24px; gap: 16px; max-width: 560px; }
	.hero-intent__grid { gap: 12px; }
	.intent { padding: 18px; gap: 14px; }
	.intent__icon { width: 52px; height: 52px; }
	.intent__icon svg { width: 26px; height: 26px; }

	.ribbon__viewport { height: 72px; }
	.ribbon__item { height: 56px; min-width: 150px; font-size: 15px; padding: 0 26px; }

	.section-title { font-size: clamp(2rem, 9vw, 44px); }
	/* Two-up project grid on phones instead of one-by-one — halves the scroll and
	   the pair of brand-coloured tiles looks intentional, not endless. */
	.projects-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
	.project-card { gap: 10px; }
	.project-card__meta { gap: 8px; padding-left: 0; }
	.project-card__name { font-size: 15px; }
	.project-card__cat { font-size: 10px; }
	.project-card__wordmark { font-size: clamp(16px, 4.5vw, 26px); padding: 14px; }
	.project-card__placeholder-label { font-size: 11px; letter-spacing: 0.16em; }
	.services-grid, .trainings-grid { grid-template-columns: 1fr; }
	.svc-cols--pair, .svc-cols--single { grid-template-columns: 1fr; }
	/* Collapse the three-up matrix to one column; let items flow in source order. */
	.svc-matrix { grid-template-columns: 1fr; gap: 14px; }
	.svc-matrix > * { grid-column: auto !important; grid-row: auto !important; }
	.svc-matrix__head { margin-top: 8px; }
	.svc-col { padding: 18px; }
	.services-cta .btn { width: 100%; }
	.cv-footer { flex-direction: column; align-items: stretch; gap: 28px; }
	.cv-education { gap: 24px; }
	.btn--outline { align-self: flex-start; }
	.form-row--split { grid-template-columns: 1fr; }
	.section { --sec-fade: 88px; }               /* shorter colour fade on small screens */
	.section--contact { padding-left: 20px; padding-right: 20px; padding-bottom: 64px; }
	.contact-panel { padding: 26px; }
	.site-footer-line { margin-top: 40px; }

	/* Case study */
	.case-topbar { padding: 10px 16px; gap: 10px; }
	.case-topbar__counter { display: none; } /* keep the two actions clear on small screens */
	.case-back { padding: 11px 18px 11px 14px; font-size: 12px; }
	.case-hero { padding: 48px 20px 64px; }
	.case-hero--offset { padding-top: 88px; }
	.case-section { padding: 32px 20px; }
	.case-brief-grid { gap: 32px; }
	/* Mosaic on phones: force a single big column. */
	.case-collage { column-count: 1; column-gap: 14px; }
	.case-collage__tile { margin-bottom: 14px; }
	.case-prevnext { grid-template-columns: 1fr; }
	.case-footer-cta { padding: 72px 20px 64px; }
}

/* --- Phone: one clean column of doors, decluttered. Placed AFTER the 860 block
   so it wins (max-width blocks must run widest → narrowest in source order). --- */
@media (max-width: 560px) {
	.hero { min-height: auto; padding: 18px 18px 20px; }
	.hero__content { gap: 16px; padding: 8px 0; }
	/* The three words ARE the positioning statement — dropping them to save
	   space traded away the one line that says what this site is about. Kept,
	   but reset to the smallest readable mono and allowed to wrap onto two
	   lines, which costs about 20px instead of the ~40 the old spacing did. */
	.hero__kicker {
		display: flex; flex-wrap: wrap; justify-content: center;
		font-size: 9.5px; letter-spacing: 0.18em; gap: 6px; line-height: 1.5;
	}
	/* The theme switch was the other space hog above the fold — a full-width
	   pill with desktop padding. Same control, two thirds the height. */
	.hero-theme { padding: 3px; }
	.hero-theme__btn { padding: 8px 14px; font-size: 10px; letter-spacing: 0.16em; gap: 7px; }
	.hero-theme__glyph { width: 14px; height: 14px; }
	.hero__name { font-size: clamp(40px, 14vw, 68px); }
	/* Phone: the name wraps to two lines, so a left-side title reads as floating.
	   Stack "Ing." centred above the name instead. */
	.hero__namelock { flex-direction: column; align-items: center; gap: 2px; }
	.hero__namelock::after { display: none; }
	.hero__ing { font-size: 15px; }
	.hero__tagline { font-size: clamp(15px, 4.2vw, 18px); }
	.hero-intent { margin-top: 20px; gap: 14px; max-width: 460px; }
	.hero-intent__ask { font-size: clamp(19px, 5.2vw, 23px); }
	.hero-intent__grid { grid-template-columns: 1fr; gap: 10px; }
	.intent { padding: 15px 16px; gap: 14px; border-radius: var(--r-sm); }
	.intent__icon { width: 46px; height: 46px; border-radius: 13px; }
	.intent__icon svg { width: 24px; height: 24px; }
	.intent__goal { font-size: 16px; }
	.intent__sub { display: block; font-size: 12.5px; }
	.intent__arrow { display: none; }
	.ribbon { margin-top: 16px; padding-top: 16px; }
}

/* --- Small phone --- */
@media (max-width: 420px) {
	.section { padding: 56px 16px; --sec-fade: 40px; }
	.hero { padding: 16px 16px 20px; }
	.hero__name { letter-spacing: -0.03em; }
	.site-nav__link { padding: 11px 14px; font-size: 12px; }
	.contact-title { font-size: clamp(2.25rem, 12vw, 48px); }
}

/* =========================================================================
   Real-content adjustments — assimilated ep_* data layer
   ========================================================================= */
/* Cards now carry the project's real brand colour (set inline on the frame),
   so the logo layer must be transparent instead of the placeholder stripes. */
.project-card__logo { background-image: none; padding: 0; }
.project-card__wordmark { display: flex; flex-direction: column; align-items: center; gap: 6px; font-weight: 800; font-size: clamp(22px, 3vw, 40px); letter-spacing: -0.01em; text-align: center; line-height: 1; padding: 24px; }
.project-card__wordmark small { font-family: 'IBM Plex Mono', monospace; font-size: 11px; font-weight: 500; letter-spacing: 0.24em; opacity: 0.8; }
.project-card__hover--label { background: rgba(8,14,12,0.82); display: flex; align-items: center; justify-content: center; }
.project-card__hover--label span { font-family: 'IBM Plex Mono', monospace; font-size: 13px; letter-spacing: 0.22em; color: #8fe3cf; }
.project-card__cat { margin-left: auto; font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.14em; color: var(--faint); }

.contact-socials { display: flex; gap: 18px; }
.contact-socials a { font-family: 'IBM Plex Mono', monospace; font-size: 12px; letter-spacing: 0.16em; color: var(--body); text-decoration: none; transition: color .25s ease; }
.contact-socials a:hover { color: #8fe3cf; }

/* Case-study mosaic — every tile ADAPTS to its media. Images and self-hosted
   .mp4 videos keep their natural aspect ratio (a vertical video makes a vertical
   tile — no more letterboxed side bars), and the masonry packs them. Only iframe
   embeds (YouTube/Vimeo), which have no intrinsic size, need an explicit box. */
.case-collage__media img, .case-collage__media video { width: 100%; height: auto; display: block; }
/* Self-hosted clips are silent, looping wallpaper — no controls, and unclickable
   so they can't be paused or long-pressed. (Scoped to <video>, so the tap-to-play
   Instagram/YouTube iframes that share the class keep their own interaction.) */
video.case-collage__video { pointer-events: none; }
.case-embed { position: relative; width: 100%; }
.case-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; }
/* Instagram's /embed renders on a white card — give the frame a matching bg and
   rounded corners so it reads as an intentional tile, not a raw iframe. */
.case-embed--ig { background: #fff; border-radius: var(--r-sm); overflow: hidden; }

/* Optional free case-study body (the project editor content). */
.case-body { max-width: 900px; margin: 0 auto; font-size: 18px; line-height: 1.7; color: var(--muted); }
.case-body h2, .case-body h3 { color: var(--fg); margin: 1.4em 0 0.5em; }
.case-body img { border-radius: var(--r-sm); margin: 24px 0; }
.case-body a { color: #8fe3cf; }

/* ---------- Fallback index / archive / search list ---------- */
.index-list { display: flex; flex-direction: column; gap: 4px; }
.index-item { padding: 24px 0; border-top: 1px solid rgba(127,217,196,0.12); }
.index-item:first-child { border-top: none; }
.index-item__title { font-size: 26px; font-weight: 700; letter-spacing: -0.01em; }
.index-item__title a { color: var(--fg); text-decoration: none; transition: color .25s ease; }
.index-item__title a:hover { color: #8fe3cf; }
.index-item__excerpt { margin-top: 8px; color: var(--muted); font-size: 16px; line-height: 1.6; }
.index-empty { color: var(--muted); font-size: 18px; }
.index-pagination { margin-top: 40px; }
.index-pagination .page-numbers { display: inline-flex; align-items: center; justify-content: center; min-width: 40px; height: 40px; padding: 0 12px; margin: 0 3px; border-radius: 10px; border: 1px solid rgba(127,217,196,0.2); color: var(--body); text-decoration: none; font-family: 'IBM Plex Mono', monospace; font-size: 13px; transition: all .25s ease; }
.index-pagination .page-numbers.current { background: linear-gradient(135deg, #8fe3cf, #6cc9b2); color: #0a100e; border-color: transparent; }
.index-pagination a.page-numbers:hover { border-color: rgba(127,217,196,0.6); color: #8fe3cf; }

/* =========================================================================
   Services sales page (page-services.php)
   Same CRT design language as the front page — hero, offer grid, process,
   packages, proof and FAQ, all tuned to sell rather than describe.
   ========================================================================= */
.svc-hero { display: flex; flex-direction: column; justify-content: center; min-height: calc(100dvh - 120px); overflow: hidden; }
/* width:100% is essential — the parent .svc-hero is a flex column, and the
   `margin:0 auto` here would otherwise defeat the default stretch and shrink this
   container to its content width, collapsing the chooser grid. */
.svc-hero__inner { position: relative; z-index: 2; width: 100%; max-width: min(1720px, 94vw); margin: 0 auto; text-align: center; display: flex; flex-direction: column; align-items: center; gap: 18px; }
.svc-hero__kicker { display: inline-block; }
.svc-hero__title { font-size: clamp(2.1rem, 5vw, 60px); font-weight: 900; letter-spacing: -0.03em; line-height: 0.98; color: var(--fg); }
.svc-hero__accent { color: #8fe3cf; }
.svc-hero__lede { max-width: 620px; font-size: clamp(16px, 1.6vw, 20px); line-height: 1.5; color: var(--body); font-weight: 500; }
.svc-hero__ctas { display: flex; gap: 14px; flex-wrap: wrap; justify-content: center; margin-top: 6px; }
.svc-hero__trust { font-family: 'IBM Plex Mono', monospace; font-size: 12px; letter-spacing: 0.14em; color: var(--faint); margin-top: 8px; }
.svc-hero__trust strong { color: var(--muted); font-weight: 600; }

/* Services hero "I want…" chooser (v3.23 "Gateway") — three photo doors that
   scroll to the matching section (#branding / #engineering / #purpose). Images
   reuse the Portfolio Content → Services fields; icon fallback otherwise. */
.svc-chooser { width: 100%; max-width: 100%; display: flex; flex-direction: column; align-items: center; gap: 20px; }
.svc-chooser__label { font-size: clamp(20px, 2.4vw, 30px); font-weight: 800; color: var(--fg); letter-spacing: -0.01em; }
.svc-chooser__grid { width: 100%; display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(16px, 1.6vw, 28px); }
.svc-choice {
	--svc-accent: #7fd9c4;
	/* Big, near screen-filling doors: wider (landscape) than the old squares so
	   more of each cover image reads at a glance. */
	position: relative; display: block; aspect-ratio: 4 / 3; border-radius: var(--r-panel); overflow: hidden;
	text-decoration: none; background: color-mix(in srgb, var(--svc-accent) 14%, var(--body-bg));
	border: 1px solid color-mix(in srgb, var(--svc-accent) 34%, transparent);
	transition: transform .4s cubic-bezier(.34,1.56,.64,1), box-shadow .4s ease, border-color .3s ease;
}
.svc-choice--a { --svc-accent: #7fd9c4; }
.svc-choice--b { --svc-accent: #e5c37c; }
.svc-choice--c { --svc-accent: #b3a5f2; }
.svc-choice:hover { transform: translateY(-6px); border-color: color-mix(in srgb, var(--svc-accent) 70%, transparent); box-shadow: 0 22px 50px rgba(0,0,0,0.45); }
.svc-choice__media { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.svc-choice__media img { width: 100%; height: 100%; object-fit: cover; }
.svc-choice__icon { color: var(--svc-accent); display: block; }
.svc-choice__icon svg { width: clamp(64px, 6vw, 92px); height: clamp(64px, 6vw, 92px); display: block; opacity: 0.9; }
.svc-choice__bar {
	position: absolute; left: 0; right: 0; bottom: 0; display: flex; align-items: center; justify-content: space-between; gap: 14px;
	padding: clamp(20px, 2vw, 32px) clamp(22px, 2.2vw, 36px); background: linear-gradient(to top, rgba(8,14,12,0.88) 0%, rgba(8,14,12,0.55) 62%, rgba(8,14,12,0) 100%);
}
.svc-choice__name { font-size: clamp(19px, 1.9vw, 28px); font-weight: 700; color: #f4f8f5; text-align: left; letter-spacing: -0.01em; line-height: 1.15; }
.svc-choice__arrow { flex: 0 0 auto; font-size: clamp(22px, 2vw, 30px); color: var(--svc-accent); transition: transform .3s ease; }
.svc-choice:hover .svc-choice__arrow { transform: translateX(4px); }
.svc-chooser__alt { font-size: 14px; color: var(--faint); }
.svc-chooser__alt a { color: #8fe3cf; text-decoration: none; border-bottom: 1px solid rgba(143,227,207,0.3); padding-bottom: 1px; }
.svc-chooser__alt a:hover { border-color: #8fe3cf; }
/* Paper-readable accents + alt link on the light theme. */
:root[data-theme="light"] .svc-choice--a { --svc-accent: #2f6f5d; }
:root[data-theme="light"] .svc-choice--b { --svc-accent: #8a6a2e; }
:root[data-theme="light"] .svc-choice--c { --svc-accent: #5a4e86; }
:root[data-theme="light"] .svc-chooser__alt a { color: #2f6f5d; border-color: rgba(47,111,93,0.3); }

/* Belief / problem statement — one big, quietly dramatic paragraph. */
.svc-belief .section__inner { max-width: 1000px; }
.svc-belief__statement { font-size: clamp(24px, 3vw, 40px); font-weight: 700; line-height: 1.32; letter-spacing: -0.02em; color: var(--faint); margin-top: 22px; }
.svc-belief__turn { color: var(--fg); display: block; margin: 0.4em 0; }

/* Offer grid — cards that read like a menu of outcomes. */
.svc-offer-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.svc-offer-card {
	display: flex; flex-direction: column; gap: 16px; padding: 30px; border-radius: var(--r-card);
	background: linear-gradient(160deg, rgba(255,255,255,0.03) 0%, rgba(255,255,255,0) 100%);
	border: 1px solid rgba(127,217,196,0.14); border-top: 3px solid var(--svc-accent);
	transition: transform .35s cubic-bezier(.16,1,.3,1), border-color .35s ease, box-shadow .35s ease;
}
.svc-offer-card:hover { transform: translateY(-6px); border-color: var(--svc-accent); box-shadow: 0 20px 50px rgba(0,0,0,0.35); }
.svc-offer-card--featured { grid-column: 1 / -1; background: var(--svc-tint); border-color: var(--svc-accent); }
.svc-offer-card--featured .svc-offer-card__pitch { font-size: 19px; max-width: 720px; }
.svc-offer-card__head { display: flex; flex-direction: column; gap: 8px; }
.svc-offer-card__tag { font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--svc-accent); }
.svc-offer-card__name { font-size: 26px; font-weight: 800; letter-spacing: -0.01em; color: var(--fg); }
.svc-offer-card__pitch { font-size: 16px; line-height: 1.55; color: var(--muted); }
.svc-offer-card__includes { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
.svc-offer-card__includes li { position: relative; padding-left: 22px; font-size: 14px; line-height: 1.5; color: var(--body); }
.svc-offer-card__includes li::before { content: ''; position: absolute; left: 2px; top: 8px; width: 8px; height: 8px; border-radius: 2px; background: var(--svc-accent); }
.svc-offer-card__outcome { margin-top: auto; padding-top: 14px; border-top: 1px solid rgba(127,217,196,0.12); font-size: 14px; font-weight: 600; color: var(--fg); }
.svc-offer-card__outcome span { color: var(--svc-accent); }

/* Process — four numbered moves. */
.svc-process-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; }
.svc-step { display: flex; flex-direction: column; gap: 12px; padding: 26px 0; border-top: 1px solid rgba(127,217,196,0.18); }
.svc-step__no { font-family: 'IBM Plex Mono', monospace; font-size: 15px; letter-spacing: 0.16em; color: #8fe3cf; }
.svc-step__name { font-size: 22px; font-weight: 800; color: var(--fg); }
.svc-step__desc { font-size: 15px; line-height: 1.6; color: var(--muted); }

/* Packages — three engagement tiers, the middle one lifted. */
.svc-package-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; align-items: stretch; }
.svc-package {
	position: relative; display: flex; flex-direction: column; gap: 10px; padding: 32px 28px; border-radius: var(--r-card);
	background: linear-gradient(160deg, rgba(255,255,255,0.03) 0%, rgba(255,255,255,0) 100%);
	border: 1px solid rgba(127,217,196,0.16);
}
.svc-package--featured { border-color: rgba(143,227,207,0.6); box-shadow: 0 0 0 1px rgba(143,227,207,0.25), 0 20px 50px rgba(0,0,0,0.35); }
.svc-package__badge { position: absolute; top: -12px; left: 28px; padding: 5px 14px; border-radius: 999px; font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.14em; color: #0a100e; background: linear-gradient(135deg, #8fe3cf, #6cc9b2); }
/* Name is the card heading now that prices are gone. */
.svc-package__name { font-size: 24px; font-weight: 800; letter-spacing: -0.01em; color: var(--fg); }
.svc-package__inherits { display: block; margin-top: 6px; font-size: 12.5px; font-weight: 600; color: var(--faint); }
.svc-package__points { list-style: none; padding: 0; margin: 16px 0 20px; display: flex; flex-direction: column; gap: 10px; }
.svc-package__points li { position: relative; padding-left: 24px; font-size: 15px; line-height: 1.5; color: var(--body); }
.svc-package__points li::before { content: '✓'; position: absolute; left: 0; top: 0; color: #8fe3cf; font-weight: 700; }
/* Outcome line sits just above the CTA and gets pinned to the bottom so the
   buttons line up across cards of different length. */
.svc-package__result { margin-top: auto; padding-top: 16px; border-top: 1px solid rgba(127,217,196,0.14); font-size: 13.5px; line-height: 1.5; color: var(--body); font-style: italic; }
.svc-package .btn { margin-top: auto; }
.svc-package__result + .btn { margin-top: 16px; }
.svc-packages__foot { margin-top: 28px; text-align: center; font-size: 15px; color: var(--faint); }

/* Sub-heading inside a services category (e.g. "Packages", "Trainings"). */
.svc-subhead { margin: 48px 0 20px; font-size: 22px; font-weight: 800; letter-spacing: -0.01em; color: var(--fg); }
/* "Scoped per project" note card (engineering group). */
.svc-note {
	display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap;
	margin-top: 24px; padding: 28px 32px; border-radius: var(--r-card);
	background: linear-gradient(160deg, rgba(255,255,255,0.03) 0%, rgba(255,255,255,0) 100%);
	border: 1px solid rgba(229,195,124,0.28);
}
.svc-note__text { font-size: 17px; line-height: 1.5; color: var(--body); max-width: 640px; }
.svc-note .btn { flex: none; }

/* Proof — stat row + reused partner ribbon. */
.svc-proof__stats { display: flex; flex-wrap: wrap; justify-content: center; gap: 20px; }
.svc-proof__stat { flex: 1 1 200px; max-width: 300px; text-align: center; padding: 30px 20px; border-radius: var(--r-md); border: 1px solid rgba(127,217,196,0.14); background: linear-gradient(160deg, rgba(255,255,255,0.03) 0%, rgba(255,255,255,0) 100%); }
.svc-proof__num { display: block; font-size: 56px; font-weight: 900; letter-spacing: -0.03em; color: #8fe3cf; line-height: 1; }
.svc-proof__label { display: block; margin-top: 10px; font-family: 'IBM Plex Mono', monospace; font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--faint); }
.svc-proof__ribbon { margin-top: 46px; }

/* FAQ — native disclosure, styled. */
.svc-faq-list { max-width: 860px; margin: 0 auto; display: flex; flex-direction: column; }
.svc-faq-item { border-top: 1px solid rgba(127,217,196,0.14); }
.svc-faq-item:last-child { border-bottom: 1px solid rgba(127,217,196,0.14); }
.svc-faq-item__q { cursor: pointer; list-style: none; display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 24px 4px; font-size: clamp(17px, 1.6vw, 21px); font-weight: 700; color: var(--fg); }
.svc-faq-item__q::-webkit-details-marker { display: none; }
.svc-faq-item__icon { flex: none; font-family: 'IBM Plex Mono', monospace; font-size: 24px; font-weight: 400; color: #8fe3cf; transition: transform .3s ease; }
.svc-faq-item[open] .svc-faq-item__icon { transform: rotate(45deg); }
.svc-faq-item__a { padding: 0 4px 26px; max-width: 720px; font-size: 16px; line-height: 1.65; color: var(--muted); }

.svc-cta__sub { max-width: 560px; margin: 0 auto; font-size: 17px; line-height: 1.55; color: var(--body); }

/* --- Services page: desktop — the three doors fill the screen so the page opens
   as an unmissable "make your choice" moment: a call to choice, almost a game.
   The doors drop their fixed 4/3 ratio and grow tall to claim the viewport. --- */
@media (min-width: 861px) {
	.svc-hero { min-height: calc(100dvh - 76px); padding-top: 40px; padding-bottom: 44px; justify-content: center; }
	.svc-hero__inner { gap: 14px; }
	.svc-chooser { gap: 22px; }
	.svc-choice { aspect-ratio: auto; height: clamp(380px, 54vh, 640px); }
	.svc-choice__name { font-size: clamp(23px, 2.1vw, 32px); }
	.svc-choice__bar { padding: clamp(24px, 2.4vw, 40px) clamp(24px, 2.4vw, 40px); }
	.svc-choice__icon svg { width: clamp(72px, 6.5vw, 104px); height: clamp(72px, 6.5vw, 104px); }
}
/* --- Services page: tablet --- */
@media (max-width: 980px) {
	.svc-offer-grid { grid-template-columns: repeat(2, 1fr); }
	.svc-process-grid { grid-template-columns: repeat(2, 1fr); }
	.svc-package-grid { grid-template-columns: 1fr; max-width: 520px; margin: 0 auto; }
}
/* --- Services page: phone --- */
@media (max-width: 620px) {
	.svc-hero { min-height: auto; }
	.svc-offer-grid { grid-template-columns: 1fr; }
	.svc-offer-card--featured { grid-column: auto; }
	.svc-process-grid { grid-template-columns: 1fr; }
	.svc-hero__ctas { flex-direction: column; width: 100%; max-width: 340px; }
	.svc-hero__ctas .btn { width: 100%; }
	/* Phone: stack the three doors as short full-width banners — three cramped
	   squares side-by-side read as clutter on a narrow screen. */
	.svc-chooser { gap: 14px; }
	.svc-chooser__grid { grid-template-columns: 1fr; gap: 12px; }
	.svc-choice { aspect-ratio: 5 / 2; border-radius: var(--r-sm); }
	.svc-choice__icon svg { width: 40px; height: 40px; }
	.svc-choice__bar { padding: 12px 16px; }
	.svc-choice__name { font-size: clamp(15px, 4.4vw, 19px); }
	.svc-choice__arrow { display: none; }
}

/* =========================================================================
   Motion — Cadence styleguide (§04). Named spring easing tokens + the
   reveal-on-scroll classes. The reveal classes are ONLY ever added by
   assets/js/motion.js, so a no-JS visitor sees everything at full opacity;
   reduced-motion hard-stops all of it below.
   ========================================================================= */
:root {
	--ease-slow: cubic-bezier(0.2, 1.7, 0.3, 1);    /* sections, images — heavy, one soft overshoot */
	--ease-bouncy: cubic-bezier(0.16, 2.4, 0.3, 1); /* hover, cards, nav pills — the loose spring */
	--ease-fast: cubic-bezier(0.3, 1.5, 0.4, 1);    /* press, confirm — short and tight */

	/* ---- Shape (Cadence §05) — "vormen zijn nooit symmetrisch; één hoek is
	   altijd zachter". The soft corner is bottom-right, scaled by element size,
	   so cards/panels/fields all repeat the same M3-Expressive gesture. ---- */
	--r-hero: 28px 28px 96px 28px;   /* the big statement cards (CV detail) */
	--r-panel: 28px 28px 64px 28px;  /* service/contact panels, large surfaces */
	--r-card: 22px 22px 52px 22px;   /* project + offer cards */
	--r-md: 18px 18px 40px 18px;     /* mid blocks, embeds, collage tiles */
	--r-sm: 14px 14px 30px 14px;     /* small cells, chips, meta */
	--r-field: 12px 12px 26px 12px;  /* inputs + textareas */
}
.will-reveal {
	opacity: 0;
	transform: translateY(34px) scale(0.985);
	transition: opacity 0.44s cubic-bezier(0.2, 0.9, 0.3, 1), transform 0.62s var(--ease-slow);
}
.will-reveal.is-revealed { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
	.will-reveal { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* =========================================================================
   Fixes + Cadence adoption round 3
   ========================================================================= */

/* --- `hidden` must win over the layout display of these blocks. --------------
   .contact-form and .contact-success are display:flex, and an author-stylesheet
   class beats the UA sheet's [hidden]{display:none} — so the success panel was
   ALWAYS visible and the form never actually hid. Restore the attribute's
   meaning explicitly. */
[hidden] { display: none !important; }

/* --- Theme switch motion (Cadence §04) -------------------------------------
   The light/dark change was instant. Give the big surfaces a cross-fade so the
   switch reads as one deliberate move rather than a hard cut. Only colour
   properties transition — no layout, no transform, so nothing reflows. */
body, .emre-app, .site-scroll, .section, .site-nav,
.project-card__frame, .service-card, .contact-panel, .cv-detail,
.intent, .domain-tile, .form-field input, .form-field select, .form-field textarea {
	transition-property: background-color, background-image, color, border-color, box-shadow;
	/* Slow enough to watch. At .5s the switch was over before the eye had found
	   it, which is why it kept reading as an instant repaint rather than as a
	   tube changing state. Eased so it leaves quickly and arrives gently. */
	transition-duration: 1.1s;
	transition-timing-function: cubic-bezier(.32,.72,.24,1);
}
/* Never let the theme cross-fade override the springs on interactive parts —
   those re-declare their own transition above, so restate the composite here. */
.btn {
	transition: transform .4s var(--ease-bouncy), box-shadow .4s var(--ease-bouncy),
		background .5s ease, color .5s ease, border-color .5s ease;
}
.project-card__frame { transition: transform .45s var(--ease-bouncy), box-shadow .45s var(--ease-bouncy), background-color .5s ease, border-color .5s ease; }
.intent { transition: transform .35s var(--ease-bouncy), background-color .5s ease, border-color .5s ease, box-shadow .5s ease; }

@media (prefers-reduced-motion: reduce) {
	body, .emre-app, .site-scroll, .section, .site-nav, .btn,
	.project-card__frame, .service-card, .contact-panel, .cv-detail,
	.intent, .domain-tile, .form-field input, .form-field select, .form-field textarea {
		transition-duration: .01ms !important;
	}
}

/* --- Book a call panel (Setmore) --------------------------------------------
   Replaces the old full-height iframe. Same visual weight as the message panel
   so the two contact columns balance. */
.contact-book {
	display: flex; flex-direction: column; gap: 16px;
	background: var(--card); border: 1px solid rgba(127,217,196,0.18);
	border-radius: var(--r-panel); padding: 40px;
	box-shadow: 0 22px 60px rgba(0,0,0,0.5);
}
:root[data-theme="light"] .contact-book {
	border-color: var(--border-hair);
	box-shadow: 0 1px 2px rgba(40,50,44,0.04), 0 14px 34px rgba(40,50,44,0.09);
}
.contact-book__title { font-size: clamp(22px, 2.2vw, 30px); font-weight: 800; letter-spacing: -0.01em; color: var(--fg); }
.contact-book__text { font-size: 15.5px; line-height: 1.6; color: var(--muted); }
:root[data-theme="light"] /* Setmore injects its own inline styles on the button; our .btn rules need to
   hold, so restate the essentials at a matching specificity. */
.contact-book .anywhere-book-now-button.btn {
	margin-top: 6px; width: 100%; font-family: 'Archivo', sans-serif;
	border-radius: 999px; cursor: pointer;
}

/* =========================================================================
   Accessibility opt-ins — driven by the Display panel (classes set on <html>
   by main.js applyA11y()). These sit alongside the OS-level media queries:
   a visitor can opt in here even when their system preference says otherwise.
   ========================================================================= */

/* --- Reduce motion: same contract as prefers-reduced-motion ---------------- */
.a11y-reduce-motion *,
.a11y-reduce-motion *::before,
.a11y-reduce-motion *::after {
	animation-duration: .01ms !important;
	animation-iteration-count: 1 !important;
	transition-duration: .01ms !important;
	scroll-behavior: auto !important;
}
/* Reveals must never leave content hidden when motion is off. */
.a11y-reduce-motion .will-reveal { opacity: 1 !important; transform: none !important; }
/* Ambient loops (marquee, flicker, scan sweep, blinking cursor) simply stop. */
.a11y-reduce-motion .ribbon__track,
.a11y-reduce-motion .hero__scan-sweep,
.a11y-reduce-motion .hero__cursor-blink,
.a11y-reduce-motion .hero__hud-grid { animation: none !important; }

/* --- Higher contrast ------------------------------------------------------
   Lifts text and borders and pulls the CRT overlays back, without changing
   layout or the brand hues. */
.a11y-high-contrast {
	--fg: #ffffff;
	--body: #eaf4ef;
	--muted: #dceae3;
	--faint: #b9cfc4;
	--border-hair: rgba(180,230,214,0.5);
}
.a11y-high-contrast[data-theme="light"] {
	--fg: #06120d;
	--body: #17241d;
	--muted: #1d2b23;
	--faint: #33443a;
	--border-hair: #7d8b81;
}
/* Pull the decorative screen layers back so they can't wash out text. */
.a11y-high-contrast .crt-lines,
.a11y-high-contrast .crt-vignette,
.a11y-high-contrast .crt-gloss,
.a11y-high-contrast .crt-fringe { opacity: .12 !important; }
/* The bulge is a shadow, not a fill — opacity can't reach it. */
.a11y-high-contrast .crt-bulge { box-shadow: none !important; }
.a11y-high-contrast .hero__hud-grid,
.a11y-high-contrast .case-hero__grid { opacity: .35; }
/* Give interactive edges a real outline rather than a hairline tint. */
.a11y-high-contrast .btn--secondary,
.a11y-high-contrast .btn--outline,
.a11y-high-contrast .site-nav__link,
.a11y-high-contrast .form-field input,
.a11y-high-contrast .form-field select,
.a11y-high-contrast .form-field textarea,
.a11y-high-contrast .project-card__frame,
.a11y-high-contrast .service-card,
.a11y-high-contrast .contact-panel,
.a11y-high-contrast .contact-book { border-color: var(--border-hair) !important; }
.a11y-high-contrast :focus-visible { outline: 3px solid #8fe3cf; outline-offset: 3px; }

/* Small helper text under a control in the Display panel. */
.emre-ctrl__hint { margin: -4px 0 12px; font-size: 12px; line-height: 1.45; color: var(--faint); }
/* Sits in the same row position as the switches, but it opens something rather
   than toggling something — so it reads as a link, not as a control that is
   already in one of two states. */
.emre-ctrl__link {
	font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.12em;
	padding: 6px 14px; border-radius: 999px; cursor: pointer;
	border: 1px solid var(--border-hair); background: transparent; color: var(--fg);
	transition: background .25s ease, border-color .25s ease;
}
.emre-ctrl__link:hover { border-color: rgba(127,217,196,0.6); background: rgba(127,217,196,0.1); }

/* --- "OR" rail between the two contact routes ------------------------------
   A labelled separator, not decoration: it tells the visitor these are two
   alternatives. Vertical rail on desktop, horizontal band once the columns
   stack. aria-hidden because the heading of each panel already names the
   choice for assistive tech. */
.contact-or {
	display: flex; flex-direction: column; align-items: center; gap: 16px;
	align-self: stretch; padding: 8px 0;
}
.contact-or::before, .contact-or::after {
	content: ""; flex: 1; width: 1px; min-height: 24px;
	background: linear-gradient(180deg, transparent, rgba(127,217,196,0.34), transparent);
}
.contact-or span {
	font-family: 'IBM Plex Mono', monospace; font-size: 11px; letter-spacing: 0.24em;
	color: var(--faint); flex: none;
	width: 44px; height: 44px; border-radius: 999px;
	display: flex; align-items: center; justify-content: center;
	border: 1px solid rgba(127,217,196,0.22);
	background: color-mix(in srgb, var(--body-bg) 60%, transparent);
}
:root[data-theme="light"] .contact-or::before,
:root[data-theme="light"] .contact-or::after {
	background: linear-gradient(180deg, transparent, rgba(31,143,118,0.3), transparent);
}
:root[data-theme="light"] .contact-or span { border-color: rgba(31,143,118,0.28); }

/* Stacked layout: the rail turns into a horizontal band between the panels. */
@media (max-width: 980px) {
	.contact-grid--split { grid-template-columns: 1fr; gap: 28px; }
	.contact-or { flex-direction: row; width: 100%; padding: 0; gap: 18px; }
	.contact-or::before, .contact-or::after {
		width: auto; height: 1px; min-height: 0; flex: 1;
		background: linear-gradient(90deg, transparent, rgba(127,217,196,0.34), transparent);
	}
	:root[data-theme="light"] .contact-or::before,
	:root[data-theme="light"] .contact-or::after {
		background: linear-gradient(90deg, transparent, rgba(31,143,118,0.3), transparent);
	}
}

/* --- Honeypot traps --------------------------------------------------------
   Must be invisible AND unreachable: off-screen (not display:none, which some
   bots detect and skip), zero tab stops, hidden from assistive tech via the
   aria-hidden on the wrapper. A human can never put a value in these. */
.contact-form__trap {
	position: absolute !important;
	left: -9999px !important;
	top: auto !important;
	width: 1px !important;
	height: 1px !important;
	overflow: hidden !important;
}


/* =========================================================================
   Anchor landing + touch feedback (v67)
   ========================================================================= */

/* --- Anchors -----------------------------------------------------------
   Every in-page target reserves the sticky nav's height plus a little air, so
   a section never lands underneath the bar. Doing it in CSS (rather than only
   in the JS scroll maths) also fixes arriving directly at emresahin.nl/#services
   and back/forward navigation, which never ran that JS at all.
   --nav-h is kept up to date by main.js; the fallback covers first paint. */
:root { --nav-h: 71px; }
section[id], .section[id], [id].case-section { scroll-margin-top: calc(var(--nav-h) + 16px); }

/* --- Touch feedback ----------------------------------------------------
   A touch device gets no :hover, and the block above deliberately strips the
   hover transforms so they can't stick after a tap. That left phones with NO
   feedback at all. Press states fill the gap: they fire on touch, and because
   they're :active they can never get stuck. */
@media (hover: none) {
	.btn:active,
	.site-nav__link:active,
	.intent:active,
	.hero-theme__btn:active,
	.domain-tile:active,
	.svc-choice:active,
	.emre-display-toggle:active,
	.contact-book .anywhere-book-now-button:active {
		transform: scale(0.965) !important;
		transition: transform .12s var(--ease-fast) !important;
	}
	.project-card:active .project-card__frame,
	.service-card:active,
	.svc-offer-card:active,
	.case-prevnext__card:active {
		transform: scale(0.985) !important;
		transition: transform .12s var(--ease-fast) !important;
	}
	/* The accent border confirms the target that was hit, not just the shrink. */
	.intent:active { border-color: var(--intent-accent) !important; }
	.project-card:active .project-card__frame { border-color: var(--project-accent, #7fd9c4) !important; }
}

/* Kill the grey flash iOS/Android paint over tapped elements — the press
   states above are the intended feedback. */
.btn, .site-nav__link, .intent, .hero-theme__btn, .domain-tile,
.svc-choice, .project-card, .service-card, .svc-offer-card,
.emre-display-toggle, .anywhere-book-now-button {
	-webkit-tap-highlight-color: transparent;
}

@media (prefers-reduced-motion: reduce) {
	@media (hover: none) {
		.btn:active, .site-nav__link:active, .intent:active, .hero-theme__btn:active,
		.domain-tile:active, .svc-choice:active, .project-card:active .project-card__frame,
		.service-card:active, .svc-offer-card:active { transform: none !important; }
	}
}

/* --- Selected-service confirmation chip -------------------------------------
   Shown above the message form when a visitor arrives from a specific package
   on /services. It acknowledges the click and shows what will be discussed. */
.contact-context {
	display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
	margin: 0 0 20px; padding: 14px 18px;
	border: 1px solid rgba(127,217,196,0.34); border-radius: 16px 16px 30px 16px;
	background: rgba(127,217,196,0.08);
}
.contact-context__label {
	font-family: 'IBM Plex Mono', monospace; font-size: 10.5px; letter-spacing: 0.18em;
	text-transform: uppercase; color: var(--faint); flex: none;
}
.contact-context__value { font-size: 15px; font-weight: 700; color: var(--fg); flex: 1 1 auto; min-width: 0; }
.contact-context__clear {
	flex: none; width: 30px; height: 30px; border-radius: 999px; cursor: pointer; font-size: 16px; line-height: 1;
	background: transparent; border: 1px solid rgba(127,217,196,0.28); color: var(--body);
	transition: background .25s ease, color .25s ease;
}
.contact-context__clear:hover { background: rgba(127,217,196,0.18); color: var(--fg); }
:root[data-theme="light"] .contact-context { border-color: rgba(31,143,118,0.3); background: rgba(31,143,118,0.07); }
:root[data-theme="light"] .contact-context__clear { border-color: rgba(31,143,118,0.28); }

/* =========================================================================
   Services page — readability pass (Cadence §03 type / §08 rhythm)
   The page reads as one long wall: 52px section titles drop straight to 22px
   subheads, prose runs the full container width, and the outcome line is small
   italic low-contrast text. Fixes below are hierarchy and measure only — no
   layout or component changes, so nothing moves position.
   ========================================================================= */

/* Prose gets a real measure. Beyond ~70 characters the eye loses the line. */
.svc-hero__lede, .svc-belief__statement, .svc-belief__turn,
.svc-offer-card__pitch, .svc-cta__sub { max-width: 68ch; text-wrap: pretty; }

/* Subheads ("Packages", "Monthly retainers") become a clear third level: a
   mono eyebrow rule above, more air before, less after — so each block reads
   as belonging to the heading rather than floating between two. */
.svc-subhead {
	margin: 72px 0 24px;
	padding-top: 20px;
	border-top: 1px solid var(--border-hair, rgba(127,217,196,0.16));
	font-size: clamp(24px, 2.2vw, 30px);
	font-weight: 800;
	letter-spacing: -0.015em;
	color: var(--fg);
}
.svc-subhead:first-of-type { margin-top: 56px; }

/* Cards need room to read as separate objects, not a wall of panels. */
.svc-package-grid, .svc-offer-grid { gap: 24px; }
.svc-package__points { margin: 18px 0 22px; gap: 12px; }
.svc-package__points li { font-size: 15.5px; line-height: 1.55; }

/* The outcome line is the payoff of each card — it was the least readable
   thing on it. Upright, larger, and accent-coloured instead of grey italic. */
.svc-package__result {
	padding-top: 18px;
	font-size: 14.5px;
	line-height: 1.55;
	font-style: normal;
	font-weight: 600;
	color: var(--fg);
}
.svc-package__result::before {
	content: "→ ";
	color: #8fe3cf;
	font-weight: 700;
}
:root[data-theme="light"] .svc-package__result::before { color: #1f8f76; }

/* Section headings on this page get the same air as the homepage. */
.svc-offer .section-head { margin-bottom: 40px; }

@media (max-width: 860px) {
	.svc-subhead { margin: 48px 0 20px; padding-top: 16px; }
	.svc-package-grid, .svc-offer-grid { gap: 18px; }
}

/* =========================================================================
   Theme switch — motion (v68)
   The pill only swapped colour, so the change read as a repaint rather than a
   move. The active background is now its own layer that springs in from the
   side you pressed, and the glyph rotates as it takes over. Colour still
   carries the state; the motion just makes the switch feel operated.
   ========================================================================= */
.hero-theme__btn { position: relative; isolation: isolate; overflow: hidden; }
.hero-theme__btn.is-active { background: transparent !important; box-shadow: none !important; }
.hero-theme__btn::before {
	content: ""; position: absolute; inset: 0; z-index: -1; border-radius: 11px 11px 20px 11px;
	background: linear-gradient(135deg, #8fe3cf, #6cc9b2);
	box-shadow: 0 4px 14px rgba(127,217,196,0.32);
	opacity: 0; transform: scale(0.72);
	transition: opacity .22s ease, transform .42s var(--ease-bouncy);
}
:root[data-theme="light"] .hero-theme__btn::before {
	background: linear-gradient(135deg, #2f9e83, #1f8f76);
	box-shadow: 0 4px 14px rgba(31,143,118,0.28);
}
.hero-theme__btn.is-active::before { opacity: 1; transform: scale(1); }
/* Pressing the inactive half nudges it toward the active one first. */
.hero-theme__btn:not(.is-active):active { transform: scale(0.94); }
.hero-theme__btn { transition: color .25s ease, transform .3s var(--ease-fast); }

.hero-theme__glyph {
	display: inline-flex;
	transition: transform .5s var(--ease-bouncy), opacity .3s ease;
}
.hero-theme__btn.is-active .hero-theme__glyph { transform: rotate(0deg) scale(1.06); }
.hero-theme__btn:not(.is-active) .hero-theme__glyph { transform: rotate(-35deg) scale(0.9); opacity: 0.75; }

@media (prefers-reduced-motion: reduce) {
	.hero-theme__btn::before, .hero-theme__glyph { transition-duration: .01ms !important; }
	.hero-theme__btn:not(.is-active) .hero-theme__glyph { transform: none; }
}
.a11y-reduce-motion .hero-theme__btn::before,
.a11y-reduce-motion .hero-theme__glyph { transition-duration: .01ms !important; }

/* =========================================================================
   Homepage services — fit the section, and its CTA, in one screen (v68)
   Clicking SERVICES landed on the section but the "See all services in detail"
   button sat just past the fold, so the anchor felt broken. The section was
   simply taller than the viewport: three columns each with a 16:9 image, three
   tier cards, and generous padding. Trimmed below — the image keeps its role
   as a visual anchor but stops being the tallest thing in the column.
   ========================================================================= */
@media (min-width: 861px) {
	.svc-col__thumb { aspect-ratio: 21 / 9; }
	.svc-col { padding: 18px; gap: 11px; }
	.svc-col__tiers { gap: 8px; }
	.svc-tier { padding: 11px 14px; gap: 3px; }
	.svc-matrix { gap: 16px 16px; }
	.section--services .section-head { margin-bottom: 24px; }
	.services-cta { margin-top: 18px; }
}
/* Very short viewports (laptops at 768/800px tall) need one more step. */
@media (min-width: 861px) and (max-height: 900px) {
	.svc-col__thumb { aspect-ratio: 24 / 9; }
	.svc-col__line { display: none; }
	.section--services { padding-top: 48px; padding-bottom: 48px; }
}
