/**
 * Black Hole — the style layer.
 *
 * ===========================================================================
 * THE GROUND IS THE DESIGN, NOT THE CANVAS
 * ===========================================================================
 *
 * Everything here has to hold up with the WebGL scene switched off. It will
 * be off for anyone on reduced motion, on a metered connection, on a device
 * without WebGL, and for anyone who turns it off in Studio — and it is off
 * for the first few hundred milliseconds of every single page load, before
 * the shader has compiled.
 *
 * So the page paints its own black ground and its own faint glow in CSS. The
 * canvas, when it arrives, sits underneath and replaces the glow with the
 * real thing. Nothing moves, nothing reflows, and a visitor who never gets
 * the canvas gets a coherent dark design rather than a broken light one.
 *
 * ===========================================================================
 * THE COLOURS WERE SOLVED
 * ===========================================================================
 *
 * Measured, not chosen. Every pairing that carries text:
 *
 *   text   #e9eef8 on ground #05070d = 17.31:1
 *   text   #e9eef8 on panel  #0c111b = 16.24:1
 *   muted  #a8b6cb on ground          =  9.80:1
 *   muted  #a8b6cb on panel           =  9.19:1
 *   accent #ffbf6d on ground          = 12.40:1
 *   accent #ffbf6d on panel           = 11.63:1
 *   ground #05070d on accent          = 12.40:1   (dark type on a button)
 *
 * The worst pairing is 9.19:1, which is AAA with a lot of room. That margin
 * is deliberate and it is not padding: this text sits over a canvas that is
 * moving, and moving contrast reads lower than the number says.
 *
 * WHITE ON THE ACCENT IS 1.40:1 AND IS NEVER USED. The accent is a light
 * gold, so a button takes dark type, not white — which is the opposite of
 * every other demo here and is the single easiest thing to get wrong.
 *
 * The ground is #05070d rather than #000000. Pure black gives the soft edges
 * of a rendered scene nothing to resolve into: the bloom has no gradient to
 * fall off to and the frame ends at a visible band.
 */

body.u-style-blackhole {
	--u-bh-ground: #05070d;
	--u-bh-panel: #0c111b;
	--u-bh-text: #e9eef8;
	--u-bh-muted: #a8b6cb;
	--u-bh-accent: #ffbf6d;

	/*
	 * Two border weights, because they answer to different rules.
	 *
	 * `rule` is decoration — a divider between two blocks. It carries no
	 * information, so it is allowed to be quiet.
	 *
	 * `edge` is the boundary of a control: an input, a select, the outline of
	 * a button you have to be able to find. WCAG 1.4.11 asks for 3:1 against
	 * the adjacent colour for exactly those, and #546484 measures 3.39:1 on
	 * the ground. Using one border colour for both means either invisible
	 * dividers or unusable form fields.
	 */
	--u-bh-rule: #2b3648;
	--u-bh-edge: #546484;

	background: var(--u-bh-ground);
	color: var(--u-bh-text);
}

/* --- the canvas ---------------------------------------------------------- */

/*
 * ===========================================================================
 * z-index: -1, AND WHY IT HAS TO BE NEGATIVE
 * ===========================================================================
 *
 * THE BUG THIS FIXES. 25.0.0 shipped this at `z-index: 0` and the whole site
 * disappeared. Reported as "the content is not working on the blackhole demo,
 * on all pages".
 *
 * The canvas is printed by wp_footer, so it is the LAST element in the body.
 * Among elements that all sit at z-index 0 or auto in the same stacking
 * context, the last one in document order paints on top. So a full-viewport
 * fixed element printed at the end of the page covers every single thing on
 * it — header, text, images, buttons. The page was rendering perfectly and
 * was entirely hidden behind a black rectangle.
 *
 * There were two ways out and the first release picked the wrong one. It
 * tried to lift the CONTENT above the canvas:
 *
 *     body.u-style-blackhole .u-site,
 *     body.u-style-blackhole .site,
 *     body.u-style-blackhole #page { position: relative; z-index: 1 }
 *
 * Not one of those selectors exists in this theme. The wrapper is `.u-main`.
 * So the rule matched nothing, silently, and a stylesheet cannot tell you
 * that a selector never fired.
 *
 * Pushing the canvas BEHIND the page instead is the right answer and it is
 * what Contour has always done. It needs no knowledge of the markup at all,
 * so it cannot be broken by a template rename — which is exactly how the
 * other version broke.
 *
 * The body has to carry the ground colour for this to work, since a negative
 * z-index puts the canvas behind the page but still in front of the body
 * background. It does, in the token block above.
 */
.u-blackhole-field {
	position: fixed;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	background: var(--u-bh-ground);
}

