.gc-cn {
	--gc-cn-w: .15;
	--gc-cn-r: .68;
	--gc-cn-ease: cubic-bezier(.65,.02,.2,1);
	position: relative;
	font-family: var(--gc-cn-font-body, var(--gc-font-body));
	color: var(--gc-cn-text);
	background: transparent;
	overflow: hidden;
	isolation: isolate;
	min-height: var(--gc-cn-min-h, 640px);
}

.gc-cn * { box-sizing: border-box; }

.gc-cn[data-skin="night"] {
	--gc-cn-field: #08131F;
	--gc-cn-field-2: #102939;
	--gc-cn-text: #EAF3FA;
	--gc-cn-muted: #8AA5B8;
	--gc-cn-mark: #FFFFFF;
	--gc-cn-lattice: rgba(255,255,255,.34);
	--gc-cn-live: #5BA7DB;
	--gc-cn-halo: rgba(91,167,219,.22);
	--gc-cn-card: rgba(13,33,49,.82);
	--gc-cn-card-line: rgba(140,190,225,.22);
	--gc-cn-card-edge: rgba(150,195,228,.11);
	--gc-cn-card-hi: rgba(255,255,255,.07);
	--gc-cn-chip: rgba(91,167,219,.14);
	--gc-cn-dust: rgba(222,240,252,.92);
	--gc-cn-glass: rgba(180,215,240,.10);
	--gc-cn-sheen: rgba(255,255,255,.72);
	--gc-cn-bloom: rgba(91,167,219,.3);
	--gc-cn-accent: #F2994A;
	--gc-cn-core-ink: #EAF3FA;
}

.gc-cn[data-skin="day"] {
	--gc-cn-field: #F4F8FB;
	--gc-cn-field-2: #E3F0FA;
	--gc-cn-text: #14212B;
	--gc-cn-muted: #5A6B75;
	--gc-cn-mark: #3D82B3;
	--gc-cn-lattice: rgba(61,130,179,.34);
	--gc-cn-live: #3D82B3;
	--gc-cn-halo: rgba(91,167,219,.20);
	--gc-cn-card: rgba(255,255,255,.9);
	--gc-cn-card-line: rgba(61,130,179,.20);
	--gc-cn-card-edge: rgba(61,130,179,.13);
	--gc-cn-card-hi: rgba(255,255,255,.7);
	--gc-cn-chip: rgba(91,167,219,.14);
	--gc-cn-dust: rgba(61,130,179,.5);
	--gc-cn-glass: rgba(255,255,255,.55);
	--gc-cn-sheen: rgba(255,255,255,.9);
	--gc-cn-bloom: rgba(91,167,219,.22);
	--gc-cn-accent: #F2994A;
	--gc-cn-core-ink: #14212B;
}

/* Optional bleed: the field and the map fade to genuine transparency at the top
   and bottom, so whatever sits behind the widget shows through. The header, card
   and buttons stay unmasked so copy never fades. */
.gc-cn-bg {
	position: absolute; inset: 0; z-index: 0; pointer-events: none;
	background: var(--gc-cn-field);
}
/* the mask is always applied: at zero fade its stops collapse and it is a no-op,
   which lets the sliders update live in the editor without a re-render */
.gc-cn-bg, .gc-cn-stage, .gc-cn-drifter-layer {
	/* eased ramp rather than a straight line, so the edge dissolves instead of banding.
	   Every stop is a fraction of the fade distance, so at zero they collapse to 0. */
	--gc-cn-mask: linear-gradient(
		to bottom,
		rgba(0,0,0,0)    0,
		rgba(0,0,0,.004) calc(var(--gc-cn-bleed-top, 0px) * .08),
		rgba(0,0,0,.018) calc(var(--gc-cn-bleed-top, 0px) * .17),
		rgba(0,0,0,.045) calc(var(--gc-cn-bleed-top, 0px) * .26),
		rgba(0,0,0,.09)  calc(var(--gc-cn-bleed-top, 0px) * .35),
		rgba(0,0,0,.15)  calc(var(--gc-cn-bleed-top, 0px) * .44),
		rgba(0,0,0,.23)  calc(var(--gc-cn-bleed-top, 0px) * .52),
		rgba(0,0,0,.34)  calc(var(--gc-cn-bleed-top, 0px) * .61),
		rgba(0,0,0,.47)  calc(var(--gc-cn-bleed-top, 0px) * .69),
		rgba(0,0,0,.61)  calc(var(--gc-cn-bleed-top, 0px) * .77),
		rgba(0,0,0,.75)  calc(var(--gc-cn-bleed-top, 0px) * .84),
		rgba(0,0,0,.87)  calc(var(--gc-cn-bleed-top, 0px) * .9),
		rgba(0,0,0,.96)  calc(var(--gc-cn-bleed-top, 0px) * .96),
		#000             var(--gc-cn-bleed-top, 0px),
		#000             calc(100% - var(--gc-cn-bleed-bottom, 0px)),
		rgba(0,0,0,.96)  calc(100% - var(--gc-cn-bleed-bottom, 0px) * .96),
		rgba(0,0,0,.87)  calc(100% - var(--gc-cn-bleed-bottom, 0px) * .9),
		rgba(0,0,0,.75)  calc(100% - var(--gc-cn-bleed-bottom, 0px) * .84),
		rgba(0,0,0,.61)  calc(100% - var(--gc-cn-bleed-bottom, 0px) * .77),
		rgba(0,0,0,.47)  calc(100% - var(--gc-cn-bleed-bottom, 0px) * .69),
		rgba(0,0,0,.34)  calc(100% - var(--gc-cn-bleed-bottom, 0px) * .61),
		rgba(0,0,0,.23)  calc(100% - var(--gc-cn-bleed-bottom, 0px) * .52),
		rgba(0,0,0,.15)  calc(100% - var(--gc-cn-bleed-bottom, 0px) * .44),
		rgba(0,0,0,.09)  calc(100% - var(--gc-cn-bleed-bottom, 0px) * .35),
		rgba(0,0,0,.045) calc(100% - var(--gc-cn-bleed-bottom, 0px) * .26),
		rgba(0,0,0,.018) calc(100% - var(--gc-cn-bleed-bottom, 0px) * .17),
		rgba(0,0,0,.004) calc(100% - var(--gc-cn-bleed-bottom, 0px) * .08),
		rgba(0,0,0,0)    100%
	);
	-webkit-mask-image: var(--gc-cn-mask);
	mask-image: var(--gc-cn-mask);
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
}

