/* ======================================================================
   Brand hero

   The greenhouse photograph plus the interactions layered over it. Loaded on
   the front page only.

   Two rules govern everything here:

     1. The photograph is never touched. No filter, no transform, no overlay
        tints the picture as a whole. Every effect is confined to a region
        placed over it, and the picture underneath is the file as supplied.

     2. Only `transform` and `opacity` are animated. Glow is a pseudo-element
        that fades, not a box-shadow that grows; lift is a translate, not a
        margin. Nothing here can reflow the page mid-hover.
   ====================================================================== */

.p-hero {
	--p-hero-panel-top: #062118;
	--p-hero-panel-mid: #033124;
	--p-hero-panel-foot: #053026;

	/* Sampled from the artwork's own accent, not the theme's darker greens. */
	--p-hero-accent: #a8d886;
	--p-hero-accent-soft: rgba(168, 216, 134, 0.42);

	/* 3000K warm white. Never green — this is a lamp, not foliage. */
	--p-hero-led: 255, 180, 107;

	/* Where the live panel gives way to the photograph. JS replaces this with
	   the artwork's own seam, measured against the rendered crop; the fallback
	   matches it at a typical desktop width if the script never runs. */
	--p-hero-seam: 40%;

	/* One easing and one duration for every interaction in the hero, so no two
	   effects can disagree about how the page feels. */
	--p-hero-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
	--p-hero-dur: 250ms;
	--p-hero-delay: 80ms;

	position: relative;
	isolation: isolate;

	/*
	 * Exactly one screen, not "at least" one.
	 *
	 * `min-height` let the panel's own content decide the height, and on a 16:9
	 * laptop that content is taller than the window — the hero came out at
	 * 1196px in a 900px viewport, so scrolling revealed a second screenful of
	 * hero before the page beneath it. Everything inside is sized against
	 * viewport height as well as width (see below), so it fits this box rather
	 * than being cut off by it.
	 *
	 * `svh` rather than `vh`: on a phone `vh` is the height with the browser
	 * chrome retracted, which is taller than what you can actually see when the
	 * page loads.
	 */
	height: 100svh;
	min-height: 32rem;
	overflow: hidden;
	background: var(--p-hero-panel-mid);
}

/* ---- The photograph ---------------------------------------------------- */

.p-hero__media {
	position: absolute;
	inset: 0;
	z-index: 0;
}

/*
 * Anchored right. A narrow viewport therefore crops from the left — off the
 * baked panel, which the live panel is covering anyway — and the wooden sign,
 * which sits 4% from the right edge, is never cropped away from its hotspot.
 */
.p-hero__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: right center;
}

/* ---- The live panel ---------------------------------------------------- */

/*
 * Opaque where the baked text is, feathered where it meets the photograph. The
 * feather lands inside the baked panel, so the join is one dark green meeting
 * the same dark green.
 */
/*
 * Pinned to the hero, not sized by what is inside it.
 *
 * As a block in flow the panel was only ever as tall as its own text, so the
 * photograph's baked wordmark showed above it and the baked feature row below
 * it — the live panel read as a rectangle floating on the picture. Anchoring it
 * to all four edges of the hero means it covers the artwork's own left column
 * completely, at every viewport size, whatever the content does.
 *
 * It also decouples the hero's height from the panel's content, which is what
 * keeps the section to exactly one screen.
 */
.p-hero__panel {
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	z-index: 1;

	/*
	 * The panel is the column plus a fade, and the fade lives outside the
	 * column rather than on top of it.
	 *
	 * Before this the feather started at 88% of the panel's own width, but the
	 * text column runs to about 94% of it — so the last inch of every line sat
	 * on a background that was busy dissolving into the photograph, and the
	 * whole overlay read as a pasted rectangle. Now the panel is `seam +
	 * feather` wide, `padding-right` keeps the content inside the opaque part,
	 * and the fade has a full 6vw of its own to disappear across.
	 */
	--p-hero-feather: 8vw;

	width: calc(var(--p-hero-seam) + var(--p-hero-feather));
	padding-right: var(--p-hero-feather);
	display: flex;
	align-items: center;
	background:
		linear-gradient(
			to right,
			var(--p-hero-panel-mid) 0%,
			var(--p-hero-panel-mid) calc(100% - var(--p-hero-feather)),
			rgba(3, 49, 36, 0.55) calc(100% - var(--p-hero-feather) * 0.45),
			rgba(3, 49, 36, 0) 100%
		),
		linear-gradient(
			to bottom,
			var(--p-hero-panel-top) 0%,
			var(--p-hero-panel-mid) 34%,
			var(--p-hero-panel-mid) 76%,
			var(--p-hero-panel-foot) 100%
		);
}

