/**
 * Zellhoff Interactive Product — front end.
 *
 * Three layouts, each a different answer to "where does the text go":
 *
 *   >= 1024px   graphic centered between two reserved gutters; a panel opens on
 *               the side its hotspot sits on, so the connector never crosses
 *               the product.
 *   601-1023px  graphic left, every panel right. Two gutters would squeeze the
 *               graphic to nothing at this width.
 *   <= 600px    the panel is a modal over the page. Side-by-side leaves neither
 *               column readable.
 *
 * The JavaScript measures the panel's real position rather than reading these
 * breakpoints, so the connector follows whichever layout is in force.
 */

.zellhoff-product {
	--zellhoff-panel-width: 20rem;
	--zellhoff-gap: 2.5rem;
	--zellhoff-accent: #89cbc0;
	--zellhoff-dot-size: 14px;
	--zellhoff-hit-size: 44px;
	--zellhoff-line-width: 3px;
	--zellhoff-ring-gap: 5px;
	--zellhoff-ring-width: 2px;
	--zellhoff-dot-color: #fff;

	/* Two columns by default — the tablet range. Wider screens override. */
	display: grid;
	grid-template-columns: minmax(0, 1fr) min(var(--zellhoff-panel-width), 38vw);
	column-gap: min(var(--zellhoff-gap), 4vw);
	align-items: start;
}

.zellhoff-product__figure {
	position: relative;
	grid-column: 1;
}

/* The image sizes the positioning context, so percentage coordinates always
   resolve against the graphic itself and never against a wider wrapper. */
.zellhoff-product__image {
	display: block;
	width: 100%;
	height: auto;
}

.zellhoff-sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* --- Hotspots ---------------------------------------------------------- */

/*
 * The button is a finger-sized transparent target; the dot people actually see
 * is the span inside it. Separating the two lets the hit area be comfortable
 * without the dot growing to match.
 *
 * A side effect worth knowing: at the default 44px, two hotspots placed closer
 * than that on the graphic will have overlapping targets, and the later one in
 * the markup wins the tap.
 */
.zellhoff-hotspot {
	position: absolute;
	display: flex;
	align-items: center;
	justify-content: center;
	width: var(--zellhoff-hit-size);
	height: var(--zellhoff-hit-size);
	/* Centers the target on its coordinate. */
	margin: calc(var(--zellhoff-hit-size) / -2) 0 0 calc(var(--zellhoff-hit-size) / -2);
	padding: 0;
	appearance: none;
	border: 0;
	border-radius: 50%;
	line-height: 0;
	cursor: pointer;
}

/*
 * Held against the theme.
 *
 * Kadence ships `button:hover`, `button:focus` and `button:active` in
 * global.min.css, each setting background, color and a large drop shadow at
 * specificity (0,1,1) — enough to beat a lone class. Unchecked, a tapped
 * hotspot became a 44px theme-coloured disc. Scoping through .zellhoff-product
 * lifts these above it; every interactive state has to be named, because
 * styling only the base selector leaves :focus and :active to the theme.
 */
.zellhoff-product .zellhoff-hotspot,
.zellhoff-product .zellhoff-hotspot:hover,
.zellhoff-product .zellhoff-hotspot:focus,
.zellhoff-product .zellhoff-hotspot:active {
	background: transparent;
	box-shadow: none;
	color: inherit;
}

.zellhoff-hotspot__dot {
	position: relative;
	display: block;
	width: var(--zellhoff-dot-size);
	height: var(--zellhoff-dot-size);
	border-radius: 50%;
	background: var(--zellhoff-dot-color);
	box-shadow: 0 1px 4px rgb(0 0 0 / 35%);
	transition: transform 0.15s ease, background-color 0.2s ease;
}

.zellhoff-hotspot:hover .zellhoff-hotspot__dot,
.zellhoff-hotspot:focus-visible .zellhoff-hotspot__dot {
	transform: scale(1.3);
}

/* On the dot, not on the 44px target, which would ring empty space. */
.zellhoff-hotspot:focus-visible .zellhoff-hotspot__dot {
	outline: 2px solid currentColor;
	outline-offset: 4px;
}

.zellhoff-hotspot[aria-expanded="true"] .zellhoff-hotspot__dot {
	background: var(--zellhoff-accent);
	transform: scale(1.3);
}