.gc-cn-veil {
	position: absolute; inset: -20%; pointer-events: none;
	background: radial-gradient(58% 54% at 50% 48%, var(--gc-cn-field-2) 0%, transparent 72%);
	opacity: .5;
	animation: gc-cn-drift 26s ease-in-out infinite alternate;
}

/* Lite mode (touch or narrow, set from JS). Every rule here removes something that
   repaints forever: the ambient loops over hundreds of SVG nodes, and the two
   backdrop blurs, which are recomputed whenever the map behind them moves. The mark,
   the camera flights, the wire lighting and the readout all still run. */
.gc-cn--lite .gc-cn-veil,
.gc-cn--lite [data-trim],
.gc-cn--lite [data-dust] circle,
.gc-cn--lite .gc-cn-star .beacon,
.gc-cn--lite .gc-cn-drifter { animation: none; }
.gc-cn--lite .gc-cn-star.is-clickable .beacon { opacity: .3; }
.gc-cn--lite .gc-cn-drifter { display: none; }
.gc-cn--lite .gc-cn-panel,
.gc-cn--lite .gc-cn-btn,
.gc-cn--lite .gc-cn-chip { backdrop-filter: none; -webkit-backdrop-filter: none; }
/* Nothing is compositing these between flights on a phone, and each hint costs a layer. */
.gc-cn--lite [data-par] { will-change: auto; }
.gc-cn--lite .gc-cn-panel { will-change: auto; }
@keyframes gc-cn-drift {
	from { transform: translate3d(-2%, -1.5%, 0) scale(1.02); }
	to   { transform: translate3d(2.5%, 2%, 0) scale(1.06); }
}

/* the reserve is the strip the centred resting card claims: the map keeps its full
   height and the section grows underneath it instead of squeezing the mark */
.gc-cn-stage {
	position: relative; z-index: 2; width: 100%;
	height: calc(var(--gc-cn-h, 100vh) + var(--gc-cn-center-reserve, 0px));
	min-height: calc(var(--gc-cn-min-h, 640px) + var(--gc-cn-center-reserve, 0px));
}
/* the field sits behind the mark on its own layer, so its motion never dirties the mark */
.gc-cn-dustlayer {
	position: absolute; inset: 0; z-index: 0;
	width: 100%; height: 100%; display: block;
	pointer-events: none;
}
.gc-cn-svg {
	position: relative; z-index: 1;
	width: 100%; height: 100%; display: block; touch-action: manipulation;
	/* auto, not geometricPrecision: the map repaints constantly, and precision multiplies
	   the cost of every one of those repaints for no visible gain at this scale */
	--lbl: 20px; --kck: 11px; --crn: 27px; --crs: 10.5px;
}

.gc-cn-bar {
	stroke: var(--gc-cn-mark);
	stroke-width: calc(26.6px * var(--gc-cn-w));
	stroke-linecap: butt; stroke-linejoin: miter;
	fill: none;
	transition: stroke .4s ease, opacity .4s ease;
}
.gc-cn-arc {
	stroke: var(--gc-cn-mark);
	stroke-width: calc(30px * var(--gc-cn-w));
	stroke-linecap: butt;
	fill: none;
	transition: stroke .4s ease, opacity .4s ease;
}
.gc-cn-bar.is-lit, .gc-cn-arc.is-lit { stroke: var(--gc-cn-live); }
.gc-cn-bar.is-dim, .gc-cn-arc.is-dim { opacity: .14; }

.gc-cn-trim { fill: var(--gc-cn-mark); transition: opacity .4s ease; }
.gc-cn-trimring { fill: none; stroke: var(--gc-cn-mark); stroke-width: calc(15.6px * var(--gc-cn-w)); transition: opacity .4s ease; }
.gc-cn-trim, .gc-cn-trimring { opacity: .82; }

.gc-cn-orbit { fill: var(--gc-cn-live); opacity: .55; }

