/*
 * wakefly/image-carousel — the one scoped stylesheet this block needs.
 *
 * Loaded through block.json's `style`/`editorStyle`, so it is enqueued only on a page that
 * renders the block and it is unaffected by the SCRIPT_DEBUG style.css/style.min.css split in
 * functions.php.
 *
 * EVERY NUMBER BELOW IS A MEASUREMENT FROM THE UNIT CONTRACT OR ARITHMETIC OVER TWO OF THEM.
 * Where a value is neither, it says so in its own comment — those are the lines a verdict
 * should look at first.
 */

/*
 * BORDER-BOX, SCOPED TO THIS BLOCK. Neither WordPress core nor this theme sets a global
 * box-sizing reset, and core's own `* { box-sizing: border-box }` ships inside the block
 * library stylesheet, which is only enqueued for blocks core knows are on the page — this
 * block's markup is written by hand, so none of it applies. Every width below is a border-box
 * width, which is what the contract measures.
 */
.wp-block-wakefly-image-carousel,
.wp-block-wakefly-image-carousel *,
.wp-block-wakefly-image-carousel *::before,
.wp-block-wakefly-image-carousel *::after {
	box-sizing: border-box;
}

.wp-block-wakefly-image-carousel {
	/*
	 * `spaceBetween: 0` FOR THIS CAROUSEL, and THIS IS THE ONLY PLACE THE NUMBER IS WRITTEN
	 * DOWN: assets/js/carousel-view.js and functions.php both build the track's transform as
	 * a calc() over this property rather than carrying a copy. The shared
	 * `defaultSwiperOptions.spaceBetween` is 20 and this unit's own initializeSwiper() call
	 * passes 0, which is the pair the 2026-09-06 incident got wrong on the hero.
	 */
	--wf-carousel-space-between: 0px;

	/* `speed: 500`, from the same options object. */
	--wf-carousel-speed: 500ms;

	/*
	 * THE ARROW LADDER, AND THE VIEWPORT MARGIN IS DERIVED FROM IT. Measured arrow boxes:
	 * 28x28 at 390, 32x32 at 768 and 1024, 36x36 at 1440. Measured .swiper side margins,
	 * as the difference between the inner box and the viewport box at each of the same four
	 * viewports: 342 - 270 = 72 (36 a side), 672 - 592 = 80 (40), 912 - 832 = 80 (40),
	 * 1272 - 1184 = 88 (44). So the margin is the arrow plus 8 at every measured width, and
	 * it is written that way rather than as a second ladder that could drift from the first.
	 *
	 * THE CONTRACT'S PROSE SAYS THE MARGIN IS "44px … identical at all four viewports" AND
	 * ITS OWN NUMBERS SAY OTHERWISE. The four box measurements above are from the same key
	 * and disagree with the sentence beside them; the numbers are what is built to, and the
	 * discrepancy is in the hand-back.
	 *
	 * THE TOP RUNG'S BREAKPOINT IS THE ONE UNMEASURED VALUE ON THIS UNIT. 1024 measures 32
	 * and 1440 measures 36, so the step is somewhere between; 1400px is Bootstrap's xxl and
	 * is the breakpoint this source's own stylesheets use for their only other responsive
	 * value (units.testimonial-carousel's p.name), so it is the grounded guess. 1200px would
	 * reproduce all four captured viewports equally well.
	 */
	--wf-carousel-arrow: 28px;

	/* The glyph is 28x28 inside a 36x36 button — measured at 1440, and the only viewport it
	   is measured at, so the other three scale on that one ratio rather than on invented
	   numbers. */
	--wf-carousel-arrow-glyph: calc(var(--wf-carousel-arrow) * 28 / 36);

	/* $image-component-width in the source's _image.scss. Measured 500px wide at all four
	   viewports, including 390, where 123px hangs off each side of a 270px slide and the
	   viewport clips it. That overflow is the source's and is reproduced, not corrected. */
	--wf-carousel-image-width: 500px;

	/* The arrows are absolutely positioned against this box: measured x=72 against a root at
	   x=72, and x=1332 against a root right edge of 1368. */
	position: relative;
}

