/**
 * Gen-2 single `project` template styles — Documentation Export production
 * template.
 *
 * Pairs with single-project.php + single-project.js. Enqueued by the Neve
 * child theme's functions.php only on is_singular('project') — this file
 * makes no theme_mod / Customizer / Site Option changes itself.
 *
 * Tokens below are taken from docs/joetennis-com-styleguide.md (Section
 * 1-3), duplicated here (not @import-ed) so this file works standalone.
 *
 * Font dependency: 'Noto Sans' and 'Inter' (Google Fonts, per the
 * styleguide) are NOT loaded by this file or by functions.php — out of
 * scope for this story (carried-forward gap from the Gen-1 slice). Rules
 * below silently fall back to generic sans-serif until fonts are enqueued
 * somewhere in the stack.
 *
 * Carousels (P/S/R mobile, Details both breakpoints) use native CSS
 * scroll-snap, not JS-computed offsets — see single-project.js and this
 * story's spec Design Notes. Everything under `.single-project__carousel-*`
 * is shared markup/styling for both carousel instances; single-project.js
 * hooks into the parallel `data-carousel-*` attributes, decoupled from
 * these class names on purpose so styling and behavior can change
 * independently.
 */

.single-project {
	--color-bg-site: #0a0e1a;
	--color-bg-recessed: #05070d;
	--color-bg-surface: #111827;
	--color-accent-primary: #00e5ff;
	--color-accent-secondary: #a855f7;
	--color-text-heading: #f8fafc;
	--color-text-body: #e2e8f0;

	/* CAP-3, spec-sitewide-alignment-band: swapped the hardcoded 1200px
	   band + 24px horizontal padding for the shared --container band
	   (same dial as the header/breadcrumb-utility row/archive hero image)
	   so this template's outer wrapper edges match the sitewide band
	   exactly. Vertical padding (64px/120px) is untouched. */
	max-width: var(--container);
	margin: 0 auto;
	padding: 64px var(--band-gutter, 15px) 120px;
	background-color: var(--color-bg-site);
	color: var(--color-text-body);
	font-family: var(--font-body);
}

.single-project__empty {
	font-family: var(--font-body);
	font-size: 18px;
	color: var(--color-text-body);
	opacity: 0.7;
}

/* ---------------------------------------------------------------------
   Hero: image + headline, split desktop / stacked mobile.
   ------------------------------------------------------------------ */

.single-project__hero {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 48px;
	align-items: center;
	margin-bottom: 96px;
}

/* No featured image set: the media column is omitted from the markup
   entirely (see single-project.php), and the text column takes the full
   row instead of leaving an empty second track. */
.single-project__hero--no-media {
	grid-template-columns: 1fr;
}
.single-project__hero--no-media .single-project__hero-content {
	max-width: 760px;
}

/* No title/subtitle/discipline term at all (thumbnail-only post): the
   content column is omitted from the markup (see single-project.php), so
   the media column takes the full row instead of sitting beside an empty
   track. */
.single-project__hero--no-text {
	grid-template-columns: 1fr;
}

.single-project__eyebrow {
	display: inline-block;
	max-width: 100%;
	font-family: var(--font-body);
	font-weight: 500;
	font-size: 14px;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: var(--color-accent-primary);
	border: 1px solid rgba(0, 229, 255, 0.3);
	padding: 6px 14px;
	margin: 0 0 24px;
}

.single-project__hero-title {
	/* Display/H1 per styleguide Section 2: 96-112px desktop, 40-48px mobile. */
	font-family: var(--font-heading);
	font-weight: 700;
	font-size: 96px;
	line-height: 0.92;
	letter-spacing: -0.05em;
	color: var(--color-text-heading);
	margin: 0 0 24px;
}

.single-project__hero-subtitle {
	font-family: var(--font-body);
	font-weight: 400;
	font-size: 18px;
	line-height: 1.6;
	color: var(--color-text-body);
	max-width: 560px;
	margin: 0;
}

.single-project__hero-media {
	line-height: 0;
}

.single-project__hero-image {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 0;
}

/* ---------------------------------------------------------------------
   Intro: heading/summary + gallery grid, between hero and P/S/R.
   Added Story 2.9 (deferred-work.md template-rendering-gap fix).
   ------------------------------------------------------------------ */