.gc-cn-spark {
	fill: none; stroke: var(--gc-cn-live); stroke-linecap: butt;
	stroke-width: calc(26.6px * var(--gc-cn-w));
	opacity: 0;
}
.gc-cn-spark.is-travelling { animation: gc-cn-travel .8s var(--gc-cn-ease) forwards; }
@keyframes gc-cn-travel {
	0%   { opacity: 1; stroke-dasharray: 14 4000; stroke-dashoffset: 0; }
	100% { opacity: 0; stroke-dasharray: 14 4000; stroke-dashoffset: -1200; }
}

/* Nothing inside an SVG can be composited, so every animated mote repaints the whole map
   for as long as it runs. Only a slice of the field is ever in motion: the rest hold a
   fixed brightness, which reads the same and costs nothing. */
.gc-cn-dust circle {
	fill: var(--gc-cn-dust);
	opacity: calc(var(--op, 1) * .58);
	transform-box: fill-box; transform-origin: center;
}
.gc-cn-dust circle.tw {
	animation: gc-cn-twinkle var(--tw, 6s) ease-in-out infinite var(--td, 0s);
}
.gc-cn-dust circle.wd {
	animation: gc-cn-wander var(--wd, 14s) ease-in-out infinite alternate var(--td, 0s);
}
.gc-cn-dust circle.tw.wd {
	animation: gc-cn-twinkle var(--tw, 6s) ease-in-out infinite var(--td, 0s),
	           gc-cn-wander var(--wd, 14s) ease-in-out infinite alternate var(--td, 0s);
}
@keyframes gc-cn-twinkle {
	0%, 100% { opacity: calc(var(--op, 1) * .26); }
	50%      { opacity: calc(var(--op, 1) * .92); }
}
.gc-cn-dust circle.flare {
	animation: gc-cn-flare var(--tw, 6s) ease-in-out infinite var(--td, 0s);
}
@keyframes gc-cn-flare {
	0%, 100% { opacity: calc(var(--op, 1) * .2);  scale: .85; }
	50%      { opacity: calc(var(--op, 1) * 1);   scale: 1.75; }
}
@keyframes gc-cn-wander {
	from { translate: -7px 5px; }
	to   { translate: 7px -6px; }
}
@keyframes gc-cn-bob { 0%,100% { transform: translateY(-6px) } 50% { transform: translateY(6px) } }

/* The breathe rides on the svg element rather than a group inside it. On the element it is a
   composited layer transform and the map's raster is reused; on a group the browser has to
   redraw every path, dot and label underneath it on every frame, forever. */
.gc-cn .gc-cn-svg {
	animation: gc-cn-breathe var(--gc-cn-breathe, 14s) ease-in-out infinite;
	transform-origin: 50% 50%;
}
@keyframes gc-cn-breathe {
	0%,100% { transform: translateY(-5px) scale(.996); }
	50%     { transform: translateY(5px)  scale(1.004); }
}
/* one animation on the group, not eighteen on its children, all of which shared the timing */
.gc-cn [data-trim] { animation: gc-cn-bob 11s ease-in-out infinite; }