.u-blackhole-field canvas {
	display: block;
	width: 100%;
	height: 100%;

	/*
	 * The canvas is rendered smaller than the screen and stretched, so the
	 * browser is doing the upscale. Letting it interpolate is the point: the
	 * scene has no hard edges except the shadow, and a smooth upscale of a
	 * soft image is indistinguishable from the full-resolution version at a
	 * fraction of the cost.
	 */
	image-rendering: auto;

	/*
	 * POSITIONED, ON PURPOSE. The stand-in below is an absolutely positioned
	 * ::before, and positioned elements paint after non-positioned ones — so
	 * an unpositioned canvas is covered by its own placeholder.
	 *
	 * It fails 900ms after load rather than immediately, which is what made
	 * the identical bug in the Manta demo take five versions to find: while
	 * the fade is running, an opacity between 0 and 1 gives the canvas its
	 * own stacking context and it paints above the ::before, so the scene is
	 * visible; the moment the transition lands on exactly 1 that stacking
	 * context disappears and the placeholder covers it again.
	 *
	 * The scene animates, then vanishes into a static gradient.
	 */
	position: relative;
	z-index: 1;

	/*
	 * It fades in rather than appearing.
	 *
	 * The shader takes a moment to compile, and a black rectangle being
	 * replaced in one frame by a bright accretion disc is a flash. The CSS
	 * glow underneath is already close to the final image, so the crossfade
	 * is almost invisible — which is the intention.
	 */
	opacity: 0;
	transition: opacity 900ms ease;
}

.u-blackhole-field[data-u-running] canvas { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
	.u-blackhole-field canvas { transition: none; }
}

/*
 * The static stand-in, painted in CSS.
 *
 * Two radial gradients: the warm core where the disc will be, and a much
 * wider, much fainter cool wash for the rest of the sky. It is positioned to
 * match the canvas's default offset, so when the real scene fades in it
 * arrives roughly where the glow already was.
 */
.u-blackhole-field::before {
	content: "";
	position: absolute;
	inset: 0;

	/* Explicitly under the canvas — see the note on the canvas rule above. */
	z-index: 0;

	background:
		radial-gradient(38% 26% at 71% 47%, rgba(255, 191, 109, 0.16) 0%, rgba(255, 191, 109, 0) 68%),
		radial-gradient(90% 70% at 60% 45%, rgba(80, 110, 180, 0.09) 0%, rgba(80, 110, 180, 0) 70%);
}

/*
 * The page wrapper, named correctly this time.
 *
 * This is belt and braces rather than the mechanism — the negative z-index
 * above is what actually puts the canvas behind everything. But `.u-main` is
 * the real wrapper in this theme (header.php line 44), and giving it a
 * stacking context of its own means a section that sets a z-index for its
 * own internal layering cannot accidentally reach out past the page.
 */
body.u-style-blackhole .u-main {
	position: relative;
	z-index: 1;
}

/* ===========================================================================
   SURFACES AND SECTIONS
   ===========================================================================

   WHAT WENT WRONG THE FIRST TIME

   25.0.0 styled this layer against class names that do not exist in this
   theme — .u-panel, .u-surface, .u-button--primary, .u-nav-mobile,
   .u-menu-panel, .u-media, .u-rule, .u-muted, .is-stuck, .u-header--solid.
   Eleven selectors, every one of them matching nothing, silently. Combined
   with the canvas covering the page it meant the demo had effectively no
   styling at all.

   Every selector below is taken from the markup this theme actually prints,
   or from style-contour.css, which is the same job done correctly. The real
   names are: .u-card, .u-tile, .u-package, .u-person, .u-quote-card,
   .u-side-card, .u-acc-item, .u-drawer-panel, .u-header-bar,
   .u-header.is-scrolled, .u-bnav-tab, .u-stat, .u-eyebrow, .u-lead,
   .u-section-title, .u-section-text.

   verify.py now fails the build if a class targeted here does not appear in
   any template.

   NO SHADOWS ANYWHERE. A drop shadow is a dark shape cast onto a lighter
   ground; on a near-black page there is nothing darker for it to be, so it
   renders as a smudge that makes an edge less clear rather than more. Depth
   here comes from surfaces being lighter than the ground.
   =========================================================================== */

body.u-style-blackhole .u-card,
body.u-style-blackhole .u-tile,
body.u-style-blackhole .u-package,
body.u-style-blackhole .u-person,
body.u-style-blackhole .u-quote-card,
body.u-style-blackhole .u-side-card,
body.u-style-blackhole .u-acc-item {
	background: rgba(12, 17, 27, 0.88);
	border: 1px solid var(--u-bh-rule);
	box-shadow: none;

	/*
	 * Slightly translucent, so the scene shows through as a suggestion.
	 * Not more than this: at higher transparency a star drifting behind a
	 * paragraph is a moving speck under the text, and the eye chases it.
	 */
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
}

