/* ============================================================
   Art of Ink Show — design system
   Colours sampled from the live brand: black ground, coral accent,
   a hot flare pink for highlights, warm chalk type.
   ============================================================ */

/* Sampled off artofinkshow.com: pure black, the logotype/heading coral
   #FF8562 and the hot pink #FF005C the site uses for small marks. Coral is
   bright enough to carry BLACK button text rather than white (10.2:1), which
   is what keeps it feeling like a signal colour instead of a pastel.
   This show is free entrance, so --chalk marks "free" the way the sister
   sites' acid marked their €1 price. */
:root {
  --ink: #F4EAE5;          /* primary text — warm off-white, 16.4:1 on --void */
  --ink-soft: #CBBDB7;
  --void: #0B0A0A;         /* page background — black, a touch warm */
  --surface: #171313;      /* card surface */
  --deep: #050404;         /* deepest panels: footer, modal, cookie */
  --surface-2: #1F1919;    /* alternating section */

  /* Coral is the brand: headings, primary buttons, active chips. */
  --coral: #FF8562;
  --coral-lit: #FFA184;    /* on dark — 9.6:1 */
  --coral-deep: #C4502F;

  /* Flare is the hot accent the site uses sparingly — keep it that way. */
  --flare: #FF005C;
  --flare-deep: #C10046;

  /* Gold for prizes and awards, so contest money reads apart from navigation. */
  --gold: #E0B15C;
  --sun: #C9902E;
  --sun-lit: #EFC275;
  --sun-deep: #8A6118;

  /* Chalk is "free" — the entrance price and nothing else. */
  --chalk: #DFF3C6;
  --gray: #9A8C87;

  /* Glow layer: hover and atmosphere only. Text never depends on it. */
  --neon-coral: #FF9B7A;
  --neon-flare: #FF3D80;
  --neon-sun: #FFD489;
  --glow-sm: 0 0 12px;
  --glow-md: 0 0 26px;
  --glow-lg: 0 0 60px;
  --line: rgba(244, 234, 229, 0.15);
  --line-light: rgba(244, 234, 229, 0.18);

  --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; }

/* Form controls do not inherit type by default — the UA stylesheet *declares*
   a font on them, which beats inheritance. Without this every <button> renders
   in Arial while an <a class="btn"> next to it renders in Archivo, and the two
   sit side by side all over this site. Component rules set their own
   font-size/family afterwards and still win on specificity. */
button, input, select, textarea { font: inherit; color: inherit; }

/* 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(--void);
  -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-coral); 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(--coral); 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(--coral-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(--coral-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 {
  /* Taller than a plain wordmark would need: this logotype is fine ornate
     script, and below ~44px the strokes close up into a blur. */
  width: auto; height: 30px;
  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(--coral-lit); }