/*
 * The column has to hold the artwork's whole left panel inside one viewport
 * height, on a screen far wider and shorter than the 4:3 picture. Padding and
 * type are therefore tied to viewport height as well as width — the block
 * breathes on a tall window and tightens on a laptop, rather than growing past
 * the fold and forcing the photograph to crop into the middle of the walkway.
 */
.p-hero__panelinner {
	width: 100%;
	max-width: 33rem;
	margin-left: auto;
	margin-right: auto;
	padding: clamp(var(--p-space-6), 6vh, var(--p-space-8)) var(--p-space-6);
	color: var(--p-white);
}

/* ---- Wordmark ---------------------------------------------------------- */

/*
 * Every size below is `min(vw, vh)` inside its clamp.
 *
 * Width alone is the wrong input for a hero that has to fit a screen: a 1440
 * viewport is 1440 wide whether the window is 900 tall or 620, and type chosen
 * from `vw` alone overflows the short one. Taking the smaller of the two means
 * the column answers to whichever dimension is actually scarce, and the whole
 * panel shrinks together rather than one element at a time.
 */
.p-hero__wordmark {
	margin: 0 0 clamp(var(--p-space-2), 1.6vh, var(--p-space-4));
	line-height: 1.1;
}

.p-hero__wordmarkname {
	display: block;
	font-size: clamp(1.8rem, min(5vw, 6vh), 3.6rem);
	font-weight: 300;
	letter-spacing: 0.22em;
	color: var(--p-white);
}

.p-hero__wordmarksub {
	display: block;
	margin-top: 0.35em;
	font-size: clamp(0.8rem, min(1.6vw, 1.9vh), 1.3rem);
	font-weight: 400;
	letter-spacing: 0.22em;
	color: var(--p-hero-accent);
}

.p-hero__rule {
	display: block;
	width: 5.5rem;
	height: 1px;
	margin: clamp(var(--p-space-3), 2.2vh, var(--p-space-5)) 0;
	background: rgba(168, 216, 134, 0.45);
}

/* ---- Headline ---------------------------------------------------------- */

/*
 * `min()` against the column's own width, not just the viewport's: the panel is
 * about 34% of a wide screen, so a size chosen from `vw` alone sets a headline
 * far too big for the box it lives in and "GARDENING ESSENTIALS" wraps into a
 * paragraph. `cqw` would be the right unit; this avoids making the panel a
 * container purely to size one heading.
 */
.p-hero__title {
	margin: 0;
	font-size: clamp(1rem, min(2.1vw, 3.3vh), 1.72rem);
	font-weight: 400;
	line-height: 1.44;
	letter-spacing: 0.015em;
	color: var(--p-white);

	/*
	 * The heading declares its own box, and deliberately.
	 *
	 * Balanced wrapping was tried here and removed: the keywords are
	 * inline-blocks so that they can be transformed, and balancing sizes the
	 * heading to its widest shrink-to-fit child — it took the h1 down to 184px
	 * and broke every keyword across two lines, nine lines in all, which pushed
	 * the hero half a viewport past the fold. The line breaks are authored, so
	 * there is nothing for it to balance anyway.
	 *
	 * These two declarations make that outcome impossible to reintroduce from
	 * anywhere else: whatever a global heading rule does, this heading is the
	 * width of its column and wraps on the breaks it was given.
	 */
	width: 100%;
	max-width: none;
}