@supports not (backdrop-filter: blur(6px)) {
	body.u-style-blackhole .u-card,
	body.u-style-blackhole .u-tile,
	body.u-style-blackhole .u-package,
	body.u-style-blackhole .u-person,
	body.u-style-blackhole .u-quote-card,
	body.u-style-blackhole .u-side-card,
	body.u-style-blackhole .u-acc-item {
		background: var(--u-bh-panel);
	}
}

body.u-style-blackhole .u-card:hover,
body.u-style-blackhole .u-tile:hover,
body.u-style-blackhole .u-package:hover {
	border-color: var(--u-bh-edge);
	transform: none;
}

/* A hairline between sections, so a long page has a rhythm without boxes. */
body.u-style-blackhole .u-section + .u-section {
	border-top: 1px solid var(--u-bh-rule);
}

body.u-style-blackhole hr { border-color: var(--u-bh-rule); }

/* --- type ---------------------------------------------------------------- */

/*
 * Headings a touch lighter than on a light ground.
 *
 * Light type on a dark ground optically thickens — the glyph bleeds into the
 * background rather than the other way round — so a weight that reads right
 * in black on white reads heavy in white on black. Standard correction, not
 * a stylistic preference.
 */
body.u-style-blackhole .u-page-title,
body.u-style-blackhole .u-section-title,
body.u-style-blackhole .u-hero-title,
body.u-style-blackhole h1,
body.u-style-blackhole h2,
body.u-style-blackhole h3 {
	font-weight: 600;
	letter-spacing: -0.018em;
	color: var(--u-bh-text);
}

body.u-style-blackhole .u-page-title,
body.u-style-blackhole .u-hero-title { letter-spacing: -0.026em; }

body.u-style-blackhole .u-eyebrow { color: var(--u-bh-accent); }

body.u-style-blackhole .u-lead,
body.u-style-blackhole .u-section-text,
body.u-style-blackhole figcaption,
body.u-style-blackhole small { color: var(--u-bh-muted); }

body.u-style-blackhole .u-mono { color: var(--u-bh-muted); }

/* Numbers are the loudest thing in a stats row, so they take the accent. */
body.u-style-blackhole .u-stat strong,
body.u-style-blackhole .u-hero-metric strong { color: var(--u-bh-accent); }

/* --- links and buttons --------------------------------------------------- */

body.u-style-blackhole a { color: var(--u-bh-accent); }

body.u-style-blackhole .u-btn-primary {
	background: var(--u-bh-accent);
	border-color: var(--u-bh-accent);

	/*
	 * DARK TYPE ON THE BUTTON. The line to read twice.
	 *
	 * The accent is a light gold. White on it measures 1.40:1 — not merely
	 * below the standard but genuinely illegible. The ground on it measures
	 * 12.40:1. Every other demo here puts white on its accent because every
	 * other accent is dark enough to take it, so this is the exception and it
	 * exists to stop the shared default winning.
	 */
	color: var(--u-bh-ground);
	box-shadow: none;
}

body.u-style-blackhole .u-btn-primary:hover { filter: brightness(1.08); }

body.u-style-blackhole .u-btn-ghost {
	background: transparent;
	border: 1px solid var(--u-bh-edge);
	color: var(--u-bh-text);
}

body.u-style-blackhole .u-btn-ghost:hover {
	border-color: var(--u-bh-accent);
	color: var(--u-bh-accent);
}

body.u-style-blackhole .u-btn:active { transform: translateY(1px); }

/* --- forms --------------------------------------------------------------- */

body.u-style-blackhole input[type="text"],
body.u-style-blackhole input[type="email"],
body.u-style-blackhole input[type="tel"],
body.u-style-blackhole input[type="url"],
body.u-style-blackhole input[type="search"],
body.u-style-blackhole input[type="number"],
body.u-style-blackhole select,
body.u-style-blackhole textarea {
	background: rgba(5, 7, 13, 0.72);
	border: 1px solid var(--u-bh-edge);
	color: var(--u-bh-text);
}

body.u-style-blackhole ::placeholder { color: var(--u-bh-muted); opacity: 1; }

/*
 * A visible focus ring, in the accent, with an offset.
 *
 * On a dark translucent field over a moving scene an inset ring is genuinely
 * hard to see. The offset puts it outside the control, where there is a known
 * dark ground behind it.
 */
body.u-style-blackhole :focus-visible {
	outline: 2px solid var(--u-bh-accent);
	outline-offset: 2px;
}

/* --- header, footer, bottom bar ------------------------------------------ */

