@font-face {
  font-family: "Funegral";
  src: url("fonts/FBSFunegral-Normal.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Poster palette */
  --ink: #01000e;
  --yellow: #F9EE7C;
  --purple: #9D4193;
  --orange: #CE564D;
  --white: #ffffff;

  --heat: linear-gradient(90deg, var(--purple), var(--orange));
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-sweep: cubic-bezier(0.7, 0, 0.2, 1);

  --content-max: 1040px;
  --gutter: 16px;

  color-scheme: dark;
}

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

html {
  background: var(--ink);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ink);
  color: var(--yellow);
  font-family: "Funegral", "Arial Black", "Helvetica Neue", Arial, sans-serif;
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

a { color: inherit; text-decoration: none; -webkit-tap-highlight-color: transparent; }

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

/* The photo is placed so that the artists' feet sit just above the title.
   --feet-y is where the feet land: 53% of the screen height, but never lower
   than the feet are in the unshifted photo (so no gap opens above the photo). */
.page {
  container-type: inline-size;
  --img-ratio: 0.6178;   /* height / width of img/photo-*.jpg */
  --feet: 0.77;          /* feet line, as a fraction of the photo height */
  --blast: 0.47;         /* explosion centre, as a fraction of the photo height */
  --img-h: calc(100cqw * var(--img-ratio));
  --top-crop: 0;         /* fraction of the photo height pushed above the screen */
  --feet-y: min(53svh, var(--img-h) * (var(--feet) - var(--top-crop)));
  --img-top: calc(var(--feet-y) - var(--img-h) * var(--feet));
  --hero-h: calc(var(--feet-y) + var(--img-h) * 0.12);
  position: relative;
  min-height: 100svh;
  overflow: clip;
}

@media (max-width: 639px) {
  .page {
    --img-ratio: 1.25;   /* img/photo-mobile.jpg */
    --feet: 0.776;
    --blast: 0.45;
    --top-crop: 0.21;    /* start just above the smoke, as on desktop */
  }
}

/* ---------- Hero photo ---------- */

.hero {
  position: relative;
  width: 100%;
  height: var(--hero-h);
  overflow: hidden;
}

/* Holds the photo and, on desktop, the WebGL layer that redraws it (main.js) */
.hero__media {
  position: absolute;
  left: 0;
  right: 0;
  top: var(--img-top);
  height: var(--img-h);
  transform-origin: 50% var(--feet-y);
}

.hero picture { display: contents; }

.hero__photo,
.hero__fx {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.hero__photo {
  object-fit: cover;
  /* Keep in sync with FOCUS in main.js */
  object-position: 50% 50%;
}

/* Melt the photo into the page at the bottom and the sides */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom, transparent 62%, var(--ink) 100%),
    radial-gradient(ellipse 120% 100% at 50% 40%, transparent 60%, rgba(1, 0, 14, 0.55));
  pointer-events: none;
}

/* Bloom that fires once when the explosion ignites on load.
   It sits outside the photo box and fades to nothing on all sides,
   so it spills into the dark area below without a hard edge. */
.flash {
  position: absolute;
  left: 50%;
  top: calc(var(--img-top) + var(--img-h) * var(--blast));
  width: 150vmax;
  aspect-ratio: 1;
  translate: -50% -50%;
  background: radial-gradient(closest-side,
    var(--yellow) 0,
    rgba(206, 86, 77, 0.8) 18%,
    rgba(157, 65, 147, 0.42) 38%,
    rgba(157, 65, 147, 0.12) 62%,
    transparent 100%);
  mix-blend-mode: screen;
  opacity: 0;
  pointer-events: none;
}

/* ---------- Content column ---------- */

.content {
  position: relative;
  z-index: 1;
  container-type: inline-size;
  /* On wider screens the column also shrinks with the screen height,
     so the title and all rows fit above the fold (content is ~0.6 × its width tall) */
  width: min(100% - var(--gutter) * 2, var(--content-max), max(520px, (100svh - var(--feet-y) - 32px) / 0.6));
  margin: calc(var(--feet-y) - var(--hero-h)) auto 0;
  padding-bottom: max(56px, env(safe-area-inset-bottom));
}

.title {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2.4cqi;
  margin: 0;
}

.title picture { display: contents; }
.title source { display: none; }
.title img { height: auto; }
.title__tour { width: 52.6%; }
.title__names { width: 100%; }

/* ---------- Tour dates ---------- */

.dates {
  list-style: none;
  margin: 8cqi 0 0;
  padding: 0;
  font-size: min(3.45cqi, 31px);
  line-height: 1;
  text-transform: uppercase;
}

