/* =====================================================================
   PLATFORM INTEGRATIONS — scroll-driven circuit visual
   =====================================================================

   Single source of truth: --bpi-progress (0..1), written every scroll
   frame by assets/js/platform-integrated.js.

   - 0  : visual about to enter the viewport, nothing drawn
   - 1  : visual centred in the viewport, all branches drawn, all nodes lit

   Per-branch draw progress (--bpi-branch-N) and per-node lit intensity
   (--bpi-node-N) are derived from --bpi-progress in the JS using the
   data-start / data-end windows authored in the PHP template. The CSS
   only has to read those values and translate them into
   stroke-dashoffsets and opacity / filter effects.

   All node data is fixed in PHP (six endpoints, alternating L/R).
   No hardcoded branch lengths anywhere — every path uses pathLength="1"
   so the CSS treats each path as a 0..1 unit of length.
   ===================================================================== */

/* The panel: dark circuit-board background, sits inside the
   .blok-platform-section__visual box that the deep-dive layout
   already provides. */
.blok-platform-section--integrations .blok-platform-section__visual {
	background: #040814;
	overflow: hidden;
	isolation: isolate;
}

.blok-platform-integrated {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	--bpi-progress: 0;
	--bpi-trunk-draw: 0;
}

.bpi-svg {
	display: block;
	width: 100%;
	height: 100%;
	overflow: visible;
}

/* ============== BACK: Board + sheen + ambient halos ============== */
.bpi-sheen {
	animation: bpi-sheen-sweep 28s linear infinite;
	mix-blend-mode: screen;
}

@keyframes bpi-sheen-sweep {
	0%   { opacity: 0;    transform: translateX(-25%); }
	15%  { opacity: 0.45; }
	50%  { opacity: 0;    transform: translateX(25%); }
	100% { opacity: 0;    transform: translateX(25%); }
}

.bpi-mesh-orb {
	animation: bpi-mesh-pulse 9s ease-in-out infinite;
	transform-origin: center;
	transform-box: fill-box;
}
.bpi-mesh-orb--2 {
	animation-delay: -4s;
	animation-duration: 11s;
}

@keyframes bpi-mesh-pulse {
	0%, 100% { opacity: 0.65; }
	50%      { opacity: 0.95; }
}

/* ============== BACK: Substrate grid (subtle pulse) ============== */
.bpi-grid circle {
	animation: bpi-grid-blink 6s ease-in-out infinite;
}
.bpi-grid circle:nth-child(7n)  { animation-delay: -0.6s; }
.bpi-grid circle:nth-child(11n) { animation-delay: -2.1s; }
.bpi-grid circle:nth-child(13n) { animation-delay: -3.4s; }

@keyframes bpi-grid-blink {
	0%, 100% { opacity: 0.6; }
	50%      { opacity: 1;   }
}

/* ============== BACK: Centre halo (behind the core) ============== */
.bpi-core-halo {
	animation: bpi-core-halo-pulse 4.5s ease-in-out infinite;
	transform-origin: center;
	transform-box: fill-box;
}

@keyframes bpi-core-halo-pulse {
	0%, 100% { opacity: 0.7; transform: scale(1); }
	50%      { opacity: 1;   transform: scale(1.05); }
}

/* ============== TRUNK: vertical neon line, drawn top → bottom ==============
   --bpi-trunk-draw (0..1) is written by the JS (clamped to 0 outside the
   trunk window, 1 inside). 1 = fully drawn. stroke-dasharray uses
   pathLength=1 so the dashoffset is a fraction. */
