/* Plain-CSS reproduction of the Figma Make mockup "Home page mockup for performer".
   Source: figma-make/source/src/App.tsx and index.css. Values mirror the mockup's Tailwind
   classes (1 Tailwind spacing unit = 0.25rem; the md breakpoint is 768px, sm is 640px). */

:root {
  /* Version 5: the near-black ground of site4, cooled a step towards indigo, with a wisteria
     accent in place of amber. The accent comes from indigo.html (wisteria #b8a3e6); the greys are
     the old ones re-tinted towards the accent so nothing on the page is warm. --amber is kept as a
     name so the rest of this file needs no change: it now holds the accent. */
  --ink: #09090f;
  --bone: #eeedf5;
  --accent: #b8a3e6;
  --amber: var(--accent);
  --dim: #18172a;
  --muted: #8f8bab;
  /* A form field's underline, its only outline: 3.1:1 on the dialog, the 3:1 a control's edge needs
     (WCAG 1.4.11; the old #34324a was 1.56:1, review 2026-10-17). */
  --field-line: #665b83;
  --raised: #0e0d17;
  --row-hover: #13121f;
  --hairline: rgba(184, 163, 230, 0.22);
  --hairline-soft: rgba(184, 163, 230, 0.15);

  --font-display: "Cormorant", Georgia, serif;
  --font-body: "Nunito", system-ui, sans-serif;
  --font-mono: "DM Mono", ui-monospace, monospace;

  --pad-x: 2rem;
  /* Space above and below every section's content; two of these sit between one section and the next. */
  --section-pad: 2.5rem;
  /* The fixed header's height: .site-header's 1.5rem padding above and below the logo's 1.75rem line.
     Change it with them; scroll-padding-top on html depends on it. */
  --header-h: 4.75rem;
}

@media (min-width: 768px) {
  :root {
    --pad-x: 3.5rem;
    --section-pad: 3rem;
  }
}

/* ─── Base ─────────────────────────────────────────── */

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

html {
  background: var(--ink);
  color: var(--bone);
  font-family: var(--font-body);
  line-height: 1.5;
  scroll-behavior: smooth;
  /* Scrolling is free (no snapping, 2026-10-10). scroll-padding-top only sets where a section's top
     lands when a link jumps to it (the nav, #shows ...). It is the header's height less the section's
     own top padding, so at every width the section's eyebrow lands just under the header (4.75rem
     down), where the hero's eyebrow is on desktop. One rule, no breakpoint: --section-pad already
     changes with the width (2026-10-16). */
  scroll-padding-top: calc(var(--header-h) - var(--section-pad));
}

body {
  margin: 0;
  overflow-x: hidden;
  /* Background and colour are stated here as well as on html: a published artifact pastes the
     page inside its own <body>, whose stylesheet sets a light background and near-black text
     that would otherwise win over html's by inheritance. */
  background: var(--ink);
  color: var(--bone);
}

h1,
h2,
h3,
p,
figure,
blockquote {
  margin: 0;
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

/* <picture> only chooses which file the img loads (tools/images/images.py); it takes no part in the layout. */
picture {
  display: contents;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

::-webkit-scrollbar {
  width: 4px;
}

::-webkit-scrollbar-thumb {
  background: rgba(184, 163, 230, 0.3);
}

::-webkit-scrollbar-track {
  background: transparent;
}

/* ─── Shared type ──────────────────────────────────── */

.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.2em;
  text-transform: uppercase; /* wide spacing suits capitals; on lowercase it broke words apart */
  color: var(--amber);
}

.accent {
  font-style: normal;
  font-weight: 600;
  color: var(--amber);
}

.body-copy {
  max-width: 32rem;
  margin-top: 2rem;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--muted);
  text-wrap: pretty;
}


.body-copy + .body-copy {
  margin-top: 1rem;
}

/* Nav link hover: a thin amber underline grows from the left. */
.nav-link {
  position: relative;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: #b5aea3; /* soft stone grey: about 9:1 on the dark header, readable over the hero video */
  transition: color 0.3s;
}

