/*
 * Single stylesheet for the whole page, shared verbatim by:
 *   - the site (linked from src/layouts/Layout.astro)
 *   - the CMS live preview (CMS.registerPreviewStyle in src/admin/preview.jsx)
 * It lives in public/ (not src/styles/) so the admin can load it unhashed.
 *
 * Layout: base/global rules first, then one section per src/ui component.
 * Component selectors are prefixed with the component's root (.hero, nav, ...)
 * - generic child class names (.badge, .card, .photo) repeat across sections
 * and must stay scoped to their component.
 */

:root {
  --bg: #130B11;
  --bg-deep: #0B060A;
  --aubergine: #2A1322;
  --card: #1C0F19;
  --ink: #F2EAD9;
  --ink-85: rgba(242, 234, 217, 0.85);
  --ink-75: rgba(242, 234, 217, 0.75);
  --ink-65: rgba(242, 234, 217, 0.65);
  --ink-60: rgba(242, 234, 217, 0.62);
  --ink-border: rgba(242, 234, 217, 0.4);
  --gold: #C6A15B;
  --gold-light: #E8CF9A;
  --gold-border: rgba(198, 161, 91, 0.3);
  --gold-border-strong: rgba(198, 161, 91, 0.5);
  --pink: #E23E8F;
  /* The food vendors' colour, and the second archive numeral. It is the one
     cool note in a warm palette, which is the point: it marks the parts of
     the night that are not the stage. */
  --mint: #9CDAC9;
  --on-gold: #1a1206;
  /* The archive sits a shade up from the page either side of it, so the
     block is visibly its own without introducing another colour. */
  --archive: #241329;
  /* The ticket call is the one light block on the page: a warm off-white
     rather than white, so it reads as paper in the same room. Gold is
     unreadable on it, hence the deep counterpart. */
  --cream: #F7F2E7;
  --ink-dark: #241019;
  --ink-dark-75: rgba(36, 16, 25, 0.75);
  --gold-deep: #8A6522;
  --buybar-clearance: 110px;
  /* One page margin for every full-width section, so the hero's copy, the
     section headings and the footer all start on the same line. */
  --page-gutter: clamp(24px, 6vw, 96px);
  --font-display: 'Rozha One', Georgia, serif;
  --font-body: 'Manrope', 'Helvetica Neue', Arial, sans-serif;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--gold);
  text-decoration: none;
}

a:hover {
  color: var(--gold-light);
}

:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

.btn-gold {
  display: inline-grid;
  place-items: center;
  border-radius: 10px;
  font-weight: 800;
  letter-spacing: 0.14em;
  color: var(--on-gold);
  background: var(--gold);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  cursor: pointer;
}

.btn-gold:hover {
  color: var(--on-gold);
  filter: brightness(1.06);
}

.kicker {
  font-size: 11px;
  letter-spacing: 0.4em;
  color: var(--gold);
  text-transform: uppercase;
}

.display {
  font-family: var(--font-display);
  font-weight: 400;
}

@keyframes marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

@keyframes drift {
  from { transform: translateY(0); }
  to { transform: translateY(-10px); }
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 100;
  padding: 10px 16px;
  border-radius: 8px;
  background: var(--bg-deep);
  color: var(--gold-light);
  font-size: 13px;
  font-weight: 700;
  transform: translateY(-200%);
}

.skip-link:focus {
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  /* the site's only animations: Film marquee and the hero scroll hint */
  .track,
  .scroll-hint {
    animation: none !important;
  }
  html {
    scroll-behavior: auto;
  }
}

/* ---------- ImageSlot ---------- */

.image-slot {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

.image-slot.placeholder {
  display: grid;
  place-items: center;
  padding: 12px;
  background: var(--card);
  border: 1px dashed var(--gold-border);
  color: var(--ink-60);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.6;
}

/* ---------- Nav ---------- */

nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 48px;
  background: rgba(11, 6, 10, 0.92);
  border-bottom: 1px solid var(--gold-border);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  transition: transform 0.3s ease;
}

nav.nav-hidden {
  transform: translateY(-100%);
}

/* Scroll-aware nav: fully transparent over the hero, settling into the solid
   bar as the page scrolls. Browsers without scroll-driven animations just
   keep the always-solid bar above. */
@supports (animation-timeline: scroll()) {
  nav {
    animation: nav-settle linear both;
    animation-timeline: scroll();
    animation-range: 0 160px;
  }

  @keyframes nav-settle {
    from {
      background: rgba(11, 6, 10, 0);
      border-bottom-color: transparent;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0);
    }
    to {
      background: rgba(11, 6, 10, 0.92);
      border-bottom-color: var(--gold-border);
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
    }
  }
}

nav .brand {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--ink);
}

nav .badge {
  width: 38px;
  height: 38px;
  border: 1px solid var(--gold);
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 14px;
  color: var(--gold);
}

nav .name {
  font-size: 16px;
  letter-spacing: 0.25em;
  text-transform: uppercase;
}

nav .links {
  display: flex;
  align-items: center;
  gap: 32px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
}

nav .links > a {
  color: var(--ink);
}

nav .links > a:hover {
  color: var(--gold-light);
}


nav .menu {
  display: none;
}

