/* ==========================================================================
   Cobalt Aurora - animated background system
   Buy Cloud Products
   --------------------------------------------------------------------------
   One decorative layer, six composable effects. Every layer is inert: it is
   absolutely positioned inside the host section, carries pointer-events:none
   and sits at z-index 0, so it can never intercept a click or cover content.

   Host requirements: position:relative and overflow:hidden on the section,
   z-index:1 on the content wrapper. The hero, category head, CTA panel and
   footer already satisfy both.

   Performance notes
   - No blur() filters. Large blurred boxes are the single most expensive
     thing a background like this can do; radial-gradient falloff gives the
     same soft edge for free.
   - Everything that moves animates transform only, so it stays on the
     compositor and never triggers layout or paint.
   - The network mesh and grid are static background-images, not animations.
   - Motion counts are fixed and small: 3 mesh fields, 12 motes, 1 sweep.
   ========================================================================== */

/* 1. Layer container ------------------------------------------------------- */

/*
 * `.bcp .bcp-fx` rather than `.bcp-fx`: several hosts style their own
 * children generically (`.bcp-cta > *` sets position:relative and z-index:1
 * to lift content above the old static glows). A two-class selector outranks
 * those without needing !important.
 */
.bcp .bcp-fx {
	position: absolute;
	inset: 0;
	z-index: 0;
	overflow: hidden;
	pointer-events: none;
	border-radius: inherit;
	/* Keeps the decorative layers from blending with anything outside the
	   section, and gives the whole group its own stacking context. */
	isolation: isolate;
}

.bcp-fx > *,
.bcp-fx i {
	pointer-events: none;
}

/* 2. Animated mesh gradients ----------------------------------------------- */

/*
 * Three slowly drifting colour fields. Inset beyond the box so the fields can
 * move without their edges ever entering the frame.
 */
.bcp-fx__mesh {
	position: absolute;
	inset: -18%;
	display: block;
}

.bcp-fx__mesh i {
	position: absolute;
	display: block;
	aspect-ratio: 1;
	border-radius: 50%;
	will-change: transform;
	animation: bcp-fx-drift-a var(--bcp-fx-drift) ease-in-out infinite alternate;
}

.bcp-fx__mesh i:nth-child(1) {
	width: 58%;
	top: -14%;
	right: -6%;
	background: radial-gradient(circle, rgba(133, 59, 250, 0.5), transparent 66%);
	animation-duration: 26s;
}

.bcp-fx__mesh i:nth-child(2) {
	width: 54%;
	bottom: -22%;
	left: -8%;
	/*
	 * Capped at 0.22. Cyan is by far the lightest field, so it lifts the navy
	 * ground more than the other two: at 0.28 the secondary text colour
	 * (#a9b4da) measured 4.29:1 over the field's centre. At 0.22 it measures
	 * 5.02:1, while violet at 0.50 and blue at 0.34 stay at 4.83 and 5.76.
	 */
	background: radial-gradient(circle, rgba(22, 217, 245, 0.22), transparent 68%);
	animation-name: bcp-fx-drift-b;
	animation-duration: 34s;
}

.bcp-fx__mesh i:nth-child(3) {
	width: 46%;
	top: 22%;
	left: 32%;
	background: radial-gradient(circle, rgba(49, 91, 255, 0.34), transparent 70%);
	animation-name: bcp-fx-drift-c;
	animation-duration: 44s;
}

@keyframes bcp-fx-drift-a {
	from { transform: translate3d(0, 0, 0) scale(1); }
	to   { transform: translate3d(-7%, 6%, 0) scale(1.16); }
}

@keyframes bcp-fx-drift-b {
	from { transform: translate3d(0, 0, 0) scale(1.08); }
	to   { transform: translate3d(9%, -7%, 0) scale(0.94); }
}

@keyframes bcp-fx-drift-c {
	from { transform: translate3d(0, 0, 0) scale(0.96); }
	to   { transform: translate3d(5%, 9%, 0) scale(1.2); }
}