.gc-cn-star { cursor: pointer; outline: none; transition: opacity .4s ease; --near: 0; }
.gc-cn-star .hit { fill: transparent; }
.gc-cn-star .lift {
	transform-box: fill-box; transform-origin: center;
	transform: scale(calc(1 + .07 * var(--near)));
	transition: transform .45s var(--gc-cn-ease);
}
.gc-cn-star .halo {
	fill: var(--gc-cn-halo);
	opacity: calc(.28 * var(--near));
	transition: opacity .35s ease;
}
.gc-cn-star .glass { fill: var(--gc-cn-glass); stroke: none; }
.gc-cn-star .ring {
	fill: none; stroke: var(--gc-cn-mark);
	stroke-opacity: calc(.72 + .28 * var(--near));
	transition: stroke .35s ease;
}
.gc-cn-star .sheen {
	fill: none; stroke: var(--gc-cn-sheen); stroke-linecap: round;
	opacity: calc(.5 + .5 * var(--near));
	transition: opacity .35s ease;
}
.gc-cn-star .pip { fill: var(--gc-cn-accent, #F2994A); opacity: 0; transition: opacity .35s ease; }
.gc-cn-star:hover .halo, .gc-cn-star:focus-visible .halo, .gc-cn-star.is-active .halo { opacity: 1; }
.gc-cn-star:hover .ring, .gc-cn-star:focus-visible .ring { stroke: var(--gc-cn-live); }
.gc-cn-star.is-active .ring { stroke: var(--gc-cn-accent, #F2994A); }
.gc-cn-star.is-active .glass { fill: var(--gc-cn-accent, #F2994A); fill-opacity: .18; }
.gc-cn-star.is-active .pip { opacity: 1; }
.gc-cn-star.is-dim { opacity: .18; }
/* labels stay put when a point is selected: only the focused point's own label goes */

.gc-cn-star.is-clickable .beacon {
	fill: none; stroke: var(--gc-cn-live);
	stroke-width: calc(26.6px * var(--gc-cn-w));
	opacity: 0;
	transform-box: fill-box; transform-origin: center;
	animation: gc-cn-beacon var(--gc-cn-beacon-dur, 3.6s) cubic-bezier(.2,.6,.3,1) infinite var(--bd, 0s);
}
@keyframes gc-cn-beacon {
	0%   { opacity: .55; scale: 1; }
	55%  { opacity: 0;   scale: 1.7; }
	100% { opacity: 0;   scale: 1.7; }
}
.gc-cn-star:hover .beacon,
.gc-cn-star.is-active .beacon,
.gc-cn-star.is-dim .beacon { animation-play-state: paused; opacity: 0; }
.gc-cn[data-beacon="off"] .gc-cn-star .beacon { display: none; }

/* Backing plate for the labels that land over the lattice. Sized in JS from the text. */
.gc-cn-star .plate {
	fill: var(--gc-cn-card);
	stroke: var(--gc-cn-card-edge);
	stroke-width: 1;
	pointer-events: none;
}
.gc-cn-star .label {
	font-family: var(--gc-cn-font-body, var(--gc-font-body));
	font-weight: 600; font-size: var(--lbl);
	fill: var(--gc-cn-text); letter-spacing: .01em; pointer-events: none;
}
/* the outer points are the headline destinations, so they carry more weight */
.gc-cn-star.is-clickable .label {
	font-family: var(--gc-cn-font-heading, var(--gc-font-heading));
	font-weight: 800;
	font-size: calc(var(--lbl) * 1.18);
	letter-spacing: -.012em;
}
/* sub points sit a step below the outer points, not a whisper */
.gc-cn-sat .label {
	font-family: var(--gc-cn-font-heading, var(--gc-font-heading));
	font-weight: 700;
	font-size: calc(var(--lbl) * 1.02);
	letter-spacing: -.008em;
}
.gc-cn-star .kicker {
	font-family: var(--gc-cn-font-mono, ui-monospace, monospace);
	font-weight: 400; font-size: var(--kck);
	fill: var(--gc-cn-muted); letter-spacing: .1em; text-transform: uppercase;
	pointer-events: none;
}
.gc-cn-star.is-quiet .label, .gc-cn-star.is-quiet .kicker, .gc-cn-star.is-quiet .plate { opacity: 0; transition: opacity .3s ease; }
.gc-cn-star.is-quiet:hover .label, .gc-cn-star.is-quiet:hover .kicker, .gc-cn-star.is-quiet:hover .plate,
.gc-cn-star.is-quiet:focus-visible .label, .gc-cn-star.is-quiet:focus-visible .kicker, .gc-cn-star.is-quiet:focus-visible .plate,
.gc-cn-star.is-quiet.is-active .label, .gc-cn-star.is-quiet.is-active .kicker, .gc-cn-star.is-quiet.is-active .plate { opacity: 1; }
/* the focused point drops its own label and eyebrow: the card already carries them */
.gc-cn-star.is-active .label,
.gc-cn-star.is-active .kicker,
.gc-cn-star.is-active .plate,
.gc-cn-star.is-quiet.is-active .label,
.gc-cn-star.is-quiet.is-active .kicker,
.gc-cn-star.is-quiet.is-active .plate { opacity: 0; transition: opacity .28s ease; }

.gc-cn-core { cursor: pointer; }
.gc-cn-core .disc { fill: var(--gc-cn-glass); }
.gc-cn-core .disc-gloss { fill: url(#gcCoreGlass); opacity: .22; }
.gc-cn-core .disc-edge { fill: none; stroke: var(--gc-cn-mark); stroke-width: calc(20px * var(--gc-cn-w)); }
.gc-cn-core .disc-sheen {
	fill: none; stroke: var(--gc-cn-sheen); stroke-linecap: round;
	stroke-width: calc(9px * var(--gc-cn-w)); opacity: .5;
}
.gc-cn-core .core-name {
	font-family: var(--gc-cn-font-heading, var(--gc-font-heading));
	font-weight: 800; font-size: var(--crn);
	fill: var(--gc-cn-core-ink); text-anchor: middle; letter-spacing: -.01em;
}
/* two-tone label: the parts run straight on from each other */
.gc-cn-core .core-name .ink-1 { fill: var(--gc-cn-core-ink-1, var(--gc-cn-live)); }
.gc-cn-core .core-name .ink-2 { fill: var(--gc-cn-core-ink-2, var(--gc-cn-core-ink)); }
.gc-cn-core .core-sub {
	font-family: var(--gc-cn-font-mono, ui-monospace, monospace);
	font-weight: 400; font-size: var(--crs);
	fill: var(--gc-cn-muted); text-anchor: middle;
	letter-spacing: .2em; text-transform: uppercase;
}

.gc-cn-sat { transition: opacity .5s ease .1s; }
.gc-cn-sat:not(.is-open) { opacity: 0 !important; pointer-events: none; }

/* the layer carries the bleed mask so the character fades at the edges like everything else */
.gc-cn-drifter-layer {
	position: absolute; inset: 0; z-index: 1;
	pointer-events: none; overflow: hidden;
}
.gc-cn-drifter {
	position: absolute; left: 0; top: 0;
	width: var(--gc-cn-drifter-size, 84px);
	height: auto;
	opacity: 0;
	pointer-events: none;
	will-change: transform, opacity;
}
/* the whole crossing is one keyframe run, so restarting it is just a class toggle.
   an eased curve makes it ease in and out of frame rather than track at a fixed rate */
.gc-cn-drifter.is-crossing {
	animation: gc-cn-cross var(--gc-cn-drifter-dur, 42s) cubic-bezier(.42,.02,.58,1) forwards;
}
/* The turn is spread over the whole crossing, so it reads as a slow drift rather than a
   spin: one revolution across a 40 second traverse is a couple of degrees a second. */
@keyframes gc-cn-cross {
	0%   { transform: translate(var(--x0, 0px), var(--y0, 0px)) rotate(0deg) scaleX(var(--sx, 1)); opacity: 0; }
	12%  { opacity: var(--gc-cn-drifter-opacity, .85); }
	88%  { opacity: var(--gc-cn-drifter-opacity, .85); }
	100% { transform: translate(var(--x1, 0px), var(--y1, 0px)) rotate(var(--gc-cn-drifter-spin, 360deg)) scaleX(var(--sx, 1)); opacity: 0; }
}
/* the bob rides on top of the crossing: a slow rise and fall with a lazy sway */
.gc-cn-drifter .bobber {
	display: block; width: 100%; height: auto;
	animation: gc-cn-drifter-bob var(--gc-cn-drifter-bob, 7s) ease-in-out infinite,
	           gc-cn-drifter-sway calc(var(--gc-cn-drifter-bob, 7s) * 2.3) ease-in-out infinite;
}
@keyframes gc-cn-drifter-bob {
	0%,100% { transform: translateY(-11px) rotate(-2.5deg); }
	50%     { transform: translateY(11px) rotate(2.5deg); }
}
@keyframes gc-cn-drifter-sway {
	0%,100% { translate: -14px 0; }
	50%     { translate: 14px 0; }
}
@media (prefers-reduced-motion: reduce) {
	.gc-cn-drifter { display: none; }
}

.gc-cn-rail {
	position: absolute; z-index: 3; top: 0; left: 0; right: 0;
	display: flex; align-items: baseline; gap: clamp(16px, 3vw, 40px);
	padding: clamp(28px, 4vw, 56px);
	padding-top: calc(clamp(28px, 4vw, 56px) + var(--gc-cn-head-offset, 0px));
	pointer-events: none;
}
.gc-cn-rail > * { pointer-events: auto; }
.gc-cn-eyebrow {
	display: inline-flex; align-items: center; gap: 9px;
	font-family: var(--gc-cn-font-mono, ui-monospace, monospace);
	font-size: 11px; font-weight: 500; letter-spacing: .16em; text-transform: uppercase;
	color: var(--gc-cn-live);
}
.gc-cn-eyebrow::before { content: ""; width: 20px; height: 1px; background: currentColor; opacity: .6; }
.gc-cn-rail h1,
.gc-cn-rail h2,
.gc-cn-rail h3 {
	font-family: var(--gc-cn-font-heading, var(--gc-font-heading));
	font-weight: 800;
	font-size: clamp(26px, 2.9vw, 40px); line-height: 1.06; letter-spacing: -.024em;
	margin: 14px 0 0; max-width: 11ch; color: var(--gc-cn-text);
}
.gc-cn-hint { margin: 14px 0 0; font-size: 13.5px; line-height: 1.55; color: var(--gc-cn-muted); max-width: 28ch; }

.gc-cn-tools {
	position: absolute; z-index: 4; top: clamp(20px,3vw,38px); right: clamp(20px,3vw,38px);
	display: flex; flex-direction: column; align-items: flex-end; gap: 10px;
}
.gc-cn-btn {
	font: inherit; font-size: 13px; font-weight: 600;
	display: inline-flex; align-items: center; gap: 8px; padding: 9px 16px;
	border-radius: 999px; border: 1px solid var(--gc-cn-card-line);
	background: var(--gc-cn-card); color: var(--gc-cn-text);
	backdrop-filter: blur(7px); cursor: pointer;
	transition: border-color .2s ease, transform .2s ease;
}
.gc-cn-btn:hover { border-color: var(--gc-cn-live); transform: translateY(-1px); }
.gc-cn-btn:focus-visible { outline: 2px solid var(--gc-cn-accent, #F2994A); outline-offset: 2px; }
.gc-cn-btn[hidden] { display: none; }

.gc-cn-panel {
	position: absolute; z-index: 3; left: 0; top: 0;
	width: var(--gc-cn-card-w, min(340px, 42vw));
	padding: 18px 20px 20px;
	border: 0; border-radius: var(--gc-cn-card-radius, 6px);
	background: var(--gc-cn-card);
	box-shadow:
		0 0 0 1px var(--gc-cn-card-edge),
		0 24px 50px -24px rgba(2,10,18,.55),
		inset 0 1px 0 var(--gc-cn-card-hi);
	/* the blur is recomputed every time the map behind it repaints, so the radius is kept
	   modest: cost scales with it, and the card reads the same */
	backdrop-filter: blur(11px) saturate(125%);
	-webkit-backdrop-filter: blur(11px) saturate(125%);
	opacity: 0; pointer-events: none;
	transform-origin: var(--gc-cn-ox, 0) 50%;
	/* closed it is tucked against the point and clipped to nothing, then it slides out
	   and unrolls away from the edge that faces the point. the clip is inset well past
	   the box on the open side so the lead line, dot and shadow are never cut. */
	--gc-cn-out: cubic-bezier(.19,1.02,.24,1);
	translate: var(--gc-cn-from, 0px) 0;
	scale: .985;
	clip-path: inset(-200px var(--gc-cn-clip-r, -200px) -200px var(--gc-cn-clip-l, -200px));
	will-change: transform, opacity, scale, translate, clip-path;
	transition:
		opacity .24s ease var(--gc-cn-card-delay, 0ms),
		translate .54s var(--gc-cn-out) var(--gc-cn-card-delay, 0ms),
		scale .54s var(--gc-cn-out) var(--gc-cn-card-delay, 0ms),
		clip-path .54s var(--gc-cn-out) var(--gc-cn-card-delay, 0ms);
}
.gc-cn-panel.is-open {
	opacity: 1; pointer-events: auto;
	translate: 0 0; scale: 1;
	clip-path: inset(-200px);
}
.gc-cn-panel.is-seating { transition: none; }
/* the docked framings have nowhere to unroll from, so they just settle up into place */
.gc-cn-panel.is-corner,
.gc-cn-panel.is-docked { translate: 0 14px; scale: .98; }
.gc-cn-panel.is-center { translate: -50% 14px; scale: .98; }
.gc-cn-panel.is-corner.is-open,
.gc-cn-panel.is-docked.is-open { translate: 0 0; scale: 1; }
.gc-cn-panel.is-center.is-open { translate: -50% 0; scale: 1; }
.gc-cn-panel.is-corner {
	transform: none !important;
	transform-origin: 0 100%;
	left: clamp(20px, 3vw, 38px);
	bottom: clamp(56px, 6vw, 76px);
	top: auto;
}
.gc-cn-panel.is-corner::before, .gc-cn-panel.is-corner::after { display: none; }
.gc-cn-panel::before {
	content: ""; position: absolute; top: 50%;
	left: var(--gc-cn-lead-left, auto); right: var(--gc-cn-lead-right, auto);
	width: var(--gc-cn-lead, 0px); height: 1px;
	background: linear-gradient(to right, transparent, var(--gc-cn-card-line));
}
.gc-cn-panel::after {
	content: ""; position: absolute; top: calc(50% - 2px);
	left: var(--gc-cn-dot-left, auto); right: var(--gc-cn-dot-right, auto);
	width: 5px; height: 5px; border-radius: 50%;
	background: var(--gc-cn-accent, #F2994A);
}
.gc-cn-panel .p-kick {
	display: flex; align-items: center; gap: 10px;
	font-family: var(--gc-cn-font-mono, ui-monospace, monospace);
	font-size: 11px; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
	color: var(--gc-cn-live);
}
.gc-cn-panel .p-kick::after {
	content: ""; flex: 1 1 auto; height: 1px;
	background: var(--gc-cn-card-line); opacity: .8;
}
.gc-cn-panel h3 {
	font-family: var(--gc-cn-font-heading, var(--gc-font-heading));
	font-weight: 700; font-size: 20px; line-height: 1.18; letter-spacing: -.015em;
	margin: 7px 0 0; color: var(--gc-cn-text);
}
.gc-cn-panel p { margin: 9px 0 0; font-size: 13.5px; line-height: 1.55; color: var(--gc-cn-muted); }
.gc-cn-links { margin: 18px 0 0; }
.gc-cn-links .l-title {
	display: flex; align-items: center; gap: 10px;
	font-family: var(--gc-cn-font-mono, ui-monospace, monospace);
	font-size: 10.5px; font-weight: 400; letter-spacing: .14em; text-transform: uppercase;
	color: var(--gc-cn-muted); opacity: .85;
}
.gc-cn-links .l-title::after {
	content: ""; flex: 1 1 auto; height: 1px;
	background: var(--gc-cn-card-line); opacity: .8;
}
.gc-cn-chips { display: flex; flex-direction: column; margin-top: 4px; }
.gc-cn-chip {
	font: inherit; font-size: 13px; font-weight: 500;
	display: flex; align-items: center; justify-content: space-between; gap: 12px;
	width: 100%; padding: 9px 2px; text-align: left;
	border: 0; border-bottom: 1px solid var(--gc-cn-card-line);
	border-radius: 0; cursor: pointer;
	background: none; color: var(--gc-cn-text);
	transition: color .2s ease, padding-left .2s ease;
}
.gc-cn-chip:last-child { border-bottom: 0; }
.gc-cn-chip:hover { color: var(--gc-cn-live); padding-left: 6px; }
.gc-cn-chip:focus-visible { outline: 2px solid var(--gc-cn-accent, #F2994A); outline-offset: 2px; }
.gc-cn-chip .go {
	font-family: var(--gc-cn-font-mono, ui-monospace, monospace);
	color: var(--gc-cn-live);
	opacity: 0; transform: translateX(-4px);
	transition: opacity .2s ease, transform .2s ease;
}
.gc-cn-chip:hover .go,
.gc-cn-chip:focus-visible .go { opacity: 1; transform: none; }

.gc-cn-cta {
	display: inline-flex; align-items: center; gap: 8px;
	margin: 16px 0 0;
	font-family: var(--gc-cn-font-body, var(--gc-font-body));
	font-size: 13px; font-weight: 600;
	padding: 11px 20px; border-radius: var(--gc-cn-cta-radius, 999px); text-decoration: none;
	color: var(--gc-cn-cta-color, #fff);
	background: var(--gc-cn-cta-bg, linear-gradient(135deg, #5BA7DB, #6EC1E4));
	transition: transform .2s ease, filter .2s ease;
}
.gc-cn-cta:hover { transform: translateY(-1px); filter: brightness(1.06); color: var(--gc-cn-cta-color, #fff); }
.gc-cn-cta:focus-visible { outline: 2px solid var(--gc-cn-accent, #F2994A); outline-offset: 2px; }

/* the copy cascades in behind the unroll rather than arriving with it, and waits out the
   same lag as the card so it does not fade in over an empty surface */
.gc-cn-fade > * { animation: gc-cn-rise .46s cubic-bezier(.19,1.02,.24,1) both calc(var(--gc-cn-card-delay, 0ms) + .08s); }
.gc-cn-fade > *:nth-child(2) { animation-delay: calc(var(--gc-cn-card-delay, 0ms) + .15s); }
.gc-cn-fade > *:nth-child(3) { animation-delay: calc(var(--gc-cn-card-delay, 0ms) + .21s); }
.gc-cn-fade > *:nth-child(4) { animation-delay: calc(var(--gc-cn-card-delay, 0ms) + .27s); }
.gc-cn-fade > *:nth-child(5) { animation-delay: calc(var(--gc-cn-card-delay, 0ms) + .33s); }
@keyframes gc-cn-rise { from { opacity: 0; transform: translate3d(0, 9px, 0); } to { opacity: 1; transform: none; } }

.gc-cn-trail {
	position: absolute; z-index: 3; left: clamp(20px,3vw,38px); bottom: clamp(20px,3vw,32px);
	display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
	font-family: var(--gc-cn-font-mono, ui-monospace, monospace);
	font-size: 11.5px; font-weight: 400; letter-spacing: .04em; color: var(--gc-cn-muted);
}
.gc-cn-trail b { color: var(--gc-cn-text); font-weight: 600; }
.gc-cn-trail .sep { opacity: .45; }

/* resting card centred under the mark: a wide, shallow bar rather than a tall corner card */
.gc-cn-panel.is-center {
	transform: none !important;
	transform-origin: 50% 100%;
	left: 50%; right: auto; top: auto;
	bottom: var(--gc-cn-center-bottom, 130px);
	width: min(var(--gc-cn-center-w, 620px), calc(100% - 96px));
	padding: 30px 40px 32px;
	text-align: center;
	background:
		radial-gradient(130% 100% at 50% -30%, color-mix(in srgb, var(--gc-cn-live) 18%, transparent), transparent 60%),
		var(--gc-cn-card);
	box-shadow:
		0 0 0 1px var(--gc-cn-card-edge),
		0 44px 90px -46px rgba(2,10,18,.75),
		inset 0 1px 0 var(--gc-cn-card-hi);
}
.gc-cn-panel.is-center::before {
	display: block;
	top: 0; left: 18%; right: 18%;
	width: auto; height: 1px;
	background: linear-gradient(90deg, transparent, var(--gc-cn-live), transparent);
	opacity: .6;
}
.gc-cn-panel.is-center::after { display: none; }
.gc-cn-panel.is-center h3 { font-size: 23px; letter-spacing: -.02em; }
.gc-cn-panel.is-center p {
	font-size: 14px; line-height: 1.6;
	color: color-mix(in srgb, var(--gc-cn-text) 72%, var(--gc-cn-muted));
}
.gc-cn-panel.is-center .p-kick { gap: 0; letter-spacing: .18em; }
.gc-cn-panel.is-center .gc-cn-fade {
	display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
	gap: 12px 14px;
}
.gc-cn-panel.is-center .p-kick,
.gc-cn-panel.is-center h3,
.gc-cn-panel.is-center p { flex: 0 0 100%; margin: 0; }
.gc-cn-panel.is-center p { max-width: 62ch; margin: 0 auto; }
.gc-cn-panel.is-center .gc-cn-links { margin: 0; display: flex; align-items: center; gap: 14px; }
.gc-cn-panel.is-center .p-kick::after,
.gc-cn-panel.is-center .l-title::after { display: none; }
.gc-cn-panel.is-center .p-kick { justify-content: center; }
.gc-cn-panel.is-center .gc-cn-chips { margin: 0; flex-direction: row; flex-wrap: wrap; justify-content: center; gap: 4px 16px; }
.gc-cn-panel.is-center .gc-cn-chip {
	position: relative;
	width: auto; border-bottom: 0;
	padding: 4px 0 4px 15px;
	transition: color .2s ease;
}
.gc-cn-panel.is-center .gc-cn-chip::before {
	content: "";
	position: absolute; left: 0; top: 50%;
	width: 6px; height: 6px; margin-top: -3px;
	border-radius: 50%;
	border: 1px solid color-mix(in srgb, var(--gc-cn-live) 70%, transparent);
	transition: background-color .2s ease, box-shadow .2s ease;
}
.gc-cn-panel.is-center .gc-cn-chip:hover { padding-left: 15px; }
.gc-cn-panel.is-center .gc-cn-chip:hover::before,
.gc-cn-panel.is-center .gc-cn-chip:focus-visible::before {
	background: var(--gc-cn-live);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--gc-cn-live) 22%, transparent);
}
.gc-cn-panel.is-center .gc-cn-chip .go { display: none; }
.gc-cn-panel.is-center .gc-cn-cta { margin: 0; }

/* card docked to the bottom edge: the mobile and narrow-window layout */
.gc-cn-panel.is-docked {
	transform: none !important;
	transform-origin: 50% 100%;
	left: 12px; right: 12px; bottom: var(--gc-cn-dock-bottom, 0px); top: auto;
	width: auto;
}
.gc-cn-panel.is-docked::before, .gc-cn-panel.is-docked::after { display: none; }

@media (max-width: 900px) {
	/* the header stacks above the map rather than over it, so nothing overlaps the mark */
	.gc-cn { display: flex; flex-direction: column; min-height: 0; }
	.gc-cn-rail { position: static; }
	/* the fit height is written by the script once it knows what the mark actually needs, so
	   the control height is the ceiling rather than the target and no dead band is left over */
	.gc-cn-stage {
		flex: 1 1 auto;
		height: var(--gc-cn-fit-h, var(--gc-cn-h, 66vh));
		min-height: min(var(--gc-cn-min-h, 420px), var(--gc-cn-fit-h, 100vh));
	}
	.gc-cn-rail { flex-direction: column; align-items: flex-start; gap: 4px; padding: 18px 18px 2px; }
	.gc-cn-rail h1,
	.gc-cn-rail h2,
	.gc-cn-rail h3 { max-width: 18ch; font-size: clamp(22px, 6.4vw, 30px); margin-top: 8px; }
	.gc-cn-hint { margin-top: 6px; font-size: 12.5px; }
	.gc-cn-tools { top: 14px; right: 14px; flex-direction: row; gap: 6px; }
	.gc-cn-btn { font-size: 12px; padding: 8px 13px; }
	/* compact card: no inner scrolling, nothing clipped, copy clamped and chips on one row */
	.gc-cn-panel { width: auto; padding: 14px 16px 16px; max-height: none; overflow: visible; }
	/* a sheet across the bottom edge rather than a floating card: the inset left a rim of
	   field down three sides, which read as a gap instead of a resting place */
	.gc-cn-panel.is-corner,
	.gc-cn-panel.is-docked {
		left: 0; right: 0; bottom: var(--gc-cn-dock-bottom, 0px); width: auto;
		border-radius: var(--gc-cn-card-radius, 6px) var(--gc-cn-card-radius, 6px) 0 0;
		box-shadow:
			0 -1px 0 var(--gc-cn-card-edge),
			0 -26px 44px -30px rgba(2,10,18,.8),
			inset 0 1px 0 var(--gc-cn-card-hi);
	}
	.gc-cn-panel h3 { font-size: 16.5px; margin-top: 4px; }
	.gc-cn-panel .p-kick { font-size: 10px; }
	.gc-cn-panel p {
		font-size: 12.5px; line-height: 1.45; margin-top: 5px;
		display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
	}
	/* the chips go: tapping the map is the way around on a phone */
	.gc-cn-panel .gc-cn-links { display: none; }
	.gc-cn-panel .gc-cn-cta { margin-top: 10px; padding: 9px 14px; font-size: 12.5px; }
	.gc-cn-trail { display: none; }

	/* less detail at this scale: the mark keeps its shape, the fine print goes */
	.gc-cn-core .core-sub { display: none; }
	.gc-cn-star .kicker { display: none; }
	.gc-cn-trim { display: none; }
	.gc-cn-trimring { opacity: .5; }
	.gc-cn-orbit { display: none; }
	.gc-cn-star .sheen { opacity: calc(.35 + .3 * var(--near)); }
	/* the plate goes with the label it backs, or it is left as an empty box */
	.gc-cn-star.is-quiet .label,
	.gc-cn-star.is-quiet .plate { display: none; }
	.gc-cn-drifter { width: calc(var(--gc-cn-drifter-size, 84px) * .7); }
}

/* In flight every frame re-rasters the whole map, so the ambient motion stands down and the
   paths render cheap. Both come straight back when the camera lands. */
.gc-cn.is-flying .gc-cn-svg { shape-rendering: optimizeSpeed; }
.gc-cn.is-flying .gc-cn-veil,
.gc-cn.is-flying .gc-cn-dust circle,
.gc-cn.is-flying [data-trim],
.gc-cn.is-flying .gc-cn-star.is-clickable .beacon { animation-play-state: paused; }

/* Off screen the ambient motion is held rather than left running. Around 180
   elements animate here, and on a long page that cost is paid the whole time the
   page is open, which is felt as scroll judder somewhere else entirely. Paused
   rather than cleared, so it picks up mid-cycle on the way back in instead of
   snapping to the start of every keyframe at once. */
.gc-cn--rest,
.gc-cn--rest *,
.gc-cn--rest *::before,
.gc-cn--rest *::after { animation-play-state: paused !important; }

@media (prefers-reduced-motion: reduce) {
	.gc-cn *, .gc-cn *::before, .gc-cn *::after {
		animation-duration: .01ms !important; transition-duration: .01ms !important;
		animation-delay: 0ms !important; transition-delay: 0ms !important;
	}
	.gc-cn-star.is-clickable .beacon { animation: none; opacity: .3; }
}