@media (max-width: 900px) {
  nav {
    padding: 12px 16px;
  }

  nav .badge {
    width: 32px;
    height: 32px;
    font-size: 12px;
  }

  nav .name {
    font-size: 13px;
  }

  nav .links {
    display: none;
  }

  nav .menu {
    display: block;
    position: relative;
  }

  nav summary {
    list-style: none;
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    border: 1px solid var(--gold-border-strong);
    border-radius: 8px;
    cursor: pointer;
  }

  nav summary::-webkit-details-marker {
    display: none;
  }

  nav .burger,
  nav .burger::before,
  nav .burger::after {
    display: block;
    width: 16px;
    height: 2px;
    border-radius: 1px;
    background: var(--gold-light);
  }

  nav .burger {
    position: relative;
  }

  nav .burger::before,
  nav .burger::after {
    content: '';
    position: absolute;
    left: 0;
  }

  nav .burger::before {
    top: -5px;
  }

  nav .burger::after {
    top: 5px;
  }

  nav .panel {
    position: absolute;
    top: 48px;
    right: 0;
    min-width: 200px;
    display: flex;
    flex-direction: column;
    padding: 8px;
    border: 1px solid var(--gold-border);
    border-radius: 12px;
    background: var(--bg-deep);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
  }

  nav .panel a {
    padding: 12px 16px;
    border-radius: 8px;
    color: var(--ink);
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.06em;
  }

  nav .panel a:hover {
    color: var(--gold-light);
    background: rgba(198, 161, 91, 0.08);
  }
}

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

   The photo is the whole frame and the copy sits in the bottom-left corner,
   clear of the subject. Photo, scrim and copy share one grid cell: the photo
   sets the height, the scrim stretches over whatever that turns out to be,
   and the copy is bottom-aligned inside it. */

.hero {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  background: var(--bg);
}

.hero .media,
.hero .scrim,
.hero .content {
  grid-area: 1 / 1;
}

/* The media block carries the hero photo's own 1364x810, so `cover` has
   nothing to crop at any width and the whole picture is on the page. The one
   exception is the height cap: on a window wider than it is tall, the full
   frame works out taller than the viewport and the buttons end up below the
   fold. The cap only ever bites there, and object-position pins the image to
   the top of the block so what it takes is the bottom of the picture. */
.hero .media {
  align-self: start;
  width: 100%;
  aspect-ratio: 1364 / 810;
  max-height: calc(100svh - 16px);
  /* The fade into the page lives on the photo itself, not on an overlay
     sized to the section: an overlay's gradient ends wherever the copy ends,
     which is a different place at every window size, and the seam showed. */
  -webkit-mask-image: linear-gradient(180deg, #000 66%, rgba(0, 0, 0, 0.6) 86%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 66%, rgba(0, 0, 0, 0.6) 86%, transparent 100%);
}

.hero .media .image-slot {
  object-position: 50% 0;
}

/* Three passes: a diagonal that is heavy into the bottom-left corner where
   the copy lives and gone by the right half where the subject is, a short
   one under the nav, and a last one carrying the photo into the page. */
.hero .scrim {
  align-self: stretch;
  pointer-events: none;
  background:
    linear-gradient(100deg, rgba(12, 10, 10, 0.86) 0%, rgba(12, 10, 10, 0.66) 34%, rgba(12, 10, 10, 0.12) 62%, rgba(12, 10, 10, 0) 80%),
    linear-gradient(180deg, rgba(12, 10, 10, 0.7) 0%, rgba(12, 10, 10, 0) 22%),
    linear-gradient(0deg, var(--bg) 0%, rgba(19, 11, 17, 0.55) 14%, transparent 34%);
}

.hero .content {
  position: relative;
  /* The metadata row below breaks on its own width, not the window's - the
     column is capped at 680px and stops well short of the viewport. */
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;
  gap: 22px;
  width: 100%;
  max-width: 680px;
  margin-right: auto;
  padding: 0 var(--page-gutter) 84px;
}

.hero .edition {
  font-size: 12px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--gold-light);
  white-space: nowrap;
}

.hero h1 {
  margin: 0;
  font-size: clamp(44px, 6.4vw, 92px);
  line-height: 0.95;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.hero h1 > span {
  display: block;
}

/* One metadata row - date, doors, venue, age. The two halves are their own
   groups so a narrow column can break between them and drop the separator in
   the middle; the separators are grey rather than gold because four gold dots
   in a row read as decoration and pull rank on the eyebrow above them. */
.hero .facts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 10px;
  font-size: 15px;
  color: var(--ink-85);
}


.hero .facts .grp {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  white-space: nowrap;
}

.hero .facts .grp > span {
  white-space: nowrap;
}

.hero .dot {
  color: var(--ink-60);
}

/* Too narrow for one line: the row becomes two whole lines - date and doors,
   then venue and age - rather than wrapping wherever it runs out of room and
   leaving a separator stranded at the end of the first line. The two lines
   share one two-column grid (`display: contents` hands each group's own
   children to it), so "Doors 16:00" and "All ages" start on the same edge
   instead of landing wherever the half in front of them happens to end. The
   dots go with the single line they belonged to: a column edge separates
   these two halves better than a mid-air dot does.  */
@container (max-width: 660px) {
  .hero .facts {
    display: grid;
    grid-template-columns: auto auto;
    justify-content: start;
    align-items: baseline;
    gap: 6px 28px;
  }

  .hero .facts .grp {
    display: contents;
  }

  .hero .facts .dot {
    display: none;
  }
}

/* One primary CTA and a quiet text link beside it, never two buttons. */
.hero .actions {
  display: flex;
  align-items: center;
  gap: 32px;
  margin-top: 6px;
}

/* Square: the only button on the site that is, because it is the only one
   sitting directly on a photograph, where a radius reads as a sticker. */
.hero .buy {
  border-radius: 0;
  padding: 18px 40px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.14em;
  box-shadow: none;
}

.hero .trailer {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.1em;
  color: var(--ink);
}

.hero .trailer:hover {
  color: var(--gold-light);
}

/* An inline glyph, not a ringed button: the ring made the trailer link look
   like a second CTA. */
.hero .small-play {
  font-size: 10px;
  color: var(--gold);
}

.hero .hero-price {
  font-size: 13px;
  color: var(--ink-75);
}

/* The scroll cue: a word and a rule at the right margin. */
.hero-scroll {
  position: absolute;
  z-index: 2;
  right: var(--page-gutter);
  bottom: 84px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.24em;
  color: rgba(244, 241, 234, 0.75);
}

.hero-scroll span:first-child {
  writing-mode: vertical-rl;
}

.hero-scroll .rule {
  width: 1px;
  height: 64px;
  background: linear-gradient(180deg, rgba(244, 241, 234, 0.7), rgba(244, 241, 234, 0));
}