/* Lighter, bluer fields for use over the light grounds. */
.bcp-fx--light .bcp-fx__mesh i:nth-child(1) {
	background: radial-gradient(circle, rgba(133, 59, 250, 0.16), transparent 68%);
}

.bcp-fx--light .bcp-fx__mesh i:nth-child(2) {
	background: radial-gradient(circle, rgba(22, 217, 245, 0.16), transparent 70%);
}

.bcp-fx--light .bcp-fx__mesh i:nth-child(3) {
	background: radial-gradient(circle, rgba(49, 91, 255, 0.14), transparent 72%);
}

/* 3. Network mesh ---------------------------------------------------------- */

/*
 * Nodes joined by thin connectors, tiled. Inlined as a data URI so it costs no
 * request and cannot 404. Masked to the centre so it never collides with text
 * at the edges of the section.
 */
.bcp-fx__net {
	position: absolute;
	inset: 0;
	display: block;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180' viewBox='0 0 180 180'%3E%3Cg fill='none' stroke='%23ffffff' stroke-width='1' stroke-opacity='0.13'%3E%3Cpath d='M24 26 L154 68 M154 68 L68 156 M24 26 L68 156 M154 68 L176 166 M24 26 L6 122 M68 156 L176 166'/%3E%3C/g%3E%3Cg fill='%23ffffff' fill-opacity='0.3'%3E%3Ccircle cx='24' cy='26' r='2.2'/%3E%3Ccircle cx='154' cy='68' r='2.2'/%3E%3Ccircle cx='68' cy='156' r='2.2'/%3E%3Ccircle cx='176' cy='166' r='1.5'/%3E%3Ccircle cx='6' cy='122' r='1.5'/%3E%3C/g%3E%3C/svg%3E");
	background-size: 180px 180px;
	opacity: 0.85;
	-webkit-mask-image: radial-gradient(ellipse 80% 75% at 55% 45%, #000 30%, transparent 76%);
	mask-image: radial-gradient(ellipse 80% 75% at 55% 45%, #000 30%, transparent 76%);
}

.bcp-fx--light .bcp-fx__net {
	/* Same tile, navy strokes, for the light grounds. */
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180' viewBox='0 0 180 180'%3E%3Cg fill='none' stroke='%23315bff' stroke-width='1' stroke-opacity='0.16'%3E%3Cpath d='M24 26 L154 68 M154 68 L68 156 M24 26 L68 156 M154 68 L176 166 M24 26 L6 122 M68 156 L176 166'/%3E%3C/g%3E%3Cg fill='%23315bff' fill-opacity='0.28'%3E%3Ccircle cx='24' cy='26' r='2.2'/%3E%3Ccircle cx='154' cy='68' r='2.2'/%3E%3Ccircle cx='68' cy='156' r='2.2'/%3E%3Ccircle cx='176' cy='166' r='1.5'/%3E%3Ccircle cx='6' cy='122' r='1.5'/%3E%3C/g%3E%3C/svg%3E");
}

/* 4. Technical grid -------------------------------------------------------- */

.bcp-fx__grid {
	position: absolute;
	inset: 0;
	display: block;
	background-image:
		linear-gradient(to right, rgba(255, 255, 255, 0.055) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(255, 255, 255, 0.055) 1px, transparent 1px);
	background-size: 56px 56px;
	-webkit-mask-image: radial-gradient(ellipse 85% 70% at 50% 38%, #000 32%, transparent 78%);
	mask-image: radial-gradient(ellipse 85% 70% at 50% 38%, #000 32%, transparent 78%);
}

.bcp-fx--light .bcp-fx__grid {
	background-image:
		linear-gradient(to right, rgba(49, 91, 255, 0.07) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(49, 91, 255, 0.07) 1px, transparent 1px);
}

/* 5. Floating particles ---------------------------------------------------- */

/*
 * Twelve motes rising slowly. Positions, durations and delays are set per
 * nth-child: deterministic, but with enough spread that no two line up.
 */
.bcp-fx__motes {
	position: absolute;
	inset: 0;
	display: block;
}

.bcp-fx__motes i {
	position: absolute;
	bottom: -12px;
	width: 3px;
	height: 3px;
	border-radius: 50%;
	background: rgba(22, 217, 245, 0.9);
	box-shadow: 0 0 7px rgba(22, 217, 245, 0.75);
	opacity: 0;
	will-change: transform, opacity;
	animation: bcp-fx-rise var(--bcp-fx-rise) linear infinite;
}

.bcp-fx__motes i:nth-child(1)  { left: 6%;  animation-duration: 19s; animation-delay: 0s; }
.bcp-fx__motes i:nth-child(2)  { left: 14%; animation-duration: 24s; animation-delay: -6s; }
.bcp-fx__motes i:nth-child(3)  { left: 23%; animation-duration: 16s; animation-delay: -11s; }
.bcp-fx__motes i:nth-child(4)  { left: 31%; animation-duration: 27s; animation-delay: -3s; }
.bcp-fx__motes i:nth-child(5)  { left: 39%; animation-duration: 21s; animation-delay: -15s; }
.bcp-fx__motes i:nth-child(6)  { left: 47%; animation-duration: 18s; animation-delay: -8s; }
.bcp-fx__motes i:nth-child(7)  { left: 56%; animation-duration: 25s; animation-delay: -19s; }
.bcp-fx__motes i:nth-child(8)  { left: 64%; animation-duration: 17s; animation-delay: -2s; }
.bcp-fx__motes i:nth-child(9)  { left: 72%; animation-duration: 23s; animation-delay: -13s; }
.bcp-fx__motes i:nth-child(10) { left: 80%; animation-duration: 20s; animation-delay: -5s; }
.bcp-fx__motes i:nth-child(11) { left: 88%; animation-duration: 28s; animation-delay: -17s; }
.bcp-fx__motes i:nth-child(12) { left: 95%; animation-duration: 22s; animation-delay: -9s; }

/* Violet motes on alternating children, so the field is not a single hue. */
.bcp-fx__motes i:nth-child(3n) {
	background: rgba(196, 181, 253, 0.9);
	box-shadow: 0 0 7px rgba(196, 181, 253, 0.7);
}

@keyframes bcp-fx-rise {
	0%   { transform: translate3d(0, 0, 0); opacity: 0; }
	12%  { opacity: 0.85; }
	84%  { opacity: 0.6; }
	100% { transform: translate3d(14px, -680px, 0); opacity: 0; }
}

/* 6. Light sweep ----------------------------------------------------------- */

.bcp-fx__sweep {
	position: absolute;
	inset: 0;
	display: block;
	overflow: hidden;
}

.bcp-fx__sweep::before {
	content: "";
	position: absolute;
	top: -12%;
	bottom: -12%;
	left: 0;
	width: 38%;
	background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.11), transparent);
	transform: translate3d(-140%, 0, 0) skewX(-14deg);
	will-change: transform;
	animation: bcp-fx-sweep var(--bcp-fx-sweep) ease-in-out infinite;
}

.bcp-fx--light .bcp-fx__sweep::before {
	background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55), transparent);
}

