/* ---------------------------------------------------------------------------
   Hero carousel, homepage only. Linked from src/HTML_skeleton/index.html.
   Colours come exclusively from the :root tokens in main.css.

   Full-bleed note: this section is a direct child of <body>, which main.css
   lays out as `display:flex; flex-direction:column`. It is therefore edge to
   edge at `width: 100%`, exactly how .page-header was full-bleed. 100vw is
   deliberately NOT used: it adds the classic scrollbar gutter on Windows and
   Linux, which `body { overflow-x: hidden }` (main.css:276) hides but does not
   fix, and which offsets this .container against the header's .container.
   --------------------------------------------------------------------------- */

.hero-carousel {
	/* Width of the full height prev/next hit zones. .hero-inner reserves the
	   same amount as horizontal padding so slide copy never sits underneath
	   them, which is what used to clip the text on narrow screens. */
	--hero-nav-w: clamp(56px, 7vw, 96px);
	/* Mirrors .container's max-width in main.css. Used to work out how much
	   free gutter sits beside the content on wide screens. */
	--hero-content-w: 1200px;
	position: relative;
	width: 100%;
	overflow: hidden;
	color: var(--white);
	background-color: var(--slate-900); /* paint floor before the image decodes */
	isolation: isolate;                 /* keeps every child stacking context
	                                       strictly below .header (z-index: 50) */
}

/* All slides occupy the same grid cell, so the viewport is as tall as the
   tallest slide and nothing reflows when the active slide changes: CLS 0. */
.hero-viewport {
	position: relative;
	display: grid;
	grid-template-areas: "slide";
	/* An implicit `auto` column would size to the copy's max-content width
	   (40rem) and overflow narrow viewports, so pin it to the container. */
	grid-template-columns: minmax(0, 1fr);
	min-height: 560px;                       /* fallback for no-svh browsers */
	min-height: clamp(560px, 82svh, 640px);
}

.hero-slide {
	grid-area: slide;
	position: relative;
	display: flex;
	align-items: center;
	min-width: 0; /* grid/flex items default to min-width:auto, which refuses
	                 to shrink below min-content and reintroduces overflow */
	opacity: 0;
	visibility: hidden;                      /* also removes off-screen CTAs from
	                                            the tab order in every engine */
	pointer-events: none;
	transition: opacity 0.6s ease, visibility 0s linear 0.6s;
}

.hero-slide.is-active {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
	transition: opacity 0.6s ease, visibility 0s linear 0s;
}

/* --- background image -------------------------------------------------------
   main.css:297 has a global `img { max-width: 100%; height: auto; }`. A class
   selector (0,1,0) outranks that element selector (0,0,1), so height:100% wins
   without !important. Keep this rule class-scoped. */
.hero-slide-bg {
	position: absolute;
	inset: 0;
	z-index: 0;
	width: 100%;
	height: 100%;
	max-width: none;
	object-fit: cover;
	object-position: center 30%;
}

/* --- readability scrim ------------------------------------------------------
   Target: >= 7:1 (WCAG AAA, normal text) for #ffffff over the WORST possible
   photo, that is pure white. Compositing slate-900 (#0f172a) at alpha a over
   white gives: a=0.72 -> #52585F -> 7.13:1 ; a=0.78 -> #444A59 -> 8.87:1.
   The gradient never drops below 0.72, and is 0.94 behind the text column. */
.hero-scrim {
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(
		90deg,
		rgba(15, 23, 42, 0.94) 0%,
		rgba(15, 23, 42, 0.88) 38%,
		rgba(15, 23, 42, 0.72) 100%
	);
}

.hero-inner {
	position: relative;
	z-index: 2;
	width: 100%;
	min-width: 0;
	padding-top: 3.5rem;
	padding-bottom: 4.5rem; /* clears .hero-controls */
}

.hero-copy {
	max-width: 55rem;
}