.hero-scroll:hover {
  color: var(--gold-light);
}

/* Laptop: the same layout, one step down. */
@media (max-width: 1200px) {
  .hero .content {
    max-width: 560px;
    gap: 18px;
    padding-bottom: 72px;
  }

  .hero .edition {
    font-size: 11px;
  }

  .hero .facts {
    font-size: 14px;
  }

  .hero .actions {
    gap: 28px;
    margin-top: 4px;
  }

  .hero .buy {
    padding: 16px 34px;
    font-size: 13px;
  }

  .hero .trailer {
    font-size: 13px;
  }

  .hero-scroll {
    bottom: 72px;
  }

  .hero-scroll .rule {
    height: 54px;
  }
}

/* Tablet and phone drop the diagonal for a bottom-up scrim: the photo lives
   in the top two-thirds and the copy stacks under it, because a one-line
   wordmark and a four-part metadata row do not both fit across this width
   over the picture. */
@media (max-width: 900px) {
  .hero {
    padding-bottom: 40px;
  }

  .hero .media {
    max-height: 58svh;
  }

  .hero .scrim {
    background: linear-gradient(
      180deg,
      rgba(12, 10, 10, 0.72) 0%,
      rgba(12, 10, 10, 0.05) 24%,
      rgba(12, 10, 10, 0.5) 52%,
      rgba(12, 10, 10, 0.94) 74%,
      var(--bg) 88%
    );
  }

  /* Clears the photo above it, which is the shorter of its own aspect ratio
     and the cap. */
  .hero .content {
    max-width: none;
    gap: 18px;
    padding: calc(min(59.4vw, 58svh) + 14px) var(--page-gutter) 0;
  }

  .hero .edition {
    font-size: 11px;
  }

  .hero h1 {
    font-size: clamp(44px, 9.8vw, 82px);
  }

  .hero .buy {
    padding: 18px 38px;
  }

  .hero-scroll {
    display: none;
  }
}

/* Phone: the metadata is already two aligned lines from the container query
   above; here the type comes down a step and the buy button goes full width
   with the trailer link centred under it. */
@media (max-width: 560px) {
  .hero .content {
    gap: 16px;
  }

  .hero .edition {
    font-size: 10px;
    letter-spacing: 0.26em;
  }

  .hero h1 {
    font-size: clamp(40px, 15.4vw, 60px);
    line-height: 0.92;
  }

  .hero .actions {
    flex-direction: column;
    align-self: stretch;
    align-items: stretch;
    gap: 8px;
    margin-top: 4px;
  }

  .hero .buy {
    display: grid;
    width: 100%;
    padding: 18px 24px;
  }

  .hero .trailer {
    align-self: center;
    justify-content: center;
    padding: 8px 4px;
    font-size: 13px;
  }

  .hero .hero-price {
    align-self: center;
  }
}

/* ---------- Intro ---------- */

.intro {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 64px;
  align-items: center;
  padding: 110px var(--page-gutter);
  background: linear-gradient(180deg, var(--bg), var(--aubergine));
}

.intro .rule {
  width: 56px;
  height: 1px;
  background: var(--gold);
  margin-bottom: 24px;
}

.intro h2 {
  margin: 0;
  font-size: 52px;
  line-height: 1.08;
}

.intro .accent {
  font-style: italic;
  color: var(--gold-light);
}

.intro p {
  font-size: 16px;
  line-height: 1.7;
  color: var(--ink-75);
  margin: 22px 0 0;
  max-width: 480px;
}

.intro .tags {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 28px;
}

.intro .tag {
  padding: 9px 18px;
  border: 1px solid var(--gold-border-strong);
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--gold-light);
}

.intro .tag.highlight {
  border-color: rgba(226, 62, 143, 0.6);
  color: var(--pink);
}

.intro .collage {
  position: relative;
  height: 460px;
}

.intro .main-photo {
  position: absolute;
  inset: 0 40px 40px 0;
}

.intro .inset-photo {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 220px;
  height: 220px;
  border: 1px solid var(--gold-border-strong);
  border-radius: 14px;
  padding: 8px;
  background: var(--bg);
}

@media (max-width: 900px) {
  .intro {
    grid-template-columns: 1fr;
    gap: 36px;
    padding: 56px var(--page-gutter) 48px;
  }

  .intro .rule {
    width: 44px;
    margin-bottom: 18px;
  }

  .intro h2 {
    font-size: 30px;
    line-height: 1.15;
  }

  .intro p {
    font-size: 14px;
    line-height: 1.65;
    margin-top: 14px;
  }

  .intro .tags {
    gap: 8px;
    margin-top: 22px;
  }

  .intro .tag {
    padding: 7px 14px;
    font-size: 11.5px;
  }

  .intro .collage {
    height: 300px;
  }

  .intro .inset-photo {
    width: 150px;
    height: 150px;
  }
}

/* ---------- Essentials ---------- */

.essentials {
  padding: 90px var(--page-gutter);
  background: var(--aubergine);
}

.essentials .kicker {
  margin: 0 0 32px;
  font-weight: 400;
}

.essentials .grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 16px;
}

.essentials .card {
  border: 1px solid var(--gold-border);
  border-radius: 14px;
  padding: 24px 20px;
  background: rgba(19, 11, 17, 0.4);
}

.essentials .label {
  font-size: 10px;
  letter-spacing: 0.2em;
  color: var(--ink-60);
  text-transform: uppercase;
}

.essentials .value {
  font-size: 26px;
  margin-top: 8px;
}

.essentials .age {
  border-color: rgba(226, 62, 143, 0.45);
}

.essentials .age .value {
  color: var(--pink);
}

@media (max-width: 900px) {
  .essentials {
    padding: 48px var(--page-gutter);
  }

  .essentials .kicker {
    font-size: 10px;
    letter-spacing: 0.35em;
    margin: 0 0 20px;
  }

  .essentials .grid {
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }

  .essentials .card {
    border-radius: 12px;
    padding: 16px 14px;
  }

  .essentials .value {
    font-size: 20px;
    margin-top: 6px;
  }
}