.single-project__intro {
	margin-bottom: 96px;
}

.single-project__intro-text {
	max-width: 760px;
	margin-bottom: 32px;
}

.single-project__intro-heading {
	font-family: var(--font-heading);
	font-weight: 600;
	font-size: 32px;
	line-height: 1.1;
	letter-spacing: -0.02em;
	color: var(--color-text-heading);
	margin: 0 0 16px;
}

.single-project__intro-summary {
	font-family: var(--font-body);
	font-size: 16px;
	line-height: 1.6;
	color: var(--color-text-body);
}
.single-project__intro-summary p {
	margin: 0 0 16px;
}
.single-project__intro-summary p:last-child {
	margin-bottom: 0;
}

.single-project__intro-gallery {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
	gap: 24px;
}

.single-project__intro-gallery-item {
	margin: 0;
}

.single-project__intro-gallery-image {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 0;
}

.single-project__intro-gallery-caption {
	font-family: var(--font-body);
	font-size: 14px;
	line-height: 1.5;
	color: var(--color-text-body);
	opacity: 0.7;
	margin-top: 8px;
}

/* ---------------------------------------------------------------------
   Problem / Solution / Results: static row desktop, peek-carousel mobile.
   ------------------------------------------------------------------ */

.single-project__psr {
	margin-bottom: 96px;
}

.single-project__psr-track {
	display: grid;
	/* Column count matches however many of Problem/Solution/Results are
	   actually populated (set inline via --single-project-psr-count in
	   single-project.php) rather than always reserving 3 tracks. */
	grid-template-columns: repeat(var(--single-project-psr-count, 3), 1fr);
	gap: 32px;
}

.single-project__psr-card {
	background-color: var(--color-bg-surface);
	border: 1px solid rgba(0, 229, 255, 0.15);
	padding: 32px;
}

.single-project__psr-label {
	font-family: var(--font-heading);
	font-weight: 600;
	font-size: 20px;
	letter-spacing: -0.01em;
	text-transform: uppercase;
	color: var(--color-accent-primary);
	margin: 0 0 16px;
}

.single-project__psr-body,
.single-project__details-body {
	font-family: var(--font-body);
	font-size: 16px;
	line-height: 1.6;
	color: var(--color-text-body);
}

.single-project__psr-body p,
.single-project__details-body p {
	margin: 0 0 16px;
}
.single-project__psr-body p:last-child,
.single-project__details-body p:last-child {
	margin-bottom: 0;
}

/* ---------------------------------------------------------------------
   Shared carousel chrome (prev/next, dots, counter) — used by both the
   P/S/R and Details carousels. Hidden by default; each carousel opts in
   below at whichever breakpoint(s) it actually scrolls at.
   ------------------------------------------------------------------ */

.single-project__carousel-controls,
.single-project__carousel-dots {
	display: none;
}

.single-project__carousel-controls {
	align-items: center;
	justify-content: center;
	gap: 24px;
	margin-top: 32px;
}

.single-project__carousel-dots {
	justify-content: center;
	gap: 8px;
	margin-top: 16px;
}

.single-project__carousel-btn {
	/* The FILL is retired to site-interactive-states.css too (story 5),
	   as `--state-carousel-rest-bg`. The `background: transparent`
	   shorthand that used to sit here is gone deliberately: it was a
	   literal doing a token's job, and at (0,1,0) it would have lost to
	   the shared rest rule anyway the moment a ground bound a real
	   fill. Declaring nothing here is what lets the ground decide. */
	/* Geometry only. Edge COLOUR, ink, radius and weight are retired to
	   site-interactive-states.css (SPEC-interactive-color-states story 2);
	   the rest edge still renders `rgba(0, 229, 255, 0.3)`, now as
	   `--state-carousel-rest-bd`. Longhands, not the `border` shorthand:
	   the shorthand would set border-color to currentColor and beat the
	   shared rule from later in the cascade. */
	border-width: 1px;
	border-style: solid;
	/* Same fix as flush-split.css's carousel button (story 5): `padding:
	   0` is what stops Neve's `padding: 12px 32px` flooring the used width
	   at 66px, which made 999px clamp to a stadium. `box-sizing` is
	   explicit rather than load-bearing -- Neve already sets it on button. Applied here for parity even
	   though this selector matches nothing on the live site today --
	   single-project.php emits `editorial-split__*` markup instead -- so
	   the bug cannot come back with the template. */
	box-sizing: border-box;
	padding: 0;
	width: 40px;
	height: 40px;
	font-size: 20px;
	line-height: 1;
	cursor: pointer;
}

