/* ==========================================================================
   Koningsfestival — design system

   Built to reference/approved-full-page.png and docs/IMPLEMENTATION-SPEC.md.
   The page is an immersive blue/orange festival composition: the supplied
   campaign artwork fills the hero, then a continuous run of deep navy and royal
   blue sections punctuated once by a solid orange newsletter band, with
   edge-to-edge photography and electric-blue neon detail.

   Every photograph, silhouette and ornament is a production file from the
   supplied asset pack, served as delivered. Nothing here draws scenery: no
   gradients standing in for sky, no vector buildings, no generated logo. The
   only vectors are UI glyphs — play, chevron, prohibition, contact, social.

   Token values are the ones fixed by the spec, not sampled approximations.

   Contrast is verified against WCAG AA by scripts/check.mjs at every viewport.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Fonts — self-hosted, so the page makes no third-party request on load
   -------------------------------------------------------------------------- */

@font-face {
	font-family: 'Anton';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('../fonts/anton-400-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: 'Anton';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('../fonts/anton-400-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;
}

@font-face {
	font-family: 'Barlow Condensed';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('../fonts/barlow-condensed-400-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: 'Barlow Condensed';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('../fonts/barlow-condensed-400-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;
}

@font-face {
	font-family: 'Barlow Condensed';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url('../fonts/barlow-condensed-500-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: 'Barlow Condensed';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url('../fonts/barlow-condensed-500-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;
}

@font-face {
	font-family: 'Barlow Condensed';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url('../fonts/barlow-condensed-600-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: 'Barlow Condensed';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url('../fonts/barlow-condensed-600-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;
}

@font-face {
	font-family: 'Barlow Condensed';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('../fonts/barlow-condensed-700-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: 'Barlow Condensed';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('../fonts/barlow-condensed-700-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;
}

/* --------------------------------------------------------------------------
   Tokens — exactly the values in docs/IMPLEMENTATION-SPEC.md
   -------------------------------------------------------------------------- */

:root {
	--kf-navy: #020D38;
	--kf-navy-deep: #010825;
	--kf-royal: #003BAE;
	--kf-electric: #067BFF;
	--kf-orange: #FF6A00;
	--kf-orange-deep: #D24E00;
	--kf-gold: #FFB000;
	--kf-white: #FFFFFF;
	--kf-text: #D9E6FF;
	--kf-text-dim: #9FB6E4;

	--kf-font-display: 'Anton', 'Arial Narrow', Impact, system-ui, sans-serif;
	--kf-font-cond: 'Barlow Condensed', 'Arial Narrow', system-ui, sans-serif;
	--kf-font-body: 'Barlow Condensed', 'Segoe UI', system-ui, -apple-system, sans-serif;

	--kf-t-micro: clamp(0.8rem, 0.76rem + 0.16vw, 0.92rem);
	--kf-t-small: clamp(0.98rem, 0.93rem + 0.22vw, 1.14rem);
	--kf-t-body: clamp(1.06rem, 1rem + 0.28vw, 1.28rem);
	--kf-t-card: clamp(1.18rem, 1.04rem + 0.6vw, 1.55rem);
	--kf-t-h3: clamp(1.3rem, 1.05rem + 1.1vw, 1.95rem);
	--kf-t-h2: clamp(1.85rem, 1.3rem + 2.4vw, 3.4rem);
	--kf-t-date: clamp(1.75rem, 0.9rem + 3.6vw, 4rem);
	--kf-t-count: clamp(1.9rem, 1.2rem + 2.9vw, 3.9rem);

	--kf-band: clamp(1.6rem, 1rem + 2.6vw, 3.9rem);
	--kf-radius: 0.6rem;
	--kf-radius-lg: 1rem;

	/* Spec: desktop content max width 1180–1240px */
	--kf-container: 76.25rem;
	--kf-header-h: 5.75rem;
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */

*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	scroll-behavior: smooth;
	scroll-padding-top: calc(var(--kf-header-h) + 0.5rem);
	-webkit-text-size-adjust: 100%;
}

body {
	margin: 0;
	background: var(--kf-navy);
	color: var(--kf-text);
	font-family: var(--kf-font-body);
	font-size: var(--kf-t-body);
	font-weight: 500;
	line-height: 1.5;
	letter-spacing: normal;
	overflow-x: hidden;
	text-rendering: optimizeLegibility;
	-webkit-font-smoothing: antialiased;
}

/* Anton ships a single weight. Anything that inherits body's 500 would be
   synthesised by the browser into a faux bold and lose its edges, so every
   display element states 400 and synthesis is refused outright. */
h1, h2, h3, h4,
.kf-hero__date,
.kf-countdown__value,
.kf-countdown__expired,
.kf-partners__title,
.kf-footer__line {
	font-weight: 400;
	font-synthesis: none;
}

/* Running text keeps normal spacing; only headings and small caps labels are
   tracked out. */
p, li, dd, dt, .kf-faq__answer, .kf-news__more {
	letter-spacing: normal;
}

img,
svg {
	max-width: 100%;
}

h1,
h2,
h3,
h4 {
	margin: 0;
	font-family: var(--kf-font-display);
	font-weight: 400;
	line-height: 0.98;
	letter-spacing: 0.005em;
	text-transform: uppercase;
}

p {
	margin: 0 0 0.8em;
}

ul,
ol {
	margin: 0;
	padding: 0;
	list-style: none;
}

a {
	color: var(--kf-gold);
}

:focus-visible {
	outline: 3px solid var(--kf-gold);
	outline-offset: 3px;
	border-radius: 4px;
}

[hidden] {
	display: none !important;
}

.screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.kf-skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 300;
	padding: 0.7rem 1.2rem;
	background: var(--kf-white);
	color: var(--kf-royal);
	font-weight: 700;
}

.kf-skip-link:focus {
	left: 0.5rem;
	top: 0.5rem;
}

.kf-container {
	width: 100%;
	max-width: var(--kf-container);
	margin-inline: auto;
	padding-inline: clamp(1rem, 3.5vw, 2.5rem);
}

.kf-placeholder-text {
	color: var(--kf-text-dim);
	font-style: italic;
}

/* Supplied gold crown ornament, used at eyebrow and card scale */
.kf-crown {
	width: auto;
	height: 1.35em;
	flex: none;
	object-fit: contain;
}

.kf-eyebrow {
	display: flex;
	align-items: center;
	gap: 0.45rem;
	margin: 0 0 0.35rem;
	color: var(--kf-orange);
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-small);
	font-weight: 700;
	letter-spacing: 0.18em;
	text-transform: uppercase;
}

.kf-eyebrow--center {
	justify-content: center;
}

.kf-title {
	font-size: var(--kf-t-h2);
	color: var(--kf-white);
	text-shadow: 0 3px 0 rgba(1, 8, 37, 0.5), 0 10px 26px rgba(1, 8, 37, 0.6);
}

.kf-title--center {
	text-align: center;
}

.kf-badge {
	display: inline-block;
	padding: 0.14rem 0.45rem;
	border-radius: 0.25rem;
	background: #3B2500;
	color: #FFD68A;
	font-family: var(--kf-font-cond);
	font-size: 0.62rem;
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	vertical-align: middle;
}

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */

.kf-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.7rem;
	min-height: 2.85rem;
	padding: 0.6rem 1.6rem;
	border: 0;
	border-radius: var(--kf-radius);
	background: linear-gradient(180deg, #FF8127 0%, var(--kf-orange) 55%, var(--kf-orange-deep) 100%);
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	font-size: clamp(1rem, 0.9rem + 0.36vw, 1.22rem);
	font-weight: 700;
	letter-spacing: 0.07em;
	line-height: 1;
	text-decoration: none;
	text-transform: uppercase;
	white-space: nowrap;
	cursor: pointer;
	box-shadow: 0 6px 20px rgba(255, 106, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.3);
	transition: transform 0.16s ease, box-shadow 0.16s ease, filter 0.16s ease;
}

.kf-button:hover,
.kf-button:focus-visible {
	filter: brightness(1.08);
	transform: translateY(-1px);
}

.kf-button--lg {
	min-height: 3.3rem;
	padding: 0.8rem 2.3rem;
	font-size: clamp(1.2rem, 1.05rem + 0.45vw, 1.4rem);
}

.kf-button--navy {
	background: linear-gradient(180deg, #0A2A7A 0%, #04154A 100%);
	box-shadow: none;
}

/* In the open mobile menu the header pill would drop to 16px, below the size
   at which 3:1 is the right floor for white on this orange. The floor keeps it
   large enough there; the desktop size is unchanged. */
.kf-ticket-cta[data-kf-ticket="header"] {
	min-height: 48px;
	padding-inline: 26px;
	font-size: clamp(1.2rem, 1rem + 0.5vw, 1.22rem);
}

.kf-ticket-cta[data-kf-ticket="hero"] {
	min-height: 50px;
	padding-inline: 2.3rem;
}

.kf-ticket-cta {
	background: #E85B00;
	background-image: none;
	color: #FFFFFF;
	box-shadow: 0 6px 22px rgba(232, 91, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.28);
}

/* Brighter on hover, and on focus as well so a keyboard user sees the same
   response a pointer gets, on top of the page's gold focus ring. */
.kf-ticket-cta:hover,
.kf-ticket-cta:focus-visible {
	background: #F86609;
	filter: none;
	box-shadow: 0 10px 28px rgba(255, 122, 20, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}

/* A dark halo under the gold ring, so the focus state is equally visible on
   the orange pill and on the navy behind it. */
.kf-ticket-cta:focus-visible {
	outline: 3px solid var(--kf-gold);
	outline-offset: 3px;
	box-shadow:
		0 0 0 7px rgba(1, 8, 37, 0.75),
		0 10px 28px rgba(255, 122, 20, 0.55),
		inset 0 1px 0 rgba(255, 255, 255, 0.4);
}

/* Sales not open, sold out or closed: same geometry, no link. The pill keeps
   its colour; only the pointer says it cannot be clicked yet. */
.kf-button--unavailable {
	cursor: default;
}

.kf-button--unavailable .kf-crown {
	opacity: 0.65;
}

.kf-button .kf-crown {
	height: 1.25em;
}

.kf-button .kf-play-glyph {
	flex: none;
	color: var(--kf-white);
}

.kf-ticket-note {
	max-width: 34rem;
	margin: 0.6rem 0 0;
	color: var(--kf-text-dim);
	font-size: var(--kf-t-small);
}

/* --------------------------------------------------------------------------
   Header — transparent over the hero, compact navy once scrolled
   -------------------------------------------------------------------------- */

.kf-header {
	position: fixed;
	inset: auto 0 auto 0;
	z-index: 200;
	/* Carries the navigation on its own, so the links need no text-shadow. */
	background: linear-gradient(180deg, rgba(2, 13, 56, 0.92) 0%, rgba(2, 13, 56, 0.55) 55%, rgba(2, 13, 56, 0) 100%);
	transition: background-color 0.2s ease, box-shadow 0.2s ease;
}

.kf-header.is-scrolled {
	background: rgba(2, 13, 56, 0.97);
	box-shadow: 0 2px 18px rgba(1, 8, 37, 0.6);
}

.kf-header__inner {
	display: flex;
	align-items: center;
	gap: clamp(1rem, 2.5vw, 2.5rem);
	/* Wider than the page's content column: the brand sits on the left edge of
	   this box and the ticket pill on the right, with the links between them. */
	width: calc(100% - 64px);
	max-width: 1320px;
	min-height: var(--kf-header-h);
	margin-inline: auto;
	padding-block: 0.55rem;
	padding-inline: 0;
}

.kf-header__brand {
	/* Brand, navigation and ticket button share one vertical centre line. The
	   minimum height is the tap target, not the text. */
	display: flex;
	align-items: center;
	min-height: 44px;
	flex: 0 1 auto;
	min-width: 0;
	text-decoration: none;
}

.kf-header__logo {
	display: block;
	width: auto;
	height: 4.5rem;
	max-width: 100%;
}

.kf-nav {
	display: flex;
	flex: 1 1 auto;
	align-items: center;
	justify-content: flex-end;
	gap: clamp(1rem, 2.5vw, 2.5rem);
	min-width: 0;
}

/* The link row takes the space between brand and pill, so the gap on either
   side of it is the same clamp as the gap between brand and navigation. */
.kf-nav__list {
	flex: 1 1 auto;
}

/* Evenly distributed across the space between brand and CTA, and never
   allowed to wrap over the hero. */
.kf-nav__list {
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	justify-content: center;
	gap: 24px;
	white-space: nowrap;
}

.kf-nav__link {
	display: inline-block;
	padding: 0.4rem 0.2rem;
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	font-size: clamp(0.94rem, 0.78rem + 0.42vw, 1.1rem);
	font-weight: 600;
	letter-spacing: 0.09em;
	text-decoration: none;
	text-transform: uppercase;
	transition: color 0.15s ease;
}

.kf-nav__link:hover {
	color: var(--kf-gold);
}

.kf-nav-toggle {
	display: none;
	align-items: center;
	gap: 0.5rem;
	min-height: 2.6rem;
	margin-left: auto;
	padding: 0.45rem 0.85rem;
	border: 1px solid rgba(255, 255, 255, 0.45);
	border-radius: var(--kf-radius);
	background: rgba(2, 13, 56, 0.72);
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	font-size: 0.95rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	cursor: pointer;
}

.kf-nav-toggle__bars {
	display: grid;
	gap: 3px;
	width: 17px;
}

.kf-nav-toggle__bars span {
	display: block;
	height: 2px;
	border-radius: 2px;
	background: currentColor;
}

/* Phones only, matching the width at which the hero switches to the tall
   artwork: there the lockup is enormous and sits directly below the header, so
   the header repeats it. The menu button keeps its own margin-left: auto and
   stays where it was. */
@media (max-width: 47.99rem) {
	.kf-header__brand {
		display: none;
	}
}

@media (max-width: 63.99rem) {
	.kf-nav-toggle {
		display: inline-flex;
	}

	.kf-header__inner {
		position: relative;
		flex-wrap: wrap;
	}

	.kf-nav {
		position: absolute;
		left: 0;
		right: 0;
		top: 100%;
		display: none;
		flex-direction: column;
		align-items: stretch;
		padding: 0.75rem clamp(1rem, 3.5vw, 2.5rem) 1.2rem;
		background: rgba(2, 13, 56, 0.98);
		border-bottom: 2px solid var(--kf-orange);
	}

	.kf-nav.is-open {
		display: flex;
	}

	.kf-nav__list {
		flex-direction: column;
		align-items: stretch;
		gap: 0;
		margin-bottom: 0.85rem;
	}

	.kf-nav__link {
		display: block;
		padding: 0.7rem 0.2rem;
		border-bottom: 1px solid rgba(255, 255, 255, 0.12);
		font-size: 1.05rem;
	}

	.kf-nav__cta .kf-button {
		width: 100%;
	}
}

/* --------------------------------------------------------------------------
   Opening — the aftermovie behind the name, the date and the ticket button

   V2. The film fills the opening; the name, the dates and KOOP TICKETS sit
   over it. A still frame paints first and stays until the loop is playing,
   so the page never waits for video. The two events straddle the lower edge
   and reach into the countdown below, so the opening does not end on a line.
   -------------------------------------------------------------------------- */

:root {
	--kf-events-overlap: clamp(3.2rem, 7vw, 5.25rem);
}

.kf-hero {
	position: relative;
	/* Above the countdown, so the event cards can reach into it instead of
	   being painted over by it. */
	z-index: 2;
	isolation: isolate;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	/* Short enough that both event cards are on screen before any scroll. */
	min-height: clamp(34rem, 78svh, 52rem);
	padding-top: var(--kf-header-h);
	background: var(--kf-navy-deep);
	text-align: center;
}

.kf-hero__stage {
	position: absolute;
	inset: 0;
	z-index: -1;
	overflow: hidden;
}

.kf-hero__poster,
.kf-hero__poster-image,
.kf-hero__loop {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 50% 42%;
}

/* A slow drift, so even the still frame is alive. */
.kf-hero__poster-image,
.kf-hero__loop {
	animation: kf-hero-drift 26s ease-in-out infinite alternate;
	transform-origin: 50% 40%;
}

@keyframes kf-hero-drift {
	from { transform: scale(1.02); }
	to   { transform: scale(1.09); }
}

.kf-hero__loop {
	opacity: 0;
	transition: opacity 0.9s ease;
}

.kf-hero.is-playing .kf-hero__loop {
	opacity: 1;
}

/* The event's colour of light over the footage, crossfaded on a change. */
.kf-hero__light {
	position: absolute;
	inset: 0;
	transition: opacity 0.9s ease;
	pointer-events: none;
}

.kf-hero__light--nacht {
	background:
		radial-gradient(60% 55% at 22% 30%, rgba(40, 96, 255, 0.46) 0%, rgba(40, 96, 255, 0) 70%),
		radial-gradient(50% 50% at 82% 20%, rgba(138, 64, 255, 0.34) 0%, rgba(138, 64, 255, 0) 70%);
	mix-blend-mode: screen;
}

.kf-hero__light--dag {
	opacity: 0;
	background:
		radial-gradient(60% 55% at 78% 26%, rgba(255, 150, 20, 0.46) 0%, rgba(255, 150, 20, 0) 70%),
		radial-gradient(50% 50% at 18% 18%, rgba(255, 205, 70, 0.3) 0%, rgba(255, 205, 70, 0) 70%);
	mix-blend-mode: screen;
}

:root[data-kf-event="dag"] .kf-hero__light--nacht { opacity: 0; }
:root[data-kf-event="dag"] .kf-hero__light--dag   { opacity: 1; }

/* Dark enough at the top for the header, open in the middle for the film,
   and fully navy at the foot so the cards and the countdown grow out of it. */
.kf-hero__veil {
	position: absolute;
	inset: 0;
	background: linear-gradient(
		180deg,
		rgba(1, 8, 37, 0.8) 0%,
		rgba(1, 8, 37, 0.3) 18%,
		rgba(1, 8, 37, 0.24) 38%,
		rgba(1, 8, 37, 0.58) 62%,
		rgba(1, 8, 37, 0.9) 82%,
		var(--kf-navy-deep) 100%
	);
}

.kf-hero__inner {
	position: relative;
	z-index: 1;
	padding-top: clamp(1.5rem, 4vw, 3rem);
	padding-bottom: clamp(1.4rem, 3vw, 2.2rem);
}

.kf-hero__logo {
	display: block;
	width: clamp(14rem, 22vw, 19.5rem);
	height: auto;
	margin: 0 auto;
	filter: drop-shadow(0 14px 38px rgba(1, 8, 37, 0.65));
}

.kf-hero__facts {
	margin: clamp(0.8rem, 2vw, 1.4rem) 0 0;
}

.kf-hero__date {
	margin: 0;
	color: var(--kf-white);
	font-family: var(--kf-font-display);
	font-size: var(--kf-t-date);
	letter-spacing: 0.005em;
	line-height: 1.02;
	text-transform: uppercase;
	text-shadow: 0 0.045em 0.015em rgba(1, 8, 37, 0.95), 0 0.09em 0.3em rgba(1, 8, 37, 0.9);
}

.kf-hero__where {
	margin: 0.45rem 0 0;
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	font-size: clamp(1rem, 0.78rem + 0.95vw, 1.6rem);
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	text-shadow: 0 2px 12px rgba(1, 8, 37, 0.9);
}

.kf-hero__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 0.8rem 1.6rem;
	margin-top: clamp(1.1rem, 2.4vw, 1.7rem);
	scroll-margin-top: calc(var(--kf-header-h) + 1rem);
}

/* The aftermovie opens from the moving picture itself: this link lies over the
   whole opening, behind the words and the buttons, so a click anywhere on the
   film plays it. It shows nothing of its own; the menu carries the word. */
.kf-hero__film {
	position: absolute;
	inset: 0;
	z-index: 0;
	display: block;
	cursor: pointer;
}

.kf-hero__film:focus-visible {
	outline: 3px solid var(--kf-gold);
	outline-offset: -8px;
}

/* The words and the ticket button sit above the link and stay clickable; the
   space around them belongs to the film. */
.kf-hero__inner {
	position: relative;
	z-index: 1;
	pointer-events: none;
}

.kf-hero__inner a,
.kf-hero__inner button {
	pointer-events: auto;
}

/* On the front page the opening carries the logo, large. The header's small
   copy waits until the opening has scrolled away, then fades in. */
.home .kf-header__brand {
	transition: opacity 0.35s ease, visibility 0.35s ease;
}

.home .kf-header:not(.is-scrolled) .kf-header__brand {
	opacity: 0;
	visibility: hidden;
}

/* --- The two events -------------------------------------------------- */

.kf-events {
	position: relative;
	z-index: 2;
	margin-bottom: calc(-1 * var(--kf-events-overlap));
}

.kf-events__title {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: center;
	gap: 0 0.7rem;
	margin: 0 0 clamp(0.6rem, 1.4vw, 0.9rem);
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	text-transform: uppercase;
}

.kf-events__title-line {
	font-size: var(--kf-t-small);
	font-weight: 700;
	letter-spacing: 0.22em;
}

.kf-events__title-sub {
	color: var(--kf-gold);
	font-size: var(--kf-t-small);
	font-weight: 700;
	letter-spacing: 0.22em;
}

.kf-events__title-sub::before {
	content: "·";
	margin-right: 0.7rem;
	color: rgba(255, 255, 255, 0.55);
}

.kf-events__list {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: clamp(0.6rem, 2vw, 1.4rem);
	max-width: 58rem;
	margin: 0 auto;
}

.kf-event {
	--kf-accent: #7CC0FF;
	--kf-accent-glow: rgba(40, 110, 255, 0.55);

	position: relative;
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	align-items: stretch;
	min-width: 0;
	margin: 0;
	padding: 0;
	overflow: hidden;
	border: 2px solid rgba(255, 255, 255, 0.16);
	border-radius: var(--kf-radius-lg);
	background: rgba(2, 13, 56, 0.78);
	color: var(--kf-white);
	font: inherit;
	text-align: left;
	cursor: pointer;
	box-shadow: 0 18px 44px -18px rgba(0, 0, 0, 0.7);
	transition: transform 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease, background-color 0.35s ease;
	-webkit-backdrop-filter: blur(12px);
	backdrop-filter: blur(12px);
}

.kf-event--dag {
	--kf-accent: var(--kf-orange);
	--kf-accent-glow: rgba(255, 106, 0, 0.55);
}

.kf-event__media {
	position: relative;
	width: clamp(6rem, 13vw, 10.5rem);
	overflow: hidden;
}

.kf-event__photo {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	filter: saturate(0.45) brightness(0.72);
	transition: filter 0.45s ease, transform 0.6s ease;
}

.kf-event__body {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 0.3rem;
	min-width: 0;
	padding: clamp(0.85rem, 1.8vw, 1.35rem) clamp(0.9rem, 1.8vw, 1.4rem);
}

.kf-event__name {
	font-family: var(--kf-font-display);
	font-size: clamp(1.5rem, 1rem + 1.9vw, 2.7rem);
	letter-spacing: 0.01em;
	line-height: 1;
	text-transform: uppercase;
}

.kf-event__date {
	color: var(--kf-text);
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-small);
	font-weight: 600;
	letter-spacing: 0.08em;
	line-height: 1.2;
	text-transform: uppercase;
}

/* The hours sit under the date, a shade quieter. */
.kf-event__hours {
	display: block;
	margin-top: 0.15rem;
	color: rgba(198, 216, 248, 0.92);
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-small);
	font-weight: 600;
	letter-spacing: 0.06em;
	line-height: 1.2;
}

.kf-event__mark {
	position: absolute;
	top: clamp(0.5rem, 1vw, 0.75rem);
	left: clamp(0.5rem, 1vw, 0.75rem);
	background: rgba(2, 13, 56, 0.55);
	display: grid;
	place-items: center;
	width: 1.9rem;
	height: 1.9rem;
	border: 2px solid rgba(255, 255, 255, 0.45);
	border-radius: 50%;
	color: transparent;
	transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}

.kf-event__mark svg {
	width: 1.15rem;
	height: 1.15rem;
}

.kf-event:hover {
	border-color: rgba(255, 255, 255, 0.4);
}

.kf-event:hover .kf-event__photo {
	filter: saturate(0.75) brightness(0.85);
	transform: scale(1.04);
}

.kf-event:focus-visible {
	outline: 3px solid var(--kf-gold);
	outline-offset: 3px;
}

/* The chosen event is unmistakable: its own colour of light, full colour in
   the photograph, a raised card and a filled mark. Not colour alone. */
.kf-event[aria-pressed="true"] {
	border-color: var(--kf-accent);
	background: rgba(2, 13, 56, 0.9);
	box-shadow:
		0 0 0 1px var(--kf-accent),
		0 22px 55px -14px var(--kf-accent-glow),
		inset 0 0 38px -18px var(--kf-accent-glow);
	transform: translateY(-5px);
}

.kf-event[aria-pressed="true"] .kf-event__photo {
	filter: none;
}

.kf-event[aria-pressed="true"] .kf-event__mark {
	border-color: var(--kf-accent);
	background: var(--kf-accent);
	color: var(--kf-navy-deep);
}

/* --- The film --------------------------------------------------------- */

.kf-film {
	width: min(92vw, 70rem);
	max-width: none;
	max-height: none;
	margin: auto;
	padding: 0;
	border: 0;
	background: transparent;
	color: var(--kf-white);
	overflow: visible;
}

.kf-film::backdrop {
	background: rgba(1, 6, 26, 0.9);
	-webkit-backdrop-filter: blur(6px);
	backdrop-filter: blur(6px);
}

.kf-film__frame {
	position: relative;
	overflow: hidden;
	border-radius: var(--kf-radius-lg);
	background: #000;
	box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
	aspect-ratio: 16 / 9;
}

.kf-film__video {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
	background: #000;
}

.kf-film__bar {
	display: flex;
	justify-content: flex-end;
	margin-top: 0.8rem;
}

.kf-film__close {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	min-height: 44px;
	padding: 0.4rem 1.1rem;
	border: 2px solid rgba(255, 255, 255, 0.75);
	border-radius: 2rem;
	background: transparent;
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-body);
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	cursor: pointer;
}

.kf-film__close svg {
	width: 1rem;
	height: 1rem;
}

.kf-film__close:hover,
.kf-film__close:focus-visible {
	border-color: var(--kf-gold);
	color: var(--kf-gold);
	outline: none;
}

/* --- Phone ----------------------------------------------------------- */

@media (max-width: 47.99rem) {
	:root {
		--kf-events-overlap: 2.6rem;
	}

	.kf-hero {
		min-height: clamp(34rem, 86svh, 48rem);
	}

	.kf-hero__logo {
		width: 12.5rem;
	}

	.kf-hero__inner {
		padding-top: 0.5rem;
	}

	.kf-hero__poster,
	.kf-hero__poster-image,
	.kf-hero__loop {
		object-position: 50% 35%;
	}

	.kf-hero__actions {
		flex-direction: column;
		gap: 0.5rem;
	}

	.kf-events__list {
		gap: 0.55rem;
	}

	.kf-event {
		grid-template-columns: minmax(0, 1fr);
		grid-template-rows: auto 1fr;
	}

	.kf-event__media {
		width: auto;
		aspect-ratio: 2 / 1;
	}

	.kf-event__body {
		padding: 0.65rem 0.7rem 0.75rem;
	}

	.kf-event__name {
		font-size: clamp(1.25rem, 0.7rem + 3vw, 1.6rem);
	}

	.kf-event__date,
	.kf-event__hours {
		font-size: var(--kf-t-micro);
		letter-spacing: 0.04em;
	}

	.kf-event__mark {
		top: 0.45rem;
		left: 0.45rem;
		width: 1.65rem;
		height: 1.65rem;
	}

	.kf-event[aria-pressed="true"] {
		transform: translateY(-3px);
	}
}

@media (prefers-reduced-motion: reduce) {
	.kf-hero__poster-image,
	.kf-hero__loop {
		animation: none;
		transform: none;
	}

	.kf-event,
	.kf-event__photo,
	.kf-hero__light,
	.kf-hero__loop {
		transition: none;
	}

	.kf-event[aria-pressed="true"] {
		transform: none;
	}
}

/* On-page ticket state, in place of a fake checkout */
.kf-ticket-pending {
	position: relative;
	z-index: 2;
	padding: 0.55rem 0;
	background: linear-gradient(90deg, rgba(255, 106, 0, 0.24) 0%, rgba(255, 176, 0, 0.3) 50%, rgba(255, 106, 0, 0.24) 100%);
	border-top: 1px solid rgba(255, 176, 0, 0.5);
	border-bottom: 1px solid rgba(255, 176, 0, 0.5);
	text-align: center;
}

.kf-ticket-pending:target,
.kf-ticket-pending:focus {
	background: rgba(255, 176, 0, 0.32);
	outline: none;
}

.kf-ticket-pending__inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 0.4rem 1rem;
}

