/**
 * Bellora Design System — shared primitives.
 *
 * Every value reads a token printed by Bellora_Design_System on :root.
 * Widgets compose these primitives and the tokens; they never hardcode a
 * design value.
 *
 * Faces: Playfair Display (display) and Outfit (body/UI), both from Google
 * Fonts via Bellora_Assets.
 */

/* -------------------------------------------------- *
 * Display face.
 *
 * Playfair Display (loaded from Google Fonts) is the shipped display serif.
 * The stack still names "Butler" first, so a site that licenses it only has
 * to self-host the files and declare its own @font-face — nothing else has
 * to change. No @font-face is declared here for a face the theme does not
 * ship: it would cost every page four failing requests.
 * -------------------------------------------------- */

/* -------------------------------------------------- *
 * Spec aliases — the bellora.md token names, mapped onto the printed
 * design tokens so stylesheets can be written in either vocabulary.
 * -------------------------------------------------- */

:root {
	--vsp-base: var(--bellora-color-surface);
	--vsp-band: var(--bellora-color-surface-cream);
	--vsp-ink: var(--bellora-color-heading);
	--vsp-ink-soft: var(--bellora-color-heading-soft);
	--vsp-accent: var(--bellora-color-accent);
	--vsp-line: var(--bellora-color-border);
	--vsp-invert: var(--bellora-color-surface-invert);
	--vsp-invert-text: var(--bellora-color-on-invert);
	--vsp-font-display: var(--bellora-font-display);
	--vsp-font-body: var(--bellora-font-body);
	--vsp-hairline: 1px solid var(--bellora-color-border);
	--vsp-arch: 999px 999px 0 0;
	--vsp-max-text: 720px;
}

/* -------------------------------------------------- *
 * Buttons — black fill, sharp corners, uppercase; hover inverts to
 * transparent with ink text (spec §2.5).
 * -------------------------------------------------- */

.bellora-btn {
	display: inline-flex;
	align-items: center;
	gap: 0.875rem;
	padding: 18px 34px;
	border: 1px solid var(--bellora-color-primary);
	border-radius: var(--bellora-radius-xs);
	background: var(--bellora-color-primary);
	color: var(--bellora-color-on-primary);
	font-family: var(--bellora-font-ui);
	font-size: 12px;
	font-weight: var(--bellora-weight-medium);
	line-height: 1;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	text-decoration: none;
	cursor: pointer;
	transition: background 0.45s var(--bellora-motion-easing),
		color 0.45s var(--bellora-motion-easing);
}

.bellora-btn svg {
	width: 1.375rem;
	height: 0.6875rem;
	transition: transform 0.45s var(--bellora-motion-easing);
}

.bellora-btn:hover,
.bellora-btn:focus-visible {
	background: transparent;
	color: var(--bellora-color-heading);
}

.bellora-btn:hover svg,
.bellora-btn:focus-visible svg {
	transform: translateX(4px);
}

/* Ghost: transparent at rest, ink fill on hover. */
.bellora-btn--ghost {
	background: transparent;
	border-color: currentColor;
	color: inherit;
}

.bellora-btn--ghost:hover,
.bellora-btn--ghost:focus-visible {
	background: var(--bellora-color-primary);
	border-color: var(--bellora-color-primary);
	color: var(--bellora-color-on-primary);
}

/* Invert: base fill for dark bands. */
.bellora-btn--invert {
	background: var(--bellora-color-surface);
	border-color: var(--bellora-color-surface);
	color: var(--bellora-color-heading);
}

.bellora-btn--invert:hover,
.bellora-btn--invert:focus-visible {
	background: transparent;
	color: var(--bellora-color-on-invert);
	border-color: var(--bellora-color-surface);
}

/* -------------------------------------------------- *
 * Text link — small caps; a 1px underline draws in from the left on
 * hover and leaves to the right (spec §2.5).
 * -------------------------------------------------- */

.bellora-link {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 0.625rem;
	padding-bottom: 4px;
	font-family: var(--bellora-font-ui);
	font-size: 12px;
	font-weight: var(--bellora-weight-medium);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	text-decoration: none;
	color: var(--bellora-color-heading);
}

.bellora-link::after {
	content: "";
	position: absolute;
	left: 0;
	bottom: 0;
	width: 100%;
	height: 1px;
	background: currentColor;
	transform: scaleX(0);
	transform-origin: right;
	transition: transform 0.4s var(--bellora-motion-easing);
}

.bellora-link:hover::after,
.bellora-link:focus-visible::after {
	transform: scaleX(1);
	transform-origin: left;
}

.bellora-link svg {
	width: 1.25rem;
	height: 0.625rem;
}

/* -------------------------------------------------- *
 * Motion
 *
 * Armed only when bellora-motion.js stamps `bellora-motion` on <html> —
 * without JavaScript (or with reduced motion) nothing is ever hidden.
 * Views set `--reveal-delay` inline to stagger siblings.
 * -------------------------------------------------- */

.bellora-motion [data-reveal] {
	opacity: 0;
	transform: translateY(28px);
	transition:
		opacity 0.9s var(--bellora-motion-easing),
		transform 0.9s var(--bellora-motion-easing);
	transition-delay: var(--reveal-delay, 0s);
	will-change: opacity, transform;
}

.bellora-motion [data-reveal].is-inview {
	opacity: 1;
	transform: none;
}