.nav-cta {
  background: var(--coral); color: var(--void); 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-coral); 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(--coral-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(255, 155, 122, 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(--coral); color: var(--void); }
.nav-menu a[aria-current="page"] { color: var(--coral-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(--coral); color: var(--void); }

.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:
    /* Bottom stop is near-opaque so the footage dissolves into the page
       instead of ending on a visible seam at the section edge. */
    linear-gradient(180deg, rgba(11,10,10,0.80) 0%, rgba(11,10,10,0.62) 42%, rgba(11,10,10,0.98) 100%),
    linear-gradient(105deg, rgba(255, 133, 98,0.42) 0%, transparent 48%, rgba(255, 161, 132,0.30) 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;
  /* tall enough that `contain` renders the art at a decent size rather than
     shrinking it to a stamp between the header and the copy */
  /* Effectively full-screen, with a sliver of the next section showing so it
     reads as scrollable. The 1200px cap stops it turning into a canyon on a
     very tall display. */
  min-height: clamp(640px, 94vh, 1200px);
  display: flex; align-items: center;
  padding: clamp(56px, 10vh, 120px) 0 clamp(52px, 8vh, 96px);
  text-align: center;
}
/* A plum wash bleeding from the top so the black never reads as an empty
   canvas, and the hero has somewhere to sit. */
.hero::before {
  content: ""; position: absolute; inset: -30% 0 auto; height: 90%;
  background:
    radial-gradient(52% 60% at 50% 8%, rgba(255, 133, 98, 0.34), transparent 68%),
    radial-gradient(40% 46% at 82% 26%, rgba(224, 177, 92, 0.10), transparent 70%);
  pointer-events: none; z-index: 1;
}
.hero-inner {
  max-width: 940px; margin: 0 auto; padding: 0 24px;
  position: relative; z-index: 2;
  display: flex; flex-direction: column; align-items: center;
}
.hero-inner .eyebrow { margin-bottom: 26px; }
.hero-inner h1 { font-size: clamp(2.6rem, 7.4vw, 5.4rem); line-height: 0.94; }
.hero-inner .hero-blurb { max-width: 52ch; margin: 0 auto; }
.hero-inner .hero-actions { justify-content: center; }

/* Stats: the three numbers that answer "is this worth the trip". */
.hero-stats {
  list-style: none; display: flex; flex-wrap: wrap; justify-content: center;
  gap: clamp(24px, 6vw, 72px); margin-top: clamp(34px, 5vh, 56px);
  padding-top: clamp(26px, 4vh, 40px); border-top: 1px solid var(--line);
  width: 100%;
}
.hero-stats li { display: flex; flex-direction: column; gap: 4px; }
.hero-stats strong {
  font-family: var(--font-display); font-size: clamp(1.9rem, 4.4vw, 3rem);
  line-height: 1; color: var(--ink);
}
.hero-stats li:last-child strong { color: var(--chalk); }
.hero-stats span {
  font-family: var(--font-mono); font-size: 0.72rem; text-transform: uppercase;
  letter-spacing: 0.16em; color: var(--gray);
}

.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-sun);
  text-stroke: 3px var(--neon-sun);
}
.title-dot { color: var(--coral-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 { font-family: var(--font-display); font-size: clamp(1rem, 2.2vw, 1.3rem); letter-spacing: 0.02em; color: var(--coral-lit); margin: 18px 0 20px; }
.hero-dates span { color: var(--ink); }
.date-num { font-size: clamp(2.4rem, 5vw, 4rem); }
.date-sep { color: var(--coral-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;
}
/* Black on coral is 8.8:1; white on it is only 2.4:1 and would fail AA. */
.btn-primary { background: var(--coral); color: var(--void); }
.btn-primary:hover { background: var(--neon-coral); color: var(--void); transform: translateY(-2px) rotate(-1deg); }
.btn-ghost { border-color: var(--ink); color: var(--ink); background: transparent; }
.btn-ghost:hover { background: var(--ink); color: var(--void); 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(--coral-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(--sun); 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, 155, 122, 0.20), transparent 70%),
    radial-gradient(34% 40% at 88% 26%, rgba(255, 155, 122, 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(--sun-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(--surface); 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(--coral-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(--coral);
  transform: scaleX(0); transform-origin: left; transition: transform 0.25s ease;
}
.pillar:nth-child(2)::before { background: var(--sun); }
.pillar:nth-child(3)::before { background: var(--coral-lit); }
.pillar:nth-child(4)::before { background: var(--flare); }
.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(--chalk); }
.value-label {
  font-family: var(--font-mono); font-size: 0.72rem; text-transform: uppercase;
  letter-spacing: 0.16em; color: var(--chalk); margin-bottom: 14px;
}
.value h3 { font-size: clamp(1.05rem, 1.7vw, 1.4rem); line-height: 1.12; }

/* ============ 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(--sun-lit);
  background: rgba(255, 255, 255, 0.05);
  box-shadow: var(--glow-sm) rgba(255, 161, 132, 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(--sun-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(--coral); color: var(--void); border-color: var(--coral); }

.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(--surface); border: 1.5px solid var(--line); border-radius: var(--radius);
  overflow: hidden;
}
.artist-card:hover, .artist-card:focus-visible { border-color: var(--coral); }
.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-coral);
  box-shadow: 0 0 6px rgba(255, 155, 122, 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(--coral-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(244, 234, 229,0.55); margin-top: 6px; letter-spacing: 0.08em; }
.day-tab:hover { border-color: var(--ink); }
.day-tab.is-active { background: var(--coral); border-color: var(--coral); }
.day-tab.is-active { color: var(--void); }
.day-tab.is-active .day-hours { color: rgba(11,10,10,0.72); }

.timetable { list-style: none; border-top: 1px solid var(--line-light); }
/* Three columns: time, event, kind. The kind tag is the third — without its
   own track it wrapped under the time and doubled every row's height. */
.timetable li {
  display: grid; grid-template-columns: 92px 1fr auto; 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(--sun-lit); font-size: 0.95rem; }
.timetable .tt-event { font-weight: 500; }
.timetable li:hover { background: rgba(244, 234, 229, 0.03); }

/* ============ tickets ============ */
.tickets-card {
  display: grid; grid-template-columns: 1.2fr 1fr; gap: clamp(32px, 5vw, 72px);
  background: var(--surface); border: 2px solid var(--coral); 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(--void);
}
.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; }

/* Ticket conditions — a numbered list where the number carries the weight,
   so the eight lines scan as terms rather than as body copy. */
.conditions { list-style: none; counter-reset: cond; display: grid; gap: 2px; max-width: 780px; }
.conditions li {
  counter-increment: cond;
  position: relative; padding: 15px 0 15px 52px;
  border-bottom: 1px solid var(--line-light);
  color: var(--ink-soft); font-size: 0.98rem; line-height: 1.55;
}
.conditions li:last-child { border-bottom: 0; }
.conditions li::before {
  content: counter(cond, decimal-leading-zero);
  position: absolute; left: 0; top: 15px;
  font-family: var(--font-mono); font-size: 0.8rem; letter-spacing: 0.08em;
  color: var(--coral);
}
.conditions a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.conditions a:hover { color: var(--coral); }
/* ============ faq ============ */
.faq-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; }
.faq-col { background: var(--surface); 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(--sun-deep); color: #fff; }
.faq-col-title.no { background: var(--coral); color: var(--void); }
.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 ============ */
/* Malaga put this on a full-bleed pale panel. Here the ground stays black and
   the section earns attention with a bordered plum-lit card instead — acid is
   reserved for the price tag, so spending it on a whole background would blunt
   the one place it means something. */
.newsletter { background: var(--surface-2); text-align: center; }
/* Centred and narrow: it is a single ask at the end of the page, and left-
   aligning it against a full-width section left a void the eye reads as a
   missing column. */
.newsletter .container { max-width: 680px; }
.newsletter .section-head { margin-bottom: 30px; }
.newsletter .section-lede { margin-left: auto; margin-right: auto; }
.newsletter .signup-form { margin: 0 auto; justify-content: center; }
.newsletter .fine-print { margin-top: 20px; }

.signup-form {
  display: flex; flex-wrap: wrap; gap: 12px; align-items: center;
  max-width: 560px;
}
.signup-form input[type="email"] {
  flex: 1 1 260px; min-width: 0; font: inherit; font-size: 1rem;
  padding: 15px 22px; border-radius: 999px; color: var(--ink);
  border: 1.5px solid var(--line); background: rgba(255, 255, 255, 0.04);
  transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}
.signup-form input[type="email"]::placeholder { color: var(--gray); }
.signup-form input[type="email"]:hover { border-color: var(--ink-soft); }
.signup-form input[type="email"]:focus {
  outline: none; border-color: var(--coral-lit);
  background: rgba(255, 255, 255, 0.06);
  box-shadow: var(--glow-sm) rgba(255, 161, 132, 0.4);
}
.signup-form .btn { flex: 0 0 auto; }
/* The status line takes the full row so a long message never squeezes the
   input, and it holds its height so the form does not jump when one appears. */
.signup-form .form-note { flex: 1 0 100%; margin: 2px 0 0; min-height: 1.2em; }

/* ============ contact ============
   Form on the left, the direct routes on the right — someone who would rather
   mail or walk in never has to read past the first screen to find how. */
.contact-grid { display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 0.85fr); gap: clamp(32px, 5vw, 72px); align-items: start; }
.contact-form { display: grid; gap: 18px; }
.contact-row { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }
.field { display: grid; gap: 8px; min-width: 0; }
.field > span { font-family: var(--font-mono); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.12em; color: var(--gray); }
.field input, .field select, .field textarea {
  font: inherit; font-size: 1rem; width: 100%;
  padding: 14px 18px; border-radius: 14px; color: var(--ink);
  border: 1.5px solid var(--line); background: rgba(255, 255, 255, 0.04);
  transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}
.field textarea { resize: vertical; min-height: 150px; line-height: 1.6; }
/* The native arrow is drawn in the OS colour and disappears on this dark
   field, so the control draws its own. */
.field select {
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--gray) 50%), linear-gradient(135deg, var(--gray) 50%, transparent 50%);
  background-position: right 22px top 55%, right 16px top 55%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}
.field select option { background: var(--void); color: var(--ink); }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--ink-soft); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--coral-lit);
  background: rgba(255, 255, 255, 0.06);
  box-shadow: var(--glow-sm) rgba(255, 161, 132, 0.4);
}
.contact-actions { display: flex; flex-wrap: wrap; gap: 16px; align-items: center; }
.contact-actions .form-note { margin: 0; min-height: 1.2em; }
/* Off-screen rather than display:none — a bot that skips hidden fields still
   fills this one, which is the whole point. */