.kf-ticket-pending__title {
	margin: 0;
	color: var(--kf-gold);
	font-family: var(--kf-font-display);
	font-size: var(--kf-t-card);
	letter-spacing: 0.02em;
	text-transform: uppercase;
}

.kf-ticket-pending__body {
	max-width: 34rem;
	margin: 0;
	color: var(--kf-white);
	font-size: var(--kf-t-small);
}

.kf-ticket-pending .kf-button {
	min-height: 2.25rem;
	padding: 0.35rem 1rem;
	font-size: var(--kf-t-small);
}

/* --------------------------------------------------------------------------
   Blue ribbons — countdown and agenda
   -------------------------------------------------------------------------- */

.kf-band {
	position: relative;
	isolation: isolate;
	padding: clamp(1.5rem, 3vw, 2.8rem) 0;
	background:
		radial-gradient(120% 220% at 50% 50%, #0A55D8 0%, var(--kf-royal) 45%, #002A80 100%);
	overflow: hidden;
	box-shadow: inset 0 1px 0 rgba(120, 190, 255, 0.85), inset 0 -1px 0 rgba(120, 190, 255, 0.85);
}

/* Electric-blue inner glow along both edges of the ribbon */
.kf-band::before,
.kf-band::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	height: 3.5rem;
	pointer-events: none;
}

