/*
 * nagi theme - design layer
 *
 * Loaded after style.bundle.css (Bootstrap 5) so everything here is an override.
 * Palette is sampled from the nagi mark itself: navy #151D30 -> blue #055BAD -> cyan #1093CF.
 * Layout/型 direction follows the agreed reference: near-black ground, oversized display
 * type at weight 500, pill navigation, generous vertical rhythm, scroll reveals.
 *
 * No build step: this is plain CSS on purpose, the production host has no Node.
 */

/* ------------------------------------------------------------------ tokens */

:root,
[data-bs-theme="dark"] {
	/* ground */
	--nagi-bg: #030303;
	--nagi-bg-raised: #0b0c0e;
	--nagi-bg-sunken: #000;
	--nagi-line: rgba(255, 255, 255, .09);
	--nagi-line-strong: rgba(255, 255, 255, .18);

	/* ink */
	--nagi-ink: #f2f2f0;
	--nagi-ink-dim: #969696;
	--nagi-ink-faint: #5d6068;

	/* Scrollbar thumb — the track is transparent, see the html rule below. */
	--nagi-scrollbar-thumb: #4b4b4b;
	--nagi-scrollbar-thumb-hover: #6a6a6a;

	/* brand ramp, straight off the mark */
	--nagi-navy: #151d30;
	--nagi-blue-deep: #055bad;
	--nagi-blue: #156db3;
	--nagi-cyan: #1093cf;
	--nagi-cyan-bright: #5fd9f5;
	--nagi-lavender: #b1b7ca;

	--nagi-accent: var(--nagi-cyan);
	--nagi-accent-contrast: #00121c;

	--nagi-gradient: linear-gradient(115deg, var(--nagi-navy) 0%, var(--nagi-blue-deep) 45%, var(--nagi-cyan) 78%, var(--nagi-cyan-bright) 100%);
	--nagi-gradient-text: linear-gradient(100deg, #ffffff 0%, #cfe6f5 40%, var(--nagi-cyan-bright) 100%);

	/* rhythm */
	--nagi-section-y: clamp(5rem, 11vw, 10.5rem);
	--nagi-radius: 14px;
	--nagi-radius-lg: 22px;
	--nagi-radius-pill: 999px;

	/* bootstrap bridge */
	--bs-body-bg: var(--nagi-bg);
	--bs-body-color: var(--nagi-ink-dim);
	--bs-emphasis-color: var(--nagi-ink);
	--bs-border-color: var(--nagi-line);
	--bs-primary: var(--nagi-cyan);
	--bs-link-color: var(--nagi-ink);
	--bs-link-hover-color: var(--nagi-cyan-bright);
}

/* ------------------------------------------------------------------- base */

html {
	scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}
}

body {
	background: var(--nagi-bg);
	color: var(--nagi-ink-dim);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	overflow-x: hidden;
}

/*
 * Scrollbars: transparent track, so the page background shows through instead
 * of the browser's own light-grey strip down the side of a near-black page.
 *
 * Two syntaxes because no single one is supported everywhere: `scrollbar-color`
 * is the standard (Firefox, and Chromium 121+), `::-webkit-scrollbar` is the
 * older WebKit/Blink one. Declaring both is not redundant — a browser that
 * understands `scrollbar-color` ignores the pseudo-elements, and vice versa.
 *
 * Deliberately not `scrollbar-width: thin`: it also shortens the thumb's hit
 * area, and this page scrolls a long way.
 */
html {
	scrollbar-color: var(--nagi-scrollbar-thumb) transparent;
}

::-webkit-scrollbar {
	width: 10px;
	height: 10px;
	background: transparent;
}

::-webkit-scrollbar-track {
	background: transparent;
}

::-webkit-scrollbar-thumb {
	background-color: var(--nagi-scrollbar-thumb);
	border-radius: 9999px;
	/* Inset the thumb from the track edge without a second element. */
	border: 2px solid transparent;
	background-clip: padding-box;
}

::-webkit-scrollbar-thumb:hover {
	background-color: var(--nagi-scrollbar-thumb-hover);
}

::-webkit-scrollbar-corner {
	background: transparent;
}

::selection {
	background: var(--nagi-cyan);
	color: var(--nagi-accent-contrast);
}

h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
	color: var(--nagi-ink);
	font-weight: 500;
	letter-spacing: -.02em;
	line-height: 1.06;
}

/* the reference leans on very large, tightly-tracked display type */
.display-1, .display-2, .display-3 {
	font-weight: 500;
	letter-spacing: -.035em;
	line-height: .98;
}

.display-1 {
	font-size: clamp(2.75rem, 7.4vw, 6.5rem);
}

.display-2 {
	font-size: clamp(2.25rem, 5.6vw, 4.75rem);
}

.display-3 {
	font-size: clamp(1.9rem, 4.2vw, 3.4rem);
}

.nagi-lead {
	font-size: clamp(1rem, 1.35vw, 1.2rem);
	line-height: 1.65;
	color: var(--nagi-ink-dim);
	max-width: 46ch;
}

.nagi-gradient-text {
	background: var(--nagi-gradient-text);
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
}

/* small caps-ish section label, used above every section heading */
.nagi-eyebrow {
	display: inline-flex;
	align-items: center;
	gap: .55rem;
	font-size: .75rem;
	font-weight: 500;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--nagi-ink-faint);
	margin-bottom: 1.25rem;
}

.nagi-eyebrow::before {
	content: "";
	width: 1.75rem;
	height: 1px;
	background: var(--nagi-line-strong);
}

section,
.nagi-section {
	padding-block: var(--nagi-section-y);
	position: relative;
}

.nagi-hairline {
	border-top: 1px solid var(--nagi-line);
}

/* ---------------------------------------------------------------- buttons */

.btn {
	--bs-btn-border-radius: var(--nagi-radius-pill);
	border-radius: var(--nagi-radius-pill);
	font-weight: 500;
	letter-spacing: -.01em;
	padding: .85rem 1.9rem;
	background-clip: padding-box;
	transition: transform .25s cubic-bezier(.2, .7, .3, 1), box-shadow .25s, background .25s, color .25s;
}

/*
 * The base theme ships light-theme drop/inset shadows on buttons. Against our
 * near-black ground they read as pale square patches poking out past the pill's
 * rounded corners, so the button looks un-chamfered.
 *
 * Killed with !important deliberately: the shadow is declared in several places
 * in style.bundle.css (.btn, .btn.btn-primary, and Bootstrap's --bs-btn-box-shadow
 * custom property), and matching each one by specificity is fragile.
 */
.btn,
.btn:hover,
.btn:focus,
.btn:active,
.btn.btn-primary,
.btn.btn-dark,
.btn.btn-secondary {
	--bs-btn-box-shadow: none;
	--bs-btn-focus-box-shadow: none;
	box-shadow: none !important;
}

/* the base theme also hangs a stray "." on every button via a pseudo-element */
.btn::before,
.btn::after {
	content: none !important;
}

.btn:hover {
	transform: translateY(-2px);
}

.btn-primary,
.nagi-btn-primary {
	background: var(--nagi-ink);
	border: 1px solid var(--nagi-ink);
	color: #050505;
}