.nav-link::after {
  content: "";
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 0;
  height: 1px;
  background: var(--amber);
  transition: width 0.3s;
}

.nav-link:hover {
  color: var(--bone);
}

.nav-link:hover::after {
  width: 100%;
}

.button {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.875rem 1.75rem;
  background: var(--amber);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background-color 0.3s;
}

.button:hover {
  background: var(--bone);
}

.button-outline {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem 2rem;
  border: 1px solid rgba(184, 163, 230, 0.4);
  color: var(--amber);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: border-color 0.3s, background-color 0.3s;
}

.button-outline:hover {
  border-color: var(--amber);
  background: rgba(184, 163, 230, 0.05);
}

/* ─── Header ───────────────────────────────────────── */

.site-header {
  position: fixed;
  inset: 0 0 auto;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.5rem var(--pad-x);
  background: linear-gradient(to bottom, rgba(9, 9, 15, 0.9) 0%, transparent 100%);
}

.logo {
  font-family: var(--font-display);
  font-size: 1.25rem;
  line-height: 1.75rem;
  font-style: italic;
  letter-spacing: 0.1em;
}

.nav {
  display: none;
  gap: 2.5rem;
}

/* The header nav matters most, so it is larger and brighter than the other text links. */
.nav .nav-link {
  font-size: 0.85rem;
  color: var(--bone);
  text-shadow: 0 1px 8px rgba(9, 9, 15, 0.8);
}

.nav .nav-link:hover {
  color: var(--amber);
}

.menu-button {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.menu-button span {
  display: block;
  width: 1.5rem;
  height: 1px;
  background: var(--amber);
  transition: transform 0.3s, opacity 0.3s;
}

.menu-button[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}

.menu-button[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
}

.menu-button[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2rem;
  background: rgba(9, 9, 15, 0.98);
}

.mobile-menu[hidden] {
  display: none;
}

.mobile-menu a {
  font-family: var(--font-display);
  font-size: 2.25rem;
  line-height: 2.5rem;
  font-style: italic;
  transition: color 0.15s;
}

.mobile-menu a:hover {
  color: var(--amber);
}

/* The header nav replaces the menu button from 960px: its six links (Home to Coaching) don't clear the
   logo any narrower, so a small tablet keeps the menu. Everything else changes at 768px. */
@media (min-width: 960px) {
  .nav {
    display: flex;
  }

  .menu-button,
  .mobile-menu {
    display: none;
  }
}

/* ─── Hero ─────────────────────────────────────────── */

.hero {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr auto; /* the content, then the ticker along the bottom */
  min-height: 100vh;
  overflow: hidden;
}

.hero-text {
  position: relative;
  z-index: 10;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  /* Starts right under the fixed header (4.75rem tall) rather than sinking to the bottom of the screen,
     so the title sits at the same height whatever the window size. Phones leave more room for the photo. */
  padding: calc(4.75rem + 7rem) var(--pad-x) 4rem;
}

.hero .eyebrow {
  margin-bottom: 1.5rem;
}

/* Four lines of title instead of the mockup's three short words, so it sits a step smaller. */
.hero-title {
  font-family: var(--font-display);
  font-size: clamp(3rem, 7vw, 6.5rem);
  font-style: italic;
  font-weight: 300;
  line-height: 0.9;
}

.hero-intro {
  max-width: 28rem;
  margin-top: 2rem;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--muted);
  text-wrap: pretty;
}

/* A second hero paragraph (the intro is an editable paragraph group) sits closer than the first. */
.hero-intro + .hero-intro {
  margin-top: 1rem;
}

.hero-actions {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  margin-top: 2.5rem;
}

.stats {
  display: flex;
  gap: 2.5rem;
  margin-top: 4rem;
  padding-top: 2rem;
  border-top: 1px solid var(--hairline);
}

.stat-value {
  font-family: var(--font-display);
  font-size: 1.875rem;
  font-style: italic;
  font-weight: 600;
  line-height: 2.25rem;
  color: var(--amber);
}

.stat-label {
  margin-top: 0.25rem;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}

.hero-image {
  position: relative;
  display: none;
  background: var(--dim);
}