.single-project__carousel-counter {
	font-family: var(--font-body);
	font-size: 14px;
	color: var(--color-text-body);
}

.single-project__carousel-dot {
	width: 8px;
	height: 8px;
	/* A dot, so a full round. This once read "exception to the 0px rule,
	   per styleguide Section 3"; that rule was retired sitewide on
	   2026-09-19 (SPEC-interactive-color-states story 4, "round means
	   clickable"). This is static decoration, not a control, so it is
	   outside the affordance rule either way -- but it is no longer an
	   exception to anything. The styleguide doc still states the old
	   rule and has not been reconciled. */
	border-radius: 50%;
	background: var(--color-text-body);
	opacity: 0.3;
	border: none;
	padding: 0;
	cursor: pointer;
}
.single-project__carousel-dot.is-active {
	opacity: 1;
	background: var(--color-accent-primary);
}

/* Details carousel controls are visible at every breakpoint — it's a
   carousel on both desktop and mobile. P/S/R controls stay hidden until
   the mobile breakpoint turns its track into a scroller (see below).
   Both are gated on `.has-js-controls`, a class single-project.js adds only
   after it successfully initializes a carousel — so if JS fails to load,
   the (otherwise inert) prev/next/dot buttons never appear; native
   scroll-snap swipe/scroll still works either way. */
.single-project__details.has-js-controls .single-project__carousel-controls {
	display: flex;
}
.single-project__details.has-js-controls .single-project__carousel-dots {
	display: flex;
}

/* ---------------------------------------------------------------------
   Details: numbered carousel over narrative_chunks, desktop and mobile.
   ------------------------------------------------------------------ */

.single-project__details {
	margin-bottom: 32px;
}

.single-project__details-track {
	display: flex;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	gap: 48px;
	scrollbar-width: none;
}
.single-project__details-track::-webkit-scrollbar {
	display: none;
}

.single-project__details-card {
	flex: 0 0 100%;
	scroll-snap-align: start;
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 48px;
	/* Top-aligned, not centered: card height is set by whichever chunk has
	   the most text, so centering left short chunks floating with a big
	   gap above the image. Top alignment keeps image and heading level
	   across every chunk regardless of body length. */
	align-items: start;
}

.single-project__details-image-wrap {
	line-height: 0;
}
.single-project__details-image {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 0;
}

.single-project__details-heading {
	font-family: var(--font-heading);
	font-weight: 600;
	font-size: 32px;
	line-height: 1.1;
	letter-spacing: -0.02em;
	color: var(--color-text-heading);
	margin: 0 0 8px;
}

.single-project__details-subhead {
	font-family: var(--font-body);
	/* 18px, not 16px: styleguide Section 1 reserves the violet secondary
	   accent for 18px+/bold 14px+ text — 16px regular-weight body-size text
	   falls below its verified-contrast threshold. */
	font-size: 18px;
	color: var(--color-accent-secondary);
	margin: 0 0 16px;
}

/* ---------------------------------------------------------------------
   Toggle Sections: native <details>/<summary> accordion, no JS dependency.
   Added Story 2.9 (deferred-work.md template-rendering-gap fix).
   ------------------------------------------------------------------ */

.single-project__toggles {
	margin-bottom: 32px;
}

.single-project__toggle {
	background-color: var(--color-bg-surface);
	border: 1px solid rgba(0, 229, 255, 0.15);
	padding: 24px 32px;
	margin-bottom: 16px;
}
.single-project__toggle:last-child {
	margin-bottom: 0;
}