/* Headings: wipe up from under their baseline. */
.bellora-motion [data-reveal="mask"] {
	transform: none;
	clip-path: inset(0 -0.15em 100% -0.15em);
	transition:
		opacity 0.9s var(--bellora-motion-easing),
		clip-path 1.1s var(--bellora-motion-easing);
	transition-delay: var(--reveal-delay, 0s);
}

.bellora-motion [data-reveal="mask"].is-inview {
	clip-path: inset(-0.2em -0.15em -0.2em -0.15em);
}

/* Images: the frame unclips upward while the photo settles from a gentle
   overscale back to rest. */
.bellora-motion [data-reveal="media"] {
	transform: none;
	opacity: 1;
	clip-path: inset(100% 0 0 0);
	transition: clip-path 1.2s var(--bellora-motion-easing);
	transition-delay: var(--reveal-delay, 0s);
	overflow: hidden;
}

.bellora-motion [data-reveal="media"] img {
	transform: scale(1.12);
	transition: transform 1.6s var(--bellora-motion-easing);
	transition-delay: var(--reveal-delay, 0s);
}

.bellora-motion [data-reveal="media"].is-inview {
	clip-path: inset(0 0 0 0);
}

.bellora-motion [data-reveal="media"].is-inview img {
	transform: scale(1);
}

/* Parallax frames crop the drifting, slightly overscaled photo. */
.bellora-motion .is-parallax {
	overflow: hidden;
}

.bellora-motion .is-parallax img {
	will-change: transform;
}

/* Parallax owns the img transform, so a frame that is both is-parallax and
   a media reveal keeps only the clip wipe. */
.bellora-motion [data-reveal="media"].is-parallax img {
	transition: none;
}

/* -------------------------------------------------- *
 * Word reveal — headings whose words rise one by one.
 * The element itself is never hidden; each word carries its own clip.
 * -------------------------------------------------- */

.bellora-motion [data-reveal="words"] {
	opacity: 1;
	transform: none;
	transition: none;
}

/* The mask has to hide the word while it rises, but a box sized to the glyph
   advance shaves italic overhangs and descenders for the whole second the
   animation runs. Padding widens the mask past the ink and an equal negative
   margin gives the space back, so layout is untouched; the word simply has to
   travel a little further to start out of sight. */
.b-word {
	display: inline-block;
	padding: 0.3em 0.35em;
	margin: -0.3em -0.35em;
	overflow: hidden;
	vertical-align: bottom;
}

.bellora-motion .b-word__inner {
	display: inline-block;
	transform: translateY(140%);
	transition: transform 0.9s var(--bellora-motion-easing);
	transition-delay: calc(var(--reveal-delay, 0s) + var(--w, 0) * 70ms);
	will-change: transform;
}

.bellora-motion [data-reveal="words"].is-inview .b-word__inner {
	transform: none;
}

/* A mask is only needed while the entrance plays. Once it has finished the
   clip is dropped, otherwise it keeps shaving the ink that sits outside the
   layout box — italic overhangs, serif flourishes, descenders and commas.
   The class is added by bellora-motion.js when the animation completes. */
.bellora-motion [data-reveal].is-revealed {
	clip-path: none;
}

.bellora-motion [data-reveal="words"].is-revealed .b-word {
	overflow: visible;
}

/* Scroll-drift headings own their transform — give them room to move. */
.is-drift {
	will-change: transform;
}

/* -------------------------------------------------- *
 * Page transition — a base-coloured curtain unclips upward over the
 * leaving page (700ms); on arrival it opens away upward (600ms).
 * The system cursor is never touched and no scroll library exists:
 * both are deliberate spec decisions (§7.1).
 * -------------------------------------------------- */

/* The curtain is printed by the template and starts closed *in CSS*, so it
   covers the very first painted frame. Driving the arrival from a keyframe
   with `both` fill means the covered state applies before the animation
   starts — there is no gap for the raw page to flash through, and no
   dependency on a script that only runs at the end of the body. */
.bellora-transition {
	position: fixed;
	inset: 0;
	z-index: 10000;
	background: var(--bellora-color-surface);
	clip-path: inset(0 0 100% 0);
	pointer-events: none;
	animation: bellora-curtain-open 0.6s cubic-bezier(0.65, 0, 0.35, 1) both;
}

@keyframes bellora-curtain-open {
	from {
		clip-path: inset(0 0 0 0);
	}

	to {
		clip-path: inset(0 0 100% 0);
	}
}

/* Departure is a keyframe too, not a transition: swapping `animation: none`
   and a new clip-path in the same recalculation left the browser without a
   start value to interpolate from, so the curtain snapped shut instantly and
   the page looked like it simply vanished. */
.bellora-transition.is-entering {
	animation: bellora-curtain-close 0.65s cubic-bezier(0.65, 0, 0.35, 1) both;
	pointer-events: auto;
}

/* Rises from the bottom edge to cover, so the wipe keeps travelling upward
   into the arrival, which retracts off the top. */
@keyframes bellora-curtain-close {
	from {
		clip-path: inset(100% 0 0 0);
	}

	to {
		clip-path: inset(0 0 0 0);
	}
}

@media (prefers-reduced-motion: reduce) {
	.bellora-transition {
		animation: none;
	}
}

/* -------------------------------------------------- *
 * Utilities
 * -------------------------------------------------- */

.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}