.btn-primary:hover,
.nagi-btn-primary:hover {
	background: #fff;
	border-color: #fff;
	color: #050505;
	box-shadow: 0 10px 40px -12px rgba(255, 255, 255, .45);
}

.nagi-btn-ghost {
	background: transparent;
	border: 1px solid var(--nagi-line-strong);
	color: var(--nagi-ink);
}

.nagi-btn-ghost:hover {
	border-color: var(--nagi-cyan);
	color: var(--nagi-cyan-bright);
	background: rgba(16, 147, 207, .08);
}

/* the "Introducing …" capsule from the reference hero */
.nagi-badge {
	display: inline-flex;
	align-items: center;
	gap: .6rem;
	padding: .5rem 1.15rem;
	border-radius: var(--nagi-radius-pill);
	border: 1px solid var(--nagi-line-strong);
	background: rgba(255, 255, 255, .03);
	backdrop-filter: blur(10px);
	color: var(--nagi-ink);
	font-size: .85rem;
	font-weight: 500;
	text-decoration: none;
}

.nagi-badge:hover {
	border-color: var(--nagi-cyan);
	color: var(--nagi-cyan-bright);
}

.nagi-badge__dot {
	width: .45rem;
	height: .45rem;
	border-radius: 50%;
	background: var(--nagi-cyan-bright);
	box-shadow: 0 0 0 3px rgba(95, 217, 245, .18);
}

/* ------------------------------------------------------------ navigation */

/* the base theme paints this strip translucent white; we want it to disappear
   over the hero so the pill is the only visible chrome */
.navigation-1,
.navigation-1 .navbar,
.navbar {
	background: transparent !important;
	border: 0;
}

.navbar {
	padding-block: 1.15rem;
}

.navbar-brand img {
	height: 24px;
	width: auto;
}

/* icon + wordmark lockup */
.nagi-brand {
	display: inline-flex;
	align-items: center;
	gap: .55rem;
}

.nagi-brand__icon {
	height: 26px !important;
	width: auto;
	flex: 0 0 auto;
}

/* floating pill that holds the links, mirroring the reference nav */
.navbar .navbar-collapse {
	flex-grow: 0;
}

@media (min-width: 768px) {
	.navbar-nav {
		align-items: center;
		gap: .15rem;
		padding: .25rem .35rem;
		border-radius: var(--nagi-radius-pill);
		border: 1px solid var(--nagi-line);
		background: rgba(12, 12, 14, .55);
		backdrop-filter: blur(14px);
	}
}

.navbar-nav .nav-link {
	color: var(--nagi-ink);
	font-weight: 500;
	font-size: .9rem;
	/* keep every item on one line - "Contact us" wrapping was forcing the whole
	   nav pill to double height */
	white-space: nowrap;
	line-height: 1.2;
	padding: .4rem .8rem;
	border-radius: var(--nagi-radius-pill);
	transition: background .2s, color .2s;
}

/* the nav items sit in position-static <li>s for the mega menu, so pin the
   height on the item itself rather than relying on the row.
   align-items must stay 'stretch': 'center' also vertically centres the static
   position of the absolutely-positioned dropdown child, which pushed the
   dropdowns up above the navbar. */
.navbar-nav .nav-item {
	display: flex;
	align-items: stretch;
}

/*
 * The base theme makes the nav full-bleed tall with
 *   @media screen and (min-width: 767px) {
 *     .navigation-1 .navbar .navbar-nav a.nav-link { padding: 2.1rem 1rem }
 *   }
 * which is 85px per item. We want the items about as tall as the search icon,
 * so match that selector's specificity to win the cascade.
 */
@media screen and (min-width: 767px) {
	.navigation-1 .navbar .navbar-nav a.nav-link {
		font-size: .9rem;
		padding: .4rem .85rem;
	}

	/* same treatment for the account / cart / language / theme toggles on the
	   right; the base theme pads these with its own, more specific rule
	   (.navigation-1 .navbar .navbar-nav .nav-toggle a.nav-link) so mirror it */
	.navigation-1 .navbar .navbar-nav .nav-toggle a.nav-link {
		display: inline-flex;
		align-items: center;
		padding: .4rem .55rem;
	}
}

/* those controls are icon buttons - the hero CTA sizing must not leak in */
.navbar .btn,
.navbar-nav .btn {
	padding: .35rem .55rem;
	font-size: .85rem;
	line-height: 1.2;
}

.navbar-nav .nav-toggle {
	display: flex;
	align-items: center;
}

.navbar-nav .nav-link:hover,
.navbar-nav .nav-link.active {
	color: #fff;
	background: rgba(255, 255, 255, .07);
}

.dropdown-menu {
	background: var(--nagi-bg-raised);
	border: 1px solid var(--nagi-line);
	border-radius: var(--nagi-radius);
	box-shadow: 0 30px 80px -30px rgba(0, 0, 0, .9);
}

.dropdown-item {
	color: var(--nagi-ink-dim);
	border-radius: 8px;
}

.dropdown-item:hover {
	background: rgba(255, 255, 255, .06);
	color: var(--nagi-ink);
}

/*
 * Dropdown positioning.
 *
 * Vvveb tags nav items that could be mega menus with `.position-static`
 * (position: static !important), so a plain dropdown anchors to the navbar
 * container instead of its own toggle and opens in the wrong place. We split
 * the two cases by the inline `column-count` that Vvveb only puts on real
 * mega-menu panels:
 *   - simple dropdown (no column-count) -> anchor under its toggle
 *   - mega menu (column-count)          -> leave width/left to the theme, just
 *                                          pin the top to the navbar bottom
 */
@media (min-width: 767px) {
	.navigation-1 .navbar .navbar-nav li.nav-item.dropdown.position-static:has(> .dropdown-menu:not([style*="column-count"])) {
		position: relative !important;
	}

	.navigation-1 .navbar .navbar-nav li.nav-item.dropdown > .dropdown-toggle + .dropdown-menu:not([style*="column-count"]) {
		top: 100% !important;
		left: 0 !important;
		right: auto !important;
		bottom: auto !important;
		min-width: 12rem;
		transform: translateY(8px);
	}

	.navigation-1 .navbar .navbar-nav li.nav-item.dropdown:hover > .dropdown-toggle + .dropdown-menu:not([style*="column-count"]),
	.navigation-1 .navbar .navbar-nav li.nav-item.dropdown:focus-within > .dropdown-toggle + .dropdown-menu:not([style*="column-count"]) {
		transform: translateY(0) !important;
	}

	/* mega-menu panel: drop it below the bar rather than over it */
	.navigation-1 .navbar .navbar-nav li.nav-item.dropdown > .dropdown-menu[style*="column-count"] {
		top: 100% !important;
	}
}

/* sticky state */
.navbar.is-stuck {
	background: rgba(3, 3, 3, .82);
	backdrop-filter: blur(18px);
	border-bottom: 1px solid var(--nagi-line);
}

/* ----------------------------------------------------------------- hero */