@media (min-width: 768px) {

	.wp-block-wakefly-image-carousel {
		--wf-carousel-arrow: 32px;
	}
}

@media (min-width: 1400px) {

	.wp-block-wakefly-image-carousel {
		--wf-carousel-arrow: 36px;
	}
}

/* ------------------------------------------------------------------------------ the frame */

/*
 * Bootstrap's div.container. Measured exactly as wide as the root at all four viewports, so
 * its only job is the 12px inline gutter — 1296 - 12 - 12 = 1272, which is the measured inner
 * width.
 */
.wp-block-wakefly-image-carousel__container {
	padding-inline: 12px;
}

/*
 * div.page-component-intro. Measured 1272x24 at 1440x900: 16px/24px in the theme's own
 * `body-text`, no padding of its own, 16px below it. The colour and the size are the theme's
 * defaults and are not restated here — writing them would be two literals for values nothing
 * measured as an override.
 */
.wp-block-wakefly-image-carousel__intro {
	margin-block-end: var(--wp--preset--spacing--40);
}

.wp-block-wakefly-image-carousel__intro > :first-child {
	margin-block-start: 0;
}

.wp-block-wakefly-image-carousel__intro > :last-child {
	margin-block-end: 0;
}

/*
 * div.image-carousel-inner, which also carries the dead count class. Measured display block
 * with no padding, background or border of its own at every viewport — so it declares
 * nothing, and it exists as a node because it is where the count class lives.
 */

/*
 * div.swiper — the clipping viewport. Measured 1184x381 at x=128 in a 1440 window: the inner
 * box is 1272 and the side margins are the arrow ladder plus 8. `overflow: hidden` is the
 * whole of the 390x844 finding — the 500px image is wider than the 270px slide there, and the
 * source clips it rather than scaling it down.
 */
.wp-block-wakefly-image-carousel__viewport {
	position: relative;
	margin-inline: calc(var(--wf-carousel-arrow) + 8px);
	overflow: hidden;
}

/*
 * div.swiper-wrapper, the track. Measured display flex, position relative, and carrying
 * Swiper's own translate3d(0,0,0) at rest. `gap` is the resolved spaceBetween, which is 0.
 */
.wp-block-wakefly-image-carousel__track {
	display: flex;
	flex-direction: row;
	flex-wrap: nowrap;
	gap: var(--wf-carousel-space-between);
	transition: transform var(--wf-carousel-speed) ease;
	will-change: transform;
}

/*
 * WCAG 2.3.3 (AAA, so not required) costs three lines here and leaves the carousel fully
 * working — the arrows still change which slide shows, and only the sweep is taken away.
 */
@media (prefers-reduced-motion: reduce) {

	.wp-block-wakefly-image-carousel__track {
		transition: none;
	}
}

/*
 * ONE SLIDE, EXACTLY AS WIDE AS THE VIEWPORT at every measured width (1184 / 832 / 592 / 270),
 * which is why only one is ever visible whatever the count class says. `justify-content:
 * center` is the measured value and the computed string is literally `center`, so no mapping
 * from core's layout vocabulary was needed.
 *
 * `visibility` IS THE MEASURED REST STATE, not a convenience: the source paints
 * swiper-slide-visible on the active slide only and the other two measure visibility hidden.
 * It also takes the clipped slides' buttons out of the tab order for free.
 */
.wp-block-wakefly-image-carousel__slide {
	flex: 0 0 100%;
	/*
	 * `min-width: 0` IS LOAD-BEARING AND IT IS 123px, MEASURED. A flex item's min-width
	 * defaults to `auto`, which is its MIN-CONTENT size — and this slide's min-content is its
	 * non-shrinking item, 516px wide. So at 390x844 the slide grew from the 270 that
	 * `flex: 0 0 100%` asks for to 516, the media landed at x=68 instead of the contract's
	 * x=-55, AND every step of the track's -100% transform would have been 516 rather than one
	 * viewport. Verified in isolation before it was written: the same three rules with and
	 * without this line put the item at -15 and at +108 inside a 270px box.
	 */
	min-width: 0;

	display: flex;
	flex-direction: row;
	justify-content: center;
	visibility: hidden;
}