.kf-band::before {
	top: 0;
	background: linear-gradient(180deg, rgba(6, 123, 255, 0.55) 0%, rgba(6, 123, 255, 0) 100%);
}

.kf-band::after {
	bottom: 0;
	background: linear-gradient(0deg, rgba(6, 123, 255, 0.5) 0%, rgba(6, 123, 255, 0) 100%);
}

/* The event cards reach down into the countdown; it makes room for them.
   Its top no longer starts on a ruled line: the royal blue rises out of the
   opening's navy behind the cards, so the two read as one space. */
.kf-band--countdown {
	padding-top: calc(clamp(1.5rem, 3vw, 2.8rem) + var(--kf-events-overlap));
	background:
		linear-gradient(180deg, var(--kf-navy-deep) 0%, rgba(1, 8, 37, 0) calc(var(--kf-events-overlap) + 3.5rem)),
		radial-gradient(120% 220% at 50% 62%, #0A55D8 0%, var(--kf-royal) 45%, #002A80 100%);
	box-shadow: inset 0 -1px 0 rgba(120, 190, 255, 0.85);
}

.kf-band--countdown::before {
	display: none;
}

.kf-band__confetti {
	position: absolute;
	/* The opening lies over the top of this band (the event cards), so the
	   ribbons start below its edge instead of being cut off by it. */
	top: var(--kf-events-overlap, 0px);
	width: auto;
	height: calc(100% - var(--kf-events-overlap, 0px));
	opacity: 0.32;
	transform: none;
	pointer-events: none;
	z-index: -1;
}

.kf-band__confetti--left {
	left: -1rem;
}

.kf-band__confetti--right {
	right: -1rem;
	transform: scaleX(-1);
}

/* --- Countdown ------------------------------------------------------- */

.kf-countdown {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: clamp(0.6rem, 1.6vw, 1.7rem);
}

/* Nothing sits beside them any more, so the four boxes are the band. */
.kf-countdown__units {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	width: 100%;
	gap: clamp(0.4rem, 1.6vw, 1.6rem);
}

.kf-countdown__unit {
	width: clamp(5rem, 14vw, 13rem);
	min-width: 0;
	padding: clamp(0.55rem, 1.2vw, 1.1rem) clamp(0.5rem, 1.1vw, 1.1rem);
	border: 3px solid rgba(170, 220, 255, 1);
	border-radius: 0.7rem;
	background: rgba(0, 26, 92, 0.55);
	box-shadow:
		0 0 22px rgba(6, 123, 255, 0.9),
		0 0 46px rgba(6, 123, 255, 0.45),
		inset 0 0 24px rgba(6, 123, 255, 0.5);
	text-align: center;
}

.kf-countdown__value {
	display: block;
	color: var(--kf-white);
	font-family: var(--kf-font-display);
	font-size: var(--kf-t-count);
	font-variant-numeric: tabular-nums;
	line-height: 1;
}

.kf-countdown__name {
	display: block;
	margin-top: 0.15em;
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	font-size: clamp(0.79rem, 0.68rem + 0.35vw, 0.95rem);
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

.kf-countdown__summary {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.kf-countdown__expired {
	margin: 0;
	color: var(--kf-white);
	font-family: var(--kf-font-display);
	font-size: var(--kf-t-h3);
	text-align: center;
	text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   Sections
   -------------------------------------------------------------------------- */

.kf-section {
	position: relative;
	isolation: isolate;
	padding: var(--kf-band) 0;
	overflow: hidden;
}

/* Equal blue above and below the video, and a taller section than the
   default band gives, so the composition sits in the middle of its own space. */
.kf-section--aftermovie {
	padding-block: clamp(2.2rem, 1.3rem + 3.4vw, 5rem);
}

.kf-section--navy {
	background: radial-gradient(95% 130% at 50% 0%, #06266E 0%, var(--kf-navy) 62%, var(--kf-navy-deep) 100%);
}

.kf-section--royal {
	background: radial-gradient(80% 120% at 50% 40%, #0A55D8 0%, var(--kf-royal) 32%, #011C5E 76%, var(--kf-navy) 100%);
}

/* Built from the photograph rather than around it. The tower's sky measures
   #02061C at the sides and top, so the ground it fades into is that tone; its
   lit base measures #031C57, which the radial picks up where the tower stands.
   The band closes on --kf-navy, the colour the partners row opens with. */
.kf-section--info {
	background:
		radial-gradient(44% 58% at 50% 97%, rgba(6, 76, 190, 0.5) 0%, rgba(3, 28, 87, 0) 72%),
		linear-gradient(180deg, #02071E 0%, #030E30 52%, var(--kf-navy) 100%);
}

.kf-section__head {
	margin-bottom: clamp(0.8rem, 1.5vw, 1.35rem);
}

.kf-section__head--center {
	text-align: center;
}

.kf-section__actions {
	display: flex;
	justify-content: center;
	margin-top: clamp(0.8rem, 1.5vw, 1.35rem);
}

/* --------------------------------------------------------------------------
   Aftermovie
   -------------------------------------------------------------------------- */

.kf-aftermovie {
	display: grid;
	gap: clamp(1.2rem, 3vw, 2.8rem);
	align-items: center;
}

@media (min-width: 64rem) {
	.kf-aftermovie {
		/* Video 56.5%, copy 36%, the remainder as the gutter between them. */
		grid-template-columns: 56.5% 36%;
		column-gap: 0;
		justify-content: space-between;
		align-items: center;
	}

	.kf-video {
		position: relative;
	}

	.kf-video__note {
		position: absolute;
		inset: 100% 0 auto 0;
	}
}

.kf-video {
	width: 100%;
	margin-inline: auto;
}

.kf-video__frame {
	position: relative;
	aspect-ratio: 16 / 9;
	overflow: hidden;
	border: 2px solid var(--kf-gold);
	border-radius: var(--kf-radius-lg);
	background: var(--kf-navy-deep);
	box-shadow: 0 18px 48px rgba(1, 8, 37, 0.8);
}

.kf-video__poster {
	width: 100%;
	height: 100%;
	display: block;
	object-fit: cover;
}

.kf-video__play {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	padding: 0;
	border: 0;
	background: transparent;
	color: var(--kf-white);
	cursor: pointer;
}

/* The site already has one shape for "press this": the orange pill. The play
   control carries that colour, so it belongs to the design instead of looking
   like a player badge dropped on the artwork. */
.kf-video__play-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: clamp(3.4rem, 5.6vw, 4.8rem);
	aspect-ratio: 1;
	border: 0;
	border-radius: 50%;
	background: #E85B00;
	color: var(--kf-white);
	box-shadow:
		0 0 0 6px rgba(232, 91, 0, 0.22),
		0 10px 30px rgba(1, 8, 37, 0.55);
	transition: transform 0.18s ease, background-color 0.18s ease, box-shadow 0.18s ease;
}

.kf-video__play:hover .kf-video__play-icon,
.kf-video__play:focus-visible .kf-video__play-icon {
	transform: scale(1.07);
	background: #F86609;
	box-shadow:
		0 0 0 9px rgba(248, 102, 9, 0.28),
		0 12px 34px rgba(1, 8, 37, 0.6);
}

.kf-video__play-icon svg {
	width: 32%;
	height: auto;
	/* The triangle's own centre of mass sits left of its bounding box. */
	margin-left: 8%;
}

/* The pending notice is plain text under the poster; as an overlay it
   covered the artwork it was describing. */
.kf-video__note.is-pulsing {
	animation: kf-pulse 0.9s ease;
}

@keyframes kf-pulse {
	0%, 100% { color: var(--kf-text-dim); }
	40% { color: var(--kf-gold); }
}

.kf-video__iframe,
.kf-video__file {
	display: block;
	width: 100%;
	height: 100%;
	border: 0;
	background: var(--kf-navy-deep);
}

/* cover, not the default contain: the frame's inner box rounds to 1.7864 while
   the file is 1.7778, and contain answered that with a dark sliver down both
   sides inside the gold rule. */
.kf-video__file {
	object-fit: cover;
	border-radius: calc(var(--kf-radius-lg) - 2px);
}

/* The player's controls live in a shadow tree. Tabbing lands first on the
   player and then inside its control bar, and neither :focus-visible nor
   :focus matches the host for that second stop — :focus-within does, so the
   ring stays on screen for both. */
.kf-video__file:focus,
.kf-video__file:focus-within,
.kf-video__file:focus-visible {
	outline: 3px solid var(--kf-gold);
	outline-offset: 3px;
}

.kf-video__note {
	margin: 0.7rem 0 0;
	color: var(--kf-text-dim);
	font-size: var(--kf-t-small);
	text-align: center;
}

.kf-aftermovie__title {
	font-size: clamp(2.1rem, 1.35rem + 3.2vw, 4rem);
	color: var(--kf-white);
	line-height: 0.94;
}

.kf-aftermovie__year {
	display: block;
	color: var(--kf-orange);
}

.kf-aftermovie__text {
	max-width: 26rem;
	margin: 0.8rem 0 1.3rem;
	color: var(--kf-text);
	font-size: var(--kf-t-body);
}

/* --------------------------------------------------------------------------
   Gallery — four frames, edge to edge, no gutters on desktop
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   Photo rows — two edge-to-edge strips, one drifting each way
   -------------------------------------------------------------------------- */

.kf-gallery {
	/* The rows are wider than the screen by design; the page must not scroll
	   sideways because of them. clip leaves the vertical axis alone. */
	overflow-x: clip;
	background: var(--kf-navy);
}

.kf-strip {
	position: relative;
	overflow: hidden;
}

.kf-strip:focus-visible {
	outline: 3px solid var(--kf-gold);
	outline-offset: -3px;
}

.kf-strip__track {
	display: flex;
	width: max-content;
	margin: 0;
	padding: 0;
	list-style: none;
	line-height: 0;
}

.kf-strip__item {
	flex: none;
	width: clamp(11rem, 21vw, 19rem);
	margin: 0;
	padding: 0;
}

.kf-strip__image {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 3;
	object-fit: cover;
}

/* Half the track is one full set of pictures, so moving by exactly -50% lands
   the copy where the original started. No jump, no gap. */
@keyframes kf-strip-left {
	from { transform: translate3d(0, 0, 0); }
	to   { transform: translate3d(-50%, 0, 0); }
}

@keyframes kf-strip-right {
	from { transform: translate3d(-50%, 0, 0); }
	to   { transform: translate3d(0, 0, 0); }
}

/* Movement belongs to pointers. A touch screen gets the swipeable version
   below instead, which is what a finger expects of a row of photographs. */
@media (hover: hover) and (pointer: fine) {
	.kf-strip__track {
		/* Roughly nine seconds per panel, so the row reads as drifting rather
		   than scrolling. */
		animation: kf-strip-left calc(var(--kf-strip-count) * 9s) linear infinite;
	}

	.kf-strip--right .kf-strip__track {
		animation-name: kf-strip-right;
	}

	.kf-strip:hover .kf-strip__track,
	.kf-strip:focus-within .kf-strip__track,
	.kf-strip:focus-visible .kf-strip__track {
		animation-play-state: paused;
	}
}

/* Touch: no movement of its own, a swipe with snapping instead. Written as
   two positive conditions rather than a negated query, which reads clearer and
   matches a coarse pointer even where a device also reports hover. */
@media (hover: none), (pointer: coarse) {
	.kf-strip {
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
	}

	.kf-strip::-webkit-scrollbar {
		display: none;
	}

	.kf-strip__item {
		scroll-snap-align: start;
	}

	/* The second lap only exists to make the animation seamless; with the
	   animation off it is eight more pictures to swipe past. */
	.kf-strip__item--lap {
		display: none;
	}
}

/* Anyone who has asked for less motion gets the still, swipeable version on
   every device. The global reduced-motion rule shortens animations to nothing,
   which would leave the track parked at -50%; this stops it starting at all. */
@media (prefers-reduced-motion: reduce) {
	.kf-strip__track {
		animation: none !important;
		transform: none !important;
	}

	.kf-strip {
		overflow-x: auto;
		scroll-snap-type: x mandatory;
	}

	.kf-strip__item {
		scroll-snap-align: start;
	}

	.kf-strip__item--lap {
		display: none;
	}
}

/* --------------------------------------------------------------------------
   Line-up — supplied silhouettes in an electric-blue neon frame
   -------------------------------------------------------------------------- */

.kf-lineup__grid {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: clamp(0.55rem, 1.1vw, 1.05rem);
}

@media (max-width: 63.99rem) {
	.kf-lineup__grid {
		grid-template-columns: repeat(3, 1fr);
	}
}

/* Two across on a phone, never one: a single column doubles the page height. */
@media (max-width: 47.99rem) {
	.kf-lineup__grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

.kf-artist {
	position: relative;
}

.kf-artist__frame {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	aspect-ratio: 4 / 6.2;
	padding: 0 0.3rem 1.3rem;
	border: 3px solid #3AA0FF;
	border-radius: 1.3rem;
	background: linear-gradient(180deg, rgba(0, 46, 146, 0.6) 0%, rgba(1, 22, 76, 0.82) 58%, rgba(1, 12, 46, 0.94) 100%);
	box-shadow:
		0 0 0 1px rgba(150, 210, 255, 0.55),
		0 0 26px rgba(6, 123, 255, 0.95),
		0 0 60px rgba(6, 123, 255, 0.45),
		inset 0 0 34px rgba(6, 123, 255, 0.32);
	overflow: hidden;
	text-align: center;
}

.kf-artist__media {
	position: absolute;
	/* Down to the frame's own edge: the busts are cut flat at the bottom, and
	   ending the box short of the edge left that cut showing as a dark bar. */
	inset: 0;
	z-index: 0;
	display: flex;
	align-items: flex-end;
	justify-content: center;
}

.kf-artist__silhouette {
	width: 112%;
	height: 100%;
	margin-inline: -6%;
	object-fit: contain;
	object-position: bottom center;
}

.kf-artist__image {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center top;
}

.kf-artist__name {
	position: relative;
	z-index: 1;
	margin: 0;
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	font-size: clamp(1.05rem, 0.86rem + 0.75vw, 1.5rem);
	font-weight: 700;
	letter-spacing: 0.06em;
	line-height: 1.05;
	text-transform: uppercase;
}

/* "Wordt bekendgemaakt" is three times the length of the name it replaces and
   would run past the card at the announced-artist size. Only this label steps
   down; the card, its frame, the silhouette and the label's position are all
   untouched. */
.kf-artist__name--pending {
	font-size: clamp(0.79rem, 0.58rem + 0.5vw, 0.98rem);
	letter-spacing: 0.04em;
	line-height: 1.08;
}

.kf-artist .kf-badge {
	position: absolute;
	left: 50%;
	top: 0.4rem;
	z-index: 3;
	transform: translateX(-50%);
}

/* --------------------------------------------------------------------------
   News
   -------------------------------------------------------------------------- */

.kf-news {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: clamp(0.7rem, 1.5vw, 1.35rem);
}

@media (max-width: 63.99rem) {
	.kf-news {
		grid-template-columns: repeat(2, 1fr);
	}
}

.kf-news__card {
	position: relative;
	display: flex;
	flex-direction: column;
	height: 100%;
	overflow: hidden;
	border: 2px solid rgba(255, 176, 0, 0.9);
	border-radius: var(--kf-radius-lg);
	background: var(--kf-royal);
	box-shadow: 0 14px 34px rgba(1, 8, 37, 0.65);
}

.kf-news__media {
	position: relative;
	aspect-ratio: 16 / 10;
	overflow: hidden;
	background: #01184C;
}

.kf-news__image {
	width: 100%;
	height: 100%;
	display: block;
	object-fit: cover;
}

.kf-news__media .kf-badge {
	position: absolute;
	right: 0.5rem;
	top: 0.5rem;
	z-index: 2;
}

.kf-news__tag {
	position: absolute;
	left: 0.6rem;
	top: 0.6rem;
	z-index: 2;
	padding: 0.2rem 0.6rem;
	border: 1px solid rgba(140, 205, 255, 0.9);
	border-radius: 0.3rem;
	background: rgba(0, 59, 174, 0.95);
	box-shadow: 0 0 12px rgba(6, 123, 255, 0.8);
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	font-size: 0.79rem;
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

.kf-news__body {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	padding: 0.85rem 1.05rem 0.95rem;
}

.kf-news__link {
	color: inherit;
	text-decoration: none;
}

/* Stretched over the card, so the whole card is the hit area while the link
   itself stays a single, properly named link for keyboard and screen reader. */
.kf-news__link::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

.kf-news__card:hover {
	border-color: var(--kf-white);
	box-shadow: 0 18px 40px rgba(1, 8, 37, 0.75);
}

.kf-news__card:hover .kf-news__more,
.kf-news__card:focus-within .kf-news__more {
	color: var(--kf-gold);
}

/* The ring stays on the link itself, which is the element that takes focus;
   the card answers with the same lift it gives a pointer. */
.kf-news__card:focus-within {
	border-color: var(--kf-white);
	box-shadow: 0 18px 40px rgba(1, 8, 37, 0.75);
}

.kf-news__title {
	margin: 0;
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-card);
	font-weight: 700;
	line-height: 1.06;
	text-transform: uppercase;
	/* Two lines reserved in every card, so the four headlines read as one row
	   and "Lees meer" lands on the same line across the grid. */
	min-height: 2.12em;
}

.kf-news__more {
	margin: auto 0 0;
	padding-top: 0.55rem;
	color: var(--kf-white);
	font-size: var(--kf-t-small);
	transition: color 0.15s ease;
}

/* --------------------------------------------------------------------------
   Newsletter — full-width vivid orange
   -------------------------------------------------------------------------- */

.kf-newsletter {
	padding: clamp(1.3rem, 2.8vw, 2.4rem) 0;
	background: var(--kf-orange);
}

.kf-newsletter__inner {
	display: grid;
	gap: clamp(1rem, 2.5vw, 2.5rem);
	align-items: center;
}

.kf-newsletter__inner > * {
	align-self: center;
	min-width: 0;
}

@media (min-width: 56rem) {
	.kf-newsletter__inner {
		/* 45 / 55 — the heading had been swamping a form half its size. */
		grid-template-columns: minmax(0, 45fr) minmax(0, 55fr);
		gap: clamp(1.5rem, 4vw, 3.5rem);
	}
}

.kf-newsletter__title {
	margin: 0;
	color: var(--kf-white);
	font-size: clamp(1.6rem, 1.1rem + 2.3vw, 3rem);
	line-height: 1;
	text-transform: uppercase;
}

.kf-newsletter__lead {
	max-width: 28rem;
	margin: 0.6rem 0 0;
	color: rgba(255, 255, 255, 0.97);
	font-size: var(--kf-t-body);
	font-weight: 500;
}

.kf-newsletter__notice {
	margin: 0.65rem 0 0;
	padding: 0.5rem 0.7rem;
	border-left: 3px solid var(--kf-white);
	background: rgba(0, 0, 0, 0.2);
	color: var(--kf-white);
	font-size: var(--kf-t-small);
}

.kf-form,
.kf-form fieldset {
	min-width: 0;
}

.kf-form__group {
	display: flex;
	flex-wrap: wrap;
	align-items: stretch;
	min-width: 0;
	border-radius: var(--kf-radius);
	background: var(--kf-white);
	box-shadow: 0 8px 22px rgba(120, 50, 0, 0.3);
	overflow: hidden;
}

.kf-form__input {
	flex: 1 1 9rem;
	min-width: 0;
	width: 100%;
	height: 3.75rem;
	padding: 0.6rem 1.15rem;
	border: 0;
	background: transparent;
	color: #0B1226;
	font-family: var(--kf-font-body);
	font-size: clamp(1.05rem, 1rem + 0.3vw, 1.3rem);
}

.kf-form__input::placeholder {
	color: #66708A;
}

.kf-form__submit {
	flex: none;
	height: 3.75rem;
	min-height: 0;
	padding-inline: clamp(1.3rem, 2.4vw, 2.2rem);
	border-radius: 0;
	background: linear-gradient(180deg, #06246B 0%, #02133F 100%);
	box-shadow: none;
	font-size: clamp(1rem, 0.92rem + 0.32vw, 1.24rem);
}

/* Disabled while no mailing provider is connected. The pointer said the
   opposite. */
.kf-form__submit:disabled {
	cursor: not-allowed;
}

/* The answer to a signup, on the orange band itself.
   Both tones are readable against that orange: the confirmation in the deep
   navy the band already uses, the refusal on a white plate so it cannot be
   mistaken for part of the decoration. */
.kf-form__result {
	grid-column: 1 / -1;
	margin: 0.75rem 0 0;
	padding: 0.6rem 0.9rem;
	border-radius: var(--kf-radius);
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-small);
	font-weight: 600;
	letter-spacing: 0.02em;
	line-height: 1.35;
}

.kf-form__result--ok {
	background: rgba(2, 13, 56, 0.92);
	color: var(--kf-white);
}

.kf-form__result--fout {
	background: var(--kf-white);
	color: #8A2B00;
}

/* This one sits flush inside the white field group, so the shared 1px lift on
   hover uncovered a white line under it. It brightens instead of moving. */
.kf-form__submit:hover,
.kf-form__submit:focus-visible {
	transform: none;
	filter: none;
	background: linear-gradient(180deg, #0A3392 0%, #041B57 100%);
}

/* Phone: field and button stack full width rather than squeezing. */
@media (max-width: 34rem) {
	.kf-form__group {
		background: transparent;
		box-shadow: none;
		gap: 0.6rem;
	}

	.kf-form__input {
		border-radius: var(--kf-radius);
		background: var(--kf-white);
		box-shadow: 0 8px 22px rgba(120, 50, 0, 0.28);
	}

	.kf-form__submit {
		width: 100%;
		border-radius: var(--kf-radius);
	}
}

.kf-form__consent {
	display: flex;
	align-items: flex-start;
	gap: 0.6rem;
	margin-top: 0.85rem;
	color: rgba(255, 255, 255, 0.94);
	font-size: var(--kf-t-small);
	font-weight: 500;
	cursor: pointer;
}

.kf-form__checkbox {
	flex: none;
	width: 1.5rem;
	height: 1.5rem;
	margin-top: 0.05rem;
	accent-color: #02133F;
}

.kf-form__consent a {
	color: var(--kf-white);
	text-decoration: underline;
}

.kf-form__legal {
	margin: 0.4rem 0 0;
	color: rgba(255, 255, 255, 0.92);
	font-size: var(--kf-t-micro);
}

.kf-form__honeypot {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* --------------------------------------------------------------------------
   FAQ and house rules, composed around the supplied tower photograph
   -------------------------------------------------------------------------- */

.kf-info {
	display: grid;
	gap: clamp(1.2rem, 3vw, 2rem);
	align-items: start;
}

/* The supplied 2027 artwork — tower, flag, crown, stage, disco ball — whole,
   standing in the gutter between the two columns on the section's own night
   blue. The artwork itself is cut off at its foot, so it stands on the horizon
   line between this section and the partners, where the cut reads as ground.
   It is a fixed size, so opening a list never resizes it.

   Only on a wide screen. Stacked on a tablet or a phone there is no gutter to
   stand in, and behind the lists it could only read as a smudge. */
:root {
	--kf-tower-w: clamp(15rem, 20vw, 21rem);
	--kf-tower-h: calc(var(--kf-tower-w) / 0.5625);
}

.kf-info__tower {
	display: none;
	order: 2;
}

@media (min-width: 64rem) {
	.kf-info {
		/* Tall enough for the whole artwork, which hangs from the line below. */
		min-height: calc(var(--kf-tower-h) - var(--kf-band));
		position: relative;
		/* The two columns span the container, like every other section; the
		   gutter between them is where the artwork stands. */
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
		column-gap: clamp(12rem, 21vw, 21rem);
		align-items: start;
	}

	.kf-info__col {
		position: relative;
		z-index: 1;
	}

	/* Out of the flow, so it never sets the section height. */
	.kf-info__tower {
		display: block;
		position: absolute;
		left: 50%;
		bottom: calc(var(--kf-band) * -1);
		z-index: 0;
		width: var(--kf-tower-w);
		height: var(--kf-tower-h);
		transform: translateX(-50%);
		pointer-events: none;
	}

	.kf-info__tower-image {
		display: block;
		width: 100%;
		height: 100%;
		object-fit: contain;
	}
}

/* Stacked, practical information and questions are two separate subjects,
   and the space between them has to say so: roughly three times the gap
   between sibling cards. */
@media (max-width: 63.99rem) {
	.kf-info {
		row-gap: clamp(2.75rem, 9vw, 4rem);
	}
}



/* Stacked below the two-column breakpoint: practical information, tower,
   questions. The tower carries order 2 of its own. */
.kf-info__col--practical {
	order: 1;
}

.kf-info__col--faq {
	order: 3;
}

/* The heading carries the old #faq anchor. It sits inside the section's own
   padding, so scrolling to it left the band's top edge tucked under the fixed
   header; this offsets it by exactly that padding. Nothing renders
   differently — the heading is hidden either way. */
.kf-section--info > .screen-reader-text {
	scroll-margin-top: var(--kf-band);
}

/* One line where a list of unconfirmed questions or rules used to be. It
   keeps the row's own surface so the two columns still read as a pair. */
.kf-info__pending {
	margin: 0;
	padding: 0.9rem 1rem;
	border: 1px solid rgba(120, 180, 255, 0.35);
	border-radius: 0.5rem;
	background: rgba(0, 32, 104, 0.55);
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-body);
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.kf-info__title {
	margin: 0 0 0.9rem;
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-h3);
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

.kf-info__badge {
	margin: 0.6rem 0 0;
}

/* "Alle vragen" is a quiet line rather than a second orange button, set to the
   right so it clears the artwork in the middle of the band. */
.kf-info__actions {
	display: flex;
	justify-content: flex-end;
	margin-top: 0.9rem;
}

.kf-info__more {
	padding: 0.2rem 0;
	border: 0;
	background: none;
	color: var(--kf-white);
	font-family: var(--kf-font-body);
	font-size: var(--kf-t-small);
	font-weight: 600;
	cursor: pointer;
	text-decoration: underline;
	text-decoration-color: rgba(255, 176, 0, 0.8);
	text-decoration-thickness: 2px;
	text-underline-offset: 4px;
}

.kf-info__more:hover,
.kf-info__more:focus-visible {
	color: var(--kf-gold);
}

.kf-info__more:focus-visible {
	outline: 3px solid var(--kf-gold);
	outline-offset: 3px;
	border-radius: 0.25rem;
}

/* Closed, hover, open and focus each had to be told apart at a glance. The
   row's own surface carries the state and orange marks only the open one, so
   the text stays white and readable throughout. */
.kf-faq {
	display: grid;
	gap: 0.5rem;
}

.kf-faq__item {
	border: 1px solid rgba(120, 180, 255, 0.35);
	border-radius: 0.5rem;
	background: rgba(0, 32, 104, 0.55);
	overflow: hidden;
	transition: background-color 0.15s ease, border-color 0.15s ease;
}

.kf-faq__item:hover {
	border-color: rgba(160, 205, 255, 0.7);
	background: rgba(0, 48, 150, 0.7);
}

.kf-faq__item[open] {
	border-color: var(--kf-orange);
	background: rgba(0, 48, 150, 0.85);
}

/* Denser panels where the tower stands behind them.
   At 55% the photograph shone through unevenly: the cards over the lit shaft
   measured 37% brighter than the ones beside it, so a row that should read as
   one set read as five different surfaces. At 85% that spread falls to 12% and
   the tower reads as what it is — behind the panels rather than through them,
   still fully in view above, below and in the gap between the two blocks.

   Desktop keeps 55%: there the tower stands in the gutter between the columns
   and never sits behind a card. This block has to follow the rules above,
   because a media query adds no specificity and source order decides. */
@media (max-width: 63.99rem) {
	.kf-faq__item,
	.kf-info__pending {
		background: rgba(0, 32, 104, 0.85);
	}

	.kf-faq__item:hover {
		background: rgba(0, 48, 150, 0.9);
	}

	.kf-faq__item[open] {
		background: rgba(0, 48, 150, 0.94);
	}
}

.kf-faq__question {
	display: flex;
	align-items: center;
	gap: 0.8rem;
	padding: 0.85rem 1rem;
	color: var(--kf-white);
	font-size: var(--kf-t-body);
	font-weight: 600;
	cursor: pointer;
	list-style: none;
}

.kf-faq__question::-webkit-details-marker {
	display: none;
}

.kf-faq__question:focus-visible {
	outline: 3px solid var(--kf-gold);
	outline-offset: -3px;
	border-radius: 0.45rem;
}

.kf-faq__question-text {
	flex: 1 1 auto;
	min-width: 0;
}

/* One chevron, rotated when the row opens. */
.kf-faq__marker {
	flex: none;
	color: var(--kf-orange);
	transition: transform 0.2s ease, color 0.15s ease;
}

.kf-faq__item:hover .kf-faq__marker {
	color: var(--kf-gold);
}

.kf-faq__item[open] .kf-faq__marker {
	transform: rotate(180deg);
}

/* The answer is set apart from the question by a rule and a darker ground,
   so an open row reads as question plus answer rather than one long block. */
.kf-faq__answer {
	padding: 0.85rem 1rem 0.95rem;
	border-top: 1px solid rgba(255, 106, 0, 0.55);
	background: rgba(1, 20, 68, 0.6);
	color: var(--kf-white);
	font-size: var(--kf-t-body);
	font-weight: 400;
}

.kf-faq__answer p:last-child {
	margin-bottom: 0;
}

/* Rows slide open and shut instead of jumping, and the tower, standing on the
   section's lower edge, glides with them. Browsers without ::details-content
   simply open at once, as before. */
.kf-faq {
	interpolate-size: allow-keywords;
}

.kf-faq__item::details-content {
	block-size: 0;
	overflow: hidden;
	transition:
		block-size 0.38s cubic-bezier(0.3, 0.7, 0.2, 1),
		content-visibility 0.38s allow-discrete;
}

.kf-faq__item[open]::details-content {
	block-size: auto;
}

@media (prefers-reduced-motion: reduce) {
	.kf-faq__item::details-content {
		transition: none;
	}
}

/* --------------------------------------------------------------------------
   Partners
   -------------------------------------------------------------------------- */

.kf-partners {
	/* The same band every other section uses, top and bottom. */
	padding-block: var(--kf-band);
	background: var(--kf-navy);
	text-align: center;

	/* The horizon below is drawn behind everything in this section, so the
	   element needs a stacking context of its own. z-index 0 is enough; the
	   fixed header at 200 still passes over the top of it. */
	position: relative;
	z-index: 0;

	/* One dial per layer, so the mobile version is the same treatment turned
	   down rather than a different one. */
	--kf-horizon-core: 0.78;
	--kf-horizon-bloom: 0.26;
	--kf-horizon-height: clamp(6rem, 12vw, 9.5rem);
	/* Seven tenths of the column the sections are set in, not of the window:
	   the same figure the container arrives at, times 0.7. */
	--kf-horizon-width: calc(0.7 * (min(100%, var(--kf-container)) - 2 * clamp(1rem, 3.5vw, 2.5rem)));
}

/* --------------------------------------------------------------------------
   The horizon between the practical section and the partners

   The tower photograph stops dead where the two sections meet, and the cut
   read as unfinished. This is that cut lit from behind: a hairline core in the
   neon the tower itself is lit with, and a shallow bloom either side of it.

   It spans seven tenths of the content column, centred, dissolving at both
   ends. Edge to edge it read as a border; this reads as light.

   It is one absolutely positioned box centred on the seam, so it adds no
   height and no scroll width, and z-index -1 inside this section's own
   stacking context puts it above both backgrounds but under every word.
   -------------------------------------------------------------------------- */

.kf-partners::before {
	content: "";
	position: absolute;
	z-index: -1;
	top: 0;
	left: 50%;
	width: var(--kf-horizon-width);
	height: var(--kf-horizon-height);
	transform: translate(-50%, -50%);
	pointer-events: none;
	background:
		/* the core: one pixel, brightest under the tower, easing out before
		   it reaches either edge so it never ends on a hard stop */
		linear-gradient(
			90deg,
			rgba(10, 85, 216, 0) 0%,
			rgba(46, 132, 244, calc(var(--kf-horizon-core) * 0.14)) 10%,
			rgba(46, 132, 244, calc(var(--kf-horizon-core) * 0.42)) 24%,
			rgba(92, 168, 250, calc(var(--kf-horizon-core) * 0.74)) 38%,
			rgba(150, 210, 255, var(--kf-horizon-core)) 50%,
			rgba(92, 168, 250, calc(var(--kf-horizon-core) * 0.74)) 62%,
			rgba(46, 132, 244, calc(var(--kf-horizon-core) * 0.42)) 76%,
			rgba(46, 132, 244, calc(var(--kf-horizon-core) * 0.14)) 90%,
			rgba(10, 85, 216, 0) 100%
		),
		/* the bloom: wide, shallow, gone well before the partners heading */
		radial-gradient(
			/* The horizontal radius is what makes the bloom reach zero exactly
			   at the box edge: the last stop sits at 76%, and 76% of 66% is
			   half the width. Any wider and the gradient is still lit where
			   the box stops, which draws the two vertical edges we are here
			   to avoid. The vertical radius and the stops are untouched. */
			66% 52% at 50% 50%,
			rgba(20, 108, 240, var(--kf-horizon-bloom)) 0%,
			rgba(10, 68, 190, calc(var(--kf-horizon-bloom) * 0.5)) 42%,
			rgba(6, 44, 140, calc(var(--kf-horizon-bloom) * 0.19)) 62%,
			rgba(6, 44, 140, 0) 76%
		);
	background-repeat: no-repeat;
	background-position: 50% 50%, 50% 50%;
	background-size: 100% 1px, 100% 100%;
}

/* Smaller screens sit closer to the eye and carry the seam across a narrower
   span, so the same horizon is turned down and drawn tighter. */
@media (max-width: 48rem) {
	.kf-partners {
		--kf-horizon-core: 0.6;
		--kf-horizon-bloom: 0.17;
		--kf-horizon-height: 5.5rem;
	}
}

.kf-partners__title {
	margin: 0;
	color: var(--kf-white);
	font-family: var(--kf-font-display);
	font-size: var(--kf-t-h2);
	letter-spacing: 0.02em;
	text-shadow: 0 3px 0 rgba(1, 8, 37, 0.5), 0 10px 26px rgba(1, 8, 37, 0.6);
	text-transform: uppercase;
}

.kf-partners__list {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 1.4rem clamp(2rem, 5vw, 4.5rem);
	margin-top: clamp(1.6rem, 3vw, 2.6rem);
}

/* On a phone the row slides instead of wrapping, the same gesture as the photo
   strip. With only a couple of marks there is nothing to slide and they stay
   centred: "safe" centring falls back to the start edge the moment the row
   overflows, so the first logo is never cut off. It bleeds to both screen
   edges so a half-visible next logo signals there is more. */
@media (max-width: 47.99rem) {
	.kf-partners__list {
		flex-wrap: nowrap;
		justify-content: safe center;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
		margin-inline: calc(-1 * clamp(1rem, 3.5vw, 2.5rem));
		padding-inline: clamp(1rem, 3.5vw, 2.5rem);
		overscroll-behavior-x: contain;
	}

	.kf-partners__list::-webkit-scrollbar {
		display: none;
	}

	.kf-partners__item {
		flex: 0 0 auto;
		scroll-snap-align: center;
	}
}

/* Confirmed partners take the full row; anything still to be confirmed drops
   to a small neutral marker on a line of its own. */
.kf-partners__item--lead {
	flex: 0 0 auto;
}

.kf-partners__item {
	position: relative;
}

.kf-partners__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	color: inherit;
	text-decoration: none;
}

/* The two marks have very different aspect ratios, so each is bounded on
   both axes; that is what makes them read at a comparable size. */
.kf-partners__logo {
	width: auto;
	height: auto;
	max-width: clamp(9rem, 22vw, 13rem);
	max-height: clamp(3rem, 7vw, 3.5rem);
	object-fit: contain;
}

/* No partner logo has been supplied. Setting the names in the display face
   read as a designed wordmark, which is a claim about somebody else's brand.
   Until the official files arrive both partners get the same neutral box at
   the same visual weight. */
.kf-partners__placeholder {
	display: flex;
	align-items: center;
	justify-content: center;
	width: clamp(9.5rem, 17vw, 13.5rem);
	height: clamp(3rem, 5vw, 3.6rem);
	padding: 0.4rem 0.8rem;
	border: 1px solid rgba(150, 190, 255, 0.45);
	border-radius: 0.3rem;
	background: rgba(255, 255, 255, 0.05);
	color: var(--kf-text);
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-body);
	font-weight: 600;
	letter-spacing: 0.1em;
	line-height: 1.1;
	text-align: center;
	text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */

.kf-footer {
	padding: 0 0 1.2rem;
	background: var(--kf-navy-deep);
	color: rgba(198, 216, 248, 0.95);
	font-size: var(--kf-t-body);
}

.kf-footer__rule {
	height: 1px;
	margin: 0;
	border: 0;
	background: linear-gradient(90deg, rgba(255, 176, 0, 0) 0%, rgba(255, 176, 0, 0.7) 18%, rgba(255, 176, 0, 0.7) 82%, rgba(255, 176, 0, 0) 100%);
}

.kf-footer__main {
	padding-block: clamp(0.9rem, 2vw, 1.5rem);
}

/* Flat white between two gold rules had nothing to hold the eye. The dates
   carry the line in festival gold; the name stays white behind them. */
.kf-footer__line {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: center;
	gap: 0 0.4em;
	margin: 0;
	color: rgba(233, 241, 255, 0.92);
	font-family: var(--kf-font-display);
	font-size: clamp(1.35rem, 1.1rem + 0.8vw, 1.85rem);
	font-weight: 400;
	letter-spacing: 0.02em;
	line-height: 1.15;
	text-align: center;
	text-transform: uppercase;
}

.kf-footer__line-date {
	color: var(--kf-gold);
	text-shadow: 0 0 18px rgba(255, 176, 0, 0.55);
}

.kf-footer__legal {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem 1.5rem;
	padding-top: 0.95rem;
	color: rgba(214, 230, 255, 0.95);
	font-size: var(--kf-t-small);
	font-weight: 400;
}

.kf-footer__legal p {
	margin: 0;
}

/* The closing sentence breaks as a whole or not at all. On a narrow screen it
   drops to its own line instead of leaving "voorbehouden." stranded there; on
   a wide one it still sits on the first line. */
.kf-footer__rights {
	display: inline-block;
	white-space: nowrap;
}

.kf-footer__legal-links {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem 1.3rem;
	margin: 0;
	padding: 0;
	color: var(--kf-white);
	font-weight: 400;
	list-style: none;
}

/* Padding for the finger, negative margin so the row keeps the height the
   three inert labels had. Nothing moves; the target grows. */
.kf-footer__legal-links a {
	display: inline-block;
	margin-block: -0.34rem;
	padding-block: 0.34rem;
	color: inherit;
	text-decoration-color: rgba(214, 230, 255, 0.5);
	text-underline-offset: 0.22em;
}

.kf-footer__legal-links a:hover,
.kf-footer__legal-links a:focus-visible {
	color: var(--kf-gold);
	text-decoration-color: currentColor;
}

/* Subordinate to the closing line above: two marks on the legal row, at the
   size of the text beside them, not a block of their own. */
.kf-footer__socials {
	display: flex;
	gap: 0.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.kf-footer__social {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.1rem;
	height: 2.1rem;
	border: 1px solid rgba(190, 215, 255, 0.45);
	border-radius: 50%;
	color: var(--kf-white);
	transition: border-color 0.15s ease, color 0.15s ease, background-color 0.15s ease;
}

.kf-footer__social:hover {
	border-color: var(--kf-orange);
	background: rgba(255, 106, 0, 0.16);
	color: var(--kf-gold);
}

.kf-footer__social:focus-visible {
	outline: 3px solid var(--kf-gold);
	outline-offset: 3px;
}

/* On a phone the legal row already wraps; the marks take a line of their own
   and centre with the rest rather than hanging off the end. */
@media (max-width: 47.99rem) {
	.kf-footer__legal {
		justify-content: center;
		text-align: center;
	}

	.kf-footer__legal-links {
		justify-content: center;
	}

	.kf-footer__socials {
		width: 100%;
		justify-content: center;
		margin-top: 0.2rem;
	}
}

/* ==========================================================================
   MOTION — added on request. Everything between these markers can be deleted
   in one go to return the page to its static state; nothing outside depends
   on it. The reduced-motion rule at the end of this file already disables all
   of it for visitors who ask for that.
   ========================================================================== */

/* The supplied crown, once, straddling the seam between the orange band and
   the dark one below it. A single large mark, not a repeated ornament. */
/* The band is the crown's positioning context. overflow-x: clip cuts the
   crown at the band's own edges on a narrow screen instead of letting it push
   the page sideways; clip is the one value that leaves the vertical axis
   visible, which the crown needs to sit on the top seam. */
.kf-newsletter {
	position: relative;
	overflow-x: clip;
	overflow-y: visible;
}

/* The supplied crown, once, tilted, sitting on the band's top edge to the
   right of the submit button. A single mark, not a repeated ornament, and it
   does not move. */
.kf-seam-crown {
	position: absolute;
	top: 0;
	/* Centred on the container's right content edge — the same line the last
	   news card and the submit button end on — rather than on a distance from
	   the viewport. The offset is the page gutter plus whatever margin the
	   container has at this width, so the crown holds that line at every size
	   and simply runs off the screen when there is no room, instead of
	   creeping inwards. */
	right: calc(max((100% - var(--kf-container)) / 2, 0px) + clamp(1rem, 3.5vw, 2.5rem) - 70px);
	z-index: 2;
	display: block;
	width: clamp(4.4rem, 7.8vw, 6.6rem);
	transform: translate(50%, -52%) rotate(30deg);
	transform-origin: 50% 50%;
	pointer-events: none;
	filter: drop-shadow(0 5px 16px rgba(1, 8, 37, 0.7));
}

.kf-seam-crown__image {
	display: block;
	width: 100%;
	height: auto;
}

/* On tablets and phones the crown would only show as a clipped sliver at the
   screen edge, so it is left out there. */
@media (max-width: 63.99rem) {
	.kf-seam-crown {
		display: none;
	}
}


/* The seconds box, so the band reads as running rather than printed. */
.kf-countdown__unit.is-ticking {
	animation: kf-tick 0.55s ease-out;
}

@keyframes kf-tick {
	0% {
		border-color: var(--kf-white);
		box-shadow:
			0 0 30px rgba(140, 205, 255, 1),
			0 0 60px rgba(6, 123, 255, 0.7),
			inset 0 0 26px rgba(6, 123, 255, 0.7);
	}
	100% {
		border-color: rgba(170, 220, 255, 1);
		box-shadow:
			0 0 22px rgba(6, 123, 255, 0.9),
			0 0 46px rgba(6, 123, 255, 0.45),
			inset 0 0 24px rgba(6, 123, 255, 0.5);
	}
}

.kf-countdown__unit.is-ticking .kf-countdown__value {
	animation: kf-tick-digit 0.55s ease-out;
}

@keyframes kf-tick-digit {
	0%   { transform: translateY(-2px); opacity: 0.75; }
	100% { transform: translateY(0); opacity: 1; }
}

/* ======================= end MOTION ====================================== */

/* --------------------------------------------------------------------------
   A single news post — the page a card on the landing page leads to
   -------------------------------------------------------------------------- */

.kf-post {
	padding-top: calc(var(--kf-header-h) + var(--kf-band));
}

/* 832px puts the body at about 75 characters a line, the top of the range
   that still reads comfortably, and gives the picture 15% more width. Wider
   than this and the line outruns the eye; a photo-left, text-right split was
   tried and left the text at 45 characters, which reads as a card rather
   than as an article. */
.kf-post__inner {
	max-width: 52rem;
}

/* The documents are mostly lists, headings and short articles rather than long
   prose, and at 52rem they read as a narrow column in a wide screen. They get
   the room; a news story keeps the measure above. */
.kf-legal .kf-post__inner {
	max-width: 64rem;
}

.kf-post__back {
	margin: 0 0 clamp(1.2rem, 3vw, 2rem);
	font-size: var(--kf-t-small);
}

.kf-post__back a,
.kf-post__date {
	color: var(--kf-text-dim);
	text-decoration: none;
}

.kf-post__back a:hover {
	color: var(--kf-gold);
	text-decoration: underline;
}

.kf-post__meta {
	position: relative;
	margin: 0 0 0.9rem;
}

/* The tag is positioned over a card image on the landing page; here it sits
   in the flow, so it needs the ordinary box back. */
.kf-post__meta .kf-news__tag {
	position: static;
	display: inline-block;
}

.kf-post__title {
	margin: 0;
	color: var(--kf-white);
	font-size: clamp(1.9rem, 1.3rem + 2.6vw, 3.4rem);
	line-height: 1.02;
	text-transform: uppercase;
	text-shadow: 0 3px 0 rgba(1, 8, 37, 0.5), 0 10px 26px rgba(1, 8, 37, 0.6);
}

.kf-post__date {
	margin: 0.7rem 0 0;
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-small);
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.kf-post__figure {
	margin: clamp(1.4rem, 3.5vw, 2.4rem) 0 0;
}

.kf-post__image {
	display: block;
	width: 100%;
	height: auto;
	border: 2px solid rgba(255, 176, 0, 0.9);
	border-radius: var(--kf-radius-lg);
	box-shadow: 0 14px 34px rgba(1, 8, 37, 0.65);
}

.kf-post__figure figcaption {
	margin-top: 0.6rem;
	color: var(--kf-text-dim);
	font-size: var(--kf-t-small);
}

.kf-post__body {
	margin-top: clamp(1.4rem, 3.5vw, 2.4rem);
	color: var(--kf-white);
	font-size: var(--kf-t-body);
	font-weight: 400;
}

.kf-post__body > * + * {
	margin-top: 1em;
}

.kf-post__body h2,
.kf-post__body h3 {
	margin-top: 1.6em;
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

.kf-post__body h2 {
	font-size: var(--kf-t-h3);
}

.kf-post__body h3 {
	font-size: var(--kf-t-card);
}

.kf-post__body a {
	color: var(--kf-gold);
}

.kf-post__body ul,
.kf-post__body ol {
	padding-left: 1.3em;
	list-style: revert;
}

.kf-post__body li + li {
	margin-top: 0.4em;
}

.kf-post__body img {
	height: auto;
	border-radius: var(--kf-radius);
}

.kf-post__body blockquote {
	padding-left: 1.1em;
	border-left: 3px solid var(--kf-orange);
	color: var(--kf-text);
}

.kf-share {
	margin-top: clamp(1.8rem, 4vw, 2.8rem);
	padding-top: clamp(1.2rem, 3vw, 1.8rem);
	border-top: 1px solid rgba(120, 180, 255, 0.28);
}

.kf-share__title {
	margin: 0 0 0.85rem;
	color: var(--kf-text-dim);
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-small);
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

.kf-share__list {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.kf-share__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	min-width: 44px;
	min-height: 44px;
	padding: 0 0.85rem;
	border: 1px solid rgba(150, 200, 255, 0.4);
	border-radius: var(--kf-radius);
	background: rgba(0, 32, 104, 0.55);
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-small);
	font-weight: 600;
	letter-spacing: 0.06em;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.kf-share__link:hover,
.kf-share__link:focus-visible {
	border-color: var(--kf-orange);
	background: rgba(0, 48, 150, 0.8);
	color: var(--kf-gold);
}

/* All five are marks of the same size, so the copy button shows a tick in
   place of its link mark rather than growing a label. */
.kf-share__icon--check {
	display: none;
}

.kf-share__link.is-copied {
	border-color: var(--kf-gold);
	color: var(--kf-gold);
}

.kf-share__link.is-copied .kf-share__icon--link {
	display: none;
}

.kf-share__link.is-copied .kf-share__icon--check {
	display: block;
}

.kf-post__actions {
	margin-top: clamp(1.8rem, 4vw, 3rem);
}

/* --------------------------------------------------------------------------
   Mobile sticky CTA
   -------------------------------------------------------------------------- */

.kf-sticky-cta {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 190;
	padding: 0.5rem clamp(0.75rem, 3vw, 1.5rem);
	padding-bottom: calc(0.5rem + env(safe-area-inset-bottom, 0px));
	background: rgba(2, 13, 56, 0.98);
	border-top: 2px solid var(--kf-orange);
	transform: translateY(0);
	transition: transform 0.25s ease;
}

.kf-sticky-cta.is-hidden {
	transform: translateY(110%);
}

.kf-sticky-cta__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	max-width: var(--kf-container);
	margin-inline: auto;
}

.kf-sticky-cta__meta {
	color: var(--kf-white);
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-small);
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

body.has-sticky-cta .kf-footer {
	padding-bottom: 4.4rem;
}

@media (min-width: 48rem) {
	.kf-sticky-cta {
		display: none;
	}

	body.has-sticky-cta .kf-footer {
		padding-bottom: 1rem;
	}
}

/* --------------------------------------------------------------------------
   Motion and print
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
	}
}

@media print {
	.kf-header,
	.kf-sticky-cta,
	.kf-hero__art,
	.kf-env-banner,
	.kf-video__play,
	.kf-band__confetti {
		display: none !important;
	}

	body,
	.kf-section,
	.kf-hero,
	.kf-footer {
		background: #fff !important;
		color: #000 !important;
	}
}


/* --------------------------------------------------------------------------
   Legal documents
   --------------------------------------------------------------------------
   The same column as a news post. Two additions only: an opening paragraph
   that carries the summary, and a jump list, because these pages are read by
   looking something up rather than from top to bottom.
   -------------------------------------------------------------------------- */

.kf-legal__lead {
	color: var(--kf-white);
	font-size: var(--kf-t-card);
	font-weight: 500;
	line-height: 1.45;
}

.kf-legal__toc {
	margin-top: clamp(1.4rem, 3.5vw, 2.2rem);
	padding: clamp(1rem, 2.6vw, 1.4rem) clamp(1.1rem, 3vw, 1.6rem);
	border: 1px solid rgba(120, 180, 255, 0.28);
	border-radius: var(--kf-radius);
	background: rgba(8, 24, 66, 0.55);
}

.kf-legal__toc-title {
	margin: 0 0 0.7rem;
	color: var(--kf-gold);
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-small);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.kf-legal__toc ol {
	display: grid;
	gap: 0.35rem 1.6rem;
	margin: 0;
	padding: 0;
	list-style: none;
	counter-reset: kf-toc;
}

@media (min-width: 44rem) {
	.kf-legal__toc ol {
		grid-template-columns: 1fr 1fr;
	}
}

.kf-legal__toc li {
	counter-increment: kf-toc;
}

.kf-legal__toc a {
	color: var(--kf-white);
	font-size: var(--kf-t-small);
	text-decoration-color: rgba(214, 230, 255, 0.35);
	text-underline-offset: 0.2em;
}

.kf-legal__toc a::before {
	content: counter(kf-toc) ". ";
	color: var(--kf-gold);
}

.kf-legal__toc a:hover,
.kf-legal__toc a:focus-visible {
	color: var(--kf-gold);
	text-decoration-color: currentColor;
}

/* A heading that a jump list points at needs the sticky header's clearance. */
.kf-legal__body h2 {
	scroll-margin-top: calc(var(--kf-header-h) + 1rem);
}

.kf-legal__body code {
	padding: 0.1em 0.4em;
	border-radius: 0.25rem;
	background: rgba(120, 180, 255, 0.14);
	font-size: 0.92em;
}


/* ==========================================================================
   V2 — flow through the page

   The client read the page as a stack of rectangles. The answer here is
   composition rather than decoration: elements that reach across a seam, one
   deliberate tilt, colour that fades instead of stopping, and one panel that
   floats instead of spanning. No separators were added.
   ========================================================================== */

/* --- Following the chosen event ------------------------------------------ */

/* Content bound to one event shows only while that event is chosen. Without
   JavaScript no event is set, so everything stays visible. */
:root[data-kf-event="nacht"] [data-kf-event-only="dag"],
:root[data-kf-event="dag"] [data-kf-event-only="nacht"] {
	display: none !important;
}

.kf-gallery__ribbon {
	display: flex;
	flex-direction: column;
}

/* --- Countdown into the photographs ------------------------------------- */

/* The countdown no longer ends on a ruled line either. */
.kf-band--countdown {
	box-shadow: none;
}

.kf-band--countdown::after {
	display: none;
}

/* --- The photographs as a ribbon laid across two sections ---------------- */

/* At every width. On touch the rows are swiped rather than drifting; a tilt
   this small leaves the swipe horizontal to the thumb (measured, see the V2
   verification), so phones get the same composition as desktops. */
@media all {
	:root {
		--kf-ribbon-tilt: -2.2deg;
		--kf-ribbon-overlap: clamp(1.4rem, 3.4vw, 3.2rem);
	}

	.kf-gallery {
		position: relative;
		z-index: 3;
		margin-block: calc(-1 * var(--kf-ribbon-overlap));
		padding-block: var(--kf-ribbon-overlap);
		background: transparent;
		overflow-x: clip;
		overflow-y: visible;
	}

	.kf-gallery__ribbon {
		width: 108%;
		margin-left: -4%;
		transform: rotate(var(--kf-ribbon-tilt));
		box-shadow:
			0 34px 60px -26px rgba(1, 6, 26, 0.9),
			0 -24px 50px -26px rgba(1, 6, 26, 0.7);
	}

	/* Room for the ribbon's lower edge to lie over the line-up. */
	#line-up {
		padding-top: calc(var(--kf-band) + var(--kf-ribbon-overlap));
	}
}

/* --- One background from the line-up down -------------------------------- */

/* The line-up opens on the royal blue the photographs lie on and the page
   darkens from there, evenly, to the navy the partners row opens with. One
   gradient over the whole run instead of a navy and a glow per section. The
   sections inside are transparent; the orange band stays a band. */
:root {
	--kf-countdown-fade: calc(var(--kf-events-overlap) + 9rem);
}

/* The confetti may reach below the band, onto the photographs' edge. */
.kf-band--countdown {
	overflow: visible;
	overflow-x: clip;
}

/* Each ribbon rests on the tilted rows: the rows rise to the right, so the
   left ribbon comes down and the right one goes up by the tilt over the
   distance from the middle of the screen, and both sit 5px clear of it. */
.kf-band__confetti--left {
	transform: translateY(calc((50vw - 4rem) * 0.0384 - 5px));
}

.kf-band__confetti--right {
	transform: translateY(calc((50vw - 4rem) * -0.0384 - 5px)) scaleX(-1);
}

.kf-flow {
	background: linear-gradient(180deg,
		var(--kf-royal) 0%,
		#022C8A 18%,
		#031E66 40%,
		#021447 68%,
		var(--kf-navy) 100%);
}

.kf-flow > .kf-section {
	background: transparent;
}

/* The photographs lie on that same royal blue, and the countdown settles
   into it, so no darker strip shows behind the tilted rows. */
.kf-gallery {
	/* Transparent, so the countdown above, the line-up below and the confetti
	   all run on behind the tilted rows without an edge of their own. */
	background: transparent;
}

.home .kf-main {
	background: var(--kf-royal);
}

.kf-band--countdown {
	background:
		/* Eased rather than linear: a straight ramp starts and stops on a
		   visible crease. */
		linear-gradient(180deg,
			rgba(1, 8, 37, 1) 0,
			rgba(1, 8, 37, 0.97) calc(var(--kf-countdown-fade) * 0.125),
			rgba(1, 8, 37, 0.87) calc(var(--kf-countdown-fade) * 0.25),
			rgba(1, 8, 37, 0.71) calc(var(--kf-countdown-fade) * 0.375),
			rgba(1, 8, 37, 0.5) calc(var(--kf-countdown-fade) * 0.5),
			rgba(1, 8, 37, 0.29) calc(var(--kf-countdown-fade) * 0.625),
			rgba(1, 8, 37, 0.13) calc(var(--kf-countdown-fade) * 0.75),
			rgba(1, 8, 37, 0.03) calc(var(--kf-countdown-fade) * 0.875),
			rgba(1, 8, 37, 0) var(--kf-countdown-fade)),
		linear-gradient(180deg,
			rgba(0, 59, 174, 0) 50%,
			rgba(0, 59, 174, 0.15) 62%,
			rgba(0, 59, 174, 0.5) 75%,
			rgba(0, 59, 174, 0.85) 88%,
			var(--kf-royal) 100%),
		radial-gradient(120% 220% at 50% 62%, #0A55D8 0%, var(--kf-royal) 45%, #002A80 100%);
}

/* --- Motion ------------------------------------------------------------- */

/* Things arrive as they scroll into view: a short rise, once. motion.js only
   sets kf-motion when the visitor has not asked for less motion, and only
   hides what is still below the fold, so nothing on screen ever blinks out. */
html.kf-motion .kf-reveal {
	opacity: 0;
	transform: translateY(1.1rem);
	transition:
		opacity 0.7s ease var(--kf-reveal-delay, 0s),
		transform 0.8s cubic-bezier(0.2, 0.7, 0.2, 1) var(--kf-reveal-delay, 0s);
}

html.kf-motion .kf-reveal.is-in {
	opacity: 1;
	transform: none;
}

/* The ticket button catches the light when a pointer reaches it. */
.kf-ticket-cta {
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

.kf-ticket-cta::after {
	content: "";
	position: absolute;
	inset: 0 auto 0 -60%;
	z-index: -1;
	width: 45%;
	background: linear-gradient(100deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.45) 50%, rgba(255, 255, 255, 0) 100%);
	transform: skewX(-18deg);
	transition: left 0.6s ease;
	pointer-events: none;
}

@media (hover: hover) {
	.kf-ticket-cta:hover::after,
	.kf-ticket-cta:focus-visible::after {
		left: 120%;
	}
}

@media (prefers-reduced-motion: reduce) {
	html.kf-motion .kf-reveal {
		opacity: 1;
		transform: none;
		transition: none;
	}

	.kf-ticket-cta::after {
		display: none;
	}
}

/* ==========================================================================
   Line-up spotlight

   Under a mouse pointer on a wide screen the card turns slightly towards the
   pointer, a soft light follows it across the card, the silhouette steps
   forward and the other cards step back. spotlight.js writes the position;
   everything visible is here. Touch and reduced motion keep the cards still.
   ========================================================================== */

@media (min-width: 64rem) and (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {
	.kf-lineup__grid {
		perspective: 1100px;
	}

	.kf-artist__frame {
		transform: rotateX(var(--kf-tilt-x, 0deg)) rotateY(var(--kf-tilt-y, 0deg));
		transition:
			transform 0.6s cubic-bezier(0.2, 0.7, 0.2, 1),
			box-shadow 0.35s ease,
			border-color 0.35s ease,
			filter 0.45s ease;
	}

	.kf-artist__frame.is-lit {
		border-color: #8FD0FF;
		transform: translateY(-6px) rotateX(var(--kf-tilt-x, 0deg)) rotateY(var(--kf-tilt-y, 0deg));
		transition:
			transform 0.18s ease-out,
			box-shadow 0.35s ease,
			border-color 0.35s ease,
			filter 0.45s ease;
		box-shadow:
			0 0 0 1px rgba(190, 230, 255, 0.9),
			0 0 34px rgba(60, 160, 255, 1),
			0 0 90px rgba(6, 123, 255, 0.6),
			inset 0 0 40px rgba(6, 123, 255, 0.45);
	}

	/* The light itself: above the silhouette, below the label. */
	.kf-artist__frame::after {
		content: "";
		position: absolute;
		inset: 0;
		z-index: 0;
		background: radial-gradient(circle at var(--kf-spot-x, 50%) var(--kf-spot-y, 30%),
			rgba(205, 236, 255, 0.3) 0%,
			rgba(120, 190, 255, 0.16) 30%,
			rgba(40, 140, 255, 0.06) 55%,
			rgba(6, 123, 255, 0) 85%);
		mix-blend-mode: screen;
		opacity: 0;
		transition: opacity 0.35s ease;
		pointer-events: none;
	}

	.kf-artist__frame.is-lit::after {
		opacity: 1;
	}

	/* Zoomed from just above the bottom edge, so the bust grows past the
	   frame's lower edge instead of lifting off it. */
	.kf-artist__silhouette,
	.kf-artist__image {
		transform-origin: 50% 85%;
		transition: transform 0.5s cubic-bezier(0.2, 0.7, 0.2, 1), filter 0.5s ease;
	}

	.kf-artist__frame.is-lit .kf-artist__silhouette,
	.kf-artist__frame.is-lit .kf-artist__image {
		transform: scale(1.05);
		filter: brightness(1.18);
	}

	/* The rest of the stage dims a little. */
	.kf-lineup__grid.has-spotlight .kf-artist__frame:not(.is-lit) {
		filter: brightness(0.82) saturate(0.9);
	}
}

/* ==========================================================================
   Consent for the advertising pixel

   A card in the middle of the screen over a dimmed page, because it is a
   question that has to be answered before anything is loaded. Refusing and
   accepting are the same size, the same shape and side by side; only colour
   tells them apart, and the refusal is not the quieter one.
   ========================================================================== */

.kf-consent {
	width: min(34rem, calc(100vw - 2rem));
	max-width: none;
	padding: 0;
	border: 0;
	border-radius: var(--kf-radius-lg, 1rem);
	background: transparent;
	color: var(--kf-white);
	overflow: visible;
}

.kf-consent::backdrop {
	background: rgba(1, 8, 37, 0.78);
}

.kf-consent__inner {
	padding: clamp(1.3rem, 3vw, 2rem);
	border: 2px solid rgba(120, 190, 255, 0.5);
	border-radius: var(--kf-radius-lg, 1rem);
	background:
		radial-gradient(120% 140% at 50% 0%, #06266E 0%, var(--kf-navy) 62%, var(--kf-navy-deep) 100%);
	box-shadow: 0 30px 80px rgba(1, 6, 26, 0.75);
	text-align: left;
}

.kf-consent__title {
	margin: 0 0 0.75rem;
	color: var(--kf-white);
	font-family: var(--kf-font-display);
	font-size: clamp(1.25rem, 1rem + 1.2vw, 1.7rem);
	letter-spacing: 0.02em;
	line-height: 1.1;
	text-transform: uppercase;
}

.kf-consent__text {
	margin: 0 0 0.7rem;
	color: rgba(214, 228, 252, 0.95);
	font-size: var(--kf-t-body);
	line-height: 1.55;
}

.kf-consent__link {
	color: var(--kf-white);
	text-decoration-color: rgba(255, 176, 0, 0.8);
	text-decoration-thickness: 2px;
	text-underline-offset: 3px;
}

.kf-consent__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.7rem;
	margin-top: clamp(1rem, 2.5vw, 1.5rem);
}

/* Same size and weight for both answers; refusing is never the harder click. */
.kf-consent__button {
	flex: 1 1 10rem;
	min-height: 48px;
	padding: 0.6rem 1.4rem;
	border: 2px solid transparent;
	border-radius: var(--kf-radius-sm, 0.5rem);
	font-family: var(--kf-font-cond);
	font-size: var(--kf-t-body);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	cursor: pointer;
	transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.kf-consent__button--yes {
	border-color: var(--kf-orange);
	background: var(--kf-orange);
	color: var(--kf-white);
}

.kf-consent__button--no {
	border-color: rgba(198, 216, 248, 0.75);
	background: transparent;
	color: var(--kf-white);
}

.kf-consent__button--yes:hover,
.kf-consent__button--yes:focus-visible {
	background: #ff8418;
	border-color: #ff8418;
}

.kf-consent__button--no:hover,
.kf-consent__button--no:focus-visible {
	border-color: var(--kf-white);
	background: rgba(255, 255, 255, 0.12);
}

.kf-consent__button:focus-visible {
	outline: 3px solid var(--kf-gold);
	outline-offset: 3px;
}

/* The frame holds the focus while the question is open; it is not a control,
   so it shows no ring. */
.kf-consent__inner:focus,
.kf-consent__inner:focus-visible {
	outline: none;
}

/* The footer's own control sits in the row of documents and looks like them. */
.kf-footer__legal-links button.kf-footer__legal-link {
	padding: 0;
	border: 0;
	background: none;
	color: inherit;
	font: inherit;
	cursor: pointer;
	text-decoration: underline;
}

@media (prefers-reduced-motion: reduce) {
	.kf-consent__button {
		transition: none;
	}
}