/*
 * `.u-header.is-scrolled` is the real state class — main.js toggles it past a
 * scroll threshold. The first version invented `.is-stuck` and
 * `.u-header--solid`, neither of which anything sets, so the header stayed
 * transparent over the content forever.
 */
body.u-style-blackhole .u-header-bar {
	background: transparent;
	border-bottom: 1px solid transparent;
}

body.u-style-blackhole .u-header.is-scrolled .u-header-bar {
	background: rgba(5, 7, 13, 0.86);
	border-bottom-color: var(--u-bh-rule);
	backdrop-filter: blur(10px);
	-webkit-backdrop-filter: blur(10px);
}

body.u-style-blackhole .u-header-nav a { color: var(--u-bh-text); }
body.u-style-blackhole .u-header-nav a:hover { color: var(--u-bh-accent); }

body.u-style-blackhole .u-footer {
	background: transparent;
	border-top: 1px solid var(--u-bh-rule);
}

/*
 * The drawer is OPAQUE. Not a preference.
 *
 * A translucent panel over a full-screen animated scene is a menu whose
 * labels are moving. It has to be a solid ground.
 */
body.u-style-blackhole .u-drawer-panel {
	background: var(--u-bh-ground);
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
	border-left: 1px solid var(--u-bh-rule);
}

body.u-style-blackhole .u-bottomnav-inner {
	background: rgba(5, 7, 13, 0.92);
	border-top: 1px solid var(--u-bh-rule);
}

body.u-style-blackhole .u-bnav-tab { color: var(--u-bh-muted); }
body.u-style-blackhole .u-bnav-tab.is-active { color: var(--u-bh-accent); }
body.u-style-blackhole .u-bnav-pill { background: rgba(255, 191, 109, 0.14); }

/* --- tables, code, quotes ------------------------------------------------ */

body.u-style-blackhole table,
body.u-style-blackhole th,
body.u-style-blackhole td { border-color: var(--u-bh-rule); }

body.u-style-blackhole thead th { color: var(--u-bh-muted); }

body.u-style-blackhole pre,
body.u-style-blackhole code {
	background: rgba(5, 7, 13, 0.8);
	border: 1px solid var(--u-bh-rule);
	color: var(--u-bh-text);
}

body.u-style-blackhole blockquote {
	border-left: 2px solid var(--u-bh-accent);
	color: var(--u-bh-text);
}

/* --- images -------------------------------------------------------------- */

/*
 * A bright photograph on a near-black page is a rectangle of light with a
 * hard edge, and it wins every composition it is in. A slight reduction in
 * brightness settles it into the page without touching the colours in it.
 */
body.u-style-blackhole .u-card-media img,
body.u-style-blackhole .u-folio-media img,
body.u-style-blackhole .u-single-media img {
	filter: brightness(0.94);
}

/* --- the specimen list --------------------------------------------------- */

body.u-style-blackhole .u-specimen-row { border-color: var(--u-bh-rule); }
body.u-style-blackhole .u-specimen-mark { color: var(--u-bh-accent); }
body.u-style-blackhole .u-specimen-text { color: var(--u-bh-muted); }
body.u-style-blackhole .u-specimen-meta { color: var(--u-bh-muted); }

/* --- the WebGL hero ------------------------------------------------------ */

/*
 * The hero's own canvas is suppressed while the scene is running, so the
 * hero is text over the black hole. It only needs its ground removing.
 */
body.u-style-blackhole .u-volume { background: transparent; }
body.u-style-blackhole .u-volume-title { color: var(--u-bh-text); }
body.u-style-blackhole .u-volume-eyebrow { color: var(--u-bh-accent); }

/* --- narrow screens ------------------------------------------------------ */

@media (max-width: 780px) {
	/*
	 * The scene runs on phones, at a shorter ray budget and half resolution.
	 * What changes here is the page, not the canvas: surfaces go fully opaque
	 * because a small screen is mostly text, and translucency over a moving
	 * background costs more legibility the less room there is.
	 */
	body.u-style-blackhole .u-card,
	body.u-style-blackhole .u-tile,
	body.u-style-blackhole .u-package,
	body.u-style-blackhole .u-person,
	body.u-style-blackhole .u-quote-card,
	body.u-style-blackhole .u-side-card,
	body.u-style-blackhole .u-acc-item {
		background: var(--u-bh-panel);
		backdrop-filter: none;
		-webkit-backdrop-filter: none;
	}
}

/* --- printing ------------------------------------------------------------ */

@media print {
	/* Nobody wants to print a black page. */
	.u-blackhole-field { display: none; }

	body.u-style-blackhole {
		background: #fff;
		color: #000;
	}
}
