/*
 * Janda Events — fonts, reset, typography, layout primitives, controls.
 */

/* ==========================================================================
   Fonts
   ========================================================================== */

/* Body — Plus Jakarta Sans, variable, self-hosted (SIL OFL). */
@font-face {
	font-family: "Plus Jakarta Sans";
	font-style: normal;
	font-weight: 200 800;
	font-display: swap;
	src: url("../fonts/plus-jakarta-sans-latin.woff2") format("woff2");
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
		U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
		U+FEFF, U+FFFD;
}

@font-face {
	font-family: "Plus Jakarta Sans";
	font-style: normal;
	font-weight: 200 800;
	font-display: swap;
	src: url("../fonts/plus-jakarta-sans-latin-ext.woff2") format("woff2");
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
		U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
		U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/*
 * Display — Nyght Serif by Maksym Kobuzan, self-hosted (SIL OFL 1.1).
 * Source: https://gitlab.com/mkobuzan/nyght-serif (distributed by Tunera Type
 * Foundry). Licence text: assets/fonts/nyght-serif-OFL.txt.
 *
 * The family ships Light/Regular/Medium/Bold/Dark plus italics, but the design
 * only ever sets Regular 400 — so only that face is declared. Adding more here
 * without a matching file would let the browser synthesise a fake weight, which
 * is worse than not having it. If a future template genuinely uses another
 * style, add the file and its own @font-face block.
 */
@font-face {
	font-family: "Nyght Serif";
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url("../fonts/nyght-serif-regular.woff2") format("woff2");
}

/*
 * Secondary fallback only — bridges the swap window and covers the case where
 * the primary file fails to load. Never the active heading face.
 */
@font-face {
	font-family: "Nyght Serif Fallback";
	font-style: normal;
	font-weight: 400 700;
	font-display: swap;
	src: url("../fonts/playfair-display-latin.woff2") format("woff2");
}

/* ==========================================================================
   Reset
   ========================================================================== */

*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
	/* The header is sticky on every template, so anchored targets — the skip
	   link, in-page section links — have to stop below it rather than under it. */
	scroll-padding-top: var(--header-h);
}

/*
 * Set by app.js when it takes over the page scroll. The native behaviour has to
 * stand down while it does: easing the position per frame against
 * scroll-behavior: smooth means the browser eases toward each intermediate
 * target in turn, which lags visibly.
 */
html.has-smooth-scroll {
	scroll-behavior: auto;
}

body,
h1, h2, h3, h4, h5, h6,
p, figure, blockquote, dl, dd, ul, ol {
	margin: 0;
}

/*
 * Wrapped in :where() so the reset carries zero specificity. As a bare
 * `ul[class]` it scores (0,1,1) and silently beats any single-class rule that
 * sets padding on a list — which is exactly what component styles do.
 */
:where(ul[class], ol[class]) {
	padding: 0;
	list-style: none;
}

/*
 * The UA sheet's `[hidden] { display: none }` carries no more weight than any
 * component rule, so a single `display: flex` on a card silently defeats it —
 * which is how a paged grid ends up rendering the pages it just hid. Nothing in
 * this theme wants a visible [hidden] element, so the reset wins outright.
 */
[hidden] {
	display: none !important;
}

img,
picture,
video,
canvas,
svg {
	display: block;
	max-width: 100%;
}

img {
	height: auto;
}

input,
button,
textarea,
select {
	font: inherit;
	color: inherit;
}

button {
	background: none;
	border: 0;
	cursor: pointer;
}

table {
	border-collapse: collapse;
	width: 100%;
}

/* ==========================================================================
   Document
   ========================================================================== */

body {
	margin: 0;
	background-color: var(--c-ground-light);
	color: var(--c-text);
	font-family: var(--font-body);
	font-size: var(--fs-body-md);
	font-weight: var(--fw-regular);
	line-height: var(--lh-body);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	overflow-x: hidden;
}

/* ==========================================================================
   Typography
   ========================================================================== */

h1, h2, h3, h4, h5, h6,
.display-4xl, .display-3xl, .display-2xl, .display-xl, .display-lg {
	font-family: var(--font-display);
	font-weight: var(--fw-regular);
	line-height: var(--lh-display);
	color: var(--c-heading);
	/*
	 * No text-wrap: balance. The design's line breaks are natural wraps inside
	 * fixed text boxes, and balancing redistributes them — it was turning
	 * "Wedding Singer / & Soloist" into "Wedding / Singer & Soloist".
	 */
}

