/* Self-hosted Inter (SIL Open Font License — see assets/fonts/inter/LICENSE.txt).
   One variable file covers the whole weight range used site-wide, so this
   is the only font file the site ever requests — no Google Fonts CDN call,
   no per-weight static files. font-display:swap avoids a blank-text flash;
   the system-font fallback stack (declared in theme.json) is what actually
   renders during that brief swap window. */
@font-face {
	font-family: "Inter";
	src: url("../fonts/inter/Inter-Variable-Latin.woff2") format("woff2-variations"), url("../fonts/inter/Inter-Variable-Latin.woff2") format("woff2");
	font-weight: 100 900;
	font-style: normal;
	font-display: swap;
}

/* =========================================================
   Jhilik Portfolio — component & visual system
   Correction 01D — content-driven hero, modern sans display,
   rebuilt sections. Loaded on the front end AND in the editor.
   ---------------------------------------------------------
   This file fully REPLACES the 01C version. There is no
   viewport-height hero, no aspect-locked oversized stage, and
   no duplicated section-spacing rules — spacing is owned here.
   ---------------------------------------------------------
    1.  Tokens
    2.  Primitives (wrapper, eyebrow, section rhythm, lead)
    3.  Header
    4.  Hero — layout (content driven)
    5.  Hero — studio scene
    6.  Hero — task bubbles
    7.  Stats
    8.  Meet My Agents
    9.  Research — publication cards
   10.  Portfolio — project windows
   11.  Tools — featured + secondary
   12.  Videos
   13.  Gallery — mosaic
   14.  About — visual timeline
   15.  Contact — midnight closing scene
   16.  Buttons
   17.  Motion
   18.  Responsive
   19.  Editor adjustments
   ========================================================= */

/* 1. Tokens ---------------------------------------------------- */

/* Canonical global design tokens. One source of truth for layout width,
   rhythm and surface color across every template — new work should read
   these, not invent a fresh px/ch value per page (that's how the site
   ended up feeling like several different designs). */
:root {
	/* Layout */
	--content-width: 1220px;         /* general page content */
	--content-width-narrow: 760px;   /* reading / article measure */
	--content-width-cv: 960px;       /* CV */
	--section-space: clamp(2.75rem, 4.5vw, 4rem);
	--card-gap: 1.5rem;

	/* Shape & surface. Was 24/14/28/36 — the two most-used tiers (default,
	   sm) sat on opposite sides of the site's 16-18px card-radius target
	   instead of inside it; nudged both in, and scaled -lg/-xl down
	   proportionally so bigger panels still read as a visibly larger step,
	   not a separate, oversized system. */
	--radius: 17px;
	--radius-sm: 16px;
	--radius-lg: 22px;
	--radius-xl: 28px;
	--surface: var(--wp--preset--color--canvas);
	--surface-raised: #ffffff;
	--text: var(--wp--preset--color--contrast);
	/* A first-class Global Styles swatch (Settings > Styles > Colors) —
	   its default value matches the color-mix() this replaced, so this is
	   a no-visual-change swap that makes "muted text" directly editable
	   from the backend instead of only ever derived from Ink. */
	--muted: var(--wp--preset--color--muted);
	--border: rgba(21, 27, 51, 0.09);
	--shadow: 0 1px 2px rgba(21, 27, 51, 0.04), 0 12px 34px -16px rgba(21, 27, 51, 0.20);
	--shadow-md: 0 2px 8px rgba(21, 27, 51, 0.06), 0 28px 60px -24px rgba(21, 27, 51, 0.26);
	--shadow-lg: 0 3px 14px rgba(21, 27, 51, 0.07), 0 50px 100px -34px rgba(21, 27, 51, 0.34);

	/* Legacy aliases — kept so the rest of this file (written against the
	   old `--jh-*` names) keeps working untouched; new rules should prefer
	   the canonical names above. */
	--jh-radius: var(--radius);
	--jh-radius-sm: var(--radius-sm);
	--jh-radius-lg: var(--radius-lg);
	--jh-radius-xl: var(--radius-xl);
	--jh-line: 1px solid var(--border);
	--jh-shadow-sm: var(--shadow);
	--jh-shadow-md: var(--shadow-md);
	--jh-shadow-lg: var(--shadow-lg);
	--jh-ink-soft: var(--muted);
	--jh-wrap: min(calc(100% - 2.5rem), var(--content-width));

	/* Semantic status tokens — the same success/warning/danger values this
	   file already used ad hoc (case-study deltas, capability marks)
	   before this pass, now named once instead of repeated as raw hex. */
	--jh-success: #1b8a5a;
	--jh-warning: #d9a441;
	--jh-warning-tint: #F5DE9A;
	--jh-danger-text: #8a3b4a;
}

/* 2. Primitives --------------------------------------------- */

.jhilik-eyebrow {
	display: inline-block;
	margin: 0 0 1rem;
	padding: 0.4rem 0.85rem;
	font-family: var(--wp--preset--font-family--sans);
	font-size: 0.78rem;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--wp--preset--color--primary);
	background: color-mix(in srgb, var(--wp--preset--color--secondary) 34%, #ffffff);
	border-radius: 999px;
}

/* Every top-level homepage section gets its rhythm here — not inline.
   scroll-margin-top keeps every anchored section (#agents, #research,
   #portfolio, #tools, #journey, #videos, #about, #contact — see the
   hero's "Explore My Work" / "Meet My AI Agents" links and the header's
   Explore panel) clear of the fixed header when the browser jumps to it,
   instead of landing the heading right under/behind it. */
.jhilik-section {
	padding-block: clamp(2.75rem, 4.5vw, 4rem);
	scroll-margin-top: var(--jh-header-clearance);
}

.jhilik-section__head {
	max-width: 44ch;
	margin-bottom: clamp(1.75rem, 3vw, 2.5rem);
}

.jhilik-section__head h2 {
	margin: 0 0 0.75rem;
}

.jhilik-lead {
	max-width: 54ch;
	font-size: 1.1rem;
	color: var(--jh-ink-soft);
	/* WordPress's own "constrained layout" CSS centers any direct child
	   that's narrower than its container (margin-inline:auto !important) —
	   correct for a full-width block, wrong here: this is meant to read as
	   left-aligned body copy under a left-aligned heading, not a centered
	   hero blurb. Without this override it only LOOKED aligned in
	   sections that happen to nest it inside an even-narrower wrapper
	   (.jhilik-section__head); anywhere it sits directly in a wider
	   constrained group (e.g. the Research Bulletin / Research-in-Action
	   intros), it drifted to the middle while its heading stayed put. */
	margin-left: 0 !important;
	margin-right: 0 !important;
}

