/**
 * wwh/guide-slideshow — public member guides.
 *
 * ⚠️ Off-slides are hidden by TRANSFORM, never display:none or
 * visibility:hidden. Google discounts content hidden by those two, and these
 * pages exist partly to rank for "how do I join as an artisan". The overflow
 * clip on the viewport is what actually hides them; inert (set in markup and
 * by view.js) is what removes them from focus.
 *
 * No focus-visible rules here: the theme's assets/css/focus.css sets a
 * specificity-0 floor with :where(), which these controls inherit. Never write
 * outline:none on a base selector — WCAG.md F-1 records three rules that did
 * exactly that and cost a whole audit finding.
 */

.wwh-guide {
	--wwh-guide-gap: clamp( 1rem, 3vw, 2rem );
	/* Wider than a prose column: the screenshots are the content here, and
	   every extra pixel of width is a legible pixel of UI in the picture. */
	max-width: 82rem;
	margin-inline: auto;
	padding-inline: 1rem; /* 16px gutter: no horizontal scroll at 320px. */
	padding-block-end: var( --wwh-guide-gap );
}

/* ---- Header ---------------------------------------------------------- */

/*
 * ⚠️ The dark band is load-bearing, not decoration.
 *
 * The site header is an absolutely-positioned transparent overlay with
 * hardcoded white text (theme assets/css/header.css). Every other page puts a
 * dark cover hero underneath it; this page has no hero, so without a dark band
 * here the logo and all four nav buttons are white-on-white and fail contrast
 * outright — measured as 7 axe violations when the hero was first removed.
 *
 * The top padding clears the 106px header. If you change either value, re-run
 * axe on /guides/<slug>/ before assuming it still passes.
 */
/*
 * Full-bleed by painting, not by width. The previous `margin-inline:
 * calc( 50% - 50vw )` made the box 100vw wide, and 100vw includes the vertical
 * scrollbar, so the page scrolled sideways by the scrollbar's width (measured
 * 1433px in a 1425px viewport). The shadow paints the band out to both edges
 * and clip-path trims its top and bottom; the box itself stays in the column.
 */