/* ---------- Film ----------

   The trailer is shot on a phone and plays portrait. A 9:16 player alone in
   the middle of a full-width section reads as a mistake, so the copy sits
   beside it and the two share the row. */

.film {
  padding: 100px 0 80px;
  background: linear-gradient(180deg, var(--aubergine), var(--bg) 35%);
}

.film-layout {
  display: grid;
  grid-template-columns: 1fr minmax(300px, 380px);
  gap: 56px;
  align-items: center;
  padding: 0 var(--page-gutter);
}

.film h2 {
  margin: 12px 0 0;
  text-align: left;
  font-size: clamp(36px, 4.2vw, 58px);
}

.film .accent {
  font-style: italic;
  color: var(--gold-light);
}

.film .film-copy p {
  margin: 22px 0 0;
  max-width: 46ch;
  font-size: 16px;
  line-height: 1.75;
  color: var(--ink-75);
}

.film .film-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
  margin-top: 28px;
  padding-top: 22px;
  border-top: 1px solid var(--gold-border);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-60);
}

/* The player keeps the same frame - size, radius, gold border - whether a
   trailer has been uploaded or not, so the section does not jump around when
   one is added. */
.film .player {
  position: relative;
  aspect-ratio: 9 / 16;
  overflow: hidden;
  border: 1px solid var(--gold-border);
  border-radius: 14px;
  background: var(--card);
}

/* A portrait trailer in a portrait frame has nothing to letterbox, so it
   fills the card and there are no black bars either side of it. */
.film .player-video {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}

/* Both buttons are unhidden by public/site.js, so neither is ever a control
   that does nothing. The `hidden` attribute needs saying out loud here
   because each rule below sets a display of its own. */
.film-play[hidden],
.film-sound[hidden] {
  display: none;
}

/* The one control on the trailer: it is muted and looping on its own, so
   sound is the only thing left to decide. Top right, clear of the play
   overlay's bottom-aligned content, and above it so it stays reachable
   while the video is paused. */
.film-sound {
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 2;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--gold);
  background: rgba(19, 11, 17, 0.55);
  color: var(--gold-light);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  cursor: pointer;
  transition: transform 0.2s ease, background 0.2s ease;
}

.film-sound:hover {
  transform: scale(1.06);
  background: rgba(19, 11, 17, 0.75);
}

/* One icon per state, both in the markup so the swap costs no request. */
.film-sound .sound-on,
.film-sound .sound-off {
  display: grid;
  place-items: center;
}

.film-sound .sound-off,
.film-sound.is-muted .sound-on {
  display: none;
}

.film-sound.is-muted .sound-off {
  display: grid;
}

/* The overlay the play button sits on. It is the paused state - shown only
   when the silent loop was refused or stopped - so it never sits alongside
   a playing video. */
.film-play {
  position: absolute;
  inset: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 14px;
  padding: 0 20px 32px;
  border: 0;
  font: inherit;
  color: var(--ink);
  background: linear-gradient(0deg, rgba(19, 11, 17, 0.85), rgba(19, 11, 17, 0.1) 60%);
  cursor: pointer;
}

.film .play-circle {
  width: 68px;
  height: 68px;
  display: grid;
  place-items: center;
  padding-left: 4px;
  border-radius: 50%;
  background: var(--gold);
  color: var(--on-gold);
  font-size: 20px;
  transition: transform 0.2s ease;
}

.film-play:hover .play-circle {
  transform: scale(1.06);
}

.film-play .film-duration {
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-75);
}

/* The no-trailer state: the cover frame with a static play mark on it. */
.film .play-overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}

.film .play-btn {
  width: 88px;
  height: 88px;
  border-radius: 50%;
  background: rgba(19, 11, 17, 0.55);
  border: 1px solid var(--gold);
  display: grid;
  place-items: center;
  color: var(--gold-light);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.film .marquee {
  margin-top: 44px;
  overflow: hidden;
}

.film .track {
  display: flex;
  gap: 14px;
  width: max-content;
  animation: marquee 32s linear infinite;
}

.film .frame {
  height: 190px;
  flex-shrink: 0;
}

.film .frame.wide {
  width: 280px;
}

.film .frame.narrow {
  width: 200px;
}

@media (max-width: 1000px) {
  .film-layout {
    grid-template-columns: 1fr;
    gap: 36px;
  }

  .film .player {
    max-width: 340px;
    margin: 0 auto;
  }
}

@media (max-width: 900px) {
  .film {
    padding: 60px 0 48px;
  }

  .film h2 {
    margin-bottom: 0;
    font-size: 32px;
    line-height: 1.1;
  }

  .film .film-copy p {
    font-size: 15px;
  }

  .film .marquee {
    margin-top: 32px;
  }

  .film .track {
    gap: 10px;
    animation-duration: 28s;
  }

  .film .frame {
    height: 110px;
  }

  .film .frame.wide {
    width: 150px;
  }

  .film .frame.narrow {
    width: 110px;
  }
}

/* ---------- PastEditions ----------

   The archive reads as an index rather than a wall of cards: a hairline, the
   volume set large, the photos, then the write-up. */

.past {
  padding: 96px var(--page-gutter);
  /* The deck fans its cards sideways past its own box (see .deck-slide), and
     on a phone that overhang is wider than the screen - it grew the page's
     scroll width and let the whole site be swiped sideways. Clipped here, at
     the only section that fans anything, so the fan still spills into the
     gutter as designed and nothing spills off the page. `clip` rather than
     `hidden`: no scroll container, so sticky/fixed children keep working. */
  overflow-x: clip;
  /* A flat aubergine between two sections of --bg above and below it, so the
     archive reads as its own block - the same colour a shade up, not a
     different one. */
  background: var(--archive);
}

.past .kicker {
  margin-bottom: 8px;
}

.past h2 {
  margin: 12px 0 40px;
  font-size: clamp(36px, 4.2vw, 58px);
}

.past .grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 44px;
}

