@charset "UTF-8";

/* ============================================================
   EXPONENTIAL POSSIBILITY ARCHITECTURE
   exponential-possibility-architecture.css

   Styles for the generative canvas in the code.html entry of the same
   name (engine: js/exponential-possibility-architecture.js). It uses the
   shared Interactive Module layout (css/component-layout.css):

     <div class="interactive-module interactive-frame epa-widget">
       <div class="interactive-module__stage">
         <div class="epa-stage" id="epaStage"> canvases, loader </div>
       </div>
       <div class="interactive-module__bar"> controls | how it works </div>
     </div>

   so the module owns the bleed, the 16:9 stage, the frame and the
   controls/guide bar. This file only styles the EPA-specific parts.

   THEME
   Every visual setting is a custom property on .epa-widget, pointed
   at the design-system tokens in css/tokens.css. The JS reads them
   live every frame, so they follow the tokens (and dark mode, once
   it's switched on) with no JS changes.
   ============================================================ */

.epa-widget {
	/* ---- Canvas ---- */
	--epa-bg: var(--color-background-page);          /* "paper"                       */
	--epa-grid-color: var(--color-border-default);   /* blueprint mesh                */
	--epa-grid-size: 40;                              /* mesh spacing at the 1920px
	                                                     baseline (unitless, read by JS) */
	--epa-ink-color: var(--color-border-strong);     /* nodes + travelled paths       */
	--epa-node-diameter: 8px;                         /* at the 1920px baseline        */
	--epa-segment-width: var(--stroke-thin);
	--epa-grid-width: 0.5px;

	/* Shockwave ring: a soft band that grows from each Alpha Node at the
	   same rate as the node tree. */
	--epa-ring-color: var(--epa-grid-color);
	--epa-ring-band-width: 40px;
	--epa-ring-max-opacity: 0.2;
	--epa-ring-outer-falloff-ratio: 0.5;

	/* Grid ripple warp trailing the ring. Set --epa-ripple-amplitude: 0px
	   to switch it off. */
	--epa-ripple-amplitude: 7px;
	--epa-ripple-ring-spacing: 42px;
	--epa-ripple-decay-length: 90px;
	--epa-ripple-sample-step: 22px;
	--epa-ripple-overshoot: 3;

	background-color: var(--epa-bg);
	/* Own stacking context: the loader's z-index only orders things
	   inside this widget, so nothing can rise above the fixed nav. */
	isolation: isolate;
}

.epa-stage {
	position: absolute;
	inset: 0;
	overflow: hidden;
	background: var(--epa-bg);
}

.epa-stage canvas {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	display: block;
}

#epaGridCanvas { touch-action: none; }
#epaFxCanvas   { touch-action: none; cursor: crosshair; }

/* ------------------------------------------------------------
   Loader: the site's cube loader (js/cube-loader.js animates any
   .cube-loader-svg), shown while the canvas initialises.
   ------------------------------------------------------------ */
.epa-loader {
	position: absolute;
	inset: 0;
	z-index: 30;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--epa-bg);
	opacity: 1;
	transition: opacity var(--duration-base) var(--easing-default);
}

.epa-loader--hidden {
	opacity: 0;
	pointer-events: none;
}

/* ------------------------------------------------------------
   Controls: the four sliders, in the Controls panel of the module's
   bar (under the canvas). Two columns, so the bar stays short;
   Open Sans small copy for labels.
   ------------------------------------------------------------ */
.epa-controls__list {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--space-16) var(--space-32);
}

.epa-control__row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--space-8);
}

.epa-control label,
.epa-control output {
	font-family: "Open Sans", sans-serif;
	font-size: clamp(0.656rem, calc(0.31 * var(--vw)) + 0.594rem, 0.844rem); /* small tier */
	line-height: 140%;
	color: var(--color-text-primary);
	margin: 0;
}

.epa-control label {
	font-weight: 300;
}