/* The ticker takes the bottom of the first screen, so the picture keeps its full height and moves up by
   the ticker's height instead: its top is cut off by that much (the hero clips it) rather than the
   whole picture shrinking. The video and the still move together, so the swap between them stays exact. */
.hero-image img,
.hero-image .hero-video {
  position: absolute;
  top: calc(var(--ticker-h) * -1);
  left: 0;
  width: 100%;
  height: calc(100% + var(--ticker-h));
  object-fit: cover;
  opacity: 0.8;
}

/* Two tonal gradients fade the photo into the black page. */
.hero-image::before,
.hero-image::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.hero-image::before {
  background: linear-gradient(to right, var(--ink) 0%, transparent 30%, transparent 100%);
}

.hero-image::after {
  background: linear-gradient(to top, var(--ink) 0%, transparent 40%);
}

.hero-image-mobile {
  position: absolute;
  inset: 0;
  background: var(--dim);
}

/* The photo is see-through, so the still underneath would show through the video. Hide it while the video is up. */
.hero-image:has(.hero-video:not([hidden])) img,
.hero-image-mobile:has(.hero-video:not([hidden])) img {
  visibility: hidden;
}

.hero-image-mobile img,
.hero-image-mobile .hero-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.3;
}

@media (min-width: 768px) {
  .hero {
    grid-template-columns: 1fr 1fr;
  }


  /* The site name ends 3.25rem down, so this leaves 1.5rem under it: the same gap as between the
     eyebrow and the title inside the block. */
  .hero-text {
    padding-top: 4.75rem;
  }

  .hero-image {
    display: block;
  }

  .hero-image-mobile {
    display: none;
  }
}

/* Fade-in on load. Opacity only: a rising slide made the page look as if it scrolled as it loaded. */
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.fade-up {
  animation: fadeIn 0.9s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.fade-up-2 {
  animation-delay: 0.15s;
}

.fade-up-3 {
  animation-delay: 0.3s;
}

.fade-up-4 {
  animation-delay: 0.45s;
}


/* ─── About ────────────────────────────────────────── */

.about {
  display: grid;
  grid-template-columns: 1fr;
  gap: 4rem;
  align-items: start;
  padding: var(--section-pad) var(--pad-x);
}

/* The same 1.5rem that separates the site name from the eyebrow. */
.about .eyebrow {
  margin-bottom: 1.5rem;
}

.about img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
}

/* The About photo's crossfade video lies exactly over the still (the still is its last frame). The video is
   opaque and the same shape, so the still can stay where it is underneath. */
.about-photo {
  position: relative;
}

.about-photo img {
  display: block;
}

.about-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.about-title {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 5vw, 5rem);
  font-style: italic;
  font-weight: 300;
  line-height: 1.05;
}

/* In the mockup this link's text-xs class loses its font size to .nav-link but keeps its line height. */
.read-more {
  display: inline-block;
  margin-top: 2.5rem;
  line-height: calc(1 / 0.75);
}

/* The listings' line about the show, set apart from the synopsis. */
.pull-quote {
  max-width: 32rem;
  margin-top: 2.5rem;
  padding-left: 1.25rem;
  border-left: 1px solid var(--amber);
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-style: italic;
  font-weight: 300;
  line-height: 1.3;
}

@media (min-width: 768px) {
  .about {
    grid-template-columns: 2fr 3fr;
  }

  /* The text block starts 3rem below the photo, as in the mockup. */
  .about-text {
    padding-top: 5.5rem;
  }
}

/* ─── Section headings (Work, Shows) ───────────────── */

.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  /* The same 1.5rem that separates the site name from the eyebrow. */
  margin-bottom: 1.5rem;
}

.section-head .eyebrow {
  margin-bottom: 0.5rem;
}

.section-title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 4vw, 4rem);
  font-style: italic;
  font-weight: 300;
  line-height: 1.25;
}

.archive-link {
  display: none;
}

@media (min-width: 768px) {
  .archive-link {
    display: block;
  }
}

/* ─── Press quotes (in the hero) ───────────────────── */

/* Phone: the last row of the hero, under the buttons, so it shows on the first screen.
   Desktop: laid over the foot of the photo, beside the title. */