/* Everything in an entry is centred on its own column - the volume, the
   photos and the write-up under them share one centre line, rather than the
   deck sitting mid-column with the text against the left edge. */
.past .card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 26px;
  padding-top: 22px;
  border-top: 1px solid var(--gold-border);
  text-align: center;
}

.past .card > * {
  width: 100%;
}

/* The volume, set large - the thing every entry has in common and the thing
   people name these nights by. Alternating gold and mint so a long archive
   does not become a column of identical gold numerals. */
.past .archive-number {
  font-size: 68px;
  line-height: 1;
  color: var(--gold);
}

.past .card:nth-child(even) .archive-number {
  color: var(--mint);
}

.past .body {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.past .title-row {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.past h3 {
  margin: 0;
  font-size: 26px;
  line-height: 1.15;
}

.past .date {
  font-size: 13px;
  color: var(--ink-65);
}

.past p {
  margin: 10px 0 0;
  font-size: 15px;
  line-height: 1.7;
  color: var(--ink-65);
}

.past .links {
  display: flex;
  justify-content: center;
  gap: 20px;
  margin-top: 12px;
  font-size: 13px;
  font-weight: 700;
}

.past .links a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

/* ---------- PhotoDeck ----------

   Several photos from one night arrive as a hand of cards: the top card is
   the photo, the rest fan out behind it, blurred back far enough to read as
   "there is more" without competing with the one in front. public/site.js
   deals the fan and turns it over; with no JavaScript the first card is
   simply the photo, which is what this section used to show anyway.

   A deck of one photo gets none of it - no fan, no dots, no counter. */

.deck {
  position: relative;
  width: 100%;
  max-width: 420px;
  margin: 0 auto 34px;
  /* The square every card is fitted into, whichever way round the photo is. */
  aspect-ratio: 1 / 1;
}

/* The card takes the photo's own proportions - public/site.js reads them off
   the image and sets --ar - and is fitted into the square and centred, so a
   landscape photo is a landscape card rather than a landscape photo cropped
   into a portrait one. The 5:7 default is the shape every card had before,
   which is what a deck with no JavaScript (and the CMS preview) still shows.
   The square never changes size, so a turn from portrait to landscape moves
   no other pixel on the page. */
.deck-slide {
  position: absolute;
  inset: 0;
  margin: auto;
  aspect-ratio: var(--ar, 5 / 7);
  max-width: 100%;
  max-height: 100%;
  overflow: hidden;
  border: 1px solid var(--gold-border);
  border-radius: 16px;
  background: var(--card);
  transform-origin: 50% 92%;
  transition: transform 0.36s cubic-bezier(0.22, 0.85, 0.3, 1), opacity 0.36s ease, filter 0.36s ease;
  will-change: transform;
}

.deck-slide .image-slot {
  width: 100%;
  height: 100%;
}

/* Position is by depth rather than per-slide, so a deck of three and a deck
   of nine fan the same way. The depths are set by public/site.js. */
.deck-slide[data-depth="0"] {
  transform: none;
  opacity: 1;
  filter: none;
  z-index: 6;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.5);
}

.deck-slide[data-depth="1"] {
  transform: translate(36%, -2%) rotate(8deg) scale(0.92);
  opacity: 0.62;
  filter: blur(1.5px);
  z-index: 5;
}

.deck-slide[data-depth="2"] {
  transform: translate(-36%, -3%) rotate(-8deg) scale(0.9);
  opacity: 0.48;
  filter: blur(2.5px);
  z-index: 4;
}

.deck-slide[data-depth="3"] {
  transform: translate(22%, -6%) rotate(4.5deg) scale(0.85);
  opacity: 0.3;
  filter: blur(3.5px);
  z-index: 3;
}

.deck-slide[data-depth="4"] {
  transform: translate(-22%, -7%) rotate(-4.5deg) scale(0.83);
  opacity: 0.2;
  filter: blur(4px);
  z-index: 2;
}

.deck-slide[data-depth="hidden"] {
  transform: translateY(-8%) scale(0.8);
  opacity: 0;
  filter: blur(5px);
  z-index: 1;
}

/* The card that just left goes forward and off, not backwards through the
   stack - backwards reads as an undo of the turn that dismissed it. */
.deck-slide[data-depth="out"] {
  transform: translate(-14%, 12%) rotate(-11deg) scale(1.02);
  opacity: 0;
  z-index: 7;
}

/* Over the top card only, so the fanned cards behind it are not swallowing
   clicks meant for the photo in front. */
.deck-nav {
  position: absolute;
  inset: 0;
  z-index: 7;
  border: 0;
  background: none;
  cursor: pointer;
}

.deck-controls {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -26px;
  z-index: 8;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}

.deck-dots {
  display: flex;
  gap: 7px;
}

.deck-dot {
  width: 7px;
  height: 7px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(242, 234, 217, 0.35);
  cursor: pointer;
  transition: background 0.2s ease, width 0.2s ease;
}

.deck-dot[aria-current="true"] {
  width: 18px;
  border-radius: 4px;
  background: var(--gold);
}

/* Rides inside the top card (public/site.js moves it there on every turn):
   pinned to the square instead, it would hang in the empty space above a
   landscape card. */
.deck-count {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 8;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(11, 6, 10, 0.72);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-85);
}

@media (max-width: 900px) {
  .past {
    padding: 60px var(--page-gutter);
  }

  .past .kicker {
    font-size: 10px;
    letter-spacing: 0.35em;
    margin-bottom: 6px;
  }

  .past h2 {
    font-size: 36px;
    margin-bottom: 28px;
  }

  .past .grid {
    grid-template-columns: 1fr;
    gap: 34px;
  }

  .past .archive-number {
    font-size: 44px;
  }

  .past h3 {
    font-size: 22px;
  }

  .past p {
    font-size: 14px;
  }

  .past .links {
    gap: 14px;
    font-size: 12px;
  }
}