.single-project__toggle-summary {
	font-family: var(--font-heading);
	font-weight: 600;
	font-size: 20px;
	letter-spacing: -0.01em;
	color: var(--color-text-heading);
	cursor: pointer;
	list-style: none;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
}
/* Replace the native disclosure triangle (inconsistent across browsers)
   with a +/- indicator that flips on [open], instead of a browser-default
   marker.

   The reason given here used to be "matching the site's square, no-radius
   visual language". THAT LANGUAGE IS RETIRED -- story 4 of
   SPEC-interactive-color-states inverted it sitewide on 2026-09-19 to
   "round means clickable". The +/- indicator is kept on its own merits
   (cross-browser consistency), not on the retired rule. Note that this
   <summary> IS operable and is NOT yet on a Family C radius token, so it
   is one of the recorded open cases -- see the Family C block in
   site-interactive-states.css. */
.single-project__toggle-summary::-webkit-details-marker {
	display: none;
}
.single-project__toggle-summary::marker {
	display: none;
}
.single-project__toggle-summary::after {
	content: '+';
	flex: 0 0 auto;
	font-size: 24px;
	color: var(--color-accent-primary);
}
.single-project__toggle[open] .single-project__toggle-summary::after {
	content: '\2212'; /* minus sign */
}

.single-project__toggle-body {
	font-family: var(--font-body);
	font-size: 16px;
	line-height: 1.6;
	color: var(--color-text-body);
	margin-top: 16px;
}
.single-project__toggle-body p {
	margin: 0 0 16px;
}
.single-project__toggle-body p:last-child {
	margin-bottom: 0;
}

/* ---------------------------------------------------------------------
   Mobile — matches the styleguide's existing mobile scale.
   ------------------------------------------------------------------ */

@media (max-width: 768px) {
	.single-project {
		padding: 40px 16px 64px;
	}

	.single-project__hero {
		grid-template-columns: 1fr;
		gap: 32px;
		margin-bottom: 64px;
	}
	.single-project__hero-title {
		font-size: 44px;
	}
	.single-project__hero-subtitle {
		font-size: 16px;
		max-width: none;
	}

	.single-project__intro {
		margin-bottom: 64px;
	}
	.single-project__intro-heading {
		font-size: 24px;
	}
	.single-project__intro-gallery {
		grid-template-columns: 1fr;
		gap: 16px;
	}

	.single-project__toggle {
		padding: 16px 20px;
	}
	.single-project__toggle-summary {
		font-size: 18px;
	}

	/* P/S/R becomes a swipeable peek-carousel: fixed card width below
	   100% so neighbors visibly peek at the track edges. Per-card
	   scroll-snap-align (start/center/end) + scroll-padding-inline on the
	   track (matching the peek margin) produces the peek effect on the
	   first/middle/last cards without any hand-computed offsets — see
	   this story's spec Design Notes. */
	.single-project__psr-track {
		display: flex;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		scroll-padding-inline: 32px;
		gap: 16px;
		scrollbar-width: none;
	}
	.single-project__psr-track::-webkit-scrollbar {
		display: none;
	}
	.single-project__psr-card {
		flex: 0 0 82%;
	}
	.single-project__psr-card:first-child {
		scroll-snap-align: start;
	}
	.single-project__psr-card:nth-child(2) {
		scroll-snap-align: center;
	}
	.single-project__psr-card:last-child {
		scroll-snap-align: end;
	}

	.single-project__psr.has-js-controls .single-project__carousel-controls,
	.single-project__psr.has-js-controls .single-project__carousel-dots {
		display: flex;
	}

	.single-project__details {
		margin-bottom: 16px;
	}
	.single-project__details-track {
		gap: 32px;
	}
	.single-project__details-card {
		grid-template-columns: 1fr;
		gap: 24px;
	}
	/* Image runs edge to edge: cancel the container's 16px mobile gutter.
	   Body text keeps the full available width (no max-width constraint)
	   instead of the desktop two-column split. */
	.single-project__details-image-wrap {
		margin-inline: -16px;
	}
	.single-project__details-heading {
		font-size: 24px;
	}
}

/* Respect a visitor's OS-level reduced-motion preference. single-project.js
   also checks this before requesting smooth scrolling on prev/next/dot
   clicks; this is the CSS-only backstop for any scroll not driven by JS. */
@media (prefers-reduced-motion: reduce) {
	.single-project__psr-track,
	.single-project__details-track {
		scroll-behavior: auto;
	}
}