.ct-trap { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.contact-form .fine-print { margin-top: 0; }

.contact-aside { border: 1.5px solid var(--line); border-radius: var(--radius); padding: 30px; background: var(--surface); }
.contact-aside-title { font-size: 1.15rem; margin-bottom: 16px; }
.contact-aside-title + * { margin-top: 0; }
.contact-list { list-style: none; display: grid; gap: 16px; margin-bottom: 32px; }
.contact-list li { display: grid; gap: 3px; }
.contact-list .mono { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.12em; color: var(--gray); }
.contact-list a { color: var(--ink); text-decoration: none; word-break: break-word; }
.contact-list a:hover { color: var(--coral-lit); }
.contact-hours { font-size: 0.8rem; color: var(--gray); margin: 12px 0 22px; letter-spacing: 0.06em; }

@media (max-width: 900px) {
  .contact-grid { grid-template-columns: 1fr; }
  .contact-row { grid-template-columns: 1fr; }
}

/* ============ prose (privacy, hostess) ============ */
.prose { max-width: 74ch; }
.prose h2 {
  font-size: clamp(1.15rem, 2.2vw, 1.45rem); margin: 42px 0 14px;
  padding-top: 22px; border-top: 1px solid var(--line);
}
.prose h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.prose p { color: var(--ink-soft); line-height: 1.8; margin-bottom: 16px; }
.prose ul { margin: 0 0 18px 20px; }
.prose li { color: var(--ink-soft); line-height: 1.8; margin-bottom: 8px; }
.prose a { color: var(--coral-lit); }
.prose strong { color: var(--ink); }
.prose code {
  font-family: var(--font-mono); font-size: 0.86em;
  padding: 2px 6px; border-radius: 5px;
  background: rgba(244, 234, 229, 0.08); color: var(--sun-lit);
}
.prose .btn { margin-top: 8px; }

/* ============ address blocks ============ */
.venue-address {
  font-style: normal; font-size: 1.02rem; line-height: 1.85;
  color: var(--ink-soft); margin: 4px 0 26px;
  padding-left: 18px; border-left: 2px solid var(--coral);
}

/* ============ footer ============ */
.site-footer { background: var(--deep); color: var(--ink); padding: 64px 0 32px; }
/* Four columns since the "Our shows" / Rising High column came out; the
   organiser is still credited in the legal line under the grid. */
.footer-grid { display: grid; grid-template-columns: 1.25fr 0.85fr 1fr 1.2fr; gap: 40px; padding-bottom: 48px; border-bottom: 1px solid var(--line-light); }
.footer-logo { width: auto; height: 40px; margin-bottom: 4px; }
.footer-tag { margin-top: 16px; color: rgba(244, 234, 229, 0.65); font-size: 0.95rem; }
.footer-grid h4 { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.14em; color: var(--sun-lit); margin-bottom: 16px; font-weight: 500; }
.footer-grid a { display: block; text-decoration: none; padding: 5px 0; color: rgba(244, 234, 229,0.85); font-size: 0.95rem; }
.footer-grid a:hover { color: var(--coral-lit); }
.footer-addr { color: rgba(244, 234, 229,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(244, 234, 229,0.5); }
.footer-legal a { color: rgba(244, 234, 229,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(--coral-lit); }
.site-nav a[aria-current="page"].nav-cta { background: var(--neon-coral); 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(--coral);
  transition: gap 0.18s var(--ease-out), color 0.18s ease;
}
.link-arrow:hover { color: var(--coral-lit); gap: 14px; }
.section-dark .link-arrow { border-bottom-color: var(--sun-lit); }
.section-dark .link-arrow:hover { color: var(--sun-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(244, 234, 229,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(--sun-lit); letter-spacing: 0.1em; margin-top: 8px; }
.day-card .day-peek { display: block; color: rgba(244, 234, 229,0.6); font-size: 0.92rem; margin-top: 16px; }

/* ============ full-width CTA band ============ */
/* The band is a full coral field, so everything on it flips to dark type. */
.cta-band { background: var(--coral); color: var(--void); 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(11,10,10,0.78); }
.cta-band .btn { margin-top: 30px; }
.cta-band .btn-primary { background: var(--deep); color: var(--ink); }
.cta-band .btn-primary:hover { background: var(--neon-brass); 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(--surface); 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(--sun-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(255, 155, 122, 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(--coral); box-shadow: var(--glow-md) rgba(255, 155, 122, 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(244, 234, 229, 0.75); margin-bottom: 16px; }
.cookie a { color: var(--sun-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(244, 234, 229, 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(--surface); border: 1.5px solid var(--line); border-radius: var(--radius);
  padding: 26px 24px 28px;
}
.section-dark .cat-day { background: rgba(244, 234, 229, 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(--coral);
}
.section-dark .cat-day-title { border-bottom-color: var(--sun-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(--coral-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(244, 234, 229, 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(--coral-lit); letter-spacing: 0.06em;
}

.dq-list { list-style: none; display: grid; gap: 16px; }
.dq-list li {
  border: 1.5px solid var(--flare); 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(--flare); 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; }
/* ============ confirmed traders ============
   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(244, 234, 229, 0.05);
}
.trader:hover { border-color: var(--sun-lit); background: rgba(244, 234, 229, 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(244, 234, 229, 0.5); }
/* The whole tile is the anchor now; this label is a span inside it, so it
   styles its own link affordance instead of inheriting one. */
.trader-link {
  display: inline-block; margin-top: 8px;
  font-family: var(--font-mono); font-size: 0.72rem;
  text-transform: uppercase; letter-spacing: 0.12em;
  color: var(--sun-lit);
  text-decoration: underline; text-underline-offset: 3px;
}
a.trader:hover .trader-link { color: var(--coral-lit); }

.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(--coral-lit);
}
.tier-head::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.tier + .tier { margin-top: 48px; }
.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(--flare);
}
.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);
}
.prereg .btn-primary { background: var(--flare-deep); }
.prereg .btn-primary:hover { background: var(--ink); color: var(--deep); }

/* 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(--sun-lit);
}
.form-note.is-bad { color: #FF9A8C; }

.newsletter .form-note { color: rgba(10, 20, 26, 0.82); }
/* One step deeper than --flare-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(--sun); }
.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(--sun-lit); }
.act p { color: rgba(244, 234, 229, 0.65); font-size: 0.93rem; }
.act-ig {
  justify-self: start; margin-top: 4px;
  font-size: 0.74rem; letter-spacing: 0.06em;
  color: var(--sun-lit); text-decoration: none;
}
.act-ig:hover { color: var(--sun); 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 */
  .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); }
  .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(--void); }
  .site-header.is-stuck { background: var(--void); 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(--void); border-top: 2px solid var(--neon-coral);
    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(--coral-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(--coral-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-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; }
  .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) {
  .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-coral), var(--neon-brass), var(--neon-sun));
  box-shadow: var(--glow-sm) rgba(255, 155, 122, 0.7);
  pointer-events: none;
}

/* buttons --------------------------------------------------------- */
.btn-primary {
  position: relative;
  box-shadow: var(--glow-sm) rgba(255, 155, 122, 0.35);
}
.btn-primary:hover {
  box-shadow: var(--glow-md) rgba(255, 155, 122, 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, 155, 122, 0.4); }
.nav-cta:hover { box-shadow: var(--glow-md) rgba(255, 155, 122, 0.8); }

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

/* headings on dark pick up a soft neon edge ----------------------- */
.section-dark h2,
.next-edition h2 { text-shadow: 0 0 34px rgba(255, 155, 122, 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(--coral); }

/* 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-coral), 0 0 24px rgba(255, 155, 122, 0.25); }
.ticker-track i { text-shadow: var(--glow-sm) var(--neon-coral); }

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

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

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

/* language switcher ----------------------------------------------- */
.lang-btn.is-active { box-shadow: var(--glow-sm) rgba(255, 155, 122, 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(255, 155, 122, 0.28); border-radius: 20px;
  box-shadow: var(--glow-lg) rgba(255, 155, 122, 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(--coral); box-shadow: var(--glow-sm) rgba(255, 155, 122, 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(244, 234, 229, 0.4); transition: background 0.15s ease, box-shadow 0.15s ease;
}
.shot-dot.is-on { background: var(--neon-sun); box-shadow: var(--glow-sm) rgba(255, 155, 122, 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-sun);
  text-shadow: var(--glow-sm) rgba(255, 155, 122, 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(255, 155, 122, 0.2);
}
.amodal-studio { color: rgba(244, 234, 229, 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(244, 234, 229, 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(--coral); box-shadow: var(--glow-sm) rgba(255, 155, 122, 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,
.tickets-facts li {
  /* 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, .contest-day:hover,
.tickets-facts li:hover,
.artist-card:hover, .artist-card:focus-visible {
  transform: translateY(var(--float-lift));
  box-shadow: var(--float-glow), var(--float-cast);
  transition-duration: 0.32s;
  transition-timing-function: var(--ease-float);
}
.artist-card { --float-glow: var(--glow-md) rgba(255, 155, 122, 0.3); }
.act, .value, .day-card, .trader,
.tickets-facts li { --float-glow: var(--glow-md) rgba(255, 155, 122, 0.22); }
/* Contests are the money pages — they glow brass rather than plum. */
.contest-day { --float-glow: var(--glow-md) rgba(224, 177, 92, 0.22); }

@media (prefers-reduced-motion: reduce) {
  .pillar:hover, .offer:hover, .act:hover, .value:hover, .cat-day:hover,
  .day-card:hover, .trader:hover, .contest-day:hover,
  .tickets-facts li:hover,
  .artist-card:hover, .artist-card:focus-visible {
    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(--coral); }
.legal a { color: var(--coral); 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(--surface); 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(--coral); background: rgba(255, 133, 98, 0.05);
}
.legal-note .mono {
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--coral); 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; }
}

/* ============ contests ============ */
.contest-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.contest-day {
  background: var(--surface); border: 1.5px solid var(--line);
  border-radius: var(--radius); padding: 28px 26px;
}
.contest-day h3 {
  font-size: 1.05rem; padding-bottom: 16px; margin-bottom: 4px;
  border-bottom: 1.5px solid var(--line);
}
.contest-list { list-style: none; }
.contest-list li { padding: 14px 0; border-bottom: 1px solid var(--line); }
.contest-list li:last-child { border-bottom: 0; }
.contest-name { display: block; font-weight: 600; font-size: 0.97rem; }
/* Prize money is the reason artists read this page — brass, and never
   competing with the category name for first read. */
.contest-note {
  display: block; margin-top: 4px; font-size: 0.76rem;
  letter-spacing: 0.06em; color: var(--gold);
}

/* ============ FAQ (details/summary) ============ */
.faq-list { display: grid; gap: 12px; max-width: 820px; }
.faq-item {
  background: var(--surface); border: 1.5px solid var(--line);
  border-radius: 12px; overflow: hidden;
}
.faq-item summary {
  list-style: none; cursor: pointer; padding: 20px 54px 20px 24px;
  font-weight: 600; font-size: 1rem; position: relative;
  transition: color 0.15s, background 0.15s;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover { color: var(--coral-lit); background: rgba(244, 234, 229, 0.03); }
.faq-item summary:focus-visible { outline: 2px solid var(--coral-lit); outline-offset: -3px; }
/* Chevron drawn in CSS so the row needs no icon font and no markup of its own. */
.faq-item summary::after {
  content: ""; position: absolute; right: 24px; top: 50%;
  width: 9px; height: 9px; margin-top: -6px;
  border-right: 2px solid var(--coral-lit); border-bottom: 2px solid var(--coral-lit);
  transform: rotate(45deg); transition: transform 0.22s var(--ease-out);
}
.faq-item[open] summary::after { transform: rotate(-135deg); margin-top: -2px; }
.faq-item[open] summary { color: var(--coral-lit); }
.faq-answer { padding: 0 24px 22px; }
.faq-answer p { color: var(--ink-soft); font-size: 0.95rem; line-height: 1.75; }

/* ============ timetable row kinds ============
   One accent per kind so a day reads as a shape. Arena and contest are the
   two people plan around, so they get the two strongest colours. */
.timetable li.tt-arena  .tt-time { color: var(--flare); }
.timetable li.tt-contest .tt-time { color: var(--gold); }
.timetable li.tt-stage  .tt-time { color: var(--coral-lit); }
.timetable li.tt-fun    .tt-time { color: var(--chalk); }
.timetable li.tt-open   .tt-event { font-weight: 700; }
.tt-kind {
  font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--gray); justify-self: end;
}
@media (max-width: 720px) { .tt-kind { display: none; } }

/* ============ country select (artists page) ============ */
.artist-filters { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-bottom: 14px; }
.artist-country {
  font-family: var(--font-mono); font-size: 0.8rem; letter-spacing: 0.04em;
  padding: 12px 38px 12px 16px; border-radius: 999px;
  border: 1.5px solid var(--line); background-color: rgba(255, 255, 255, 0.03);
  color: var(--ink); cursor: pointer; appearance: none;
  /* inline chevron, so the control needs no wrapper element */
  background-image: linear-gradient(45deg, transparent 50%, var(--coral-lit) 50%),
                    linear-gradient(135deg, var(--coral-lit) 50%, transparent 50%);
  background-position: right 19px center, right 13px center;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}
.artist-country:hover { border-color: var(--ink-soft); }
.artist-country:focus { outline: none; border-color: var(--coral-lit); box-shadow: var(--glow-sm) rgba(255, 161, 132, 0.35); }
/* The dropdown list is painted by the OS, which ignores the page's palette —
   set both so the options are not black-on-black. */
.artist-country option { background: var(--surface); color: var(--ink); }

@media (max-width: 900px) { .contest-grid { grid-template-columns: 1fr; } }
@media (max-width: 720px) {
  .artist-filters { flex-direction: column; align-items: stretch; }
  .artist-country { width: 100%; font-size: 16px; }
}

/* ============ acts / offers grids ============ */
.acts { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }
.offers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
.act-blurb { margin-top: 10px; }
/* The Instagram link is the only interactive thing in the card, so it needs to
   look like one — the card itself is not a link. */
.act-ig { margin-top: 14px; display: inline-block; }

/* A single-image artist has one lonely dot and nothing to step through.
   The disabled arrows are already hidden by the .shot-btn rule above; this
   drops the pointless dot too. */
.shot-dots:not(:has(.shot-dot + .shot-dot)) { display: none; }

@media (max-width: 900px) {
  .acts, .offers { grid-template-columns: 1fr; }
}
@media (max-width: 720px) {
  .signup-form { flex-direction: column; align-items: stretch; }
  .signup-form input[type="email"] { flex: 1 1 auto; font-size: 16px; }
  .signup-form .btn { width: 100%; justify-content: center; }
}

/* The €1 is the entire pitch, so it is set large — but opt-in by class, not by
   position. As `li:first-child` it also blew up "By tram" on the info page,
   which reuses this list. */
.tickets-facts li.is-headline strong {
  font-size: clamp(1.7rem, 3.6vw, 2.3rem); line-height: 1;
  color: var(--chalk); letter-spacing: -0.01em;
}
.tickets-facts li.is-headline { align-items: center; }

/* ============ hostess ============ */
.hostess-grid { display: grid; grid-template-columns: minmax(0, 360px) minmax(0, 1fr); gap: clamp(28px, 5vw, 56px); align-items: start; }
.hostess-photo { border-radius: var(--radius); overflow: hidden; border: 1.5px solid var(--line); }
.hostess-photo img { display: block; width: 100%; height: auto; }

/* ============ past edition ============ */
.recap { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: clamp(30px, 5vw, 60px); align-items: center; }
.recap-copy .section-lede { margin-top: 16px; }

.recap-player { position: relative; }
/* The facade is a button, not a link: it swaps itself for the iframe in
   place, so nothing navigates and the poster keeps the layout from jumping. */
.recap-play {
  display: block; width: 100%; padding: 0; border: 1.5px solid var(--line);
  border-radius: var(--radius); overflow: hidden; background: var(--deep);
  cursor: pointer; position: relative; line-height: 0;
  transition: border-color 0.2s ease, box-shadow 0.25s ease, transform 0.25s var(--ease-out);
}
.recap-play img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover;
  transition: opacity 0.25s ease, transform 0.4s var(--ease-out); }
.recap-play::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(11,10,10,0.10) 0%, rgba(11,10,10,0.62) 100%);
  transition: background 0.25s ease;
}
.recap-play:hover { border-color: var(--coral-lit); box-shadow: var(--glow-md) rgba(255, 133, 98, 0.35); transform: translateY(-3px); }
.recap-play:hover img { transform: scale(1.03); }
.recap-play:focus-visible { outline: 2px solid var(--coral-lit); outline-offset: 3px; }

.recap-play-btn {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 74px; height: 74px; border-radius: 50%; z-index: 1;
  display: grid; place-items: center;
  background: var(--coral); color: #fff;
  box-shadow: var(--glow-md) rgba(255, 133, 98, 0.55);
  transition: background 0.2s ease, transform 0.25s var(--ease-out);
}
.recap-play-btn svg { width: 34px; height: 34px; margin-left: 3px; }
.recap-play:hover .recap-play-btn { background: var(--neon-coral); transform: translate(-50%, -50%) scale(1.08); }

.recap-play-label {
  position: absolute; left: 0; right: 0; bottom: 16px; z-index: 1;
  text-align: center; line-height: 1.4;
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.14em; color: var(--ink);
}

/* Same box as the poster it replaces, so pressing play does not shift the page. */
.recap-frame {
  display: block; width: 100%; aspect-ratio: 16 / 9; border: 0;
  border-radius: var(--radius); background: #000;
}
.recap-player.is-playing .recap-note { opacity: 0; pointer-events: none; }
.recap-note { margin-top: 12px; transition: opacity 0.2s ease; }

@media (max-width: 900px) {
  .recap { grid-template-columns: 1fr; }
  .recap-play-btn { width: 62px; height: 62px; }
  .recap-play-btn svg { width: 28px; height: 28px; }
}

@media (max-width: 820px) {
  .hostess-grid { grid-template-columns: 1fr; }
  .hostess-photo { max-width: 340px; }
}

/* ============ hero artwork ============
   Full-bleed key art. The source is 1.46:1 and a desktop header is 1.8-2.2:1,
   so filling the screen means scaling to width and losing a little top and
   bottom — the composition is centred, so the dragon itself survives that.
   (`contain` was tried first: it keeps every pixel but cannot fill a wide
   screen, which is what this needs to do.) */
/* The hero footage lives in .hero-video (see "hero video" above). The black
   behind it matters while the poster is still decoding. */
.hero-video { background-color: var(--void); }

/* Scrim between the art and the copy, so the headline holds contrast without
   dimming the artwork into mud. */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(62% 64% at 50% 46%, rgba(11,10,10,0.80) 0%, rgba(11,10,10,0.46) 58%, transparent 100%),
    linear-gradient(180deg, rgba(11,10,10,0.58) 0%, rgba(11,10,10,0.18) 34%, rgba(11,10,10,0.97) 100%);
}

@media (max-width: 1040px) {
  /* A phone is far taller than the footage, so `cover` crops it to a narrow
     slice; pulling it back keeps the copy dominant. */
  .hero-video video { opacity: 0.5; }
}

/* ============ jury ============ */
.judges-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
.judge { text-align: center; }
/* The photo lifts on hover rather than the whole card: judges sit on the bare
   page background, so shadowing the article would draw a box behind the name. */
.judge-photo {
  aspect-ratio: 1 / 1; border-radius: 50%; overflow: hidden;
  border: 1.5px solid var(--line); margin-bottom: 14px;
  transition: transform 0.32s var(--ease-float), box-shadow 0.32s ease, border-color 0.2s ease;
}
.judge-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.judge:hover .judge-photo {
  transform: translateY(-6px); border-color: var(--coral);
  box-shadow: var(--glow-md) rgba(255, 133, 98, 0.32);
}
.judge h3 { font-size: 1rem; }
.judge .mono { font-size: 0.74rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--gray); margin-top: 5px; }

/* ============ sponsor wall ============ */
.logo-wall { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; }
/* Sponsor logos arrive as opaque files with their own backgrounds, so they get
   a near-black tile and are contained rather than cropped. A logo drawn
   black-on-white will still read as a white square — that needs a new file,
   not CSS. */
.logo-slot {
  aspect-ratio: 1 / 1; display: flex; align-items: center; justify-content: center;
  background: #0C0A0A; border: 1.5px solid var(--line); border-radius: var(--radius);
  padding: 20px; overflow: hidden;
  transition: border-color 0.2s ease, box-shadow 0.28s ease, transform 0.28s var(--ease-out);
}
.logo-slot img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
.logo-slot:hover { border-color: var(--coral); box-shadow: var(--glow-md) rgba(255, 133, 98, 0.28); transform: translateY(-4px); }

/* ============ art exhibition albums ============
   One horizontally scrollable album per exhibitor, rather than a grid of
   single tiles: these artists show several pieces each, and a catalogue reads
   better as a row you move through than as one cropped thumbnail. */
.exhibitors { display: grid; gap: clamp(30px, 4vw, 46px); }
/* min-width: 0 on every ancestor of the rail. A grid/flex item defaults to
   min-width: auto, so the flex row grows to fit its content instead of
   overflowing — the rail then measures wider than the page and never scrolls. */
.album, .album-wrap { min-width: 0; }

.album-head {
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
  margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--line);
}
.album-head h3 { font-size: clamp(1.05rem, 2vw, 1.35rem); }
.album-head .mono { font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--gold); }

.album-wrap { position: relative; }
.album-rail {
  display: flex; gap: 14px; overflow-x: auto; scroll-snap-type: x mandatory;
  scroll-behavior: smooth; scrollbar-width: none;
  /* room for the snap to breathe at both ends */
  padding: 2px 2px 6px;
  /* the rail is focusable for keyboard users; keep the ring off the images */
  border-radius: var(--radius);
}
.album-rail::-webkit-scrollbar { display: none; }
.album-rail:focus-visible { outline: 2px solid var(--coral-lit); outline-offset: 3px; }

.album-item {
  flex: 0 0 auto; margin: 0; scroll-snap-align: start;
  width: clamp(210px, 26vw, 300px); aspect-ratio: 1 / 1;
  border-radius: 12px; overflow: hidden; border: 1.5px solid var(--line);
  background: linear-gradient(140deg, rgba(255,133,98,0.14), rgba(255,0,92,0.08));
  transition: border-color 0.2s ease, transform 0.3s var(--ease-out);
}
.album-item img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.45s var(--ease-out); }
.album-item:hover { border-color: var(--coral); transform: translateY(-4px); }
.album-item:hover img { transform: scale(1.04); }

.album-btn {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 44px; height: 44px; display: grid; place-items: center;
  font-size: 1.5rem; line-height: 1; cursor: pointer;
  border-radius: 50%; border: 1.5px solid var(--line-light);
  background: rgba(11, 10, 10, 0.82); color: var(--ink);
  backdrop-filter: blur(6px);
  transition: background 0.18s ease, opacity 0.18s ease, box-shadow 0.2s ease;
}
.album-btn:hover { background: var(--coral); color: var(--void); box-shadow: var(--glow-md) rgba(255, 133, 98, 0.5); }
.album-btn[disabled] { opacity: 0; pointer-events: none; }
.album-prev { left: -14px; }
.album-next { right: -14px; }
/* Fewer works than fit the row — no controls at all. */
.album-wrap.is-static .album-btn { display: none; }

@media (hover: none) {
  /* Touch scrolls directly; arrows would just cover the artwork. */
  .album-btn { display: none; }
  .album-rail { scroll-snap-type: x proximity; }
}

/* ============ timetable kinds (this show) ============ */
.timetable li.tt-auction .tt-time { color: var(--gold); }
.timetable li.tt-talk    .tt-time { color: var(--coral-lit); }

@media (max-width: 900px) {
  .judges-row, .logo-wall { grid-template-columns: repeat(2, 1fr); }
  .exhibitors { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .exhibitors { grid-template-columns: 1fr; }
}

/* ---- footer: parent company + sister shows ---- */
.footer-grid .is-current {
  display: block; padding: 5px 0; font-size: 0.95rem; color: var(--gray);
}
/* The show you are already on is named but not linked — a link back to the
   current site is a dead end. */
.footer-grid .is-current::after { content: " (you are here)"; font-size: 0.78em; opacity: 0.75; }
.rhp { display: block; margin-top: 16px; max-width: 190px; padding: 0; }
.rhp img {
  width: 100%; height: auto; display: block; border-radius: 6px;
  opacity: 0.72; transition: opacity 0.2s ease, transform 0.25s var(--ease-out);
}
.rhp:hover img { opacity: 1; transform: translateY(-2px); }

@media (max-width: 900px) { .rhp { max-width: 160px; } }

/* ============ venue photos ============
   A carousel rather than a grid: these are wide interior shots, and four of
   them stacked two-up pushed the FAQ well below the fold. Built on the same
   album rail as the art exhibition — the only difference is the frame shape. */
.venue-photos { margin-top: 34px; min-width: 0; }
.venue-rail .album-item {
  /* landscape, not the square the artwork tiles use */
  width: clamp(280px, 52vw, 560px); aspect-ratio: 3 / 2;
}

/* ============ venue map ============ */
.map { margin-top: 30px; border-radius: var(--radius); overflow: hidden; border: 1.5px solid var(--line); }
/* The address panel sits *behind* the iframe: the box is never empty while
   Google is loading, and nothing shifts when the map paints over it. */
.map-facade {
  position: absolute; inset: 0;
  display: grid; place-items: center; gap: 14px; text-align: center;
  padding: 26px;
  background:
    radial-gradient(60% 70% at 50% 40%, rgba(255,133,98,0.14), transparent 70%),
    var(--surface);
}
/* A faint street-grid suggestion, drawn in CSS — no image request for a
   placeholder the real map covers a moment later. */
.map-facade::before {
  content: ""; position: absolute; inset: 0; opacity: 0.28; pointer-events: none;
  background-image:
    linear-gradient(rgba(244,234,229,0.10) 1px, transparent 1px),
    linear-gradient(90deg, rgba(244,234,229,0.10) 1px, transparent 1px);
  background-size: 46px 46px, 46px 46px;
}
.map { position: relative; }
.map-facade > * { position: relative; z-index: 1; }
.map-pin { font-size: 1.6rem; line-height: 1; }
.map-address { font-family: var(--font-mono); font-size: 0.86rem; line-height: 1.7; color: var(--ink-soft); }
.map-frame {
  position: relative; z-index: 1;
  display: block; width: 100%; aspect-ratio: 16 / 7; border: 0; background: transparent;
}
@media (max-width: 720px) {
  .map-facade, .map-frame { aspect-ratio: 4 / 3; }
}