.wwh-guide__header {
	--wwh-guide-band: var( --wp--preset--color--warm-obsidian, #18140F );
	padding: calc( 106px + 0.5rem ) 1rem 1.25rem;
	background: var( --wwh-guide-band );
	box-shadow: 0 0 0 100vmax var( --wwh-guide-band );
	clip-path: inset( 0 -100vmax );
	color: #fff;
	text-align: center;
	margin-block-end: var( --wwh-guide-gap );
}

.admin-bar .wwh-guide__header {
	padding-block-start: calc( 106px + 32px + var( --wwh-guide-gap ) );
}

.wwh-guide__title {
	margin-block: 0 0.25em;
	color: #fff;
}

.wwh-guide__summary {
	margin-block: 0 0.5em;
	margin-inline: auto;
	max-width: 60ch;
	color: rgba( 255, 255, 255, 0.85 );
}

.wwh-guide__viewtoggle {
	margin-block: 0;
	font-size: 0.875rem;
}

.wwh-guide__viewtoggle a {
	color: rgba( 255, 255, 255, 0.85 );
}

/* ---- Video ----------------------------------------------------------- */

/*
 * The guide's own video sits above the slides. At the full 82rem column a
 * 16:9 player is taller than a laptop screen and pushes the first step and
 * "Get started" below the fold, so it is held to a comfortable watching width.
 */
.wwh-guide .wwh-vinline {
	max-width: min( 100%, 48rem );
	margin-inline: auto;
	margin-block-end: var( --wwh-guide-gap );
}

.wwh-guide .wwh-vinline video,
.wwh-guide .wwh-vinline iframe {
	border-radius: 0.5rem;
}

/* ---- Slides ---------------------------------------------------------- */

.wwh-guide__viewport {
	overflow: hidden;
	border-radius: 0.5rem;
}

.wwh-guide__track {
	display: flex;
	/* Transition is cleared to `none` by view.js under prefers-reduced-motion,
	   which is why it is declared here rather than inside a media query. */
	transition: transform 300ms ease;
	will-change: transform;
}

.wwh-guide__slide {
	flex: 0 0 100%;
	min-width: 0; /* flex children refuse to shrink below content without this */
	box-sizing: border-box;
}

/* tabindex="-1" is there so view.js can move focus on step change; it must not
   draw a ring, because that focus is programmatic and not a user's tab stop. */
.wwh-guide__slide:focus {
	outline: none;
}

.wwh-guide__slide-inner {
	padding: 0 0 var( --wwh-guide-gap );
	text-align: center;
}

.wwh-guide__slide-heading {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: center;
	gap: 0.5em;
	margin-block-start: 0;
	font-size: clamp( 1.25rem, 2.5vw, 1.75rem );
}

.wwh-guide__step-badge {
	font-size: 0.75rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	opacity: 0.7;
	white-space: nowrap;
}

.wwh-guide__slide-body {
	max-width: 62ch;
	margin-inline: auto;
	text-align: left; /* Prose still reads left-aligned; only the frame centres. */
}

.wwh-guide__slide-body > :first-child { margin-block-start: 0; }
.wwh-guide__slide-body > :last-child  { margin-block-end: 0; }

/* ---- Figures --------------------------------------------------------- */

.wwh-guide__figure {
	margin: var( --wwh-guide-gap ) 0 0;
}

/*
 * The screenshot is the point of the slide, so it gets the room.
 *
 * Capped by viewport height as well as width: a 16:9 screenshot at full column
 * width is taller than many laptop viewports, which would put the Next button
 * below the fold on every step and make the guide feel like a scrolling page
 * rather than a slideshow.
 *
 * ⚠️ `width: 100%` + `max-height` + `object-fit: contain` is the obvious way to
 * write that and it is WRONG. `width: 100%` with `height: auto` sizes the
 * layout box from the image's aspect ratio; `max-height` then squashes THE BOX;
 * and `contain` letterboxes the picture inside that squashed box rather than
 * shrinking the box to fit. The image stays centred in a frame far wider than
 * itself. Measured on manage-your-subscription at 1440×900: every slide got a
 * 1312×522 box whatever its shape, so a 1600×1111 frame drew at 752×522 (43%
 * of the box empty) and the portrait 1536×2000 Stripe captures drew at just
 * 401×522 — a fifth of the available width, and genuinely unreadable.
 *
 * `max-width` + `max-height` with `width: auto` constrains the BOX by both
 * axes, so it shrink-wraps the picture and nothing is letterboxed. No
 * object-fit needed: the box now always matches the image's ratio.
 */
.wwh-guide__image {
	display: block;
	width: auto;
	height: auto;
	max-width: 100%;
	max-height: 58vh;
	margin-inline: auto;
	border-radius: 0.375rem;
	box-shadow: 0 2px 10px rgba( 0, 0, 0, 0.16 );
}

/*
 * Portrait screenshots get more height, because for them height decides WIDTH.
 *
 * 58vh keeps the Next button above the fold, which is what makes this read as
 * a slideshow rather than a page — worth keeping for a landscape frame, whose
 * width binds first anyway. A tall frame is the opposite: the height cap sets
 * its width, and the 1536×2000 Stripe portal captures came out 401px wide in a
 * 1312px column. A fifth of the available space, and too small to read the
 * labels the slide is talking about.
 *
 * 88vh lets those roughly half again wider. The reader scrolls a little on
 * these slides; that is the better failure — a picture you scroll to see is
 * usable, a picture too small to read is not.
 *
 * The class comes from render.php: CSS cannot branch on an intrinsic ratio.
 */
.wwh-guide__image--tall {
	max-height: 88vh;
}

/*
 * Legacy two-image slides stack rather than sitting side by side.
 *
 * Pairs were tried and dropped: two screenshots in one row are each half size,
 * which defeats the purpose of a full-bleed screenshot. A step needing two
 * pictures should be two slides. This rule only stops an older public.md
 * looking broken.
 */
.wwh-guide__figure--pair {
	display: grid;
	gap: 1rem;
}

/* ---- Zoom ------------------------------------------------------------ */

/*
 * The button is a transparent wrapper — the image is the visible thing.
 *
 * It shrink-wraps the image rather than filling the column: the image sizes
 * itself by max-width AND max-height (see .wwh-guide__image), so a full-width
 * button would leave a portrait screenshot pinned to the left of a much wider
 * button, with the "Click to enlarge" hint floating at the button's edge
 * instead of the picture's corner. `width: fit-content` + auto margins keeps
 * the two the same size and centred.
 */
.wwh-guide__zoom {
	display: block;
	width: fit-content;
	max-width: 100%;
	margin-inline: auto;
	padding: 0;
	border: 0;
	background: none;
	cursor: zoom-in;
	position: relative;
}

.wwh-guide__zoom-hint {
	position: absolute;
	inset: auto 0.75rem 0.75rem auto;
	padding: 0.35em 0.8em;
	border-radius: 999px;
	background: rgba( 24, 20, 15, 0.82 );
	color: #fff;
	font-family: var( --wp--preset--font-family--ui, system-ui, sans-serif );
	font-size: 0.75rem;
	letter-spacing: 0.04em;
	opacity: 0;
	transition: opacity 150ms ease;
	pointer-events: none;
}

/* Shown on hover, and on keyboard focus — a keyboard user needs to know the
   image is actionable just as much as a mouse user does. */
.wwh-guide__zoom:hover .wwh-guide__zoom-hint,
.wwh-guide__zoom:focus-visible .wwh-guide__zoom-hint {
	opacity: 1;
}

@media ( prefers-reduced-motion: reduce ) {
	.wwh-guide__zoom-hint { transition: none; }
}

/* Touch has no hover, so the affordance has to be permanent there. */
@media ( hover: none ) {
	.wwh-guide__zoom-hint { opacity: 1; }
}

.wwh-guide__lightbox {
	position: fixed;
	inset: 0;
	z-index: 9999;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: clamp( 0.5rem, 3vw, 2.5rem );
	background: rgba( 12, 10, 8, 0.94 );
	cursor: zoom-out;
}

/* [hidden] needs help against display:flex — without this the overlay is
   permanently visible, covering the page. */
.wwh-guide__lightbox[hidden] {
	display: none;
}

.wwh-guide__lightbox-img {
	max-width: 100%;
	max-height: 100%;
	width: auto;
	height: auto;
	object-fit: contain;
	cursor: default; /* The image is for looking at; only the backdrop closes. */
	border-radius: 0.25rem;
}

.wwh-guide__lightbox-close {
	position: absolute;
	inset: 0.75rem 0.75rem auto auto;
	width: 44px;
	height: 44px;
	border: 1px solid rgba( 255, 255, 255, 0.5 );
	border-radius: 50%;
	background: rgba( 0, 0, 0, 0.5 );
	color: #fff;
	font-size: 1.5rem;
	line-height: 1;
	cursor: pointer;
}

/*
 * Nudged down for logged-in users: the overlay is position:fixed and so sits
 * under WordPress's admin bar, which would cover the close button for any
 * editor previewing the page. Visitors never see the bar, so the offset only
 * applies when it is present.
 */
.admin-bar .wwh-guide__lightbox-close {
	inset-block-start: calc( 0.75rem + 32px );
}

/* ---- Get started ----------------------------------------------------- */

.wwh-guide__cta {
	margin-block: var( --wwh-guide-gap ) 0;
}

.wwh-guide__start {
	padding: 0.7em 2em;
	border: 0;
	border-radius: 999px;
	background: var( --wp--preset--color--warm-obsidian, #18140F );
	color: #fff;
	font: inherit;
	font-weight: 600;
	font-size: 1.05rem;
	min-height: 48px;
	cursor: pointer;
}

.wwh-guide__start:hover {
	opacity: 0.88;
}

/* ---- Controls -------------------------------------------------------- */

.wwh-guide__controls {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	margin-block-start: var( --wwh-guide-gap );
}

/* The top bar is navigation, not a conclusion — lighter, and it sits above
   the slide rather than after it. */
.wwh-guide__controls--top {
	margin-block: 0 var( --wwh-guide-gap );
	padding-block-end: 0.75rem;
	border-block-end: 1px solid rgba( 128, 128, 128, 0.22 );
}

.wwh-guide__prev,
.wwh-guide__next {
	padding: 0.5em 1em;
	border: 1px solid currentColor;
	border-radius: 999px;
	background: transparent;
	color: inherit;
	font: inherit;
	cursor: pointer;
	/* 44px min target — WCAG 2.5.5, and these are the primary controls. */
	min-height: 44px;
}

.wwh-guide__dots {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.wwh-guide__dots li { margin: 0; }

.wwh-guide__dot {
	/* The visual dot is small, but the button is not: 44x44 with the dot drawn
	   by a background, so a shaky finger on a phone still lands it. */
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	background: transparent;
	cursor: pointer;
	position: relative;
}

.wwh-guide__dot::before {
	content: "";
	position: absolute;
	inset: 50% auto auto 50%;
	translate: -50% -50%;
	width: 10px;
	height: 10px;
	border-radius: 50%;
	border: 1px solid currentColor;
}

.wwh-guide__dot[aria-current="true"]::before {
	background: currentColor;
	/* Never colour alone — the ring grows too, so the current step is
	   distinguishable without perceiving the fill (WCAG 1.4.1). */
	width: 14px;
	height: 14px;
}

/* GitLab #55 (R10f): each dot is a 44px target, so a 16-step guide needs
   ~824px of dots, and on narrower screens they wrapped onto up to six rows and
   pushed Back and Next onto lines of their own. view.js adds is-compact to a
   bar whose dots don't fit on one row with Back and Next (the point depends on
   the number of steps, so it can't be a fixed breakpoint). The dots go, Back
   and Next share a row, and the "Step N of M" line beneath does the counting. */
.wwh-guide__controls.is-compact { flex-wrap: nowrap; }
.wwh-guide__controls.is-compact .wwh-guide__dots { display: none; }

.wwh-guide__progress {
	margin-block: 0.5rem 0;
	font-size: 0.875rem;
	opacity: 0.8;
	text-align: center;
}

/* ---- "View as one page" ---------------------------------------------- */

.wwh-guide--all .wwh-guide__viewport { overflow: visible; }

.wwh-guide--all .wwh-guide__track {
	display: block;
	transform: none;
	transition: none;
}

.wwh-guide--all .wwh-guide__slide {
	border-block-end: 1px solid rgba( 128, 128, 128, 0.25 );
}

.wwh-guide--all .wwh-guide__slide:last-child { border-block-end: 0; }

/* ---- Index ----------------------------------------------------------- */

/*
 * The index has no header of its own: the Guides Page supplies a cover hero
 * (an index-only group, see includes/guides.php), which is what sits behind
 * the transparent site header here.
 */
.wwh-guide-index {
	max-width: 1320px;
	margin-inline: auto;
	padding: var( --wwh-section-pad-y, clamp( 3rem, 6vw, 5rem ) ) var( --wwh-section-pad-x, 1rem );
}

.wwh-guide-index__grid {
	display: grid;
	/* 3 across on a desktop, 2 on a tablet, 1 on a phone — no breakpoints. */
	grid-template-columns: repeat( auto-fill, minmax( min( 100%, 20rem ), 1fr ) );
	gap: clamp( 1.5rem, 3vw, 2.5rem );
	margin: 0;
	padding: 0;
	list-style: none;
}

.wwh-guide-card {
	margin: 0;
}

/* The whole card is the link: one tab stop, one big target. */
.wwh-guide-card__link {
	display: flex;
	flex-direction: column;
	height: 100%;
	overflow: hidden;
	border-radius: 0.5rem;
	background: #fff;
	color: var( --wp--preset--color--ink-primary, #1A1613 );
	text-decoration: none;
	box-shadow: 0 1px 2px rgba( 24, 20, 15, 0.06 ), 0 4px 18px rgba( 24, 20, 15, 0.07 );
	transition: transform 180ms ease, box-shadow 180ms ease;
}

.wwh-guide-card__link:hover {
	transform: translateY( -3px );
	box-shadow: 0 2px 4px rgba( 24, 20, 15, 0.08 ), 0 12px 30px rgba( 24, 20, 15, 0.12 );
}

@media ( prefers-reduced-motion: reduce ) {
	.wwh-guide-card__link,
	.wwh-guide-card__link:hover {
		transition: none;
		transform: none;
	}
}

.wwh-guide-card__media {
	display: block;
	aspect-ratio: 16 / 10;
	overflow: hidden;
	background: var( --wp--preset--color--warm-cream-2, #E9E4DB );
	border-block-end: 1px solid rgba( 24, 20, 15, 0.08 );
}

/* Screenshots: keep the top of the frame, which is where the page title is. */
.wwh-guide-card__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: top center;
}

.wwh-guide-card__body {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 0.6rem;
	padding: 1.25rem 1.4rem 1.4rem;
}

.wwh-guide-card__title {
	margin: 0;
	font-family: var( --wp--preset--font-family--display ), 'DM Serif Display', serif;
	font-style: italic;
	font-weight: 400;
	font-size: clamp( 1.35rem, 2vw, 1.6rem );
	line-height: 1.15;
	color: inherit;
}

.wwh-guide-card__summary {
	display: block;
	font-family: var( --wp--preset--font-family--body ), 'EB Garamond', serif;
	font-size: 1.05rem;
	line-height: 1.5;
	color: var( --wp--preset--color--ink-caption, #5A544D );
}

.wwh-guide-card__meta,
.wwh-guide-card__cta {
	font-family: var( --wp--preset--font-family--ui ), 'Montserrat', sans-serif;
	font-size: 0.72rem;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

.wwh-guide-card__meta {
	display: block;
	color: var( --wp--preset--color--ink-caption, #5A544D );
}

/* brand-text on white is 5.2:1 — passes AA for this small text. */
.wwh-guide-card__video {
	color: var( --wp--preset--color--brand-text, #8F632F );
	font-weight: 600;
}

.wwh-guide-card__video::before {
	content: "\25B6\FE0E\00a0";
}

.wwh-guide-card__cta {
	margin-block-start: auto;
	padding-block-start: 0.75rem;
	border-block-start: 1px solid rgba( 24, 20, 15, 0.1 );
	font-weight: 600;
	color: var( --wp--preset--color--ink-primary, #1A1613 );
}

.wwh-guide-card__link:hover .wwh-guide-card__cta {
	text-decoration: underline;
	text-underline-offset: 3px;
}

@media print {
	.wwh-guide__controls,
	.wwh-guide__progress,
	.wwh-guide__viewtoggle { display: none; }

	/* Print every step, not just the one on screen. */
	.wwh-guide__viewport { overflow: visible; }
	.wwh-guide__track { display: block; transform: none; }
	.wwh-guide__slide { break-inside: avoid; }
}