.bpi-trunk {
	stroke-dasharray: 1 1;
	stroke-dashoffset: calc(1 - var(--bpi-trunk-draw, 0));
	filter: url(#bpi-glow);
	transition: stroke-dashoffset 80ms linear;
}

/* ============== TRUNK CAP: top input badge ============== */
.bpi-trunk-cap__bg {
	transition: stroke 200ms var(--ease, ease);
}
.bpi-trunk-cap__dot {
	filter: drop-shadow(0 0 3px rgba(167, 139, 250, 0.85));
	animation: bpi-cap-dot-blink 2.4s ease-in-out infinite;
}

@keyframes bpi-cap-dot-blink {
	0%, 100% { opacity: 0.55; }
	50%      { opacity: 1;    }
}

/* ============== BRANCHES: orthogonal neon traces ==============
   --bpi-branch-N-draw is written by the JS (0..1) per branch group.
   0 = not started, 1 = fully drawn. */
.bpi-branch {
	stroke-dasharray: 1 1;
	stroke-dashoffset: calc(1 - var(--bpi-branch-draw, 0));
	transition: stroke-dashoffset 80ms linear;
}

/* ============== NODES: database cylinder endpoints ==============
   Each node group carries --bpi-node-N-lit (0..1) once the branch
   finishes drawing. 0 = dormant (dim, low-opacity stroke), 1 = lit
   (full brand gradient, soft glow, port pulses).

   Inactive state is the default; active state is additive on top. */
.bpi-node {
	opacity: calc(0.45 + 0.55 * var(--bpi-node-lit, 0));
	transition: opacity 200ms var(--ease, ease);
}

.bpi-node__rim,
.bpi-node__shell,
.bpi-node__shelf {
	stroke-width: 1.4;
	transition: stroke-width 200ms var(--ease, ease);
}

/* Lit boost: thicker stroke when fully lit */
.bpi-node[style*="--bpi-node-lit: 1"],
.bpi-node[data-lit="true"] .bpi-node__rim,
.bpi-node[data-lit="true"] .bpi-node__shell {
	stroke-width: 1.8;
}

/* Glow behind the cylinder, ramps with lit value */
.bpi-node__halo {
	opacity: var(--bpi-node-lit, 0);
	transform-box: fill-box;
	transform-origin: center;
	transform: scale(calc(0.8 + 0.4 * var(--bpi-node-lit, 0)));
	transition: opacity 200ms var(--ease, ease), transform 200ms var(--ease, ease);
}

/* Port (top connection point) — soft pulse when lit */
.bpi-node__port {
	opacity: calc(0.6 + 0.4 * var(--bpi-node-lit, 0));
	filter: drop-shadow(0 0 calc(2px * var(--bpi-node-lit, 0)) rgba(167, 139, 250, 0.8));
	transition: filter 200ms var(--ease, ease);
}

/* One-shot connection pulse — fades out after the branch completes.
   Played by toggling .is-connected on the node group from the JS. */
.bpi-node.is-connected .bpi-node__pulse {
	animation: bpi-node-pulse 1.2s var(--ease, ease-out) forwards;
}

.bpi-node__pulse {
	opacity: 0;
	transform-box: fill-box;
	transform-origin: center;
}

@keyframes bpi-node-pulse {
	0%   { opacity: 0.9; transform: scale(0.4); }
	60%  { opacity: 0.5; transform: scale(1.6); }
	100% { opacity: 0;   transform: scale(2.2); }
}

/* Slow breathing on already-lit nodes (ambient life) */
.bpi-node[data-lit="true"] .bpi-node__rim,
.bpi-node[data-lit="true"] .bpi-node__shell {
	animation: bpi-node-breathe 4.2s ease-in-out infinite;
}

@keyframes bpi-node-breathe {
	0%, 100% { stroke-opacity: 0.85; }
	50%      { stroke-opacity: 1;    }
}

/* ============== CENTRE CORE ============== */
.bpi-core__ring {
	animation: bpi-core-ring-spin 60s linear infinite;
	transform-box: fill-box;
	transform-origin: center;
}

@keyframes bpi-core-ring-spin {
	to { transform: rotate(360deg); }
}

.bpi-core__disc {
	filter: drop-shadow(0 0 8px rgba(236, 72, 153, 0.45));
}

.bpi-core__label {
	opacity: calc(0.6 + 0.4 * var(--bpi-progress, 0));
	transition: opacity 220ms var(--ease, ease);
}

/* ============== HUD overlay ==============
   Sits in the top-right of the panel. Two stacked labels swap
   based on --bpi-progress (the JS flips .is-connected on the
   .blok-platform-integrated wrapper at progress >= 0.95). */
.bpi-hud {
	position: absolute;
	top: 14px;
	right: 14px;
	z-index: 5;
	pointer-events: none;
}

.bpi-hud__pill {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 6px 12px 6px 10px;
	background: rgba(8, 17, 31, 0.78);
	border: 1px solid rgba(139, 92, 246, 0.35);
	border-radius: 999px;
	font-family: 'JetBrains Mono', ui-monospace, monospace;
	font-size: 10.5px;
	font-weight: 700;
	letter-spacing: 0.12em;
	color: #C4B5FD;
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	transition: border-color 200ms var(--ease, ease), color 200ms var(--ease, ease);
}

.bpi-hud__dot {
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: #A78BFA;
	box-shadow: 0 0 6px rgba(167, 139, 250, 0.8);
	animation: bpi-hud-dot-blink 1.4s ease-in-out infinite;
}

.bpi-hud__label {
	display: inline-block;
}
.bpi-hud__label--final { display: none; }

/* Once everything is connected, swap the pill content + colour. */
.blok-platform-integrated.is-connected .bpi-hud__pill {
	border-color: rgba(16, 185, 129, 0.55);
	color: #A7F3D0;
}
.blok-platform-integrated.is-connected .bpi-hud__dot {
	background: #10B981;
	box-shadow: 0 0 8px rgba(16, 185, 129, 0.9);
	animation: none;
}
.blok-platform-integrated.is-connected .bpi-hud__label--interim { display: none; }
.blok-platform-integrated.is-connected .bpi-hud__label--final    { display: inline-block; }

@keyframes bpi-hud-dot-blink {
	0%, 100% { opacity: 0.55; }
	50%      { opacity: 1;    }
}

/* ============== No-JS fallback ==============
   If scripting is disabled, paint the visual in its fully lit
   state so the section is still readable and the screenshot
   test still passes. */
@media (scripting: none) {
	.blok-platform-integrated {
		--bpi-progress: 1;
		--bpi-trunk-draw: 1;
		--bpi-branch-draw: 1;
		--bpi-node-lit: 1;
	}
	.bpi-trunk,
	.bpi-branch {
		stroke-dashoffset: 0;
	}
	.bpi-node {
		opacity: 1;
	}
	.bpi-hud__label--interim { display: none; }
	.bpi-hud__label--final    { display: inline-block; }
	.bpi-hud__pill {
		border-color: rgba(16, 185, 129, 0.55);
		color: #A7F3D0;
	}
	.bpi-hud__dot {
		background: #10B981;
		animation: none;
	}
}

/* ============== Reduced motion ==============
   The JS already pins --bpi-progress to 1 when the user prefers
   reduced motion. This block covers the brief window before the
   JS initialises, and the case where the user toggles the media
   query at runtime. */
@media (prefers-reduced-motion: reduce) {
	.bpi-sheen,
	.bpi-mesh-orb,
	.bpi-grid circle,
	.bpi-core-halo,
	.bpi-core__ring,
	.bpi-trunk-cap__dot,
	.bpi-hud__dot,
	.bpi-node[data-lit="true"] .bpi-node__rim,
	.bpi-node[data-lit="true"] .bpi-node__shell {
		animation: none;
	}
	.bpi-node.is-connected .bpi-node__pulse {
		animation: none;
		opacity: 0;
	}
}

/* ============== Mobile refinements ==============
   On narrow viewports the deep-dive layout already stacks the
   visual under the copy; we just trim the HUD a touch so it
   doesn't crowd the trunk cap. */
@media (max-width: 600px) {
	.bpi-hud {
		top: 10px;
		right: 10px;
	}
	.bpi-hud__pill {
		font-size: 9.5px;
		padding: 4px 10px 4px 8px;
	}
}