/*
 * Two rings on the dot's pseudo-elements, so neither disturbs the dot itself:
 *
 *   ::after   a standing ring — the decoration that marks it as something to
 *             press, present whether or not it is mid-animation
 *   ::before  the pulse, which expands and fades out of that ring
 */
.zellhoff-hotspot__dot::after {
	content: "";
	position: absolute;
	inset: calc(-1 * var(--zellhoff-ring-gap));
	border: var(--zellhoff-ring-width) solid var(--zellhoff-accent);
	border-radius: 50%;
	opacity: 0.55;
	transition: opacity 0.2s ease;
	pointer-events: none;
}

.zellhoff-hotspot:hover .zellhoff-hotspot__dot::after,
.zellhoff-hotspot:focus-visible .zellhoff-hotspot__dot::after,
.zellhoff-hotspot[aria-expanded="true"] .zellhoff-hotspot__dot::after {
	opacity: 1;
}

.zellhoff-hotspot__dot::before {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: 50%;
	pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
	.zellhoff-hotspot__dot::before {
		animation: zellhoff-pulse 2.6s ease-out infinite;
	}
}

/*
 * Fades the pseudo-element rather than the shadow color's alpha, so the pulse
 * follows --zellhoff-accent instead of a hard-coded value.
 */
@keyframes zellhoff-pulse {
	0% {
		box-shadow: 0 0 0 0 var(--zellhoff-accent);
		opacity: 0.5;
	}

	70% {
		box-shadow: 0 0 0 16px var(--zellhoff-accent);
		opacity: 0;
	}

	100% {
		box-shadow: 0 0 0 0 var(--zellhoff-accent);
		opacity: 0;
	}
}

/* --- Panels ------------------------------------------------------------ */

.zellhoff-panel {
	position: absolute;
	left: calc(100% + min(var(--zellhoff-gap), 4vw));
	width: min(var(--zellhoff-panel-width), 38vw);
	opacity: 0;
	visibility: hidden;
	/*
	 * visibility is stepped, not faded: instantly on open, delayed by the fade
	 * on close.
	 *
	 * Transitioning it over a duration leaves the computed value `hidden` at the
	 * moment the class lands, and an element that is still hidden refuses
	 * focus() — so the modal opened without moving focus into it, and no amount
	 * of forcing a reflow helped, because the value only advances with the
	 * transition. Delaying it on the way out keeps the panel on screen for the
	 * whole fade rather than blinking away.
	 */
	transition: opacity 0.25s ease, visibility 0s linear 0.25s;
}

.zellhoff-panel.is-open {
	opacity: 1;
	visibility: visible;
	transition: opacity 0.25s ease, visibility 0s linear 0s;
}

/*
 * Body size, bold. The heading level stays h3 because the panel is labelled by
 * it, and only the appearance was ever meant to be a heading's.
 *
 * Prefixed with .zellhoff-product for the same reason the hotspot rules are:
 * the theme styles headings at a specificity a lone class does not beat, so
 * font-size would keep coming from Kadence's h3 rule.
 */
.zellhoff-product .zellhoff-panel__title {
	margin: 0 0 0.6em;
	font-size: inherit;
	font-weight: 700;
	line-height: 1.25;
}

/*
 * The connector continues through the panel as the rule between title and
 * description. Same token as the connector's height, and the JavaScript offsets
 * the panel so this border lands exactly on the hotspot's center line — the two
 * read as one unbroken line.
 */
.zellhoff-panel__body {
	border-top: var(--zellhoff-line-width) solid var(--zellhoff-accent);
	padding-top: 1.1em;
}

.zellhoff-panel__body > :first-child {
	margin-top: 0;
}

.zellhoff-panel__body > :last-child {
	margin-bottom: 0;
}

/* Only ever shown in the modal layout. */
.zellhoff-panel__close {
	display: none;
	position: absolute;
	top: 0.5rem;
	right: 0.5rem;
	width: 2.25rem;
	height: 2.25rem;
	padding: 0;
	align-items: center;
	justify-content: center;
	appearance: none;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: inherit;
	cursor: pointer;
}

.zellhoff-product .zellhoff-panel__close,
.zellhoff-product .zellhoff-panel__close:hover,
.zellhoff-product .zellhoff-panel__close:focus,
.zellhoff-product .zellhoff-panel__close:active {
	background: transparent;
	box-shadow: none;
	color: inherit;
}