/*
 * Interpolates the two source frames exactly: 48px at 428, 80px at 1440.
 * Long unbreakable headlines are handled where they occur (.home-hero__title)
 * rather than by holding the whole scale down to 40.
 */
h1, .display-4xl {
	font-size: clamp(2.5rem, 2.1541rem + 3.1621vw, var(--fs-display-4xl));
	overflow-wrap: break-word;
}

/* Interpolates the two source frames exactly: 40px at 428, 64px at 1440. */
h2, .display-3xl {
	font-size: clamp(2.5rem, 1.87rem + 2.37vw, var(--fs-display-3xl));
}

/* 34px at 428, 48px at 1440 — the mobile frames set the story and SEO headings
   on a 41px line (51288:11093 is 4 lines in 164, 51288:11229 3 in 123). */
h3, .display-2xl {
	font-size: clamp(1.75rem, 1.77rem + 1.3666vw, var(--fs-display-2xl));
	letter-spacing: var(--ls-display);
}

h4, .display-xl {
	font-size: clamp(1.5rem, 1.2rem + 1.2vw, var(--fs-display-xl));
	letter-spacing: var(--ls-display);
}

h5, .display-lg {
	font-size: var(--fs-display-lg);
	line-height: 2rem;
	letter-spacing: var(--ls-display);
}

h6 {
	font-size: var(--fs-body-xl);
}

p {
	text-wrap: pretty;
}

p + p {
	margin-top: 1em;
}

a {
	color: var(--c-link);
	text-decoration-thickness: 1px;
	text-underline-offset: 0.2em;
	transition: color var(--dur-fast) var(--ease);
}

a:hover {
	color: var(--c-link-hover);
}

strong,
b {
	font-weight: var(--fw-semibold);
}

/* Small uppercase label above a heading ("why us?", "FEATURED TALENT").
   Figma 51288:10784 — 14/20px, 0.56px tracking, primary/500. */
.eyebrow {
	display: block;
	margin: 0;
	font-family: var(--font-body);
	font-size: var(--fs-body-sm);
	font-weight: var(--fw-regular);
	letter-spacing: var(--ls-eyebrow);
	line-height: 20px;
	text-transform: uppercase;
	color: var(--c-primary-500);
}

/* Figma 51284:4644 / 51284:4780 — same metrics on a light ground. */
.eyebrow--dark {
	color: var(--c-black);
}

/* Figma 51284:4903 — "Featured events", 2px tracking at 14/16. */
.eyebrow--wide {
	font-weight: var(--fw-medium);
	line-height: 16px;
	letter-spacing: 2px;
	color: var(--c-black);
}

.lede {
	font-size: var(--fs-body-lg);
}

/* Ground-aware text colours. */
.is-dark {
	background-color: var(--c-ground-dark);
	color: var(--c-text-on-dark);
}

.is-dark h1, .is-dark h2, .is-dark h3,
.is-dark h4, .is-dark h5, .is-dark h6,
.is-dark .eyebrow {
	color: var(--c-heading-on-dark);
}

/* ==========================================================================
   Layout primitives
   ========================================================================== */

.container {
	width: 100%;
	max-width: calc(var(--container) + (var(--gutter) * 2));
	margin-inline: auto;
	padding-inline: var(--gutter);
}

.container--narrow {
	max-width: calc(var(--container-narrow) + (var(--gutter) * 2));
}

.section {
	padding-block: var(--section-y);
}

.section--flush {
	padding-block: 0;
}

.stack > * + * {
	margin-top: var(--space-24);
}

.grid {
	display: grid;
	gap: var(--space-24);
}

/* Horizontal card rails: scrollable on small screens, never on the page body. */
.rail {
	display: flex;
	gap: var(--space-16);
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	/* Without this the first snap target aligns to the border edge and the
	   browser scrolls the rail by its own padding on load. */
	scroll-padding-inline: var(--gutter);
	scrollbar-width: none;
	padding-bottom: var(--space-8);
	-webkit-overflow-scrolling: touch;
}

.rail::-webkit-scrollbar {
	display: none;
}

.rail > * {
	flex: 0 0 auto;
	scroll-snap-align: start;
	/*
	 * Never the full width of the rail: --rail-peek of the next card stays on
	 * screen so the row reads as draggable. Wide viewports are unaffected — the
	 * cap is above every card's own width there.
	 */
	max-width: calc(100% - var(--rail-peek));
}

/* ==========================================================================
   Accessibility
   ========================================================================== */

.screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.skip-link {
	position: absolute;
	top: var(--space-8);
	left: var(--space-8);
	z-index: 999;
	padding: var(--space-12) var(--space-16);
	background: var(--c-white);
	color: var(--c-primary-800);
	border-radius: var(--radius-md);
	transform: translateY(-200%);
	transition: transform var(--dur) var(--ease);
}

.skip-link:focus-visible {
	transform: translateY(0);
}

:where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
	outline: 2px solid var(--c-focus);
	outline-offset: 3px;
	border-radius: var(--radius-sm);
}

.is-dark :where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
	outline-color: var(--c-white);
}

/* ==========================================================================
   Controls
   ========================================================================== */

.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-8);
	min-height: var(--btn-height);
	min-width: var(--btn-min-width);
	padding: 0 var(--btn-padding-x);
	border: 1px solid transparent;
	border-radius: var(--radius-pill);
	font-size: var(--fs-body-md);
	/* Figma sets every button label at 400/16/24 (51013:3521, 51013:3503) —
	   500 was reading a shade heavier than the design everywhere it appeared. */
	font-weight: var(--fw-regular);
	line-height: 24px;
	text-align: center;
	text-decoration: none;
	transition: background-color var(--dur-fast) var(--ease),
		color var(--dur-fast) var(--ease),
		border-color var(--dur-fast) var(--ease);
}

.btn--primary {
	background-color: var(--c-primary-500);
	color: var(--c-white);
}

.btn--primary:hover,
.btn--primary:focus-visible {
	background-color: var(--c-primary-800);
	color: var(--c-white);
}

/*
 * Figma strokes this pill with a linear gradient (#EFFCFC → #248596), not a
 * flat border, so the border area is painted with a second background layer
 * clipped to it.
 */