.p-hero__lede {
	margin: clamp(var(--p-space-2), 1.6vh, var(--p-space-4)) 0 0;
	font-size: clamp(0.78rem, min(1.15vw, 1.7vh), 1.02rem);
	font-weight: 400;
	line-height: 1.66;
	color: rgba(255, 255, 255, 0.94);
}

.p-hero__accent {
	color: var(--p-hero-accent);
}

/* ---- Words that are links ---------------------------------------------- */

/*
 * A keyword behaves like a navigation item: it lifts slightly toward the
 * cursor, warms to the accent, and draws its own underline from the left.
 *
 * `inline-block` is what makes it transformable at all — an inline box ignores
 * `transform`. The delay is on the way in only, so the effect never feels
 * twitchy on a pointer crossing the headline, but leaves the instant you go.
 */
.p-hero__word {
	position: relative;
	display: inline-block;
	color: inherit;
	text-decoration: none;
	cursor: pointer;
	transform: translate3d(var(--p-word-x, 0), var(--p-word-y, 0), 0) scale(var(--p-word-s, 1));
	transform-origin: left center;
	will-change: transform;
	transition:
		transform var(--p-hero-dur) var(--p-hero-ease) var(--p-hero-delay),
		color var(--p-hero-dur) var(--p-hero-ease) var(--p-hero-delay),
		text-shadow var(--p-hero-dur) var(--p-hero-ease) var(--p-hero-delay);
}

.p-hero__word--accent {
	color: var(--p-hero-accent);
}

/* The underline. A pseudo-element scaled on the X axis, so it costs a
   composite and never a layout. */
.p-hero__word::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: -0.14em;
	height: 1px;
	background: currentColor;
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform var(--p-hero-dur) var(--p-hero-ease) var(--p-hero-delay);
}

.p-hero__word:hover,
.p-hero__word:focus-visible {
	color: var(--p-hero-accent);
	text-shadow: 0 0 18px var(--p-hero-accent-soft);
	--p-word-s: 1.06;
}

.p-hero__word:hover::after,
.p-hero__word:focus-visible::after {
	transform: scaleX(1);
}

/* Leaving is immediate — the delay belongs to arriving. */
.p-hero__word:not(:hover):not(:focus-visible),
.p-hero__word:not(:hover):not(:focus-visible)::after {
	transition-delay: 0ms;
}

.p-hero__word--sm:hover,
.p-hero__word--sm:focus-visible {
	--p-word-s: 1.04;
}

.p-hero__word:focus-visible {
	outline: 1px solid var(--p-hero-accent);
	outline-offset: 0.3em;
}

/* ---- Feature row -------------------------------------------------------- */

.p-hero__features {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 0;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* The hairline dividers from the artwork. On the item, not the link, so the
   card can lift without dragging the rule with it. */
.p-hero__feature + .p-hero__feature {
	border-left: 1px solid rgba(168, 216, 134, 0.28);
}

.p-hero__featurelink {
	position: relative;
	display: grid;
	justify-items: center;
	gap: clamp(var(--p-space-1), 1vh, var(--p-space-2));
	padding: clamp(var(--p-space-2), 1.5vh, var(--p-space-3)) var(--p-space-2);
	color: var(--p-white);
	text-decoration: none;
	text-align: center;
	cursor: pointer;
	border-radius: var(--p-radius-sm);
	transform: translate3d(0, var(--p-feat-y, 0), 0) scale(var(--p-feat-s, 1));
	will-change: transform;
	transition:
		transform var(--p-hero-dur) var(--p-hero-ease) var(--p-hero-delay),
		color var(--p-hero-dur) var(--p-hero-ease) var(--p-hero-delay),
		text-shadow var(--p-hero-dur) var(--p-hero-ease) var(--p-hero-delay);
}

/* The tint and the glass, as a pseudo-element that fades. Animating the
   element's own background would repaint the text with it. */
.p-hero__featurelink::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	border-radius: inherit;
	background: rgba(168, 216, 134, 0.12);
	backdrop-filter: blur(6px) saturate(1.15);
	-webkit-backdrop-filter: blur(6px) saturate(1.15);
	opacity: 0;
	transition: opacity var(--p-hero-dur) var(--p-hero-ease) var(--p-hero-delay);
}