/* The deck's own transition is the turn; anything that reduces motion drops
   it, and public/site.js does not start the timer in the first place. */
@media (prefers-reduced-motion: reduce) {
  .deck-slide {
    transition: none;
  }
}

/* ---------- Performers ---------- */

.performers {
  padding: 90px var(--page-gutter);
  background: var(--bg);
}

.performers .kicker {
  margin-bottom: 8px;
}

.performers h2 {
  margin: 0 0 40px;
  font-size: 44px;
}

.performers .grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
}

.performers .performer {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.performers .photo {
  height: 280px;
  margin-bottom: 6px;
}

.performers .name {
  font-weight: 700;
  font-size: 15px;
}

.performers .role {
  font-size: 12px;
  color: var(--gold);
}

.performers .more {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--gold-border);
  border-radius: 14px;
  text-align: center;
  padding: 20px;
}

.performers .more span {
  font-style: italic;
  font-size: 20px;
  color: var(--gold-light);
}

/* The food vendors, on their own hairlines below the acts. They are part of
   the bill and people plan around them, but they are not performers - mint
   rather than gold, because this is the part of the night that is not the
   stage. */

.performers .food {
  margin-top: 48px;
  padding-top: 26px;
  border-top: 1px solid var(--gold-border);
}

.performers .food .kicker {
  display: block;
  margin-bottom: 18px;
  color: var(--mint);
}

.performers .food-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.performers .food-list li {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 18px 0;
  border-bottom: 1px solid rgba(156, 218, 201, 0.22);
}

.performers .food-name {
  font-size: 20px;
  font-weight: 600;
}

.performers .food-role {
  font-size: 13px;
  color: var(--ink-65);
}

.performers .food-mark {
  margin-left: auto;
  color: var(--mint);
  font-size: 22px;
}

@media (max-width: 900px) {
  .performers {
    padding: 60px var(--page-gutter);
  }

  .performers .kicker {
    font-size: 10px;
    letter-spacing: 0.35em;
    margin-bottom: 6px;
  }

  .performers h2 {
    font-size: 30px;
    margin-bottom: 24px;
  }

  .performers .grid {
    grid-template-columns: 1fr 1fr;
    gap: 14px;
  }

  .performers .performer {
    gap: 4px;
  }

  .performers .photo {
    height: 150px;
    margin-bottom: 4px;
  }

  .performers .name {
    font-size: 13px;
  }

  .performers .role {
    font-size: 11px;
  }

  .performers .more {
    border-radius: 12px;
    padding: 16px;
  }

  .performers .more span {
    font-size: 16px;
  }

  .performers .food {
    margin-top: 34px;
  }

  .performers .food-name {
    font-size: 17px;
  }
}

/* ---------- FinalCta ---------- */

.final-cta {
  padding: 96px var(--page-gutter);
  /* The lighter of the two off-whites: the last thing on the page is the one
     bright thing on it. */
  background: var(--cream);
  color: var(--ink-dark);
  text-align: left;
}

/* Two columns: what the night is on the left, the one thing to do about it
   on the right. The pair is capped and centred in the section rather than
   pushed out to both page margins - at full width the heading and the panel
   drifted apart with nothing between them. */
.cta-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(280px, 360px);
  gap: 56px;
  align-items: center;
  max-width: 1040px;
  margin: 0 auto;
}

.final-cta h2 {
  margin: 0;
  font-size: clamp(38px, 4.4vw, 60px);
  line-height: 1.08;
  text-wrap: balance;
}

/* Whether tickets are actually being sold, said once and in a form you can
   read without reading - the panel opposite carries the detail. */
.ticket-status {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 22px;
  font-size: 14px;
  color: var(--ink-dark-75);
}

.status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--pink);
}

.ticket-preview-price {
  margin: 6px 0 0;
  font-size: 48px;
  line-height: 1.2;
  color: var(--gold-deep);
}

/* The panel the buying happens in, lifted off the section so the form reads
   as the one thing to act on. Every BUY TICKETS on the page scrolls here. */
.final-cta .cta-panel {
  padding: 26px;
  border: 1px solid var(--gold-border-strong);
  border-radius: 16px;
  /* The panel stays dark on the off-white section: it is the one thing to
     act on here, and everything inside it (the gold button, the tier list,
     the notes) is drawn for a dark ground. */
  background: var(--card);
  color: var(--ink);
  box-shadow: 0 18px 44px rgba(36, 16, 25, 0.16);
}

.final-cta .accent {
  font-style: italic;
  color: var(--gold-deep);
}

.final-cta .cta-copy > p {
  margin: 16px 0 0;
  font-size: 16px;
  color: var(--ink-dark-75);
}

.final-cta .buy {
  padding: 0 28px;
  height: 54px;
  font-size: 15px;
}

.final-cta .buy-form {
  display: grid;
  gap: 12px;
  width: 100%;
}

.final-cta .qty {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 0 8px 0 18px;
  border: 1px solid var(--gold-border-strong);
  border-radius: 10px;
  background: rgba(11, 6, 10, 0.5);
  color: var(--ink-75);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.final-cta .qty select {
  appearance: none;
  -webkit-appearance: none;
  height: 100%;
  min-width: 64px;
  padding: 0 28px 0 10px;
  border: 0;
  border-radius: 8px;
  background: transparent url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23C6A15B' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") no-repeat right 8px center;
  color: var(--ink);
  font: inherit;
  font-size: 18px;
  font-weight: 800;
  letter-spacing: 0;
  cursor: pointer;
}

.final-cta .qty select:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: -2px;
}

/* Sales stopped after this page was built - paused, sold out or past doors -
   and the availability script has disabled the form and said why underneath.
   The picker has to read as dead too: dimming only the button leaves a live
   looking control next to it, still inviting the interaction the form no
   longer accepts. Matches .buy.soon so the two halves fade together. */
.final-cta .qty:has(select:disabled) {
  opacity: 0.55;
}