.wp-block-wakefly-image-carousel__slide.is-current {
	visibility: visible;
}

/* ----------------------------------------------------------------------- the slide's media */

/*
 * THE UA BUTTON BOX, DECLARED RATHER THAN INHERITED, AND IT IS A SOURCE DEFECT REPRODUCED ON
 * PURPOSE.
 *
 * chrome.slide-button-frame measures button.image-carousel-modal-button at 516x381 with
 * background rgb(239,239,239), a 2px rgb(0,0,0) border, 1px/6px padding and centred text —
 * every one of which is Chromium's UA stylesheet for a bare <button>, because no rule in the
 * source's own CSS touches that class. The arithmetic closes exactly: 500 + 6 + 6 + 2 + 2 =
 * 516 and 375 + 1 + 1 + 2 + 2 = 381. It is legible in the reference as a thin dark rule
 * around every slide with a hairline gutter inside it.
 *
 * IT IS DECLARED HERE RATHER THAN LEFT TO THE BROWSER because "the UA default" is not a
 * stable value — a theme reset, a core block stylesheet or a future Chromium would move it,
 * and then the unit would drift with no edit to blame. Writing the four measurements down
 * makes the reproduction deliberate and reviewable.
 *
 * THE STYLE IS `outset`, NOT `solid`, AND THAT IS THE WHOLE OF THE FRAME'S PAINT. The
 * contract's `computed` block records borderWidth and borderColor and NOT border-style, so
 * this rule was written `2px solid #000` and painted a flat black rectangle where the source
 * paints a bevel. MEASURED 2026-09-10 with tooling/extract/probe.js --html against a page
 * carrying three buttons: (a) a button with nothing on it but Bootstrap Reboot's own
 * `button { border-radius: 0 }`, which is the source's exact condition — no rule touches
 * .image-carousel-modal-button, but Reboot touches the tag, and an author border-radius is
 * what makes Blink drop the native widget paint and honour the UA's own `border-style:
 * outset`; (b) this rule with `outset`; (c) this rule with `solid`. Border pixels, top /
 * bottom / left / right:
 *
 *   Reboot-only   rgb(168,168,168) / rgb(84,84,84) / rgb(168,168,168) / rgb(84,84,84)
 *   `outset`      rgb(168,168,168) / rgb(84,84,84) / rgb(168,168,168) / rgb(84,84,84)
 *   `solid`       rgb(0,0,0)       / rgb(0,0,0)    / rgb(0,0,0)       / rgb(0,0,0)
 *
 * The same probe reports the UA button's own computed values as border-style outset,
 * border-color rgb(0,0,0), border-width 2px, background rgb(239,239,239), color rgb(0,0,0),
 * padding 1px 6px — every one of them the contract's measured figure, which is what says the
 * four declarations below are the source's box and not an approximation of it.
 *
 * WHETHER TO REPRODUCE IT AT ALL is a fidelity-versus-correction decision with a client
 * conversation behind it, and it is the operator's rather than this package's (CLAUDE.md
 * §Standards). This build reproduces, because that is what a replatform's build owes; the
 * question is raised in the hand-back.
 */
.wp-block-wakefly-image-carousel__frame {
	display: inline-block;
	/*
	 * NO SHRINKING, AND IT IS 123px OF MEASUREMENT. A flex item defaults to `flex-shrink: 1`,
	 * so inside the 270px slide at 390x844 this box would collapse from its natural width to
	 * 270 and the 500px image inside would overflow IT rather than the slide. Measured with
	 * the default: the media box landed at x=68 instead of the contract's x=-55.
	 *
	 * The contract's number is what says the source does not shrink: 500x375 at x=-55 in a
	 * 270px slide is exactly 123px hanging off each side of a centred full-width item, and
	 * .swiper's own overflow is what clips it. That overflow is a source defect and it is
	 * reproduced rather than corrected, so the item has to keep its width for there to be
	 * anything to clip.
	 */
	flex-shrink: 0;

	padding: 1px 6px;
	border: 2px outset #000;
	border-radius: 0;
	background-color: #efefef;
	color: #000;
	font: inherit;
	text-align: center;
	cursor: pointer;
}