.p-hero__featureicon svg {
	display: block;
	width: clamp(20px, min(2.1vw, 3.1vh), 30px);
	height: clamp(20px, min(2.1vw, 3.1vh), 30px);
	stroke: var(--p-hero-accent);
	fill: none;
	stroke-width: 1.4;
	transition: stroke var(--p-hero-dur) var(--p-hero-ease) var(--p-hero-delay);
}

.p-hero__featurelabel {
	display: grid;
	gap: 0.15em;
	font-size: clamp(0.56rem, min(0.85vw, 1.25vh), 0.72rem);
	font-weight: 500;
	letter-spacing: 0.11em;
	line-height: 1.3;
}

.p-hero__featurelink:hover,
.p-hero__featurelink:focus-visible {
	--p-feat-s: 1.04;
	--p-feat-y: -3px;
	text-shadow: 0 0 16px var(--p-hero-accent-soft);
}

.p-hero__featurelink:hover::before,
.p-hero__featurelink:focus-visible::before {
	opacity: 1;
}

.p-hero__featurelink:hover .p-hero__featureicon svg,
.p-hero__featurelink:focus-visible .p-hero__featureicon svg {
	stroke: #c6f29d;
}

.p-hero__featurelink:focus-visible {
	outline: 1px solid var(--p-hero-accent);
	outline-offset: 2px;
}

/* ---- Closing line ------------------------------------------------------- */

.p-hero__closing {
	margin: clamp(var(--p-space-3), 2.4vh, var(--p-space-6)) 0 0;
	font-size: clamp(0.82rem, min(1.5vw, 2vh), 1.25rem);
	font-weight: 400;
	letter-spacing: 0.15em;
	line-height: 1.65;
}

/* ---- Explore collection ------------------------------------------------- */

.p-hero__cta {
	position: relative;
	display: inline-block;
	margin-top: clamp(var(--p-space-3), 2.4vh, var(--p-space-6));
	padding: 0.9em 2.1em;
	border: 1px solid rgba(168, 216, 134, 0.55);
	border-radius: var(--p-radius-pill);
	color: var(--p-white);
	font-size: clamp(0.72rem, 1vw, 0.82rem);
	font-weight: 500;
	letter-spacing: 0.18em;
	text-decoration: none;
	cursor: pointer;
	transform: translate3d(0, var(--p-cta-y, 0), 0) scale(var(--p-cta-s, 1));
	will-change: transform;
	transition:
		transform 300ms var(--p-hero-ease) var(--p-hero-delay),
		border-color 300ms var(--p-hero-ease) var(--p-hero-delay);
}

/*
 * The halo. A blurred pseudo-element that fades up, rather than a box-shadow
 * that animates its spread — a growing shadow repaints the area under the
 * button on every frame, and this does not.
 */
.p-hero__cta::before {
	content: "";
	position: absolute;
	inset: -14px;
	z-index: -1;
	border-radius: inherit;
	background: radial-gradient(
		60% 60% at 50% 50%,
		rgba(168, 216, 134, 0.34) 0%,
		rgba(168, 216, 134, 0.14) 45%,
		rgba(168, 216, 134, 0) 72%
	);
	opacity: 0;
	transition: opacity 300ms var(--p-hero-ease) var(--p-hero-delay);
}

/* The seated shadow, deepening as the button lifts. */
.p-hero__cta::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	border-radius: inherit;
	box-shadow: 0 14px 30px rgba(3, 26, 18, 0.55);
	opacity: 0;
	transition: opacity 300ms var(--p-hero-ease) var(--p-hero-delay);
}

.p-hero__cta:hover,
.p-hero__cta:focus-visible {
	--p-cta-s: 1.05;
	--p-cta-y: -2px;
	border-color: rgba(198, 242, 157, 0.9);
}