.final-cta .qty select:disabled {
  cursor: default;
  color: var(--ink);
}

.final-cta .buy-form .buy {
  border: 0;
  font: inherit;
  font-weight: 800;
  letter-spacing: 0.14em;
}

/* Pre-launch, the panel holds nothing but this button and one line under
   it, so the button takes the panel's full width and the line is centred on
   it - sat left in a panel this empty, the pair read as misplaced. */
.final-cta .buy.soon {
  cursor: default;
  opacity: 0.55;
  box-shadow: none;
  width: 100%;
}

.final-cta .buy.soon + .note {
  text-align: center;
}

/* The ticket types. There is nothing to choose here - the server always sells
   the cheapest one left - so this reads as a price list, not as a picker. */
.final-cta .tiers {
  display: grid;
  gap: 8px;
  width: 100%;
  margin: 22px 0 0;
  padding: 0;
  list-style: none;
}

/* name | status | price. The status is usually empty, so it sits in the
   flexible middle column rather than reserving a slab of dead space on the
   right - the price stays pinned to the edge and nothing shifts when the
   status arrives from the ticket server. */
.final-cta .tiers li {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: baseline;
  gap: 14px;
  padding: 12px 18px;
  border: 1px solid var(--gold-border);
  border-radius: 10px;
  background: rgba(11, 6, 10, 0.4);
  text-align: left;
}

.final-cta .tier-name {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-75);
}

/* Right-aligned against the row edge, so the prices line up down the list
   however many digits they carry. */
.final-cta .tier-price {
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--gold-light);
  text-align: right;
}

/* Empty until the script in index.astro fills it in. */
.final-cta .tier-status {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-60);
}

/* Nearly gone: the one place on this list worth hurrying for. */
.final-cta .tier-status.few {
  color: var(--pink);
  font-weight: 700;
}

/* Set by the live-count script in index.astro once a tier is gone. */
.final-cta .tiers li.gone {
  opacity: 0.5;
}

.final-cta .tiers li.gone .tier-price {
  text-decoration: line-through;
}

/* Why the form above is not taking orders, unhidden by the availability
   script in index.astro. Pink and full weight because it is the answer to
   "why did nothing happen when I clicked", not a footnote - it has to be
   found by someone whose eye is already on the button. */
.final-cta .buy-state {
  margin: 16px 0 0;
  font-size: 13px;
  line-height: 1.5;
  font-weight: 700;
  color: var(--pink);
}

.final-cta .note {
  margin-top: 18px;
  font-size: 12px;
  letter-spacing: 0.1em;
  color: var(--ink-60);
}

/* The "no email arrived" and terms links under the form: same quiet note
   type, but they are links, so they get the gold and an underline. */
.final-cta .note.help {
  margin-top: 10px;
}

.final-cta .note.help a {
  text-decoration: underline;
  text-underline-offset: 3px;
}

@media (max-width: 900px) {
  .final-cta {
    padding: 64px var(--page-gutter);
  }

  .final-cta h2 {
    font-size: 36px;
    line-height: 1.1;
  }

  .final-cta p {
    font-size: 13px;
    margin: 14px 0 22px;
  }

  .final-cta .buy {
    display: grid;
    height: 54px;
    padding: 0;
    font-size: 15px;
  }

  .cta-layout {
    grid-template-columns: 1fr;
    gap: 32px;
    align-items: stretch;
  }

  .ticket-preview-price {
    font-size: 40px;
  }

  .final-cta .qty {
    height: 54px;
    justify-content: space-between;
    padding: 0 10px 0 18px;
  }

  .final-cta .qty select {
    height: 44px;
  }

  .final-cta .tiers li {
    padding: 10px 14px;
    gap: 10px;
  }

  .final-cta .tier-name {
    font-size: 11px;
    letter-spacing: 0.1em;
  }

  .final-cta .tier-price {
    min-width: 70px;
    font-size: 19px;
  }

  .final-cta .tier-status {
    font-size: 10px;
  }
}

/* On a phone the three columns leave the name about 130px, which "General
   admission" does not fit - it wrapped, and the rows went ragged against each
   other. Give the name its own line and let price and count share the next. */
@media (max-width: 560px) {
  .final-cta .tiers li {
    grid-template-columns: auto 1fr;
    row-gap: 4px;
  }

  /* Placed explicitly, so the source order (name, status, price) can stay the
     reading order on desktop while the phone gets price then status. */
  .final-cta .tier-name {
    grid-column: 1 / -1;
    grid-row: 1;
  }

  .final-cta .tier-price {
    grid-column: 1;
    grid-row: 2;
    text-align: left;
  }

  .final-cta .tier-status {
    grid-column: 2;
    grid-row: 2;
    text-align: right;
  }
}

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

footer {
  padding: 64px var(--page-gutter) var(--buybar-clearance);
  background: var(--bg-deep);
  border-top: 1px solid var(--gold-border);
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: 40px;
}

footer .brand {
  font-size: 22px;
  color: var(--gold);
  margin-bottom: 14px;
}

footer .about p {
  font-size: 12.5px;
  color: rgba(242, 234, 217, 0.55);
  max-width: 280px;
  line-height: 1.6;
  margin: 0;
}

/* Where the night actually is. Matches the line above it: <address> is the
   right element for it but browsers default it to italic, which reads as
   emphasis the address does not want. */
footer .about address {
  font-size: 12.5px;
  color: rgba(242, 234, 217, 0.55);
  max-width: 280px;
  line-height: 1.6;
  margin: 12px 0 0;
  font-style: normal;
}

footer .sponsors {
  margin-top: 24px;
  display: flex;
  gap: 14px;
  opacity: 0.45;
}

footer .sponsors span {
  width: 72px;
  height: 24px;
  border: 1px solid var(--ink-border);
  border-radius: 4px;
  display: grid;
  place-items: center;
  font-size: 8px;
  letter-spacing: 0.15em;
}

footer .col {
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-size: 13px;
}