.epa-control output {
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

/* Range sliders: 1px track in the strong stroke colour, circular thumb
   with a page-colour fill and a 1px strong stroke. The thumb grows slightly on hover/drag. */
.epa-control input[type="range"] {
	-webkit-appearance: none;
	appearance: none;
	display: block;
	width: 100%;
	height: 16px;
	margin: var(--space-4) 0 0;
	background: transparent;
	cursor: pointer;
}

.epa-control input[type="range"]:focus {
	outline: none;
}

.epa-control input[type="range"]:focus-visible {
	outline: var(--stroke-bold) solid var(--color-border-strong);
	outline-offset: 4px;
}

.epa-control input[type="range"]::-webkit-slider-runnable-track {
	height: var(--stroke-bold);
	background: var(--color-border-strong);
}

.epa-control input[type="range"]::-webkit-slider-thumb {
	-webkit-appearance: none;
	appearance: none;
	width: 14px;
	height: 14px;
	margin-top: -6.5px;
	box-sizing: border-box;
	border: var(--stroke-bold) solid var(--color-border-strong);
	border-radius: var(--radius-pill);
	background: var(--color-background-page);
	transition: transform var(--duration-fast) var(--easing-default);
}

.epa-control input[type="range"]::-moz-range-track {
	height: var(--stroke-bold);
	background: var(--color-border-strong);
}

.epa-control input[type="range"]::-moz-range-thumb {
	width: 14px;
	height: 14px;
	box-sizing: border-box;
	border: var(--stroke-bold) solid var(--color-border-strong);
	border-radius: var(--radius-pill);
	background: var(--color-background-page);
	transition: transform var(--duration-fast) var(--easing-default);
}

.epa-control input[type="range"]:hover::-webkit-slider-thumb,
.epa-control input[type="range"]:active::-webkit-slider-thumb {
	transform: scale(1.3);
}

.epa-control input[type="range"]:hover::-moz-range-thumb,
.epa-control input[type="range"]:active::-moz-range-thumb {
	transform: scale(1.3);
}

/* ============================================================
   CODE.HTML ENTRY BANNER: .epa-thumb
   Inline SVG artwork in the entry's Hero with Banner Image frame:
   four seeded node trees on the same blueprint mesh (generated once,
   ~12KB uncompressed, no image request). Each generation is one path,
   so the trees draw outward generation by generation on load, and
   replay when the entry is hovered or a link inside it is focused.
   Swap the <svg> for a background-image thumbnail any time; nothing
   else depends on it.
   ============================================================ */
.hero-banner-image .epa-thumb {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	display: block;
	background-color: var(--color-background-page);
}

.epa-thumb__grid {
	fill: none;
	stroke: var(--color-border-default);
	stroke-width: 0.5;
}

/* Dash length (30) is longer than the longest segment (a 20-unit
   diagonal = 28.3), and dash patterns restart on every subpath, so
   animating the offset 30 → 0 draws every segment in a path at once. */
.epa-thumb__seg {
	fill: none;
	stroke: var(--color-border-strong);
	stroke-width: 1;
	stroke-linecap: round;
	stroke-dasharray: 30 30;
	stroke-dashoffset: 0;
	animation: epa-thumb-draw 0.24s linear both;
	animation-delay: calc(var(--g) * 0.12s + 0.2s);
}

/* Zero-length round-capped strokes = dots, no circle elements needed. */
.epa-thumb__node {
	fill: none;
	stroke: var(--color-border-strong);
	stroke-width: 3.5;
	stroke-linecap: round;
	animation: epa-thumb-node 0.2s ease-out both;
	animation-delay: calc(var(--g) * 0.12s + 0.2s);
}

/* Changing animation-name restarts the animation, so hover/focus
   replays the growth with a second, identical set of keyframes. */
.epa-entry:hover .epa-thumb__seg,
.epa-entry:focus-within .epa-thumb__seg {
	animation-name: epa-thumb-draw-replay;
}

.epa-entry:hover .epa-thumb__node,
.epa-entry:focus-within .epa-thumb__node {
	animation-name: epa-thumb-node-replay;
}

@keyframes epa-thumb-draw        { from { stroke-dashoffset: 30; } to { stroke-dashoffset: 0; } }
@keyframes epa-thumb-draw-replay { from { stroke-dashoffset: 30; } to { stroke-dashoffset: 0; } }
@keyframes epa-thumb-node        { from { opacity: 0; } to { opacity: 1; } }
@keyframes epa-thumb-node-replay { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
	.epa-thumb__seg,
	.epa-thumb__node {
		animation: none;
	}
}