.nagi-hero {
	position: relative;
	min-height: min(100svh, 60rem);
	display: flex;
	align-items: center;
	/* lets the scene layer wrap below the copy once it goes static on mobile */
	flex-wrap: wrap;
	overflow: hidden;
	padding-block: clamp(7rem, 14vh, 11rem) var(--nagi-section-y);
	background: var(--nagi-bg);
	/*
	 * The render is dragged to orbit it (nagi-scene3d.js). On touch that has to
	 * leave the page scrollable, so the browser keeps vertical pans and pinch
	 * zoom and only horizontal drags reach the scene.
	 */
	touch-action: pan-y pinch-zoom;
}

/* set by nagi-scene3d.js: the pointer is over the panel / is turning it */
.nagi-hero.is-scene-grab {
	cursor: grab;
}

.nagi-hero.is-scene-drag,
.nagi-hero.is-scene-drag * {
	cursor: grabbing;
	user-select: none;
}

/* the 3D layer - either a Spline scene or the built-in canvas fallback */
.nagi-hero__stage {
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;

	/*
	 * Dissolve the animation into the page instead of letting overflow:hidden
	 * slice the strokes off in a hard line at the section boundary. The mask
	 * fades the actual pixels, so it works for the Spline scene too.
	 */
	-webkit-mask-image: linear-gradient(180deg,
		#000 0%,
		#000 52%,
		rgba(0, 0, 0, .72) 74%,
		rgba(0, 0, 0, .28) 90%,
		transparent 100%);
	mask-image: linear-gradient(180deg,
		#000 0%,
		#000 52%,
		rgba(0, 0, 0, .72) 74%,
		rgba(0, 0, 0, .28) 90%,
		transparent 100%);
}

.nagi-hero__stage > canvas,
.nagi-hero__stage > spline-viewer {
	width: 100%;
	height: 100%;
	display: block;
}

/*
 * Keeps type legible over whatever the stage renders.
 * Deliberately light: an earlier, much heavier scrim (opaque bg at the edges
 * plus a .7 wash across the top) buried the animation completely. Only the
 * left half - where the headline sits - needs real protection.
 */
.nagi-hero__scrim {
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	background:
		linear-gradient(90deg, rgba(3, 3, 3, .84) 0%, rgba(3, 3, 3, .56) 38%, rgba(3, 3, 3, 0) 72%),
		/* top wash for the nav, and a tail that settles onto the page colour so
		   the hero meets the next section without a seam */
		linear-gradient(180deg,
			rgba(3, 3, 3, .5) 0%,
			rgba(3, 3, 3, 0) 22%,
			rgba(3, 3, 3, 0) 76%,
			var(--nagi-bg) 100%);
}

.nagi-hero__inner {
	position: relative;
	z-index: 3;
}

.nagi-hero h1 {
	margin-block: 1.5rem 1.75rem;
	max-width: 18ch;
}

/*
 * No text-shadow on the headline: .nagi-gradient-text paints its gradient with
 * background-clip:text over transparent glyphs, so a shadow shows *through* the
 * letterforms and flattens the gradient to grey.
 *
 * Slightly under .display-1: that size was set when the hero was one wide column
 * with nothing beside it, and it overpowers the frame now the render shares it.
 */
.nagi-hero h1 {
	/* capped so the second clause still holds one line inside the column */
	font-size: clamp(2.5rem, 5.5vw, 4.85rem);
	/* wide enough for the second clause to hold one line at this size */
	max-width: 25ch;
}

.nagi-hero .nagi-lead {
	max-width: 52ch;
}

.nagi-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: .85rem;
	margin-top: 2.5rem;
}

.nagi-hero__meta {
	margin-top: 2.25rem;
	display: flex;
	flex-wrap: wrap;
	gap: 1.5rem;
	color: var(--nagi-ink-faint);
	font-size: .85rem;
}

.nagi-hero__meta span {
	display: inline-flex;
	align-items: center;
	gap: .45rem;
}

/* the copy now shares the hero with the 3D scene, so cap the display size */
/*
 * The 3D scene is a layer, not a column: the headline keeps its full display
 * size and the render sits behind it on the right. The scrim above it is what
 * keeps the type legible where the two meet.
 */
.nagi-hero__scene {
	position: absolute;
	/*
	 * Below the scrim (z-index 1), not above it. The render is deliberately wide
	 * enough to reach back under the headline, and the scrim's left wash is what
	 * keeps the type readable where they cross - so the render has to sit under
	 * it. The copy is z-index 3 and stays clear of both.
	 */
	z-index: 0;
	/*
	 * Anchored by its centre, so it keeps the same spot on any width. Pinning the
	 * right edge instead pushed it off into the corner on wide monitors, because
	 * the width is capped in rem.
	 */
	left: 66%;
	top: 50%;
	transform: translate(-50%, -50%);
	width: min(58rem, 72%);
	height: min(124%, 50rem);
	pointer-events: none;
}

.nagi-hero__scene .nagi-scene {
	height: 100%;
}

/* ------------------------------------------------------- hero 3D scene */

/*
 * A chunky, toy-like nagi plugin window built out of CSS 3D transforms.
 * This is what the hero shows by default; setting a Spline scene URL in the
 * theme settings swaps in a real Spline scene instead (see nagi-hero.js).
 *
 * Everything is sized in em off the scene's own font-size, so the whole
 * composition scales as one object with the viewport. Static placement in
 * 3D uses `transform`; the idle motion uses the independent `translate` /
 * `rotate` properties so the two never fight over one property.
 */
.nagi-scene {
	position: relative;
	font-size: clamp(8px, 1.02vw, 14.5px);
	height: 34em;
	display: flex;
	align-items: center;
	justify-content: center;
	perspective: 62em;
	perspective-origin: 50% 45%;
}

.nagi-scene__glow {
	position: absolute;
	inset: -12% -18%;
	background: radial-gradient(closest-side,
		rgba(16, 147, 207, .30) 0%,
		rgba(5, 91, 173, .12) 52%,
		rgba(3, 3, 3, 0) 76%);
	pointer-events: none;
}

.nagi-scene__world {
	position: relative;
	width: 30em;
	height: 26em;
	transform-style: preserve-3d;
	/* JS nudges these from the pointer; the values here are the resting pose */
	transform: rotateX(var(--nagi-rx, 5deg)) rotateY(var(--nagi-ry, -17deg));
	will-change: transform;
}

/* a Spline scene or the WebGL render takes the whole column */
.nagi-scene > spline-viewer,
.nagi-scene > canvas {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	display: block;
}

/*
 * The CSS-3D plugin scene below is a no-WebGL fallback only: hidden by default so
 * it never flashes ahead of the render, revealed by nagi-hero.js (.is-css) if both
 * the Spline and WebGL paths fail.
 */
.nagi-scene__world {
	display: none;
}

.nagi-scene.is-css .nagi-scene__world {
	display: block;
}

/*
 * The render fills the column, so the tile wall would otherwise stop on a hard
 * vertical line at the canvas edge. Feather the frame instead - centred slightly
 * up and left, where the panels actually sit.
 */