footer .heading {
  font-size: 10px;
  letter-spacing: 0.25em;
  color: var(--ink-60);
  text-transform: uppercase;
  margin-bottom: 4px;
}

@media (max-width: 900px) {
  footer {
    grid-template-columns: 1fr 1fr;
    gap: 28px;
    padding: 40px var(--page-gutter) var(--buybar-clearance);
  }

  footer .about {
    grid-column: span 2;
  }

  footer .brand {
    font-size: 18px;
  }
}

/* ---------- StickyBuyBar ----------

   The page's always-available ticket control, on every viewport - the nav
   carries no BUY TICKETS. public/site.js adds `is-managed` and then shows it
   only where neither the hero button nor the ticket panel is on screen, so
   the reader is never offered the same thing twice. With no JavaScript it
   simply stays visible, which is the safe failure: one extra route to the
   ticket form, never none. */

.buy-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 50;
  padding: 12px var(--page-gutter) calc(14px + env(safe-area-inset-bottom));
  background: linear-gradient(180deg, transparent, rgba(11, 6, 10, 0.92) 40%);
  pointer-events: none;
}

.buy-bar.is-managed {
  visibility: hidden;
  opacity: 0;
  transform: translateY(100%);
  transition: opacity 0.22s ease, transform 0.22s ease, visibility 0.22s;
}

.buy-bar.is-managed.is-visible {
  visibility: visible;
  opacity: 1;
  transform: none;
}

.buy-bar .bar {
  pointer-events: auto;
  max-width: 560px;
  margin: 0 auto;
  height: 60px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 26px;
  background: var(--gold);
  color: var(--on-gold);
  box-shadow: 0 10px 34px rgba(0, 0, 0, 0.55);
}

.buy-bar .bar:hover {
  color: var(--on-gold);
  filter: brightness(1.06);
}

.buy-bar .label {
  font-size: 14px;
  font-weight: 800;
  letter-spacing: 0.12em;
}

.buy-bar .price {
  font-size: 13px;
  font-weight: 700;
}

@media (max-width: 900px) {
  .buy-bar {
    padding-left: 16px;
    padding-right: 16px;
  }
}

/* ---------------------------------------------------------------------------
   Teaser (src/ui/Teaser.jsx) - the whole public page while `prelaunch` is on
   in the CMS. It replaces the site rather than sitting inside it, so these
   rules are self-contained and share only the palette and the fonts.
--------------------------------------------------------------------------- */

.teaser {
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: 48px 28px;
  background:
    radial-gradient(120% 80% at 50% 0%, var(--aubergine) 0%, transparent 60%),
    radial-gradient(90% 60% at 50% 100%, rgba(226, 62, 143, 0.12) 0%, transparent 70%),
    var(--bg-deep);
}

.teaser .teaser-inner {
  width: 100%;
  max-width: 720px;
  text-align: center;
}

.teaser .badge {
  width: 56px;
  height: 56px;
  margin: 0 auto 28px;
  border: 1px solid var(--gold);
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 20px;
  letter-spacing: 0.06em;
  color: var(--gold);
}

.teaser h1 {
  margin: 0;
  font-size: clamp(40px, 10.5vw, 84px);
  line-height: 1.02;
  letter-spacing: 0.01em;
  text-wrap: balance;
  color: var(--ink);
}

.teaser .teaser-lead {
  margin: 18px 0 0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.42em;
  text-transform: uppercase;
  color: var(--gold);
}

.teaser .teaser-note {
  margin: 28px auto 0;
  max-width: 42ch;
  font-size: 15px;
  line-height: 1.7;
  color: var(--ink-75);
}

.teaser .teaser-links {
  margin-top: 40px;
  display: grid;
  justify-items: center;
  gap: 20px;
}

.teaser .btn-gold {
  padding: 14px 30px;
  border-radius: 8px;
  font-size: 12.5px;
  letter-spacing: 0.14em;
}

.teaser .teaser-mail {
  font-size: 14px;
  color: var(--ink-65);
  border-bottom: 1px solid var(--gold-border);
  padding-bottom: 2px;
}

.teaser .teaser-mail:hover {
  color: var(--gold-light);
}

/* ---------------------------------------------------------------------------
   Legal pages (src/pages/terms.astro, src/pages/privacy.astro) - the ticket
   terms and the privacy notice. Long-form reading rather than a landing page,
   so this is one narrow measure of text on the same palette; nothing here is
   shared with the CMS preview, which only ever renders the one-page site.
--------------------------------------------------------------------------- */

.legal {
  max-width: 760px;
  margin: 0 auto;
  padding: 96px 24px 110px;
  color: var(--ink-85);
  font-size: 16px;
  line-height: 1.75;
}

.legal .back {
  display: inline-block;
  margin-bottom: 28px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.28em;
  text-transform: uppercase;
}

.legal h1 {
  margin: 0 0 28px;
  font-size: 52px;
  line-height: 1.08;
  color: var(--ink);
}

.legal h2 {
  margin: 48px 0 12px;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
}

.legal p {
  margin: 0 0 16px;
}

.legal ul {
  margin: 0 0 16px;
  padding-left: 22px;
}

.legal li {
  margin-bottom: 10px;
}

.legal strong {
  color: var(--ink);
  font-weight: 700;
}

/* The "not legally reviewed" banner and the unresolved-question callouts:
   deliberately loud, because both are meant to be read and then removed. */
.legal .draft,
.legal .todo {
  border-left: 2px solid var(--gold);
  border-radius: 0 10px 10px 0;
  padding: 16px 20px;
  background: rgba(198, 161, 91, 0.08);
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--ink-75);
}

.legal .draft {
  margin-bottom: 8px;
}

.legal .todo {
  border-left-color: var(--pink);
  background: rgba(226, 62, 143, 0.08);
}

@media (max-width: 900px) {
  .legal {
    padding: 56px 24px 64px;
    font-size: 15px;
  }

  .legal h1 {
    font-size: 32px;
  }

  .legal h2 {
    margin-top: 36px;
    font-size: 13px;
  }
}
