/* ============================================================
   Urban Art Fest Malaga — design system
   Colours taken from the official 2026 poster:
   teal backdrop · magenta · gold · spray yellow · navy linework
   ============================================================ */

/* Palette sampled directly from the 2026 festival poster:
   teal backdrop, magenta jacket, gold bucket hat, yellow spray splatter,
   navy-black linework. Magenta is one step deeper than the poster's
   #C6459A so white button text clears WCAG AA (5.75:1). */
:root {
  /* Dark base — neon needs darkness to read as neon. --ink is the TEXT
     colour; --deep/--surface are backgrounds. */
  --ink: #EAF3F5;          /* primary text */
  --ink-soft: #C7D8DE;     /* secondary text */
  --paper: #0F1C24;        /* page background */
  --paper-card: #16262F;   /* card surface */
  --deep: #0A141A;         /* deepest panels: footer, modal, cookie */
  --surface-2: #1B2F3A;    /* alternating section */
  --magenta: #B03287;
  --magenta-lit: #E178B6;
  --teal: #4FAFB6;
  --teal-lit: #67BFC5;
  --teal-deep: #2E7A82;
  --gold: #F9BE36;
  --yellow: #F8DA27;
  /* From the 2027 bull poster — accent only, on dark (4.71:1).
     --red-deep is for white button text (5.48:1). */
  --red: #F25A4A;
  --red-deep: #C92A1E;
  --gray: #8CA3AC;

  /* Neon layer — deliberately hotter than the text palette. These are for
     glow, gradients and hover states only; body text keeps the AA-safe
     colours above so contrast never depends on a glow being visible. */
  --neon-magenta: #FF3DA6;
  --neon-teal: #3BF0DA;
  --neon-gold: #FFD03D;
  --neon-red: #FF5C48;
  --glow-sm: 0 0 12px;
  --glow-md: 0 0 26px;
  --glow-lg: 0 0 60px;
  --line: rgba(234, 243, 245, 0.14);
  --line-light: rgba(234, 243, 245, 0.16);

  --font-display: "Archivo Black", "Archivo", sans-serif;
  --font-body: "Archivo", sans-serif;
  --font-mono: "IBM Plex Mono", monospace;

  --container: 1180px;
  --radius: 14px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* The marquee and hero splat deliberately extend past the viewport;
   clip on both html and body so they never create a horizontal scrollbar. */
html { scroll-behavior: smooth; overflow-x: clip; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
}

body {
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

img { max-width: 100%; display: block; }
a { color: inherit; }

.mono { font-family: var(--font-mono); }
.container { max-width: var(--container); margin: 0 auto; padding: 0 24px; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.skip-link {
  position: absolute; left: 16px; top: -60px; z-index: 200;
  background: var(--neon-magenta); color: #0A141A; padding: 10px 16px; border-radius: 8px;
  text-decoration: none; transition: top 0.2s;
}
.skip-link:focus { top: 12px; }

:focus-visible { outline: 3px solid var(--magenta); outline-offset: 3px; }

/* ============ type ============ */
h1, h2, h3 { font-family: var(--font-display); font-weight: 400; line-height: 1.02; text-transform: uppercase; letter-spacing: -0.01em; }
h2 { font-size: clamp(2rem, 4.4vw, 3.4rem); }
h3 { font-size: 1.15rem; letter-spacing: 0.02em; }

.eyebrow {
  display: inline-block; font-size: 0.78rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.14em; color: var(--magenta-lit);
  border: 1.5px solid currentColor; padding: 4px 12px; border-radius: 999px;
  margin-bottom: 18px;
}
.section-lede { max-width: 54ch; color: var(--gray); margin-top: 16px; }
.section-dark .section-lede { color: var(--gray); }
.accent { color: var(--magenta-lit); }

/* ============ header ============ */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(15, 28, 36, 0.86);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
  transition: box-shadow 0.3s ease, background 0.3s ease;
}
.site-header.is-stuck {
  background: rgba(15, 28, 36, 0.96);
  box-shadow: 0 6px 26px rgba(0, 0, 0, 0.45);
}
.header-inner {
  max-width: var(--container); margin: 0 auto; padding: 14px 24px;
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
}
.brand { display: flex; align-items: center; text-decoration: none; }
.brand-logo {
  width: auto; height: 34px;          /* the logotype is already angled — no extra rotation */
  transition: opacity 0.15s ease;
}
.brand:hover .brand-logo { opacity: 0.72; }

.site-nav { display: flex; align-items: center; gap: 26px; }
.nav-foot { display: contents; }        /* desktop: children stay inline in the bar */
.nav-contact { display: none; }         /* mobile-only detail */
.site-nav a {
  text-decoration: none; font-weight: 600; font-size: 0.85rem;
  text-transform: uppercase; letter-spacing: 0.07em;
}
.site-nav a:not(.nav-cta):hover { color: var(--magenta-lit); }
.nav-cta {
  background: var(--magenta); color: #fff; padding: 9px 18px; border-radius: 999px;
  white-space: nowrap;              /* "€1 pass" must never break onto two lines */
  transition: transform 0.15s ease, background 0.15s ease;
}
.site-nav > a, .nav-trigger, .lang-btn { white-space: nowrap; }
.nav-cta:hover { background: var(--neon-magenta); color: #0A141A; transform: rotate(-2deg); }

/* ---- dropdown groups ---- */
.nav-group { position: relative; }
.nav-trigger {
  display: inline-flex; align-items: center; gap: 6px;
  font: inherit; font-weight: 600; font-size: 0.85rem;
  text-transform: uppercase; letter-spacing: 0.07em;
  background: none; border: 0; padding: 0; cursor: pointer; color: inherit;
}
.nav-trigger::after {
  content: ""; width: 6px; height: 6px; margin-top: -3px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg); transition: transform 0.2s var(--ease-out);
}
.nav-group[data-open="true"] .nav-trigger { color: var(--magenta-lit); }
.nav-group[data-open="true"] .nav-trigger::after { transform: rotate(-135deg); margin-top: 2px; }

.nav-menu {
  position: absolute; top: calc(100% + 14px); left: -14px; z-index: 120;
  min-width: 208px; padding: 8px;
  background: var(--deep); border: 1.5px solid rgba(59, 240, 218, 0.3); border-radius: 14px;
  box-shadow: 0 14px 34px rgba(20, 38, 46, 0.16);
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity 0.18s var(--ease-out), transform 0.18s var(--ease-out), visibility 0.18s;
}
.nav-group[data-open="true"] .nav-menu { opacity: 1; visibility: visible; transform: none; }
.nav-menu a {
  display: block; padding: 10px 14px; border-radius: 9px;
  font-size: 0.82rem; letter-spacing: 0.05em;
}
.nav-menu a:hover { background: var(--magenta); color: #fff; }
.nav-menu a[aria-current="page"] { color: var(--magenta-lit); }

/* ---- language switcher ---- */
.lang-switch { display: flex; gap: 2px; padding: 3px; border: 1.5px solid var(--line); border-radius: 999px; }
.lang-btn {
  display: inline-flex; align-items: center; gap: 5px;
  font: inherit; font-family: var(--font-mono); font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.06em; padding: 6px 10px; border: 0; border-radius: 999px;
  background: none; color: var(--gray); cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
/* Flags render as regional-indicator pairs; Windows shows the letters
   instead, which is why the EN/ES/FR label always stays alongside. */
.lang-flag {
  font-size: 0.95em; line-height: 1;
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}
.lang-btn:hover { color: var(--ink); }
.lang-btn.is-active { background: var(--magenta); color: #fff; }

.nav-toggle { display: none; background: none; border: 0; cursor: pointer; padding: 8px; }
.nav-toggle span { display: block; width: 24px; height: 2.5px; background: var(--ink); margin: 5px 0; border-radius: 2px; transition: transform 0.2s, opacity 0.2s; }

/* ============ hero video ============
   Footage sits behind the copy under a tinted gradient so the headline
   keeps its contrast no matter which frame is on screen. */
/* The footage is decoration behind a tint and must never take a tap. iOS draws
   its own play button over a paused video (Low Power Mode blocks autoplay),
   and tapping that native control hands playback to the fullscreen player —
   making the element inert means the tap falls through to the page instead,
   where the gesture handler in main.js starts it inline. */
.hero-video { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.hero-video video {
  width: 100%; height: 100%; object-fit: cover;
  filter: saturate(1.15) contrast(1.05);
  pointer-events: none;
}
.hero-video video::-webkit-media-controls,
.hero-video video::-webkit-media-controls-start-playback-button {
  display: none !important;
  -webkit-appearance: none;
}
.hero-video-tint {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(15,28,36,0.72) 0%, rgba(15,28,36,0.55) 45%, rgba(15,28,36,0.94) 100%),
    linear-gradient(105deg, rgba(176,50,135,0.38) 0%, transparent 46%, rgba(79,175,182,0.32) 100%);
  mix-blend-mode: normal;
}
/* faint scanline texture ties the footage to the poster-print feel */
.hero-video-tint::after {
  content: ""; position: absolute; inset: 0; opacity: 0.16;
  background: repeating-linear-gradient(0deg, rgba(0,0,0,0.5) 0 1px, transparent 1px 3px);
}

/* ============ hero ============ */
.hero { position: relative; overflow: hidden; padding: clamp(40px, 7vh, 100px) 0 clamp(48px, 7vh, 90px); }
.hero-inner {
  max-width: var(--container); margin: 0 auto; padding: 0 24px;
  position: relative; z-index: 2;
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: clamp(32px, 5vw, 72px);
  align-items: center;
}
.hero-copy { min-width: 0; }

/* The official poster, pinned up like a real flyposter */
.hero-poster {
  position: relative;
  width: clamp(230px, 27vw, 380px); flex-shrink: 0;
  transform: rotate(2deg);
  transition: transform 0.35s var(--ease-out);
}
.hero-poster img {
  width: 100%; height: auto; border-radius: 6px;
  box-shadow: 0 18px 44px rgba(20, 38, 46, 0.28), 0 2px 6px rgba(20, 38, 46, 0.16);
}
.hero-poster:hover { transform: rotate(0deg) scale(1.02); }
.hero-kicker { text-shadow: 0 1px 12px rgba(0,0,0,0.6); font-size: 0.82rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--gray); margin-bottom: 22px; }

.hero-title {
  text-shadow: 0 4px 40px rgba(0,0,0,0.5);
  font-size: clamp(3.5rem, 9vw, 8.5rem);
  line-height: 0.86; letter-spacing: -0.02em;
}
.hero-title .line { display: block; }
.line-outline {
  color: transparent;
  -webkit-text-stroke: 3px var(--neon-teal);
  text-stroke: 3px var(--neon-teal);
}
.title-dot { color: var(--magenta-lit); }

.hero-meta {
  display: grid; grid-template-columns: auto 1fr; gap: 40px; align-items: end;
  margin-top: clamp(28px, 4vh, 48px); max-width: 980px;
}
.hero-dates { display: flex; align-items: baseline; gap: 8px; font-family: var(--font-display); }
.date-num { font-size: clamp(2.4rem, 5vw, 4rem); }
.date-sep { color: var(--magenta-lit); font-size: clamp(1.6rem, 3vw, 2.6rem); }
.date-month {
  font-family: var(--font-mono); font-size: 0.85rem; text-transform: uppercase;
  letter-spacing: 0.12em; line-height: 1.3; margin-left: 10px; color: var(--gray);
}
.hero-blurb { color: var(--ink-soft); max-width: 46ch; text-shadow: 0 1px 10px rgba(0,0,0,0.55); }
.hero-actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 26px; grid-column: 1 / -1; }

/* buttons */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  font-weight: 700; font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.06em;
  text-decoration: none; padding: 15px 28px; border-radius: 999px; border: 2px solid transparent;
  cursor: pointer; transition: transform 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.btn-primary { background: var(--magenta); color: #fff; }
.btn-primary:hover { background: var(--neon-magenta); color: #0A141A; transform: translateY(-2px) rotate(-1deg); }
.btn-ghost { border-color: var(--ink); color: var(--ink); background: transparent; }
.btn-ghost:hover { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.btn-ghost-light { border-color: var(--ink); color: var(--ink); }
.btn-ghost-light:hover { background: var(--ink); color: var(--deep); }
.btn-lg { padding: 18px 34px; font-size: 1rem; }


/* spray splat */
.hero-splat {
  position: absolute; z-index: 1; pointer-events: none;
  width: 560px; height: 560px; right: -140px; bottom: -220px;
  background: radial-gradient(circle at 40% 40%, rgba(31,185,165,0.35), transparent 62%);
  filter: blur(2px);
}

/* ============ ticker ============ */
.ticker { background: var(--deep); color: var(--ink); overflow: hidden; padding: 14px 0; border-block: 3px solid var(--deep); }
.ticker-track {
  display: flex; gap: 28px; align-items: center; width: max-content;
  animation: ticker 26s linear infinite;
  font-family: var(--font-display); text-transform: uppercase; font-size: 1.05rem; letter-spacing: 0.04em;
  white-space: nowrap;
}
.ticker-track i { color: var(--magenta-lit); font-style: normal; }
@keyframes ticker { to { transform: translateX(-50%); } }

/* ============ stats band ============
   The poster's teal used at full-surface scale. */
.stats-band { background: var(--teal); color: #0A141A; padding: clamp(44px, 6vh, 76px) 0; }
.stats {
  list-style: none; display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 24px; text-align: center;
}
.stat { position: relative; }
.stat + .stat::before {
  content: ""; position: absolute; left: -12px; top: 12%; bottom: 12%;
  width: 1.5px; background: rgba(20, 38, 46, 0.22);
}
.stat-num {
  display: block;
  font-family: var(--font-display); line-height: 0.94;
  font-size: clamp(2.6rem, 7vw, 5rem);
  font-variant-numeric: tabular-nums;   /* stops digits jittering while counting */
  letter-spacing: -0.02em;
}
.stat-label {
  display: block; margin-top: 12px;
  font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.16em;
  color: rgba(10, 20, 26, 0.78);
}

/* ============ sections ============ */
.section { padding: clamp(64px, 10vh, 120px) 0; }
.section-head { margin-bottom: clamp(36px, 5vh, 56px); }
.section-dark {
  background: var(--surface-2); color: var(--ink);
  position: relative; isolation: isolate;
}
/* Slow-drifting colour wash so dark sections aren't flat black */
.section-dark::before {
  content: ""; position: absolute; inset: -20% -10%; z-index: -1; pointer-events: none;
  background:
    radial-gradient(38% 44% at 12% 18%, rgba(255, 61, 166, 0.20), transparent 70%),
    radial-gradient(34% 40% at 88% 26%, rgba(59, 240, 218, 0.16), transparent 70%),
    radial-gradient(40% 46% at 62% 88%, rgba(255, 208, 61, 0.12), transparent 70%);
  filter: blur(28px);
  animation: aurora 26s ease-in-out infinite alternate;
}
@keyframes aurora {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(2%, -3%, 0) scale(1.08); }
  100% { transform: translate3d(-2%, 2%, 0) scale(1.04); }
}
.section-dark .eyebrow { color: var(--teal-lit); }

/* pillars */
.pillars { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; }
.pillar {
  display: flex; flex-direction: column; text-decoration: none; color: inherit;
  background: var(--paper-card); border: 1.5px solid var(--line); border-radius: var(--radius);
  padding: 28px 24px 26px; position: relative; overflow: hidden;
}
.pillar-more {
  margin-top: auto; padding-top: 18px;
  font-family: var(--font-mono); font-size: 0.72rem;
  text-transform: uppercase; letter-spacing: 0.12em; color: var(--magenta-lit);
  display: inline-flex; align-items: center; gap: 7px;
  transition: gap 0.18s var(--ease-out);
}
.pillar:hover .pillar-more { gap: 13px; }
.pillar::before {
  content: ""; position: absolute; inset: 0 auto auto 0; width: 100%; height: 5px;
  background: var(--magenta);
  transform: scaleX(0); transform-origin: left; transition: transform 0.25s ease;
}
.pillar:nth-child(2)::before { background: var(--teal); }
.pillar:nth-child(3)::before { background: var(--yellow); }
.pillar:nth-child(4)::before { background: var(--neon-red); }
.pillar:hover { border-color: var(--ink); }
.pillar:hover::before { transform: scaleX(1); }
.pillar h3 { margin-bottom: 12px; }
.pillar p { color: var(--gray); font-size: 0.97rem; }

/* ============ value strip ============ */
.value-strip { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.value {
  border: 1.5px solid var(--line-light); border-radius: var(--radius);
  padding: 28px 26px 30px;
}
.value:hover { border-color: var(--yellow); }
.value-label {
  font-family: var(--font-mono); font-size: 0.72rem; text-transform: uppercase;
  letter-spacing: 0.16em; color: var(--yellow); margin-bottom: 14px;
}
.value h3 { font-size: clamp(1.05rem, 1.7vw, 1.4rem); line-height: 1.12; }

/* ============ judges ============ */
.judges-row { display: grid; grid-template-columns: repeat(5, 1fr); gap: 18px; }
.judge { text-align: center; }
.judge-photo {
  aspect-ratio: 1; border-radius: var(--radius); margin-bottom: 16px; overflow: hidden;
  background: linear-gradient(145deg, var(--ink-soft), #2e2e3a);
  border: 1.5px solid var(--line-light);
  display: grid; place-items: center; position: relative;
}
.judge-photo img { width: 100%; height: 100%; object-fit: cover; }
.judge h3 { font-size: 1rem; }
.judge .mono {
  color: var(--teal-lit); font-size: 0.78rem; text-transform: uppercase;
  letter-spacing: 0.12em; margin-top: 6px; text-wrap: balance;
}

.register-strip {
  margin-top: 56px; padding: 28px 32px; border-radius: var(--radius);
  background: rgba(237, 243, 243,0.06); border: 1.5px dashed var(--line-light);
  display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap;
}
.register-strip p { color: rgba(237, 243, 243,0.65); }

/* ============ artists ============ */
/* Search sits above the country chips: with 170+ names, scanning the grid
   for one person is the slow path. The two narrow together — a query is
   applied within whatever country chip is active. */
.artist-search { position: relative; max-width: 440px; margin-bottom: 14px; }
.artist-search-input {
  width: 100%; box-sizing: border-box;
  font-family: var(--font-mono); font-size: 0.85rem; letter-spacing: 0.02em;
  padding: 13px 44px 13px 44px; border-radius: 999px;
  border: 1.5px solid var(--line); background: rgba(255, 255, 255, 0.03);
  color: var(--ink);
  transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}
.artist-search-input::placeholder { color: var(--gray); }
.artist-search-input:hover { border-color: var(--ink-soft); }
.artist-search-input:focus {
  outline: none; border-color: var(--teal-lit);
  background: rgba(255, 255, 255, 0.05);
  box-shadow: var(--glow-sm) rgba(79, 175, 182, 0.35);
}
/* The browser's own clear affordance is inconsistent across engines and
   ignores the pill shape — we draw our own below. */
.artist-search-input::-webkit-search-decoration,
.artist-search-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

.artist-search-icon {
  position: absolute; left: 16px; top: 50%; transform: translateY(-50%);
  width: 17px; height: 17px; color: var(--gray); pointer-events: none;
  stroke-linecap: round;
}
/* :focus-within, not a sibling selector — the icon precedes the input. */
.artist-search:focus-within .artist-search-icon { color: var(--teal-lit); }

.artist-search-clear {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 30px; height: 30px; display: flex; align-items: center; justify-content: center;
  border: 0; border-radius: 50%; background: transparent;
  color: var(--gray); font-size: 1.4rem; line-height: 1; cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.artist-search-clear:hover { color: var(--ink); background: rgba(255, 255, 255, 0.08); }

/* Empty state — spans the whole grid rather than sitting in column one. */
.artist-none {
  grid-column: 1 / -1; text-align: center; padding: 54px 20px;
  border: 1.5px dashed var(--line); border-radius: 14px;
}
.artist-none strong {
  display: block; font-family: var(--font-display);
  font-size: 1.1rem; text-transform: uppercase; margin-bottom: 8px; color: var(--ink);
}
.artist-none span { color: var(--gray); font-size: 0.9rem; }

.filter-bar { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 34px; }
.chip {
  font-family: var(--font-mono); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.08em;
  padding: 9px 18px; border-radius: 999px; border: 1.5px solid var(--line);
  background: transparent; color: var(--ink); cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.chip:hover { border-color: var(--ink); }
.chip-n { opacity: 0.5; font-size: 0.9em; margin-left: 2px; }
.chip.is-active .chip-n { opacity: 0.7; }
.chip.is-active { background: var(--magenta); color: #fff; border-color: var(--magenta); }

.artist-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.artist-card {
  display: block; text-decoration: none; color: inherit;
  width: 100%; padding: 0; font: inherit; text-align: left; cursor: pointer;
  background: var(--paper-card); border: 1.5px solid var(--line); border-radius: var(--radius);
  overflow: hidden;
}
.artist-card:hover, .artist-card:focus-visible { border-color: var(--magenta); }
.artist-photo { position: relative; aspect-ratio: 1; overflow: hidden; background: var(--ink-soft); }
/* Two stacked layers so a shot change cross-fades instead of flashing white
   while the next file decodes. Only the top layer is ever swapped. */
.artist-photo img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity 900ms var(--ease-out);
}
.artist-photo img.is-on { opacity: 1; }

/* Progress pips — three faint marks so it reads as a set, not a glitch. */
.shot-pips {
  position: absolute; left: 0; right: 0; bottom: 8px; z-index: 2;
  display: flex; justify-content: center; gap: 5px;
  opacity: 0; transition: opacity 0.3s ease; pointer-events: none;
}
.artist-card.is-cycling .shot-pips { opacity: 1; }
.shot-pips i {
  width: 4px; height: 4px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.4);
  box-shadow: 0 0 0 1px rgba(10, 20, 26, 0.35);
  transition: background 0.4s ease, box-shadow 0.4s ease;
}
.shot-pips i.is-on {
  background: var(--neon-magenta);
  box-shadow: 0 0 6px rgba(255, 61, 166, 0.9);
}
@media (prefers-reduced-motion: reduce) {
  .artist-photo img { transition: none; }
  .shot-pips { display: none; }
}

.artist-info { padding: 14px 16px 16px; }
.artist-info h3 {
  font-family: var(--font-body); font-weight: 700; font-size: 0.95rem;
  text-transform: none; letter-spacing: 0; line-height: 1.25;
}
.artist-info p {
  font-family: var(--font-mono); font-size: 0.7rem; color: var(--gray);
  text-transform: uppercase; letter-spacing: 0.06em; margin-top: 6px; line-height: 1.4;
}

.grid-footer {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  margin-top: 36px;
}
.grid-count { font-size: 0.75rem; color: var(--gray); text-transform: uppercase; letter-spacing: 0.12em; }
.grid-note { margin-top: 22px; text-align: center; font-size: 0.8rem; color: var(--gray); text-transform: uppercase; letter-spacing: 0.08em; }
.grid-note a { color: var(--magenta-lit); }

/* ============ program ============ */
.day-tabs { display: flex; gap: 12px; margin-bottom: 36px; flex-wrap: wrap; }
.day-tab {
  flex: 1 1 160px; text-align: left; cursor: pointer;
  background: transparent; color: var(--ink);
  border: 1.5px solid var(--line-light); border-radius: var(--radius);
  padding: 18px 22px; transition: background 0.15s, border-color 0.15s;
}
.day-tab .day-name { display: block; font-family: var(--font-display); text-transform: uppercase; font-size: 1.2rem; }
.day-tab .day-hours { display: block; font-size: 0.78rem; color: rgba(237, 243, 243,0.55); margin-top: 6px; letter-spacing: 0.08em; }
.day-tab:hover { border-color: var(--ink); }
.day-tab.is-active { background: var(--magenta); border-color: var(--magenta); }
.day-tab.is-active .day-hours { color: rgba(255,255,255,0.8); }

.timetable { list-style: none; border-top: 1px solid var(--line-light); }
.timetable li {
  display: grid; grid-template-columns: 110px 1fr; gap: 24px; align-items: baseline;
  padding: 16px 8px; border-bottom: 1px solid var(--line-light);
}
.timetable .tt-time { font-family: var(--font-mono); font-weight: 600; color: var(--teal-lit); font-size: 0.95rem; }
.timetable .tt-event { font-weight: 500; }
.timetable li.tt-highlight .tt-event { color: var(--yellow); font-weight: 700; }

/* ============ tickets ============ */
.tickets-card {
  display: grid; grid-template-columns: 1.2fr 1fr; gap: clamp(32px, 5vw, 72px);
  background: var(--paper-card); border: 2px solid var(--magenta); border-radius: 22px;
  padding: clamp(32px, 5vw, 64px);
  position: relative; overflow: hidden;
}
.tickets-card::after {
  content: ""; position: absolute; right: -80px; top: -80px; width: 260px; height: 260px;
  background: radial-gradient(circle, rgba(255,210,63,0.5), transparent 65%);
}
.tickets-copy .btn { margin-top: 28px; }
.fine-print { font-size: 0.75rem; color: var(--gray); margin-top: 16px; text-transform: uppercase; letter-spacing: 0.08em; }

.tickets-facts { list-style: none; display: grid; gap: 14px; align-content: center; position: relative; z-index: 1; }
.tickets-facts li {
  border: 1.5px solid var(--line); border-radius: var(--radius); padding: 16px 20px;
  display: grid; gap: 2px; background: var(--paper);
}
.tickets-facts strong { font-family: var(--font-display); text-transform: uppercase; font-size: 0.95rem; }
.tickets-facts span { color: var(--gray); font-size: 0.92rem; }

/* ============ venue ============ */
.venue-grid { display: grid; grid-template-columns: 1.1fr 1fr; gap: clamp(32px, 6vw, 80px); align-items: center; }
.venue-address { font-style: normal; margin: 22px 0 28px; color: rgba(237, 243, 243,0.7); line-height: 1.8; font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.08em; }
.venue-tips { list-style: none; display: grid; gap: 14px; }
.venue-tips li {
  border: 1.5px solid var(--line-light); border-radius: var(--radius); padding: 18px 22px;
  display: grid; gap: 4px;
}
.venue-tips strong { font-family: var(--font-display); text-transform: uppercase; font-size: 0.9rem; color: var(--teal-lit); }
.venue-tips span { color: rgba(237, 243, 243,0.7); font-size: 0.95rem; }

/* Venue photo strip below the details. The figure owns the aspect ratio and
   the image fills it with object-fit, so two shots of different native sizes
   still line up on one row. */
.venue-photos {
  margin-top: clamp(30px, 5vw, 56px);
  display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(14px, 2vw, 22px);
}
.venue-photo {
  margin: 0; aspect-ratio: 3 / 2; overflow: hidden;
  border-radius: var(--radius); border: 1px solid var(--line);
  background: var(--deep);
}
.venue-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 720px) { .venue-photos { grid-template-columns: 1fr; } }

/* ============ faq ============ */
.faq-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.faq-col { background: var(--paper-card); border: 1.5px solid var(--line); border-radius: var(--radius); padding: 28px; }
.faq-col-title {
  display: inline-block; font-size: 1.4rem; padding: 6px 18px; border-radius: 10px; margin-bottom: 20px;
  transform: rotate(-1.5deg);
}
.faq-col-title.yes { background: var(--teal-deep); color: #fff; }
.faq-col-title.no { background: var(--magenta); color: #fff; }
.faq-list { list-style: none; }
.faq-list li {
  padding: 12px 0 12px 26px; border-bottom: 1px solid var(--line);
  position: relative; font-size: 0.97rem; color: var(--ink-soft);
}
.faq-list li:last-child { border-bottom: 0; }
.faq-list li::before { content: "—"; position: absolute; left: 0; color: var(--gray); }

/* ============ newsletter ============ */
/* The one light-background section left, so it opts out of the dark theme's
   light text entirely rather than relying on per-element overrides. */
.newsletter { background: var(--yellow); color: var(--deep); }
.newsletter h2, .newsletter h3, .newsletter p, .newsletter label, .newsletter a { color: var(--deep); }
.newsletter .section-lede { color: rgba(10, 20, 26, 0.72); }
.newsletter-inner { display: grid; grid-template-columns: 1.2fr 1fr; gap: 40px; align-items: center; }
.newsletter-form { display: flex; gap: 12px; }
.newsletter-form input {
  flex: 1; min-width: 0; font: inherit; padding: 15px 20px; border-radius: 999px;
  border: 2px solid var(--ink); background: #fff;
}
.newsletter-form input:focus { outline: 3px solid var(--magenta); outline-offset: 2px; }

/* ============ footer ============ */
.site-footer { background: var(--deep); color: var(--ink); padding: 64px 0 32px; }
.footer-grid { display: grid; grid-template-columns: 1.3fr 1fr 1fr 1.2fr; gap: 40px; padding-bottom: 48px; border-bottom: 1px solid var(--line-light); }
.footer-logo { width: auto; height: 42px; margin-bottom: 4px; }
.footer-tag { margin-top: 16px; color: rgba(237, 243, 243,0.65); font-size: 0.95rem; }
.footer-grid h4 { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.14em; color: var(--teal-lit); margin-bottom: 16px; font-weight: 500; }
.footer-grid a { display: block; text-decoration: none; padding: 5px 0; color: rgba(237, 243, 243,0.85); font-size: 0.95rem; }
.footer-grid a:hover { color: var(--magenta-lit); }
.footer-addr { color: rgba(237, 243, 243,0.55); font-size: 0.85rem; margin-top: 10px; line-height: 1.7; }
.footer-legal { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; padding-top: 24px; font-size: 0.82rem; color: rgba(237, 243, 243,0.5); }
.footer-legal a { color: rgba(237, 243, 243,0.7); }

/* ============ page hero (subpages) ============ */
.page-hero {
  position: relative; overflow: hidden;
  padding: clamp(48px, 7vh, 92px) 0 clamp(36px, 5vh, 60px);
  border-bottom: 1.5px solid var(--line);
}
.page-hero h1 { font-size: clamp(2.5rem, 7.5vw, 5.4rem); line-height: 0.94; }
.page-hero .hero-blurb { margin-top: 22px; }
.page-hero .hero-actions { margin-top: 28px; }
.page-hero::after {
  content: ""; position: absolute; pointer-events: none;
  width: 420px; height: 420px; right: -150px; top: -170px;
  background: radial-gradient(circle at 45% 45%, rgba(31,185,165,0.3), transparent 62%);
}
.page-hero .container { position: relative; z-index: 1; }

/* active nav item */
.site-nav a[aria-current="page"]:not(.nav-cta) { color: var(--magenta-lit); }
.site-nav a[aria-current="page"].nav-cta { background: var(--neon-magenta); color: #0A141A; }

/* ============ teaser blocks (home) ============ */
.teaser-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 24px; flex-wrap: wrap; margin-bottom: clamp(28px, 4vh, 44px);
}
.teaser-head .section-head { margin-bottom: 0; }
.link-arrow {
  display: inline-flex; align-items: center; gap: 8px; white-space: nowrap;
  font-weight: 700; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.07em;
  text-decoration: none; padding-bottom: 5px; border-bottom: 2px solid var(--magenta);
  transition: gap 0.18s var(--ease-out), color 0.18s ease;
}
.link-arrow:hover { color: var(--magenta-lit); gap: 14px; }
.section-dark .link-arrow { border-bottom-color: var(--teal-lit); }
.section-dark .link-arrow:hover { color: var(--teal-lit); }

/* day cards linking through to the program */
.day-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.day-card {
  display: block; text-decoration: none; padding: 30px 26px 34px;
  border: 1.5px solid var(--line-light); border-radius: var(--radius);
}
.day-card:hover { background: rgba(237, 243, 243,0.05); border-color: var(--ink); }
.day-card .day-name { display: block; font-family: var(--font-display); text-transform: uppercase; font-size: 1.5rem; }
.day-card .day-hours { display: block; font-family: var(--font-mono); font-size: 0.8rem; color: var(--teal-lit); letter-spacing: 0.1em; margin-top: 8px; }
.day-card .day-peek { display: block; color: rgba(237, 243, 243,0.6); font-size: 0.92rem; margin-top: 16px; }

/* ============ full-width CTA band ============ */
.cta-band { background: var(--magenta); color: #fff; text-align: center; padding: clamp(56px, 9vh, 104px) 0; }
.cta-band h2 { font-size: clamp(2rem, 5vw, 3.6rem); }
.cta-band p { max-width: 48ch; margin: 18px auto 0; color: rgba(255,255,255,0.85); }
.cta-band .btn { margin-top: 30px; }
.cta-band .btn-primary { background: var(--deep); color: var(--ink); }
.cta-band .btn-primary:hover { background: var(--neon-gold); color: #0A141A; }
.cta-band .fine-print { color: rgba(255,255,255,0.75); }

/* ============ traders ============ */
.offer-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.offer {
  background: var(--paper-card); border: 1.5px solid var(--line); border-radius: var(--radius);
  padding: 26px 24px 30px;
}
.offer h3 { margin-bottom: 10px; }
.offer p { color: var(--gray); font-size: 0.96rem; }

.stand-split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(28px, 5vw, 64px); align-items: start; }
.stand-list { list-style: none; display: grid; gap: 12px; margin-top: 24px; }
.stand-list li {
  display: grid; grid-template-columns: auto 1fr; gap: 14px; align-items: baseline;
  padding: 14px 0; border-bottom: 1px solid var(--line-light);
}
.stand-list li:last-child { border-bottom: 0; }
.stand-list .mono { color: var(--teal-lit); font-size: 0.8rem; letter-spacing: 0.1em; text-transform: uppercase; }

/* ============ entertainment gallery ============
   Masonry-ish columns so portrait and landscape shots sit together
   without cropping either. */
.gallery-wrap { position: relative; }
.gallery {
  display: flex; gap: 14px; overflow-x: auto; scroll-snap-type: x mandatory;
  scroll-behavior: smooth; padding: 4px 2px 14px;
  scrollbar-width: none; -ms-overflow-style: none;
}
.gallery::-webkit-scrollbar { display: none; }
.gallery figure {
  flex: 0 0 clamp(220px, 26vw, 320px); margin: 0; scroll-snap-align: start;
  aspect-ratio: 3 / 4; overflow: hidden; border-radius: 12px;
  border: 1.5px solid var(--line-light);
}
.gallery figure img { width: 100%; height: 100%; object-fit: cover; }

/* arrows so it can be driven without swiping */
.gallery-btn {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  width: 48px; height: 48px; display: grid; place-items: center;
  border: 1.5px solid rgba(59, 240, 218, 0.4); border-radius: 50%; cursor: pointer;
  background: rgba(10, 20, 26, 0.85); color: var(--ink); font-size: 1.3rem;
  transition: background 0.18s ease, box-shadow 0.18s ease, opacity 0.18s ease;
}
.gallery-btn:hover { background: var(--magenta); box-shadow: var(--glow-md) rgba(255, 61, 166, 0.7); }
.gallery-btn[disabled] { opacity: 0.25; cursor: default; }
.gallery-prev { left: -10px; }
.gallery-next { right: -10px; }
@media (max-width: 720px) {
  .gallery-prev { left: 2px; }
  .gallery-next { right: 2px; }
}
.gallery img {
  width: 100%; height: auto; border-radius: 8px; display: block;
  background: var(--ink-soft);
  transition: transform 0.3s var(--ease-out), filter 0.3s ease;
}
.gallery figure:hover img { transform: scale(1.02); filter: saturate(1.1); }

/* ============ cookie banner ============ */
.cookie {
  position: fixed; z-index: 200; inset: auto 16px 16px 16px;
  max-width: 560px; margin-inline: auto;
  background: var(--deep); color: var(--ink);
  border: 1.5px solid var(--line-light); border-radius: var(--radius);
  padding: 22px 24px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.35);
  display: none;
}
.cookie.is-open { display: block; animation: cookieIn 0.4s var(--ease-out); }
/* The notice outranks the mobile menu (z-index 200 vs 99) and was sitting on
   top of the language switcher and pass button. Two stacked sheets is wrong
   anyway — stand the notice down while the menu is open; it returns on close.
   Same for the artist modal, which covers the whole screen at z-index 400. */
body.nav-open .cookie.is-open,
body.amodal-open .cookie.is-open { display: none; }
@keyframes cookieIn { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
.cookie p { font-size: 0.9rem; color: rgba(237, 243, 243, 0.75); margin-bottom: 16px; }
.cookie a { color: var(--teal-lit); }
.cookie-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.cookie .btn { padding: 11px 22px; font-size: 0.8rem; }
.cookie .btn-ghost { border-color: rgba(237, 243, 243, 0.4); color: var(--ink); }
.cookie .btn-ghost:hover { background: var(--ink); color: var(--deep); }

/* ============ contest categories ============ */
.cat-days { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; align-items: start; }
.cat-day {
  background: var(--paper-card); border: 1.5px solid var(--line); border-radius: var(--radius);
  padding: 26px 24px 28px;
}
.section-dark .cat-day { background: rgba(237, 243, 243, 0.05); border-color: var(--line-light); }
.cat-day-title {
  font-size: 1.05rem; padding-bottom: 14px; margin-bottom: 6px;
  border-bottom: 2px solid var(--magenta);
}
.section-dark .cat-day-title { border-bottom-color: var(--teal-lit); }
.cat-list { list-style: none; }
.cat-list li {
  padding: 12px 0 12px 26px; position: relative;
  border-bottom: 1px solid var(--line); font-size: 0.97rem;
}
.section-dark .cat-list li { border-bottom-color: var(--line-light); }
.cat-list li:last-child { border-bottom: 0; }
.cat-list li::before {
  content: "★"; position: absolute; left: 0; top: 12px;
  color: var(--magenta-lit); font-size: 0.8rem;
}
.section-dark .cat-list li::before { color: var(--gold); }
.cat-note {
  display: block; font-family: var(--font-mono); font-size: 0.7rem;
  text-transform: uppercase; letter-spacing: 0.1em; color: var(--gray); margin-top: 3px;
}
.section-dark .cat-note { color: rgba(237, 243, 243, 0.55); }

/* ============ contest rules ============ */
.rule-list { list-style: none; counter-reset: rule; display: grid; gap: 2px; }
.rule-list li {
  counter-increment: rule; position: relative;
  padding: 18px 0 18px 54px; border-bottom: 1px solid var(--line);
  font-size: 0.98rem; color: var(--ink-soft);
}
.rule-list li:last-child { border-bottom: 0; }
.rule-list li::before {
  content: counter(rule, decimal-leading-zero);
  position: absolute; left: 0; top: 18px;
  font-family: var(--font-mono); font-size: 0.8rem; font-weight: 600;
  color: var(--magenta-lit); letter-spacing: 0.06em;
}

.dq-list { list-style: none; display: grid; gap: 16px; }
.dq-list li {
  border: 1.5px solid var(--red); border-radius: var(--radius);
  padding: 22px 26px; position: relative;
  color: var(--ink); font-size: 0.98rem;
}
.dq-list li::before {
  content: "!"; display: inline-grid; place-items: center;
  width: 22px; height: 22px; margin-right: 12px; vertical-align: -4px;
  border-radius: 50%; background: var(--red); color: var(--ink);
  font-family: var(--font-display); font-size: 0.8rem;
}

/* ============ sponsor logo wall ============ */
.logo-wall { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.logo-slot {
  /* Square tile on a near-black ground, no white plate. The logos turned out
     to be opaque images with their own (mostly black) backgrounds — not
     dark-on-transparent — so the old light plate framed every one in white,
     which is what looked wrong. A near-black tile makes those black grounds
     blend edge to edge, and `contain` keeps the whole logo (no cropped text)
     with any letterbox falling on black rather than white. */
  aspect-ratio: 1 / 1; display: flex; align-items: center; justify-content: center; overflow: hidden;
  border: 1.5px solid var(--line); border-radius: var(--radius);
  background: #0C0F13; padding: 10px;
}
.logo-slot:hover { border-color: var(--neon-teal); }
.logo-slot img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; display: block; }
.logo-slot span {
  font-family: var(--font-mono); font-size: 0.7rem; text-transform: uppercase;
  letter-spacing: 0.12em; color: var(--gray);
}
/* ============ confirmed traders ============
   Same treatment as .logo-slot — the logos are opaque, mostly on their own
   black backgrounds, so a near-black square tile lets them sit edge to edge
   with no white frame. */
.trader-wall { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.trader {
  display: block; text-decoration: none; color: inherit; text-align: center;
  padding: 22px 20px 20px; border-radius: var(--radius);
  border: 1.5px solid var(--line-light); background: rgba(237, 243, 243, 0.05);
}
.trader:hover { border-color: var(--teal-lit); background: rgba(237, 243, 243, 0.09); }
.trader-logo {
  aspect-ratio: 1 / 1; display: flex; align-items: center; justify-content: center;
  overflow: hidden; background: #0C0F13; border-radius: 10px; padding: 10px; margin-bottom: 16px;
}
.trader-logo img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
.trader h3 { font-size: 0.95rem; }
.trader .mono {
  font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--gray); margin-top: 6px;
}
.section-dark .trader .mono { color: rgba(237, 243, 243, 0.5); }
.section-dark .trader-link { color: var(--teal-lit); }
a.trader:hover .trader-link { color: var(--paper); }

/* ============ art expo ============ */
.art-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 26px; }
.art-artist { display: flex; flex-direction: column; gap: 8px; }
.art-lead {
  aspect-ratio: 3 / 2; overflow: hidden; border-radius: var(--radius);
  background: var(--ink-soft); border: 1.5px solid var(--line);
}
.art-lead img { width: 100%; height: 100%; object-fit: cover; }
.art-thumbs { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.art-thumb {
  aspect-ratio: 3 / 2; padding: 0; overflow: hidden; cursor: pointer;
  background: var(--ink-soft); border: 1.5px solid var(--line); border-radius: 8px;
  opacity: 0.55; transition: opacity 0.18s ease, border-color 0.18s ease;
}
.art-thumb img { width: 100%; height: 100%; object-fit: cover; }
.art-thumb:hover { opacity: 0.85; }
.art-thumb.is-on { opacity: 1; border-color: var(--magenta); }
.art-artist h3 { font-size: 1rem; margin-top: 4px; }

.tier-head {
  display: flex; align-items: baseline; gap: 14px; margin: 0 0 20px;
  font-family: var(--font-mono); font-size: 0.75rem;
  text-transform: uppercase; letter-spacing: 0.16em; color: var(--magenta-lit);
}
.tier-head::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.tier + .tier { margin-top: 48px; }

/* ============ next edition (2027) ============
   Deliberately off-palette: the 2027 poster is red/black, so this block
   reads as a different edition rather than more 2026 content. */
.next-edition { background: var(--deep); color: var(--ink); }
.next-edition .eyebrow { color: var(--red); }
.next-grid {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(32px, 5vw, 72px); align-items: center;
}
.next-dates {
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  font-family: var(--font-display); font-size: clamp(2rem, 4.5vw, 3.4rem);
  margin: 18px 0 4px; color: var(--red);
}
.next-dates span {
  font-family: var(--font-mono); font-size: 0.9rem; color: var(--ink);
  text-transform: uppercase; letter-spacing: 0.14em;
}
.next-poster { width: clamp(210px, 24vw, 330px); transform: rotate(-2deg); }
.next-poster img {
  width: 100%; height: auto; border-radius: 6px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.45);
}

/* pre-registration form */
.prereg { margin-top: 26px; display: grid; gap: 12px; max-width: 440px; }
.prereg-row { display: flex; gap: 12px; flex-wrap: wrap; }
.prereg input, .prereg select {
  flex: 1 1 160px; min-width: 0; font: inherit;
  padding: 14px 18px; border-radius: 999px;
  border: 1.5px solid rgba(237, 243, 243, 0.3);
  background: rgba(237, 243, 243, 0.06); color: var(--ink);
}
.prereg input::placeholder { color: rgba(237, 243, 243, 0.5); }
/* The dropdown list is painted by the OS, not the page — on Windows/Linux it
   comes up on a white sheet, so the options need their own dark text. */
.prereg select option { color: #0A141A; background: #fff; }
.prereg .btn-primary { background: var(--red-deep); }
.prereg .btn-primary:hover { background: var(--ink); color: var(--deep); }
.prereg-note { font-size: 0.78rem; color: rgba(237, 243, 243, 0.55); }
.prereg-note a { color: var(--red); }

/* Confirmation line under either sign-up form. Teal for "done", red for
   "that failed" — never colour alone, the wording says which it is too.
   These two forms sit on opposite backgrounds, so the colours cannot be
   shared: the pre-registration block is near-black, the newsletter is the
   poster yellow. The light-on-dark pair scores 1.5:1 on yellow, which is
   not a readable message, it is a smudge. */
.form-note {
  font-size: 0.8rem; line-height: 1.5; margin-top: 10px;
  color: var(--teal-lit);
}
.form-note.is-bad { color: #FF9A8C; }

.newsletter .form-note { color: rgba(10, 20, 26, 0.82); }
/* One step deeper than --red-deep, which only reaches 3.9:1 against the
   poster yellow. This clears AA at 5.6:1 and still reads as the same red. */
.newsletter .form-note.is-bad { color: #A31D13; }
.newsletter-form { flex-wrap: wrap; }
.newsletter-form .form-note { flex-basis: 100%; margin-top: 4px; }

/* ============ stage lineup ============ */
.stage-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.act {
  border: 1.5px solid var(--line-light); border-radius: var(--radius);
  padding: 24px; display: grid; gap: 8px; align-content: start;
}
.act:hover { border-color: var(--teal); }
.act h3 { font-size: 1.15rem; }
.act .act-kind { font-family: var(--font-mono); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.12em; color: var(--teal-lit); }
.act p { color: rgba(237, 243, 243,0.65); font-size: 0.93rem; }
.act-ig {
  justify-self: start; margin-top: 4px;
  font-size: 0.74rem; letter-spacing: 0.06em;
  color: var(--teal-lit); text-decoration: none;
}
.act-ig:hover { color: var(--teal); text-decoration: underline; }

/* ============ motion ============
   One easing curve across the whole page so everything feels related:
   a quick start that settles, like a poster being pressed down. */
:root { --ease-out: cubic-bezier(0.22, 0.85, 0.3, 1); --stagger: 55ms; }

.reveal {
  opacity: 0;
  transform: translateY(26px) scale(0.985);
  transition:
    opacity 0.7s var(--ease-out),
    transform 0.7s var(--ease-out);
  transition-delay: calc(var(--i, 0) * var(--stagger));
  will-change: opacity, transform;
}
/* Artist cards drift in with a slight tilt that straightens out. Declared
   before the settled state so one .reveal.is-visible clears every variant —
   a per-variant `.x.reveal.is-visible` reset would outrank the :hover lift
   at the bottom of this file and the card would never leave the page. */
.artist-card.reveal { transform: translateY(30px) rotate(-1.2deg); }

.reveal.is-visible { opacity: 1; transform: none; will-change: auto; }

/* Pillars rise on a shared curve, accent bar sweeps after they land */
.pillar.reveal.is-visible::before {
  transform: scaleX(1);
  transition-delay: calc(var(--i, 0) * var(--stagger) + 0.35s);
}
.pillar:hover::before { transition-delay: 0s; }

/* Timetable rows cascade whenever the day changes */
.tt-enter {
  animation: rowIn 0.55s var(--ease-out) backwards;
  animation-delay: calc(var(--i, 0) * 38ms);
}
@keyframes rowIn {
  from { opacity: 0; transform: translateX(-14px); }
  to { opacity: 1; transform: none; }
}

/* Hero types itself into place on load */
.hero-title .line {
  animation: lineIn 0.9s var(--ease-out) backwards;
}
.hero-title .line:nth-child(1) { animation-delay: 0.05s; }
.hero-title .line:nth-child(2) { animation-delay: 0.16s; }
.hero-title .line:nth-child(3) { animation-delay: 0.27s; }
@keyframes lineIn {
  from { opacity: 0; transform: translateY(0.24em) skewY(2deg); }
  to { opacity: 1; transform: none; }
}
.hero-kicker, .hero-meta {
  animation: fadeUp 0.8s var(--ease-out) backwards;
}
.hero-kicker { animation-delay: 0.02s; }
.hero-meta { animation-delay: 0.42s; }
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
  .hero-title .line, .hero-kicker, .hero-meta, .tt-enter { animation: none; }
}

/* ============ responsive ============ */
@media (max-width: 1040px) {
  /* Posters step down before the type gets squeezed */
  .hero-inner, .next-grid { grid-template-columns: 1fr; gap: 36px; }
  .hero-poster { width: min(300px, 62vw); margin: 0 auto; transform: rotate(-1.5deg); }
  .next-poster { width: min(280px, 60vw); margin: 0 auto; }
}

@media (max-width: 960px) {
  .pillars { grid-template-columns: repeat(2, 1fr); }
  /* Three-up on tablets: two would make each card wider than it is on a
     desktop, which reads as broken rather than roomy. */
  .artist-grid { grid-template-columns: repeat(3, 1fr); }
  .day-cards, .offer-grid, .stage-grid, .cat-days { grid-template-columns: 1fr; }
  .value-strip, .logo-wall, .trader-wall, .art-grid { grid-template-columns: repeat(2, 1fr); }
  .judges-row { grid-template-columns: repeat(3, 1fr); }
  .stand-split { grid-template-columns: 1fr; }
  .tickets-card, .venue-grid, .newsletter-inner { grid-template-columns: 1fr; }
  .hero-meta { grid-template-columns: 1fr; gap: 24px; }
}

/* The grouped nav needs more room than a phone breakpoint allows, so the
   overlay menu takes over at tablet width while the rest of the layout
   stays desktop until 720px. */
@media (max-width: 900px) {
  /* ---- nav ----
     backdrop-filter would make .site-header the containing block for this
     fixed panel, collapsing it to the header's height. Drop the blur on
     mobile and make the bar solid so the panel resolves against the viewport. */
  .site-header { backdrop-filter: none; background: var(--paper); }
  .site-header.is-stuck { background: var(--paper); box-shadow: 0 6px 26px rgba(0,0,0,0.5); }

  .site-nav {
    position: fixed; z-index: 99;
    top: var(--header-h, 61px); right: 0; bottom: 0; left: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--paper); border-top: 2px solid var(--neon-magenta);
    padding: 12px 22px 40px;
    display: none; overflow-y: auto;               /* long menu must scroll */
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
  .site-nav.is-open { display: flex; }
  /* Rows share the space above the footer so the sheet reads as a full
     screen rather than a short list with a void under it. They still grow
     past their share when a group is expanded. */
  .site-nav > a,
  .site-nav > .nav-group { flex: 1 1 auto; min-height: 62px; }
  .site-nav > a {
    display: flex; align-items: center;
    padding: 8px 0; border-bottom: 1px solid var(--line); font-size: 1rem;
  }
  .nav-group { display: flex; flex-direction: column; justify-content: center; }

  /* Footer zone sits against the bottom of the panel so the sheet reads as
     full-height rather than a short list with dead space beneath it. */
  .nav-foot {
    display: flex; flex-direction: column; gap: 14px;
    margin-top: auto; padding-top: 26px;
    border-top: 1.5px solid var(--line);
  }
  .lang-switch { align-self: flex-start; margin: 0; }
  .lang-btn { padding: 10px 16px; min-height: 44px; font-size: 0.8rem; }
  .site-nav a.nav-cta {
    border: 0; text-align: center; margin: 0; padding: 17px;
    font-size: 0.95rem; justify-content: center;
  }
  .nav-contact {
    display: block; text-align: center;
    font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.06em;
    text-transform: none; color: var(--gray); padding: 4px 0 2px;
  }

  /* Groups become tap-to-expand accordions so the whole menu fits on screen */
  .nav-group { border-bottom: 1px solid var(--line); }
  .nav-trigger {
    width: 100%; justify-content: space-between;
    padding: 8px 0; min-height: 44px;
    cursor: pointer; font-size: 1rem; letter-spacing: 0.07em; color: inherit;
  }
  .nav-trigger::after { width: 8px; height: 8px; margin-top: -4px; }
  .nav-group[data-open="true"] .nav-trigger { color: var(--magenta-lit); }

  .nav-menu {
    position: static; opacity: 1; visibility: visible; transform: none;
    min-width: 0; padding: 0; margin: 0;
    background: none; border: 0; box-shadow: none;
    max-height: 0; overflow: hidden;
    transition: max-height 0.3s var(--ease-out);
  }
  .nav-group[data-open="true"] { max-height: none; }
  .nav-group[data-open="true"] .nav-menu { max-height: 320px; padding-bottom: 10px; }
  .nav-menu a { padding: 12px 0 12px 16px; font-size: 0.92rem; }
  .nav-menu a:hover { background: none; color: var(--magenta-lit); }
  .nav-toggle { display: block; }
  .nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7.5px) rotate(45deg); }
  .nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
  .nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7.5px) rotate(-45deg); }
  /* scroll lock lives on .is-scroll-locked (set in main.js) — overflow:hidden
     alone is ignored by iOS Safari, so the body has to be pinned instead */
  body.nav-open { overflow: hidden; }
}

@media (max-width: 720px) {

  /* ---- rhythm: tighter sections, smaller gaps ---- */
  .section { padding: 56px 0; }
  .container, .hero-inner { padding-left: 20px; padding-right: 20px; }
  .section-head { margin-bottom: 28px; }
  h2 { font-size: clamp(1.75rem, 8vw, 2.3rem); }

  /* ---- hero ---- */
  .hero { padding: 28px 0 44px; }
  .hero-title { font-size: clamp(3.4rem, 21vw, 6rem); }
  .hero-kicker { font-size: 0.7rem; letter-spacing: 0.14em; margin-bottom: 16px; }
  .hero-poster { width: min(268px, 72vw); }
  .hero-blurb { font-size: 1rem; }
  .hero-actions .btn { width: 100%; justify-content: center; }
  .hero-dates { flex-wrap: wrap; }

  /* ---- grids collapse ---- */
  .faq-cols, .pillars, .value-strip { grid-template-columns: 1fr; }
  /* Artists stay two-up on phones — one card per row makes each portrait
     enormous and pushes the lineup off the screen. */
  .artist-grid { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .artist-info { padding: 11px 12px 13px; }
  .artist-info h3 { font-size: 0.85rem; }
  .artist-info p { font-size: 0.63rem; letter-spacing: 0.04em; margin-top: 5px; }
  .stats { grid-template-columns: 1fr; gap: 30px; }
  .stat + .stat::before { left: 22%; right: 22%; top: -15px; bottom: auto; width: auto; height: 1.5px; }
  .logo-wall, .trader-wall { grid-template-columns: repeat(2, 1fr); }
  .art-grid { grid-template-columns: 1fr; }
  .judges-row { grid-template-columns: repeat(2, 1fr); }
  .timetable li { grid-template-columns: 74px 1fr; gap: 12px; padding: 14px 4px; }
  .newsletter-form { flex-direction: column; }
  .newsletter-form .btn { justify-content: center; }
  .cookie { inset: auto 12px 12px 12px; padding: 20px; }
  .cookie .btn { flex: 1 1 auto; justify-content: center; min-height: 44px; }
  .prereg-row { flex-direction: column; }
  .prereg .btn { width: 100%; justify-content: center; }
  .prereg input, .prereg select { flex: 1 1 auto; width: 100%; }

  /* ---- comfortable tap targets (44px min) ---- */
  .chip { padding: 12px 18px; }
  .artist-search { max-width: none; }
  /* 16px exactly: iOS Safari zooms the page in on focus for anything
     smaller, which throws the grid off screen mid-search. */
  .artist-search-input { font-size: 16px; padding-top: 14px; padding-bottom: 14px; }
  .artist-search-clear { width: 38px; height: 38px; }
  .day-tab { flex: 1 1 100%; padding: 16px 20px; }
  .grid-footer .btn { width: 100%; justify-content: center; }
  .footer-grid a,
  .footer-legal a { display: flex; align-items: center; min-height: 44px; padding: 4px 0; }
  .link-arrow { min-height: 44px; align-items: center; }
  .brand { min-height: 44px; }
  .faq-list li { padding-top: 14px; padding-bottom: 14px; }

  /* ---- keep small labels legible (never below 12px) ---- */
  .hero-kicker { font-size: 0.8rem; }
  .eyebrow, .value-label, .act .act-kind, .grid-count,
  .stand-list .mono, .footer-grid h4, .artist-info p { font-size: 0.75rem; }
  .fine-print, .grid-note { font-size: 0.78rem; }
  .nav-toggle { padding: 10px; }
  .brand-logo { height: 28px; }

  /* ---- footer stacks ---- */
  .footer-grid { grid-template-columns: 1fr; gap: 30px; padding-bottom: 34px; }
  .footer-legal { flex-direction: column; gap: 10px; }

  /* ---- cards breathe less ---- */
  .pillar { padding: 24px 20px 22px; }
  .tickets-card { padding: 28px 22px; }
  .cta-band { padding: 52px 0; }
  .cta-band .btn { width: 100%; justify-content: center; }
}

@media (max-width: 420px) {
  .judges-row { grid-template-columns: repeat(2, 1fr); }
  .logo-wall { grid-template-columns: 1fr; }
  .artist-grid { gap: 10px; }
  .artist-info { padding: 9px 10px 11px; }
  .hero-title { font-size: clamp(3rem, 20vw, 4.6rem); }
}


/* ============================================================
   NEON / INTERACTION LAYER
   Glow is decoration only — every element underneath still meets
   contrast on its own, so nothing depends on the glow rendering.
   ============================================================ */

/* scroll progress ------------------------------------------------ */
.scroll-progress {
  position: fixed; top: 0; left: 0; height: 3px; width: 100%; z-index: 300;
  transform: scaleX(0); transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--neon-magenta), var(--neon-gold), var(--neon-teal));
  box-shadow: var(--glow-sm) rgba(255, 61, 166, 0.7);
  pointer-events: none;
}

/* buttons --------------------------------------------------------- */
.btn-primary {
  position: relative;
  box-shadow: var(--glow-sm) rgba(255, 61, 166, 0.35);
}
.btn-primary:hover {
  box-shadow: var(--glow-md) rgba(255, 61, 166, 0.75), 0 8px 22px rgba(20, 38, 46, 0.2);
}
.section-dark .btn-ghost-light:hover,
.cta-band .btn-primary:hover { box-shadow: var(--glow-md) rgba(255, 208, 61, 0.5); }

.nav-cta { box-shadow: var(--glow-sm) rgba(255, 61, 166, 0.4); }
.nav-cta:hover { box-shadow: var(--glow-md) rgba(255, 61, 166, 0.8); }

/* eyebrow pills get a faint halo ---------------------------------- */
.eyebrow { box-shadow: var(--glow-sm) rgba(255, 61, 166, 0.18); }
.section-dark .eyebrow { box-shadow: var(--glow-sm) rgba(59, 240, 218, 0.28); }

/* headings on dark pick up a soft neon edge ----------------------- */
.section-dark h2,
.next-edition h2 { text-shadow: 0 0 34px rgba(59, 240, 218, 0.18); }
.cta-band h2 { text-shadow: 0 0 40px rgba(255, 255, 255, 0.28); }

/* cards ----------------------------------------------------------- */
.offer:hover, .cat-day:hover { border-color: var(--magenta); }
.venue-tips li:hover { border-color: var(--teal-lit); }

/* stats band glows ------------------------------------------------ */
.stats-band { position: relative; overflow: hidden; }
.stats-band::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(60% 120% at 50% 0%, rgba(255, 255, 255, 0.22), transparent 70%);
}
.stat-num { text-shadow: 0 0 30px rgba(20, 38, 46, 0.18); }

/* ticker gets a neon underline ------------------------------------ */
.ticker { box-shadow: inset 0 -3px 0 0 var(--neon-magenta), 0 0 24px rgba(255, 61, 166, 0.25); }
.ticker-track i { text-shadow: var(--glow-sm) var(--neon-magenta); }

/* links ----------------------------------------------------------- */
.link-arrow { position: relative; }
.link-arrow:hover { text-shadow: var(--glow-sm) rgba(255, 61, 166, 0.6); }
.section-dark .link-arrow:hover { text-shadow: var(--glow-sm) rgba(59, 240, 218, 0.7); }

/* chips ----------------------------------------------------------- */
.chip.is-active { box-shadow: var(--glow-sm) rgba(255, 61, 166, 0.45); }
.day-tab.is-active { box-shadow: var(--glow-md) rgba(255, 61, 166, 0.4); }

/* hero title gets a subtle chromatic lift ------------------------- */
.title-dot { text-shadow: var(--glow-md) rgba(255, 61, 166, 0.8); }
.date-sep { text-shadow: var(--glow-sm) rgba(255, 61, 166, 0.7); }

/* language switcher ----------------------------------------------- */
.lang-btn.is-active { box-shadow: var(--glow-sm) rgba(59, 240, 218, 0.35); }

@media (prefers-reduced-motion: reduce) {
  .section-dark::before { animation: none; }
  .scroll-progress { display: none; }
}


/* ============ artist modal ============ */
.amodal {
  position: fixed; inset: 0; z-index: 400;
  display: grid; place-items: center; padding: 24px;
  background: rgba(10, 20, 26, 0.82);
  backdrop-filter: blur(10px);
  opacity: 0; visibility: hidden;
  transition: opacity 0.28s var(--ease-out), visibility 0.28s;
}
.amodal.is-open { opacity: 1; visibility: visible; }

.amodal-card {
  position: relative; width: min(920px, 100%); max-height: 88vh; overflow: auto;
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  background: var(--deep); color: var(--ink);
  border: 1.5px solid rgba(59, 240, 218, 0.28); border-radius: 20px;
  box-shadow: var(--glow-lg) rgba(255, 61, 166, 0.22), 0 30px 80px rgba(0, 0, 0, 0.5);
  transform: translateY(18px) scale(0.97);
  transition: transform 0.32s var(--ease-out);
}
.amodal.is-open .amodal-card { transform: none; }

.amodal-figure { background: var(--surface-2); aspect-ratio: 1; position: relative; }
.shot-btn {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 40px; height: 40px; display: grid; place-items: center;
  border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(10, 20, 26, 0.8); color: var(--ink); font-size: 1.15rem;
  transition: background 0.15s ease, opacity 0.15s ease, box-shadow 0.15s ease;
}
.shot-btn:hover { background: var(--magenta); box-shadow: var(--glow-sm) rgba(255, 61, 166, 0.8); }
.shot-btn[disabled] { opacity: 0.25; cursor: default; }
.shot-prev { left: 10px; }
.shot-next { right: 10px; }
.shot-dots {
  position: absolute; bottom: 12px; left: 0; right: 0; z-index: 2;
  display: flex; justify-content: center; gap: 8px;
}
.shot-dot {
  width: 9px; height: 9px; padding: 0; border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(234, 243, 245, 0.4); transition: background 0.15s ease, box-shadow 0.15s ease;
}
.shot-dot.is-on { background: var(--neon-teal); box-shadow: var(--glow-sm) rgba(59, 240, 218, 0.9); }
.amodal-figure img { width: 100%; height: 100%; object-fit: cover; }

.amodal-body { padding: clamp(24px, 4vw, 40px); display: flex; flex-direction: column; }
.amodal-country {
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.16em;
  text-transform: uppercase; color: var(--neon-teal);
  text-shadow: var(--glow-sm) rgba(59, 240, 218, 0.5); margin-bottom: 12px;
}
.amodal-body h3 {
  font-size: clamp(1.5rem, 3vw, 2.2rem); line-height: 1.05; margin-bottom: 10px;
  text-shadow: 0 0 30px rgba(59, 240, 218, 0.2);
}
.amodal-studio { color: rgba(237, 243, 243, 0.7); font-size: 0.95rem; }
.amodal-actions { margin-top: auto; padding-top: 26px; display: flex; flex-direction: column; gap: 10px; }
.amodal-actions .btn { justify-content: center; }
.amodal-hint {
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: rgba(237, 243, 243, 0.45); text-align: center;
}

.amodal-close {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  width: 44px; height: 44px; display: grid; place-items: center;
  border: 0; border-radius: 50%; cursor: pointer;
  background: rgba(10, 20, 26, 0.75); color: var(--ink);
  font-size: 1.4rem; line-height: 1;
  transition: background 0.15s ease, box-shadow 0.15s ease;
}
.amodal-close:hover { background: var(--magenta); box-shadow: var(--glow-sm) rgba(255, 61, 166, 0.8); }


body.amodal-open { overflow: hidden; }
body.is-scroll-locked { position: fixed; left: 0; right: 0; width: 100%; overflow: hidden; }
/* Pinning the body sets scrollY to 0, so a sticky header has nothing left to
   stick past and drops back to its natural spot — which is now scrolled off
   the top of the screen. Opening the menu after scrolling took the logo and
   the close button with it. While locked the body cannot scroll, so a fixed
   header sits exactly where the sticky one was. */
body.is-scroll-locked .site-header { position: fixed; top: 0; left: 0; right: 0; }

@media (max-width: 720px) {
  .amodal { padding: 0; }
  .amodal-card {
    /* minmax(0, 1fr), not 1fr: a grid item keeps an automatic min-width of its
       min-content, and the figure's aspect-ratio resolves against the row
       height — which pushed the column ~190px wider than the phone and made
       the photo look zoomed in. Pinning the rows makes width drive height. */
    grid-template-columns: minmax(0, 1fr);
    /* Photo takes the slack and the details sit under it. The other way round
       left ~500px of empty card below the studio name on a tall phone. */
    grid-template-rows: minmax(0, 1fr) auto;
    width: 100%;
    height: 100vh; height: 100dvh;          /* dvh so the URL bar can't clip it */
    max-height: 100vh; max-height: 100dvh;
    border-radius: 0; border: 0;
  }
  .amodal-figure { aspect-ratio: auto; min-height: 44vh; min-width: 0; width: 100%; }
  .amodal-body { min-width: 0; padding: 22px 22px 28px; }
  .amodal-actions { margin-top: 20px; padding-top: 0; }
}

/* Keyboard shortcut hint is noise on a touch screen */
@media (hover: none) {
  .amodal-hint { display: none; }
}

/* Respect data-saver and reduced-motion: hold the poster frame instead */
@media (prefers-reduced-motion: reduce) {
  .hero-video video { display: none; }
  .hero-video { background: url("../video/hero-poster.jpg") center/cover no-repeat; }
}

/* Same treatment when the browser refuses to play inline — in-app webviews
   (Zalo, Messenger, Instagram) hand any play() to the native fullscreen
   player, which is worse than no video at all. main.js sets this class. */
.hero-video.is-poster-only video { display: none; }
.hero-video.is-poster-only { background: url("../video/hero-poster.jpg") center/cover no-repeat; }


/* ============================================================
   Floating hover
   One lift for every card-like surface, so the whole site reacts the
   same way. Two things make it read as "floating" rather than "sliding":
   the card overshoots slightly on the way up and settles back down more
   slowly than it rose, and a cast shadow grows underneath it — without
   the shadow a translated card just looks nudged, not lifted.
   Accent glows stay per-family through --float-glow.
   ============================================================ */
:root {
  --ease-float: cubic-bezier(0.34, 1.32, 0.5, 1);   /* gentle overshoot */
  --float-lift: -6px;
  --float-cast: 0 18px 34px -14px rgba(20, 38, 46, 0.42);
  --float-glow: 0 0 0 rgba(0, 0, 0, 0);            /* families opt in below */
}
.section-dark, .next-edition { --float-cast: 0 22px 40px -14px rgba(0, 0, 0, 0.55); }

.pillar, .offer, .act, .value, .cat-day, .day-card, .artist-card, .trader,
.logo-slot, .venue-tips li, .tickets-facts li, .judge-photo, .art-lead {
  /* base state owns the settle-back: slower, no overshoot */
  transition: transform 0.42s var(--ease-out), box-shadow 0.42s ease,
              border-color 0.28s ease, background 0.28s ease;
}

.pillar:hover, .offer:hover, .act:hover, .value:hover, .cat-day:hover,
.day-card:hover, .trader:hover, .logo-slot:hover,
.venue-tips li:hover, .tickets-facts li:hover,
.artist-card:hover, .artist-card:focus-visible,
.judge:hover .judge-photo, .art-artist:hover .art-lead {
  transform: translateY(var(--float-lift));
  box-shadow: var(--float-glow), var(--float-cast);
  transition-duration: 0.32s;
  transition-timing-function: var(--ease-float);
}

/* per-family accent halo, composed into the shadow above */
.pillar, .offer, .cat-day, .art-lead { --float-glow: var(--glow-md) rgba(255, 61, 166, 0.2); }
.artist-card { --float-glow: var(--glow-md) rgba(255, 61, 166, 0.3); }
.act, .value, .day-card, .trader, .logo-slot,
.venue-tips li, .tickets-facts li, .judge-photo { --float-glow: var(--glow-md) rgba(59, 240, 218, 0.22); }

/* Judges and art artists lift their image rather than the whole card: both
   sit on the page background with no plate of their own, so shadowing the
   full article would draw a rectangle behind the caption text. */

@media (prefers-reduced-motion: reduce) {
  .pillar:hover, .offer:hover, .act:hover, .value:hover, .cat-day:hover,
  .day-card:hover, .trader:hover, .logo-slot:hover,
  .venue-tips li:hover, .tickets-facts li:hover,
  .artist-card:hover, .artist-card:focus-visible,
  .judge:hover .judge-photo, .art-artist:hover .art-lead {
    transform: none;
  }
}


/* ============ legal / long-form pages ============
   The only place on the site with sustained body copy, so it gets a
   narrow measure and generous rhythm rather than the card grids the
   rest of the pages are built from. */
/* .legal is still a full .container so the copy starts on the same left gutter
   as every other page — the measure is constrained on the children instead. */
.legal > * { max-width: 68ch; }
.legal h2 {
  font-size: clamp(1.15rem, 2.4vw, 1.5rem);
  margin: 52px 0 14px; padding-top: 22px;
  border-top: 1.5px solid var(--line);
}
.legal h2:first-of-type { margin-top: 0; }
.legal p { margin-bottom: 14px; color: var(--ink-soft); }
.legal ul { list-style: none; margin: 0 0 18px; display: grid; gap: 10px; }
.legal li { position: relative; padding-left: 22px; color: var(--ink-soft); }
.legal li::before { content: "—"; position: absolute; left: 0; color: var(--magenta); }
.legal a { color: var(--magenta); text-underline-offset: 3px; }
.legal a:hover { text-decoration: none; }
.legal code {
  font-family: var(--font-mono); font-size: 0.86em;
  background: rgba(20, 38, 46, 0.07); border-radius: 5px; padding: 2px 6px;
}
.legal strong { color: var(--ink); }
.legal-updated { color: var(--gray); font-size: 0.78rem; letter-spacing: 0.1em; margin-top: 20px; }

/* plain-language summary up top — the part most people actually read */
.legal-summary {
  background: var(--paper-card); border: 1.5px solid var(--ink); border-radius: var(--radius);
  padding: 28px 30px; margin-bottom: 44px;
}
.legal-summary h2 { margin: 0 0 14px; padding: 0; border: 0; }
.legal-summary ul { margin: 0; }

/* build note for the site owner — deliberately loud so it can't ship by accident */
.legal-note {
  margin-top: 56px; padding: 24px 26px; border-radius: var(--radius);
  border: 1.5px dashed var(--magenta); background: rgba(176, 50, 135, 0.05);
}
.legal-note .mono {
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--magenta); margin-bottom: 10px;
}
.legal-note p:last-child { margin-bottom: 0; }

@media (max-width: 720px) {
  .legal h2 { margin-top: 40px; }
  .legal-summary, .legal-note { padding: 22px 20px; }
}