.hero-eyebrow {
	display: inline-block;
	margin-bottom: 0.75rem;
	padding: 0.25rem 0.75rem;
	border-radius: 9999px;
	background-color: rgba(96, 165, 250, 0.16);
	color: var(--blue-400);
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.02em;
	text-transform: uppercase;
}

/* h1 on slide 1, <p> on slides 2 and 3. Identical presentation, one document
   <h1> only. Does not inherit main.css h1 sizing, so it is set explicitly. */
.hero-title {
	margin-bottom: 1rem;
	overflow-wrap: break-word;
	font-size: 2rem;
	font-weight: 700;
	line-height: 1.15;
	color: var(--white);
	text-shadow: 0 1px 3px rgba(0, 0, 0, 0.55);
}

.hero-desc {
	margin-bottom: 1.25rem;
	max-width: 47rem;
	color: var(--slate-200);
	font-size: 1.0625rem;
	line-height: 1.6;
}

.hero-creds {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0 0 1.5rem;
	padding: 0;
	list-style: none;
}

.hero-creds li {
	margin-left: 0; /* main.css:283 sets li { margin-left: 1.5rem } globally */
	padding: 0.3125rem 0.75rem;
	border: 1px solid rgba(96, 165, 250, 0.35);
	border-radius: 0.375rem;
	background-color: rgba(15, 23, 42, 0.45);
	color: var(--slate-100);
	font-size: 0.8125rem;
	font-weight: 600;
}

.hero-actions {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
}

/* The portrait is the whole point of slide 1: a visitor who knows Chris should
   recognise the site as his. It therefore stays visible on every viewport, as a
   compact avatar above the copy on small screens and as a full portrait beside
   it from 1024px up. column-reverse lifts it above .hero-copy without moving it
   in the DOM, so the heading still reads first for assistive technology. */
.hero-inner--split {
	display: flex;
	flex-direction: column-reverse;
	align-items: flex-start;
	gap: 1.5rem;
}

.hero-figure {
	display: flex;
	justify-content: flex-start;
}

.hero-portrait {
	width: 88px;
	height: 88px;
	max-width: 100%;
	border-radius: 9999px;
	object-fit: cover;
	object-position: center top;
	border: 3px solid rgba(96, 165, 250, 0.55);
	box-shadow: 0 12px 28px -10px rgba(0, 0, 0, 0.65);
}

/* --- prev / next ------------------------------------------------------------ */
/* The button spans the full height of the carousel, so anywhere down the left
   or right edge triggers prev/next. Only the chip inside it is painted; the
   column itself stays transparent until hover. It sits below .hero-controls in
   the stack so the play/pause pill always wins the pointer. */
.hero-nav {
	position: absolute;
	top: 0;
	bottom: 0;
	z-index: 2;
	display: none;
	/* The column still spans the full height, so the whole edge stays clickable.
	   Only the chip drops to the bottom, where it lines up with the dots and the
	   play/pause pill to read as one row of controls. */
	align-items: flex-end;
	justify-content: center;
	width: var(--hero-nav-w);
	padding: 0 0 1.25rem;
	border: 0;
	background-color: transparent;
	color: var(--white);
	cursor: pointer;
	transition: background-color 0.25s ease;
}

/* The visible chip. Styling the svg directly avoids an extra wrapper element. */
.hero-nav > svg {
	width: 44px;
	height: 44px;
	padding: 7px;
	border: 1px solid rgba(255, 255, 255, 0.25);
	border-radius: 9999px;
	background-color: rgba(15, 23, 42, 0.55);
	transition: background-color 0.25s ease, border-color 0.25s ease, transform 0.25s ease;
}

.hero-nav:hover > svg {
	background-color: var(--blue-600);
	border-color: var(--blue-400);
	transform: scale(1.08);
}

/* A faint wash confirms the whole column is the target, not just the chip. */
.hero-nav--prev:hover { background-image: linear-gradient(90deg, rgba(15, 23, 42, 0.5), transparent); }
.hero-nav--next:hover { background-image: linear-gradient(270deg, rgba(15, 23, 42, 0.5), transparent); }