/*
 * div.image-inner — the positioning context the caption bar is absolute against. Measured
 * 500x375 at 1440, 1024 and 768, AND 500x375 at 390 too, at x=-55 inside a 270px slide. The
 * width is the source's $image-component-width and does not clamp; the height is the image's
 * own, because this widget emits a bare .image-inner with no `ratio ratio-Nx N` class.
 */
.wp-block-wakefly-image-carousel__media {
	position: relative;
	display: block;
	width: var(--wf-carousel-image-width);
}

/*
 * Measured 500x375 against a 400x300 source asset — a scale-UP that crops nothing here, with
 * objectFit cover from the source's `.image-inner img { object-fit: cover }`. The height stays
 * the image's own (`height: auto`), which is what the contract's core/image node records by
 * deliberately writing no aspectRatio; `object-fit` is declared because it is the measured
 * computed value and because it is what would crop a set with mixed aspect ratios.
 */
.wp-block-wakefly-image-carousel__image {
	display: block;
	width: 100%;
	height: auto;
	object-fit: cover;
}

/*
 * The caption bar. Measured at 1440x900: 500x62 at the media box's bottom edge, position
 * absolute, background rgba(33,37,41,0.6), colour rgb(255,255,255), 16px padding on all four
 * sides (derived from the four offsets, not read from a declaration), and a 468x30 title at
 * 20px/30px weight 700. 16 + 30 + 16 = 62 closes the bar.
 *
 * THE BACKGROUND IS A RAW rgba() AND NOT A SLUG, KNOWINGLY: it is this theme's `dark`
 * (#212529) at 60% alpha, and theme.json's palette carries no translucent entry, so
 * `--wp--preset--color--dark` cannot express it. A slug would paint an opaque bar over the
 * image. The white and the 20px ARE presets, because those two exist.
 */
.wp-block-wakefly-image-carousel__caption {
	position: absolute;
	inset-inline: 0;
	inset-block-end: 0;
	display: block;
	padding: var(--wp--preset--spacing--40);
	background-color: rgba(33, 37, 41, 0.6);
	color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 700;
	line-height: 1.5;
	text-align: start;
}

/* ----------------------------------------------------------------------------- the arrows */

/*
 * Measured: a solid circle in this theme's `secondary` slug with a white glyph, absolutely
 * positioned against the block root — x=72 where the root's own left edge is x=72, and
 * x=1332 against a root right edge of 1368, i.e. flush to both. `margin-top: -22px` is
 * measured and is Swiper's own half of its 44px `--swiper-navigation-size`, which is why it
 * does NOT track the button's size.
 *
 * `font: inherit` is a measurement rather than a reset habit: Chromium's UA stylesheet sets
 * `font: 400 13.3333px Arial` on a <button>, so a control with nothing declared renders in a
 * font nobody chose. Nothing here renders text, so it changes what the box inherits and not
 * what it measures.
 */
.wp-block-wakefly-image-carousel__arrow {
	position: absolute;
	inset-block-start: 50%;
	margin-block-start: -22px;
	display: flex;
	align-items: center;
	justify-content: center;
	width: var(--wf-carousel-arrow);
	height: var(--wf-carousel-arrow);
	padding: 0;
	border: 0;
	border-radius: 50%;
	background-color: var(--wp--preset--color--secondary);
	color: var(--wp--preset--color--white);
	font: inherit;
	cursor: pointer;
	z-index: 1;
}

.wp-block-wakefly-image-carousel__arrow.is-previous {
	inset-inline-start: 0;
}

.wp-block-wakefly-image-carousel__arrow.is-next {
	inset-inline-end: 0;
}

.wp-block-wakefly-image-carousel__arrow-glyph {
	display: block;
	width: var(--wf-carousel-arrow-glyph);
	height: var(--wf-carousel-arrow-glyph);
}