/* Full-bleed band with a tinted background */
.jhilik-band--cream {
	background: linear-gradient(180deg, color-mix(in srgb, var(--wp--preset--color--base) 70%, #ffffff), var(--wp--preset--color--canvas));
	border-block: var(--jh-line);
}

/* 3. Header — floating over the page, Google-Labs-inspired ---------
   Not a pill/capsule: at rest this is fully transparent with no visible
   box at all, so the logo/nav/CTA simply float over the hero. A soft,
   restrained translucent-blur backing only appears once the page has
   scrolled (`.is-scrolled`, toggled by labs.js), purely for readability
   over whatever content is now behind it — see initHeaderScroll(). */

.jhilik-site-header {
	/* `fixed`, not `sticky`: tested directly in-browser (scrolling to
	   several fixed offsets and reading getBoundingClientRect each time)
	   and `position: sticky` never actually held this element in place —
	   it scrolled away 1:1 with the page from the very first pixel, on
	   every ancestor-overflow configuration tried, while `fixed` held
	   correctly every time. `fixed` also happens to match the brief
	   better anyway ("float OVER the top content"): the header is out of
	   flow from the start, so the hero's own background/art can run
	   underneath it, rather than the page reserving flow space for a
	   header that then merely stays put once scrolled to. See the
	   `main { margin-top }` rule below, which restores the space this
	   removes from normal flow. */
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 100;
	padding-block: 1.35rem;
}

/* Compensates for .jhilik-site-header now being out of normal flow, using
   the real measured header height (--jh-header-clearance, kept in sync by
   labs.js's initHeaderClearance) instead of one flat guessed number for
   every page. `margin`, not `padding`, deliberately: several templates
   already set their own inline `padding-top` on <main> for internal
   rhythm, and inline styles would otherwise win the cascade over a
   stylesheet padding rule here, leaving those pages uncompensated. Margin
   stacks independently of that padding, so this applies everywhere
   without touching per-template values.

   The homepage is the one exception: its <main> keeps margin-top:0 (see
   `.home main` below) so the header can float transparently over the
   hero's own background, and the hero section itself carries the
   clearance instead — see `.jhilik-hero` padding-top. */
main {
	margin-top: var(--jh-header-clearance);
}

/* Homepage: let the header float over the hero's background all the way
   to the top of the page — the hero section supplies its own top
   clearance (see `.jhilik-hero`) instead of <main> pushing the whole
   page down. `.home` is WordPress's own standard body class for the
   site's front page, so this never depends on a numeric post/page ID. */
.home main {
	margin-top: 0;
}

.jhilik-site-header__bar {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	column-gap: 1.25rem;
	padding: 0.55rem 1.5rem;
	border-radius: 18px;
	background: transparent;
	border: 1px solid transparent;
	box-shadow: none;
	transition: background 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease, backdrop-filter 0.3s ease;
}

.jhilik-site-header.is-scrolled .jhilik-site-header__bar {
	background: color-mix(in srgb, var(--wp--preset--color--canvas) 80%, transparent);
	border-color: var(--border);
	box-shadow: var(--jh-shadow-sm);
	-webkit-backdrop-filter: blur(14px);
	backdrop-filter: blur(14px);
}

/* `backdrop-filter` on an ancestor makes it the containing block for any
   `position:fixed` descendant (same rule as `filter`/`will-change:transform`)
   — without this, the mobile panel's full-screen overlay gets trapped
   inside this bar instead of covering the viewport. Suspend the blur
   only while the panel is actually open and the bar is scrolled. */
.jhilik-site-header.is-scrolled .jhilik-site-header__bar:has(+ .jhilik-mobile-panel:not([hidden])) {
	-webkit-backdrop-filter: none;
	backdrop-filter: none;
}

.jhilik-site-header__brand {
	justify-self: start;
	min-width: 0;
	white-space: nowrap;
}

.jhilik-site-header__nav {
	justify-self: center;
}

.jhilik-site-header__actions {
	justify-self: end;
	gap: 0.75rem;
}

/* --- Primary nav: exactly three items (About / Explore / Stay connected) */

.jhilik-primary-nav {
	display: flex;
	align-items: center;
	gap: 2.25rem;
	font-size: 0.98rem;
	font-weight: 500;
}

.jhilik-primary-nav__link {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	padding: 0.3rem 0.1rem;
	background: none;
	border: none;
	font: inherit;
	font-weight: inherit;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	cursor: pointer;
	transition: color 0.18s ease;
}
.jhilik-primary-nav__link::after {
	content: "";
	position: absolute;
	left: 50%;
	right: 50%;
	bottom: -3px;
	height: 2px;
	border-radius: 2px;
	background: linear-gradient(90deg, var(--wp--preset--color--primary), var(--wp--preset--color--accent));
	transition: left 0.25s cubic-bezier(0.2, 0.8, 0.2, 1), right 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.jhilik-primary-nav__link:hover,
.jhilik-primary-nav__link:focus-visible {
	color: var(--wp--preset--color--primary);
}
.jhilik-primary-nav__link:hover::after,
.jhilik-primary-nav__link:focus-visible::after,
.jhilik-explore.is-open .jhilik-primary-nav__link::after {
	left: 0;
	right: 0;
}
.jhilik-primary-nav__link:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 3px;
}

/* --- Explore: disclosure trigger + floating grouped panel */

.jhilik-explore {
	position: relative;
}
.jhilik-explore__chevron {
	transition: transform 0.2s ease;
}
.jhilik-explore.is-open .jhilik-explore__chevron {
	transform: rotate(180deg);
}

.jhilik-explore__panel {
	position: absolute;
	top: calc(100% + 0.9rem);
	left: 50%;
	transform: translateX(-50%);
	display: flex;
	gap: 2rem;
	padding: 1.5rem 1.75rem;
	background: color-mix(in srgb, var(--wp--preset--color--canvas) 96%, #fff);
	border: var(--jh-line);
	border-radius: var(--jh-radius);
	box-shadow: var(--jh-shadow-md);
	white-space: nowrap;
	z-index: 10;
}
.jhilik-explore__panel[hidden] {
	display: none;
}
.jhilik-explore__group {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}
.jhilik-explore__group-label {
	margin: 0 0 0.15rem;
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--jh-ink-soft);
}
.jhilik-explore__group a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	font-size: 0.94rem;
	padding: 0.15rem 0;
	transition: color 0.18s ease;
}
.jhilik-explore__group a:hover,
.jhilik-explore__group a:focus-visible {
	color: var(--wp--preset--color--primary);
}

@media (prefers-reduced-motion: no-preference) {
	.jhilik-explore__panel {
		animation: jhilik-explore-panel-in 0.18s cubic-bezier(0.2, 0.8, 0.2, 1) both;
	}
}
@keyframes jhilik-explore-panel-in {
	from { opacity: 0; transform: translateX(-50%) translateY(-6px); }
	to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

/* --- Right side: social icon buttons + CTA */

.jhilik-social-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.25rem;
	height: 2.25rem;
	border-radius: 50%;
	border: var(--jh-line);
	background: transparent;
	color: var(--wp--preset--color--contrast);
	transition: background 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}
.jhilik-social-icon:hover {
	background: color-mix(in srgb, var(--wp--preset--color--secondary) 30%, #fff);
	border-color: color-mix(in srgb, var(--wp--preset--color--contrast) 25%, transparent);
}
@media (hover: hover) {
	.jhilik-social-icon:hover { transform: translateY(-2px); }
}
.jhilik-social-icon:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}

.jhilik-site-header__cta .wp-block-button__link {
	padding-block: 0.68rem;
	padding-inline: 1.35rem;
	white-space: nowrap;
	box-shadow: var(--jh-shadow-sm);
}
@media (max-width: 420px) {
	.jhilik-site-header__cta .wp-block-button__link {
		padding-inline: 1rem;
		font-size: 0.92rem;
	}
}

/* --- Mobile/tablet trigger + overlay panel (<=1024px) ------------------
   Below 1024px the three-item primary nav, Explore panel, and social/CTA
   cluster all hide in favour of a single compact trigger; opening it
   shows one floating rounded-card panel with the same destinations
   (About, the 8 Explore destinations, Stay connected, social icons) laid
   out as a simple stacked list — see initMobilePanel() in labs.js. */

.jhilik-mobile-trigger {
	display: none;
	align-items: center;
	justify-content: center;
	width: 2.75rem;
	height: 2.75rem;
	border-radius: 999px;
	background: color-mix(in srgb, var(--wp--preset--color--primary) 10%, #fff);
	border: var(--jh-line);
	color: var(--wp--preset--color--contrast);
	transition: transform 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;
}
.jhilik-mobile-trigger:hover {
	background: color-mix(in srgb, var(--wp--preset--color--primary) 18%, #fff);
	box-shadow: var(--jh-shadow-sm);
}
.jhilik-mobile-trigger:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}

@media (max-width: 1024px) {
	.jhilik-primary-nav,
	.jhilik-site-header__actions .jhilik-social-icon {
		display: none;
	}
	.jhilik-mobile-trigger {
		display: inline-flex;
	}
	/* .jhilik-site-header__bar has 4 real grid children in the markup
	   (brand, primary-nav, actions, mobile-trigger); hiding primary-nav
	   above still leaves 3 visible items (brand, actions/CTA, trigger),
	   so 3 explicit tracks are needed here — 2 silently overflowed the
	   trigger onto an implicit second row (verified visually at 1024px:
	   the trigger rendered on its own line under the brand instead of
	   inline with it). */
	.jhilik-site-header__bar {
		grid-template-columns: 1fr auto auto;
	}
}

/* Body-scroll lock while the mobile panel is open. Previously free from
   WordPress core's own navigation-block stylesheet; now that the header
   no longer includes a core/navigation block at all, core has no reason
   to enqueue that stylesheet on this page, so the rule is defined here
   directly rather than depending on it loading incidentally. */
html.has-modal-open {
	overflow: hidden;
}
/* Restrained backdrop behind the open panel — dims the page without a
   separate markup element, by hanging off the same has-modal-open class
   the panel's own open/close logic already toggles. Sits below both the
   header (z-index 100) and the panel (200) so it never covers either. */
@media (prefers-reduced-motion: no-preference) {
	html.has-modal-open::before { transition: opacity 0.2s ease; }
}
html.has-modal-open::before {
	content: "";
	position: fixed;
	inset: 0;
	background: rgba(16, 21, 42, 0.32);
	z-index: 150;
	pointer-events: none;
}

/* The panel is a child of .jhilik-site-header (itself position:fixed),
   so positioning it with top:100% instead of a hardcoded pixel offset
   automatically starts it right at the header's own bottom edge — at
   any breakpoint, at any header height — rather than the previous fixed
   full-screen overlay that sat on TOP of the header with a large empty
   padding reserved to visually clear it. Same reasoning gives max-height
   its "rest of the viewport" value for free: 100% here resolves to the
   header's height, so 100dvh minus it is exactly the space below it. */
.jhilik-mobile-panel {
	position: absolute;
	top: 100%;
	margin-top: 10px;
	right: 12px;
	left: 12px;
	max-height: calc(100dvh - 100% - 22px);
	z-index: 200;
	display: flex;
	flex-direction: column;
	gap: 1.5rem;
	padding: 1.5rem 1.5rem 1.75rem;
	background: color-mix(in srgb, var(--wp--preset--color--canvas) 98%, #fff);
	border: var(--jh-line);
	border-radius: var(--jh-radius-lg);
	box-shadow: var(--jh-shadow-lg);
	overflow-y: auto;
}
.jhilik-mobile-panel[hidden] {
	display: none;
}
.jhilik-mobile-panel__close {
	align-self: flex-end;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.75rem;
	height: 2.75rem;
	border-radius: 999px;
	background: color-mix(in srgb, var(--wp--preset--color--primary) 10%, #fff);
	border: var(--jh-line);
	color: var(--wp--preset--color--contrast);
	flex: none;
}
.jhilik-mobile-panel__close:hover {
	background: color-mix(in srgb, var(--wp--preset--color--primary) 18%, #fff);
}
.jhilik-mobile-panel__nav {
	display: flex;
	flex-direction: column;
}
.jhilik-mobile-panel__nav a {
	padding: 0.75rem 0.25rem;
	font-size: 1.15rem;
	font-weight: 500;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	border-bottom: var(--jh-line);
}
.jhilik-mobile-panel__nav a:first-child {
	font-weight: 600;
}
.jhilik-mobile-panel__label {
	margin: 1.1rem 0 0.15rem;
	font-size: 0.7rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--jh-ink-soft);
}
/* Separates "Stay connected" from the Explore links above it — the same
   gap an empty, NBSP-only `.jhilik-mobile-panel__label` used to create
   (a real heading has real text; this link has none, so it gets its own
   wrapper and margin instead of an empty non-breaking-space paragraph). */
.jhilik-mobile-panel__connect {
	margin-top: 1.1rem;
}
.jhilik-mobile-panel__social {
	display: flex;
	gap: 0.75rem;
}
@media (prefers-reduced-motion: no-preference) {
	.jhilik-mobile-panel:not([hidden]) {
		animation: jhilik-nav-panel-in 0.28s cubic-bezier(0.2, 0.8, 0.2, 1) both;
	}
}

/* 3b. Footer — rebuilt as a real 3-column CSS grid (not flex-wrap with
   `space-between`, which is what produced the old footer's huge uneven
   gaps: unequal-width items wrapped unpredictably as content changed).
   Grid guarantees equal thirds regardless of how long any column's
   content gets, at every breakpoint. Compact by design — see the
   `--section-space`-based padding on `.jhilik-site-footer` below; total
   footer height targets ~420-560px on desktop, not a near-full screen. */

.jhilik-footer__inner {
	position: relative;
	z-index: 1; /* sit above .jhilik-footer-deco */
	max-width: var(--content-width);
	margin-inline: auto;
	padding-inline: clamp(1.25rem, 3vw, 2rem);
}

.jhilik-footer__grid {
	display: grid;
	grid-template-columns: 1fr 0.85fr 1.35fr;
	gap: var(--card-gap) clamp(1.5rem, 4vw, 3.5rem);
	align-items: start;
}

.jhilik-footer__col { min-width: 0; }

.jhilik-footer__about { display: flex; flex-direction: column; gap: 0.5rem; }
.jhilik-footer__tagline { color: var(--muted); }

.jhilik-footer__heading {
	margin: 0 0 0.9rem;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	font-size: 0.875rem !important;
	color: var(--muted);
}

.jhilik-footer__about a,
.jhilik-footer__links a,
.jhilik-footer__social a { color: inherit; }

.jhilik-footer__links .wp-block-navigation {
	font-size: inherit;
	--wp--style--block-gap: 0.65rem;
}
.jhilik-footer__links .wp-block-navigation-item__content {
	padding: 0;
	color: inherit;
	opacity: 0.82;
}
.jhilik-footer__links .wp-block-navigation-item__content:hover,
.jhilik-footer__links .wp-block-navigation-item__content:focus-visible {
	opacity: 1;
	text-decoration: underline;
}

/* Social list — a clean 2-column grid, not the inline comma-wrapped row
   `.jhilik-social-links` renders by default elsewhere on the site. Every
   verified profile (there are 9) is real content, not decoration, so it
   can't just be trimmed to fit a height target — a 2-column grid is what
   keeps this column from single-handedly doubling the footer's height. */
.jhilik-footer__social .jhilik-social-links {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 0.6rem 1.25rem;
}
/* Bug fix: this column used to break real names mid-word ("WordPress.
   org profile", "ResearchGa\nte") because a 3-column grid inside an
   already-narrow footer column left no room for whole words, and
   word-break:break-word will happily split anywhere once a track is too
   tight. The real fix is width (2 columns instead of 3, plus a wider
   grid-column share above) — normal word-wrapping only ever breaks at
   spaces once there's enough room, so labels stay intact. */
.jhilik-footer__social .jhilik-social-links li { min-width: 0; }
.jhilik-footer__social .jhilik-social-links a {
	opacity: 0.82;
	overflow-wrap: normal;
	word-break: normal;
	white-space: normal;
}
.jhilik-footer__social .jhilik-social-links a:hover,
.jhilik-footer__social .jhilik-social-links a:focus-visible { opacity: 1; text-decoration: underline; }

.jhilik-footer__rule {
	margin: clamp(1.5rem, 3vw, 2rem) 0 0;
	border-color: rgba(42, 41, 38, 0.16);
}

.jhilik-footer__legal {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem 1.5rem;
	align-items: center;
	justify-content: space-between;
	padding-top: 1rem;
}
.jhilik-footer__copyright { margin: 0; color: var(--muted); }
.jhilik-footer__legal .wp-block-navigation {
	font-size: inherit;
	--wp--style--block-gap: 1.25rem;
}
.jhilik-footer__legal .wp-block-navigation-item__content {
	padding: 0.1rem 0;
	color: inherit;
	opacity: 0.82;
}
.jhilik-footer__legal .wp-block-navigation-item__content:hover,
.jhilik-footer__legal .wp-block-navigation-item__content:focus-visible {
	opacity: 1;
	text-decoration: underline;
}

/* Tablet — about column keeps its own row, explore/social share the
   second row as two even columns rather than each stretching full-width
   (that's what made the old footer so tall). */
@media (max-width: 860px) {
	.jhilik-footer__grid {
		grid-template-columns: 1fr 1fr;
		row-gap: clamp(1.75rem, 4vw, 2.25rem);
	}
	.jhilik-footer__about { grid-column: 1 / -1; }

	/* Explore — 2-column grid instead of one tall stacked list. Without
	   this, Explore's 7 stacked links stay the tallest thing in the
	   footer once About drops to its own full-width row, and the footer
	   creeps well past the compact-height target at tablet widths. */
	.jhilik-footer__links .wp-block-navigation .wp-block-navigation__container {
		display: grid !important;
		grid-template-columns: 1fr 1fr;
		gap: 0.55rem 1rem !important;
	}
	/* Same min-width:auto grid blowout guard as the social list above. */
	.jhilik-footer__links .wp-block-navigation-item {
		min-width: 0;
	}
	.jhilik-footer__links .wp-block-navigation-item__label {
		overflow-wrap: break-word;
		word-break: break-word;
	}
}

/* Mobile — brand block full width, then Explore and Elsewhere EACH full
   width in turn (not side-by-side sharing the width — nesting a 2-column
   grid inside a 2-column grid left only ~70px per column, too narrow for
   "ResearchGate"/"Portfolio" to read without breaking mid-word). Each
   section keeps its own internal 2-column grid, per spec. Legal row
   stacked and centered. Distinct from desktop positioning. */
@media (max-width: 599px) {
	.jhilik-footer__grid { grid-template-columns: 1fr; }
	.jhilik-footer__about { text-align: left; }

	/* Elsewhere — 2 columns at this width, not 3 (labels like "WordPress.org
	   profile" need the room), per spec. */
	.jhilik-footer__social .jhilik-social-links { grid-template-columns: 1fr 1fr; }

	.jhilik-footer__legal {
		flex-direction: column;
		align-items: flex-start;
		gap: 0.6rem;
	}
	.jhilik-footer__legal .wp-block-navigation {
		flex-wrap: wrap;
		gap: 0.5rem 1.1rem !important;
	}
}

/* 4. Hero — layout (content driven) ----------------------- */

.jhilik-hero {
	position: relative;
	overflow: hidden;
	/* Content-driven. No min-height, no viewport units, no flex centring.
	   The header floats over this section (see `.home main` above), so
	   its own top padding has to do the header-clearance work that <main>
	   normally does on every other page — real header height first, then
	   the same breathing room the section already had. */
	padding-top: calc(var(--jh-header-clearance) + clamp(2rem, 3vw, 3rem));
	padding-bottom: clamp(5.5rem, 8vw, 7.25rem);
	background:
		radial-gradient(760px 520px at 8% 2%, color-mix(in srgb, var(--wp--preset--color--secondary) 46%, transparent), transparent 62%),
		radial-gradient(820px 620px at 98% 12%, color-mix(in srgb, var(--wp--preset--color--accent) 40%, transparent), transparent 60%),
		radial-gradient(720px 560px at 74% 106%, color-mix(in srgb, var(--wp--preset--color--blush) 46%, transparent), transparent 58%),
		linear-gradient(180deg, var(--wp--preset--color--canvas), color-mix(in srgb, var(--wp--preset--color--secondary) 10%, var(--wp--preset--color--canvas)));
}

.jhilik-hero__cols {
	gap: clamp(2rem, 5vw, 4.5rem) !important;
	align-items: center;
}

.jhilik-hero__text {
	max-width: 600px;
}

.jhilik-hero h1 {
	/* Single fluid token (36px at 390px viewport -> 56px at 1440px),
	   replacing three separate hand-tuned clamp()s that used to disagree
	   with each other at the 981-1180px and <=980px breakpoints (one
	   even rendered 72px on a 1440px screen, well past any of them). */
	font-size: var(--wp--preset--font-size--display);
	line-height: 1.05;
	font-weight: 750;
	letter-spacing: -0.035em;
	text-wrap: balance;
	margin: 0 0 1.4rem;
}

.jhilik-hero__lead {
	max-width: 44ch;
	margin: 0 0 1.9rem;
	font-size: var(--wp--preset--font-size--lead);
	line-height: 1.6;
	color: var(--jh-ink-soft);
}

.jhilik-hero .wp-block-buttons {
	gap: 0.8rem 0.9rem;
}

/* small expertise line under the hero CTAs */
.jhilik-hero__meta {
	margin: 1.3rem 0 0;
	color: var(--jh-ink-soft);
	letter-spacing: 0.01em;
	opacity: 0.85;
}

/* 5. Hero — studio scene --------------------------------- */

.jhilik-stage {
	position: relative;
	width: 100%;
	max-width: 600px;
	margin-inline: auto;
	aspect-ratio: 1 / 0.9;
}

/* studio backdrop panel — gives the cast depth */
.jhilik-stage::before {
	content: "";
	position: absolute;
	inset: 5% 1% 3%;
	border-radius: 40px;
	background:
		radial-gradient(130% 85% at 50% 8%, rgba(255, 255, 255, 0.92), transparent 68%),
		linear-gradient(158deg, color-mix(in srgb, var(--wp--preset--color--secondary) 42%, #ffffff), color-mix(in srgb, var(--wp--preset--color--accent) 40%, #ffffff));
	box-shadow: var(--jh-shadow-lg);
}

/*
   CHARACTER ARTWORK — real animated WebP characters + a static PNG fallback,
   final delivered assets in assets/characters/ (jil-workspace.png,
   <name>-working.png, <name>-idle.webp, <name>-fly.webp). Wired by
   patterns/hero-characters.php. Nothing here is drawn in CSS/SVG, and no
   still image is transform-tricked into looking like it flaps — the wing
   motion is real, decoded from the WebP's own frames.

   - .jhilik-figure                positioned wrapper + JS flight transform target
   - .agent-character              inner wrapper — carries the idle body float
   -   .agent-character__fallback  static PNG — shown for prefers-reduced-motion
   -   .agent-character__idle      animated WebP — default pose, plays continuously
   -   .agent-character__flying    animated WebP — flight pose (opacity 0 -> 1 on .is-airborne)
   - .jil-character                Jhilik, single static image (she never flies)

   All slots: transparent background, object-fit: contain — no panels,
   no masks, no black rectangles behind the art.
*/

/* wrapper: transform is reserved for the JS flight engine (translate3d) */
.jhilik-figure {
	position: absolute;
	text-align: center;
	transform: translate3d(0, 0, 0);
	transform-origin: 50% 78%;
	will-change: transform;
	transition: transform 0.32s cubic-bezier(0.34, 1.4, 0.5, 1);
}

/* only the four dragons are interactive */
.jhilik-figure.is-flyer { cursor: pointer; }
.jhilik-figure.is-flyer:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 6px;
	border-radius: 12px;
}

/* ground shadow — softens + shrinks when airborne, strengthens on landing */
.jhilik-figure::before {
	content: "";
	position: absolute;
	z-index: -1;
	left: 22%;
	right: 22%;
	bottom: 1%;
	height: 9%;
	border-radius: 50%;
	background: radial-gradient(closest-side, rgba(21, 27, 51, 0.28), transparent);
	filter: blur(4px);
	transition: opacity 0.35s ease, transform 0.35s ease;
}

/* soft flight glow — only while airborne */
.jhilik-figure::after {
	content: "";
	position: absolute;
	z-index: -1;
	inset: 10% 6% 20%;
	border-radius: 50%;
	background: radial-gradient(closest-side, color-mix(in srgb, var(--fig-glow, #ffffff) 26%, transparent), transparent 72%);
	filter: blur(12px);
	opacity: 0;
	transition: opacity 0.4s ease;
}

.jhilik-figure.is-airborne::before {
	opacity: 0.16;
	transform: translate3d(0, 4px, 0) scale(0.58);
}
.jhilik-figure.is-airborne::after { opacity: 0.55; }

/* inner wrapper — idle float / wing-beat lives here so it never fights the
   flight transform on .jhilik-figure */
.agent-character {
	position: relative;
	display: block;
	width: 100%;
	transform-origin: 50% 90%;
}

.agent-character__fallback,
.agent-character__idle,
.agent-character__flying,
.jil-character {
	display: block;
	width: 100%;
	height: auto;
	background: transparent;
	object-fit: contain;
	object-position: center bottom;
	filter: drop-shadow(0 14px 20px rgba(21, 27, 51, 0.16));
}

/* static PNG — establishes the box; visible by default and whenever motion
   is reduced (see the reduced-motion swap below) or before CSS has loaded */
.agent-character__fallback {
	position: relative;
	opacity: 1;
}

.agent-character__idle,
.agent-character__flying {
	position: absolute;
	inset: 0;
	height: 100%;
	opacity: 0;
	transition: opacity 0.26s ease;
}

/* Motion allowed: the animated WebP idle pose replaces the static fallback
   and plays continuously — real in-frame motion, decoded from the file. */
@media (prefers-reduced-motion: no-preference) {
	.agent-character__fallback { opacity: 0; }
	.agent-character__idle { opacity: 1; }
}

/* idle <-> flying pose swap, driven by .is-airborne on the wrapper (added
   at takeoff, removed just before landing by the flight engine). Only ever
   reachable when motion is allowed, since flights never start otherwise. */
.jhilik-figure.is-airborne .agent-character__idle   { opacity: 0; }
.jhilik-figure.is-airborne .agent-character__flying { opacity: 1; }

/* Load-failure safety net: the inline onerror on each WebP (see
   hero-characters.php) adds this class if that file 404s or can't decode.
   Hide both WebP layers outright and force the static PNG on — no broken-
   image icon, regardless of motion preference or flight state. */
.agent-character.has-fallback .agent-character__fallback { opacity: 1; }
.agent-character.has-fallback .agent-character__idle,
.agent-character.has-fallback .agent-character__flying { display: none; }

.jil-character {
	position: relative;
	transform-origin: 50% 90%;
	filter: drop-shadow(0 20px 28px rgba(21, 27, 51, 0.18));
}

/* Motion V2's pointer-parallax target for Jhilik specifically (see the note
   in hero-characters.php) — a plain, non-positioned pass-through wrapper so
   V2's translate/rotate never touches .jhilik-figure--jhilik's own static
   centering translate. No layout role beyond matching its child's width. */
.jhilik-figure__parallax { display: block; width: 100%; }

.jhilik-figure__name {
	position: relative;
	display: inline-block;
	margin: -0.5rem 0 0;
	padding: 0.24rem 0.7rem;
	font-family: var(--wp--preset--font-family--sans);
	font-size: 0.82rem;
	font-weight: 600;
	line-height: 1.2;
	color: var(--wp--preset--color--contrast);
	background: var(--wp--preset--color--white);
	border-radius: 999px;
	box-shadow: var(--jh-shadow-sm);
	z-index: 6;
}

/* HOME POSITIONS — the animation origin for each character.
   Jhilik: centre / lower-centre. Deany: upper-left. Joyee: upper-right.
   Judy: lower-left. Arlo: lower-right. The flight system only ever adds a
   transform on top of these. */
.jhilik-figure--jhilik { left: 50%; top: 55%; translate: -50% -50%; width: 46%; z-index: 3; }
.jhilik-figure--deany  { top: -3%;    left: -4%;  width: 39%; z-index: 2; --fig-glow: var(--wp--preset--color--agent-deany); }
.jhilik-figure--joyee  { top: -1%;    right: -5%; width: 38%; z-index: 2; --fig-glow: var(--wp--preset--color--agent-joyee); }
.jhilik-figure--judy   { bottom: -3%; left: -6%;  width: 41%; z-index: 4; --fig-glow: var(--wp--preset--color--agent-judy); }
.jhilik-figure--arlo   { bottom: -1%; right: -6%; width: 40%; z-index: 4; --fig-glow: var(--wp--preset--color--agent-arlo); }

/* dragons in flight rise above Jhilik */
.jhilik-figure.is-airborne { z-index: 7; }

/* 6. Hero — task bubbles (few, larger, readable) --------- */

.jhilik-bubble {
	position: absolute;
	z-index: 5;
	pointer-events: none;            /* never intercept dragon hover / taps */
	padding: 0.6rem 0.9rem;
	font-size: 0.8125rem; /* 13px */
	font-weight: 600;
	line-height: 1.25;
	color: var(--wp--preset--color--contrast);
	background: var(--wp--preset--color--white);
	border-radius: 12px;
	box-shadow: var(--jh-shadow-md);
	white-space: nowrap;
	/* `translate` = idle drift (keyframe); `transform` = reaction scale.
	   Kept on separate properties so they compose. */
	transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.jhilik-bubble::before {
	content: "";
	display: inline-block;
	width: 0.5rem;
	height: 0.5rem;
	margin-right: 0.45rem;
	border-radius: 50%;
	background: var(--bubble-dot, var(--wp--preset--color--primary));
	vertical-align: middle;
}

/* a dragon is hovering nearby */
.jhilik-bubble.is-active {
	transform: scale(1.07);
	box-shadow: var(--jh-shadow-lg);
}

.jhilik-bubble--headlines { top: 15%; left: 0%;   --bubble-dot: var(--wp--preset--color--agent-deany); }
.jhilik-bubble--research  { bottom: 33%; left: -4%; --bubble-dot: var(--wp--preset--color--agent-judy); }
.jhilik-bubble--drafting  { top: 21%; right: -3%; --bubble-dot: var(--wp--preset--color--agent-joyee); }
.jhilik-bubble--data      { bottom: 22%; right: -2%; --bubble-dot: var(--wp--preset--color--agent-arlo); }
.jhilik-bubble--ready     { top: 4%; left: 41%;   --bubble-dot: var(--wp--preset--color--primary); }

/* 7. "Inside the studio, right now" — Live Lab section (replaces the old
   discovery carousel). Two-column grid: one large spotlight card (the real
   Insight article + its real image) beside a compact "currently building"
   activity panel listing real tools/research already published on this
   site. `.jhilik-activity-row` items highlight in sequence via labs.js
   (reduced-motion-safe, gated behind `.jhilik-js`) to read as "alive"
   without any flashing or fake data. */

.jhilik-live-lab__grid {
	display: grid;
	grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
	gap: clamp(1.5rem, 3vw, 2.5rem);
	/* Bug fix: stretch forced the activity card to match the spotlight
	   card's height, which is driven by its screenshot image — the
	   activity list (as few as 1-2 real items some days) then had a
	   large dead gap below it. Each card should size to its own real
	   content instead of borrowing height from an unrelated image. */
	align-items: start;
}

.jhilik-live-lab__spotlight {
	display: flex;
	flex-direction: column;
	background: var(--wp--preset--color--white);
	border: var(--jh-line);
	border-radius: var(--jh-radius-lg, 24px);
	box-shadow: var(--jh-shadow-sm);
	overflow: hidden;
	text-decoration: none;
	color: inherit;
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.jhilik-live-lab__spotlight:hover,
.jhilik-live-lab__spotlight:focus-visible {
	transform: translateY(-5px);
	box-shadow: var(--jh-shadow-md);
}
.jhilik-live-lab__spotlight:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 3px;
}
.jhilik-live-lab__spotlight-img {
	display: block;
	width: 100%;
	height: auto;
	max-height: 320px;
	object-fit: contain;
	background: color-mix(in srgb, var(--wp--preset--color--secondary) 16%, #ffffff);
}
.jhilik-live-lab__spotlight-body {
	padding: clamp(1.5rem, 2.5vw, 2.25rem);
	display: flex;
	flex-direction: column;
	flex: 1;
}
.jhilik-live-lab__spotlight-body .jhilik-status-pill { align-self: flex-start; margin-bottom: 0.9rem; }
.jhilik-live-lab__spotlight-body h3 {
	margin: 0 0 0.6rem;
	line-height: 1.35;
}
.jhilik-live-lab__spotlight-body p {
	margin: 0 0 1rem;
	color: var(--jh-ink-soft);
	font-size: 0.94rem;
	flex: 1;
}

.jhilik-live-lab__activity {
	display: flex;
	flex-direction: column;
	background: var(--wp--preset--color--white);
	border: var(--jh-line);
	border-radius: var(--jh-radius-lg, 24px);
	box-shadow: var(--jh-shadow-sm);
	padding: clamp(1.5rem, 2.5vw, 2rem);
}
.jhilik-live-lab__activity-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem;
	margin-bottom: 1rem;
}
.jhilik-live-lab__activity-head h3 {
	margin: 0;
	font-size: var(--wp--preset--font-size--subhead);
}

.jhilik-activity-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
}
.jhilik-activity-row a {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding: 0.7rem 0.6rem;
	border-radius: 12px;
	text-decoration: none;
	color: inherit;
	transition: background 0.2s ease;
}
.jhilik-activity-row a:hover,
.jhilik-activity-row a:focus-visible {
	background: color-mix(in srgb, var(--wp--preset--color--secondary) 20%, #ffffff);
}
.jhilik-activity-row a:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}
.jhilik-activity-row__dot {
	flex: none;
	width: 0.5rem;
	height: 0.5rem;
	border-radius: 50%;
	background: var(--wp--preset--color--tertiary);
}
.jhilik-activity-row__dot--beta { background: var(--wp--preset--color--accent); }
.jhilik-activity-row__dot--ongoing { background: var(--wp--preset--color--mint); }
.jhilik-activity-row__dot--experiment { background: var(--wp--preset--color--blush); }
.jhilik-activity-row__dot--development { background: var(--wp--preset--color--primary); }
@media (prefers-reduced-motion: no-preference) {
	/* The row labs.js currently emphasizes gets a gentle pulsing dot, so
	   "what I'm working on right now" reads as live, not just bold text. */
	.jhilik-activity-row.is-active .jhilik-activity-row__dot { animation: jhilik-pulse-soft 1.8s ease-in-out infinite; }
	.jhilik-live-lab__spotlight-img { animation: jhilik-float 8s ease-in-out infinite; }
}
.jhilik-activity-row__name {
	flex: 1;
	font-size: 0.92rem;
	font-weight: 500;
	line-height: 1.35;
}
.jhilik-activity-row__status {
	flex: none;
	font-size: 0.76rem;
	color: var(--jh-ink-soft);
	white-space: nowrap;
}

/* Sequential "alive" highlight — labs.js toggles this one row at a time.
   Motion-safe only; a no-JS or reduced-motion visitor sees a static list. */
@media (prefers-reduced-motion: no-preference) {
	.jhilik-js .jhilik-activity-row a {
		transition: background 0.5s ease, box-shadow 0.5s ease;
	}
	.jhilik-js .jhilik-activity-row.is-active a {
		background: color-mix(in srgb, var(--wp--preset--color--secondary) 28%, #ffffff);
		box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--wp--preset--color--primary) 30%, transparent);
	}
}

@media (max-width: 860px) {
	.jhilik-live-lab__grid {
		grid-template-columns: 1fr;
	}
}

/* 8. Meet My Agents ----------------------------------- */

.jhilik-agents-grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: clamp(1rem, 2vw, 1.6rem);
	/* Stretch (the default): descriptions here are all similar, short
	   single sentences, so equal-height cards read as intentional, not as
	   dead space — and it's what lets the "Ask me something" CTA
	   (margin-top:auto) share one baseline across all four cards. */
	align-items: stretch;
}

.jhilik-agent-card {
	position: relative;
	height: 100%;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	padding: clamp(1.4rem, 2.2vw, 1.9rem);
	padding-top: 0;
	border-radius: var(--jh-radius);
	border: var(--jh-line);
	background: var(--card-bg, #ffffff);
	box-shadow: var(--jh-shadow-sm);
	transition: transform 0.22s ease, box-shadow 0.22s ease;
}

.jhilik-agent-card::before {
	content: "";
	display: block;
	height: clamp(210px, 18vw, 260px);
	margin: 0 clamp(-1.4rem, -2.2vw, -1.9rem) 1.1rem;
	/* `contain`, not `auto 94%`: the four artwork files aren't all the same
	   native aspect ratio, so sizing by height alone ("auto 94%") let each
	   dragon render at a different effective width — same box, visibly
	   inconsistent scale. `contain` fits each one fully inside the same
	   box at its own true proportions (never distorted, never cropped),
	   which is the one sizing rule that's actually identical across all
	   four regardless of the source art's own dimensions. */
	background:
		var(--card-art-tint, color-mix(in srgb, var(--card-accent) 20%, #ffffff))
		center bottom / contain no-repeat;
	border-bottom: 3px solid var(--card-accent);
}

.jhilik-agent-card:hover {
	transform: translateY(-8px);
	box-shadow: var(--jh-shadow-md);
}
@keyframes jhilik-agent-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
@media (prefers-reduced-motion: no-preference) {
	.jhilik-agent-card::before { transition: transform 0.28s ease; }
	.jhilik-agent-card:hover::before, .jhilik-agent-card:focus-within::before { transform: translateY(-3px) !important; animation-play-state: paused; }
	.jhilik-agent-card--deany::before { animation: jhilik-agent-float 6s ease-in-out infinite; animation-delay: 0s; }
	.jhilik-agent-card--judy::before  { animation: jhilik-agent-float 6s ease-in-out infinite; animation-delay: 0.5s; }
	.jhilik-agent-card--joyee::before { animation: jhilik-agent-float 6s ease-in-out infinite; animation-delay: 1s; }
	.jhilik-agent-card--arlo::before  { animation: jhilik-agent-float 6s ease-in-out infinite; animation-delay: 1.5s; }
	.jhilik-agent-card__cue { transition: transform 0.18s ease; display: inline-block; }
	.jhilik-agent-card:hover .jhilik-agent-card__cue,
	.jhilik-agent-card:focus-within .jhilik-agent-card__cue { transform: translateX(3px); }
}

.jhilik-agent-card h3 {
	margin: 0 0 0.1rem;
}

.jhilik-agent-card__role {
	margin: 0 0 0.6rem;
	font-family: var(--wp--preset--font-family--sans);
	font-weight: 600;
	font-size: 0.9rem;
	color: color-mix(in srgb, var(--card-accent) 72%, var(--wp--preset--color--contrast));
}

.jhilik-agent-card__status {
	position: absolute;
	top: 1rem;
	right: 1.1rem;
	margin: 0;
	font-size: 0.62rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--jh-ink-soft);
	z-index: 2;
}

.jhilik-agent-card__status::before {
	content: "";
	display: inline-block;
	width: 0.45rem;
	height: 0.45rem;
	margin-right: 0.3rem;
	border-radius: 50%;
	background: var(--card-accent);
	vertical-align: middle;
}

.jhilik-agent-card p:last-child {
	margin-bottom: 0;
	color: var(--jh-ink-soft);
	font-size: 0.98rem;
}

/* Card artwork uses the delivered "working" pose. object-fit-style contain
   via background-size; transparent PNGs, no panel behind the art. */
.jhilik-agent-card--deany { --card-accent: var(--wp--preset--color--agent-deany); --card-bg: color-mix(in srgb, var(--wp--preset--color--agent-deany) 6%, #ffffff); }
.jhilik-agent-card--deany::before { background-image: url("../characters/deany-working.png"); }
.jhilik-agent-card--judy  { --card-accent: var(--wp--preset--color--agent-judy);  --card-bg: color-mix(in srgb, var(--wp--preset--color--agent-judy) 6%, #ffffff); }
.jhilik-agent-card--judy::before  { background-image: url("../characters/judy-working.png"); }
.jhilik-agent-card--joyee { --card-accent: var(--wp--preset--color--agent-joyee); --card-bg: color-mix(in srgb, var(--wp--preset--color--agent-joyee) 6%, #ffffff); }
.jhilik-agent-card--joyee::before { background-image: url("../characters/joyee-working.png"); }
.jhilik-agent-card--arlo  { --card-accent: var(--wp--preset--color--agent-arlo);  --card-bg: color-mix(in srgb, var(--wp--preset--color--agent-arlo) 6%, #ffffff); }
.jhilik-agent-card--arlo::before  { background-image: url("../characters/arlo-working.png"); }

/* 8b. Agent Desk — real pipeline strip. Deliberately plain-text steps, no
   Telegram/token/credential/admin references — this is the public-safe
   explanation of the actual draft-first pipeline in jhilik-content-agent's
   pipeline.php, not a diagram of internal tooling. */
.jhilik-agent-workflow {
	margin-top: clamp(2.5rem, 5vw, 3.5rem);
	padding: clamp(1.5rem, 3vw, 2.25rem);
	background: var(--wp--preset--color--base);
	border: var(--jh-line);
	border-radius: var(--jh-radius-lg, 24px);
}
.jhilik-agent-workflow__title {
	margin: 0 0 clamp(1.25rem, 2.5vw, 1.75rem);
	font-size: 1.05rem;
	text-align: center;
}
.jhilik-agent-workflow__steps {
	display: flex;
	align-items: flex-start;
	justify-content: center;
	flex-wrap: wrap;
	gap: 0.75rem 0;
}
.jhilik-agent-workflow__step {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	width: 168px;
	gap: 0.35rem;
}
.jhilik-agent-workflow__num {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 2rem;
	height: 2rem;
	border-radius: 50%;
	background: var(--wp--preset--color--secondary);
	color: var(--wp--preset--color--contrast);
	font-weight: 700;
	font-size: 0.9rem;
	margin-bottom: 0.15rem;
}
.jhilik-agent-workflow__step--human .jhilik-agent-workflow__num {
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--white);
}
.jhilik-agent-workflow__label { margin: 0; font-weight: 700; font-size: 0.92rem; }
.jhilik-agent-workflow__desc { margin: 0; font-size: 0.82rem; color: var(--jh-ink-soft); line-height: 1.4; }
.jhilik-agent-workflow__arrow {
	align-self: center;
	margin-top: 0.85rem;
	color: var(--jh-ink-soft);
	font-size: 1.1rem;
	flex: none;
}
.jhilik-agent-workflow__text { display: flex; flex-direction: column; gap: 0.35rem; }
@media (max-width: 720px) {
	.jhilik-agent-workflow__steps { flex-direction: column; align-items: stretch; gap: 0; }
	.jhilik-agent-workflow__step { width: auto; flex-direction: row; text-align: left; align-items: flex-start; padding: 0.85rem 0; gap: 0; }
	.jhilik-agent-workflow__num { flex: none; margin: 0 0.9rem 0 0; }
	.jhilik-agent-workflow__label, .jhilik-agent-workflow__desc { text-align: left; }
	.jhilik-agent-workflow__arrow { display: none; }
	.jhilik-agent-workflow__step:not(:last-child) { border-bottom: var(--jh-line); }
}

/* 9. Research — publication cards --------------------- */

.jhilik-research {
	display: grid;
	grid-template-columns: 0.85fr 1.15fr;
	gap: clamp(2rem, 5vw, 4rem);
	align-items: center;
}

/* Used to hand-tune a "step down from global H2" here — the corrected
   base H2 scale (theme.json) now lands at the same size on its own, so
   this section just inherits it like every other homepage section head. */

.jhilik-research__text p {
	color: var(--jh-ink-soft);
	font-size: 1.08rem;
	max-width: 42ch;
}


/* small subtle deep-link CTAs under a section's intro copy (Portfolio,
   Tools, Videos → their full archive) — same link language as
   .jhilik-pub__link, not a new button */
.jhilik-deep-link {
	display: inline-block;
	margin-top: 0.6rem;
	font-size: 0.9rem;
	font-weight: 600;
	text-decoration: none;
	color: var(--wp--preset--color--primary);
}
.jhilik-deep-link::after {
	content: " \2192";
}

/* 10. Portfolio — project windows -------------------- */

.jhilik-portfolio {
	display: grid;
	grid-template-columns: 1.15fr 0.85fr;
	gap: clamp(2rem, 5vw, 4rem);
	align-items: center;
}

.jhilik-portfolio__text p {
	color: var(--jh-ink-soft);
	font-size: 1.08rem;
	max-width: 42ch;
}


/* 11. Tools — featured + secondary ------------------- */

.jhilik-tools {
	background:
		radial-gradient(760px 480px at 10% 0%, color-mix(in srgb, var(--wp--preset--color--mint) 40%, transparent), transparent 62%),
		radial-gradient(680px 420px at 100% 100%, color-mix(in srgb, var(--wp--preset--color--secondary) 34%, transparent), transparent 60%),
		linear-gradient(180deg, color-mix(in srgb, var(--wp--preset--color--mint) 14%, var(--wp--preset--color--canvas)), var(--wp--preset--color--canvas));
	border-block: var(--jh-line);
	/* Tighter than the generic .jhilik-section rhythm — this section's own
	   content (a compact heading row, one featured tool, two small tiles)
	   doesn't need as much top/bottom air as sections with a full grid or
	   long-form copy, and the oversized H2 below was the other half of
	   why this read as a large empty canvas around three small pieces. */
	padding-block: clamp(2rem, 3.2vw, 2.75rem);
}

.jhilik-tools .jhilik-section__head {
	margin-bottom: clamp(1.25rem, 2vw, 1.75rem);
}
/* Used to hand-tune its own H2 size here too — same fix as Research above,
   now just inherits the corrected base H2 scale. */


/* 12. Videos --------------------------------------- */

.jhilik-videos__grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: clamp(1rem, 2vw, 1.6rem);
}

.jhilik-video {
	display: flex;
	flex-direction: column;
	gap: 0.8rem;
}

.jhilik-video__frame {
	position: relative;
	aspect-ratio: 16 / 9;
	border-radius: 18px;
	overflow: hidden;
	border: var(--jh-line);
	box-shadow: var(--jh-shadow-sm);
	background: linear-gradient(135deg, color-mix(in srgb, var(--wp--preset--color--accent) 34%, #ffffff), color-mix(in srgb, var(--wp--preset--color--secondary) 34%, #ffffff));
	transition: transform 0.22s ease, box-shadow 0.22s ease;
}

.jhilik-video:nth-child(2) .jhilik-video__frame {
	background: linear-gradient(135deg, color-mix(in srgb, var(--wp--preset--color--mint) 40%, #ffffff), color-mix(in srgb, var(--wp--preset--color--secondary) 30%, #ffffff));
}

.jhilik-video:nth-child(3) .jhilik-video__frame {
	background: linear-gradient(135deg, color-mix(in srgb, var(--wp--preset--color--blush) 42%, #ffffff), color-mix(in srgb, var(--wp--preset--color--accent) 30%, #ffffff));
}

.jhilik-video__frame::before {
	content: "";
	position: absolute;
	inset: 0;
	margin: auto;
	width: 64px;
	height: 64px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.92);
	box-shadow: var(--jh-shadow-md);
}

.jhilik-video__frame::after {
	content: "";
	position: absolute;
	inset: 0;
	margin: auto;
	width: 0;
	height: 0;
	border-style: solid;
	border-width: 12px 0 12px 20px;
	border-color: transparent transparent transparent var(--wp--preset--color--primary);
	translate: 4px 0;
}

.jhilik-video:hover .jhilik-video__frame {
	transform: translateY(-4px);
	box-shadow: var(--jh-shadow-md);
}

.jhilik-video p {
	margin: 0;
	font-weight: 600;
	font-size: 1rem;
}

/* 14. About — visual timeline -------------------- */

.jhilik-about {
	display: grid;
	grid-template-columns: 0.9fr 1.1fr;
	gap: clamp(2rem, 5vw, 4rem);
	align-items: start;
}

.jhilik-about__text p {
	color: var(--jh-ink-soft);
	font-size: 1.08rem;
	max-width: 56ch;
}

/* Byline-style header: a small round portrait sits beside the eyebrow +
   heading as a personal signature, then the body copy runs full-width
   below — replaces the old float-left portrait, which forced the eyebrow
   pill and heading to wrap awkwardly around a 120px image. */
.jhilik-about__header {
	display: flex;
	align-items: center;
	gap: 1.1rem;
	margin-bottom: 1.1rem;
}
.jhilik-about__avatar {
	flex: none;
	width: 4.5rem;
	height: 4.5rem;
	border-radius: 50%;
	overflow: hidden;
	box-shadow: var(--jh-shadow-sm);
	border: 2px solid var(--wp--preset--color--white);
	outline: var(--jh-line);
}
.jhilik-about__avatar img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
.jhilik-about__intro .jhilik-eyebrow { margin-bottom: 0.35rem; }
.jhilik-about__intro h2 { margin: 0; }
@media (max-width: 700px) {
	.jhilik-about__avatar { width: 3.5rem; height: 3.5rem; }
}

.jhilik-timeline {
	counter-reset: jh-tl;
	display: grid;
	gap: 1.5rem;
}

.jhilik-timeline__item {
	counter-increment: jh-tl;
	position: relative;
	padding: 1.25rem 1.4rem 1.25rem 4.25rem;
	background: var(--wp--preset--color--white);
	border: var(--jh-line);
	border-radius: var(--jh-radius-sm);
	box-shadow: var(--jh-shadow-sm);
}

.jhilik-timeline__item::before {
	content: counter(jh-tl, decimal-leading-zero);
	position: absolute;
	left: 1.1rem;
	top: 1.15rem;
	width: 2.4rem;
	height: 2.4rem;
	display: grid;
	place-items: center;
	border-radius: 50%;
	font-family: var(--wp--preset--font-family--display);
	font-weight: 800;
	font-size: 0.85rem;
	color: #ffffff;
	background: var(--wp--preset--color--primary);
}

.jhilik-timeline__item:nth-child(2)::before { background: var(--wp--preset--color--agent-judy); }
.jhilik-timeline__item:nth-child(3)::before { background: var(--wp--preset--color--agent-arlo); }

.jhilik-timeline__item::after {
	content: "";
	position: absolute;
	left: 2.28rem;
	top: 3.55rem;
	bottom: -1.5rem;
	width: 2px;
	background: color-mix(in srgb, var(--wp--preset--color--accent) 60%, #ffffff);
}

.jhilik-timeline__item:last-child::after { display: none; }

.jhilik-timeline__item h3 {
	margin: 0 0 0.25rem;
}

.jhilik-timeline__item p {
	margin: 0;
	font-size: 0.95rem;
	color: var(--jh-ink-soft);
}

/* 15. Contact — midnight closing scene ----------- */

.jhilik-contact {
	position: relative;
	overflow: hidden;
	text-align: center;
	color: var(--wp--preset--color--white);
	background:
		radial-gradient(620px 420px at var(--jh-cta-x1, 18%) var(--jh-cta-y1, 8%), color-mix(in srgb, var(--wp--preset--color--accent) 42%, transparent), transparent 66%),
		radial-gradient(720px 520px at var(--jh-cta-x2, 84%) var(--jh-cta-y2, 92%), color-mix(in srgb, var(--wp--preset--color--agent-deany) 40%, transparent), transparent 64%),
		var(--wp--preset--gradient--midnight);
	border-block: 1px solid rgba(255, 255, 255, 0.08);
	/* Was clamp(4rem, 7vw, 6rem) — 64-96px, exceeding the site's own
	   72-84px desktop / 44-52px mobile section-padding ceiling on both
	   ends (a closing CTA doesn't need more air than every other section). */
	padding-block: clamp(3rem, 6vw, 5.25rem);
}

.jhilik-contact h2 {
	/* Was clamp(2.4rem, 4.4vw, 3.6rem) — up to 57.6px, nearly double every
	   other section H2 on the site (34px). A closing CTA can still read as
	   a strong moment at the shared H2 scale; it doesn't need its own
	   oversized tier. */
	color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--x-large);
	margin: 0 auto 1rem;
	max-width: 16ch;
}

.jhilik-contact p {
	margin: 0 auto 1.9rem;
	max-width: 44ch;
	font-size: 1.15rem;
	color: rgba(255, 255, 255, 0.74);
}

.jhilik-contact .jhilik-eyebrow {
	color: var(--wp--preset--color--white);
	background: rgba(255, 255, 255, 0.12);
}

.jhilik-contact .wp-block-buttons {
	justify-content: center;
}

.jhilik-contact .wp-block-button__link {
	background: var(--wp--preset--color--white);
	color: var(--wp--preset--color--navy);
	padding: 1.1rem 2.4rem;
	font-size: 1.02rem;
	box-shadow: 0 20px 50px -20px rgba(0, 0, 0, 0.6);
}

.jhilik-contact .wp-block-button__link:hover,
.jhilik-contact .wp-block-button__link:focus {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--navy);
}

/* the four dragons, subtle, along the base — "working" poses, reusing the
   images the Meet-My-Agents cards already load (so they come from cache). */
/* Registering these as <percentage> lets the browser actually interpolate
   the drift smoothly; without @property, an unregistered custom property
   animates as a discrete string (an instant jump at 50%, not a drift). */
@property --jh-cta-x1 { syntax: '<percentage>'; inherits: false; initial-value: 18%; }
@property --jh-cta-y1 { syntax: '<percentage>'; inherits: false; initial-value: 8%; }
@property --jh-cta-x2 { syntax: '<percentage>'; inherits: false; initial-value: 84%; }
@property --jh-cta-y2 { syntax: '<percentage>'; inherits: false; initial-value: 92%; }
@keyframes jhilik-cta-drift {
	0%, 100% { --jh-cta-x1: 18%; --jh-cta-y1: 8%; --jh-cta-x2: 84%; --jh-cta-y2: 92%; }
	50% { --jh-cta-x1: 24%; --jh-cta-y1: 14%; --jh-cta-x2: 78%; --jh-cta-y2: 86%; }
}
@media (prefers-reduced-motion: no-preference) {
	.jhilik-contact { animation: jhilik-cta-drift 16s ease-in-out infinite; }
}
.jhilik-contact__crew {
	height: clamp(74px, 9vw, 108px);
	margin: clamp(2.25rem, 4vw, 3.25rem) auto 0;
	max-width: 560px;
	opacity: 0.94;
	background:
		url("../characters/deany-working.png") 7% bottom / auto 100% no-repeat,
		url("../characters/judy-working.png") 37% bottom / auto 92% no-repeat,
		url("../characters/joyee-working.png") 64% bottom / auto 92% no-repeat,
		url("../characters/arlo-working.png") 92% bottom / auto 100% no-repeat;
}

/* 16. Buttons ----------------------------------- */

.wp-block-button__link {
	text-decoration: none;
	transition: transform 0.16s ease, background-color 0.2s ease, color 0.2s ease;
}

.wp-block-button__link:active {
	transform: translateY(1px);
}

.wp-block-button.is-style-outline .wp-block-button__link {
	background-color: rgba(255, 255, 255, 0.55);
	color: var(--wp--preset--color--contrast);
	border: 1.5px solid var(--wp--preset--color--contrast);
	-webkit-backdrop-filter: blur(4px);
	backdrop-filter: blur(4px);
}

.wp-block-button.is-style-outline .wp-block-button__link:hover,
.wp-block-button.is-style-outline .wp-block-button__link:focus {
	background-color: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--white);
}

/* 17. Motion — hero studio ---------------------- */
/*
   Layers, all gated by prefers-reduced-motion:

   1. IDLE     — CSS keyframes on .agent-character / .jil-character add a
                 gentle whole-body float (translate3d + tiny rotation, one
                 cadence per dragon) on top of the dragon's own animated
                 WebP, which is already alive inside its frame — the body
                 sway and the in-frame animation are independent layers.

   2. FLIGHT   — assets/js/hero.js animates .jhilik-figure `transform` with
                 the Web Animations API along the phased route
                 (crouch -> takeoff -> climb -> bank -> glide -> approach ->
                 land). It toggles `.is-airborne`, which both swaps the pose
                 (idle WebP -> flying WebP) and drives the shadow/glow. The
                 flying WebP keeps playing its own frames throughout — the
                 travel and the in-frame animation are two independent
                 layers, not one faked from the other. Autonomous flights
                 and travel are disabled for reduced-motion.

   3. HOVER    — CSS `:hover` lift on .jhilik-figure (phase 1); hero.js runs
                 a short mini-flight after ~0.5s of hover (phase 2).

   4. BUBBLES  — soft fade-in + gentle drift; `.is-active` reaction scale.
*/

@media (prefers-reduced-motion: no-preference) {

	.agent-character,
	.jil-character {
		animation: jh-idle var(--idle-dur, 6s) ease-in-out var(--idle-delay, 0s) infinite;
	}
	.jhilik-figure--deany  { --idle-dur: 4.8s; --idle-delay: 0s; }
	.jhilik-figure--joyee  { --idle-dur: 5.6s; --idle-delay: 0.5s; }
	.jhilik-figure--judy   { --idle-dur: 6.3s; --idle-delay: 0.2s; }
	.jhilik-figure--arlo   { --idle-dur: 5.4s; --idle-delay: 0.8s; }
	.jil-character         { --idle-dur: 7.2s; animation-name: jh-idle-soft; }

	.jhilik-bubble {
		animation:
			jh-bubble-in 0.6s ease-out both var(--bubble-in, 0.3s),
			jh-bubble-drift var(--drift-dur, 7s) ease-in-out calc(var(--bubble-in, 0.3s) + 0.6s) infinite;
	}
	.jhilik-bubble--headlines { --bubble-in: 0.35s; --drift-dur: 7.2s; }
	.jhilik-bubble--research  { --bubble-in: 0.7s;  --drift-dur: 8s; }
	.jhilik-bubble--drafting  { --bubble-in: 0.55s; --drift-dur: 7.6s; }
	.jhilik-bubble--data      { --bubble-in: 0.9s;  --drift-dur: 8.3s; }
	.jhilik-bubble--ready     { --bubble-in: 1.3s;  --drift-dur: 7.9s; }

	.jhilik-agent-card__status::before { animation: jh-pulse 1.9s ease-in-out infinite; }
}

@keyframes jh-idle {
	0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
	45%      { transform: translate3d(0, -8px, 0) rotate(-1.4deg); }
	55%      { transform: translate3d(0, -8px, 0) rotate(1.4deg); }
}

@keyframes jh-idle-soft {
	0%, 100% { transform: translate3d(0, 0, 0); }
	50%      { transform: translate3d(0, -5px, 0); }
}

/* Hover reaction (phase 1) — pointer devices only. hero.js adds .is-flyer
   to the four dragons; phase 2 (a short mini-flight) is JS. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
	.jhilik-figure.is-flyer:not(.is-airborne):hover {
		transform: translate3d(0, -12px, 0) rotate(1.6deg) scale(1.05);
	}
}
@media (hover: hover) and (prefers-reduced-motion: reduce) {
	.jhilik-figure.is-flyer:not(.is-airborne):hover {
		transform: scale(1.03);
	}
}

@keyframes jh-bubble-in {
	from { opacity: 0; translate: 0 8px; }
	to   { opacity: 1; translate: 0 0; }
}

@keyframes jh-bubble-drift {
	0%, 100% { translate: 0 0; }
	50%      { translate: 0 -5px; }
}

@keyframes jh-pulse {
	0%, 100% { opacity: 1; transform: scale(1); }
	50%      { opacity: 0.4; transform: scale(0.7); }
}

/* 18. Responsive ------------------------------- */

@media (min-width: 1500px) {
	.jhilik-stage { max-width: 650px; }
	.jhilik-hero__cols { gap: 5.5rem !important; }
}

/* "Laptop" zone (981–1180px, e.g. 1024px): the two-column hero still holds
   here (it doesn't stack until 980px). The heading/lead no longer need a
   one-off shrink here — both now use the site-wide fluid typography scale
   (theme.json), which already lands at a comfortable size at this width
   instead of holding a fixed desktop floor. Only the column gap still
   needs tightening at this width. */
@media (max-width: 1180px) and (min-width: 981px) {
	.jhilik-hero__cols { gap: clamp(1.5rem, 3vw, 2.5rem) !important; }
	/* Task bubbles are positioned/sized for the full ~713px desktop stage;
	   in this tablet gap the stage shrinks to ~500-550px while the bubble
	   text and dragon artwork stay the same fixed size, so bubbles land
	   on top of the dragons and read as truncated (e.g. "Building
	   headlines" half-hidden behind Deany). Below 980px the stage already
	   drops to a static grid without bubbles at all — simplest correct
	   fix here is the same: hide them rather than risk them clipping. */
	.jhilik-bubble { display: none; }
}

@media (max-width: 1080px) {
	.jhilik-agents-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.jhilik-videos__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Hero + feature sections stack; scene becomes a calm static grid */
@media (max-width: 980px) {
	.jhilik-hero {
		/* Split, not the `padding-block` shorthand: a shorthand here would
		   reset padding-top back to a plain clamp(), silently dropping the
		   header-clearance term the base .jhilik-hero rule adds and putting
		   the H1 back under the fixed header at exactly this breakpoint —
		   caught by measuring h1's real getBoundingClientRect().top at
		   768px, not by an HTTP-200/scrollWidth check. */
		padding-top: calc(var(--jh-header-clearance) + clamp(3rem, 8vw, 4.5rem));
		padding-bottom: clamp(3.25rem, 9vw, 5rem);
	}
	.jhilik-hero__cols { flex-wrap: wrap; }
	.jhilik-hero__cols > .wp-block-column { flex-basis: 100% !important; }
	.jhilik-hero__text { max-width: none; }
	/* Font-size no longer overridden here — the fluid display token
	   already scales down correctly at this width. Only margin changes. */
	.jhilik-hero h1 { margin-bottom: 1.1rem; }
	.jhilik-hero__lead { margin-bottom: 1.4rem; }

	.jhilik-stage {
		aspect-ratio: auto;
		max-width: 440px;
		margin-top: clamp(2rem, 6vw, 3rem);
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		grid-template-areas:
			"jhilik jhilik"
			"deany  joyee"
			"judy   arlo";
		gap: 1.25rem 1rem;
	}
	.jhilik-stage::before { display: none; }
	.jhilik-figure {
		position: static;
		translate: none;
		transform: none;
		will-change: auto;
		width: auto;
		max-width: 200px;
		justify-self: center;
	}
	/* the ground shadow / glow pseudos are absolute — hide them once the
	   scene is a static grid (flights become tiny contained hops) */
	.jhilik-figure::before,
	.jhilik-figure::after { display: none; }
	.jhilik-figure--jhilik { grid-area: jhilik; max-width: 220px; }
	.jhilik-figure--deany { grid-area: deany; }
	.jhilik-figure--joyee { grid-area: joyee; }
	.jhilik-figure--judy { grid-area: judy; }
	.jhilik-figure--arlo { grid-area: arlo; }
	.jhilik-bubble { display: none; }

	.jhilik-research,
	.jhilik-portfolio,
	.jhilik-about {
		grid-template-columns: 1fr;
		gap: clamp(1.5rem, 5vw, 2.25rem);
	}
}

@media (max-width: 720px) {
	.jhilik-agents-grid,
	.jhilik-videos__grid { grid-template-columns: 1fr; }
}

@media (max-width: 460px) {
	/* Keep the 2-column grid from the 980px rule above (not a full single-
	   column stack) — 5 images stacked one-per-row at this max-width made
	   the hero run to ~1700px of pure scrolling on a phone before Studio
	   even started. Shrinking the same layout keeps every character
	   visible in roughly a third of that height. */
	.jhilik-stage { max-width: 300px; }
	.jhilik-figure { max-width: 132px; }
	.jhilik-figure--jhilik { max-width: 148px; }
}

/* 20. Content-type archives/singles (Research first) -------- */
/*
   Shared look for jhilik-core's CPT archive/single pages — reuses the same
   tokens as everywhere else (--jh-radius, --jh-shadow-*, --jh-line, the
   agent accent colors) so a Research page feels like the same website as
   the homepage. Research is wired up first via templates/archive-
   jhilik_research.html and single-jhilik_research.html; Portfolio/Tools/
   Videos/Gallery still use jhilik-core's generic template for now.
*/

/* Bug fix: this referenced --wide, a variable that was never defined
   anywhere in the codebase — max-width silently resolved to its initial
   value (none), so every archive page (Research/Portfolio/Tools) was
   actually being constrained by theme.json's much narrower global
   contentSize (820px) instead of this rule, which is exactly why they
   read as cramped with excess side whitespace. --content-width (1220px)
   is the real, already-defined "wide page" token. */
.jhilik-cpt-archive { max-width: var(--content-width); margin-inline: auto; padding-inline: var(--wp--style--root--padding-left, 1.5rem); }
.jhilik-about-page { max-width: 1000px; margin-inline: auto; padding-inline: var(--wp--style--root--padding-left, 1.5rem); }

/* Gallery now has its own versioned theme file (templates/archive-
   jhilik_gallery_item.html), whose <main> carries .jhilik-cpt-archive
   like every other archive — but that class only sets max-width on the
   OUTER <main>, not the --wp--style--global--content-size variable core's
   own child selector (.is-layout-constrained > *) reads for the query-
   title and the photo grid inside it. Scoped to the semantic
   .jhilik-cpt-archive--gallery class the template gives <main>, so this
   never depends on WordPress's own post-type-archive body class or a
   bare `main.wp-block-group` tag selector. */
.jhilik-cpt-archive--gallery {
	--wp--style--global--content-size: var(--content-width);
}

.jhilik-archive-head {
	max-width: 60ch;
	margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
}
.jhilik-archive-head h1 { margin: 0.4rem 0 0.6rem; }
/* The 60ch measure above is sized for a plain text-only archive intro.
   Any hero that instead pairs its text with an image via .jhilik-media-
   split (Research, Videos, Tools all do) needs the wider "content"
   measure instead: 60ch caps the WHOLE two-column panel, leaving each
   column only ~30ch wide — narrow enough that a large heading (theme.
   json's fluid xx-large size) has no room to breathe, which is what was
   pushing single-word headings toward an ugly mid-word wrap, and left
   Tools noticeably narrower than every other archive hero for no design
   reason. Keyed off :has() so it applies to every image-paired hero
   uniformly, not just ones that also carry a specific extra class. */
.jhilik-labs-hero:has(.jhilik-media-split) { max-width: var(--content-width); }

/* Portfolio hero — full-bleed image with overlaid text, replacing the
   small-pastel-box-plus-side-image treatment every other archive head
   uses. The real image is a genuine core/image block (still replaceable
   from Media Library) positioned as an absolute-fill layer behind a
   scrim and the text group, inside one position:relative card. */
.jhilik-portfolio-hero {
	position: relative;
	overflow: hidden;
	border-radius: var(--jh-radius-xl);
	margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
	min-height: clamp(320px, 46vw, 520px);
	display: flex;
	align-items: flex-end;
	width: 100%;
	max-width: var(--content-width);
}
.jhilik-portfolio-hero__media {
	position: absolute;
	inset: 0;
	margin: 0;
	z-index: 0;
}
.jhilik-portfolio-hero__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* The illustration's characters sit in the lower-middle band with a
	   tall band of safe, empty background above them — biasing the crop
	   toward the bottom keeps every character in frame at wide desktop
	   ratios instead of a center crop cutting through their heads. */
	object-position: center 68%;
	display: block;
}
.jhilik-portfolio-hero__scrim {
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(0deg, rgba(16, 21, 42, 0.78) 0%, rgba(16, 21, 42, 0.42) 45%, rgba(16, 21, 42, 0.05) 75%);
	pointer-events: none;
}
.jhilik-portfolio-hero__text {
	position: relative;
	z-index: 2;
	padding: clamp(1.75rem, 4vw, 3rem);
	max-width: 60ch;
}
.jhilik-portfolio-hero__text .jhilik-eyebrow {
	background: rgba(255, 255, 255, 0.16);
	color: var(--wp--preset--color--white);
}
.jhilik-portfolio-hero__text h1 {
	margin: 0.4rem 0 0.6rem;
	color: var(--wp--preset--color--white);
}
.jhilik-portfolio-hero__text .jhilik-lead {
	color: rgba(255, 255, 255, 0.88);
}
@media (max-width: 640px) {
	.jhilik-portfolio-hero { min-height: 380px; }
	.jhilik-portfolio-hero__media img { object-position: center 78%; }
}

.jhilik-archive-grid { gap: clamp(1.25rem, 2.5vw, 1.75rem) !important; }

.jhilik-research-card {
	/* Deliberately NOT height:100% — that stretched a short, text-only card
	   (an "ongoing" record with no featured image and no excerpt yet) to
	   match a taller sibling's row height, then the excerpt's flex:1 below
	   turned the leftover space into one big dead gap before "View
	   Research" instead of the CTA simply sitting after the copy. align-
	   self:start opts this one card out of the grid's default row-stretch
	   without touching the archive's grid container itself. */
	align-self: start;
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	padding: clamp(1.4rem, 2.2vw, 1.8rem);
	background: #ffffff;
	border: var(--jh-line);
	border-left: 4px solid var(--wp--preset--color--agent-judy);
	border-radius: var(--jh-radius-sm);
	box-shadow: var(--jh-shadow-sm);
	transition: transform 0.22s ease, box-shadow 0.22s ease;
}
.jhilik-research-card:hover { transform: translateY(-4px); box-shadow: var(--jh-shadow-md); }
.jhilik-research-card .jhilik-research-card__tag {
	display: inline-block;
	margin: 0;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--agent-judy);
}
.jhilik-research-card h3 { margin: 0; }
.jhilik-research-card .wp-block-post-excerpt {
	display: flex;
	flex-direction: column;
	color: var(--jh-ink-soft);
	font-size: 0.95rem;
}
/* The "more" link WordPress renders is wrapped in its own <p> — a fixed
   gap now, not margin-top:auto, so the CTA sits naturally right after
   the excerpt copy instead of being pushed to the bottom of a stretched
   card (see .jhilik-research-card above). A card with no excerpt text at
   all (an ongoing record with nothing written yet) simply reads as
   status + title + link, with no artificial blank space in between. */
.jhilik-research-card .wp-block-post-excerpt__more-text {
	margin-top: 0.5rem;
}
.jhilik-research-card .wp-block-post-excerpt__more-link {
	display: inline-block;
	font-weight: 600;
	font-size: 0.9rem;
	text-decoration: none;
	color: var(--wp--preset--color--primary);
}
.jhilik-research-card .wp-block-post-excerpt__more-link::after { content: " \2192"; }

.jhilik-archive-empty {
	padding: clamp(2.5rem, 5vw, 3.5rem) clamp(1.5rem, 3vw, 2.5rem);
	text-align: center;
	background: color-mix(in srgb, var(--wp--preset--color--secondary) 18%, #ffffff);
	border: var(--jh-line);
	border-radius: var(--jh-radius);
}
.jhilik-archive-empty p { margin: 0; color: var(--jh-ink-soft); }

/* single CPT views: the meta panel jhilik-core appends after the content */
.single-jhilik_research .jhilik-meta,
.single-jhilik_portfolio .jhilik-meta,
.single-jhilik_video .jhilik-meta,
.single-jhilik_tool .jhilik-meta,
.single-jhilik_gallery_item .jhilik-meta {
	max-width: 60ch;
	padding: 1.25rem 1.5rem;
	border: var(--jh-line);
	border-radius: var(--jh-radius-sm);
	box-shadow: var(--jh-shadow-sm);
	background: #ffffff;
}
.single-jhilik_research .jhilik-meta { border-left: 4px solid var(--wp--preset--color--agent-judy); }
.single-jhilik_portfolio .jhilik-meta { border-left: 4px solid var(--wp--preset--color--agent-deany); }
.single-jhilik_tool .jhilik-meta { border-left: 4px solid var(--wp--preset--color--agent-arlo); }
.single-jhilik_video .jhilik-meta { border-left: 4px solid var(--wp--preset--color--agent-joyee); }

/* Portfolio cards (accent: Deany blue) */
.jhilik-portfolio-card {
	height: 100%;
	display: flex;
	flex-direction: column;
	background: #ffffff;
	border: var(--jh-line);
	border-radius: var(--jh-radius-sm);
	box-shadow: var(--jh-shadow-sm);
	overflow: hidden;
	transition: transform 0.22s ease, box-shadow 0.22s ease;
}
.jhilik-portfolio-card:hover { transform: translateY(-4px); box-shadow: var(--jh-shadow-md); }
.jhilik-portfolio-card__thumb {
	aspect-ratio: 16 / 9;
	background: linear-gradient(135deg, color-mix(in srgb, var(--wp--preset--color--agent-deany) 26%, #ffffff), color-mix(in srgb, var(--wp--preset--color--accent) 24%, #ffffff));
}
.jhilik-portfolio-card__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.jhilik-portfolio-card__body { padding: clamp(1.25rem, 2vw, 1.6rem); display: flex; flex-direction: column; gap: 0.4rem; flex: 1; }
/* Frontend repair: capability-grouping cards have no real screenshot to
   show, so the "PROJECT VISUAL" placeholder panel was removed from the
   template entirely rather than replaced with an unrelated photo. This
   top accent bar (reusing the same portfolio accent color the removed
   thumb used to carry) keeps a text-only card from reading as visually
   flat/unfinished. */
.jhilik-portfolio-card--no-thumb { border-top: 4px solid var(--jh-accent-a, var(--wp--preset--color--agent-deany)); }
.jhilik-portfolio-card--no-thumb .jhilik-portfolio-card__body { padding-top: clamp(1.5rem, 2.4vw, 1.9rem); }
.jhilik-portfolio-card__body > .jhilik-meta-field {
	display: block;
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--wp--preset--color--agent-deany);
}
.jhilik-portfolio-card h3 { margin: 0; }
.jhilik-portfolio-card p { margin: 0; color: var(--jh-ink-soft); font-size: 0.975rem; }
/* Bug fix: margin-top:auto on the <a> itself did nothing, because
   WordPress wraps that link in its own <p class="...__more-text"> —
   that paragraph, not the link inside it, is the flex child of
   .wp-block-post-excerpt that actually needs to be pushed down. Latent
   until a second, differently-sized card lands in the same grid row as
   a thumb card and stretches this one; matches the fix applied to
   .jhilik-research-card for the identical structure. */
.jhilik-portfolio-card .wp-block-post-excerpt {
	display: flex;
	flex-direction: column;
	flex: 1;
}
.jhilik-portfolio-card .wp-block-post-excerpt__more-text {
	margin-top: auto;
	padding-top: 0.6rem;
}
.jhilik-portfolio-card .wp-block-post-excerpt__more-link {
	display: inline-block;
	font-weight: 600;
	font-size: 0.9rem;
	text-decoration: none;
	color: var(--wp--preset--color--primary);
}
.jhilik-portfolio-card .wp-block-post-excerpt__more-link::after { content: " \2192"; }

/* Tools cards (accent: Arlo mint) + status pills */
.jhilik-tool-card {
	height: 100%;
	padding: clamp(1.4rem, 2.2vw, 1.8rem);
	background: #ffffff;
	border: var(--jh-line);
	border-radius: var(--jh-radius);
	box-shadow: var(--jh-shadow-sm);
	transition: transform 0.22s ease, box-shadow 0.22s ease;
}
.jhilik-tool-card:hover { transform: translateY(-4px); box-shadow: var(--jh-shadow-md); }
.jhilik-tool-card h3 { margin: 0.5rem 0 0.35rem; }
.jhilik-tool-card p { margin: 0; color: var(--jh-ink-soft); font-size: 0.975rem; }
.jhilik-tool-card > .jhilik-meta-field { display: block; font-weight: 600; margin: 0 0 0.4rem; }
.jhilik-tool-card .wp-block-post-excerpt__more-link {
	display: inline-block;
	margin-top: 0.9rem;
	font-weight: 600;
	font-size: 0.9rem;
	text-decoration: none;
	color: var(--wp--preset--color--primary);
}
.jhilik-tool-card .wp-block-post-excerpt__more-link::after { content: " \2192"; }

.jhilik-status-pill {
	display: inline-block;
	padding: 0.28rem 0.7rem;
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	border-radius: 999px;
	color: var(--wp--preset--color--contrast);
	background: color-mix(in srgb, var(--wp--preset--color--secondary) 55%, #ffffff);
}
.jhilik-status-pill--live { background: color-mix(in srgb, var(--wp--preset--color--mint) 55%, #ffffff); }
.jhilik-status-pill--beta { background: color-mix(in srgb, var(--wp--preset--color--accent) 45%, #ffffff); }
.jhilik-status-pill--experiment { background: color-mix(in srgb, var(--wp--preset--color--blush) 50%, #ffffff); }
.jhilik-status-pill--in-development,
.jhilik-status-pill--concept,
.jhilik-status-pill--ongoing,
.jhilik-status-pill--completed { background: color-mix(in srgb, var(--wp--preset--color--tertiary) 70%, #ffffff); }
.jhilik-status-pill--published { background: color-mix(in srgb, var(--wp--preset--color--mint) 55%, #ffffff); }

/* Video cards (accent: Joyee coral) — reuses the homepage's own frame look */
.jhilik-video-card {
	display: flex;
	flex-direction: column;
	gap: 0.7rem;
}
.jhilik-video-card__frame {
	position: relative;
	aspect-ratio: 16 / 9;
	border-radius: 18px;
	overflow: hidden;
	border: var(--jh-line);
	box-shadow: var(--jh-shadow-sm);
	background: linear-gradient(135deg, color-mix(in srgb, var(--wp--preset--color--agent-joyee) 30%, #ffffff), color-mix(in srgb, var(--wp--preset--color--accent) 26%, #ffffff));
	transition: transform 0.22s ease, box-shadow 0.22s ease;
}
.jhilik-video-card__frame img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.3s ease; }
.jhilik-video-card:hover .jhilik-video-card__frame { transform: translateY(-4px); box-shadow: var(--jh-shadow-md); }
.jhilik-video-card__frame::before {
	content: "";
	position: absolute;
	inset: 0;
	margin: auto;
	width: 56px;
	height: 56px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.92);
	box-shadow: var(--jh-shadow-md);
	transition: transform 0.22s ease;
}
.jhilik-video-card__frame::after {
	content: "";
	position: absolute;
	inset: 0;
	margin: auto;
	width: 0;
	height: 0;
	border-style: solid;
	border-width: 10px 0 10px 17px;
	border-color: transparent transparent transparent var(--wp--preset--color--primary);
	translate: 3px 0;
	transition: transform 0.22s ease;
}
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
	/* "Image gently scales, play button enlarges slightly" on hover. */
	.jhilik-video-card:hover .jhilik-video-card__frame img { transform: scale(1.05); }
	.jhilik-video-card:hover .jhilik-video-card__frame::before,
	.jhilik-video-card:hover .jhilik-video-card__frame::after { transform: scale(1.12); }
}

/* Homepage "Latest Videos" strip: desktop keeps the normal 3-column grid
   (all 3 already fit — nothing to scroll); mobile becomes a native
   horizontal swipe instead of stacking to 1 column. */
@media (max-width: 720px) {
	.jhilik-youtube-grid--rail {
		display: flex;
		overflow-x: auto;
		gap: var(--card-gap);
		scroll-snap-type: x proximity;
		padding-bottom: 0.5rem;
		scrollbar-width: none;
	}
	.jhilik-youtube-grid--rail::-webkit-scrollbar { display: none; }
	.jhilik-youtube-grid--rail > .jhilik-video-card { flex: 0 0 82vw; scroll-snap-align: start; }
}
.jhilik-video-card > .jhilik-meta-field { display: block; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--wp--preset--color--agent-joyee); }
.jhilik-video-card .wp-block-post-excerpt__more-link {
	display: inline-block;
	margin-top: 0.4rem;
	font-weight: 600;
	font-size: 0.9rem;
	text-decoration: none;
	color: var(--wp--preset--color--primary);
}
.jhilik-video-card .wp-block-post-excerpt__more-link::after { content: " \2192"; }
.jhilik-video-card h3 { margin: 0; }
/* Latest-YouTube-uploads block (jhilik-core/youtube-videos) reuses every
   .jhilik-video-card rule above as-is; these two rules are the only
   pieces that block needs beyond it. */
.jhilik-youtube-grid .jhilik-video-card > a.jhilik-deep-link { margin-top: 0.2rem; }

/* showFeatured=true (the Videos archive): card thumbnails become buttons
   that re-cue the featured player instead of navigating away. Reset native
   button chrome so `.jhilik-video-card__frame`'s existing play-button
   overlay (::before/::after above) is the only visible affordance. */
button.jhilik-video-card__play {
	display: block;
	width: 100%;
	padding: 0;
	margin: 0;
	font: inherit;
	color: inherit;
	cursor: pointer;
}

/* The large featured player above the grid — a real IFrame API embed,
   cued (never autoplaying) on load. See labs.js initYouTubePlayer(). */
.jhilik-yt-featured {
	width: 100%;
	max-width: 960px;
	margin: 0 0 clamp(1.75rem, 3.5vw, 2.5rem);
}
.jhilik-yt-featured__frame {
	position: relative;
	aspect-ratio: 16 / 9;
	border-radius: 18px;
	overflow: hidden;
	border: var(--jh-line);
	box-shadow: var(--jh-shadow-md);
	background: #000;
}
.jhilik-yt-featured__frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.jhilik-yt-featured__meta { padding-top: 0.85rem; }
.jhilik-yt-featured__title { margin: 0 0 0.35rem; font-size: 1.15rem; }
.jhilik-yt-featured__sub { display: flex; align-items: center; gap: 0.85rem; flex-wrap: wrap; font-size: 0.88rem; }
.jhilik-yt-featured__sub .jhilik-deep-link { font-weight: 600; }

.jhilik-yt-grid-heading { margin: 0 0 1rem; }
.jhilik-youtube-channel-link { margin-top: clamp(1.5rem, 3vw, 2.25rem); }
.jhilik-video-embed {
	position: relative;
	aspect-ratio: 16 / 9;
	border-radius: var(--jh-radius);
	overflow: hidden;
	box-shadow: var(--jh-shadow-md);
	background: var(--wp--preset--color--navy);
}
.jhilik-video-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* meta strip (role · year · status pill etc.) on CPT singles */
.jhilik-meta-strip {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem 0.9rem;
	margin: 0.4rem 0 0.5rem;
	color: var(--jh-ink-soft);
	font-size: 0.92rem;
}
.jhilik-meta-strip .jhilik-meta-field:not(:last-child)::after { content: "\00b7"; margin-left: 0.9rem; opacity: 0.5; }

/* a single labeled callout (e.g. Outcome) — only ever printed when there's
   a real, non-empty value behind it (see jhilik-core/meta-field 'callout') */
.jhilik-callout {
	margin: 1.5rem 0;
	padding: clamp(1.2rem, 2vw, 1.6rem);
	background: color-mix(in srgb, var(--wp--preset--color--mint) 14%, #ffffff);
	border: var(--jh-line);
	border-radius: var(--jh-radius-sm);
}
.jhilik-callout h3 { margin: 0 0 0.4rem; font-size: var(--wp--preset--font-size--subhead); }
.jhilik-callout p { margin: 0; color: var(--jh-ink-soft); }

@media (max-width: 720px) {
	.jhilik-archive-grid { grid-template-columns: 1fr !important; }
}
/* Portfolio cards carry a category, title, description and CTA — 2 columns
   is the readable default; only a genuinely wide desktop gets a 3rd. */
@media (min-width: 1400px) {
	.jhilik-cpt-archive--portfolio .jhilik-archive-grid { grid-template-columns: repeat(3, 1fr) !important; }
}

/* 19. Editor adjustments ----------------------- */

.editor-styles-wrapper .jhilik-hero {
	padding-block: 2.5rem;
}

/* Never absolutely-position the scene in the editor canvas. */
.editor-styles-wrapper .jhilik-stage {
	position: relative;
	aspect-ratio: auto;
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 1rem;
	max-width: 560px;
}
.editor-styles-wrapper .jhilik-stage::before,
.editor-styles-wrapper .jhilik-figure::before,
.editor-styles-wrapper .jhilik-figure::after { display: none; }
.editor-styles-wrapper .jhilik-figure,
.editor-styles-wrapper .jhilik-bubble {
	position: static;
	translate: none;
	transform: none;
	width: auto;
	animation: none;
	opacity: 1;
	cursor: default;
	transition: none;
}
.editor-styles-wrapper .agent-character,
.editor-styles-wrapper .jil-character {
	animation: none;
	max-width: 170px;
	margin-inline: auto;
}
.editor-styles-wrapper .agent-character__fallback { position: relative; opacity: 1; }
.editor-styles-wrapper .agent-character__idle,
.editor-styles-wrapper .agent-character__flying { opacity: 0; }
.editor-styles-wrapper .jhilik-figure--jhilik { grid-column: 1 / -1; justify-self: center; max-width: 190px; }
.editor-styles-wrapper .jhilik-bubble { white-space: normal; }

/* 21. Google Labs design foundation ----------------------------------- */
/*
   Shared, reusable system for the "experimental tool ecosystem" look —
   colorful, rounded, playful, but built entirely from tokens already in
   theme.json (agent colors, secondary/accent/blush/mint/tertiary) so every
   page still reads as the same site. Applied to secondary pages only; the
   homepage hero (section 5) is untouched and stays the design anchor.

   Per-area color personality: wrap a page's <main> (or a section within it)
   in .jhilik-labs-area--{name} and every child .jhilik-labs-* component
   picks up that area's --jh-accent-a/b/c automatically. No area wrapper =
   the site-wide default (primary blue / lavender accent).
*/

:root {
	/* --jh-radius-lg / --jh-radius-xl now live in the section 1 tokens block */
	--jh-accent-a: var(--wp--preset--color--primary);
	--jh-accent-b: var(--wp--preset--color--accent);
	--jh-accent-c: var(--wp--preset--color--secondary);
}

.jhilik-labs-area--research  { --jh-accent-a: var(--wp--preset--color--agent-judy);  --jh-accent-b: var(--wp--preset--color--secondary); --jh-accent-c: var(--wp--preset--color--accent); }
.jhilik-labs-area--portfolio { --jh-accent-a: var(--wp--preset--color--agent-deany); --jh-accent-b: var(--wp--preset--color--agent-joyee); --jh-accent-c: var(--wp--preset--color--secondary); }
.jhilik-labs-area--tools     { --jh-accent-a: var(--wp--preset--color--agent-arlo);  --jh-accent-b: var(--wp--preset--color--blush); --jh-accent-c: var(--wp--preset--color--secondary); }
.jhilik-labs-area--videos    { --jh-accent-a: var(--wp--preset--color--agent-joyee); --jh-accent-b: var(--wp--preset--color--accent); --jh-accent-c: var(--wp--preset--color--secondary); }
.jhilik-labs-area--insights  { --jh-accent-a: var(--wp--preset--color--tertiary);    --jh-accent-b: var(--wp--preset--color--accent); --jh-accent-c: var(--wp--preset--color--secondary); }
.jhilik-labs-area--about     { --jh-accent-a: var(--wp--preset--color--blush);       --jh-accent-b: var(--wp--preset--color--base); --jh-accent-c: var(--wp--preset--color--secondary); }
.jhilik-labs-area--contact   { --jh-accent-a: var(--wp--preset--color--agent-arlo);  --jh-accent-b: var(--wp--preset--color--secondary); }
.jhilik-labs-area--cv        { --jh-accent-a: var(--wp--preset--color--tertiary);    --jh-accent-b: var(--wp--preset--color--secondary); }

/* Decorative floating shapes / dots — purely cosmetic, aria-hidden in markup */
.jhilik-labs-shapes { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 0; }
.jhilik-labs-shape {
	position: absolute;
	border-radius: 50%;
	opacity: 0.5;
	background: radial-gradient(circle at 32% 30%, var(--jh-shape-color, var(--jh-accent-a)), transparent 72%);
	will-change: transform;
}
.jhilik-labs-dot {
	position: absolute;
	width: 9px;
	height: 9px;
	border-radius: 50%;
	background: var(--jh-shape-color, var(--jh-accent-b));
	opacity: 0.6;
}
.jhilik-labs-hero,
.jhilik-labs-panel { position: relative; overflow: hidden; }

/* Fixed ambient variant — used on hand-authored pages (About/CV/Contact/
   Insights) via wp_body_open(), so their color personality shows up
   without editing their stored content. Sits behind everything, never
   intercepts clicks or scrolls with the page. */
.jhilik-labs-shapes--fixed {
	position: fixed;
	inset: 0;
	overflow: hidden;
	pointer-events: none;
	z-index: 0;
}
.jhilik-labs-hero > *:not(.jhilik-labs-shapes),
.jhilik-labs-panel > *:not(.jhilik-labs-shapes) { position: relative; z-index: 1; }

/* Hero-style intro panel for secondary pages */
.jhilik-labs-hero {
	padding: clamp(2.25rem, 5vw, 3.75rem) clamp(1.5rem, 3vw, 2.5rem);
	border-radius: var(--jh-radius-xl);
	background: linear-gradient(135deg, color-mix(in srgb, var(--jh-accent-a) 16%, #ffffff), color-mix(in srgb, var(--jh-accent-b) 14%, #ffffff));
	margin-bottom: clamp(2rem, 4vw, 3rem);
}
.jhilik-labs-hero h1 { margin: 0.5rem 0 0.75rem; }
.jhilik-labs-hero .jhilik-lead { max-width: 62ch; }

/* Filter chip row (Tools directory, and reusable elsewhere) */
.jhilik-chip-row { display: flex; flex-wrap: wrap; gap: 0.6rem; margin: 0 0 clamp(1.5rem, 3vw, 2.25rem); }
.jhilik-chip {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.55rem 1.15rem;
	border-radius: 999px;
	border: 1.5px solid rgba(21, 27, 51, 0.14);
	background: #ffffff;
	font-family: var(--wp--preset--font-family--sans);
	font-size: 0.88rem;
	font-weight: 600;
	color: var(--jh-ink-soft);
	cursor: pointer;
	transition: transform 0.18s ease, background 0.18s ease, color 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
}
.jhilik-chip:hover { transform: translateY(-2px); box-shadow: var(--jh-shadow-sm); }
.jhilik-chip[aria-pressed="true"] {
	background: var(--jh-accent-a);
	border-color: transparent;
	color: var(--wp--preset--color--contrast);
}
.jhilik-chip:focus-visible { outline: 2px solid var(--jh-accent-a); outline-offset: 2px; }

/* Labs experiment card — large radius, per-card accent, icon chip, badge */
.jhilik-labs-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
	gap: clamp(1.25rem, 2.5vw, 1.75rem);
}
.jhilik-labs-card {
	--jh-card-accent: var(--jh-accent-a);
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 0.85rem;
	height: 100%;
	padding: clamp(1.5rem, 2.5vw, 2rem);
	background: #ffffff;
	border: var(--jh-line);
	border-radius: var(--jh-radius-lg);
	box-shadow: var(--jh-shadow-sm);
	overflow: hidden;
	transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.3, 1), box-shadow 0.3s ease;
}
.jhilik-labs-card::before {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 6px;
	background: linear-gradient(90deg, var(--jh-card-accent), color-mix(in srgb, var(--jh-card-accent) 40%, var(--jh-accent-b)));
}
.jhilik-labs-card:hover { transform: translateY(-6px); box-shadow: var(--jh-shadow-lg); }
.jhilik-labs-card--wide { grid-column: span 2; }
.jhilik-labs-card--tall { justify-content: space-between; }
.jhilik-labs-card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.75rem; }
.jhilik-labs-card__icon {
	width: 44px;
	height: 44px;
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 15px;
	font-size: 1.35rem;
	background: color-mix(in srgb, var(--jh-card-accent) 22%, #ffffff);
}
.jhilik-labs-card h3 { margin: 0; }
.jhilik-labs-card__purpose { margin: 0; color: var(--jh-ink-soft); font-size: 0.975rem; }
.jhilik-labs-card__actions { margin-top: auto; display: flex; gap: 0.65rem; flex-wrap: wrap; padding-top: 0.5rem; }
.jhilik-labs-card__actions a {
	font-weight: 600;
	font-size: 0.9rem;
	text-decoration: none;
	color: var(--wp--preset--color--primary);
}
.jhilik-labs-card__actions a.jhilik-labs-card__try {
	padding: 0.5rem 1.05rem;
	border-radius: 999px;
	background: var(--jh-card-accent);
	color: var(--wp--preset--color--contrast);
}
.jhilik-labs-card__actions a::after { content: " \2192"; }

/* Labs-skinned status badge (colorful variant of .jhilik-status-pill) */
.jhilik-labs-badge {
	display: inline-block;
	padding: 0.3rem 0.75rem;
	font-size: 0.68rem;
	font-weight: 700;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	border-radius: 999px;
	white-space: nowrap;
	color: var(--wp--preset--color--contrast);
	background: color-mix(in srgb, var(--jh-card-accent, var(--jh-accent-a)) 38%, #ffffff);
}

/* Scroll-reveal utility (JS toggles .is-visible; no-JS/reduced-motion = always visible) */
.jhilik-reveal-on-scroll { opacity: 1; }

/* Motion keyframes — gated exactly like section 17: only assigned inside
   prefers-reduced-motion:no-preference, never on by default. */
@keyframes jhilik-float     { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes jhilik-drift     { 0%, 100% { transform: translate(0, 0) rotate(0deg); } 50% { transform: translate(16px, -20px) rotate(9deg); } }
@keyframes jhilik-wiggle    { 0%, 100% { transform: rotate(0deg); } 30% { transform: rotate(-10deg); } 70% { transform: rotate(10deg); } }
@keyframes jhilik-pulse-soft { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } }
@keyframes jhilik-pulse-ring { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--jh-accent-a) 45%, transparent); } 100% { box-shadow: 0 0 0 16px color-mix(in srgb, var(--jh-accent-a) 0%, transparent); } }
@keyframes jhilik-reveal-up { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }

@media (prefers-reduced-motion: no-preference) {
	.jhilik-labs-shape { animation: jhilik-drift var(--jh-drift-dur, 10s) ease-in-out infinite; }
	.jhilik-labs-dot { animation: jhilik-pulse-soft var(--jh-pulse-dur, 4.5s) ease-in-out infinite; }
	.jhilik-labs-card:hover .jhilik-labs-card__icon { animation: jhilik-wiggle 0.6s ease; }
	.jhilik-labs-upload-zone.is-dragover { animation: jhilik-pulse-ring 1.3s ease-out infinite; }
	.jhilik-reveal-on-scroll {
		opacity: 0;
		transform: translateY(16px);
		/* --reveal-i: set by labs.js initReveal() to each item's index
		   among its reveal-on-scroll siblings, so a card group cascades
		   in with a subtle stagger instead of all appearing at once. */
		transition: opacity 0.6s ease calc(var(--reveal-i, 0) * 70ms), transform 0.6s ease calc(var(--reveal-i, 0) * 70ms);
	}
	.jhilik-reveal-on-scroll.is-visible { opacity: 1; transform: translateY(0); }
}

@media (max-width: 720px) {
	.jhilik-labs-grid { grid-template-columns: 1fr; }
	.jhilik-labs-card--wide { grid-column: span 1; }
	.jhilik-labs-hero { border-radius: var(--jh-radius-lg); }
}

/* 22. Tools directory — experiment listing ---------------------------- */

.jhilik-tools-directory .jhilik-archive-head { max-width: 68ch; }

/* Each card gets a unique accent, rotating through the Tools area's three
   personality colors — no manual per-tool color assignment needed. Grid
   items are <li> (core/post-template's own markup); the accent-bearing
   card is the sole child inside each, so the rotation is keyed off the
   <li> position, not the card div itself. */
.jhilik-tools-directory .jhilik-labs-grid > li:nth-of-type(3n+1) .jhilik-labs-card { --jh-card-accent: var(--jh-accent-a); }
.jhilik-tools-directory .jhilik-labs-grid > li:nth-of-type(3n+2) .jhilik-labs-card { --jh-card-accent: var(--jh-accent-b); }
.jhilik-tools-directory .jhilik-labs-grid > li:nth-of-type(3n+3) .jhilik-labs-card { --jh-card-accent: var(--jh-accent-c); }
.jhilik-labs-card--tools .jhilik-labs-card__icon { background: color-mix(in srgb, var(--jh-card-accent) 24%, #ffffff); }
/* the query-loop <ul> itself carries .jhilik-labs-grid + needs display:grid,
   same convention as the existing .jhilik-archive-grid usage elsewhere. */
ul.jhilik-labs-grid { list-style: none; padding: 0; margin: 0; }
.jhilik-labs-card .jhilik-status-pill { font-size: 0.7rem; }
.jhilik-labs-card > .jhilik-meta-field { display: block; color: var(--jh-ink-soft); font-size: 0.96rem; }
.jhilik-labs-card .wp-block-post-excerpt { margin: 0; }
.jhilik-labs-card .wp-block-post-excerpt p { margin: 0; color: var(--jh-ink-soft); font-size: 0.975rem; }
.jhilik-labs-card .wp-block-post-excerpt__more-link {
	display: inline-block;
	margin-top: 0.5rem;
	font-weight: 600;
	font-size: 0.88rem;
	text-decoration: none;
	color: var(--wp--preset--color--primary);
}
.jhilik-labs-card .wp-block-post-excerpt__more-link::after { content: " \2192"; }

/* 23. Tool shell (shared) — one consistent base for all three public
   tools (Image -> Prompt, DOI Citation Finder, Search Readiness Checker),
   each still free to add its own inner classes on top. ----------------- */

.jhilik-tool-shell { display: flex; flex-direction: column; gap: clamp(1.5rem, 3vw, 2rem); }

.jhilik-tool-shell__form {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
	padding: 1.1rem 1.2rem;
	border-radius: var(--jh-radius);
	background: color-mix(in srgb, var(--jh-tool-accent-a, var(--wp--preset--color--secondary)) 12%, #fff);
	border: 1px solid color-mix(in srgb, var(--jh-tool-accent-a, var(--wp--preset--color--secondary)) 26%, transparent);
}
.jhilik-tool-shell__label { font-weight: 600; font-size: 0.92rem; }
.jhilik-tool-shell__input-row { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.jhilik-tool-shell__input {
	flex: 1 1 280px;
	min-width: 0;
	padding: 0.75rem 1rem;
	font-size: 1rem;
	border: 1.5px solid color-mix(in srgb, var(--jh-tool-accent-a, var(--wp--preset--color--secondary)) 30%, var(--border));
	border-radius: var(--jh-radius-sm);
	font-family: inherit;
	background: #fff;
	transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.jhilik-tool-shell__button {
	padding: 0.75rem 1.5rem;
	border: 0;
	border-radius: var(--jh-radius-sm);
	background: var(--wp--preset--color--primary);
	color: #fff;
	font-weight: 700;
	cursor: pointer;
	white-space: nowrap;
	box-shadow: var(--jh-shadow-sm);
	transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.jhilik-tool-shell__button:hover:not(:disabled) { transform: translateY(-2px); box-shadow: var(--jh-shadow-md); }
.jhilik-tool-shell__button--secondary {
	background: color-mix(in srgb, #fff 82%, var(--jh-tool-accent-a, var(--wp--preset--color--secondary)));
	border: 1.5px solid color-mix(in srgb, var(--jh-tool-accent-a, var(--wp--preset--color--secondary)) 35%, var(--border));
	color: var(--wp--preset--color--contrast);
	box-shadow: none;
}
.jhilik-tool-shell__button--secondary:hover:not(:disabled) { box-shadow: var(--jh-shadow-sm); }
.jhilik-tool-shell__button.is-confirmed { background: var(--jh-success); border-color: var(--jh-success); color: #fff; transition: background-color 0.2s ease, color 0.2s ease; }
.jhilik-tool-shell__status { min-height: 1.4em; font-size: 0.92rem; color: var(--jh-ink-soft); }
.jhilik-tool-shell__status.is-error { color: var(--jh-danger-text); font-weight: 600; }

.jhilik-tool-shell__unavailable {
	padding: clamp(1.75rem, 4vw, 2.5rem);
	text-align: center;
	background: color-mix(in srgb, var(--wp--preset--color--tertiary) 40%, #fff);
	border-radius: var(--jh-radius);
	font-size: 0.98rem;
}

.jhilik-tool-shell__output {
	position: relative;
	padding: 1.1rem 1.35rem;
	border-radius: var(--jh-radius-sm);
	background: color-mix(in srgb, var(--jh-tool-accent-a, var(--wp--preset--color--secondary)) 14%, #fff);
	border: var(--jh-line);
}
.jhilik-tool-shell__output-label { margin: 0 0 0.5rem; font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--jh-ink-soft); }
.jhilik-tool-shell__output-text { margin: 0 0 0.9rem; white-space: pre-wrap; word-break: break-word; line-height: 1.55; }
.jhilik-tool-shell__copy-confirm { margin-left: 0.75rem; font-size: 0.85rem; opacity: 0; transition: opacity 0.25s ease; }
.jhilik-tool-shell__copy-confirm.is-shown { opacity: 1; }

@media (max-width: 640px) {
	.jhilik-tool-shell__input-row { flex-direction: column; }
	/* flex-basis (set via the `flex` shorthand for the row layout) applies
	   to height once flex-direction switches to column — without this
	   override the input inflates to ~280px tall on mobile. */
	.jhilik-tool-shell__input { flex: 1 1 auto; width: 100%; }
	.jhilik-tool-shell__button { width: 100%; }
}

/* DOI Citation Finder */
.jhilik-doi-result__title { margin: 0 0 0.3rem; }
.jhilik-doi-result__meta { margin: 0 0 0.5rem; color: var(--jh-ink-soft); font-size: 0.92rem; }
.jhilik-doi-result__doi { margin: 0 0 1.1rem; font-size: 0.88rem; word-break: break-all; }

/*
 * Per-tool subtle identity — a pastel surface/icon tint only. Primary
 * action buttons stay the site's consistent primary blue for contrast and
 * cross-tool consistency; only the icon badge, output panel, focus ring,
 * and chips pick up each tool's own accent pair.
 */
.jhilik-tool-shell {
	--jh-tool-accent-a: var(--wp--preset--color--secondary);
	--jh-tool-accent-b: var(--wp--preset--color--secondary);
}
.jhilik-prompt-finder { --jh-tool-accent-a: var(--wp--preset--color--blush); --jh-tool-accent-b: var(--wp--preset--color--secondary); }
.jhilik-doi-finder { --jh-tool-accent-a: var(--wp--preset--color--mint); --jh-tool-accent-b: var(--wp--preset--color--secondary); }
.jhilik-tool-shell--search-readiness { --jh-tool-accent-a: var(--wp--preset--color--accent); --jh-tool-accent-b: var(--wp--preset--color--secondary); }

.jhilik-tool-shell__icon-badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 42px;
	height: 42px;
	border-radius: 13px;
	font-size: 1.3rem;
	margin-bottom: 0.6rem;
	background: linear-gradient(135deg, color-mix(in srgb, var(--jh-tool-accent-a) 60%, #fff), color-mix(in srgb, var(--jh-tool-accent-b) 45%, #fff));
}

.jhilik-tool-shell__input:focus-visible,
.jhilik-tool-shell__input:focus {
	outline: none;
	border-color: color-mix(in srgb, var(--jh-tool-accent-a) 65%, var(--border));
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--jh-tool-accent-a) 28%, transparent);
}

/* Compact "can't run this" / "not found" notice — a short line, not a
   giant empty panel. */
.jhilik-tool-shell__unavailable {
	padding: 0.9rem 1.1rem;
	background: color-mix(in srgb, var(--jh-tool-accent-a) 20%, #fff);
	border-radius: var(--jh-radius-sm);
	font-size: 0.92rem;
	text-align: left;
}

.jhilik-tool-shell__privacy-note {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	margin: 0;
	padding: 0.3rem 0.7rem;
	border-radius: 999px;
	background: color-mix(in srgb, var(--jh-tool-accent-a) 25%, #fff);
	font-size: 0.78rem;
	font-weight: 600;
	color: var(--jh-ink-soft);
	width: fit-content;
}
.jhilik-tool-shell__privacy-note::before { content: "\1F512"; font-size: 0.85em; }

.jhilik-tool-shell__first-use-note {
	margin: 0;
	font-size: 0.82rem;
	color: var(--jh-ink-soft);
}

/* Search Readiness Checker */
.jhilik-sr-summary { margin: 0 0 1.25rem; font-size: 0.92rem; color: var(--jh-ink-soft); word-break: break-word; }
.jhilik-search-readiness__result { display: flex; flex-direction: column; gap: 1.25rem; }
.jhilik-sr-group { border-radius: var(--jh-radius-sm); padding: 1rem 1.25rem; border-left: 3px solid transparent; }
.jhilik-sr-group--found { background: color-mix(in srgb, var(--wp--preset--color--mint) 22%, #fff); border-left-color: color-mix(in srgb, var(--wp--preset--color--mint) 70%, var(--jh-success)); }
.jhilik-sr-group--attention { background: color-mix(in srgb, var(--jh-warning-tint) 55%, #fff); border-left-color: var(--jh-warning); }
.jhilik-sr-group--missing { background: color-mix(in srgb, var(--wp--preset--color--agent-joyee) 22%, var(--wp--preset--color--blush)); border-left-color: color-mix(in srgb, var(--wp--preset--color--agent-joyee) 75%, var(--jh-danger-text)); }
.jhilik-sr-group__title { margin: 0 0 0.7rem; font-size: 0.95rem; display: flex; align-items: center; gap: 0.5rem; }
.jhilik-sr-group__count { font-size: 0.72rem; font-weight: 700; padding: 0.1rem 0.5rem; border-radius: 999px; background: rgba(21, 27, 51, 0.08); }
.jhilik-sr-group__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.jhilik-sr-row { display: flex; flex-direction: column; gap: 0.15rem; font-size: 0.9rem; padding: 0.4rem 0; border-bottom: 1px solid rgba(21, 27, 51, 0.06); }
.jhilik-sr-row:last-child { border-bottom: 0; padding-bottom: 0; }
.jhilik-sr-row__label { font-weight: 600; }
.jhilik-sr-row__detail { font-size: 0.82rem; color: var(--jh-ink-soft); word-break: break-word; }

/* 24. Image Prompt Finder ---------------------------------------------- */
/* Google Labs / Flow-style mini-product: cream base, soft pastel surfaces,
   a subtle aurora glow behind the active workspace, tactile controls. No
   dark SaaS cards anywhere in this tool. */

.jhilik-prompt-finder {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: clamp(1.75rem, 3vw, 2.5rem);
}
/* Aurora glow — a fixed, non-interactive backdrop behind the whole
   workspace. transform/opacity are the only animated properties. */
.jhilik-prompt-finder::before {
	content: "";
	position: absolute;
	inset: -10% -6% auto -6%;
	height: 260px;
	background:
		radial-gradient(circle at 15% 20%, color-mix(in srgb, var(--wp--preset--color--secondary) 55%, transparent), transparent 60%),
		radial-gradient(circle at 55% 10%, color-mix(in srgb, var(--wp--preset--color--blush) 50%, transparent), transparent 55%),
		radial-gradient(circle at 85% 30%, color-mix(in srgb, var(--wp--preset--color--mint) 45%, transparent), transparent 55%);
	filter: blur(2px);
	opacity: 0.8;
	z-index: -1;
	pointer-events: none;
}

.jhilik-labs-upload-zone {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.6rem;
	padding: clamp(2rem, 5vw, 3rem) 1.5rem;
	text-align: center;
	border: 2.5px dashed color-mix(in srgb, var(--jh-tool-accent-a, var(--jh-accent-a)) 45%, rgba(21, 27, 51, 0.2));
	border-radius: var(--jh-radius-lg);
	background: color-mix(in srgb, #fff 88%, var(--jh-tool-accent-a, var(--jh-accent-a)));
	cursor: pointer;
	transition: border-color 0.2s ease, background 0.2s ease, transform 0.2s ease;
}
.jhilik-labs-upload-zone:hover,
.jhilik-labs-upload-zone.is-dragover {
	border-color: var(--jh-tool-accent-a, var(--jh-accent-a));
	background: color-mix(in srgb, var(--jh-tool-accent-a, var(--jh-accent-a)) 16%, #fff);
	transform: translateY(-2px);
}
.jhilik-labs-upload-zone input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.jhilik-labs-upload-zone__icon { font-size: 2.25rem; }
.jhilik-labs-upload-zone button {
	pointer-events: none;
	padding: 0.6rem 1.3rem;
	border-radius: 999px;
	background: var(--wp--preset--color--primary);
	color: #fff;
	font-weight: 700;
	border: 0;
	box-shadow: var(--jh-shadow-sm);
}

.jhilik-prompt-preview { display: grid; grid-template-columns: minmax(220px, 340px) 1fr; gap: clamp(1.5rem, 3vw, 2.25rem); align-items: start; }
.jhilik-prompt-preview__image { border-radius: var(--jh-radius-sm); overflow: hidden; box-shadow: var(--jh-shadow-sm); border: var(--jh-line); }
.jhilik-prompt-preview__image img { display: block; width: 100%; height: auto; }

.jhilik-prompt-builder { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 0.9rem; }
.jhilik-prompt-builder label { display: flex; flex-direction: column; gap: 0.35rem; font-size: 0.85rem; font-weight: 600; color: var(--jh-ink-soft); }
.jhilik-prompt-builder select,
.jhilik-prompt-builder input,
.jhilik-prompt-builder textarea {
	padding: 0.6rem 0.85rem;
	border-radius: 12px;
	border: 1.5px solid color-mix(in srgb, var(--jh-tool-accent-a, var(--jh-accent-a)) 30%, var(--border));
	background: #fff;
	font-size: 0.92rem;
	font-family: inherit;
	transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.jhilik-prompt-builder select:focus-visible,
.jhilik-prompt-builder select:focus {
	outline: none;
	border-color: var(--jh-tool-accent-a, var(--jh-accent-a));
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--jh-tool-accent-a, var(--jh-accent-a)) 28%, transparent);
}
.jhilik-prompt-style-row { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.jhilik-prompt-style-row #jhilik-ip-generate {
	background: var(--wp--preset--color--primary);
	color: #fff;
	border: 0;
	border-radius: 999px;
	padding: 0.65rem 1.4rem;
	font-weight: 700;
	cursor: pointer;
	box-shadow: var(--jh-shadow-sm);
	transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.jhilik-prompt-style-row #jhilik-ip-generate:hover:not(:disabled) { transform: translateY(-2px); box-shadow: var(--jh-shadow-md); }
.jhilik-prompt-style-row #jhilik-ip-generate:disabled { opacity: 0.55; cursor: default; transform: none; }
.jhilik-prompt-style-row .jhilik-tool-shell__button--secondary {
	background: color-mix(in srgb, #fff 85%, var(--jh-tool-accent-a, var(--jh-accent-a)));
	color: var(--jh-ink, #232430);
	border: 1.5px solid color-mix(in srgb, var(--jh-tool-accent-a, var(--jh-accent-a)) 35%, var(--border));
	border-radius: 999px;
	padding: 0.65rem 1.3rem;
	font-weight: 600;
	cursor: pointer;
}

/* Stable-height loading card — one card, text/bar updated in place, never
   re-mounted. This is the direct fix for the previous flickering plain-text
   status line: fixed min-height so nothing shifts as the stage changes. */
.jhilik-ip-loader {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.9rem;
	min-height: 190px;
	padding: 2rem 1.5rem;
	border-radius: var(--jh-radius-lg);
	text-align: center;
	background: linear-gradient(160deg, color-mix(in srgb, var(--jh-tool-accent-a, var(--jh-accent-a)) 18%, #fff), color-mix(in srgb, var(--jh-tool-accent-b, var(--jh-tool-accent-a)) 14%, #fff));
	box-shadow: var(--jh-shadow-sm);
}
.jhilik-ip-loader__orb {
	position: relative;
	width: 52px;
	height: 52px;
}
.jhilik-ip-loader__orb span {
	position: absolute;
	inset: 0;
	border-radius: 50%;
	background: conic-gradient(from 0deg, var(--wp--preset--color--secondary), var(--wp--preset--color--blush), var(--wp--preset--color--accent), var(--wp--preset--color--secondary));
	opacity: 0.85;
}
.jhilik-ip-loader__orb span:nth-child(2) { inset: 10px; opacity: 0.7; filter: blur(0.5px); }
.jhilik-ip-loader__orb span:nth-child(3) { inset: 21px; background: #fff; opacity: 0.9; }
@media (prefers-reduced-motion: no-preference) {
	.jhilik-ip-loader__orb span:nth-child(1) { animation: jhilik-orb-spin 3.2s linear infinite; }
	.jhilik-ip-loader__orb span:nth-child(2) { animation: jhilik-orb-spin 4.5s linear infinite reverse; }
}
@keyframes jhilik-orb-spin { to { transform: rotate(360deg); } }

.jhilik-ip-loader__stage { margin: 0; font-weight: 700; font-size: 0.98rem; min-height: 1.3em; }
.jhilik-ip-loader__bar-track {
	width: min(280px, 100%);
	height: 8px;
	border-radius: 999px;
	background: color-mix(in srgb, var(--jh-tool-accent-a, var(--jh-accent-a)) 20%, #fff);
	overflow: hidden;
	position: relative;
}
.jhilik-ip-loader__bar-fill {
	height: 100%;
	width: 0%;
	border-radius: 999px;
	background: linear-gradient(90deg, var(--wp--preset--color--secondary), var(--wp--preset--color--primary));
	transition: width 0.35s ease;
}
.jhilik-ip-loader__bar-fill.is-indeterminate {
	width: 40% !important;
	animation: none;
	position: absolute;
	background: linear-gradient(90deg, transparent, var(--wp--preset--color--primary), transparent);
}
@media (prefers-reduced-motion: no-preference) {
	.jhilik-ip-loader__bar-fill.is-indeterminate { animation: jhilik-bar-sweep 1.6s ease-in-out infinite; }
}
@keyframes jhilik-bar-sweep {
	0% { left: -40%; }
	100% { left: 100%; }
}
.jhilik-ip-loader__percent { margin: 0; font-size: 0.8rem; color: var(--jh-ink-soft); min-height: 1.2em; }

/* Result card — a light pastel surface (never a dark SaaS card), with a
   short settle-in animation the first time a result appears. */
.jhilik-prompt-output {
	position: relative;
	padding: 1.4rem 1.6rem;
	border-radius: var(--jh-radius);
	background: color-mix(in srgb, var(--jh-tool-accent-a, var(--jh-accent-a)) 14%, #fff);
	border: 1px solid color-mix(in srgb, var(--jh-tool-accent-a, var(--jh-accent-a)) 30%, transparent);
	box-shadow: var(--jh-shadow-sm);
	color: var(--jh-ink, #232430);
}
.jhilik-prompt-output pre { margin: 0 0 1.1rem; white-space: pre-wrap; word-break: break-word; font-family: var(--wp--preset--font-family--sans); font-size: 0.96rem; line-height: 1.6; }
.jhilik-prompt-output__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; }
.jhilik-prompt-output button {
	padding: 0.55rem 1.15rem;
	border-radius: 999px;
	border: 0;
	font-weight: 700;
	cursor: pointer;
	transition: transform 0.18s ease, box-shadow 0.18s ease;
}
#jhilik-ip-copy { background: var(--wp--preset--color--primary); color: #fff; box-shadow: var(--jh-shadow-sm); }
#jhilik-ip-copy:hover { transform: translateY(-2px); box-shadow: var(--jh-shadow-md); }
#jhilik-ip-copy.is-confirmed { background: var(--jh-success); transition: background-color 0.2s ease; }
.jhilik-prompt-output .jhilik-tool-shell__button--secondary {
	background: color-mix(in srgb, #fff 80%, var(--jh-tool-accent-a, var(--jh-accent-a)));
	color: var(--jh-ink, #232430);
	border: 1.5px solid color-mix(in srgb, var(--jh-tool-accent-a, var(--jh-accent-a)) 35%, var(--border));
}
.jhilik-prompt-output .jhilik-copy-confirm { font-size: 0.85rem; font-weight: 600; color: var(--jh-success); opacity: 0; transition: opacity 0.25s ease; }
.jhilik-prompt-output .jhilik-copy-confirm.is-shown { opacity: 1; }

@media (prefers-reduced-motion: no-preference) {
	.jhilik-prompt-output.is-settling {
		animation: jhilik-result-settle 0.5s cubic-bezier(0.2, 0.8, 0.2, 1) both;
	}
}
@keyframes jhilik-result-settle {
	from { opacity: 0; transform: translateY(8px); box-shadow: 0 0 0 8px color-mix(in srgb, var(--jh-tool-accent-a, var(--jh-accent-a)) 25%, transparent); }
	to { opacity: 1; transform: translateY(0); box-shadow: var(--jh-shadow-sm); }
}

@media (max-width: 780px) {
	.jhilik-prompt-preview { grid-template-columns: 1fr; }
}

/* 25. Site-wide secondary-page personality (Research/Portfolio/Videos) - */

.jhilik-labs-area--research .jhilik-research-card { border-left-color: var(--jh-accent-a); }
.jhilik-research-card .jhilik-imgslot {
	margin: calc(clamp(1.4rem, 2.2vw, 1.8rem) * -1) calc(clamp(1.4rem, 2.2vw, 1.8rem) * -1) 1rem;
	width: calc(100% + clamp(2.8rem, 4.4vw, 3.6rem));
	border-radius: var(--jh-radius-sm) var(--jh-radius-sm) 0 0;
	border-width: 0 0 1px 0;
}
.jhilik-cpt-single--research .jhilik-imgslot { margin-block: 1.25rem; }
/* This is the main document image on the single research page, not a
   thumbnail — the fixed 4:3 slot box was built for a landscape photo and
   letterboxes a real (portrait) certificate badly. height:auto lets the
   slot follow the certificate's own aspect ratio instead, so it renders
   at a natural, fully-legible size with no forced crop or excess
   whitespace either side. */
.jhilik-cpt-single--research .jhilik-imgslot--research {
	aspect-ratio: auto;
	height: auto;
	max-width: 640px;
	margin-inline: auto;
}
.jhilik-cpt-single--research .jhilik-imgslot--research img {
	position: static;
	width: 100%;
	height: auto;
}
.jhilik-labs-area--portfolio .jhilik-portfolio-card__thumb {
	background: linear-gradient(135deg, color-mix(in srgb, var(--jh-accent-a) 26%, #ffffff), color-mix(in srgb, var(--jh-accent-b) 24%, #ffffff));
}
.jhilik-labs-area--portfolio .jhilik-portfolio-card__body > .jhilik-meta-field { color: var(--jh-accent-a); }
.jhilik-labs-area--videos .jhilik-video-card__frame {
	background: linear-gradient(135deg, color-mix(in srgb, var(--jh-accent-a) 30%, #ffffff), color-mix(in srgb, var(--jh-accent-b) 26%, #ffffff));
}
.jhilik-labs-area--videos .jhilik-video-card > .jhilik-meta-field { color: var(--jh-accent-a); }

/* 26. Navigation redesign — superseded. The header no longer uses
   core/navigation at all (see parts/header.html and the "Header" section
   near the top of this file): three-item primary nav, an Explore
   disclosure panel, and a custom mobile overlay, all hand-built. This
   keyframe is the one piece still shared with that new mobile panel. */
@keyframes jhilik-nav-panel-in {
	from { opacity: 0; transform: translateY(-10px) scale(0.98); }
	to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* 27. Reusable image-slot system --------------------------------------- */
/*
   Looks intentional and finished even with nothing in it yet — never a
   broken-image icon or a flat grey box. Dimensions are reserved via
   aspect-ratio so nothing shifts (CLS) once a real image is added later.
*/

.jhilik-imgslot {
	position: relative;
	display: block;
	width: 100%;
	overflow: hidden;
	border-radius: var(--jh-radius);
	border: var(--jh-line);
	background: linear-gradient(135deg, color-mix(in srgb, var(--jh-accent-a) 22%, #fff), color-mix(in srgb, var(--jh-accent-b, var(--jh-accent-a)) 18%, #fff));
}
.jhilik-imgslot img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
.jhilik-imgslot--portrait { aspect-ratio: 3 / 4; }
.jhilik-imgslot--banner { aspect-ratio: 21 / 9; }
.jhilik-imgslot--square { aspect-ratio: 1 / 1; }
.jhilik-imgslot--certificate { aspect-ratio: 4 / 3; }
.jhilik-imgslot--screenshot { aspect-ratio: 16 / 10; }
.jhilik-imgslot--research { aspect-ratio: 4 / 3; }
.jhilik-imgslot--landscape { aspect-ratio: 4 / 3; }
.jhilik-imgslot--wide { aspect-ratio: 16 / 9; }
.jhilik-imgslot--article { aspect-ratio: 16 / 9; }

/* A certificate is a document, not a photo — cropping it with cover risks
   cutting off text/seals at the edges. contain + a plain white backing
   keeps the whole certificate legible even when its own aspect ratio
   doesn't exactly match the slot. The "research" variant gets the same
   treatment: every research post currently uses its publication/
   presentation certificate as the featured image, so it's a document
   slot in practice, not a photo slot — cover was cutting off roughly
   half of the certificate's height. */
.jhilik-imgslot--certificate img,
.jhilik-imgslot--research img { object-fit: contain; background: #fff; }
.jhilik-imgslot--certificate,
.jhilik-imgslot--research { background: #fff; }

/* 35. Research-in-action mosaic (real event/conference photography, used
   to illustrate research activity in general — never presented as the
   visual for one specific paper). Mixed portrait/landscape proportions
   via the existing per-image .jhilik-imgslot--portrait/--landscape
   classes; auto-fit means 4-6 photos lay out sensibly without a fixed
   column count that would force empty tracks. */
.jhilik-research-mosaic {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
	gap: clamp(1rem, 2vw, 1.5rem);
	margin: clamp(1.5rem, 3vw, 2.25rem) 0;
}
.jhilik-research-mosaic .jhilik-imgslot { margin: 0; }

.jhilik-imgslot.is-empty { box-shadow: inset 0 0 0 1px rgba(21, 27, 51, 0.04); }
.jhilik-imgslot.is-empty::before {
	content: "";
	position: absolute;
	inset: 0;
	background-image: radial-gradient(circle, color-mix(in srgb, var(--jh-accent-a) 40%, transparent) 1.5px, transparent 1.5px);
	background-size: 18px 18px;
	opacity: 0.35;
}
.jhilik-imgslot.is-empty::after {
	content: "";
	position: absolute;
	width: 46%;
	height: 46%;
	max-width: 140px;
	max-height: 140px;
	border-radius: 50%;
	top: 50%;
	left: 50%;
	translate: -50% -60%;
	background: radial-gradient(circle at 35% 32%, color-mix(in srgb, var(--jh-accent-a) 50%, #fff), transparent 72%);
	opacity: 0.7;
}
.jhilik-imgslot__label {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: flex-end;
	justify-content: center;
	padding-bottom: 14%;
	z-index: 1;
	font-family: var(--wp--preset--font-family--sans);
	font-size: 0.85rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: color-mix(in srgb, var(--jh-accent-a) 65%, var(--wp--preset--color--contrast));
}
.jhilik-imgslot__caption {
	display: block;
	margin-top: 0.6rem;
	font-size: 0.85rem;
	color: var(--jh-ink-soft);
	text-align: center;
}
@media (prefers-reduced-motion: no-preference) {
	.jhilik-imgslot.is-empty::after { animation: jhilik-float 7s ease-in-out infinite; }
}

/* 28. About page layout ------------------------------------------------- */

.jhilik-about-intro {
	display: grid;
	grid-template-columns: minmax(0, 1.1fr) minmax(240px, 0.9fr);
	gap: clamp(2rem, 4vw, 3.5rem);
	align-items: center;
	margin-bottom: clamp(2.5rem, 5vw, 4rem);
}
.jhilik-about-intro__text h1 { margin: 0.4rem 0 1rem; }
.jhilik-about-intro__image .jhilik-imgslot { max-width: 420px; margin-inline: auto; }

.jhilik-about-section {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(220px, 0.7fr);
	gap: clamp(1.75rem, 3.5vw, 3rem);
	align-items: center;
	padding-block: clamp(2rem, 4vw, 3rem);
	border-top: var(--jh-line);
}
.jhilik-about-section:first-of-type { border-top: none; }
.jhilik-about-section--reverse { grid-template-columns: minmax(220px, 0.7fr) minmax(0, 1fr); }
.jhilik-about-section--reverse .jhilik-about-section__visual { order: -1; }
/* Single-column text flow, not a two-column split — the parent's gap
   (sized for separating a text column from a visual column) would
   otherwise stack on top of each child's own margin between every
   heading/paragraph, since grid items never collapse margins with the
   gap the way normal flow siblings do. Prose-appropriate rhythm instead. */
.jhilik-about-section--text-only { grid-template-columns: 1fr; max-width: 72ch; gap: 0; }

/* Real Community & Events photo strip (frontend repair) — mixed
   portrait/landscape via the existing per-image aspect classes, never
   forced into identical squares. */
.jhilik-about-community-strip {
	display: grid;
	width: 100%;
	grid-template-columns: repeat(3, 1fr);
	gap: 1rem;
	margin-top: 1.5rem;
	max-width: 72ch;
}
.jhilik-about-community-strip .jhilik-imgslot { min-width: 0; }
@media (max-width: 640px) {
	.jhilik-about-community-strip { grid-template-columns: 1fr 1fr; }
}
.jhilik-about-section h2 { margin: 0 0 0.85rem; }
.jhilik-about-section p { color: var(--jh-ink-soft); }

.jhilik-about-chips { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; }
.jhilik-about-chip {
	padding: 0.4rem 0.9rem;
	border-radius: 999px;
	font-size: 0.85rem;
	font-weight: 600;
	background: color-mix(in srgb, var(--jh-accent-a) 16%, #fff);
	color: var(--wp--preset--color--contrast);
}

.jhilik-about-quote {
	position: relative;
	padding: clamp(1.5rem, 3vw, 2rem);
	border-radius: var(--jh-radius);
	background: color-mix(in srgb, var(--jh-accent-b, var(--jh-accent-a)) 14%, #fff);
	font-size: 1.1rem;
	font-weight: 600;
	line-height: 1.5;
}
.jhilik-about-quote::before { content: "\201C"; font-size: 2.5rem; opacity: 0.35; line-height: 0; position: relative; top: 0.6rem; }

@media (max-width: 860px) {
	.jhilik-about-intro,
	.jhilik-about-section,
	.jhilik-about-section--reverse {
		grid-template-columns: 1fr !important;
	}
	.jhilik-about-section__visual { order: 0 !important; }
	.jhilik-about-intro__image .jhilik-imgslot { max-width: 320px; }
}

/* 29. CV, Profile & Certifications --------------------------------------- */

.jhilik-cv-hero {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(160px, 0.4fr);
	gap: clamp(1.5rem, 3vw, 2.5rem);
	align-items: center;
	padding-bottom: clamp(1.5rem, 3vw, 2.25rem);
	border-bottom: var(--jh-line);
	margin-bottom: clamp(1.25rem, 2.5vw, 1.75rem);
}
.jhilik-cv-hero__image .jhilik-imgslot { max-width: 220px; margin-inline: auto; }
.jhilik-cv-hero h1 { margin: 0.3rem 0 0.4rem; }
.jhilik-cv-hero__alias { font-weight: 500; opacity: 0.7; }
.jhilik-cv-hero__role { font-weight: 600; color: var(--jh-ink-soft); margin: 0 0 0.6rem; }

.jhilik-cv-hero__chips { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.9rem 0; }
.jhilik-cv-chip {
	padding: 0.32rem 0.85rem;
	border-radius: 999px;
	background: color-mix(in srgb, var(--wp--preset--color--secondary) 30%, #fff);
	font-size: 0.8rem;
	font-weight: 600;
	color: var(--wp--preset--color--primary);
	transition: transform 0.16s ease, box-shadow 0.16s ease;
}
@media (prefers-reduced-motion: no-preference) {
	.jhilik-cv-chip:hover { transform: translateY(-1px); box-shadow: var(--jh-shadow-sm); }
}
/* Each topic chip gets its own restrained pastel identity instead of one
   flat repeated blue — a soft tint background with darker, readable text
   in the same hue family, never a saturated rainbow. */
.jhilik-cv-chip--ai { background: color-mix(in srgb, var(--wp--preset--color--accent) 38%, #fff); color: #4a3f73; }
.jhilik-cv-chip--seo { background: color-mix(in srgb, var(--wp--preset--color--secondary) 42%, #fff); color: var(--wp--preset--color--primary); }
.jhilik-cv-chip--wp { background: color-mix(in srgb, var(--wp--preset--color--mint) 42%, #fff); color: #1d5c4f; }
.jhilik-cv-chip--product { background: color-mix(in srgb, #F0C868 45%, var(--wp--preset--color--tertiary)); color: #7a5a1e; }
.jhilik-cv-chip--content { background: color-mix(in srgb, var(--wp--preset--color--blush) 48%, #fff); color: var(--jh-danger-text); }

.jhilik-cv-hero__actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 1.1rem; }
.jhilik-cv-action-btn {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.55rem 1.1rem;
	border-radius: 999px;
	font-size: 0.88rem;
	font-weight: 700;
	text-decoration: none;
	border: none;
	cursor: pointer;
	transition: transform 0.18s ease, box-shadow 0.18s ease;
	font-family: inherit;
}
.jhilik-cv-action-btn--primary { background: var(--wp--preset--color--primary); color: #fff; }
.jhilik-cv-action-btn--secondary { background: color-mix(in srgb, var(--wp--preset--color--secondary) 35%, #fff); color: var(--jh-ink, #232430); }
/* One small, distinct identity per action — Google-like tactile buttons,
   never four identical pills. */
.jhilik-cv-action-btn--download { background: color-mix(in srgb, var(--wp--preset--color--secondary) 70%, #fff); color: var(--wp--preset--color--primary); }
.jhilik-cv-action-btn--print { background: color-mix(in srgb, var(--wp--preset--color--accent) 55%, #fff); color: #3d3163; }
.jhilik-cv-action-btn--linkedin { background: color-mix(in srgb, var(--wp--preset--color--primary) 16%, var(--wp--preset--color--secondary)); color: var(--wp--preset--color--primary); }
.jhilik-cv-action-btn--contact { background: color-mix(in srgb, var(--wp--preset--color--blush) 65%, #fff); color: var(--jh-danger-text); }
.jhilik-cv-action-btn:hover, .jhilik-cv-action-btn:focus-visible { transform: translateY(-2px); box-shadow: var(--jh-shadow-sm); }
.jhilik-cv-action-btn:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }

.jhilik-cv-nav {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0 0 clamp(1.75rem, 3vw, 2.5rem);
	padding: 0.6rem 0;
}
.jhilik-cv-nav__chip {
	--jh-nav-chip-accent: var(--jh-accent-a);
	position: relative;
	padding: 0.4rem 0.95rem 0.55rem;
	border-radius: 999px;
	background: color-mix(in srgb, var(--jh-nav-chip-accent) 16%, #fff);
	border: 1px solid color-mix(in srgb, var(--jh-nav-chip-accent) 30%, transparent);
	font-size: 0.85rem;
	font-weight: 600;
	text-decoration: none;
	color: inherit;
	white-space: nowrap;
	transition: background 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}
.jhilik-cv-nav__chip:hover, .jhilik-cv-nav__chip:focus-visible { background: color-mix(in srgb, var(--jh-nav-chip-accent) 30%, #fff); transform: translateY(-1px); }
/* Alternating baby-color identity, one per section — matches that
   section's own pastel accent so the nav previews what's ahead. */
.jhilik-cv-nav__chip--summary { --jh-nav-chip-accent: var(--wp--preset--color--secondary); }
.jhilik-cv-nav__chip--experience { --jh-nav-chip-accent: var(--wp--preset--color--secondary); }
.jhilik-cv-nav__chip--research { --jh-nav-chip-accent: var(--wp--preset--color--accent); }
.jhilik-cv-nav__chip--projects { --jh-nav-chip-accent: var(--wp--preset--color--blush); }
.jhilik-cv-nav__chip--skills { --jh-nav-chip-accent: var(--wp--preset--color--mint); }
.jhilik-cv-nav__chip--community { --jh-nav-chip-accent: var(--wp--preset--color--agent-joyee); }
.jhilik-cv-nav__chip--education { --jh-nav-chip-accent: color-mix(in srgb, var(--wp--preset--color--secondary) 50%, var(--wp--preset--color--accent) 50%); }
/* Active section — stronger fill + a small underline dot, not just a
   color swap, so the current section is unambiguous at a glance. */
.jhilik-cv-nav__chip.is-active {
	background: color-mix(in srgb, var(--jh-nav-chip-accent) 55%, #fff);
	border-color: color-mix(in srgb, var(--jh-nav-chip-accent) 70%, transparent);
	font-weight: 700;
}
.jhilik-cv-nav__chip.is-active::after {
	content: "";
	position: absolute;
	bottom: 6px;
	left: 50%;
	width: 4px;
	height: 4px;
	border-radius: 50%;
	background: currentColor;
	opacity: 0.6;
	transform: translateX(-50%);
}
@media (min-width: 861px) {
	.jhilik-cv-nav { position: sticky; top: var(--jh-header-height, 0); z-index: 5; background: color-mix(in srgb, var(--wp--preset--color--canvas) 88%, transparent); backdrop-filter: blur(6px); }
}
@media (max-width: 860px) {
	.jhilik-cv-nav { flex-wrap: nowrap; overflow-x: auto; scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch; padding-bottom: 0.3rem; }
	.jhilik-cv-nav__chip { scroll-snap-align: start; }
}

.jhilik-cv-section { position: relative; margin-block: clamp(1.75rem, 3vw, 2.5rem); scroll-margin-top: 6rem; }
/* A pale aurora strip/mesh behind just the section header — visual
   structure without filling the section with solid color. Sits behind
   every direct child via the z-index pairing below. */
.jhilik-cv-section::before {
	content: "";
	position: absolute;
	inset: -10px -16px auto -16px;
	height: 110px;
	background: radial-gradient(ellipse 70% 100% at 18% 25%, color-mix(in srgb, var(--jh-accent-a) 32%, transparent), transparent 72%);
	border-radius: 28px;
	z-index: 0;
	pointer-events: none;
}
.jhilik-cv-section > * { position: relative; z-index: 1; }
.jhilik-cv-section h2 {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	font-size: 1.3rem;
	margin: 0 0 1.1rem;
}
.jhilik-cv-section h2::before {
	content: "";
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: var(--jh-accent-a);
	flex: none;
}
.jhilik-cv-section__eyebrow {
	margin: 0 0 0.15rem;
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--jh-accent-a);
}

/* Restrained per-section pastel identity — a color-token swap only
   (heading dot, entry rail/node, chip tint), never a full saturated
   section background, so the page keeps most of its cream/white space. */
.jhilik-cv-section--highlights, .jhilik-cv-section--experience { --jh-accent-a: var(--wp--preset--color--secondary); }
.jhilik-cv-section--research { --jh-accent-a: var(--wp--preset--color--accent); }
.jhilik-cv-section--projects { --jh-accent-a: var(--wp--preset--color--blush); }
.jhilik-cv-section--skills { --jh-accent-a: var(--wp--preset--color--mint); }
.jhilik-cv-section--community { --jh-accent-a: var(--wp--preset--color--agent-joyee); }
.jhilik-cv-section--education { --jh-accent-a: color-mix(in srgb, var(--wp--preset--color--secondary) 50%, var(--wp--preset--color--accent) 50%); }
.jhilik-cv-section--education .jhilik-cert-grid { --jh-accent-a: var(--wp--preset--color--mint); }

.jhilik-cv-entry {
	position: relative;
	padding: 1.1rem 0 1.1rem 1.5rem;
	border-left: 2px solid color-mix(in srgb, var(--jh-accent-a) 35%, transparent);
}
.jhilik-cv-entry::before {
	content: "";
	position: absolute;
	left: -6px;
	top: 1.4rem;
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: var(--jh-accent-a);
	box-shadow: 0 0 0 3px var(--wp--preset--color--canvas);
}
.jhilik-cv-entry__head { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.4rem 1rem; }
.jhilik-cv-entry__title { margin: 0; font-size: 1.05rem; font-weight: 700; }
.jhilik-cv-entry__org { color: var(--jh-accent-a); font-weight: 600; font-size: 0.92rem; }
.jhilik-cv-entry__dates { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--jh-ink-soft); font-size: 0.85rem; white-space: nowrap; }
.jhilik-cv-entry__current-chip {
	padding: 0.12rem 0.55rem;
	border-radius: 999px;
	background: color-mix(in srgb, var(--jh-accent-a) 45%, #fff);
	color: var(--jh-ink, #232430);
	font-size: 0.72rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	white-space: nowrap;
}
.jhilik-cv-entry__meta { color: var(--jh-ink-soft); font-size: 0.85rem; margin-top: 0.15rem; }
.jhilik-cv-entry__desc { margin: 0.5rem 0 0; color: var(--jh-ink-soft); font-size: 0.94rem; }
.jhilik-cv-entry__link { display: inline-block; margin-top: 0.4rem; font-size: 0.85rem; font-weight: 600; color: var(--wp--preset--color--primary); text-decoration: none; }
.jhilik-cv-entry__link::after { content: " \2192"; }

.jhilik-cv-taglist { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.jhilik-cv-taglist span {
	padding: 0.35rem 0.8rem;
	border-radius: 999px;
	background: color-mix(in srgb, var(--jh-accent-a) 14%, #fff);
	font-size: 0.85rem;
	font-weight: 600;
}
.jhilik-cv-skill-group { margin-bottom: 1.3rem; }
.jhilik-cv-skill-group h3 { font-size: 0.98rem; margin: 0 0 0.5rem; }

.jhilik-cv-pub-group__label {
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--jh-ink-soft);
	margin: 1.4rem 0 0.7rem;
}
.jhilik-cv-pub-group:first-child .jhilik-cv-pub-group__label,
.jhilik-cv-pub-group > .jhilik-cv-pub-group__label { margin-top: 0; }
.jhilik-cv-pub-card {
	padding: 0.9rem 1.1rem;
	margin-bottom: 0.75rem;
	border-radius: var(--jh-radius-sm);
	background: color-mix(in srgb, var(--jh-accent-a) 10%, #fff);
	border: 1px solid color-mix(in srgb, var(--jh-accent-a) 22%, transparent);
}
.jhilik-cv-pub-card h3 { margin: 0.2rem 0 0; font-size: 0.98rem; font-weight: 700; }
.jhilik-cv-pub-card__status {
	display: inline-block;
	margin: 0;
	padding: 0.1rem 0.55rem;
	border-radius: 999px;
	font-size: 0.7rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.03em;
	background: color-mix(in srgb, var(--jh-accent-a) 35%, #fff);
}
.jhilik-cv-pub-card--ongoing { border-style: dashed; }
.jhilik-cv-pub-group__more { font-size: 0.88rem; color: var(--jh-ink-soft); margin: 0.6rem 0 0; }

.jhilik-cv-project-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.1rem; }
.jhilik-cv-project-card {
	padding: 1.1rem;
	border-radius: var(--jh-radius-sm);
	background: color-mix(in srgb, var(--jh-accent-a) 10%, #fff);
	border: 1px solid color-mix(in srgb, var(--jh-accent-a) 22%, transparent);
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
}
.jhilik-cv-project-card h3 { margin: 0; font-size: 1.02rem; }
.jhilik-cv-project-card p { margin: 0; font-size: 0.9rem; color: var(--jh-ink-soft); }
.jhilik-cv-project-card__status {
	align-self: flex-start;
	margin: 0;
	padding: 0.1rem 0.55rem;
	border-radius: 999px;
	font-size: 0.7rem;
	font-weight: 700;
	text-transform: uppercase;
	background: color-mix(in srgb, var(--jh-accent-a) 35%, #fff);
}
.jhilik-cv-project-card .jhilik-deep-link { font-size: 0.85rem; font-weight: 600; color: var(--wp--preset--color--primary); text-decoration: none; margin-top: auto; }
.jhilik-cv-project-card .jhilik-deep-link::after { content: " \2192"; }

.jhilik-cv-empty { color: var(--jh-ink-soft); font-style: italic; font-size: 0.92rem; }

/* Professional Profiles, /cv/ only — [jhilik_social_links] is the same
   shared shortcode the site footer uses (plain inline text links there,
   left untouched); scoping to body.page-id-44 turns the identical markup
   into small button cards here without changing the footer anywhere else
   on the site. cv.js adds the one-letter monogram badge; everything else
   is pure CSS on the existing <a> tags. */
body.page-id-44 .jhilik-cv-section--contact .jhilik-social-links {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
}
body.page-id-44 .jhilik-cv-section--contact .jhilik-social-links a {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.5rem 0.9rem 0.5rem 0.5rem;
	border-radius: 999px;
	background: color-mix(in srgb, var(--jh-accent-a) 12%, #fff);
	border: 1px solid color-mix(in srgb, var(--jh-accent-a) 28%, transparent);
	font-weight: 600;
	font-size: 0.88rem;
	text-decoration: none;
	color: var(--jh-ink, #232430);
	transition: transform 0.16s ease, background 0.16s ease;
}
body.page-id-44 .jhilik-cv-section--contact .jhilik-social-links a:hover,
body.page-id-44 .jhilik-cv-section--contact .jhilik-social-links a:focus-visible {
	background: color-mix(in srgb, var(--jh-accent-a) 24%, #fff);
	transform: translateY(-2px);
}
.jhilik-cv-profile-badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 24px;
	height: 24px;
	border-radius: 50%;
	background: color-mix(in srgb, var(--jh-accent-a) 55%, #fff);
	font-size: 0.72rem;
	font-weight: 700;
	flex: none;
}

/* Certification cards */
.jhilik-cert-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 1.25rem; }
.jhilik-cert-card {
	display: flex;
	flex-direction: column;
	gap: 0.65rem;
	padding: 1.1rem;
	background: #fff;
	border: var(--jh-line);
	border-radius: var(--jh-radius-sm);
	box-shadow: var(--jh-shadow-sm);
	transition: transform 0.22s ease, box-shadow 0.22s ease;
}
.jhilik-cert-card:hover { transform: translateY(-3px); box-shadow: var(--jh-shadow-md); }
.jhilik-cert-card .jhilik-imgslot--certificate { margin-bottom: 0.2rem; }
.jhilik-cert-card h3 { margin: 0; font-size: var(--wp--preset--font-size--subhead); }
.jhilik-cert-card__issuer { color: var(--jh-accent-a); font-weight: 600; font-size: 0.88rem; }
.jhilik-cert-card__dates { color: var(--jh-ink-soft); font-size: 0.82rem; }
.jhilik-cert-card__desc { font-size: 0.88rem; color: var(--jh-ink-soft); margin: 0; }
.jhilik-cert-card__link { margin-top: auto; font-size: 0.85rem; font-weight: 600; color: var(--wp--preset--color--primary); text-decoration: none; }
.jhilik-cert-card__link::after { content: " \2192"; }

@media (max-width: 780px) {
	.jhilik-cv-hero { grid-template-columns: 1fr; text-align: center; }
	.jhilik-cv-hero__actions { justify-content: center; }
	.jhilik-cv-entry__head { flex-direction: column; }
}

/* 30. Insights archive + article single ---------------------------------- */

/* Bug fix: a fixed 3-column grid reserved 3 equal tracks regardless of
   how many articles actually exist — with the current 1 real article,
   that left 2 empty tracks (roughly two-thirds of the row) as dead
   whitespace next to one narrow card. auto-fit only ever creates as many
   tracks as there are cards, and justify-content centers the result, so
   1 card today reads as one deliberate, appropriately-sized card, while
   more articles later will still fill the row exactly as before. */
/* The Blog hub is a hand-authored page (page-blog.html), not a real CPT
   archive template, so it never got the .jhilik-cpt-archive wide-container
   class every other archive/directory main carries (Portfolio, Research,
   Tools, Videos) — it sits at core's narrower 820px contentSize instead of
   the site's 1220px --content-width. Invisible today with only one
   published article (auto-fit centers a single 500px card either way), but
   it caps future rows at 1 fewer card per row than the other listings once
   more articles publish. Scoped to the semantic .jhilik-insights-hub body
   class (added only to the hub page itself, by slug, in functions.php)
   rather than a numeric page ID or the shared jhilik-labs-area--insights
   class, because that shared class also applies to individual article
   pages, which intentionally keep their own narrower reading measure
   regardless of the ambient container width. */
body.jhilik-insights-hub main.wp-block-group {
	--wp--style--global--content-size: var(--content-width);
}

.jhilik-insights-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 500px)); justify-content: center; gap: clamp(1.25rem, 2.5vw, 1.75rem); align-items: stretch; }
.jhilik-insight-card {
	height: 100%;
	display: flex;
	flex-direction: column;
	background: #fff;
	border: var(--jh-line);
	border-radius: var(--jh-radius-sm);
	box-shadow: var(--jh-shadow-sm);
	overflow: hidden;
	transition: transform 0.22s ease, box-shadow 0.22s ease;
}
.jhilik-insight-card:hover { transform: translateY(-4px); box-shadow: var(--jh-shadow-md); }
.jhilik-insight-card .jhilik-imgslot--article { border-radius: 0; border: 0; border-bottom: var(--jh-line); }
.jhilik-insight-card__body { padding: clamp(1.1rem, 2vw, 1.5rem); display: flex; flex-direction: column; gap: 0.5rem; flex: 1; }
.jhilik-insight-card__meta { display: flex; gap: 0.6rem; align-items: center; font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--jh-accent-a); }
.jhilik-insight-card__meta .jhilik-insight-card__date { color: var(--jh-ink-soft); font-weight: 500; text-transform: none; letter-spacing: 0; }
.jhilik-insight-card h3 { margin: 0; }
.jhilik-insight-card p { margin: 0; color: var(--jh-ink-soft); font-size: 0.975rem; flex: 1; }
.jhilik-insight-card .wp-block-post-excerpt__more-link,
.jhilik-insight-card__readmore {
	display: inline-block;
	margin-top: auto;
	padding-top: 0.5rem;
	font-weight: 600;
	font-size: 0.88rem;
	text-decoration: none;
	color: var(--wp--preset--color--primary);
}
.jhilik-insight-card .wp-block-post-excerpt__more-link::after,
.jhilik-insight-card__readmore::after { content: " \2192"; }

.jhilik-article-deck { font-size: 1.15rem; color: var(--jh-ink-soft); max-width: 68ch; }
.jhilik-article-meta-row { display: flex; flex-wrap: wrap; gap: 0.4rem 1rem; color: var(--jh-ink-soft); font-size: 0.88rem; margin: 0.5rem 0 1.5rem; }
.jhilik-article-body { max-width: 68ch; }
.jhilik-article-body blockquote { border-left: 3px solid var(--jh-accent-a, var(--wp--preset--color--primary)); padding-left: 1.2rem; font-style: italic; color: var(--jh-ink-soft); }
.jhilik-article-body pre, .jhilik-article-body code { background: color-mix(in srgb, var(--wp--preset--color--tertiary) 40%, #fff); border-radius: 8px; }
.jhilik-article-body pre { padding: 1rem 1.25rem; overflow-x: auto; }

.jhilik-author-card {
	display: flex;
	align-items: center;
	gap: 1rem;
	margin: 2.5rem 0;
	padding: 1.1rem 1.4rem;
	border-radius: var(--jh-radius-sm);
	background: color-mix(in srgb, var(--jh-accent-a, var(--wp--preset--color--primary)) 10%, #fff);
	max-width: 68ch;
}
.jhilik-author-card__avatar { width: 52px; height: 52px; border-radius: 50%; flex: none; overflow: hidden; }
.jhilik-author-card__avatar .jhilik-imgslot { border-radius: 50%; aspect-ratio: 1/1; }
.jhilik-author-card__name { font-weight: 700; margin: 0; }
.jhilik-author-card__name a { color: inherit; text-decoration: none; }
.jhilik-author-card__name a:hover { text-decoration: underline; }
.jhilik-author-card__role { margin: 0; font-size: 0.85rem; color: var(--jh-ink-soft); }

/* These fixed-column overrides are no longer needed: auto-fit above
   already collapses gracefully at every width on its own (a fixed
   2-column override at 980px would otherwise force an empty second
   track back into existence while there's only 1 article). */

/* 31. Small consistency fixes -------------------------------------------- */

/* Every archive empty-state, callout, and card now shares one radius/line
   scale — this just closes a few stragglers found during the audit. */
.jhilik-cpt-archive, .jhilik-cpt-single { overflow-x: clip; }

/* CPT single titles (Research, Portfolio) — an editorial case-study/article
   title, not a homepage-hero-scale billboard. Previously inherited the
   theme's global H1 (clamp up to 3.75rem, weight 800), which read as
   oversized against a compact meta row and body copy underneath it. */
.jhilik-cpt-single h1 {
	font-size: clamp(2rem, 3.4vw, 2.75rem);
	line-height: 1.1;
	font-weight: 700;
	letter-spacing: -0.02em;
	margin: 0 0 0.5rem;
}
.jhilik-labs-hero, .jhilik-about-intro, .jhilik-cv-hero { overflow-wrap: anywhere; }
/* ...but never for headings: overflow-wrap:anywhere will happily split a
   single word mid-letter ("Researc/h") the instant its column is even a
   little tight, instead of just wrapping at the next natural break or
   letting the (now-fixed) column width give it room. Headings get the
   same normal, whole-word-only wrapping as everywhere else on the site. */
.jhilik-labs-hero h1, .jhilik-labs-hero h2, .jhilik-labs-hero h3,
.jhilik-about-intro h1, .jhilik-about-intro h2, .jhilik-about-intro h3,
.jhilik-cv-hero h1, .jhilik-cv-hero h2, .jhilik-cv-hero h3 {
	overflow-wrap: normal;
	word-break: normal;
}
.jhilik-portfolio-card, .jhilik-video-card, .jhilik-research-card, .jhilik-labs-card, .jhilik-insight-card, .jhilik-cert-card {
	scroll-margin-top: 6rem;
}
a:focus-visible, button:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
}

/* 32. Footer — playful geometric art direction --------------------------- */
/*
   Rebuilt composition — same tokens used everywhere else on the site
   (agent-deany/arlo/joyee + tertiary sand), still pure HTML/CSS, but
   deliberately kept out of the row the 3-column text grid sits in.
   Every shape lives entirely in the footer's own top or bottom padding
   band (above the grid, or below the legal row) and is corner-cropped
   by two edges at once, so no shape's box can ever reach a text box —
   verified against real rendered layouts, not just eyeballed. Content
   itself gets z-index:1, shapes sit at z-index:0 beneath it.
*/

.jhilik-site-footer {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	padding-top: clamp(3rem, 6vw, 4rem);
	padding-bottom: clamp(2.75rem, 5vw, 3.5rem);
	font-size: 0.9rem; /* footer body target (14-15px), smaller than the 16px site body */
}

.jhilik-footer-deco {
	position: absolute;
	inset: 0;
	overflow: hidden;
	z-index: 0;
	pointer-events: none;
}

.jhilik-fshape {
	position: absolute;
	display: block;
	will-change: transform;
}
.jhilik-fshape--circle { border-radius: 50%; }
.jhilik-fshape--square { border-radius: 28%; }
.jhilik-fshape--blob {
	/* an organic, hexagon-ish rounded blob — no clip-path needed */
	border-radius: 62% 38% 41% 59% / 55% 44% 56% 45%;
}

.jhilik-fshape--blue      { background: color-mix(in srgb, var(--wp--preset--color--agent-deany) 55%, transparent); }
.jhilik-fshape--mint      { background: color-mix(in srgb, var(--wp--preset--color--agent-arlo) 55%, transparent); }
.jhilik-fshape--mint-soft { background: color-mix(in srgb, var(--wp--preset--color--agent-arlo) 34%, transparent); }
.jhilik-fshape--coral     { background: color-mix(in srgb, var(--wp--preset--color--agent-joyee) 55%, transparent); }
.jhilik-fshape--sand      { background: color-mix(in srgb, var(--wp--preset--color--tertiary) 85%, transparent); }
/* "Warm orange" — a genuine warm tone mixed only from tokens already in
   the palette (Joyee coral + sand), not a new arbitrary color. */
.jhilik-fshape--orange    { background: color-mix(in srgb, color-mix(in srgb, var(--wp--preset--color--agent-joyee) 60%, var(--wp--preset--color--tertiary) 40%) 62%, transparent); }

/* Shape 1 — mint circle, bottom-left corner. Its top edge sits at
   bottom-band height so it only ever occupies the padding-bottom strip
   below the legal row, never the grid/legal text itself. */
.jhilik-fshape-1 { width: 220px; height: 220px; left: -90px; bottom: -160px; }
/* Shape 2 — rounded blue square, top-right corner, cropped by both the
   top and right edges so its reveal is a small diagonal sliver only. */
.jhilik-fshape-2 { width: 110px; height: 110px; right: -35px; top: -65px; rotate: -12deg; }
/* Shape 3 — warm-orange organic blob, bottom-right corner. */
.jhilik-fshape-3 { width: 190px; height: 170px; right: -80px; bottom: -125px; }
/* Shape 4 — the clover, bottom-center, mostly cropped below the footer
   edge; only its top lobes peek into the bottom padding band. */
.jhilik-footer-clover {
	position: absolute;
	left: 50%;
	bottom: -108px;
	width: 140px;
	height: 140px;
	translate: -50% 0;
}
.jhilik-footer-clover__lobe {
	position: absolute;
	width: 62%;
	height: 62%;
	border-radius: 50%;
	background: color-mix(in srgb, var(--wp--preset--color--agent-joyee) 46%, transparent);
}
.jhilik-footer-clover__lobe--t { top: 0; left: 19%; }
.jhilik-footer-clover__lobe--b { bottom: 0; left: 19%; }
.jhilik-footer-clover__lobe--l { left: 0; top: 19%; }
.jhilik-footer-clover__lobe--r { right: 0; top: 19%; }
/* Shape 5 — soft mint rounded square, top-left corner, small peek. */
.jhilik-fshape-5 { width: 84px; height: 84px; left: -32px; top: -48px; rotate: 8deg; }

/* Motion — only some shapes, transform/opacity only, gated exactly like
   every other animated element on this site. */
@keyframes jhilik-fshape-drift  { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(10px, -14px); } }
@keyframes jhilik-fshape-drift-slow { 0%, 100% { transform: translate(0, 0) rotate(8deg); } 50% { transform: translate(-8px, -8px) rotate(4deg); } }
@keyframes jhilik-fshape-float  { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-16px); } }
@keyframes jhilik-fshape-rotate { 0%, 100% { transform: rotate(-12deg); } 50% { transform: rotate(-4deg); } }
@keyframes jhilik-fshape-pop    { from { opacity: 0; transform: scale(0.85); } to { opacity: 1; transform: scale(1); } }

@media (prefers-reduced-motion: no-preference) {
	.jhilik-fshape--drift      { animation: jhilik-fshape-drift 9s ease-in-out infinite; }
	.jhilik-fshape--drift-slow { animation: jhilik-fshape-drift-slow 13s ease-in-out infinite; }
	.jhilik-fshape--float      { animation: jhilik-fshape-float 8s ease-in-out infinite; }
	.jhilik-fshape--rotate     { animation: jhilik-fshape-rotate 10s ease-in-out infinite; }
	.jhilik-fshape--pop,
	.jhilik-footer-clover.jhilik-fshape--pop {
		animation: jhilik-fshape-pop 0.7s cubic-bezier(0.2, 0.8, 0.2, 1) both;
		animation-timeline: view();
		animation-range: entry 0% cover 25%;
	}
}
/* animation-timeline isn't universally supported yet; fall back to a
   simple one-shot reveal on load so the pop is never lost. */
@supports not (animation-timeline: view()) {
	@media (prefers-reduced-motion: no-preference) {
		.jhilik-fshape--pop,
		.jhilik-footer-clover.jhilik-fshape--pop { animation: jhilik-fshape-pop 0.8s cubic-bezier(0.2, 0.8, 0.2, 1) 0.2s both; }
	}
}

/* Tablet — pull in the two biggest shapes a little; corners still. */
@media (max-width: 1024px) {
	.jhilik-fshape-1 { width: 180px; height: 180px; bottom: -135px; }
	.jhilik-fshape-3 { width: 150px; height: 135px; bottom: -100px; }
}

/* Mobile — 3 shapes only, compact footer, never wider than the viewport
   regardless of a shape's own negative offset (`.jhilik-footer-deco`
   already clips at `inset:0`, so nothing can cause horizontal scroll). */
@media (max-width: 599px) {
	.jhilik-fshape-3 { display: none; }
	/* Small "peek" amounts on purpose — the legal row at this width stacks
	   (copyright, then wrapped links) and sits closer to the footer's
	   bottom edge than on desktop, so there's less clear padding-bottom
	   for a shape to bleed into before it would reach that text. */
	.jhilik-fshape-1 { width: 140px; height: 140px; left: -55px; bottom: -125px; }
	.jhilik-fshape-5 { width: 56px; height: 56px; left: -18px; top: -32px; }
	.jhilik-footer-clover { width: 90px; height: 90px; bottom: -80px; }
	.jhilik-site-footer {
		padding-top: clamp(2.25rem, 7vw, 2.75rem);
		padding-bottom: clamp(1.75rem, 6vw, 2.25rem);
	}
}

/* 33. Article Reader -------------------------------------------------
   Only ever loaded (visually meaningful) on the "Article (Reader)" page
   template. Reuses the global tokens (section 1) rather than inventing
   its own width/radius/color values. */

.jhilik-article {
	--jhilik-reader-font-scale: 1;
	background: var(--wp--preset--color--base);
	max-width: var(--content-width);
	margin-inline: auto;
	padding: clamp(2rem, 4vw, 3rem) clamp(1.25rem, 3vw, 2.5rem);
	border-radius: var(--radius-lg);
}

.jhilik-article__intro,
.jhilik-article__end {
	max-width: var(--content-width-narrow);
	margin-inline: auto;
}
.jhilik-article--wide .jhilik-article__intro,
.jhilik-article--wide .jhilik-article__end { max-width: 980px; }

.jhilik-article__title {
	/* font-size used to be forced here (with !important) specifically to
	   fight theme.json's old core/post-title block style, which forced
	   every post-title block — including this real H1 — to H2 scale
	   regardless of its actual heading level. That block override has
	   been removed, so this now correctly inherits the base H1 scale
	   (34-46px) like any other page H1, with no !important needed. */
	line-height: 1.15;
	margin: 0.5rem 0 1rem;
}

.jhilik-article-header__eyebrow { margin: 0 0 0.5rem; }
.jhilik-article-header__eyebrow a {
	display: inline-block;
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--primary);
	text-decoration: none;
	padding: 0.3rem 0.75rem;
	border-radius: 999px;
	background: color-mix(in srgb, var(--wp--preset--color--secondary) 34%, #fff);
}
.jhilik-article-header__deck {
	font-size: 1.15rem;
	color: var(--text);
	opacity: 0.82;
	margin: 0 0 1.1rem;
	line-height: 1.6;
}
.jhilik-article-header__meta {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	align-items: center;
	font-size: 0.88rem;
	color: var(--muted);
	margin-bottom: 1.5rem;
}
.jhilik-article-header__author a { color: inherit; font-weight: 600; text-decoration: none; }
.jhilik-article-header__author a:hover { text-decoration: underline; }

.jhilik-reader-controls {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	padding-top: 1.1rem;
	border-top: var(--jh-line);
	margin-bottom: 0.5rem;
}
.jhilik-reader-controls__label {
	font-size: 0.75rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--muted);
	margin-right: 0.25rem;
}
.jhilik-reader-controls__btn {
	font: inherit;
	font-size: 0.85rem;
	font-weight: 600;
	cursor: pointer;
	border: var(--jh-line);
	background: #fff;
	color: var(--text);
	border-radius: 999px;
	padding: 0.35rem 0.85rem;
	line-height: 1;
	transition: background 0.15s ease, color 0.15s ease;
}
.jhilik-reader-controls__btn:hover { background: color-mix(in srgb, var(--wp--preset--color--secondary) 24%, #fff); }
.jhilik-reader-controls__btn[aria-pressed="true"] { background: var(--wp--preset--color--primary); color: #fff; border-color: transparent; }
.jhilik-reader-controls__divider { width: 1px; align-self: stretch; background: var(--border); margin: 0 0.25rem; }

.jhilik-article__cover { max-width: var(--content-width-narrow); margin: 0 auto clamp(2rem, 4vw, 3rem); }
.jhilik-article--wide .jhilik-article__cover { max-width: 980px; }
.jhilik-article__cover:not(.wp-block-post-featured-image) { display: none; } /* core hides an unset featured image itself; belt-and-braces */

.jhilik-article-layout {
	display: grid;
	grid-template-columns: 1fr;
	gap: clamp(1.75rem, 4vw, 2.5rem);
	max-width: var(--content-width-narrow);
	margin-inline: auto;
}
.jhilik-article--wide .jhilik-article-layout { max-width: 980px; }

@media (min-width: 1180px) {
	.jhilik-article-layout {
		grid-template-columns: 220px minmax(0, var(--content-width-narrow));
		max-width: none;
		justify-content: center;
	}
	.jhilik-article--wide .jhilik-article-layout { grid-template-columns: 220px minmax(0, 980px); }
}

/* Table of contents */
.jhilik-toc {
	border: var(--jh-line);
	border-radius: var(--radius-sm);
	background: #fff;
	padding: 1rem 1.1rem;
	font-size: 0.92rem;
}
@media (min-width: 1180px) {
	.jhilik-toc {
		position: sticky;
		top: 6rem;
		max-height: calc(100vh - 8rem);
		overflow-y: auto;
	}
}
.jhilik-toc__summary {
	font-weight: 700;
	cursor: pointer;
	list-style: none;
	display: flex;
	align-items: center;
	justify-content: space-between;
	font-size: 0.75rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--muted);
}
.jhilik-toc__summary::-webkit-details-marker { display: none; }
.jhilik-toc__summary::after { content: "\2304"; font-size: 1rem; transition: transform 0.2s ease; }
.jhilik-toc[open] > .jhilik-toc__summary::after { transform: rotate(180deg); }
.jhilik-toc__list { list-style: none; margin: 0.85rem 0 0; padding: 0; display: grid; gap: 0.5rem; }
.jhilik-toc__list a { color: var(--text); text-decoration: none; opacity: 0.78; line-height: 1.4; }
.jhilik-toc__list a:hover, .jhilik-toc__list a:focus-visible { opacity: 1; color: var(--wp--preset--color--primary); }
.jhilik-toc__sublist { list-style: none; margin: 0.35rem 0 0; padding-left: 0.9rem; display: grid; gap: 0.4rem; border-left: 2px solid var(--border); }

/* Body typography — tuned specifically for long-form reading */
.jhilik-article-body {
	font-size: calc(1.1125rem * var(--jhilik-reader-font-scale, 1));
	line-height: 1.75;
	color: var(--text);
}
.jhilik-article-body > * + * { margin-top: 1.5em; }
.jhilik-article-body p { margin: 0; line-height: inherit; }
/* em, not rem/px — deliberately relative to .jhilik-article-body's own
   font-size (which the reader controls can scale via
   --jhilik-reader-font-scale), so headings grow proportionally when a
   reader increases the text size instead of staying fixed while body
   copy grows around them. These values are sized for the mobile target
   (~25-28px H2, ~20-21px H3 at the default 17.8px base); the min-width
   rule below scales both up to the desktop/tablet target. */
.jhilik-article-body h2 { font-size: 1.55em; margin-top: 1.7em; scroll-margin-top: 6rem; }
.jhilik-article-body h3 { font-size: 1.22em; margin-top: 1.4em; scroll-margin-top: 6rem; }
@media (min-width: 601px) {
	.jhilik-article-body h2 { font-size: 1.8em; }
	.jhilik-article-body h3 { font-size: 1.3em; }
}
.jhilik-article-body ul, .jhilik-article-body ol { padding-left: 1.4em; display: grid; gap: 0.55em; }
.jhilik-article-body li { line-height: 1.7; }
.jhilik-article-body a { text-decoration-thickness: 1px; text-underline-offset: 3px; }
.jhilik-article-body blockquote {
	padding: 0.25em 1.5em;
	border-left: 3px solid var(--wp--preset--color--primary);
	font-style: italic;
	color: var(--muted);
	font-size: 1.05em;
}
.jhilik-article-body blockquote > *:last-child { margin-bottom: 0; }
.jhilik-article-body code {
	font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
	font-size: 0.88em;
	background: color-mix(in srgb, var(--wp--preset--color--secondary) 20%, #fff);
	padding: 0.15em 0.4em;
	border-radius: 5px;
}
.jhilik-article-body pre {
	overflow-x: auto;
	padding: 1.1rem 1.25rem;
	border-radius: var(--radius-sm);
	background: var(--wp--preset--color--contrast);
	color: #fff;
}
.jhilik-article-body pre code { background: none; padding: 0; color: inherit; }
.jhilik-article-body figure { margin: 0; }
.jhilik-article-body img { max-width: 100%; height: auto; border-radius: var(--radius-sm); display: block; margin-inline: auto; }
.jhilik-article-body figcaption { text-align: center; font-size: 0.85em; color: var(--muted); margin-top: 0.6em; }
.jhilik-article-body hr { border: none; border-top: var(--jh-line); }

/* Author card + related reading */
.jhilik-article__end { margin-top: clamp(3rem, 6vw, 4.5rem); display: grid; gap: clamp(2rem, 4vw, 3rem); }
.jhilik-related-reading__heading { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin: 0 0 1rem; }
.jhilik-insights-grid--related { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 860px) { .jhilik-insights-grid--related { grid-template-columns: 1fr 1fr; } }
@media (max-width: 599px) { .jhilik-insights-grid--related { grid-template-columns: 1fr; } }

.jhilik-author-card__links { display: flex; gap: 1rem; margin: 0.4rem 0 0; font-size: 0.88rem; }
.jhilik-author-card__links a { color: var(--wp--preset--color--primary); text-decoration: none; }
.jhilik-author-card__links a:hover { text-decoration: underline; }

/* Reading progress bar */
.jhilik-reader-progress {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	height: 3px;
	z-index: 200;
	pointer-events: none;
}
.jhilik-reader-progress span {
	display: block;
	height: 100%;
	width: 0%;
	background: linear-gradient(90deg, var(--wp--preset--color--primary), var(--wp--preset--color--accent));
}
@media (prefers-reduced-motion: no-preference) {
	.jhilik-reader-progress span { transition: width 0.12s linear; }
}

@media (max-width: 599px) {
	.jhilik-article { border-radius: var(--radius-sm); padding: 1.75rem 1.1rem; }
	.jhilik-article-header__meta { font-size: 0.82rem; }
	.jhilik-reader-controls { gap: 0.4rem; }
}

/* Print — no decorative floating shapes, no progress bar, no controls */
@media print {
	.jhilik-reader-progress,
	.jhilik-reader-controls,
	.jhilik-labs-shapes { display: none !important; }

	/* CV print/ATS hygiene (page-id-44 = /cv/ only — scoped so this never
	   changes print output for any other page). Purely additive inside
	   @media print: zero effect on-screen. Hides site chrome, section nav
	   and buttons that aren't part of the CV content itself, forces the
	   hero's photo+text side-by-side layout into one column, flattens
	   every pastel section identity to plain black-on-white, and disables
	   the scroll-reveal animation so nothing can print mid-transition.
	   This is a readability aid, not a claim of universal ATS
	   compatibility — actual ATS parsers vary widely and this cannot
	   guarantee compatibility with all of them. */
	.page-id-44 .jhilik-site-header,
	.page-id-44 .jhilik-site-footer,
	.page-id-44 .jhilik-cv-nav,
	.page-id-44 .jhilik-cv-hero__actions { display: none !important; }
	.page-id-44 .jhilik-cv-hero { grid-template-columns: 1fr !important; text-align: left !important; border-bottom-color: #000 !important; }
	.page-id-44 .jhilik-cv-hero__image { margin: 0 0 1rem !important; }
	.page-id-44 .jhilik-cv-hero__image .jhilik-imgslot { max-width: 140px !important; margin-inline: 0 !important; }
	.page-id-44 .jhilik-cv-hero__chips { display: none !important; }
	.page-id-44 * {
		animation: none !important;
		transition: none !important;
		box-shadow: none !important;
		background-image: none !important;
	}
	.page-id-44 .jhilik-reveal-on-scroll { opacity: 1 !important; transform: none !important; }
	body.page-id-44 { background: #fff !important; color: #000 !important; }
	.page-id-44 a { color: #000 !important; text-decoration: underline !important; }
	.page-id-44 .jhilik-cv-section__eyebrow,
	.page-id-44 .jhilik-cv-pub-group__label,
	.page-id-44 .jhilik-cv-entry__org,
	.page-id-44 .jhilik-cert-card__issuer { color: #555 !important; }
	.page-id-44 .jhilik-cv-chip,
	.page-id-44 .jhilik-cv-taglist span,
	.page-id-44 .jhilik-cv-pub-card__status,
	.page-id-44 .jhilik-cv-project-card__status,
	.page-id-44 .jhilik-cv-entry__current-chip,
	.page-id-44 .jhilik-cv-section--contact .jhilik-social-links a { background: #fff !important; border: 1px solid #000 !important; color: #000 !important; }
	.page-id-44 .jhilik-cv-entry,
	.page-id-44 .jhilik-cv-pub-card,
	.page-id-44 .jhilik-cv-project-card,
	.page-id-44 .jhilik-cert-card { border-color: #000 !important; background: #fff !important; break-inside: avoid; page-break-inside: avoid; }
	.page-id-44 .jhilik-cv-entry::before { background: #000 !important; box-shadow: none !important; }
	.page-id-44 .jhilik-cv-section h2::before { background: #000 !important; }
	.page-id-44 .jhilik-cv-section { margin-block: 1rem !important; }
	.page-id-44 .jhilik-cv-section::before,
	.page-id-44 .jhilik-cv-profile-badge { display: none !important; }
	.page-id-44 .jhilik-cert-grid { display: block !important; }
	.page-id-44 .jhilik-cert-card { margin-bottom: 0.75rem; }
	@page { margin: 1.6cm; }
}

/* 34. Public agent drawer (homepage dragon cards) ------------------------
   Progressive enhancement only: assets/js/agents.js marks the existing
   dragon cards interactive at runtime and builds this drawer. Nothing
   here changes if JS fails to load — the cards stay exactly as they are
   today, purely decorative. Reuses existing tokens/agent accent colors,
   no new visual system. */

.jhilik-agent-card--clickable {
	cursor: pointer;
	transition: transform 0.22s ease, box-shadow 0.22s ease;
}
.jhilik-agent-card--clickable:hover,
.jhilik-agent-card--clickable:focus-visible {
	transform: translateY(-6px);
	box-shadow: var(--shadow-md);
}
.jhilik-agent-card--clickable:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 3px;
}

.jhilik-agent-card__cue {
	display: inline-block;
	/* auto, not a fixed value: with .jhilik-agent-card back to height:100%
	   and the grid stretching all four cards to the same row height, this
	   pins the CTA to one shared baseline across all four regardless of
	   each card's own (similar-length) description — "same CTA baseline"
	   per the agent-card redesign brief. */
	margin-top: auto;
	padding-top: 0.85rem;
	font-size: 0.82rem;
	font-weight: 600;
	color: var(--card-accent, var(--wp--preset--color--primary));
}
.jhilik-agent-card__cue::after { content: " \2192"; }

.jhilik-agent-drawer-backdrop {
	position: fixed;
	inset: 0;
	background: rgba(16, 21, 42, 0.42);
	z-index: 300;
}

.jhilik-agent-drawer {
	position: fixed;
	z-index: 301;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	width: min(92vw, 480px);
	max-height: min(86vh, 640px);
	overflow-y: auto;
	background: var(--surface);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-lg);
	border-top: 4px solid var(--agent-accent, var(--wp--preset--color--primary));
	padding: clamp(1.5rem, 3vw, 2.25rem);
}

@media (prefers-reduced-motion: no-preference) {
	.jhilik-agent-drawer,
	.jhilik-agent-drawer-backdrop {
		animation: jhilik-agent-drawer-in 0.22s cubic-bezier(0.2, 0.8, 0.2, 1) both;
	}
}
@keyframes jhilik-agent-drawer-in {
	from { opacity: 0; }
	to { opacity: 1; }
}

.jhilik-agent-drawer[data-agent="deany"] { --agent-accent: var(--wp--preset--color--agent-deany); }
.jhilik-agent-drawer[data-agent="judy"]  { --agent-accent: var(--wp--preset--color--agent-judy); }
.jhilik-agent-drawer[data-agent="joyee"] { --agent-accent: var(--wp--preset--color--agent-joyee); }
.jhilik-agent-drawer[data-agent="arlo"]  { --agent-accent: var(--wp--preset--color--agent-arlo); }

.jhilik-agent-drawer__close {
	position: absolute;
	top: 0.9rem;
	right: 0.9rem;
	width: 2.25rem;
	height: 2.25rem;
	min-width: 44px;
	min-height: 44px;
	display: grid;
	place-items: center;
	border: none;
	background: color-mix(in srgb, var(--agent-accent, var(--wp--preset--color--primary)) 12%, #fff);
	border-radius: 50%;
	font-size: 1.3rem;
	line-height: 1;
	color: var(--text);
	cursor: pointer;
}
.jhilik-agent-drawer__close:hover { background: color-mix(in srgb, var(--agent-accent, var(--wp--preset--color--primary)) 22%, #fff); }

.jhilik-agent-drawer__eyebrow {
	margin: 0 0 0.35rem;
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--agent-accent, var(--wp--preset--color--primary));
}
.jhilik-agent-drawer__title { margin: 0 0 0.4rem; font-size: 1.6rem; padding-right: 2.5rem; }
.jhilik-agent-drawer__specialty { margin: 0 0 1.35rem; color: var(--muted); font-size: 0.95rem; }

.jhilik-agent-drawer__label {
	display: block;
	margin-bottom: 0.5rem;
	font-weight: 600;
	font-size: 0.92rem;
}
.jhilik-agent-drawer__textarea {
	width: 100%;
	min-height: 6.5rem;
	padding: 0.85rem 1rem;
	border-radius: var(--radius-sm);
	border: var(--jh-line);
	background: #fff;
	font: inherit;
	font-size: 0.98rem;
	resize: vertical;
}
.jhilik-agent-drawer__textarea:focus-visible {
	outline: 2px solid var(--agent-accent, var(--wp--preset--color--primary));
	outline-offset: 1px;
}

.jhilik-agent-drawer__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	margin-top: 1rem;
}
.jhilik-agent-drawer__ask,
.jhilik-agent-drawer__cancel {
	min-height: 44px;
	padding: 0.7rem 1.5rem;
	border-radius: 999px;
	font-weight: 600;
	font-size: 0.95rem;
	cursor: pointer;
	border: var(--jh-line);
}
.jhilik-agent-drawer__ask {
	background: var(--agent-accent, var(--wp--preset--color--primary));
	color: #fff;
	border-color: transparent;
}
.jhilik-agent-drawer__ask:hover { filter: brightness(1.06); }
.jhilik-agent-drawer__ask:disabled { opacity: 0.6; cursor: default; }
.jhilik-agent-drawer__cancel { background: #fff; color: var(--text); }
.jhilik-agent-drawer__cancel:hover { background: color-mix(in srgb, var(--agent-accent, var(--wp--preset--color--primary)) 10%, #fff); }

.jhilik-agent-drawer__status {
	margin: 0.9rem 0 0;
	min-height: 1.2em;
	font-size: 0.9rem;
	color: var(--muted);
}

.jhilik-agent-drawer__response {
	margin-top: 0.75rem;
	padding: 1rem 1.1rem;
	border-radius: var(--radius-sm);
	background: color-mix(in srgb, var(--agent-accent, var(--wp--preset--color--primary)) 7%, #fff);
	border-left: 3px solid var(--agent-accent, var(--wp--preset--color--primary));
	font-size: 0.98rem;
	line-height: 1.6;
	white-space: pre-wrap;
}
.jhilik-agent-drawer__response--error {
	background: #fbe3e0;
	border-left-color: #b3392c;
	color: #6b2019;
}

/* Mobile — a comfortable near-full-width sheet, not a centered card. */
@media (max-width: 599px) {
	.jhilik-agent-drawer {
		left: 0;
		right: 0;
		top: auto;
		bottom: 0;
		transform: none;
		width: 100%;
		max-height: 88vh;
		border-radius: var(--radius-lg) var(--radius-lg) 0 0;
	}
	@media (prefers-reduced-motion: no-preference) {
		.jhilik-agent-drawer { animation: jhilik-agent-drawer-in-mobile 0.24s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
	}
}
@keyframes jhilik-agent-drawer-in-mobile {
	from { opacity: 0; transform: translateY(24px); }
	to { opacity: 1; transform: translateY(0); }
}

/* Generated visual pack v2 (final single-image set) — decorative/
   conceptual illustrations only. Real photos, certificates and event
   evidence keep their existing rules above; this section only styles
   containers for imported generated artwork.

   v1 of this section (removed) rendered these images as cropped/forced
   fragments — object-fit:cover in small fixed-height boxes, or tiny
   floated banners. That is exactly the "cut strip" bug this pass fixes:
   every generated illustration now renders as one full, uncropped image
   (object-fit: contain, width 100%, height auto) inside a normal content
   block, never a fixed-height frame. */

.jhilik-support-visual {
	display: block;
	width: 100%;
	height: auto;
	max-width: 100%;
	object-fit: contain;
	border-radius: var(--jh-radius-sm, 14px);
	/* Harmless on a plain <img> (no content to clip); needed when this
	   class instead lands on a core/image block's <figure> wrapper, so
	   the radius still clips the image's corners the same way either way. */
	overflow: hidden;
}

/* A support visual placed in its own block gets breathing room from
   whatever text sits above/below it, instead of touching it. */
.jhilik-visual-block {
	margin-block: clamp(1.25rem, 3vw, 2rem);
}

/* Large editorial feature treatment — used for the homepage "Meet the
   team" illustration, which was previously capped at max-width:640px
   (an inline style on the <img> itself) and read as a small thumbnail
   dropped into a wide section. This lets it fill the section's own wide
   container instead, so it reads as a key visual, not an afterthought. */
.jhilik-visual-block--feature {
	margin-block: clamp(2rem, 4vw, 3rem);
}
.jhilik-visual-block--feature .jhilik-support-visual {
	max-width: 100%;
	border-radius: var(--jh-radius-lg, 24px);
	box-shadow: var(--jh-shadow-md);
	/* This class now also lands on a core/image block's <figure> wrapper
	   (converting the raw <img> to a real, Media-Library-editable Image
	   block — see front-page.html) rather than only ever an <img> itself.
	   overflow:hidden makes the radius clip the image's corners the same
	   way it did when border-radius sat directly on the <img>; box-shadow
	   is unaffected since it isn't clipped by a box's own overflow. */
	overflow: hidden;
}

/* Two-up layout used for hero/section "text beside a full illustration"
   placements (Tools featured tool, Contact hero, archive heroes). Stacks
   on tablet/mobile — see the media query below. */
.jhilik-media-split {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: center;
}
.jhilik-media-split > * { min-width: 0; }
.jhilik-media-split > .jhilik-support-visual { width: 100%; }
@media (max-width: 860px) {
	.jhilik-media-split { grid-template-columns: 1fr; }
}

/* Gentle floating motion for decorative illustrations only (never applied
   to real photos/certificates). Small, slow, and fully disabled under
   prefers-reduced-motion. */
@media (prefers-reduced-motion: no-preference) {
	.jhilik-float-anim { animation: jhilik-float 7s ease-in-out infinite; }
}
@keyframes jhilik-float {
	0%, 100% { transform: translateY(0); }
	50% { transform: translateY(-8px); }
}

/* --- Fix: dead filter chips (Tools archive) ---------------------------
   labs.js correctly sets `.hidden = true` on non-matching cards, but the
   card's own `display:flex` rule (below, from the card component) has
   higher specificity than the browser's default `[hidden]{display:none}`
   UA rule, so nothing ever actually disappeared. This restores it. */
[hidden] { display: none !important; }

/* --- Fix: Tools "simulator" white overlay ------------------------------
   These ::before/::after pseudo-elements drew a fake mockup toolbar over
   whatever sat inside .jhilik-tools__preview. That was fine over an empty
   gradient, but once a real illustration fills the container it reads as
   a broken blank white box sitting on top of the artwork. Now that this
   container always holds a real image, the fake mockup chrome is removed
   rather than layered over it. */
.jhilik-tools__preview::before,
.jhilik-tools__preview::after {
	content: none;
}
.jhilik-tools__preview {
	aspect-ratio: auto;
	display: flex;
	align-items: center;
	background: none;
	box-shadow: none;
	border: none;
}

/* --- Roadmap / Journey So Far ------------------------------------------ */
.jhilik-roadmap {
	display: grid;
	grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
	gap: clamp(2rem, 5vw, 3.5rem);
	align-items: start;
}
.jhilik-roadmap__visual { position: sticky; top: 6.5rem; }
.jhilik-roadmap__timeline {
	list-style: none;
	margin: 0;
	padding: 0;
	position: relative;
}
.jhilik-roadmap__timeline::before {
	content: "";
	position: absolute;
	left: 0.5rem;
	top: 0.35rem;
	bottom: 0.35rem;
	width: 2px;
	background: var(--wp--preset--color--agent-deany);
	opacity: 0.22;
}
/* The actual growing progress line, drawn on top of the faint full-height
   track above. Base state (no JS, reduced motion, or before JS has had a
   chance to run at all) is scaleY(1) — fully drawn — because a timeline
   that starts "empty" and depends on JS to fill it is exactly the kind of
   state that must never be the default; see .jhilik-roadmap--tracking
   below, which is the only thing allowed to start it from zero. */
.jhilik-roadmap__timeline::after {
	content: "";
	position: absolute;
	left: 0.5rem;
	top: 0.35rem;
	bottom: 0.35rem;
	width: 2px;
	background: linear-gradient(180deg, var(--wp--preset--color--agent-deany), var(--wp--preset--color--agent-arlo));
	transform: scaleY(1);
	transform-origin: top;
}
.jhilik-roadmap__item {
	position: relative;
	padding: 0 0 1.75rem 1.75rem;
}
.jhilik-roadmap__item:last-child { padding-bottom: 0; }
/* Base state: a solid, "reached" dot — the safe default a no-JS visitor,
   a reduced-motion visitor, and a visitor whose JS hasn't finished
   initializing all see. Only .jhilik-roadmap--tracking (added by labs.js
   once it's actually managing scroll progress) turns this into an
   outline that fills in per-milestone — see below. */
.jhilik-roadmap__item::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.3rem;
	width: 1.05rem;
	height: 1.05rem;
	border-radius: 50%;
	background: var(--wp--preset--color--agent-deany);
	border: 3px solid var(--wp--preset--color--agent-deany);
}
.jhilik-roadmap__year {
	display: inline-block;
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--agent-deany);
	margin-bottom: 0.25rem;
}
.jhilik-roadmap__item h3 {
	margin: 0 0 0.3rem;
}
.jhilik-roadmap__item p {
	margin: 0;
	color: var(--jh-ink-soft);
	font-size: 0.95rem;
}
@media (max-width: 860px) {
	.jhilik-roadmap { grid-template-columns: 1fr; }
	.jhilik-roadmap__visual { position: static; order: -1; }
}

/* Timeline progress — the line fills and each dot switches from outline
   to solid as the user's actual scroll position reaches it, not as a
   fixed-duration animation that plays once on section-enter regardless
   of scroll speed. `.jhilik-roadmap--tracking` is added by labs.js
   (initHeaderClearance's sibling, initTimelineReveal) ONLY once it has a
   live scroll listener running — every rule in this block is additive on
   top of the always-solid, always-visible base state above, so a visitor
   whose JS hasn't run yet (or reduced-motion, or the block's own
   animation toggle set to off) simply keeps seeing that base "complete"
   state, never an empty line or hidden text. */
@media (prefers-reduced-motion: no-preference) {
	.jhilik-roadmap--tracking .jhilik-roadmap__timeline::after {
		transform: scaleY(var(--jh-roadmap-progress, 0));
	}

	.jhilik-roadmap--tracking .jhilik-roadmap__item {
		/* De-emphasized, not hidden — text stays legible (never opacity:0)
		   even before its own milestone is reached. */
		opacity: 0.5;
		transform: translateY(10px);
		transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
	}
	.jhilik-roadmap--tracking .jhilik-roadmap__item::before {
		background: var(--wp--preset--color--canvas);
		transition: background-color 0.3s ease, border-color 0.3s ease, transform 0.3s ease;
	}
	.jhilik-roadmap--tracking .jhilik-roadmap__item.is-passed,
	.jhilik-roadmap--tracking .jhilik-roadmap__item.is-current {
		opacity: 1;
		transform: translateY(0);
	}
	/* Passed: solid brand-blue, normal size — a completed milestone. */
	.jhilik-roadmap--tracking .jhilik-roadmap__item.is-passed::before {
		background: var(--wp--preset--color--agent-deany);
		border-color: var(--wp--preset--color--agent-deany);
	}
	/* Current: dark ink, slightly larger — the one milestone the reading
	   line is actually at right now, visually distinct from both the
	   outlined-upcoming and solid-blue-passed states. */
	.jhilik-roadmap--tracking .jhilik-roadmap__item.is-current::before {
		background: var(--wp--preset--color--contrast);
		border-color: var(--wp--preset--color--contrast);
		transform: scale(1.15);
	}
	/* The active milestone's own text nudges right and reaches full
	   opacity, on top of the item-level fade-in above. */
	.jhilik-roadmap--tracking .jhilik-roadmap__item h3,
	.jhilik-roadmap--tracking .jhilik-roadmap__item p {
		transition: transform 0.4s ease, opacity 0.4s ease;
	}
	.jhilik-roadmap--tracking .jhilik-roadmap__item.is-current h3,
	.jhilik-roadmap--tracking .jhilik-roadmap__item.is-current p {
		transform: translateX(4px);
		opacity: 1;
	}
}

/* 34. 2026 Case-Study System --------------------------------------------
   One reusable set of components for every Portfolio single instead of
   bespoke CSS per page. Data (numbers, labels, percentages) stays as
   plain editable text/HTML — every visual here is CSS/SVG, never a
   generated raster chart. */

/* The editorial shell: everything on a Portfolio single (hero, content,
   related work) sits in ONE 1180px canvas. `layout:"flow"` on the template's
   main/post-content blocks means nothing here is auto-narrowed by core's
   constrained-layout rules — width is controlled entirely here. */
.case-study-shell,
.jhilik-blog-shell {
	max-width: 1180px;
	margin-inline: auto;
	padding-inline: clamp(24px, 4vw, 56px);
}

/* Readable prose (the hero summary, plain paragraphs) stays narrower than
   the full shell; grids/cards/evidence/related-work are NOT given this
   class, so they use the full 1180px canvas. */
.case-study-prose { max-width: 760px; }

.case-study-hero { margin-bottom: clamp(1.25rem, 2.5vw, 1.75rem); }

.case-study-summary {
	font-size: 1.1rem;
	color: var(--jh-ink-soft);
	margin-bottom: 1.1rem;
}

/* --- hero metadata row: one horizontal line under the summary, replacing
   a detached "CURRENT 2026" pill floating on its own. --- */
.case-study-hero-meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.6rem 1rem;
	padding-bottom: clamp(1.5rem, 3vw, 2rem);
	margin-bottom: clamp(1.5rem, 3vw, 2rem);
	border-bottom: var(--jh-line);
	font-size: 0.92rem;
	color: var(--jh-ink-soft);
}
.case-study-hero-meta__badge {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	padding: 0.3rem 0.75rem;
	border-radius: 999px;
	font-size: 0.7rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	background: color-mix(in srgb, var(--wp--preset--color--primary) 12%, #fff);
	color: var(--wp--preset--color--primary);
}
.case-study-hero-meta__sep { opacity: 0.4; }

/* --- heading scale, scoped to this shell: a tighter, more deliberate
   ratio than the sitewide default so H2 section titles never compete
   visually with H1, and H3 card/platform titles stay clearly subordinate
   to H2. --- */
.case-study-shell h1 { font-size: clamp(2.25rem, 4.2vw, 3.1rem); }
.case-study-shell .wp-block-post-content > h2 {
	/* Was clamp(1.4rem, 2.4vw, 1.9rem) — 22.4-30.4px, under the site's
	   article-heading target (30-34 desktop / 25-28 mobile). Explicit
	   390->1440px anchors, matching the same fluid method as theme.json. */
	font-size: clamp(1.625rem, calc(1.625rem + 6px * ((100vw - 390px) / 1050px)), 2rem);
	margin-top: clamp(56px, 7vw, 80px);
	margin-bottom: clamp(20px, 2.5vw, 28px);
}
.case-study-shell .wp-block-post-content > h2:first-child { margin-top: 0; }
.case-study-shell .wp-block-post-content h3 {
	/* Was clamp(1rem, 1.4vw, 1.15rem) — 16-18.4px, well under the H3
	   target (22-24 desktop / 20-21 mobile) and closer to H4 scale. */
	font-size: clamp(1.25rem, calc(1.25rem + 3px * ((100vw - 390px) / 1050px)), 1.4375rem);
}

/* The Blog page's H2s ("Featured Stories", "Latest Articles") are direct
   children of main, not inside a wp:post-content block. These are section
   headers on a listing page, not article prose, so — unlike the case-study
   prose scale above — they just inherit the site's normal base H2 (34px)
   like every other homepage/archive section head; no separate override. */
.jhilik-blog-shell h1 { font-size: clamp(2.25rem, 4.2vw, 3.1rem); }
.jhilik-blog-shell > h2 {
	font-size: var(--wp--preset--font-size--x-large);
	margin-top: clamp(56px, 7vw, 80px);
	margin-bottom: clamp(20px, 2.5vw, 28px);
}
.jhilik-blog-shell > h2:first-of-type { margin-top: clamp(20px, 2.5vw, 28px); }

/* A single real article shouldn't float flush-left with a dead gap beside
   it — center it as a deliberate spotlight card instead (matches the
   Studio spotlight card's width so the two "one featured item" patterns
   on this page read as the same design language). */
.jhilik-insights-grid--single { max-width: 560px; margin-inline: auto; }

/* Every section component gets its own top margin (collapses harmlessly
   with a preceding h2's margin-bottom when one is present) so a component
   placed right after the hero — with no h2 above it — still gets breathing
   room instead of butting straight into the meta row. */
.case-study-kpi-grid,
.case-study-platform-grid,
.case-study-bar-list,
.case-study-snapshot,
.case-study-funnel,
.case-study-gauge,
.case-study-channel-card,
.product-flow,
.capability-grid {
	margin-top: clamp(20px, 2.5vw, 28px);
}

/* --- KPI dashboard: explicit column count per instance (via --cols, set
   inline by the component that renders it) so a row of 3 or 4 compact KPI
   cards never falls back to an ugly 3+1 auto-fit wrap. --- */
.case-study-kpi-grid {
	display: grid;
	grid-template-columns: repeat(var(--cols, 4), 1fr);
	gap: var(--card-gap);
	margin: 0;
}
.case-study-kpi {
	padding: 1.6rem;
	border-radius: var(--jh-radius-sm);
	border: var(--jh-line);
	background: #fff;
	box-shadow: var(--jh-shadow-sm);
}
.case-study-kpi__value {
	display: block;
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(1.6rem, 2.8vw, 2.25rem);
	font-weight: 800;
	line-height: 1.05;
	color: var(--wp--preset--color--contrast);
}
.case-study-kpi__label { display: block; margin-top: 0.5rem; font-size: 0.82rem; color: var(--jh-ink-soft); }
.case-study-kpi__delta { display: inline-block; margin-top: 0.4rem; font-size: 0.78rem; font-weight: 700; }
.case-study-kpi__delta--up { color: var(--jh-success); }
.case-study-kpi__delta--down { color: #c94b4b; }
/* Primary vs. secondary metrics in the same dashboard (e.g. Search
   Console Clicks/Impressions vs. CTR/Average position). */
.case-study-kpi--lg .case-study-kpi__value { font-size: clamp(2.1rem, 4vw, 3rem); }
.case-study-kpi--lg { background: color-mix(in srgb, var(--wp--preset--color--primary) 6%, #fff); }

/* A purely decorative trend flourish under the Search Visibility module —
   never labelled with invented daily values. */
.case-study-trend-decorative { margin-top: 1.5rem; padding: 1.25rem 1.5rem 0.75rem; border-radius: var(--jh-radius-sm); border: var(--jh-line); background: #fff; }
.case-study-trend-decorative__svg { display: block; width: 100%; height: 90px; }
.case-study-trend-decorative__caption { margin: 0.5rem 0 0; font-size: 0.78rem; color: var(--jh-ink-soft); font-style: italic; }
/* No intermediate 2-column override here: forcing 2 columns at tablet
   widths regardless of item count is exactly what produces a 3+1 orphan
   row for a 3-KPI grid. Each grid keeps its own --cols count (set per
   instance, matching its real item count) until the single mobile
   breakpoint below. */
@media (max-width: 560px) { .case-study-kpi-grid { grid-template-columns: 1fr; } }

/* --- comparison / share-of-traffic bars (kept only where a shared unit
   makes the comparison honest, e.g. traffic sessions by source) --- */
.case-study-bar-list { display: flex; flex-direction: column; gap: 0.85rem; margin: 0; }
.case-study-bar { display: grid; grid-template-columns: minmax(110px, 170px) 1fr auto; align-items: center; gap: 0.75rem; font-size: 0.92rem; }
.case-study-bar__label { color: var(--jh-ink-soft); }
.case-study-bar__track { position: relative; height: 10px; border-radius: 999px; background: color-mix(in srgb, var(--wp--preset--color--secondary) 32%, #fff); overflow: hidden; }
.case-study-bar__fill { position: absolute; inset: 0; width: var(--pct, 0%); border-radius: 999px; background: linear-gradient(90deg, var(--wp--preset--color--primary), var(--wp--preset--color--accent)); }
.case-study-bar__value { font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* --- platform / channel cards: explicit --cols too. 4 content-heavy cards
   default to a 2x2 grid (not a single squeezed row); 3 or 2 cards get one
   equal row. --- */
.case-study-platform-grid { display: grid; grid-template-columns: repeat(var(--cols, 2), 1fr); gap: var(--card-gap); margin: 0; }
.case-study-platform-card { padding: 1.6rem; border-radius: var(--jh-radius-sm); border: var(--jh-line); background: #fff; box-shadow: var(--jh-shadow-sm); border-top: 3px solid var(--accent, transparent); }
.case-study-platform-card h3 { margin: 0 0 0.6rem; }
.case-study-platform-card__stat { display: block; font-family: var(--wp--preset--font-family--display); font-size: 1.5rem; font-weight: 800; margin-bottom: 0.2rem; color: var(--wp--preset--color--contrast); }
.case-study-platform-card__note { margin: 0; font-size: 0.85rem; color: var(--jh-ink-soft); }
@media (max-width: 700px) { .case-study-platform-grid { grid-template-columns: 1fr; } }

/* --- campaign snapshot: a 2-column module (sequence visual + efficiency
   cards) for data that has NO shared unit and must never be forced into
   one proportional bar scale. --- */
.case-study-snapshot { display: grid; grid-template-columns: 1fr 1fr; gap: var(--card-gap); margin: 0; align-items: start; }
@media (max-width: 800px) { .case-study-snapshot { grid-template-columns: 1fr; } }

/* A vertical sequence of equal-weight steps + arrows — NOT sized by data,
   just showing "this happens, then this happens." */
.case-study-sequence { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 1.6rem; border-radius: var(--jh-radius-sm); border: var(--jh-line); background: #fff; box-shadow: var(--jh-shadow-sm); height: 100%; box-sizing: border-box; justify-content: center; }
.case-study-sequence__step { text-align: center; }
.case-study-sequence__value { display: block; font-family: var(--wp--preset--font-family--display); font-size: clamp(1.5rem, 2.6vw, 2rem); font-weight: 800; color: var(--wp--preset--color--contrast); }
.case-study-sequence__label { display: block; margin-top: 0.3rem; font-size: 0.85rem; color: var(--jh-ink-soft); }
.case-study-sequence__arrow { font-size: 1.3rem; color: var(--wp--preset--color--primary); margin: 0.35rem 0; }

.case-study-efficiency-cards { display: flex; flex-direction: column; gap: 0.85rem; height: 100%; }
.case-study-efficiency-cards .case-study-kpi { flex: 1; display: flex; flex-direction: column; justify-content: center; }

/* --- funnel --- */
.case-study-funnel { display: flex; flex-direction: column; gap: 0.5rem; margin: 0; max-width: 560px; }
.case-study-funnel__step {
	display: grid;
	grid-template-columns: 1fr auto;
	align-items: center;
	gap: 1rem;
	padding: 0.85rem 1.1rem;
	border-radius: var(--jh-radius-sm);
	background: color-mix(in srgb, var(--wp--preset--color--secondary) var(--depth, 40%), #fff);
	width: var(--width, 100%);
}
.case-study-funnel__label { font-weight: 600; }
.case-study-funnel__value { font-family: var(--wp--preset--font-family--display); font-weight: 800; font-variant-numeric: tabular-nums; }

/* --- gauge (conic-gradient donut, e.g. a health/optimization score) --- */
.case-study-gauge { display: inline-flex; align-items: center; gap: 1rem; }
.case-study-gauge__ring {
	--gauge-pct: 0;
	width: 96px;
	height: 96px;
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	background: conic-gradient(var(--wp--preset--color--mint) calc(var(--gauge-pct) * 1%), color-mix(in srgb, var(--wp--preset--color--secondary) 30%, #fff) 0);
}
.case-study-gauge__ring::before {
	content: "";
	position: absolute;
}
.case-study-gauge__inner {
	width: 72px;
	height: 72px;
	border-radius: 50%;
	background: #fff;
	display: flex;
	align-items: center;
	justify-content: center;
	font-family: var(--wp--preset--font-family--display);
	font-weight: 800;
	font-size: 1.3rem;
}
.case-study-gauge__label { font-size: 0.9rem; color: var(--jh-ink-soft); max-width: 20ch; }

/* --- a prominent current-channel card (e.g. YouTube), never a plain
   inline text link. --- */
.case-study-channel-card {
	display: flex;
	align-items: center;
	gap: 1.25rem;
	flex-wrap: wrap;
	padding: 1.75rem;
	border-radius: var(--jh-radius);
	background: linear-gradient(135deg, color-mix(in srgb, var(--wp--preset--color--primary) 14%, #fff), color-mix(in srgb, var(--wp--preset--color--accent) 12%, #fff));
	border: var(--jh-line);
}
.case-study-channel-card__icon {
	flex: 0 0 auto;
	width: 56px;
	height: 56px;
	border-radius: 16px;
	background: #fff;
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: var(--jh-shadow-sm);
}
.case-study-channel-card__body { flex: 1 1 220px; }
.case-study-channel-card__name { font-family: var(--wp--preset--font-family--display); font-size: 1.3rem; font-weight: 800; margin: 0 0 0.2rem; }
.case-study-channel-card__handle { margin: 0; font-size: 0.9rem; color: var(--jh-ink-soft); }
.case-study-channel-card__cta {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	padding: 0.75rem 1.4rem;
	border-radius: 999px;
	background: var(--wp--preset--color--contrast);
	color: #fff;
	font-weight: 700;
	font-size: 0.92rem;
	text-decoration: none;
}

/* --- takeaway / insight callout --- */
.case-study-insight {
	margin: 2rem 0 0;
	padding: clamp(1.25rem, 2.5vw, 1.75rem);
	border-radius: var(--jh-radius);
	border-left: 4px solid var(--wp--preset--color--primary);
	background: color-mix(in srgb, var(--wp--preset--color--mint) 14%, #fff);
}
.case-study-insight p:last-child { margin-bottom: 0; }

/* --- original evidence: secondary, collapsed, never dominant --- */
.case-study-evidence { margin-top: 0; }
.case-study-evidence summary {
	cursor: pointer;
	font-weight: 600;
	padding: 0.85rem 1.1rem;
	border-radius: var(--jh-radius-sm);
	border: var(--jh-line);
	background: #fff;
	list-style: none;
}
.case-study-evidence summary::-webkit-details-marker { display: none; }
.case-study-evidence summary::after { content: "+"; float: right; color: var(--jh-ink-soft); }
.case-study-evidence[open] summary::after { content: "\2013"; }
.case-study-evidence-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin-top: 1rem; }
.case-study-evidence-grid figure { margin: 0; }
.case-study-evidence-grid a { display: block; }
.case-study-evidence-grid img { width: 100%; display: block; border-radius: 10px; border: var(--jh-line); }
.case-study-evidence-grid figcaption { margin-top: 0.4rem; font-size: 0.8rem; color: var(--jh-ink-soft); }

@media (max-width: 600px) {
	.case-study-bar { grid-template-columns: 1fr; row-gap: 0.35rem; }
	.case-study-bar__value { justify-self: start; }
}

/* 35. Product Flow & Capability Cards --------------------------------------
   Used by AI Research Supervisor to replace prose walls with a real
   HTML/CSS product diagram and scannable capability/limitation cards. */
.product-flow { display: flex; align-items: stretch; gap: 0.75rem; flex-wrap: wrap; }
.product-flow__step {
	flex: 1 1 200px; padding: 1.15rem 1.3rem; border-radius: var(--jh-radius-sm);
	border: var(--jh-line); background: #fff; box-shadow: var(--jh-shadow-sm);
}
.product-flow__step-eyebrow { display: block; font-size: 0.68rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--wp--preset--color--primary); margin-bottom: 0.4rem; }
.product-flow__step h3 { margin: 0 0 0.35rem; font-size: var(--wp--preset--font-size--subhead); }
.product-flow__step p { margin: 0; font-size: 0.85rem; color: var(--jh-ink-soft); }
.product-flow__arrow { flex: 0 0 auto; align-self: center; font-size: 1.4rem; color: var(--wp--preset--color--primary); }
@media (max-width: 700px) {
	.product-flow { flex-direction: column; }
	.product-flow__arrow { transform: rotate(90deg); align-self: flex-start; margin-left: 1.5rem; }
}

.capability-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--card-gap); }
.capability-card {
	padding: 1rem 1.2rem; border-radius: var(--jh-radius-sm); border: var(--jh-line);
	background: #fff; box-shadow: var(--jh-shadow-sm); font-size: 0.92rem; line-height: 1.5;
	display: flex; gap: 0.6rem; align-items: flex-start;
}
.capability-card__mark { flex: 0 0 auto; font-weight: 800; }
.capability-card--yes .capability-card__mark { color: var(--jh-success); }
.capability-card--limitation { background: color-mix(in srgb, var(--wp--preset--color--tertiary) 14%, #fff); }
.capability-card--limitation .capability-card__mark { color: #b9852f; }

/* 36. Card rail (motion primitive G) --------------------------------------
   One reusable horizontal-rail shell for Latest Insights / Latest Videos /
   Selected Projects / Tools. The track is native scroll-snap — touch swipe
   on mobile needs no JS at all; labs.js initRails() only adds the
   prev/next buttons, dots and optional autoplay on top. */
.jhilik-rail {
	position: relative;
	/* A rail is always a grid/flex child of some section layout. Grid and
	   flex items default to min-width:auto, which means an overflow-x:auto
	   track's intrinsic (all-cards-in-a-row) width can force the WHOLE
	   parent grid/flex track wider than the viewport instead of actually
	   scrolling — the exact bug this caused in the Research/Work/Tools
	   sections at narrow widths. min-width:0 lets the rail shrink to its
	   container and makes overflow-x:auto engage as intended. */
	min-width: 0;
}
.jhilik-rail__track { min-width: 0; }
.jhilik-rail__track {
	display: flex;
	gap: var(--card-gap);
	overflow-x: auto;
	scroll-snap-type: x proximity;
	scroll-padding-left: 4px;
	padding: 4px 4px 1rem;
	margin: 0 -4px;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
}
.jhilik-rail__track::-webkit-scrollbar { display: none; }
.jhilik-rail__track > * { flex: 0 0 auto; scroll-snap-align: start; }
/* Cards that normally live in a CSS-grid context (auto-sized columns)
   need an explicit width once they're inside a flex rail track. */
.jhilik-rail__track--featured > .jhilik-insight-card { width: min(380px, 85vw); }
.jhilik-rail__track--videos > .jhilik-video-card { width: min(320px, 78vw); }
.jhilik-rail__controls { display: flex; align-items: center; justify-content: flex-end; gap: 0.6rem; margin-bottom: 1rem; }
.jhilik-rail__arrow {
	display: inline-flex; align-items: center; justify-content: center;
	width: 40px; height: 40px; border-radius: 50%;
	border: var(--jh-line); background: #fff; box-shadow: var(--jh-shadow-sm);
	cursor: pointer; color: var(--wp--preset--color--contrast); font-size: 1.1rem;
	transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.jhilik-rail__arrow:hover { transform: translateY(-2px); box-shadow: var(--jh-shadow-md); }
.jhilik-rail__dots { display: flex; justify-content: center; gap: 0.5rem; margin-top: 0.75rem; }
.jhilik-rail__dot {
	width: 8px; height: 8px; padding: 0; border-radius: 50%; border: none;
	background: color-mix(in srgb, var(--wp--preset--color--secondary) 60%, #fff);
	cursor: pointer; transition: background 0.18s ease, transform 0.18s ease;
}
.jhilik-rail__dot.is-active { background: var(--wp--preset--color--primary); transform: scale(1.25); }
@media (max-width: 640px) { .jhilik-rail__controls { display: none; } }


/* Subtle card hover lift, shared by every card component that opts in —
   never a rotate/tilt, just a small rise + scale + shadow bump. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
	.jhilik-hover-lift { transition: transform 0.22s ease, box-shadow 0.22s ease; }
	.jhilik-hover-lift:hover { transform: translateY(-4px) scale(1.012); }
}

/* 38. Motion system class aliases -----------------------------------------
   The exact class names the motion spec asks for, mapped onto the already
   -built engine (initReveal/initRails/initCountUp in labs.js) rather than
   a second parallel implementation. */
.jh-reveal, .jh-reveal-stagger { }
.jh-reveal, .jh-reveal-stagger,
.jhilik-reveal-on-scroll { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
	.jh-reveal, .jh-reveal-stagger {
		opacity: 0;
		transform: translateY(22px);
		transition: opacity 0.6s ease calc(var(--reveal-i, 0) * 80ms), transform 0.6s ease calc(var(--reveal-i, 0) * 80ms);
	}
	.jh-reveal.is-visible, .jh-reveal-stagger.is-visible { opacity: 1; transform: translateY(0); }
	.jh-float { animation: jhilik-float 6s ease-in-out infinite; }
	.jh-pulse { animation: jhilik-pulse-soft 1.8s ease-in-out infinite; }
}
.jh-hover-lift { }
.jh-rail { }
.jh-active-dot { }

/* ---------------------------------------------------------------------
   Selected Work rail (real Portfolio CPT items).
   ------------------------------------------------------------------- */
.jhilik-rail__track--work > .jhilik-work-rail-card { width: min(560px, 86vw); }
.jhilik-work-rail-card {
	display: flex; flex-direction: column; height: 100%;
	background: #fff; border: var(--jh-line); border-radius: var(--jh-radius);
	overflow: hidden; box-shadow: var(--jh-shadow-sm);
}
.jhilik-work-rail-card__media {
	position: relative;
	display: block;
	aspect-ratio: 16/9;
	background: color-mix(in srgb, var(--wp--preset--color--agent-deany) 20%, #fff);
}
.jhilik-work-rail-card__media.is-empty {
	display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.6rem;
	background: linear-gradient(135deg, color-mix(in srgb, var(--wp--preset--color--agent-deany) 22%, #fff) 0%, color-mix(in srgb, var(--wp--preset--color--accent) 18%, #fff) 100%);
}
.jhilik-work-rail-card__media-icon { color: var(--wp--preset--color--agent-deany); opacity: 0.85; }
.jhilik-work-rail-card__media-label { font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; font-size: 0.78rem; color: var(--wp--preset--color--agent-deany); }
.jhilik-work-rail-card__media img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.3s ease; }
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
	.jhilik-work-rail-card:hover .jhilik-work-rail-card__media img { transform: scale(1.04); }
}
.jhilik-work-rail-card__body { display: flex; flex-direction: column; gap: 0.5rem; padding: 1.4rem; flex: 1; }
.jhilik-work-rail-card__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.jhilik-work-rail-card__type { font-size: 0.78rem; color: var(--jh-ink-soft); }
.jhilik-work-rail-card h3 { margin: 0; }
.jhilik-work-rail-card__result { margin: 0; font-weight: 700; color: var(--wp--preset--color--primary); font-size: 0.95rem; }
.jhilik-work-rail-card__summary { margin: 0; color: var(--jh-ink-soft); font-size: 0.975rem; flex: 1; }
.jhilik-work-rail-card .jhilik-deep-link { margin-top: auto; }

/* ---------------------------------------------------------------------
   Selected Research compact rail.
   ------------------------------------------------------------------- */
.jhilik-rail__track--research { gap: 1rem; }
.jhilik-rail__track--research > .jhilik-research-rail-card { width: min(300px, 80vw); }
.jhilik-research-rail-card {
	display: flex; flex-direction: column; gap: 0.6rem; height: 100%;
	padding: 1.3rem; border-radius: var(--jh-radius-sm); border: var(--jh-line); background: #fff;
}
.jhilik-research-rail-card--published { background: color-mix(in srgb, var(--wp--preset--color--mint) 16%, #fff); }
.jhilik-research-rail-card--ongoing { background: color-mix(in srgb, var(--wp--preset--color--tertiary) 18%, #fff); }
.jhilik-research-rail-card h3 { margin: 0; line-height: 1.3; }
.jhilik-research-rail-card p { margin: 0; font-size: 0.975rem; color: var(--jh-ink-soft); flex: 1; }
.jhilik-research-rail-card .jhilik-deep-link { margin-top: auto; }

/* ---------------------------------------------------------------------
   Tools/Experiments rail: resting tilt (max ±1.5deg), straightens + lifts
   on hover/focus. No tilt at all on touch/mobile widths.
   ------------------------------------------------------------------- */
.jhilik-rail__track--tools { gap: 1.25rem; padding-top: 0.75rem; }
.jhilik-rail__track--tools > .jhilik-tool-rail-card { width: min(260px, 78vw); }
.jhilik-tool-rail-card {
	display: flex; flex-direction: column; gap: 0.6rem; height: 100%;
	padding: 1.4rem; border-radius: var(--jh-radius); border: var(--jh-line); background: #fff;
	box-shadow: var(--jh-shadow-sm);
	transition: transform 0.22s ease, box-shadow 0.22s ease;
}
@media (min-width: 721px) and (prefers-reduced-motion: no-preference) {
	.jhilik-tool-rail-card { transform: rotate(var(--jh-tilt, 0deg)); }
	.jhilik-tool-rail-card:hover, .jhilik-tool-rail-card:focus-within {
		transform: rotate(0deg) translateY(-4px);
		box-shadow: var(--jh-shadow-md);
	}
	/* .jhilik-reveal-on-scroll.is-visible (2 classes) otherwise beats the
	   single-class tilt rule above and snaps cards flat once revealed —
	   restore the rest-state tilt here, but only once revealed to still
	   let the entrance animation itself rise in untilted. */
	.jhilik-tool-rail-card.jhilik-reveal-on-scroll.is-visible { transform: rotate(var(--jh-tilt, 0deg)); }
	.jhilik-tool-rail-card.jhilik-reveal-on-scroll.is-visible:hover,
	.jhilik-tool-rail-card.jhilik-reveal-on-scroll.is-visible:focus-within {
		transform: rotate(0deg) translateY(-4px);
	}
}
.jhilik-tool-rail-card h3 { margin: 0; }
.jhilik-tool-rail-card p { margin: 0; font-size: 0.975rem; color: var(--jh-ink-soft); flex: 1; }
.jhilik-tool-rail-card .jhilik-deep-link { margin-top: auto; }

/* ---------------------------------------------------------------------
   CTA micro-interaction: the arrow nudges right on hover/focus, applied
   wherever a .jhilik-deep-link's own text supplies the arrow glyph.
   ------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
	a.jhilik-deep-link { display: inline-block; transition: transform 0.18s ease; }
	a.jhilik-deep-link:hover, a.jhilik-deep-link:focus-visible { transform: translateX(2px); }
}