.hero-nav:focus-visible,
.hero-dot:focus-visible,
.hero-toggle:focus-visible {
	outline: 3px solid var(--blue-400);
	outline-offset: 3px;
}

.hero-nav--prev { left: 0; }
.hero-nav--next { right: 0; }

/* --- dots + play/pause ------------------------------------------------------ */
.hero-controls {
	position: absolute;
	left: 50%;
	bottom: 1.25rem;
	z-index: 4; /* above .hero-nav, so the pill always wins the pointer */
	display: flex;
	align-items: center;
	gap: 1rem;
	transform: translateX(-50%);
	padding: 0.4375rem 0.875rem;
	border-radius: 9999px;
	background-color: rgba(15, 23, 42, 0.6);
	backdrop-filter: blur(4px);
}

.hero-dots {
	display: flex;
	align-items: center;
	gap: 0.625rem;
}

.hero-dot {
	position: relative;
	width: 10px;
	height: 10px;
	padding: 0;
	border: 0;
	border-radius: 9999px;
	background-color: rgba(255, 255, 255, 0.4);
	cursor: pointer;
	transition: background-color 0.25s ease, width 0.25s ease;
}

.hero-dot:hover { background-color: rgba(255, 255, 255, 0.75); }

.hero-dot[aria-current="true"] {
	width: 28px;
	background-color: var(--blue-400);
}

/* Touch target: WCAG 2.5.8 wants >= 24x24 CSS px. The visual dot is 10px, so an
   invisible pseudo-element supplies the hit area without changing layout. */
.hero-dot::after {
	content: "";
	position: absolute;
	left: 50%;
	top: 50%;
	width: 28px;
	height: 28px;
	transform: translate(-50%, -50%);
}

.hero-toggle {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	padding: 0;
	border: 0;
	border-radius: 9999px;
	background-color: transparent;
	color: var(--white);
	cursor: pointer;
	transition: background-color 0.25s ease;
}

.hero-toggle:hover { background-color: rgba(255, 255, 255, 0.18); }

.hero-toggle .hero-toggle-play { display: none; }
.hero-toggle.is-paused .hero-toggle-pause { display: none; }
.hero-toggle.is-paused .hero-toggle-play { display: block; }

/* --- trust band -------------------------------------------------------------
   A <div>, NOT a <section>. main.css:905 `.section:nth-of-type(odd)` counts
   <section> siblings regardless of class, so adding one here would flip the
   background striping of every section below it on this page. */
.trust-band {
	position: relative;
	z-index: 1;
	background: linear-gradient(135deg, var(--slate-900), var(--slate-800));
	color: var(--slate-200);
	padding: 1.75rem 0;
	border-top: 1px solid rgba(96, 165, 250, 0.22);
}

.trust-band-inner {
	display: flex;
	min-width: 0;
	flex-direction: column;
	gap: 1rem;
	align-items: flex-start;
}

.trust-band-desc {
	margin: 0;
	max-width: 46rem;
	font-size: 0.9375rem;
	line-height: 1.6;
	color: var(--slate-300);
}

.trust-band-desc strong {
	color: var(--white);
	font-weight: 600;
}

.trust-band-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.trust-band-chips li {
	margin-left: 0; /* main.css:283 global li indent */
	padding: 0.3125rem 0.75rem;
	border: 1px solid rgba(148, 163, 184, 0.35);
	border-radius: 9999px;
	color: var(--slate-100);
	font-size: 0.8125rem;
	font-weight: 600;
	white-space: nowrap;
}