.zellhoff-product .zellhoff-panel__close:hover,
.zellhoff-product .zellhoff-panel__close:focus-visible {
	background: rgb(0 0 0 / 8%);
}

.zellhoff-panel__close svg {
	width: 1.1rem;
	height: 1.1rem;
	fill: none;
	stroke: currentColor;
	stroke-width: 2;
	stroke-linecap: round;
}

/* --- Connector --------------------------------------------------------- */

.zellhoff-connector {
	position: absolute;
	display: block;
	/*
	 * Drawn as a border, not as a background on a 3px-tall box — because the
	 * other half of this line is the panel's border-top, and browsers snap
	 * border widths to whole device pixels while leaving a background box
	 * unsnapped. On a display with a fractional devicePixelRatio (1.15625 here)
	 * a declared 3px border paints 3 device pixels crisply and reports back as
	 * 2.59px, while a 3px-tall background paints 3.47 device pixels and
	 * antialiases — visibly thicker and softer than the half beside it.
	 * Matching the mechanism is what makes the two halves identical; matching
	 * the declared width is not enough.
	 *
	 * No centering transform either: translateY(-50%) on an odd height always
	 * lands the line on a half pixel. The JS sets `top` to the line's top edge.
	 */
	height: 0;
	border-top: var(--zellhoff-line-width) solid var(--zellhoff-accent);
	opacity: 0;
	transition: opacity 0.25s ease;
	pointer-events: none;
}

.zellhoff-connector.is-open {
	opacity: 1;
}

/* --- Backdrop ---------------------------------------------------------- */

/* Exists only in the modal layout. */
.zellhoff-product__backdrop {
	display: none;
}

/* --- Wide: graphic centered, panel on its hotspot's side ---------------- */

@media (min-width: 1024px) {
	.zellhoff-product {
		grid-template-columns: var(--zellhoff-panel-width) minmax(0, 1fr) var(--zellhoff-panel-width);
		column-gap: var(--zellhoff-gap);
	}

	.zellhoff-product__figure {
		grid-column: 2;
	}

	.zellhoff-panel {
		width: var(--zellhoff-panel-width);
	}

	.zellhoff-panel--left {
		right: calc(100% + var(--zellhoff-gap));
		left: auto;
	}

	.zellhoff-panel--right {
		left: calc(100% + var(--zellhoff-gap));
		right: auto;
	}
}

/* --- Narrow: the panel becomes a modal --------------------------------- */

@media (max-width: 600px) {
	.zellhoff-product {
		grid-template-columns: minmax(0, 1fr);
	}

	.zellhoff-connector {
		display: none;
	}

	.zellhoff-product__backdrop {
		display: block;
		position: fixed;
		inset: 0;
		z-index: 9998;
		background: rgb(0 0 0 / 55%);
		opacity: 0;
		visibility: hidden;
		transition: opacity 0.2s ease, visibility 0.2s;
	}

	.zellhoff-product.is-open .zellhoff-product__backdrop {
		opacity: 1;
		visibility: visible;
	}

	.zellhoff-panel {
		position: fixed;
		/* The anchored layouts set an inline `top`; JS clears it here. */
		top: 50%;
		left: 50%;
		right: auto;
		z-index: 9999;
		box-sizing: border-box;
		width: min(92vw, 28rem);
		max-height: 82vh;
		padding: 2.75rem 1.25rem 1.5rem;
		overflow-y: auto;
		background: #fff;
		box-shadow: 0 10px 40px rgb(0 0 0 / 30%);
		transform: translate(-50%, -46%);
		transition: opacity 0.2s ease, transform 0.2s ease, visibility 0s linear 0.2s;
	}

	.zellhoff-panel.is-open {
		transform: translate(-50%, -50%);
		transition: opacity 0.2s ease, transform 0.2s ease, visibility 0s linear 0s;
	}

	.zellhoff-panel__close {
		display: flex;
	}
}

/*
 * Holds the page still behind an open modal.
 *
 * The JavaScript adds padding matching the scrollbar's width, so removing the
 * scrollbar here does not let the layout reflow into the space it occupied.
 */
body.zellhoff-modal-open {
	overflow: hidden;
}

.zellhoff-product__notice {
	padding: 0.75em 1em;
	border-left: 3px solid #d63638;
	background: #fcf0f1;
	color: #1d2327;
}