.p-hero__cta:hover::before,
.p-hero__cta:focus-visible::before,
.p-hero__cta:hover::after,
.p-hero__cta:focus-visible::after {
	opacity: 1;
}

.p-hero__cta:focus-visible {
	outline: 1px solid var(--p-hero-accent);
	outline-offset: 4px;
}

/* ======================================================================
   The wooden sign

   Placed by JS in the photograph's coordinates. Everything below is confined
   to that rectangle: nothing here can touch the rest of the picture.
   ====================================================================== */

.p-hero__sign {
	position: absolute;
	left: var(--p-sign-left, 82.53%);
	top: var(--p-sign-top, 18.78%);
	width: var(--p-sign-w, 13.47%);
	height: var(--p-sign-h, 15.19%);
	display: block;
	cursor: pointer;
	border-radius: 2px;
	-webkit-tap-highlight-color: transparent;
}

/*
 * Stage 1 — the strips themselves.
 *
 * Mounted behind the board's edges, so what shows is the light escaping around
 * it rather than the lamp. `screen` adds light to the wood instead of painting
 * a colour over it, which is why the grain survives.
 */
.p-hero__led {
	position: absolute;
	inset: -3%;
	border-radius: 4px;
	background:
		linear-gradient(to right, rgba(var(--p-hero-led), 0.5) 0%, rgba(var(--p-hero-led), 0) 16%),
		linear-gradient(to left, rgba(var(--p-hero-led), 0.5) 0%, rgba(var(--p-hero-led), 0) 16%),
		linear-gradient(to bottom, rgba(var(--p-hero-led), 0.42) 0%, rgba(var(--p-hero-led), 0) 14%),
		linear-gradient(to top, rgba(var(--p-hero-led), 0.46) 0%, rgba(var(--p-hero-led), 0) 18%);
	mix-blend-mode: screen;
	filter: blur(7px);
	opacity: 0;
	transition: opacity 600ms ease;
	pointer-events: none;
}

/* The light that reaches the wall and the leaves behind the board. Wider,
   softer, and weaker than the strips — this is bounce, not source. */
.p-hero__ledspill {
	position: absolute;
	inset: -34%;
	border-radius: 50%;
	background: radial-gradient(
		50% 50% at 50% 50%,
		rgba(var(--p-hero-led), 0.20) 0%,
		rgba(var(--p-hero-led), 0.08) 45%,
		rgba(var(--p-hero-led), 0) 74%
	);
	mix-blend-mode: screen;
	filter: blur(16px);
	opacity: 0;
	transition: opacity 600ms ease;
	pointer-events: none;
}

/*
 * The wood itself: richer, fractionally brighter, fractionally more contrast.
 * Brightness stops at 1.06 — the brief's ceiling is 8% and this leaves room for
 * the strips to add the rest.
 */
.p-hero__wood {
	position: absolute;
	inset: 0;
	border-radius: 2px;
	backdrop-filter: brightness(1.06) contrast(1.045) saturate(1.08);
	-webkit-backdrop-filter: brightness(1.06) contrast(1.045) saturate(1.08);
	opacity: 0;
	transition: opacity 600ms ease;
	pointer-events: none;
}

/*
 * Stage 3 — the engraving.
 *
 * Sits over the carved wordmark only, at 84.05%–94.61% across the board and
 * 24.31%–29.65% down it, converted here to the board's own box. It lifts
 * contrast by about 5% and lays a very soft warm sheen across the letters. No
 * colour change, no green, nothing that reads as a light of its own.
 */
.p-hero__signlogo {
	position: absolute;
	left: 11.2%;
	top: 36.5%;
	width: 78.4%;
	height: 35.2%;
	border-radius: 2px;
	backdrop-filter: brightness(1.05) contrast(1.05);
	-webkit-backdrop-filter: brightness(1.05) contrast(1.05);
	background: linear-gradient(
		105deg,
		rgba(var(--p-hero-led), 0) 18%,
		rgba(var(--p-hero-led), 0.10) 48%,
		rgba(var(--p-hero-led), 0) 78%
	);
	mix-blend-mode: screen;
	opacity: 0;
	transition: opacity 600ms ease;
	pointer-events: none;
}