/* --- breakpoints (mirrors the 640 / 768 / 1024 set already in main.css) ----- */
@media (max-width: 767px) {
	/* Small prev/next buttons on the bottom control row. The full height edge
	   columns are not usable here: they would sit on top of the copy and fight
	   the swipe gesture, so the button collapses to a corner chip instead. It is
	   anchored to the frame edge rather than offset from the centre pill, so it
	   cannot collide with the pill whatever width the dots end up. */
	.hero-nav {
		display: flex;
		top: auto;
		bottom: 1.25rem;
		width: 44px;   /* touch target */
		height: 44px;
		padding: 0;
		align-items: center;
		justify-content: center;
	}

	.hero-nav > svg {
		width: 40px;
		height: 40px;
		padding: 7px;
	}

	.hero-nav--prev { left: 0.75rem; right: auto; }
	.hero-nav--next { right: 0.75rem; left: auto; }

	/* the column wash is meaningless once the button is a corner chip */
	.hero-nav--prev:hover,
	.hero-nav--next:hover { background-image: none; }

	/* Copy sits over the whole frame on small screens rather than the dark left
	   third, so the scrim needs a higher floor. Minimum alpha 0.78 -> 8.87:1. */
	.hero-scrim {
		background: linear-gradient(
			180deg,
			rgba(15, 23, 42, 0.86) 0%,
			rgba(15, 23, 42, 0.78) 55%,
			rgba(15, 23, 42, 0.93) 100%
		);
	}

	.hero-slide-bg { object-position: center 25%; }
}

@media (min-width: 640px) {
	.hero-actions { flex-direction: row; flex-wrap: wrap; gap: 1rem; }
	.hero-title { font-size: 2.5rem; }
	.trust-band-inner { flex-direction: row; align-items: center; justify-content: space-between; gap: 2rem; }
}

@media (min-width: 768px) {
	.hero-viewport { min-height: clamp(600px, 78svh, 720px); }
	.hero-portrait { width: 112px; height: 112px; }
	.hero-nav { display: flex; }
	.hero-title { font-size: 3rem; }

	/* Each column grows to fill the free gutter beside the 1200px .container,
	   so on a wide screen the hit zone reaches all the way in to the content
	   instead of hugging the viewport edge. Below 1200px there is no gutter and
	   it falls back to --hero-nav-w. */
	.hero-nav { width: max(var(--hero-nav-w), calc((100% - var(--hero-content-w)) / 2)); }

	/* Park the chip at the content side of its column, not the screen edge. */
	.hero-nav--prev { justify-content: flex-end; padding-right: 0.25rem; }
	.hero-nav--next { justify-content: flex-start; padding-left: 0.25rem; }

	.hero-inner {
		padding-top: 4rem;
		padding-bottom: 5rem;
		/* Reserve only the part of a column that actually eats into the
		   container. Once the gutter is wider than the column (roughly 1400px
		   up) this resolves to the plain 1rem the rest of the site uses, so the
		   copy regains its full width instead of staying permanently indented. */
		padding-left: max(1rem, calc(1rem + var(--hero-nav-w) - max(0px, (100vw - var(--hero-content-w)) / 2)));
		padding-right: max(1rem, calc(1rem + var(--hero-nav-w) - max(0px, (100vw - var(--hero-content-w)) / 2)));
	}
}

@media (min-width: 1024px) {
	.hero-viewport { min-height: clamp(640px, 80svh, 760px); }
	.hero-title { font-size: 3.25rem; }

	/* Slide 1 only: two column split so the portrait reads as a person rather
	   than as decoration. */
	.hero-inner--split {
		display: grid;
		grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
		gap: 3rem;
		align-items: center;
	}

	.hero-figure {
		justify-content: center;
	}

	.hero-portrait {
		width: 340px;
		height: 340px;
		border-width: 4px;
		box-shadow: 0 24px 48px -12px rgba(0, 0, 0, 0.65);
	}
}

@media (min-width: 1280px) {
	.hero-portrait { width: 400px; height: 400px; }
}

/* --- reduced motion ---------------------------------------------------------
   Same convention already used in btt.css:175 and toc.css:327. Slides cut
   instead of cross-fading, and carousel.js reads the same media query and
   refuses to autoplay. */
@media (prefers-reduced-motion: reduce) {
	.hero-slide,
	.hero-slide.is-active,
	.hero-nav,
	.hero-dot,
	.hero-toggle {
		transition: none;
	}

	.hero-nav > svg,
	.hero-nav:hover > svg {
		transition: none;
		transform: none;
	}
}