.hero-press {
  position: relative;
  z-index: 10;
  display: grid;
  padding: 0 var(--pad-x) 2.5rem;
  animation: fadeIn 0.9s 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@media (min-width: 768px) {
  .hero-press {
    position: absolute;
    right: var(--pad-x);
    bottom: calc(3.5rem + var(--ticker-h));
    width: min(28rem, 40%);
    padding: 1.5rem 0 0;
    border-top: 1px solid var(--hairline);
  }
}

/* ─── Ticker ───────────────────────────────────────── */

/* The hero's bottom edge: a band of words that drifts left, after the mockup's marquee. It is the hero's
   last grid row, full width, so it shows on the first screen and the photo stops above it. */
:root {
  --ticker-h: 2.75rem;
}

.ticker {
  position: relative;
  z-index: 10;
  grid-column: 1 / -1;
  align-self: end;
  display: flex;
  align-items: center;
  height: var(--ticker-h);
  overflow: hidden;
  background: var(--ink);
  border-block: 1px solid var(--hairline-soft);
}

.ticker-track {
  display: flex;
  width: max-content;
  animation: ticker 60s linear infinite;
}

/* Each group ends with the same gap that separates its words, so two groups side by side repeat evenly. */
.ticker-group {
  display: flex;
  gap: 2.5rem;
  padding-right: 2.5rem;
  white-space: nowrap;
}

.ticker-group span {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--muted);
}

.ticker-group .dot {
  color: var(--accent);
}

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

@media (prefers-reduced-motion: reduce) {
  .ticker-track {
    animation: none;
  }
}

/* All quotes sit in one grid cell, so the block is as tall as the longest and nothing shifts as they change.
   Only the current one shows. It leaves by fading out, and the next arrives with the hero's own fade-in. */
.quote {
  grid-area: 1 / 1;
  align-self: end;
  max-width: 48rem;
  visibility: hidden;
}

.quote.is-current,
.quote.is-leaving {
  visibility: visible;
}

.quote.is-entering {
  animation: fadeIn 0.9s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.quote.is-leaving {
  animation: fadeOut 0.9s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes fadeOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

.quote blockquote {
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 1.8vw, 1.6rem);
  font-style: italic;
  font-weight: 300;
  line-height: 1.3;
}

.quote figcaption {
  margin-top: 1rem;
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--amber);
}

/* Pause / Play for the quotes and the ticker (script.js): a second row under the quotes, set like their
   caption so it reads as part of it, at 12px with a 24px-tall target. */
.motion-toggle {
  grid-row: 2;
  justify-self: start;
  display: inline-flex;
  align-items: center;
  min-height: 1.5rem;
  margin-top: 0.75rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color 0.15s;
}

.motion-toggle[hidden] {
  display: none;
}

@media (hover: hover) {
  .motion-toggle:hover {
    color: var(--accent);
  }
}

.ticker.is-paused .ticker-track {
  animation-play-state: paused;
}

/* ─── Upcoming shows ───────────────────────────────── */

.shows {
  padding: var(--section-pad) var(--pad-x);
  border-top: 1px solid var(--hairline-soft);
}

/* Photo tiles that pick which dates the list shows: short strips, a header for the calendar rather than cards. */
.date-filters {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  margin-bottom: 2.5rem;
  background: var(--hairline-soft);
}

/* Five tiles (2026-10-17, Dance added): on a phone the All tile takes the first row on its own, the four kinds
   pair up below it; from tablet width all five sit in one row. */
.date-filter[data-kind="all"] {
  grid-column: 1 / -1;
}

@media (min-width: 768px) {
  .date-filters {
    grid-template-columns: repeat(5, 1fr);
  }

  .date-filter[data-kind="all"] {
    grid-column: auto;
  }
}

.date-filter {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  height: 7rem;
  padding: 1rem;
  overflow: hidden;
  border: 0;
  background: var(--ink);
  color: var(--bone);
  text-align: left;
  cursor: pointer;
}

@media (min-width: 768px) {
  .date-filter {
    height: 10rem;
    padding: 1.25rem;
  }
}