@keyframes bcp-fx-sweep {
	0%        { transform: translate3d(-140%, 0, 0) skewX(-14deg); }
	58%, 100% { transform: translate3d(330%, 0, 0) skewX(-14deg); }
}

/* 7. Card sweep ------------------------------------------------------------ */

/*
 * Interaction-only variant: a single highlight crosses the card on hover or
 * keyboard focus. Separate from the ambient sweep so cards stay still until
 * the visitor engages with them.
 */
/*
 * Attached to the two shared card components rather than to a class in every
 * template, so the catalog grid, the homepage grids and both editorial
 * archives pick it up from one place. Neither component uses ::after, and
 * both already clip their overflow.
 */
.bcp-sweep,
.bcp .bcp-card,
.bcp .bcp-pcard2 {
	position: relative;
	overflow: hidden;
}

.bcp-sweep::after,
.bcp .bcp-card::after,
.bcp .bcp-pcard2::after {
	content: "";
	position: absolute;
	top: -20%;
	bottom: -20%;
	left: 0;
	width: 45%;
	background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
	transform: translate3d(-160%, 0, 0) skewX(-16deg);
	pointer-events: none;
	opacity: 0;
	z-index: 2;
}

.bcp-sweep:hover::after,
.bcp-sweep:focus-within::after,
.bcp .bcp-card:hover::after,
.bcp .bcp-card:focus-within::after,
.bcp .bcp-pcard2:hover::after,
.bcp .bcp-pcard2:focus-within::after {
	opacity: 1;
	transition: transform 620ms var(--bcp-ease-out), opacity 120ms linear;
	transform: translate3d(300%, 0, 0) skewX(-16deg);
}