/* Hovering the board lights the strips, the spill and the wood. */
.p-hero__sign:hover .p-hero__led,
.p-hero__sign:focus-visible .p-hero__led,
.p-hero__sign:hover .p-hero__ledspill,
.p-hero__sign:focus-visible .p-hero__ledspill,
.p-hero__sign:hover .p-hero__wood,
.p-hero__sign:focus-visible .p-hero__wood {
	opacity: 1;
}

/* The engraving is the extra layer, and it answers only to the engraving. */
.p-hero__sign.is-onlogo .p-hero__signlogo,
.p-hero__sign:focus-visible .p-hero__signlogo {
	opacity: 1;
}

.p-hero__sign:focus-visible {
	outline: 1px solid rgba(var(--p-hero-led), 0.85);
	outline-offset: 6px;
}

/* ======================================================================
   Responsive
   ====================================================================== */

@media (max-width: 900px) {
	.p-hero {
		--p-hero-seam: 100%;

		/*
		 * A phone gets `min-height` rather than a hard height. The sizes above
		 * bottom out at a floor — below about 0.8rem this copy stops being
		 * readable — so on a short handset the column can genuinely need more
		 * room than the screen has, and a hero that clips its own button is
		 * worse than one that runs a little long. In practice the content lands
		 * inside one screen at every common handset size, and `min-height`
		 * renders that as exactly one screen.
		 */
		height: auto;
		min-height: 100svh;
		overflow: visible;
	}

	/*
	 * Fully opaque, with no alpha anywhere.
	 *
	 * This gradient used to end at 0.9 alpha, which let the artwork's baked
	 * feature row read faintly through the foot of the panel — two sets of the
	 * same four icons, one live and one a ghost behind it. A panel whose job is
	 * to replace the baked column cannot be see-through at any point on it.
	 */
	.p-hero__panel {
		position: absolute;
		inset: 0;
		/* No photograph beside it at this width, so nothing to fade into. */
		--p-hero-feather: 0px;
		width: 100%;
		padding-right: 0;
		background: linear-gradient(
			to bottom,
			var(--p-hero-panel-top) 0%,
			var(--p-hero-panel-mid) 40%,
			var(--p-hero-panel-foot) 100%
		);
	}

	.p-hero__panelinner {
		padding: var(--p-space-7) var(--p-space-5);
	}

	/* The sign is behind the panel at this width and cannot be reached, so it
	   stops pretending to be a control. */
	.p-hero__sign {
		display: none;
	}
}

@media (max-width: 560px) {
	.p-hero__features {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--p-space-3) 0;
	}

	/* With two per row the vertical rules would land in the wrong places. */
	.p-hero__feature + .p-hero__feature {
		border-left: 0;
	}
}

/* ======================================================================
   Reduced motion

   Nothing moves. The colour, the underline and the light still answer the
   cursor, because those communicate what is clickable and removing them would
   cost more than it saves.
   ====================================================================== */

@media (prefers-reduced-motion: reduce) {
	.p-hero__word,
	.p-hero__featurelink,
	.p-hero__cta {
		transform: none;
		transition-property: color, text-shadow, border-color;
		transition-duration: 1ms;
	}

	.p-hero__word:hover,
	.p-hero__word:focus-visible,
	.p-hero__featurelink:hover,
	.p-hero__featurelink:focus-visible,
	.p-hero__cta:hover,
	.p-hero__cta:focus-visible {
		--p-word-s: 1;
		--p-feat-s: 1;
		--p-feat-y: 0;
		--p-cta-s: 1;
		--p-cta-y: 0;
	}

	.p-hero__word::after,
	.p-hero__featurelink::before,
	.p-hero__cta::before,
	.p-hero__cta::after,
	.p-hero__led,
	.p-hero__ledspill,
	.p-hero__wood,
	.p-hero__signlogo {
		transition-duration: 1ms;
	}
}