.date-filter img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Full colour on every tile, pushed brighter and more saturated so the row catches the eye;
     the amber rule, not the photo, marks the chosen tile. */
  filter: brightness(1.15) saturate(1.45) contrast(1.05);
  transition: transform 0.7s, filter 0.5s;
}

/* A short shade along the bottom keeps the labels legible without dimming the photo. */
.date-filter::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(9, 9, 15, 0.75) 0%, rgba(9, 9, 15, 0.2) 45%, transparent 70%);
}

/* Hover only where there is a real pointer: on a touch screen :hover sticks after a tap. The zoom is
   motion, so it also waits for visitors who haven't asked for reduced motion (2026-10-17 review). */
@media (hover: hover) {
  .date-filter:hover img {
    filter: brightness(1.25) saturate(1.6) contrast(1.05);
  }
}

@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .date-filter:hover img {
    transform: scale(1.05);
  }
}

/* The chosen tile carries an amber rule along its bottom edge. */
.date-filter[aria-pressed="true"]::before {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 2;
  height: 4px;
  background: var(--amber);
  box-shadow: 0 0 12px var(--amber);
}

.date-filter:focus-visible {
  outline: 1px solid var(--amber);
  outline-offset: -1px;
}

.date-filter-label,
.date-filter-count {
  position: relative;
  z-index: 1;
}

.date-filter-label {
  font-family: var(--font-display);
  font-size: clamp(1.1rem, 2vw, 1.5rem);
  font-style: italic;
  font-weight: 600;
  line-height: 1.2;
}

.date-filter-count {
  margin-top: 0.25rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--amber);
}

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

.show + .show {
  border-top: 1px solid var(--hairline-soft);
}

/* Each date is two rows. Row 1: the event's kind, name and description across the full width.
   Row 2: the facts that line up down the list (date, city, venue, link). On a phone, row 2 itself
   wraps: date and link, then city · venue. Rows bleed to the page edges so the hover tint spans the
   full width. */
.show {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas:
    "main  main  main"
    "date  date  action"
    "city  venue venue";
  column-gap: 0.4rem;
  row-gap: 0.4rem;
  align-items: baseline;
  margin-inline: calc(var(--pad-x) * -1);
  padding: 1.25rem var(--pad-x);
  transition: background-color 0.2s;
}

.show:hover {
  background: var(--row-hover);
}

.show-date {
  grid-area: date;
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.2em;
  color: var(--amber);
}

.show-city,
.show-venue {
  font-size: 0.75rem;
  line-height: 1rem;
  color: var(--muted);
}

.show-city {
  grid-area: city;
}

.show-venue {
  grid-area: venue;
}

/* On a phone city and venue share a line: a dot keeps them apart. */
.show-venue::before {
  content: "· ";
}

.show-main {
  grid-area: main;
  min-width: 0;
  margin-bottom: 0.5rem;
}

.show-title {
  font-family: var(--font-display);
  font-size: 1.125rem;
  font-style: italic;
  font-weight: 300;
  line-height: 1.75rem;
}

.show-kind {
  display: block;
  margin-bottom: 0.25rem;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--muted);
}

.show-sub {
  margin-top: 0.25rem;
  font-size: 0.75rem;
  line-height: 1rem;
  color: var(--muted);
}

.show-tickets {
  grid-area: action;
  justify-self: end;
  text-align: right;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: 0.6rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--amber);
  text-decoration: none;
}

.show-tickets:hover {
  text-decoration: underline;
}

/* Announced but not yet on sale: the row still reads, but there is nothing to click. */
.show-tickets[data-status="announced"] {
  color: var(--muted);
}

.show-tickets[data-status="few-left"]::after {
  content: " · Few left";
  color: var(--muted);
}


/* Nothing to come in the chosen kind (theatre books in bursts, so this is the section's normal condition):
   the empty state is a row of the list, the first one, asking visitors to hear about new dates. It bleeds
   to the page edges like the date rows, on a raised ground so it reads as the row to act on
   (2026-10-17). Title and copy on the left, the button on the right; stacked on a phone. */