/* 8. Scroll reveal --------------------------------------------------------- */

/*
 * Section headers start slightly lowered and settle as they enter the
 * viewport.
 *
 * Gated on `.bcp-js`, which an inline script in wp_head sets before first
 * paint, so the starting state is never painted to a no-JS visitor and there
 * is no flash of hidden content.
 *
 * `.bcp-fx-shown` is the failsafe: the same inline script sets it on a timer,
 * so if bcp.js never loads or throws before the observer is wired, every
 * tagged element becomes visible anyway. Hidden content is a far worse
 * outcome than a missing animation.
 */
.bcp-js [data-bcp-reveal] {
	opacity: 0;
	transform: translate3d(0, 18px, 0);
}

.bcp-js [data-bcp-reveal].is-revealed,
.bcp-js.bcp-fx-shown [data-bcp-reveal] {
	opacity: 1;
	transform: none;
	transition: opacity var(--bcp-t-slow) var(--bcp-ease-out),
		transform var(--bcp-t-slow) var(--bcp-ease-out);
}

/* 9. Reduced motion -------------------------------------------------------- */

/*
 * Everything decorative stops. The mesh fields keep a composed resting
 * transform rather than snapping to their start position, so a reduced-motion
 * visitor still gets a designed background, just a still one.
 */
@media (prefers-reduced-motion: reduce) {
	.bcp-fx__mesh i,
	.bcp-fx__motes i,
	.bcp-fx__sweep::before {
		animation: none !important;
	}

	.bcp-fx__mesh i:nth-child(1) { transform: translate3d(-4%, 3%, 0) scale(1.08); }
	.bcp-fx__mesh i:nth-child(2) { transform: translate3d(5%, -4%, 0) scale(1.02); }
	.bcp-fx__mesh i:nth-child(3) { transform: translate3d(3%, 5%, 0) scale(1.08); }

	.bcp-fx__motes {
		display: none;
	}

	.bcp-fx__sweep::before {
		opacity: 0;
	}

	.bcp-sweep::after,
	.bcp .bcp-card::after,
	.bcp .bcp-pcard2::after {
		display: none;
	}

	.bcp-js [data-bcp-reveal],
	.bcp-js [data-bcp-reveal].is-revealed {
		opacity: 1;
		transform: none;
		transition: none;
	}
}

/* 10. Small screens -------------------------------------------------------- */

/*
 * Phones drop the motes and the ambient sweep: they are the least visible
 * effects at that size and the most costly for battery. The mesh and the
 * static tiles stay, so the identity is unchanged.
 */
@media (max-width: 767px) {
	.bcp-fx__motes,
	.bcp-fx__sweep {
		display: none;
	}

	.bcp-fx__grid {
		background-size: 40px 40px;
	}

	.bcp-fx__net {
		background-size: 140px 140px;
	}
}