.btn--light {
	background-color: var(--c-white);
	color: var(--c-primary-800);
	border-color: transparent;
	background-image: linear-gradient(var(--c-white), var(--c-white)),
		linear-gradient(135deg, var(--c-primary-50), #248596);
	background-origin: border-box;
	background-clip: padding-box, border-box;
}

.btn--light:hover,
.btn--light:focus-visible {
	color: var(--c-primary-900);
	background-image: linear-gradient(var(--c-primary-100), var(--c-primary-100)),
		linear-gradient(135deg, var(--c-primary-50), #248596);
}

.btn--outline {
	background-color: transparent;
	border-color: currentcolor;
	color: var(--c-primary-800);
}

.btn--outline:hover,
.btn--outline:focus-visible {
	background-color: var(--c-primary-800);
	border-color: var(--c-primary-800);
	color: var(--c-white);
}

/* Text link with a trailing icon ("Find Out More", "View Package"). */
.link-arrow {
	display: inline-flex;
	align-items: center;
	gap: var(--space-8);
	font-size: var(--fs-body-sm);
	font-weight: var(--fw-medium);
	text-decoration: none;
}

.link-arrow .icon {
	width: 1rem;
	height: 1rem;
	transition: transform var(--dur-fast) var(--ease);
}

.link-arrow:hover .icon {
	transform: translateX(2px);
}

/* Filter chips. */
.chip {
	display: inline-flex;
	align-items: center;
	min-height: 2rem;
	padding: 0 var(--space-16);
	border: 1px solid var(--c-primary-500);
	border-radius: var(--radius-pill);
	background-color: transparent;
	color: var(--c-primary-800);
	font-size: var(--fs-body-sm);
	line-height: 1;
	transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.chip:hover {
	background-color: var(--c-primary-50);
}

.chip[aria-pressed="true"] {
	background-color: var(--c-primary-500);
	color: var(--c-white);
}

/* Circular icon buttons (carousel prev/next, card "+"). */
.icon-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.5rem;
	height: 2.5rem;
	border: 1px solid var(--c-border);
	border-radius: var(--radius-circle);
	background-color: var(--c-white);
	color: var(--c-primary-800);
	transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.icon-btn:hover {
	background-color: var(--c-primary-500);
	border-color: var(--c-primary-500);
	color: var(--c-white);
}

.icon-btn[disabled] {
	opacity: 0.4;
	cursor: not-allowed;
}

/* ==========================================================================
   Forms
   ========================================================================== */

label {
	display: block;
	margin-bottom: var(--space-8);
	font-size: var(--fs-body-sm);
	font-weight: var(--fw-medium);
}

input[type="text"],
input[type="email"],
input[type="tel"],
input[type="url"],
input[type="date"],
input[type="number"],
input[type="search"],
textarea,
select {
	width: 100%;
	min-height: var(--btn-height);
	padding: var(--space-12) var(--space-16);
	border: 1px solid var(--c-border);
	border-radius: var(--radius-md);
	background-color: var(--c-white);
	color: var(--c-text);
	transition: border-color var(--dur-fast) var(--ease);
}

textarea {
	min-height: 8rem;
	resize: vertical;
}

input:focus,
textarea:focus,
select:focus {
	border-color: var(--c-primary-500);
}

::placeholder {
	color: rgba(62, 62, 62, 0.55);
}

/*
 * Contact Form 7 messaging.
 *
 * CF7 emits the tip as a bare <span> inside .wpcf7-form-control-wrap, i.e.
 * inline. An inline box ignores margin-top, and it took whatever line-height
 * the wrap was carrying — under the contact card's old `line-height: 0` that
 * was zero, so the tip reserved no flow space and painted straight over the
 * next field's label (#JE-50). It has to be a block with a line-height of its
 * own so it always pushes the rest of the form down by its own height.
 */
.wpcf7-not-valid-tip {
	display: block;
	margin-top: var(--space-4);
	color: #b3261e;
	font-size: var(--fs-body-sm);
	line-height: var(--lh-body);
}

/*
 * The submit result.
 *
 * This used to say the whole thing with a 1px border and recolour it per state,
 * which is the pattern the manager rejected on the sibling project (#EAS-134:
 * "no green border and a tick icon that shows up"). It is also the weakest
 * possible signal — a hairline hue change, no icon, nothing to read at a glance
 * and nothing at all if you cannot separate red from green. It is now a filled
 * panel with a state icon, matching the treatment that was approved there.
 *
 * Selectors are qualified `.wpcf7 form` to outrank the plugin's own
 * `.wpcf7 form .wpcf7-response-output`, which otherwise re-imposes its 2px blue
 * border and its `margin: 2em 0.5em 1em` over anything written at class level —
 * that is why the old rule's border and margin never actually took effect.
 * `display` is deliberately left alone: CF7 hides this node on the init,
 * resetting and submitting states and that must keep working.
 */
.wpcf7 form .wpcf7-response-output {
	display: flex;
	align-items: center;
	gap: var(--space-16);
	margin: var(--space-24) 0 0;
	padding: var(--space-16) var(--space-20);
	border: 0;
	border-radius: var(--radius-md);
	background-color: #f1f1f1;
	color: var(--c-body);
	font-size: var(--fs-body-sm);
	line-height: var(--lh-body);
}

/* Sized and shrink-proofed so a long message cannot squash the disc. */
.wpcf7 form .wpcf7-response-output::before {
	content: "";
	flex: 0 0 auto;
	width: 28px;
	height: 28px;
	background-position: center;
	background-repeat: no-repeat;
	background-size: contain;
}

/* Success — the approved treatment: soft panel, filled dark-green disc, white
   tick. Sampled off the approved screenshot: panel #f3f6f3, disc #486c48. */
.wpcf7 form.sent .wpcf7-response-output {
	background-color: #f3f6f3;
}

.wpcf7 form.sent .wpcf7-response-output::before {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle cx='16' cy='16' r='16' fill='%23486c48'/%3E%3Cpath d='M9.5 16.8l4.6 4.6L22.5 13' fill='none' stroke='%23ffffff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* Anything that needs attention gets the same panel in the theme's error red,
   so the two states are told apart by fill and glyph rather than by hue alone. */
.wpcf7 form.invalid .wpcf7-response-output,
.wpcf7 form.unaccepted .wpcf7-response-output,
.wpcf7 form.payment-required .wpcf7-response-output,
.wpcf7 form.failed .wpcf7-response-output,
.wpcf7 form.aborted .wpcf7-response-output,
.wpcf7 form.spam .wpcf7-response-output {
	background-color: #fdf1f0;
	color: #7f1b15;
}

.wpcf7 form.invalid .wpcf7-response-output::before,
.wpcf7 form.unaccepted .wpcf7-response-output::before,
.wpcf7 form.payment-required .wpcf7-response-output::before,
.wpcf7 form.failed .wpcf7-response-output::before,
.wpcf7 form.aborted .wpcf7-response-output::before,
.wpcf7 form.spam .wpcf7-response-output::before {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Ccircle cx='16' cy='16' r='16' fill='%23b3261e'/%3E%3Cpath d='M16 8.5v9.5' fill='none' stroke='%23ffffff' stroke-width='3' stroke-linecap='round'/%3E%3Ccircle cx='16' cy='23.2' r='1.9' fill='%23ffffff'/%3E%3C/svg%3E");
}

/* ==========================================================================
   Motion preferences
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}