.date {
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: 37.6% 1fr auto;
  align-items: center;
  /* Bleed the hover band past the text edge, keep the text aligned to the title */
  margin-inline: -0.4em;
  padding: 0.2em 0.4em 0.22em;
  outline: none;
}

.date::before,
.date::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

/* Hover / focus band: the heat gradient sweeps in, then yellow wipes over it
   and the text inverts to ink */
.date::before {
  background:
    linear-gradient(var(--yellow), var(--yellow)) left / 0% 100% no-repeat,
    var(--heat);
  transform: scaleX(0);
  transform-origin: left center;
  transition:
    transform 0.4s var(--ease-sweep),
    background-size 0.3s var(--ease-sweep);
}

.date {
  transition: color 0.2s ease;
}

/* Leading edge of the load sweep */
.date::after {
  background: linear-gradient(90deg, transparent 55%, var(--purple) 80%, var(--orange) 94%, var(--yellow));
  opacity: 0;
}

.date__day { display: flex; white-space: nowrap; }
/* Fixed widths keep the columns aligned; widest day/month glyphs plus a 0.52em gap */
.date__day span { flex: none; }
.date__day span:first-child { width: 1.9em; }
.date__day span:nth-child(2) { width: 1.64em; }

.date__city { white-space: nowrap; }

.date__venue {
  justify-self: end;
  white-space: nowrap;
  overflow: hidden;
  text-align: right;
  /* Room for the rolled label so its top is not clipped */
  padding-block: 0.08em;
}

.date__roll {
  display: grid;
  transition: transform 0.45s var(--ease-out);
}

.date__roll > span { grid-area: 1 / 1; }
.date__roll > span + span { transform: translateY(115%); }

.date__cta { display: none; }

@media (hover: hover) {
  .date:hover::before {
    transform: scaleX(1);
    background-size: 100% 100%, auto;
    transition-delay: 0s, 0.22s;
  }
  .date:hover {
    color: var(--ink);
    transition-delay: 0.3s;
  }
  .date:hover .date__roll { transform: translateY(-115%); transition-delay: 0.08s; }
}

.date:focus-visible::before { transform: scaleX(1); background-size: 100% 100%, auto; }
.date:focus-visible { color: var(--ink); }
.date:focus-visible .date__roll { transform: translateY(-115%); }
.date:focus-visible { box-shadow: 0 0 0 2px var(--ink), 0 0 0 4px var(--yellow); }

.date:active::before { transform: scaleX(1); transition-duration: 0.2s; }

/* Touch devices: no hover, so show the ticket label all the time */
@media (hover: none) and (min-width: 640px) {
  .dates { font-size: min(3.1cqi, 28px); }
  .date { grid-template-columns: 35% 1fr auto auto; }
  .date__roll > span + span { display: none; }
  .date__cta { display: block; margin-left: 0.9em; }
}

/* Skew only the background so the label stays upright and centred.
   Capitals in this font sit 0.05em low in the line box, so the bottom padding is larger. */
.date__cta {
  position: relative;
  z-index: 0;
  padding: 0.32em 0.75em 0.42em;
  font-size: 0.5em;
  line-height: 1;
  color: var(--yellow);
  white-space: nowrap;
}

.date__cta::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--heat);
  transform: skewX(-10deg);
}

/* Phones: stack each row into two lines */
@media (max-width: 639px) {
  .dates {
    margin-top: 10cqi;
    font-size: min(8.4cqi, 34px);
  }

  .dates li + li .date { border-top: 1px solid rgba(249, 238, 124, 0.16); }

  .date {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "day  venue"
      "city cta";
    row-gap: 0.28em;
    margin-inline: -0.3em;
    padding: 0.5em 0.3em 0.46em;
  }

  .date__day { grid-area: day; font-size: 0.52em; }
  /* Natural date on phones: no column widths, just a space after each dot */
  .date__day span:not(:last-child) { width: auto; margin-right: 0.3em; }
  .date__city { grid-area: city; }

  .date__venue { grid-area: venue; font-size: 0.52em; }
  .date__roll > span + span { display: none; }

  .date__cta {
    display: block;
    grid-area: cta;
    justify-self: end;
    font-size: 0.47em;
  }

  .date:active .date__cta::before { background: var(--ink); }
}

/* ---------- Footer logos ---------- */

.footer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  margin-top: clamp(64px, 12.5cqi, 112px);
  color: var(--white);
}

.footer__logos {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: clamp(28px, 4.3cqi, 40px);
}