.nagi-scene > canvas {
	-webkit-mask-image: radial-gradient(140% 140% at 50% 46%, #000 38%, rgba(0, 0, 0, .82) 62%, transparent 92%);
	mask-image: radial-gradient(138% 138% at 50% 46%, #000 50%, rgba(0, 0, 0, .88) 70%, transparent 100%);
}

/* ---- windows ---- */

.g3-win {
	--t: 1.3em;    /* slab thickness */
	--r: 2em;      /* corner radius, also how far the side face is inset */
	position: absolute;
	transform-style: preserve-3d;
	border-radius: var(--r);
	border: .16em solid rgba(255, 255, 255, .14);
	background: linear-gradient(165deg, #1c2540 0%, #0b1020 58%, #06080f 100%);
	box-shadow:
		0 3em 5em -1.6em rgba(0, 0, 0, .95),
		0 0 0 .32em rgba(16, 147, 207, .06),
		inset 0 .14em 0 rgba(255, 255, 255, .14);
}

.g3-win--main {
	left: 6.6em;
	top: 3em;
	width: 21em;
	animation: g3-float 7s ease-in-out infinite;
}

.g3-win--nodes {
	--t: .8em;
	--r: 1.6em;
	left: -3.4em;
	top: -1.6em;
	width: 12.5em;
	transform: translateZ(-8em) rotateY(24deg);
	animation: g3-float 8.5s ease-in-out -2.4s infinite;
}

/*
 * Thickness. Each window is a real slab: a back plate pushed away by --t, plus
 * the one side face the resting pose actually shows (the world's rotateY swings
 * the right edge toward the viewer, so that is the right-hand face). The back
 * plate peeks out on the opposite side, which closes the silhouette.
 */
.g3-slab {
	position: absolute;
	inset: 0;
	border-radius: inherit;
	background: linear-gradient(160deg, #101728 0%, #04060c 100%);
	box-shadow: 0 0 0 1px rgba(255, 255, 255, .05);
	transform: translateZ(calc(-1 * var(--t)));
}

.g3-edge {
	position: absolute;
	top: var(--r);
	left: 100%;
	width: var(--t);
	height: calc(100% - var(--r) * 2);
	background:
		linear-gradient(180deg,
			rgba(255, 255, 255, .13) 0%,
			rgba(255, 255, 255, .02) 35%,
			rgba(0, 0, 0, .55) 100%),
		#0b1220;
	transform-origin: left center;
	transform: rotateY(90deg);
}

/*
 * The patch window is turned the other way (its own rotateY over-corrects the
 * world's), so the face that shows is its left one.
 */
.g3-win--nodes .g3-edge {
	left: auto;
	right: 100%;
	transform-origin: right center;
	transform: rotateY(-90deg);
	background:
		linear-gradient(180deg,
			rgba(255, 255, 255, .10) 0%,
			rgba(255, 255, 255, .02) 35%,
			rgba(0, 0, 0, .6) 100%),
		#0a101c;
}

/* ---- title bar ---- */

.g3-bar {
	display: flex;
	align-items: center;
	gap: .5em;
	padding: .95em 1.2em;
	border-bottom: 1px solid rgba(255, 255, 255, .07);
}

.g3-bar--slim {
	padding: .7em .9em;
}

.g3-bar__title {
	margin-left: auto;
	font-size: .72em;
	letter-spacing: .22em;
	color: var(--nagi-ink-faint);
}

.g3-dot {
	width: .64em;
	height: .64em;
	border-radius: 50%;
	background: var(--nagi-ink-faint);
}

.g3-dot--a { background: #f5c46b; }
.g3-dot--b { background: var(--nagi-lavender); }

.g3-dot--c {
	background: var(--nagi-cyan-bright);
	box-shadow: 0 0 .6em rgba(95, 217, 245, .8);
}

/* ---- plugin body ---- */

.g3-body {
	display: grid;
	gap: 1em;
	padding: 1.1em;
	transform-style: preserve-3d;
}

.g3-screen {
	position: relative;
	height: 7em;
	border-radius: 1.15em;
	overflow: hidden;
	background: linear-gradient(180deg, #05121c 0%, #030a12 100%);
	border: 1px solid rgba(95, 217, 245, .18);
	box-shadow: inset 0 0 2.6em rgba(16, 147, 207, .22);
	transform: translateZ(.3em);
}

.g3-wave {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
}

.g3-wave path {
	fill: none;
	stroke: var(--nagi-cyan-bright);
	stroke-width: 2.4;
	stroke-linecap: round;
	vector-effect: non-scaling-stroke;
	filter: drop-shadow(0 0 .35em rgba(95, 217, 245, .75));
	animation: g3-scroll 5s linear infinite;
}

.g3-screen__gloss {
	position: absolute;
	inset: 0 0 auto;
	height: 45%;
	background: linear-gradient(180deg, rgba(255, 255, 255, .07), rgba(255, 255, 255, 0));
}

/* ---- knobs ---- */

.g3-knobs {
	display: flex;
	justify-content: space-between;
	padding-inline: .5em;
	transform-style: preserve-3d;
}

.g3-knob {
	--kz: 1em;   /* how deep the dial body sits behind its cap */
	position: relative;
	width: 3.5em;
	height: 3.5em;
	border-radius: 50%;
	transform-style: preserve-3d;
	background: radial-gradient(circle at 32% 26%, #33456a 0%, #141c2e 55%, #080c15 100%);
	border: .16em solid rgba(255, 255, 255, .13);
	box-shadow:
		0 .6em 1.1em -.35em rgba(0, 0, 0, .9),
		0 0 0 .3em rgba(16, 147, 207, .07),
		inset 0 -.3em .5em rgba(0, 0, 0, .55),
		inset 0 .22em .35em rgba(255, 255, 255, .1);
	transform: translateZ(1.1em);
	/* a touch of squash keeps it reading as a soft toy dial rather than a disc */
	scale: 1 .96;
}

/*
 * Two discs stacked behind the cap, each a little wider, read as the body of a
 * chunky dial - cheaper and steadier than extruding a real cylinder, and the
 * rim stays visible from every angle the parallax reaches.
 */
.g3-knob::before,
.g3-knob::after {
	content: "";
	position: absolute;
	border-radius: 50%;
	pointer-events: none;
}

.g3-knob::before {
	inset: -.26em;
	background: linear-gradient(180deg, #26324c 0%, #101828 100%);
	transform: translateZ(calc(var(--kz) * -.5));
}

.g3-knob::after {
	inset: -.4em;
	background: linear-gradient(180deg, #35476c 0%, #131b2e 45%, #05070d 100%);
	box-shadow: 0 .7em 1.1em -.55em rgba(0, 0, 0, .9);
	transform: translateZ(calc(var(--kz) * -1));
}

.g3-knob i {
	position: absolute;
	left: calc(50% - .11em);
	top: .34em;
	width: .22em;
	height: 1.1em;
	border-radius: 999px;
	background: var(--nagi-cyan-bright);
	box-shadow: 0 0 .55em rgba(95, 217, 245, .95);
	/* lifted off the cap so it never fights the cap background for paint order */
	transform: translateZ(.06em);
	transform-origin: 50% calc(100% + .37em);
	animation: g3-turn 6s ease-in-out infinite alternate;
}

.g3-knob--1 i { animation-delay: -1.2s; }
.g3-knob--2 i { animation-delay: -3s; }
.g3-knob--3 i { animation-delay: -4.4s; }

/* the oversized dial that pops out in front of the window */
.g3-pop {
	position: absolute;
	right: -.6em;
	bottom: .2em;
	transform: translateZ(7.5em);
	animation: g3-float 5.5s ease-in-out -1.1s infinite;
}

.g3-knob--big {
	--kz: 1.8em;
	display: block;
	width: 6.6em;
	height: 6.6em;
	border-width: .22em;
	box-shadow:
		0 1.4em 2.2em -.6em rgba(0, 0, 0, .95),
		0 0 0 .45em rgba(16, 147, 207, .09),
		inset 0 -.5em .8em rgba(0, 0, 0, .55),
		inset 0 .35em .5em rgba(255, 255, 255, .11);
	transform: none;
}

.g3-knob--big::before { inset: -.4em; }
.g3-knob--big::after  { inset: -.62em; }

.g3-knob--big i {
	left: calc(50% - .17em);
	top: .55em;
	width: .34em;
	height: 2em;
	transform-origin: 50% calc(100% + .73em);
	animation-duration: 7.5s;
	animation-delay: -2.2s;
}

/* ---- sliders ---- */

.g3-sliders {
	display: grid;
	gap: .7em;
	padding-inline: .5em;
	transform-style: preserve-3d;
}

.g3-slider {
	position: relative;
	height: .85em;
	border-radius: 999px;
	background: rgba(255, 255, 255, .07);
	box-shadow: inset 0 .1em .25em rgba(0, 0, 0, .65);
	transform: translateZ(.7em);
	transform-style: preserve-3d;
}

/* the track's own body, so it reads as a groove cut into a rail */
.g3-slider::after {
	content: "";
	position: absolute;
	inset: -.16em -.1em;
	border-radius: 999px;
	background: linear-gradient(180deg, #1b2439 0%, #05070d 100%);
	transform: translateZ(-.55em);
}

.g3-slider i {
	position: absolute;
	inset: 0 auto 0 0;
	width: var(--v, 50%);
	border-radius: 999px;
	background: linear-gradient(90deg, var(--nagi-blue-deep), var(--nagi-cyan-bright));
	box-shadow: 0 0 .8em rgba(16, 147, 207, .65);
}

.g3-slider i::after {
	content: "";
	position: absolute;
	right: -.6em;
	top: 50%;
	width: 1.4em;
	height: 1.4em;
	margin-top: -.7em;
	border-radius: 50%;
	background: linear-gradient(180deg, #ffffff, #cfe6f5);
	/* the dark ring is the thumb's own side wall */
	box-shadow:
		0 0 0 .14em #0a1120,
		0 .1em 0 .16em rgba(0, 0, 0, .55),
		0 .4em .8em -.15em rgba(0, 0, 0, .9);
	transform: translateZ(.35em);
}

/* ---- node editor ---- */

.g3-nodes {
	position: relative;
	height: 8.5em;
	transform-style: preserve-3d;
}

.g3-node {
	position: absolute;
	width: 3.4em;
	height: 1.9em;
	border-radius: .8em;
	background: linear-gradient(180deg, #24314f, #0d1322);
	border: .14em solid rgba(255, 255, 255, .14);
	box-shadow: 0 .5em .9em -.35em rgba(0, 0, 0, .9);
	transform: translateZ(.6em);
	transform-style: preserve-3d;
}

/* node bodies get the same slab treatment, one plate deep */
.g3-node::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	background: linear-gradient(180deg, #131a2c, #04060c);
	transform: translateZ(-.5em);
}

.g3-node--1 { left: .7em;  top: 1.5em; }
.g3-node--2 { left: .7em;  top: 5.4em; }
.g3-node--3 { left: 5.1em; top: 3.4em; border-color: rgba(95, 217, 245, .45); }

.g3-cables {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
}

.g3-cables path {
	fill: none;
	stroke: var(--nagi-cyan);
	stroke-width: 2;
	stroke-linecap: round;
	stroke-dasharray: 6 5;
	vector-effect: non-scaling-stroke;
	animation: g3-flow 1.6s linear infinite;
}

/* ---- sparkles ---- */

.g3-spark {
	position: absolute;
	width: .5em;
	height: .5em;
	border-radius: 50%;
	background: var(--nagi-cyan-bright);
	box-shadow: 0 0 .9em rgba(95, 217, 245, .95);
	animation: g3-twinkle 3.4s ease-in-out infinite;
}

.g3-spark--1 { left: 25.5em; top: .8em;  transform: translateZ(5em); }
.g3-spark--2 { left: .6em;   top: 19em;  transform: translateZ(3em); animation-delay: -1.1s; }
.g3-spark--3 { left: 21em;   top: 23.5em; transform: translateZ(6.5em); animation-delay: -2.3s; }

/* ---- motion ---- */

@keyframes g3-float {
	50% { translate: 0 -1.1em; }
}

@keyframes g3-turn {
	from { rotate: -128deg; }
	to   { rotate: 122deg; }
}

@keyframes g3-scroll {
	to { translate: -40px 0; }
}

@keyframes g3-flow {
	to { stroke-dashoffset: -11; }
}

@keyframes g3-twinkle {
	0%, 100% { opacity: .25; scale: .7; }
	50%      { opacity: 1;   scale: 1.15; }
}

@media (prefers-reduced-motion: reduce) {
	.nagi-scene * {
		animation: none !important;
	}
}

@media (max-width: 991.98px) {
	/* below lg the scene drops out of the overlay and sits under the copy */
	.nagi-hero__scene {
		position: static;
		transform: none;
		width: 100%;
		height: auto;
	}

	.nagi-scene,
	.nagi-hero__scene .nagi-scene {
		margin-top: 2.5rem;
		/*
		 * Not em: that resolves against the scene's own font-size, which bottoms
		 * out at 8px on a phone - 208px of canvas. The render is fitted to the
		 * shorter axis, so the panel came out postage-stamp sized with empty
		 * hero below it. Size it off the viewport instead.
		 */
		height: min(46vh, 24rem);
	}

	/*
	 * The resting pose swings the window's right edge toward the viewer, which
	 * perspective then magnifies outward - fine in the desktop column, but it
	 * runs off a phone. Pull the whole composition in rather than re-posing it.
	 */
	.nagi-scene__world {
		scale: .78;
	}
}

/* ---------------------------------------------------------------- cards */

/* No height here. This used to be `height: 100%`, for the four spec cards that
   sit side by side and should line up — but a Bootstrap column stretches to
   its row, so 100% resolved against the FULL column on every page that stacks
   cards down one column: each card grew to the height of the whole page and
   pushed the footer up into the middle of the content. Cards that want to
   match a neighbour opt in with Bootstrap's .h-100 instead. */
.nagi-card {
	position: relative;
	padding: 2rem;
	border-radius: var(--nagi-radius-lg);
	border: 1px solid var(--nagi-line);
	background: linear-gradient(180deg, rgba(255, 255, 255, .035) 0%, rgba(255, 255, 255, .012) 100%);
	transition: border-color .3s, transform .3s cubic-bezier(.2, .7, .3, 1);
	overflow: hidden;
}

.nagi-card:hover {
	border-color: var(--nagi-line-strong);
	transform: translateY(-4px);
}

.nagi-card h3 {
	font-size: 1.2rem;
	margin-bottom: .75rem;
}

.nagi-card p {
	color: var(--nagi-ink-dim);
	font-size: .95rem;
	line-height: 1.65;
	margin-bottom: 0;
}

.nagi-card__index {
	font-size: .78rem;
	letter-spacing: .12em;
	color: var(--nagi-ink-faint);
	margin-bottom: 1.5rem;
	display: block;
}

.nagi-card__icon {
	width: 2.75rem;
	height: 2.75rem;
	display: grid;
	place-items: center;
	border-radius: 11px;
	margin-bottom: 1.5rem;
	background: rgba(16, 147, 207, .12);
	border: 1px solid rgba(16, 147, 207, .28);
	color: var(--nagi-cyan-bright);
	font-size: 1.15rem;
}

/* ------------------------------------------------------------- pricing */

.nagi-price {
	display: flex;
	align-items: baseline;
	gap: .5rem;
	margin-block: 1.25rem 1.75rem;
}

.nagi-price__amount {
	font-size: clamp(2.5rem, 4.5vw, 3.5rem);
	font-weight: 500;
	letter-spacing: -.03em;
	color: var(--nagi-ink);
	line-height: 1;
}

.nagi-price__note {
	font-size: .9rem;
	color: var(--nagi-ink-faint);
}

.nagi-card--featured {
	border-color: rgba(16, 147, 207, .45);
	background:
		linear-gradient(180deg, rgba(16, 147, 207, .09) 0%, rgba(255, 255, 255, .012) 60%);
}

.nagi-card--featured::before {
	content: "";
	position: absolute;
	inset: -1px -1px auto;
	height: 1px;
	background: var(--nagi-gradient);
}

.nagi-featurelist {
	list-style: none;
	padding: 0;
	margin: 0;
	display: grid;
	gap: .8rem;
}

/*
 * The bullet is absolutely positioned rather than a flex sibling. As a flex item
 * it turned every inline <code> chip into its own flex item, which threw the
 * chips to the end of the line and split them mid-word.
 */
.nagi-featurelist li {
	position: relative;
	padding-left: 1.75rem;
	font-size: .93rem;
	line-height: 1.6;
	color: var(--nagi-ink-dim);
}

.nagi-featurelist li::before {
	content: "";
	position: absolute;
	left: 0;
	top: .28em;
	width: 1.05rem;
	height: 1.05rem;
	border-radius: 50%;
	background:
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%235fd9f5' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5l3 3 6-6'/%3E%3C/svg%3E") center / 74% no-repeat,
		rgba(16, 147, 207, .13);
}

.nagi-featurelist li.is-locked {
	color: var(--nagi-ink-faint);
}

.nagi-featurelist li.is-locked::before {
	background:
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%235d6068' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='M5 5l6 6M11 5l-6 6'/%3E%3C/svg%3E") center / 62% no-repeat,
		rgba(255, 255, 255, .04);
}

/* ------------------------------------------------------ pipeline diagram */

.nagi-flow {
	margin-top: clamp(3rem, 6vw, 5.5rem);
}

.nagi-flow svg {
	width: 100%;
	height: auto;
	overflow: visible;
}

.nagi-flow__label {
	fill: var(--nagi-ink);
	font-size: 19px;
	font-weight: 500;
	letter-spacing: -.01em;
}

.nagi-flow__badge {
	fill: var(--nagi-cyan-bright);
	font-size: 20px;
	font-weight: 500;
	font-family: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
	letter-spacing: .04em;
}

/* signal running left to right along the wire */
.nagi-flow__pulse {
	stroke-dashoffset: 1200;
	animation: nagi-run 4.2s linear infinite;
}

@keyframes nagi-run {
	to {
		stroke-dashoffset: -1200;
	}
}

/* each stage breathes, staggered along the chain */
.nagi-flow__stage {
	animation: nagi-lift 5s ease-in-out infinite;
	animation-delay: calc(var(--i) * .38s);
	transform-box: fill-box;
	transform-origin: center;
}

@keyframes nagi-lift {
	0%, 100% { transform: translateY(0); }
	50%      { transform: translateY(-6px); }
}

/*
 * The preview stage scrolls a waveform through a clipped window. One period of
 * the wave is 32 user units, so translating by exactly -32 loops with no seam.
 */
.nagi-flow__wave {
	animation: nagi-wave 1.5s linear infinite;
}

@keyframes nagi-wave {
	from {
		transform: translateX(0);
	}

	to {
		transform: translateX(-32px);
	}
}

/* connection points blink as the signal passes them */
.nagi-flow__dots circle {
	animation: nagi-blip 4.2s ease-in-out infinite;
	animation-delay: calc(var(--i) * .5s);
	transform-box: fill-box;
	transform-origin: center;
}

@keyframes nagi-blip {
	0%, 55%, 100% { opacity: .45; transform: scale(1); }
	18%           { opacity: 1;   transform: scale(1.55); }
}

.nagi-flow__decor path {
	animation: nagi-drift 9s ease-in-out infinite alternate;
}

@keyframes nagi-drift {
	to {
		transform: translate3d(14px, -10px, 0);
	}
}

@media (prefers-reduced-motion: reduce) {
	.nagi-flow__pulse,
	.nagi-flow__stage,
	.nagi-flow__wave,
	.nagi-flow__decor path,
	.nagi-flow__dots circle {
		animation: none;
	}
}

/* ------------------------------------------------------ feature rows */

.nagi-feature + .nagi-feature {
	margin-top: clamp(4.5rem, 9vw, 8rem);
}

.nagi-feature h3 {
	margin-block: 0 1.25rem;
}

.nagi-feature--flip > [class*="col-"]:first-child {
	order: 2;
}

@media (max-width: 991.98px) {
	.nagi-feature--flip > [class*="col-"]:first-child {
		order: 0;
	}

	.nagi-feature > [class*="col-"] + [class*="col-"] {
		margin-top: 2.5rem;
	}
}

/* screenshot frame - sits the shot on a lit slab so it reads on black */
.nagi-shot {
	position: relative;
	margin: 0;
	border-radius: var(--nagi-radius-lg);
	border: 1px solid var(--nagi-line);
	background: linear-gradient(180deg, rgba(255, 255, 255, .05), rgba(255, 255, 255, .012));
	padding: .5rem;
	overflow: hidden;
	box-shadow: 0 40px 90px -40px rgba(0, 0, 0, .9);
}

/* brand-tinted bloom bleeding out from behind the frame */
.nagi-shot::after {
	content: "";
	position: absolute;
	inset: auto -30% -55% -30%;
	height: 65%;
	background: radial-gradient(60% 100% at 50% 0%, rgba(16, 147, 207, .3), transparent 70%);
	filter: blur(46px);
	pointer-events: none;
	z-index: -1;
}

.nagi-shot img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: calc(var(--nagi-radius-lg) - 6px);
}

.nagi-shot--narrow {
	max-width: 34rem;
	margin-inline: auto;
}

code.nagi-mono {
	color: var(--nagi-cyan-bright);
	background: rgba(16, 147, 207, .1);
	border: 1px solid rgba(16, 147, 207, .2);
	border-radius: 6px;
	padding: .1rem .4rem;
	font-size: .85em;
	/* never split a filename or parameter path across two lines */
	white-space: nowrap;
}

/* --------------------------------------------------------------- footer */

footer,
.footer-3 {
	background: var(--nagi-bg-sunken) !important;
	border-top: 1px solid var(--nagi-line);
	padding-block: 5rem 2.5rem;
}

footer a {
	color: var(--nagi-ink-dim);
	text-decoration: none;
	transition: color .2s;
}

footer a:hover {
	color: var(--nagi-ink);
}

footer .footer-brand img {
	height: 24px;
	margin-bottom: 1.25rem;
}

/* footer brand lockup: mark + wordmark, same relationship as the header */
.nagi-footer-mark {
	height: 30px;
	width: auto;
	vertical-align: middle;
	margin-right: .55rem;
}

footer [data-v-component-site] img {
	height: 24px;
	width: auto;
	vertical-align: middle;
}

/* --------------------------------------------------------------- forms */

.form-control,
.form-select {
	background: rgba(255, 255, 255, .03);
	border: 1px solid var(--nagi-line);
	border-radius: var(--nagi-radius);
	color: var(--nagi-ink);
	padding: .85rem 1.1rem;
}

.form-control::placeholder {
	color: var(--nagi-ink-faint);
}

.form-control:focus,
.form-select:focus {
	background: rgba(255, 255, 255, .05);
	border-color: var(--nagi-cyan);
	box-shadow: 0 0 0 3px rgba(16, 147, 207, .16);
	color: var(--nagi-ink);
}

/* The open dropdown is drawn by the OS, not by this stylesheet, and on Windows
   it keeps a light background even though the closed control is dark. The
   options inherit .form-select's near-white ink, so they came out white on
   white — legible only on the row the pointer happened to be over. Both halves
   of the pair are pinned here rather than just the text: leaving the background
   to the platform reproduces the same bug inverted wherever the popup is drawn
   dark. */
.form-select option,
.form-control option {
	background: #fff;
	color: #111;
}

/* ------------------------------------------------------------ utilities */

.nagi-divider {
	height: 1px;
	background: linear-gradient(90deg, transparent, var(--nagi-line-strong), transparent);
	border: 0;
	margin: 0;
	opacity: 1;
}

.nagi-glow {
	position: absolute;
	border-radius: 50%;
	filter: blur(90px);
	opacity: .5;
	pointer-events: none;
	z-index: 0;
}

.nagi-mono {
	font-family: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
	font-size: .85rem;
}

/* Cart quantity stepper: −  [ 2 ]  ＋ drawn as one pill so the three controls
   read as a single widget. The number field is a real input so a buyer can
   type a quantity and press Enter; the buttons submit the same form. */
.nagi-qty {
	display: inline-flex;
	align-items: stretch;
	border: 1px solid var(--nagi-line-strong);
	border-radius: var(--nagi-radius-pill);
	overflow: hidden;
}

.nagi-qty__btn {
	width: 2.4rem;
	background: transparent;
	border: 0;
	color: var(--nagi-ink);
	font-size: 1.1rem;
	line-height: 1;
	cursor: pointer;
	transition: background .2s, color .2s;
}

.nagi-qty__btn:hover {
	background: rgba(16, 147, 207, .12);
	color: var(--nagi-cyan-bright);
}

.nagi-qty__input {
	width: 3.2rem;
	padding: .45rem 0;
	text-align: center;
	background: transparent;
	border: 0;
	border-left: 1px solid var(--nagi-line);
	border-right: 1px solid var(--nagi-line);
	color: var(--nagi-ink);
	font-family: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
	-moz-appearance: textfield;
}

.nagi-qty__input::-webkit-outer-spin-button,
.nagi-qty__input::-webkit-inner-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

.nagi-qty__input:focus {
	outline: none;
	background: rgba(255, 255, 255, .05);
}

/* honour reduced-motion for the AOS reveals the theme ships with */
/*
 * AOS hides an element until it scrolls into view, and does it with
 * `[data-aos] { pointer-events: none }`, restored by `.aos-animate`.
 *
 * Both branches below show the element without AOS ever adding that class, so
 * both have to hand the pointer back too. Missing it cost a real bug: with
 * Reduce Motion on, the iPhone hero showed its badge and both buttons
 * perfectly and every tap fell straight through them to the column behind,
 * because init is skipped for reduced motion and `.aos-animate` never arrived.
 */
@media (prefers-reduced-motion: reduce) {
	[data-aos] {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
		pointer-events: auto !important;
	}
}

/* Set by base.latte whenever AOS will not run — reduced motion, or the script
   simply never arrived. Same reasoning: visible means tappable. */
.aos-off [data-aos] {
	opacity: 1 !important;
	transform: none !important;
	transition: none !important;
	pointer-events: auto !important;
}

/* ------------------------------------------------ content pages (TypeDock) */

/*
 * Non-home pages (page/single/archive/search/errors) have no hero, so the
 * first section must clear the floating nav on its own and give the page
 * some vertical breathing room.
 */
.nagi-content {
	padding-top: clamp(7rem, 12vw, 10rem);
	min-height: 60vh;
}

.content-header {
	margin-bottom: clamp(2rem, 4vw, 3.5rem);
}

.content-header .display-3 {
	margin-top: .5rem;
}

/* Tiptap / Markdown body output */
.entry-content {
	font-size: 1.02rem;
	line-height: 1.8;
	color: var(--nagi-ink-dim);
	max-width: 72ch;
}

.entry-content > * + * {
	margin-top: 1.4rem;
}

.entry-content h2,
.entry-content h3,
.entry-content h4 {
	margin-top: 2.6rem;
	margin-bottom: .2rem;
}

.entry-content h2 { font-size: 1.7rem; }
.entry-content h3 { font-size: 1.35rem; }

.entry-content a {
	color: var(--nagi-cyan-bright);
	text-decoration: underline;
	text-underline-offset: .18em;
}

.entry-content a:hover { color: #fff; }

.entry-content ul,
.entry-content ol {
	padding-left: 1.4rem;
}

.entry-content li + li { margin-top: .5rem; }

.entry-content blockquote {
	margin: 2rem 0;
	padding: .5rem 0 .5rem 1.4rem;
	border-left: 3px solid var(--nagi-cyan);
	color: var(--nagi-ink);
}

.entry-content :not(pre) > code {
	padding: .12em .34em;
	border-radius: 5px;
	background: rgba(16, 147, 207, .1);
	border: 1px solid rgba(16, 147, 207, .2);
	color: var(--nagi-cyan-bright);
	font-size: .9em;
}

.entry-content pre {
	margin: 1.75rem 0;
	padding: 1.1rem 1.25rem;
	overflow-x: auto;
	border-radius: var(--nagi-radius);
	border: 1px solid var(--nagi-line);
	background: var(--nagi-bg-raised);
	color: #e7f4ff;
}

.entry-content pre > code {
	background: none;
	border: 0;
	padding: 0;
	color: inherit;
}

.entry-content img,
.entry-content figure { max-width: 100%; height: auto; border-radius: var(--nagi-radius); }

.entry-content hr { border: 0; border-top: 1px solid var(--nagi-line); margin: 2.5rem 0; }

.entry-content table {
	display: block;
	width: 100%;
	overflow-x: auto;
	border-collapse: collapse;
}

.entry-content th,
.entry-content td {
	padding: .625rem .75rem;
	border: 1px solid var(--nagi-line);
	text-align: left;
}

.entry-content th { color: var(--nagi-ink); }

/* accessibility helpers required by the theme checklist */
.sr-only {
	position: absolute !important;
	width: 1px; height: 1px;
	padding: 0; margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.skip-link {
	position: absolute;
	left: -999px;
	top: 0;
	z-index: 1000;
}

.skip-link:focus {
	left: 1rem;
	top: 1rem;
	width: auto;
	height: auto;
	padding: .6rem 1rem;
	background: var(--nagi-ink);
	color: #050505;
	border-radius: var(--nagi-radius-pill);
	clip: auto;
}

/* footer link column headings reuse the eyebrow but need block layout */
.footer-3 h4.nagi-eyebrow { display: flex; margin-bottom: 1rem; }
.footer-3 .list-unstyled a { font-size: .92rem; }

/* nav CTA sign-in link */
.navbar-cta .nav-link { color: var(--nagi-ink); font-weight: 500; font-size: .9rem; }
.navbar-cta .nav-link:hover { color: var(--nagi-cyan-bright); }

/* Sign-out posts a form, so that nav item is a <button>. It has to read as the
   sign-in link it replaces, which means dropping the UA button chrome. */
.nagi-linkbutton {
	background: none;
	border: 0;
	padding: 0;
	font: inherit;
	cursor: pointer;
}

/* --------------------------------------------------------- community board */

.nagi-tag {
	display: inline-flex;
	align-items: center;
	padding: .25rem .7rem;
	border-radius: var(--nagi-radius-pill);
	font-size: .75rem;
	font-weight: 500;
	border: 1px solid var(--nagi-line-strong);
	color: var(--nagi-ink-dim);
	white-space: nowrap;
}

.nagi-tag--category-feature_request { border-color: rgba(16, 147, 207, .4); color: var(--nagi-cyan-bright); }
.nagi-tag--category-bug_report { border-color: rgba(220, 90, 90, .4); color: #f0a3a3; }
.nagi-tag--status-open,
.nagi-tag--status-in_progress { border-color: rgba(16, 147, 207, .4); color: var(--nagi-cyan-bright); }
.nagi-tag--status-planned { border-color: rgba(184, 160, 90, .45); color: #e0c584; }
.nagi-tag--status-fixed { border-color: rgba(90, 190, 120, .45); color: #8fe0ab; }
.nagi-tag--status-wontfix,
.nagi-tag--status-closed { border-color: var(--nagi-line-strong); color: var(--nagi-ink-faint); }

.nagi-topic-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	flex-wrap: wrap;
	padding: 1.25rem 0;
	border-bottom: 1px solid var(--nagi-line);
}

.nagi-topic-row:first-child { padding-top: 0; }
.nagi-topic-row:last-child { border-bottom: 0; }

.nagi-topic-row h3 { font-size: 1.05rem; margin: 0 0 .35rem; }
.nagi-topic-row h3 a { color: var(--nagi-ink); text-decoration: none; }
.nagi-topic-row h3 a:hover { color: var(--nagi-cyan-bright); }

.nagi-topic-meta {
	display: flex;
	align-items: center;
	gap: .6rem;
	flex-wrap: wrap;
	color: var(--nagi-ink-faint);
	font-size: .82rem;
}

.nagi-reply {
	padding: 1.25rem 0;
	border-bottom: 1px solid var(--nagi-line);
}

.nagi-reply:last-child { border-bottom: 0; }

.nagi-reply-meta {
	color: var(--nagi-ink-faint);
	font-size: .82rem;
	margin-bottom: .5rem;
}

.nagi-reply-actions {
	margin-top: .75rem;
}

.nagi-like-form { display: inline-block; }

.nagi-like-btn {
	display: inline-flex;
	align-items: center;
	gap: .4rem;
	padding: .3rem .7rem;
	border-radius: var(--nagi-radius-pill);
	border: 1px solid var(--nagi-line-strong);
	background: transparent;
	color: var(--nagi-ink-faint);
	font-size: .82rem;
	line-height: 1;
	cursor: pointer;
	transition: border-color .15s ease, color .15s ease;
}

.nagi-like-btn:hover { border-color: var(--nagi-cyan-bright); color: var(--nagi-cyan-bright); }

.nagi-like-btn.is-liked {
	border-color: var(--nagi-cyan-bright);
	color: var(--nagi-cyan-bright);
	background: rgba(16, 147, 207, .12);
}

.nagi-like-btn--static { cursor: default; }
.nagi-like-btn--static:hover { border-color: var(--nagi-line-strong); color: var(--nagi-ink-faint); }

/* The topic's own like sits under the post rather than beside a reply, so it
   is sized to be found rather than to stay out of the way. */
.nagi-like-btn--lg {
	gap: .55rem;
	padding: .55rem 1.1rem;
	font-size: .9rem;
}

.nagi-like-btn--lg .nagi-like-icon {
	width: 1.15rem;
	height: 1.15rem;
}

/* Read-only count in the topic list — a number with an icon, not a control. */
.nagi-like-inline {
	display: inline-flex;
	align-items: center;
	gap: .3rem;
}

.nagi-like-inline.is-liked { color: var(--nagi-cyan-bright); }
.nagi-like-inline.is-liked .nagi-like-icon { fill: currentColor; }

.nagi-like-inline .nagi-like-icon {
	width: .9rem;
	height: .9rem;
}

.nagi-like-icon {
	width: 1rem;
	height: 1rem;
	flex: none;
}

/* Outline until it is yours, solid once it is. The fill carries the state on
   its own, so "already liked" survives being read by someone who cannot pick
   the cyan out from the grey. */
.nagi-like-btn.is-liked .nagi-like-icon {
	fill: currentColor;
}

.nagi-like-count { font-weight: 500; }

.nagi-category-tabs {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
	margin-bottom: 2rem;
}

.nagi-category-tabs a {
	padding: .5rem 1.1rem;
	border-radius: var(--nagi-radius-pill);
	border: 1px solid var(--nagi-line);
	color: var(--nagi-ink-dim);
	text-decoration: none;
	font-size: .85rem;
	font-weight: 500;
}

.nagi-category-tabs a.is-active,
.nagi-category-tabs a:hover {
	border-color: var(--nagi-cyan);
	color: var(--nagi-cyan-bright);
	background: rgba(16, 147, 207, .08);
}