.shows-empty {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "title" "copy" "action";
  row-gap: 0.5rem;
  align-items: center;
  margin-inline: calc(var(--pad-x) * -1);
  padding: 1.5rem var(--pad-x);
  border-block: 1px solid var(--hairline-soft);
  background: var(--raised);
}

.shows-empty[hidden] {
  display: none;
}

.shows-empty-title {
  grid-area: title;
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.2vw, 1.75rem);
  font-style: italic;
  font-weight: 300;
  line-height: 1.2;
}

.shows-empty > div[data-copy] {
  grid-area: copy;
}

/* Only the chosen kind's title and copy show; the other kinds' pairs wait, hidden, for their tile. */
.shows-empty > [hidden] {
  display: none;
}

.shows-empty .body-copy {
  max-width: 40rem;
  margin-top: 0;
}

.shows-empty .button-outline {
  grid-area: action;
  justify-self: start;
  margin-top: 1rem;
}

@media (min-width: 768px) {
  .shows-empty {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "title action" "copy action";
    column-gap: 2.5rem;
  }

  .shows-empty .button-outline {
    margin-top: 0;
  }
}

/* The recent past, shown only when nothing is to come in the chosen kind: the same rows, under a small
   heading, faded to read as a record rather than something to book. */
.shows-past {
  margin-top: 2rem;
}

/* A past row: its words in the muted grey, still readable (6.1:1), and its ticket link switched off:
   no pointer, no hover, the dim inactive colour. script.js also takes the link out of the Tab order and
   marks it aria-disabled, since CSS alone can't stop a keyboard reaching it. */
.show.is-past .show-title,
.show.is-past .show-date {
  color: var(--muted);
}

.show.is-past:hover {
  background: transparent;
}

.show.is-past a,
.show.is-past .show-tickets {
  pointer-events: none;
  cursor: default;
  color: var(--field-line);
  text-decoration: none;
}

.shows-past-title {
  margin: 0 0 0.75rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent);
}

@media (min-width: 768px) {
  .show {
    grid-template-columns: 14rem 10rem minmax(0, 1fr) auto;
    grid-template-areas:
      "main main main  main"
      "date city venue action";
    column-gap: 1.5rem;
  }

  .show-venue::before {
    content: none;
  }
}

/* ─── Contact ──────────────────────────────────────── */

.contact {
  position: relative;
  overflow: hidden;
  padding: var(--section-pad) var(--pad-x);
  border-top: 1px solid var(--hairline-soft);
}

.contact-bg {
  position: absolute;
  inset: 0;
  background: var(--dim);
}

.contact-bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.2;
}

.contact-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(9, 9, 15, 0.9) 0%, rgba(24, 23, 42, 0.7) 100%);
}

.contact-content {
  position: relative;
  z-index: 10;
  max-width: 42rem;
}

.contact .eyebrow {
  margin-bottom: 1.5rem;
}

.contact-title {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 6vw, 6rem);
  font-style: italic;
  font-weight: 300;
  line-height: 0.95;
}

.contact .body-copy {
  max-width: 28rem;
}

.contact-actions {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-top: 2.5rem;
}

.contact-actions .button {
  padding: 1rem 2rem;
}

/* A row from 640px, wrapping when the three buttons don't fit (just over 640px, or 200% zoom) rather
   than running off the side, where body's overflow-x would cut the last one off. */
@media (min-width: 640px) {
  .contact-actions {
    flex-direction: row;
    flex-wrap: wrap;
  }
}

/* ─── The popover form ─────────────────────────────── */

.message-dialog {
  width: min(36rem, calc(100vw - 2rem));
  max-height: calc(100vh - 2rem);
  padding: 0;
  border: 1px solid var(--hairline);
  background: var(--raised);
  color: var(--bone);
  overflow: auto;
}

.message-dialog::backdrop {
  background: rgba(9, 9, 15, 0.8);
  backdrop-filter: blur(4px);
}

.message-form,
.message-sent {
  position: relative;
  padding: 3rem 2rem 2.5rem;
}

/* "Hearing about new dates" is a sign-up (script.js sets .is-signup): the name becomes optional
   (the message always is), the "Tell me" box goes (it always signs up), and the thank-you says so. */