.footer__legal {
  margin: 0;
  font-size: 11px;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.45);
}

.footer__logo {
  display: block;
  padding: 8px;
  transition: color 0.25s ease, transform 0.35s var(--ease-out);
}

.footer__logo svg { width: 100%; height: auto; overflow: visible; }
.footer__logo--mrft { width: calc(max(96px, 13cqi) + 16px); }
.footer__logo--rk { width: calc(max(84px, 11.6cqi) + 16px); }

.footer__logo:hover { color: var(--yellow); transform: translateY(-2px); }
.footer__logo:focus-visible { outline: 2px solid var(--yellow); outline-offset: 2px; }

/* ---------- Load sequence ----------
   The photo and title stay hidden until main.js adds .is-loaded (photo and font ready).
   The rows and logos stay hidden until main.js adds .is-visible (scrolled into view).
   Without JS, or with reduced motion, everything shows at once. */

.js:not(.is-loaded) :is(.hero__media, .title img) { opacity: 0; }
.js .reveal:not(.is-visible) :is(.date, .footer__logo, .footer__legal) { opacity: 0; }

.is-loaded .hero__media {
  animation:
    ignite 2.4s cubic-bezier(0.2, 0.7, 0.1, 1) both,
    breathe 16s ease-in-out 2.4s infinite alternate;
}

.is-loaded .flash { animation: flash 2s ease-out 0.2s both; }

.is-loaded .title__names { animation: rise 1.3s var(--ease-out) 0.95s both; }

/* Flickers in after the names have landed */
.is-loaded .title__tour { animation: heat 1.2s linear 1.75s both; }

/* --reveal-delay is set by main.js: the full load delay when in view at load, less when revealed by scroll */
.is-visible .date {
  animation: wipe 0.95s var(--ease-sweep) calc(var(--reveal-delay, 0s) + var(--i) * 0.11s) backwards;
}

.is-visible .date::after {
  animation: sweep 0.95s var(--ease-sweep) calc(var(--reveal-delay, 0s) + var(--i) * 0.11s) both;
}

.is-visible .footer__logo { animation: surface 0.9s var(--ease-out) var(--reveal-delay, 0s) backwards; }
.is-visible .footer__logo + .footer__logo { animation-delay: calc(var(--reveal-delay, 0s) + 0.12s); }
.is-visible .footer__legal { animation: surface 0.9s var(--ease-out) calc(var(--reveal-delay, 0s) + 0.24s) backwards; }

@keyframes ignite {
  0%   { opacity: 0; transform: scale(1.16); filter: brightness(0.15) saturate(0.4) blur(8px); }
  18%  { opacity: 1; }
  42%  { filter: brightness(1.45) saturate(1.25) blur(0); }
  100% { opacity: 1; transform: scale(1); filter: none; }
}

@keyframes breathe {
  from { transform: scale(1); }
  to   { transform: scale(1.045); }
}

@keyframes flash {
  0%   { opacity: 0; transform: scale(0.2); }
  20%  { opacity: 0.95; }
  100% { opacity: 0; transform: scale(1.25); }
}

/* Flicker in like heat haze */
@keyframes heat {
  0%   { opacity: 0; transform: translateY(12px) skewX(-14deg); filter: blur(10px) brightness(2.2); }
  14%  { opacity: 0.85; }
  22%  { opacity: 0.15; }
  34%  { opacity: 1; filter: blur(3px) brightness(1.6); }
  44%  { opacity: 0.45; }
  56%  { opacity: 1; transform: translateY(0) skewX(-4deg); }
  100% { opacity: 1; transform: none; filter: none; }
}

@keyframes rise {
  0%   { opacity: 0; transform: translateY(44px) scale(0.93); filter: blur(16px) brightness(2.4); }
  60%  { filter: blur(0) brightness(1.25); }
  100% { opacity: 1; transform: none; filter: none; }
}

@keyframes wipe {
  0%   { clip-path: inset(0 100% 0 0); }
  78%  { clip-path: inset(0 0 0 0); }
  100% { clip-path: inset(0 0 0 0); }
}

@keyframes sweep {
  0%   { opacity: 1; transform: translateX(-100%); }
  78%  { opacity: 1; transform: translateX(0); }
  100% { opacity: 0; transform: translateX(0); }
}

@keyframes surface {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .js:not(.is-loaded) :is(.hero__media, .title img),
  .js .reveal:not(.is-visible) :is(.date, .footer__logo, .footer__legal) { opacity: 1; }

  *, *::before, *::after {
    animation: none !important;
    transition-duration: 0.01ms !important;
  }
}