.message-dialog:not(.is-signup) [data-signup-only],
.message-dialog.is-signup [data-not-signup] {
  display: none;
}

.field-optional {
  margin-left: 0.5rem;
  letter-spacing: 0.1em;
  text-transform: none;
  color: var(--muted);
}

.message-close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  width: 2.5rem;
  height: 2.5rem;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-family: var(--font-display);
  font-size: 2rem;
  line-height: 1;
  cursor: pointer;
  transition: color 0.3s;
}

.message-close:hover {
  color: var(--bone);
}

.message-sent .message-close {
  position: static;
  width: auto;
  height: auto;
  margin-top: 2rem;
  font-family: var(--font-mono);
  font-size: 0.65rem;
  line-height: normal;
  cursor: pointer;
}

.message-title {
  margin-top: 1rem;
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 5vw, 3.5rem);
  font-style: italic;
  font-weight: 300;
  line-height: 0.95;
}

.message-fields {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
  margin-top: 2rem;
}

@media (min-width: 640px) {
  .message-fields {
    grid-template-columns: 1fr 1fr;
  }

  .field-wide {
    grid-column: 1 / -1;
  }
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.field-label {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--amber);
}

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.75rem 0;
  border: 0;
  border-bottom: 1px solid var(--field-line);
  border-radius: 0;
  background: transparent;
  color: var(--bone);
  font-family: var(--font-body);
  font-size: 0.95rem;
  line-height: 1.5;
  transition: border-color 0.3s;
}

.field select {
  cursor: pointer;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--amber) 50%), linear-gradient(135deg, var(--amber) 50%, transparent 50%);
  background-position: calc(100% - 12px) 55%, calc(100% - 6px) 55%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: 1.5rem;
}

.field select option {
  background: var(--raised);
  color: var(--bone);
}

.field textarea {
  resize: vertical;
  min-height: 7rem;
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-bottom-color: var(--amber);
  /* The idle line is now bright enough that colour alone no longer marks focus clearly, so the line
     also thickens to 2px (a shadow under the border, so nothing below moves). */
  box-shadow: 0 1px 0 var(--amber);
}

.field input:user-invalid,
.field textarea:user-invalid {
  border-bottom-color: #b5533a;
}

.check {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.85rem;
  color: var(--muted);
  cursor: pointer;
}

.check input {
  width: 1rem;
  height: 1rem;
  margin: 0;
  accent-color: var(--amber);
}

.message-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.5rem;
  margin-top: 2.5rem;
}

.message-actions .button {
  padding: 1rem 2.5rem;
}

.message-note {
  font-size: 0.75rem;
  color: var(--muted);
}

.message-sent .body-copy {
  margin-top: 1.5rem;
}

/* Why a form wasn't sent (from the deploy app, or the connection). Shown above the button; what was
   typed stays in the fields. */
.form-error {
  margin-top: 2rem;
  padding-left: 0.75rem;
  border-left: 2px solid var(--amber);
  font-size: 0.85rem;
  line-height: 1.5;
}

.form-error + .message-actions {
  margin-top: 1.25rem;
}

/* The honeypot field: in the form for bots, out of sight and reach for people. */
.form-trap {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ─── Reduced motion ───────────────────────────────── */

/* The Make site settings respect reduced motion (ignoreReducedMotion: false), so this does too. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .fade-up,
  .hero-press,
  .quote {
    animation: none;
  }
}

/* ─── Footer ───────────────────────────────────────── */

/* Heavier than the mockup's: it carries the writing life and the coaching practice. */
.site-footer {
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
  padding: 2.5rem var(--pad-x);
  border-top: 1px solid var(--hairline-soft);
}

.footer-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.5rem;
}

.footer-writing {
  max-width: 36rem;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--muted);
  text-wrap: pretty;
}

.footer-heading {
  margin-bottom: 0.5rem;
  font-family: var(--font-display);
  font-size: 1.125rem;
  font-style: italic;
  color: var(--bone);
}

.footer-writing p:not(.footer-heading) + p,
.footer-body + p {
  margin-top: 0.75rem;
}

/* Ask About Coaching: the same outline button as Hear About New Dates, with room above it. */
.footer-writing .footer-actions {
  margin-top: 1.5rem;
}

.footer-writing a {
  color: var(--amber);
}

.footer-logo {
  font-family: var(--font-display);
  font-size: 1.125rem;
  font-style: italic;
  line-height: 1.75rem;
  color: var(--muted);
  white-space: nowrap;
}

.footer-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2rem; /* a wrapped second line sits close under the first */
}

.footer-social {
  display: flex;
  gap: 1.25rem;
}

.footer-social a {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color 0.15s;
}

.footer-social a:hover {
  color: var(--amber);
}

.copyright {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  color: var(--muted);
}

/* Logo, six links and Instagram fit on one row from 960px, where the header nav appears too; narrower,
   they stack. */
@media (min-width: 960px) {
  .footer-row {
    flex-direction: row;
    align-items: center;
  }
}

/* ─── Typography review (2026-10-15) ─────────────────── */
/* Body text a step up on wider screens (typography review, 2026-10-15: 14px was too small for the
   audience). */
@media (min-width: 768px) {
  .body-copy,
  .hero-intro {
    font-size: 1.0625rem;
  }
}


/* Headings and pull quotes break into even lines, so no word is left alone on the last one. */
h1,
h2,
blockquote,
.shows-empty-title {
  text-wrap: balance;
}

/* The tight display leading works at desktop size; on a phone descenders (the g of "Bring") nearly
   touch the next line. */
@media (max-width: 599px) {
  .hero-title,
  .contact-title {
    line-height: 1;
  }
}

/* On a phone the two hero buttons stack, left-aligned with the text, rather than wrap their labels. */
@media (max-width: 479px) {
  .hero-actions {
    flex-direction: column;
    align-items: flex-start;
    gap: 1rem;
  }

  .button,
  .button-outline {
    padding-left: 1.25rem;
    padding-right: 1.25rem;
  }
}

/* ─── Privacy page (privacy.html) ──────────────────── */

.privacy {
  max-width: 40rem;
  padding: calc(var(--header-h) + 3rem) var(--pad-x) 4rem;
}

.privacy .section-title {
  margin-top: 1rem;
}

.privacy-date {
  margin-top: 1rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  color: var(--muted);
}

.privacy h2 {
  margin-top: 3rem;
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-style: italic;
  font-weight: 400;
}

.privacy h2 + .body-copy {
  margin-top: 1rem;
}

.privacy .body-copy {
  max-width: none;
}

.privacy strong {
  font-weight: 600;
  color: var(--bone);
}

.privacy ul.body-copy {
  padding-left: 1.25rem;
  list-style: disc;
}

.privacy li + li {
  margin-top: 0.5rem;
}

.privacy a,
.message-note a,
.copyright a {
  color: var(--bone);
  text-decoration: underline;
  text-decoration-color: var(--hairline);
  text-underline-offset: 0.2em;
}

.privacy a:hover,
.message-note a:hover,
.copyright a:hover {
  color: var(--amber);
}

/* ─── Cookie consent banner (consent.js) ───────────── */
/* consent.js adds its own stylesheet when the banner opens, after this one, so these rules need the
   extra `body` to win. Colours and type only; the layout and the equal buttons are the script's. */

body .cc-banner,
body .cc-panel {
  --cc-bg: var(--raised);
  --cc-fg: var(--bone);
  --cc-line: var(--accent);
  --cc-focus: var(--accent);
  border-width: 1px;
  box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.6);
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 0.95rem;
}

body .cc-banner h2,
body .cc-panel h2 {
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-style: italic;
  font-weight: 400;
}

body .cc-banner a,
body .cc-panel a {
  text-decoration-color: var(--hairline);
  text-underline-offset: 0.2em;
}

body .cc-row button {
  border-width: 1px;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 400;
  letter-spacing: 0.15em;
  text-transform: uppercase;
}

body .cc-row button:hover {
  background: var(--accent);
  color: var(--ink);
}

body .cc-panel small {
  color: var(--muted);
}
