/*
 * YDT theme styles, loaded after Bootstrap 5.3 and css/brand.css (the project's colour, font and radius
 * values). Reusable across projects: brand values are only referenced here, never defined.
 * Mobile-first: base rules target xs, larger breakpoints use Bootstrap min-width values
 * (sm 576, md 768, lg 992, xl 1200, xxl 1400). No clamp(): sizes step at breakpoints.
 * Bootstrap is compiled CSS, so branding is applied by overriding its CSS variables.
 */

/* ==========================================================================
   Theme tokens, derived from the project brand values in css/brand.css. The
   type scale steps up at md and lg below.
   ========================================================================== */
:root {
  --font-size-xs: 0.75rem; /* 12px */
  --font-size-sm: 0.875rem; /* 14px */
  --font-size-base: 1rem; /* 16px */
  --font-size-h6: 1rem; /* 16px */
  --font-size-h5: 1.125rem; /* 18px */
  --font-size-h4: 1.25rem; /* 20 / 22 / 24px */
  --font-size-h3: 1.5rem; /* 24 / 28 / 32px */
  --font-size-h2: 1.875rem; /* 30 / 36 / 40px */
  --font-size-h1: 2.25rem; /* 36 / 44 / 52px */
  --font-size-display: 2.625rem; /* 42 / 52 / 64px */

  --line-height-body: 1.6;
  --line-height-heading: 1.25;
  --line-height-heading-tight: 1.15;

  /* Focus: one 1px line in the focus colour, which each surface sets (the accent on light surfaces, white on dark
     ones and over images); the colour does the work, not the size. Links and controls get a 1px outline 1px off
     their edge, so it shows against any fill; a field turns its own 1px border the focus colour. --focus-ring
     (SweetAlert's close button) is the same line as a shadow: a custom property resolves where it is declared, so
     every rule that changes --focus-color declares it again beside it. */
  --focus-color: var(--color-accent-strong);
  --focus-width: 1px;
  --focus-ring: 0 0 0 var(--focus-width) var(--focus-color);
  --eyebrow-color: var(--color-accent-strong);

  /* Vertical rhythm for page sections; Bootstrap spacers stop at 3rem */
  --section-y: 3rem;

  /* Motion: short, decelerating, no overshoot; opacity does most of the work and movement stays small.
     Reduced motion (below) shortens the fades and drops the movement. */
  --motion-fast: 160ms;
  --motion-standard: 240ms;
  --motion-ease: cubic-bezier(0.2, 0, 0, 1);
  --motion-shift: 0.5rem;

  /* Bootstrap: brand colours */
  --bs-primary: var(--color-primary);
  --bs-primary-rgb: var(--color-primary-rgb);
  --bs-secondary: var(--color-secondary);
  --bs-secondary-rgb: var(--color-secondary-rgb);
  --bs-success: var(--color-success);
  --bs-success-rgb: var(--color-success-rgb);
  --bs-warning: var(--color-warning);
  --bs-warning-rgb: var(--color-warning-rgb);
  --bs-danger: var(--color-danger);
  --bs-danger-rgb: var(--color-danger-rgb);
  --bs-light: var(--color-surface-muted);
  --bs-light-rgb: var(--color-surface-muted-rgb);
  --bs-dark: var(--color-primary);
  --bs-dark-rgb: var(--color-primary-rgb);

  /* Subtle backgrounds, borders and text for alerts, badges and list items: 12% / 35% tints of each
     colour; the -text-emphasis shades are at least 4.8:1 on their tint */
  --bs-primary-text-emphasis: var(--color-primary);
  --bs-primary-bg-subtle: var(--color-surface-muted);
  --bs-primary-border-subtle: var(--color-border);
  --bs-secondary-text-emphasis: var(--color-secondary);
  --bs-secondary-bg-subtle: color-mix(in srgb, var(--color-secondary) 12%, #fff);
  --bs-secondary-border-subtle: color-mix(in srgb, var(--color-secondary) 35%, #fff);
  --bs-success-text-emphasis: var(--color-success-strong);
  --bs-success-bg-subtle: color-mix(in srgb, var(--color-success) 12%, #fff);
  --bs-success-border-subtle: color-mix(in srgb, var(--color-success) 35%, #fff);
  --bs-warning-text-emphasis: var(--color-warning-strong);
  --bs-warning-bg-subtle: color-mix(in srgb, var(--color-warning) 12%, #fff);
  --bs-warning-border-subtle: color-mix(in srgb, var(--color-warning) 35%, #fff);
  --bs-danger-text-emphasis: var(--color-danger-strong);
  --bs-danger-bg-subtle: color-mix(in srgb, var(--color-danger) 12%, #fff);
  --bs-danger-border-subtle: color-mix(in srgb, var(--color-danger) 35%, #fff);
  --bs-light-text-emphasis: var(--color-text);
  --bs-light-bg-subtle: var(--color-background);
  --bs-light-border-subtle: var(--color-border);

  /* Bootstrap: text and surfaces. Components (cards, fields, dropdowns, modals) take --bs-body-bg,
     so it is the surface colour; the page itself is painted with the background colour on body below. */
  --bs-font-sans-serif: var(--font-body);
  --bs-body-font-size: var(--font-size-base);
  --bs-body-line-height: var(--line-height-body);
  --bs-body-color: var(--color-text);
  --bs-body-color-rgb: var(--color-text-rgb);
  --bs-body-bg: var(--color-surface);
  --bs-emphasis-color: var(--color-text);
  --bs-secondary-color: var(--color-text-muted);
  --bs-secondary-color-rgb: var(--color-text-muted-rgb);
  --bs-secondary-bg: var(--color-surface-muted);
  --bs-tertiary-bg: var(--color-surface-muted);
  --bs-tertiary-bg-rgb: var(--color-surface-muted-rgb);
  --bs-heading-color: var(--color-primary);

  --bs-link-color: var(--color-accent-strong);
  --bs-link-color-rgb: var(--color-accent-strong-rgb);
  --bs-link-hover-color: var(--color-secondary);
  --bs-link-hover-color-rgb: var(--color-secondary-rgb);

  --bs-border-color: var(--color-border);
  --bs-border-radius-sm: var(--radius-sm);
  --bs-border-radius: var(--radius);
  --bs-border-radius-lg: var(--radius-lg);
  --bs-border-radius-xl: var(--radius-xl);
  --bs-border-radius-pill: var(--radius-pill);

  /* Elevation is opt-in (.shadow, .shadow-sm) and tinted with the secondary colour. No component has a
     shadow of its own: surfaces are told apart by a hairline border or a background. */
  --bs-box-shadow: 0 0.625rem 1.875rem rgba(var(--color-secondary-rgb), 0.08);
  --bs-box-shadow-sm: 0 0.125rem 0.375rem rgba(var(--color-secondary-rgb), 0.08);

  --bs-focus-ring-color: rgba(var(--color-accent-rgb), 0.35);
  --bs-form-valid-color: var(--color-success-strong);
  --bs-form-valid-border-color: var(--color-success);
  --bs-form-invalid-color: var(--color-danger);
  --bs-form-invalid-border-color: var(--color-danger);
}

@media (min-width: 768px) {
  :root {
    --font-size-h4: 1.375rem;
    --font-size-h3: 1.75rem;
    --font-size-h2: 2.25rem;
    --font-size-h1: 2.75rem;
    --font-size-display: 3.25rem;
    --section-y: 4rem;
  }
}

@media (min-width: 992px) {
  :root {
    --font-size-h4: 1.5rem;
    --font-size-h3: 2rem;
    --font-size-h2: 2.5rem;
    --font-size-h1: 3.25rem;
    --font-size-display: 4rem;
    --section-y: 5rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-fast: 80ms;
    --motion-standard: 80ms;
    --motion-shift: 0px;
  }
}

body {
  background-color: var(--color-background);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Surfaces. Cards come first so .bg-* surfaces below can recolour them; a plain white card
   restores the light-surface colours when placed inside a dark section. */
.card {
  --bs-card-border-color: var(--bs-border-color);
  --bs-card-title-color: var(--bs-heading-color);
  --bs-card-border-radius: var(--bs-border-radius-lg);
  --bs-card-inner-border-radius: calc(var(--bs-border-radius-lg) - var(--bs-border-width));
  --bs-card-spacer-y: 1.5rem;
  --bs-card-spacer-x: 1.5rem;
  --bs-card-cap-bg: var(--color-surface-muted);
  --bs-heading-color: var(--color-primary);
  --bs-secondary-color: var(--color-text-muted);
  --bs-link-color-rgb: var(--color-accent-strong-rgb);
  --bs-link-hover-color-rgb: var(--color-secondary-rgb);
  --focus-color: var(--color-accent-strong);
  --focus-ring: 0 0 0 var(--focus-width) var(--focus-color);
  --eyebrow-color: var(--color-accent-strong);
}

@media (min-width: 992px) {
  .card {
    --bs-card-spacer-y: 1.75rem;
    --bs-card-spacer-x: 1.75rem;
  }
}

/* Dark surfaces: white headings and links, muted inverse supporting text (.text-body-secondary).
   Pair .bg-dark with .text-white; .bg-overlay sets its own text colour. */
.bg-dark,
.bg-overlay {
  --bs-heading-color: var(--color-text-inverse);
  --subtitle-color: var(--color-text-inverse-muted);
  --bs-secondary-color: var(--color-text-inverse-muted);
  --bs-link-color-rgb: 255, 255, 255;
  --bs-link-hover-color-rgb: 255, 255, 255;
  --focus-color: var(--color-text-inverse);
  --focus-ring: 0 0 0 var(--focus-width) var(--focus-color);
  --eyebrow-color: var(--color-accent-on-dark);
  --bs-danger-rgb: var(--color-danger-on-dark-rgb);
  --bs-form-invalid-color: var(--color-danger-on-dark);
  --bs-form-invalid-border-color: var(--color-danger-on-dark);
}

/* Fields on a dark surface (the footer's newsletter): clear, with a light edge at 4.3:1 and white text; a ticked
   box takes the accent, which the white tick reads on at 4.3:1 */
.bg-dark :is(.form-control, .form-check-input),
.bg-dark .form-control:focus {
  color: var(--color-text-inverse);
  background-color: transparent;
}

.bg-dark :is(.form-control, .form-check-input) {
  border-color: rgba(var(--bs-white-rgb), 0.45);
}

.bg-dark :is(.form-control, .form-check-input):focus {
  border-color: var(--focus-color);
}

.bg-dark .form-check-input:checked {
  background-color: var(--color-accent);
  border-color: var(--color-accent);
}

.bg-dark .form-control.wpcf7-not-valid {
  border-color: var(--bs-form-invalid-border-color);
}

.bg-dark .wpcf7-spinner {
  background-color: var(--color-text-inverse);
}

/* On a dark surface the primary button turns light, so it stands out where the primary colour is itself dark */
:is(.bg-dark, .bg-overlay) .btn-primary {
  --bs-btn-color: var(--color-primary);
  --bs-btn-bg: var(--color-surface);
  --bs-btn-border-color: var(--color-surface);
  --bs-btn-hover-color: var(--color-primary);
  --bs-btn-hover-bg: var(--color-background);
  --bs-btn-hover-border-color: var(--color-background);
  --bs-btn-active-color: var(--color-primary);
  --bs-btn-active-bg: var(--color-surface-muted);
  --bs-btn-active-border-color: var(--color-surface-muted);
  --bs-btn-disabled-color: var(--color-primary);
  --bs-btn-disabled-bg: var(--color-surface);
  --bs-btn-disabled-border-color: var(--color-surface);
}

/* Dark band with an optional photo, e.g. page heroes and selective feature sections.
   Set the image with style="--bg-image: url(...)". The overlay is solid where text spans
   the full width, and fades to the right from lg where text sits in the left 2/3. */
.bg-overlay {
  background-color: var(--color-primary);
  background-image:
    linear-gradient(rgba(var(--bs-dark-rgb), 0.85), rgba(var(--bs-dark-rgb), 0.85)),
    var(--bg-image, none);
  background-position: center;
  background-size: cover;
  color: var(--color-text-inverse);
}

@media (min-width: 992px) {
  .bg-overlay {
    background-image:
      linear-gradient(
        90deg,
        rgba(var(--bs-dark-rgb), 0.94) 0%,
        rgba(var(--bs-dark-rgb), 0.85) 45%,
        rgba(var(--bs-dark-rgb), 0.55) 100%
      ),
      var(--bg-image, none);
  }
}

/* Light alternative to .bg-overlay (editor choice on page heroes), with light-surface text.
   At least 0.92 wherever text sits keeps links above 4.5:1 even over black image areas; supporting
   text (e.g. the breadcrumb's current page) uses the body colour, as grey would drop below AA. */
.bg-overlay-light {
  --bs-secondary-color: var(--color-text);
  --subtitle-color: var(--color-secondary);
  background-color: var(--color-background);
  background-image:
    linear-gradient(
      rgba(var(--color-background-rgb), 0.92),
      rgba(var(--color-background-rgb), 0.92)
    ),
    var(--bg-image, none);
  background-position: center;
  background-size: cover;
}

@media (min-width: 992px) {
  .bg-overlay-light {
    background-image:
      linear-gradient(
        90deg,
        rgba(var(--color-background-rgb), 0.96) 0%,
        rgba(var(--color-background-rgb), 0.92) 67%,
        rgba(var(--color-background-rgb), 0.6) 100%
      ),
      var(--bg-image, none);
  }
}

/* Hero (template-parts/sections/hero.php) on the dark .bg-dark surface. The standard overlay is flat, so left,
   centred and right-aligned text all get the same contrast: white text stays above 4.5:1 even over
   pure white image areas. Landing and event heroes replace it with a fade under the text (below). */
.hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background-color: rgba(var(--bs-dark-rgb), 0.68);
}

/* Content sets the height on phones */
@media (min-width: 768px) {
  .hero-body {
    min-height: 30rem;
  }
}

@media (min-width: 992px) {
  .hero-body {
    min-height: 34.5rem;
  }
}

/* Front page hero (landing arg): fills the screen at every width, below the sticky header and admin bar (or
   from the very top, under a clear header: .has-overlay-header), with its text at the foot of the image.
   --header-height is the header's rendered height: js/main.js measures it, and the Header section below has the
   fallback values. */
.hero-landing .hero-body {
  min-height: calc(100vh - var(--header-height) - var(--wp-admin--admin-bar--height, 0px));
  min-height: calc(100svh - var(--header-height) - var(--wp-admin--admin-bar--height, 0px));
}

.has-overlay-header .hero-landing .hero-body {
  min-height: calc(100vh - var(--wp-admin--admin-bar--height, 0px));
  min-height: calc(100svh - var(--wp-admin--admin-bar--height, 0px));
}

/* Event page (single-ydp_event.php): the event's image with its title and essentials at the foot. Taller than
   the standard hero, so the image has room above the text. */
.hero-event .hero-body {
  min-height: 26rem;
}

@media (min-width: 768px) {
  .hero-event .hero-body {
    min-height: 36rem;
  }
}

@media (min-width: 992px) {
  .hero-event .hero-body {
    min-height: max(38rem, 72vh);
  }
}

/* Landing and event heroes show the image itself: no flat overlay. Instead a dark fade belongs to the text
   block (.hero-text, at the foot of the image): it starts clear a little above the first line, is at full strength
   by that line and stays so to the bottom edge, across the whole width. However many lines the text runs to, on a
   phone or a desktop, it sits on the dark part: white text and its muted companion keep 4.5:1 there even over
   white image areas. The hero clips the fade, which reaches past it on every side but the top. */
.hero-landing,
.hero-event {
  overflow: hidden;
}

.hero-landing .hero-media::after,
.hero-event .hero-media::after {
  background-color: transparent;
}

.hero-landing .hero-text,
.hero-event .hero-text {
  --hero-fade: 7rem;
  position: relative;
  isolation: isolate;
}

.hero-landing .hero-text::before,
.hero-event .hero-text::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: calc(-1 * var(--hero-fade)) -100vw -100vh;
  background-image: linear-gradient(
    to bottom,
    rgba(var(--bs-dark-rgb), 0) 0,
    rgba(var(--bs-dark-rgb), 0.82) var(--hero-fade),
    rgba(var(--bs-dark-rgb), 0.9) 100%
  );
}

@media (min-width: 768px) {
  .hero-landing .hero-text,
  .hero-event .hero-text {
    --hero-fade: 10rem;
  }
}

/* Under a clear header the top of the image is darkened the same way, behind the logo and the buttons */
.has-overlay-header .hero-landing .hero-media::after,
.has-overlay-header .hero-event .hero-media::after {
  background-image: linear-gradient(
    to bottom,
    rgba(var(--bs-dark-rgb), 0.7) 0,
    rgba(var(--bs-dark-rgb), 0.7) var(--header-height),
    rgba(var(--bs-dark-rgb), 0) calc(var(--header-height) + 8rem)
  );
}

/* Slider: room for the indicators under the text, which sit at the bottom of the section padding */
.hero.carousel .hero-body {
  padding-bottom: calc(var(--section-y) + 3rem);
}

.hero .carousel-indicators {
  justify-content: flex-start;
  margin-inline: auto;
  margin-bottom: calc(var(--section-y) - 0.5rem);
  /* The first dot lines up with the text; its tap target reaches 0.5rem into the gutter */
  padding-inline: calc(var(--bs-gutter-x) * 0.5 - 0.5rem);
}

/* Dots with an accent pill for the active slide, on 24px tap targets */
.hero .carousel-indicators [data-bs-target] {
  position: relative;
  width: 1.5rem;
  height: 1.5rem;
  margin: 0;
  border: 0;
  background: none;
  opacity: 1;
}

.hero .carousel-indicators [data-bs-target]::after {
  content: "";
  position: absolute;
  inset: 0.5rem;
  border-radius: var(--bs-border-radius-pill);
  background-color: rgba(var(--bs-white-rgb), 0.5);
}

.hero .carousel-indicators .active {
  width: 2.5rem;
}

.hero .carousel-indicators .active::after {
  background-color: var(--color-accent);
}

/* ==========================================================================
   Typography: Bricolage Grotesque headings, Montserrat body. Sizes come from the tokens above,
   so templates use h1–h6 / .h1–.h6 / .display-1 / .small, never inline sizes.
   ========================================================================== */
/* Links are never underlined. A link in text is told from the text around it by its colour and a medium
   weight together, so it does not rest on colour alone; hover and focus change the colour and show the ring.
   Zero specificity (:where), so buttons, menu links and headings keep their own weight. */
a {
  text-decoration: none;
}

:where(p, li, dd, td, address, figcaption, .form-text, .entry-content) > a,
a:where(:not([class])) {
  font-weight: 500;
}

:focus-visible {
  outline: var(--focus-width) solid var(--focus-color);
  outline-offset: 1px;
}

h1,
.h1,
h2,
.h2,
h3,
.h3,
h4,
.h4,
h5,
.h5,
h6,
.h6,
.display-1 {
  font-family: var(--font-heading);
  font-weight: var(--font-weight-heading);
  line-height: var(--line-height-heading);
}

h1,
.h1,
h2,
.h2,
.display-1 {
  font-weight: var(--font-weight-heading-strong);
  line-height: var(--line-height-heading-tight);
  letter-spacing: -0.01em;
}

.display-1 {
  font-size: var(--font-size-display);
}

h1,
.h1 {
  font-size: var(--font-size-h1);
}

h2,
.h2 {
  font-size: var(--font-size-h2);
}

h3,
.h3 {
  font-size: var(--font-size-h3);
}

h4,
.h4 {
  font-size: var(--font-size-h4);
}

h5,
.h5 {
  font-size: var(--font-size-h5);
}

h6,
.h6 {
  font-size: var(--font-size-h6);
}

.lead {
  font-size: var(--font-size-h5);
  font-weight: 400;
  line-height: var(--line-height-body);
}

small,
.small {
  font-size: var(--font-size-sm);
}

/* Hero subheading / page hero subtitle: muted inverse on dark, secondary on .bg-overlay-light, the muted
   text colour elsewhere */
.subtitle {
  color: var(--subtitle-color, var(--bs-secondary-color));
}

/* Headings and titles take the heading face. A line set at a heading size that carries text or data (the
   subtitle above, an order's total) keeps the body face, like every other date, venue and price. */
.subtitle,
.order-total {
  font-family: var(--font-body);
}

/* Section label, e.g. "Upcoming events" */
.eyebrow {
  display: block;
  margin-bottom: 0.5rem;
  color: var(--eyebrow-color);
  font-size: var(--font-size-sm);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Separator between the items on one meta line (ydt_meta_separator()): a small square, in keeping with the
   near-square geometry, half as strong as the text around it */
.meta-sep {
  display: inline-block;
  width: 0.25em;
  height: 0.25em;
  margin-inline: 0.625em;
  vertical-align: 0.22em;
  background-color: currentColor;
  opacity: 0.5;
}

/* Front page hero heading (landing arg) uses the display size */
.hero-landing :is(h1, .h1) {
  font-size: var(--font-size-display);
}

/* ==========================================================================
   Layout
   ========================================================================== */
.section {
  padding-block: var(--section-y);
}

/* 20px side padding on phones, where Bootstrap's 12px crowds the screen edge. From sm the container's
   max-width already leaves 28px or more, so the default returns. Rows set their own gutter, so only the
   container edge changes. */
.container {
  --bs-gutter-x: 2.5rem;
}

@media (min-width: 576px) {
  .container {
    --bs-gutter-x: 1.5rem;
  }
}

/* Full-width bands (.container-fluid: the centred header, headings above an edge-to-edge grid) keep the same
   20px edge on phones, and step out as the screen widens */
.container-fluid {
  --bs-gutter-x: 2.5rem;
}

@media (min-width: 768px) {
  .container-fluid {
    --bs-gutter-x: 4rem;
  }
}

@media (min-width: 1200px) {
  .container-fluid {
    --bs-gutter-x: 6rem;
  }
}

/* Page header (template-parts/sections/page-header.php): breadcrumb, title and intro at the top of a page.
   The plain one sits on the page background with no band or rule of its own, so the title and the content
   read as one column: it keeps less space below, and the section after it gives up its top padding. */
.page-header {
  padding-block: 2.5rem;
}

.page-header-plain {
  padding-bottom: 2rem;
}

.page-header-plain + .section {
  padding-top: 0;
}

@media (min-width: 768px) {
  .page-header {
    padding-block: 3.5rem;
  }

  .page-header-plain {
    padding-bottom: 2.5rem;
  }
}

@media (min-width: 992px) {
  .page-header {
    padding-block: 4.5rem;
  }

  .page-header-plain {
    padding-bottom: 3rem;
  }
}

/* ==========================================================================
   Buttons: primary, secondary, outline, link. 12px / 20px padding
   gives 50px tall buttons (54px for .btn-lg), comfortable touch targets. The system
   has no .btn-sm; this rule loads after Bootstrap and would override its padding.
   ========================================================================== */
.btn {
  --bs-btn-padding-y: 0.75rem;
  --bs-btn-padding-x: 1.25rem;
  --bs-btn-font-weight: 600;
  --bs-btn-focus-box-shadow: none;
  --bs-btn-disabled-opacity: 0.55;
}

.btn-primary {
  --bs-btn-color: var(--color-text-inverse);
  --bs-btn-bg: var(--color-primary);
  --bs-btn-border-color: var(--color-primary);
  --bs-btn-hover-color: var(--color-text-inverse);
  --bs-btn-hover-bg: var(--color-primary-hover);
  --bs-btn-hover-border-color: var(--color-primary-hover);
  --bs-btn-active-color: var(--color-text-inverse);
  --bs-btn-active-bg: var(--color-primary-hover);
  --bs-btn-active-border-color: var(--color-primary-hover);
  --bs-btn-disabled-color: var(--color-text-inverse);
  --bs-btn-disabled-bg: var(--color-primary);
  --bs-btn-disabled-border-color: var(--color-primary);
}

.btn-secondary {
  --bs-btn-color: var(--color-text-inverse);
  --bs-btn-bg: var(--color-secondary);
  --bs-btn-border-color: var(--color-secondary);
  --bs-btn-hover-color: var(--color-text-inverse);
  --bs-btn-hover-bg: var(--color-primary);
  --bs-btn-hover-border-color: var(--color-primary);
  --bs-btn-active-color: var(--color-text-inverse);
  --bs-btn-active-bg: var(--color-primary);
  --bs-btn-active-border-color: var(--color-primary);
  --bs-btn-disabled-color: var(--color-text-inverse);
  --bs-btn-disabled-bg: var(--color-secondary);
  --bs-btn-disabled-border-color: var(--color-secondary);
}

/* Page-level calls to action; text stays 16px */
.btn-lg {
  --bs-btn-padding-y: 0.875rem;
  --bs-btn-padding-x: 1.5rem;
  --bs-btn-font-size: 1rem;
  --bs-btn-border-radius: var(--bs-border-radius);
}

.btn-outline-primary {
  --bs-btn-color: var(--color-primary);
  --bs-btn-bg: var(--color-surface);
  --bs-btn-border-color: var(--color-primary);
  --bs-btn-hover-color: var(--color-text-inverse);
  --bs-btn-hover-bg: var(--color-primary);
  --bs-btn-hover-border-color: var(--color-primary);
  --bs-btn-active-color: var(--color-text-inverse);
  --bs-btn-active-bg: var(--color-primary);
  --bs-btn-active-border-color: var(--color-primary);
  --bs-btn-disabled-color: var(--color-primary);
  --bs-btn-disabled-bg: transparent;
  --bs-btn-disabled-border-color: var(--color-primary);
}

/* White outline button for dark surfaces and hero media, next to .btn-primary */
.btn-outline-light {
  --bs-btn-color: var(--color-text-inverse);
  --bs-btn-border-color: var(--color-text-inverse);
  --bs-btn-hover-color: var(--color-primary);
  --bs-btn-hover-bg: var(--color-surface);
  --bs-btn-hover-border-color: var(--color-surface);
  --bs-btn-active-color: var(--color-primary);
  --bs-btn-active-bg: var(--color-background);
  --bs-btn-active-border-color: var(--color-background);
  --bs-btn-disabled-color: var(--color-text-inverse);
  --bs-btn-disabled-border-color: var(--color-text-inverse);
}

/* Text button: an action that should read as a link (e.g. "Change tickets") */
.btn-link {
  --bs-btn-color: var(--bs-link-color);
  --bs-btn-hover-color: var(--bs-link-hover-color);
  --bs-btn-active-color: var(--bs-link-hover-color);
  --bs-btn-disabled-color: var(--color-text-muted);
  text-decoration: none;
}

/* ==========================================================================
   Components whose active/focus colours Bootstrap hard-codes
   ========================================================================== */
.nav,
.navbar-nav {
  --bs-nav-link-font-weight: 500;
  --bs-nav-link-color: var(--color-primary);
  --bs-nav-link-hover-color: var(--color-accent-strong);
  --bs-nav-pills-link-active-bg: var(--color-primary);
}

/* Bootstrap draws its own focus shadow on these and removes the outline: the theme's outline instead */
.btn:focus-visible,
.nav-link:focus-visible {
  outline: var(--focus-width) solid var(--focus-color);
  outline-offset: 1px;
  box-shadow: none;
}

.dropdown-menu {
  --bs-dropdown-border-color: var(--color-border);
  --bs-dropdown-link-hover-bg: var(--color-surface-muted);
  --bs-dropdown-link-active-bg: var(--color-primary);
}

/* No ring on click; keyboard focus keeps the brand ring (.page-link:focus-visible below) */
.pagination {
  --bs-pagination-color: var(--color-primary);
  --bs-pagination-hover-color: var(--color-primary);
  --bs-pagination-hover-bg: var(--color-surface-muted);
  --bs-pagination-active-bg: var(--color-primary);
  --bs-pagination-active-border-color: var(--color-primary);
  --bs-pagination-disabled-color: var(--color-text-muted);
  --bs-pagination-focus-box-shadow: none;
  /* ~46px tap targets */
  --bs-pagination-padding-x: 1rem;
  --bs-pagination-padding-y: 0.625rem;
}

.page-link:focus-visible {
  outline: var(--focus-width) solid var(--focus-color);
  outline-offset: 1px;
  box-shadow: none;
}

/* Meta size (14px); .small alone loses to Bootstrap's var(--bs-breadcrumb-font-size). The divider is a small
   Bootstrap Icons chevron (chevron-right) in the muted colour, centred on the text and silent to screen readers. */
.breadcrumb {
  --bs-breadcrumb-font-size: var(--font-size-sm);
  --bs-breadcrumb-item-padding-x: 0.625rem;
  --bs-breadcrumb-divider-color: var(--bs-secondary-color);
}

.breadcrumb-item + .breadcrumb-item::before {
  float: none;
  display: inline-block;
  vertical-align: 0.125em;
  font-family: "bootstrap-icons";
  font-size: 0.625rem;
  line-height: 1;
  content: "\f285";
  content: "\f285" / "";
}

/* A long current page (e.g. an event title, shown in full in the h1 below) is shortened with an ellipsis
   instead of wrapping onto a line under its separator; parents never shorten, and the item only moves to a
   new line when less than 6rem is left */
.breadcrumb-item.active {
  flex: 1 1 0;
  min-width: 6rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.list-group {
  --bs-list-group-active-bg: var(--color-primary);
  --bs-list-group-active-border-color: var(--color-primary);
}

/* Status and label badges (template-parts/components/status-badge.php). 12px semibold, with room for
   an icon so status never relies on colour alone. Near-square like the rest of the UI (the default radius),
   with no border: the tinted surface, icon and small size keep a status from reading as a button or a field. */
.badge {
  --bs-badge-font-size: var(--font-size-xs);
  --bs-badge-font-weight: 600;
  --bs-badge-padding-y: 0.375em;
  --bs-badge-padding-x: 0.75em;
  --bs-badge-border-radius: var(--bs-border-radius);
  letter-spacing: 0.01em;
}

/* Amber at the alerts' 12% all but vanishes on the warm page background; 20% sets the badge apart as much as
   the other tones, and its text stays at 4.7:1 */
.badge.bg-warning-subtle {
  background-color: color-mix(in srgb, var(--color-warning) 20%, #fff) !important;
}

/* Alerts: Bootstrap's subtle alerts, taking the palette through the -subtle / -text-emphasis variables */
.alert {
  --bs-alert-padding-y: 1rem;
  --bs-alert-padding-x: 1.25rem;
}

.alert > :last-child {
  margin-bottom: 0;
}

/* An error summary or payment error takes focus only so a screen reader reads it out (tabindex="-1"): it is not a
   control, so it shows no focus line */
:is(.alert, [role="alert"]):focus-visible {
  outline: 0;
}

/* Dialogs (SweetAlert2, registered as 'ydt-sweetalert2'; buttons come from the ydtSwal mixin in functions.php).
   Its variables are set on body, which beats the library's :root values whatever order the stylesheets load in. */
body {
  --swal2-background: var(--color-surface);
  --swal2-color: var(--color-text);
  --swal2-border-radius: var(--radius-xl);
  --swal2-backdrop: rgba(var(--color-primary-rgb), 0.5);
  --swal2-outline: var(--focus-ring);
  --swal2-close-button-color: var(--color-text-muted);
  --swal2-close-button-focus-box-shadow: var(--focus-ring);
  --swal2-input-border: var(--bs-border-width) solid var(--color-border-strong);
  --swal2-input-border-radius: var(--radius);
  --swal2-input-focus-border: var(--bs-border-width) solid var(--focus-color);
  --swal2-input-focus-box-shadow: none;
  --swal2-footer-border-color: var(--color-border);
}

.swal2-title {
  color: var(--bs-heading-color);
  font-family: var(--font-heading);
  font-size: var(--font-size-h4);
  font-weight: var(--font-weight-heading);
  line-height: var(--line-height-heading);
}

/* Icons in the status colours; the dialog's title and text still carry the meaning */
.swal2-icon.swal2-warning {
  border-color: var(--color-warning);
  color: var(--color-warning);
}

.swal2-icon.swal2-error {
  border-color: var(--color-danger);
}

.swal2-icon.swal2-error [class^="swal2-x-mark-line"] {
  background-color: var(--color-danger);
}

.swal2-icon.swal2-success {
  border-color: var(--color-success);
  color: var(--color-success);
}

.swal2-icon.swal2-success .swal2-success-ring {
  border-color: rgba(var(--color-success-rgb), 0.3);
}

.swal2-icon.swal2-success [class^="swal2-success-line"] {
  background-color: var(--color-success);
}

.swal2-icon:is(.swal2-info, .swal2-question) {
  border-color: var(--color-secondary);
  color: var(--color-secondary);
}

/* Important notice or deadline, not for ordinary paragraphs */
.callout {
  --bs-link-color-rgb: var(--color-accent-strong-rgb);
  --bs-link-hover-color-rgb: var(--color-secondary-rgb);
  padding: 1.5rem;
  background-color: var(--color-surface-muted);
  border-left: 4px solid var(--color-accent);
  border-radius: var(--bs-border-radius);
}

.callout > :last-child {
  margin-bottom: 0;
}

/* Done and well (e.g. an order confirmed): the success colour, kept pale */
.callout-success {
  --bs-heading-color: var(--bs-success-text-emphasis);
  background-color: var(--bs-success-bg-subtle);
  border-left-color: var(--bs-success);
}

/* Closed or expired notice (e.g. ticket sales closed): the danger colour, kept pale so it
   doesn't read as an error */
.callout-closed {
  --bs-heading-color: var(--bs-danger-text-emphasis);
  background-color: var(--bs-danger-bg-subtle);
  border-left-color: var(--bs-danger);
}

/* ==========================================================================
   Tickets: the wallet notice, ticket card and QR panel
   (template-parts/components/ticket-card.php, qr-panel.php).
   ========================================================================== */
.ticket-notice > .bi {
  font-size: 1.5rem;
  line-height: 1;
  color: var(--color-accent-strong);
}

.ticket-card.ticket-card-void {
  --bs-card-border-color: var(--bs-danger-border-subtle);
}

/* A ticket is one object: a surface with an edge of its own, so tickets side by side never run together. */
.ticket-card {
  --bs-card-border-color: var(--color-border-strong);
}

/* 240px at most: large enough to scan at arm's length, small enough for two per row on a tablet. The SVG
   carries its own white background and quiet zone, so it scans on any page colour; nothing is drawn
   over or around it. */
.qr-panel-image {
  display: block;
  width: 100%;
  max-width: 15rem;
  height: auto;
  margin-inline: auto;
}

/* A used ticket keeps its QR for reference, faded so it doesn't look ready to scan; the text says why */
.qr-panel-dimmed .qr-panel-image {
  opacity: 0.25;
  filter: grayscale(1);
}

/* Read aloud or typed in at the door: spaced so similar characters stay distinct */
.qr-panel-code {
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}

/* Countdown (template-parts/components/countdown.php): four equal cells, figures that don't shift as they tick */
.countdown-cells {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.5rem;
}

.countdown-value {
  font-variant-numeric: tabular-nums;
}

/* The wallet's tickets on a phone: one row to swipe, a ticket at a time, the next one showing at the edge so it's
   clear there are more. Snapping stops each swipe on a whole ticket. From md, a grid again. */
.ticket-slider .ticket-grid {
  position: relative;
  flex-wrap: nowrap;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}

.ticket-slider .ticket-grid::-webkit-scrollbar {
  display: none;
}

.ticket-slider .ticket-grid > .col {
  flex: 0 0 auto;
  width: 88%;
  scroll-snap-align: center;
}

.ticket-slider .ticket-grid > .col:only-child {
  width: 100%;
}

/* Shown by js/main.js once it has taken over the buttons */
.ticket-slider-controls {
  display: none;
}

.ticket-slider.is-ready .ticket-slider-controls {
  display: flex;
}

@media (min-width: 768px) {
  .ticket-slider .ticket-grid {
    flex-wrap: wrap;
    overflow-x: visible;
    scroll-snap-type: none;
  }

  .ticket-slider .ticket-grid > .col {
    width: 50%;
  }

  .ticket-slider.is-ready .ticket-slider-controls {
    display: none;
  }
}

/* Tickets are shown on a phone only: a printed page carries no QR code. */
@media print {
  .qr-panel-image {
    display: none !important;
  }
}

/* ==========================================================================
   Forms: Bootstrap markup (.form-label, .form-control, .form-select, .form-check,
   .form-text, .invalid-feedback). Fields are 46px tall; field edges use the
   strong border for 3:1 contrast; focus shows the two-tone brand ring.
   Loads after Bootstrap, so it would override .form-control-sm/-lg, which the
   system doesn't use.
   ========================================================================== */
.form-label {
  margin-bottom: 0.375rem;
  font-weight: 600;
}

.form-control,
.form-select,
.form-check-input {
  border-color: var(--color-border-strong);
}

.form-control {
  padding: 0.625rem 0.875rem;
}

.form-select {
  padding: 0.625rem 2.5rem 0.625rem 0.875rem;
  background-position: right 0.875rem center;
}

.form-control::placeholder {
  color: var(--color-text-muted);
}

.form-control:focus,
.form-select:focus,
.form-check-input:focus {
  border-color: var(--focus-color);
  box-shadow: none;
}

.form-control:disabled,
.form-select:disabled {
  color: var(--color-text-muted);
  border-color: var(--color-border);
}

/* Larger boxes than Bootstrap's 1em; the label is part of the target, so the whole row is tappable */
.form-check {
  min-height: 1.75rem;
  padding-left: 2rem;
}

.form-check .form-check-input {
  width: 1.25rem;
  height: 1.25rem;
  margin-top: 0.1875rem;
  margin-left: -2rem;
}

/* Bootstrap hard-codes 0.25em here; checkboxes follow the radius scale like every other field */
.form-check-input[type="checkbox"] {
  border-radius: var(--bs-border-radius-sm);
}

.form-check-input:checked,
.form-check-input[type="checkbox"]:indeterminate {
  background-color: var(--color-primary);
  border-color: var(--color-primary);
}

.form-text {
  margin-top: 0.375rem;
  font-size: var(--font-size-sm);
}

.invalid-feedback,
.valid-feedback {
  font-size: var(--font-size-sm);
  font-weight: 500;
}

/* A field in error keeps its error colour when focused */
.form-control.is-invalid:focus,
.form-select.is-invalid:focus {
  border-color: var(--bs-form-invalid-border-color);
  box-shadow: none;
}

/* Contact Form 7: fields get Bootstrap classes in the form template (class:form-control); CF7's
   hard-coded feedback colours are swapped for Bootstrap's invalid-feedback and alert colours */
.wpcf7-not-valid-tip {
  margin-top: 0.25rem;
  color: var(--bs-form-invalid-color);
  font-size: 0.875em;
}

.form-control.wpcf7-not-valid {
  border-color: var(--bs-form-invalid-border-color);
}

.wpcf7 form .wpcf7-response-output {
  margin: 1.5rem 0 0;
  padding: 1rem;
  color: var(--bs-primary-text-emphasis);
  background-color: var(--bs-primary-bg-subtle);
  border: var(--bs-border-width) solid var(--bs-primary-border-subtle);
  border-radius: var(--bs-border-radius);
  font-size: var(--font-size-sm);
}

.wpcf7 form.sent .wpcf7-response-output {
  color: var(--bs-success-text-emphasis);
  background-color: var(--bs-success-bg-subtle);
  border-color: var(--bs-success-border-subtle);
}

.wpcf7 form.invalid .wpcf7-response-output,
.wpcf7 form.unaccepted .wpcf7-response-output {
  color: var(--bs-warning-text-emphasis);
  background-color: var(--bs-warning-bg-subtle);
  border-color: var(--bs-warning-border-subtle);
}

.wpcf7 form.failed .wpcf7-response-output,
.wpcf7 form.aborted .wpcf7-response-output,
.wpcf7 form.spam .wpcf7-response-output {
  color: var(--bs-danger-text-emphasis);
  background-color: var(--bs-danger-bg-subtle);
  border-color: var(--bs-danger-border-subtle);
}

.wpcf7-spinner {
  background-color: var(--color-primary);
}

/* Checkbox, radio and acceptance items carry .form-check (ydt_cf7_form_check_markup()): one per line, without
   CF7's inline spacing */
.wpcf7-list-item.form-check {
  display: block;
  margin: 0;
}

.wpcf7-list-item.form-check + .wpcf7-list-item.form-check {
  margin-top: 0.5rem;
}

/* The newsletter's form, quieter than a page form: small labels and consent wording (in the text colour, as
   things the visitor acts on), the same weights as the footer's other content */
.footer-newsletter :is(.form-label, .wpcf7-list-item-label) {
  font-size: var(--font-size-sm);
}

.footer-newsletter .form-label {
  font-weight: 500;
}

/* Phone fields (intl-tel-input, see js/main.js). The input keeps .form-control; the library sets its left
   padding to clear the flag and dial code. The library stylesheet loads before this file. */
.iti {
  --iti-border-color: var(--color-border-strong);
  --iti-hover-color: var(--color-surface-muted);
  --iti-icon-color: var(--color-text-muted);
  --iti-spacer-horizontal: 0.875rem;
}

.iti .iti__selected-country,
.iti .iti__selected-country-primary {
  border-radius: var(--bs-border-radius) 0 0 var(--bs-border-radius);
}

/* Country list: like .dropdown-menu */
.iti .iti__country-selector {
  color: var(--bs-body-color);
  border-radius: var(--bs-border-radius);
  box-shadow: none;
}

/* Rounded corners clip the list; not in the fullscreen picker, whose close button sits outside it */
.iti--inline-country-selector .iti__country-selector {
  overflow: hidden;
}

/* One message per field: the country-aware error replaces CF7's generic one */
.wpcf7-form-control-wrap:has(> .invalid-feedback) .wpcf7-not-valid-tip {
  display: none;
}

.iti .iti__search-input:focus-visible {
  outline-offset: -2px;
}

/* Detached list and the fullscreen picker (narrow screens) sit above the sticky header, Bootstrap modals
   and the WordPress admin bar (99999) */
.iti.iti--detached-country-selector {
  z-index: 100000;
}

/* Contact page map: a fixed, modest height so it doesn't dominate the page */
.contact-map {
  height: 20rem;
}

@media (min-width: 992px) {
  .contact-map {
    height: 24rem;
  }
}

/* Event tiles (event-card.php) in the edge-to-edge grid (event-grid.php): tall 4:5 images side by side with no
   gutter and a hairline between tiles. The caption lies on the image at its foot, over a dark fade of its own:
   clear a little above the first line, at full strength by that line and to the bottom edge, so the text reads
   on any photograph (white and muted text keep 4.5:1 there even over white image areas). A long title is cut
   at three lines, so the caption never climbs to the badge; the event page has it in full. The grid's last
   hairline on the right falls on the page edge. On hover the image moves in slightly. */
.tile-grid {
  overflow: hidden;
}

.tile-media {
  --bs-aspect-ratio: 125%;
}

/* The image and the caption share the tile's one grid cell, the caption at its foot. It is not positioned, so
   the title's stretched link still covers the whole tile. Its fade is its own background: the top padding is
   the clear-to-dark part. */
.tile {
  display: grid;
}

.tile > .tile-media,
.tile > .tile-caption {
  grid-area: 1 / 1;
}

.tile-caption {
  --tile-fade: 4rem;
  z-index: 1;
  align-self: end;
  padding-top: var(--tile-fade);
  background-image: linear-gradient(
    to bottom,
    rgba(var(--bs-dark-rgb), 0) 0,
    rgba(var(--bs-dark-rgb), 0.82) var(--tile-fade),
    rgba(var(--bs-dark-rgb), 0.9) 100%
  );
}

.tile-title {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
}

/* Clamping clips the link's own focus ring; the title shows it instead */
.tile-title:has(a:focus-visible) {
  outline: var(--focus-width) solid var(--focus-color);
  outline-offset: 1px;
}

.tile-title a:focus-visible {
  outline: 0;
}

.tile-media img {
  transition: transform 0.6s ease;
}

.tile:hover .tile-media img {
  transform: scale(1.03);
}

@media (prefers-reduced-motion: reduce) {
  .tile-media img {
    transition: none;
  }

  .tile:hover .tile-media img {
    transform: none;
  }
}

/* Heading band above an edge-to-edge grid: generous space above, less below, so the heading belongs to the grid */
.section-heading-band {
  padding-top: var(--section-y);
  padding-bottom: 1.5rem;
}

@media (min-width: 768px) {
  .section-heading-band {
    padding-bottom: 2.5rem;
  }
}

/* News cards and event tiles (news-card.php, event-card.php): an accent mark when there is no featured image */
.news-placeholder-icon,
.card-placeholder-icon {
  color: var(--color-accent);
  font-size: 2.5rem;
}

/* Lead story image: 16:9 above the text below lg, filling the card's height beside it from lg */
.news-lead-media {
  aspect-ratio: 16 / 9;
}

@media (min-width: 992px) {
  .news-lead-media {
    aspect-ratio: auto;
    height: 100%;
    min-height: 22rem;
  }
}

/* Editor content (pages, news articles): images and tables stay within the reading column; wide tables scroll */
.entry-content img {
  max-width: 100%;
  height: auto;
}

.entry-content table {
  display: block;
  overflow-x: auto;
  margin-bottom: 1rem;
  border-collapse: collapse;
}

.entry-content :is(th, td) {
  padding: 0.5rem 0.75rem;
  border: var(--bs-border-width) solid var(--bs-border-color);
}

.entry-content > :last-child {
  margin-bottom: 0;
}

/* List items of editor content get room between them, so long items read as separate points */
.entry-content li + li {
  margin-top: 0.5rem;
}

/* The terms to read before agreeing (terms-acceptance.php): a chevron at the row's end instead of the browser's
   triangle, turned while open. No outline: keyboard focus shows as the link colour. */
.terms-toggle {
  min-height: 44px;
  list-style: none;
  cursor: pointer;
}

.terms-toggle::-webkit-details-marker {
  display: none;
}

.terms-toggle:focus-visible {
  outline: 0;
  color: var(--bs-link-color);
}

.terms-toggle-icon {
  transition: transform var(--motion-standard) var(--motion-ease);
}

details[open] > .terms-toggle .terms-toggle-icon {
  transform: rotate(180deg);
}

/* Classic-editor galleries ([gallery], functions.php): square tiles, two across on phones, then the number of
   columns chosen in the editor. Each image opens the lightbox below. */
.gallery {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.5rem;
  margin-bottom: 1rem;
}

.gallery-columns-1 {
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 768px) {
  .gallery-columns-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .gallery-columns-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .gallery-columns-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .gallery-columns-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .gallery-columns-7 { grid-template-columns: repeat(7, minmax(0, 1fr)); }
  .gallery-columns-8 { grid-template-columns: repeat(8, minmax(0, 1fr)); }
  .gallery-columns-9 { grid-template-columns: repeat(9, minmax(0, 1fr)); }
}

.gallery-item {
  margin: 0;
}

.gallery-icon a {
  display: block;
  cursor: zoom-in;
}

.gallery-icon img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--bs-border-radius);
  transition: opacity var(--motion-fast) var(--motion-ease);
}

.gallery-icon a:hover img {
  opacity: 0.85;
}

.gallery-caption {
  margin-top: 0.25rem;
  color: var(--bs-secondary-color);
}

/* Videos pasted as a link (oEmbed, functions.php): the text column's width at 16:9 */
.embed-video {
  margin-bottom: 1rem;
}

/* Gallery lightbox (template-parts/components/lightbox.php): each image whole on the dark surface, its caption
   under it, the controls at the sides (hidden for a single image) */
.lightbox .modal-header {
  justify-content: space-between;
}

.lightbox .carousel-item {
  padding: 0 1rem 1rem;
}

.lightbox .carousel-item.active,
.lightbox .carousel-item-next,
.lightbox .carousel-item-prev {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.lightbox .carousel-item img {
  min-height: 0;
  max-width: 100%;
  flex: 1 1 auto;
  object-fit: contain;
}

.lightbox-caption {
  max-width: 40rem;
  margin-top: 0.75rem;
  text-align: center;
}

.lightbox .carousel-control-prev,
.lightbox .carousel-control-next {
  width: 3rem;
  font-size: var(--bs-body-font-size);
}

.lightbox .carousel-control-prev .bi,
.lightbox .carousel-control-next .bi {
  font-size: 1.5rem;
}

.lightbox .is-single :is(.carousel-control-prev, .carousel-control-next) {
  display: none;
}

@media (min-width: 768px) {
  .lightbox .carousel-item {
    padding: 0 4rem 1.5rem;
  }

  .lightbox .carousel-control-prev,
  .lightbox .carousel-control-next {
    width: 4rem;
  }
}

/* Intro image (template-parts/components/intro-media.php): a wide crop on phones so it doesn't dominate, 4:3 beside the text from lg */
.intro-media {
  --bs-aspect-ratio: 56.25%;
}

@media (min-width: 992px) {
  .intro-media {
    --bs-aspect-ratio: 75%;
  }
}

/* Wide image from edge to edge under a page header, e.g. an event's picture: 16:10 on phones, flatter as the
   screen widens so it never fills the whole of it */
.feature-media {
  --bs-aspect-ratio: 62.5%;
}

@media (min-width: 768px) {
  .feature-media {
    --bs-aspect-ratio: 50%;
  }
}

@media (min-width: 992px) {
  .feature-media {
    --bs-aspect-ratio: 42.8571%;
  }
}

/* Editor content (pages, news articles): section headings at the .h4 size and sub-headings at the .h6 size, with
   more room above a heading than below it, so each heading reads with the text it introduces */
.entry-content h2 {
  font-size: var(--font-size-h4);
}

.entry-content :is(h3, h4, h5, h6) {
  font-size: var(--font-size-h6);
}

.entry-content :is(h2, h3, h4, h5, h6) {
  margin-top: 2.5rem;
  margin-bottom: 0.75rem;
  font-weight: var(--font-weight-heading);
  line-height: var(--line-height-heading);
  letter-spacing: 0;
}

.entry-content :is(h3, h4, h5, h6) {
  margin-top: 1.75rem;
}

.entry-content > :first-child {
  margin-top: 0;
}

/* Editor content inside a titled section of a page (e.g. "About this event"): every heading is a sub-heading,
   so it stays below the section's own heading */
.entry-content-nested :is(h2, h3, h4, h5, h6) {
  margin-top: 1.5rem;
  font-size: var(--font-size-h6);
}

.entry-content-nested > :first-child {
  margin-top: 0;
}

/* Numbered steps (template-parts/components/numbered-steps.php): equal-width figures keep the text beside
   01 to 10 aligned */
.step-number {
  font-variant-numeric: tabular-nums;
}

/* Header: Bootstrap navbar, offcanvas below lg (see header.php) */

/* Sticky (.sticky-top); js/main.js adds .is-hidden while scrolling down. The transform is only
   applied when hidden: on the header itself it would pin the fixed offcanvas drawer to the header. */
/* Rendered header height (navbar padding + the 3rem logo, 3.15rem from xl), for layouts that fill the screen below
   it or run under it. js/main.js keeps it measured; these values hold until then, so they must match. The header is
   the same height clear and solid: only colours and the logo's opacity change between the two. */
:root {
  --header-height: 5rem;
}

@media (min-width: 1200px) {
  :root {
    --header-height: 5.15rem;
  }
}

/* Clear and solid states, the logo crossfade and the header's controls share one timing, so the header changes
   as one piece. Only paint properties move; the slide away is a transform. */
.site-header {
  color: var(--color-primary);
  background-color: var(--color-surface);
  transition:
    transform var(--motion-standard) var(--motion-ease),
    background-color var(--motion-standard) var(--motion-ease),
    color var(--motion-standard) var(--motion-ease);
}

.site-header :is(.header-search-toggle, .header-menu-toggle, .header-button) {
  transition-property: color, background-color, border-color;
  transition-duration: var(--motion-standard);
  transition-timing-function: var(--motion-ease);
}

.site-name {
  color: inherit;
}

/* The logo link and its light copy (header.php) share one cell, so the swap is a crossfade with no change of size.
   The light copy is decorative and lets clicks through to the link beneath. */
.header-brand {
  display: grid;
  place-items: center;
}

.header-brand > * {
  grid-area: 1 / 1;
}

.logo-default .custom-logo,
.logo-inverse {
  transition:
    opacity var(--motion-standard) var(--motion-ease),
    filter var(--motion-standard) var(--motion-ease);
}

.logo-inverse {
  opacity: 0;
  pointer-events: none;
}

/* Centred layout (header.php): Menu button, logo, actions. The two sides share the leftover width equally, so
   the logo sits on the centre line whatever is beside it. The menu is a drawer at every width. */
.site-header-centered .navbar > .container-fluid {
  flex-wrap: nowrap;
}

.site-header-centered .header-side {
  flex: 1 0 0;
  min-width: 0;
}

.site-header-centered .header-brand {
  flex: 0 1 auto;
  min-width: 0;
}

/* The menu button is an icon button like the search (below), with a larger icon */
.header-menu-toggle .bi {
  font-size: 1.5rem;
  line-height: 1;
}

/* Over a hero (ydt_has_overlay_header()): the header lies on the image, clear and white, until the page is
   scrolled or the search panel opens; js/main.js keeps .is-top and .is-search-open. The hero is pulled up
   under it by the header's height. */
.has-overlay-header .hero {
  margin-top: calc(-1 * var(--header-height));
}

.has-overlay-header .hero-body {
  padding-top: calc(var(--section-y) + var(--header-height));
}

.site-header-overlay.is-top:not(.is-search-open) {
  --focus-color: var(--color-text-inverse);
  --focus-ring: 0 0 0 var(--focus-width) var(--focus-color);
  color: var(--color-text-inverse);
  background-color: transparent;
}

.site-header-overlay.is-top:not(.is-search-open) :is(.header-search-toggle, .header-menu-toggle) {
  --bs-btn-color: var(--color-text-inverse);
  --bs-btn-hover-color: var(--color-primary);
  --bs-btn-hover-bg: var(--color-surface);
  --bs-btn-hover-border-color: var(--color-surface);
}

.site-header-overlay.is-top:not(.is-search-open) .header-button {
  --bs-btn-color: var(--color-primary);
  --bs-btn-bg: var(--color-surface);
  --bs-btn-border-color: var(--color-surface);
  --bs-btn-hover-color: var(--color-primary);
  --bs-btn-hover-bg: var(--color-background);
  --bs-btn-hover-border-color: var(--color-background);
}

.site-header-overlay.is-top:not(.is-search-open) .logo-inverse {
  opacity: 1;
}

.site-header-overlay.is-top:not(.is-search-open) .logo-default:not(.logo-auto-invert) .custom-logo {
  opacity: 0;
}

.site-header-overlay.is-top:not(.is-search-open) .logo-auto-invert .custom-logo {
  filter: brightness(0) invert(1);
}

.site-header.is-hidden {
  transform: translateY(-100%);
}

/* Search panel (header.php): lies over the page under the bar, so opening it moves neither the header nor the
   page. It fades in with a small drop; closed, it leaves the tab order (visibility) once the fade has ended. */
.header-search {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  opacity: 0;
  visibility: hidden;
  transform: translateY(calc(-1 * var(--motion-shift)));
  transition:
    opacity var(--motion-standard) var(--motion-ease),
    transform var(--motion-standard) var(--motion-ease),
    visibility 0s var(--motion-standard);
}

.header-search.is-open {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: 0s;
}

/* The form, and its close button at the end of the row. From lg the form keeps the width of the 8 (xl: 6) centred
   columns it had, with the button at the container's edge. */
.header-search-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.5rem;
}

/* 44px target, pulled back so the cross stays on the edge padding (as in the drawer) */
.header-search-close {
  padding: 0.875rem;
  margin-right: -0.625rem;
}

@media (min-width: 992px) {
  .header-search-row {
    grid-template-columns: 1fr minmax(0, 39rem) 1fr;
  }

  .header-search-row .search-form {
    grid-column: 2;
  }

  .header-search-close {
    justify-self: end;
  }
}

@media (min-width: 1200px) {
  .header-search-row {
    grid-template-columns: 1fr minmax(0, 34.875rem) 1fr;
  }
}

/* Keep it in view for keyboard users, and while the drawer is open */
.site-header:has(:focus-visible),
.site-header:has(.offcanvas.showing, .offcanvas.show, .offcanvas.hiding) {
  transform: none;
}

/* The drawer lives inside the sticky header's stacking context, so lift the header above
   Bootstrap's backdrop (1040) and the WordPress admin bar (99999) while it is open */
.site-header:has(.offcanvas.showing, .offcanvas.show, .offcanvas.hiding) {
  z-index: 100000;
}

/* A transformed header becomes the containing block of the closed drawer, which then lies beside the page
   and widens it on phones. The wrapper clips it (clip, unlike hidden, keeps the header sticky), also while
   the header slides back; for browsers without clip, the closed drawer leaves the layout while the header
   is hidden. lg renders the menu inline (below). */
.site-wrapper {
  overflow-x: clip;
}

.site-header.is-hidden .offcanvas:not(.show, .showing, .hiding) {
  display: none;
}

/* Sit below the WordPress admin bar; it scrolls away below 600px (WordPress breakpoint) */
@media (min-width: 600px) {
  .admin-bar .site-header {
    top: var(--wp-admin--admin-bar--height, 0);
  }
}

.custom-logo {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 2.325rem;
}

.navbar {
  --bs-navbar-color: var(--color-primary);
  --bs-navbar-hover-color: var(--color-accent-strong);
  --bs-navbar-active-color: var(--color-accent-strong);
  --bs-navbar-toggler-padding-x: 0.5rem;
  --bs-navbar-toggler-padding-y: 0.375rem;
  --bs-navbar-toggler-border-color: transparent;
  /* Bootstrap rings the toggler on any :focus (mouse clicks too); keyboard ring is below */
  --bs-navbar-toggler-focus-width: 0;
}

/* Same for the offcanvas close button: no ring on click, brand ring for keyboard */
.btn-close {
  --bs-btn-close-focus-shadow: none;
}

.btn-close:focus-visible,
.navbar-toggler:focus-visible {
  outline: var(--focus-width) solid var(--focus-color);
  outline-offset: 1px;
  box-shadow: none;
}

/* Fit narrow phones; sit above the WordPress admin bar (z-index 99999). The drawer keeps the surface colours
   when the header itself is clear over a hero. Its side padding is the page edge (20px, 32px from md), so the
   Close button lands where the menu button was; it widens a step at sm and lg so long labels keep their line. */
.navbar .offcanvas {
  --bs-offcanvas-width: 20rem;
  --bs-offcanvas-zindex: 100000;
  --bs-offcanvas-color: var(--color-text);
  --bs-offcanvas-padding-x: 1.25rem;
  --bs-offcanvas-padding-y: 1.5rem;
  --focus-ring: 0 0 0 var(--focus-width) var(--focus-color);
  --focus-color: var(--color-accent-strong);
}

@media (min-width: 576px) {
  .navbar .offcanvas {
    --bs-offcanvas-width: 24rem;
  }
}

@media (min-width: 768px) {
  .navbar .offcanvas {
    --bs-offcanvas-padding-x: 2rem;
    --bs-offcanvas-padding-y: 2rem;
  }
}

@media (min-width: 992px) {
  .navbar .offcanvas {
    --bs-offcanvas-width: 26rem;
  }
}

/* The logo row is the header bar's height, so the drawer's top lines up with the bar it opens from. Space above
   the first link comes from the body's padding; the last one keeps its padding above the home indicator. */
.offcanvas-header {
  min-height: var(--header-height);
  padding-block: 0;
}

.navbar .offcanvas-body {
  padding-bottom: calc(var(--bs-offcanvas-padding-y) + env(safe-area-inset-bottom, 0px));
}

/* Roomy tap targets in the drawer (~46px) */
.navbar-nav {
  --bs-nav-link-padding-y: 0.625rem;
}

/* Drawer: the logo and the close button at the top, then full-width rows with no rules between them and the
   chevron at the row's end. In the inline layout (below lg) submenus open in place as an indented list rather
   than a boxed dropdown, and lg restores the dropdown; in the centred layout they open as a second layer (below). */
/* 44px Close buttons in the drawer and its layers, pulled back so the cross stays on the edge padding */
.offcanvas .btn-close {
  padding: 0.875rem;
  margin: -0.625rem -0.625rem -0.625rem auto;
}

/* The drawer takes focus when it opens, as a dialog does; the ring belongs on its controls, not on its edge */
.offcanvas:focus-visible {
  outline: 0;
}

.offcanvas-brand {
  color: var(--bs-heading-color);
}

.offcanvas-brand .custom-logo {
  max-height: 2.5rem;
}

.navbar-nav :is(.dropdown-toggle, .submenu-toggle) {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  width: 100%;
  text-align: start;
}

.navbar-nav .dropdown-menu {
  --bs-dropdown-border-width: 0;
  --bs-dropdown-bg: transparent;
  --bs-dropdown-padding-y: 0;
  --bs-dropdown-item-padding-y: 0.625rem;
  --bs-dropdown-item-border-radius: var(--bs-border-radius);
  /* A tint rather than a solid bar, which is heavy in a list; the weight keeps it from being colour alone */
  --bs-dropdown-link-active-bg: var(--color-surface-muted);
  --bs-dropdown-link-active-color: var(--color-primary);
  margin-bottom: 0.75rem;
}

.navbar-nav .dropdown-item {
  white-space: normal;
}

.navbar-nav .dropdown-item.active {
  font-weight: 600;
}

/* Active state is not colour alone: the current item is bold as well */
.navbar-nav .nav-link.active {
  font-weight: 700;
}

/* Chevron (Bootstrap Icons chevron-down) instead of Bootstrap's caret */
.navbar .dropdown-toggle::after {
  border: 0;
  margin-left: 0.5rem;
  font-family: "bootstrap-icons";
  font-size: 0.75em;
  content: "\f282";
  content: "\f282" / "";
  vertical-align: -0.0625em;
}

.navbar .dropdown-toggle[aria-expanded="true"]::after {
  transform: rotate(180deg);
}

/* Centred layout: the drawer's links are larger, and a submenu is a second layer (.submenu-layer) that slides
   over the whole drawer (js/main.js adds its Back and Close buttons and its title, and .show). While it is open
   the first layer is hidden, so the keyboard stays in the layer. Hidden at once on closing would cut the slide
   short, so visibility waits for it; on opening it is immediate, so the layer can take focus. */
/* Rows are 56px and more (20 to 24px type on the heading line height, 1rem above and below), so a label that
   wraps stays one tight block and the space between rows does the separating. */
.site-header-centered .navbar-nav {
  --bs-nav-link-font-size: var(--font-size-h4);
  --bs-nav-link-padding-y: 1rem;
  line-height: var(--line-height-heading);
}

/* The cue is secondary: small, muted, and kept clear of a long label (gap above) */
.submenu-toggle::after {
  flex-shrink: 0;
  color: var(--color-text-muted);
  font-family: "bootstrap-icons";
  font-size: 0.75em;
  content: "\f285";
  content: "\f285" / "";
}

.submenu-toggle:hover::after {
  color: inherit;
}

.submenu-layer {
  position: absolute;
  inset: 0;
  z-index: 1;
  margin: 0;
  padding: 0 var(--bs-offcanvas-padding-x) calc(var(--bs-offcanvas-padding-y) + env(safe-area-inset-bottom, 0px));
  overflow-y: auto;
  background-color: var(--bs-offcanvas-bg);
  visibility: hidden;
  transform: translateX(100%);
  transition:
    transform 0.3s ease-in-out,
    visibility 0s 0.3s;
}

.submenu-layer.show {
  visibility: visible;
  transform: none;
  transition: transform 0.3s ease-in-out;
}

/* The layer's top row is the drawer's own (logo and Close), so Close stays put; the parent's name and the links
   start where the drawer's first link did. */
.submenu-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--header-height);
}

.submenu-back {
  --bs-btn-padding-x: 0;
  --bs-btn-padding-y: 0;
  --bs-btn-color: var(--color-primary);
  --bs-btn-hover-color: var(--color-accent-strong);
  --bs-btn-active-color: var(--color-accent-strong);
  --bs-btn-border-color: transparent;
  --bs-btn-hover-border-color: transparent;
  --bs-btn-active-border-color: transparent;
  --bs-btn-font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  padding-inline-end: 0.75rem;
}

.submenu-title {
  padding-top: var(--bs-offcanvas-padding-y);
  margin-bottom: 0.25rem;
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Links under the menu (My Orders): quieter than the menu by size and colour, on a 44px row */
.drawer-secondary a {
  min-height: 2.75rem;
  color: var(--color-text-muted);
}

.drawer-secondary a:hover {
  color: var(--bs-link-hover-color);
}

.offcanvas.has-open-layer .offcanvas-header,
.offcanvas.has-open-layer .offcanvas-body > .btn,
.offcanvas.has-open-layer .drawer-secondary,
.offcanvas.has-open-layer .navbar-nav > .nav-item > .nav-link {
  visibility: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .submenu-layer,
  .submenu-layer.show {
    transition: none;
  }
}

/* Icon buttons with no surface of their own until they are hovered or pressed */
.header-search-toggle,
.header-menu-toggle {
  --bs-btn-color: var(--color-primary);
  --bs-btn-font-size: 1.125rem;
  --bs-btn-bg: transparent;
  --bs-btn-border-color: transparent;
  --bs-btn-hover-color: var(--color-primary);
  --bs-btn-hover-bg: var(--color-surface-muted);
  --bs-btn-hover-border-color: var(--color-surface-muted);
  --bs-btn-active-color: var(--color-primary);
  --bs-btn-active-bg: var(--color-surface-muted);
  --bs-btn-active-border-color: var(--color-surface-muted);
  width: 2.75rem;
  height: 2.75rem;
}

/* Inline layout from lg (.navbar-expand-lg): the menu sits in the header. 992 to 1199px is the tightest fit: the
   smaller logo, gaps and link padding keep the logo, menu and search within the 936px container without wrapping
   a label (xl restores the larger sizes). The centred layout keeps its drawer, so none of this applies to it. */
@media (min-width: 992px) {
  .custom-logo {
    max-height: 3rem;
  }

  /* Logo and actions share the leftover width equally, so the menu sits on the header's centre line */
  .site-header:not(.site-header-centered) .header-side {
    flex: 1 0 0;
    min-width: max-content;
  }

  .navbar-expand-lg {
    --bs-navbar-nav-link-padding-x: 0.375rem;
  }

  .navbar-expand-lg .offcanvas {
    flex-grow: 0;
    margin-inline: 0.5rem;
  }

  .site-header.is-hidden .navbar-expand-lg .offcanvas:not(.show, .showing, .hiding) {
    display: flex;
  }

  .navbar-expand-lg .navbar-nav {
    --bs-nav-link-font-size: 0.9375rem;
  }

  .navbar-expand-lg .navbar-nav .dropdown-toggle {
    display: block;
    width: auto;
  }

  .navbar-expand-lg .navbar-nav .dropdown-menu {
    --bs-dropdown-border-width: var(--bs-border-width);
    --bs-dropdown-bg: var(--bs-body-bg);
    --bs-dropdown-padding-y: 0.5rem;
    --bs-dropdown-font-size: 0.9375rem;
    --bs-dropdown-item-padding-y: 0.5rem;
    --bs-dropdown-item-border-radius: 0;
    --bs-dropdown-link-active-bg: var(--color-primary);
    --bs-dropdown-link-active-color: var(--color-text-inverse);
    margin-bottom: 0;
  }

  .navbar-expand-lg .navbar-nav .dropdown-item {
    white-space: nowrap;
  }

  .navbar-expand-lg .navbar-nav .dropdown-item.active {
    font-weight: inherit;
  }

  .navbar-expand-lg .header-search-toggle {
    width: 2.25rem;
    height: 2.25rem;
  }
}

@media (min-width: 1200px) {
  .custom-logo {
    max-height: 3.15rem;
  }

  .navbar-expand-lg {
    --bs-navbar-nav-link-padding-x: 0.75rem;
  }
}

/* Footer (footer.php) on the dark .bg-dark surface. #wrapper is a flex column (header.php) with
   #container growing, so the footer sits at the bottom of short pages, below the admin bar if shown. */
.site-wrapper {
  min-height: calc(100vh - var(--wp-admin--admin-bar--height, 0px));
  /* Visible height on phones, where 100vh ignores the browser toolbar */
  min-height: calc(100dvh - var(--wp-admin--admin-bar--height, 0px));
}

/* The footer's own palette, on the dark surface: a warm near-black, content in the page's cream rather than pure
   white (13.7:1), labels and secondary text in the muted inverse, the accent only on hover. Cream also tints the
   rules, the field edges (4:1) and the light button, so nothing in the band is cold white. */
.site-footer {
  --bs-dark-rgb: var(--color-footer-rgb);
  --footer-text: var(--color-background);
  --footer-line: rgba(var(--color-background-rgb), 0.12);
  --focus-color: var(--footer-text);
  --focus-ring: 0 0 0 var(--focus-width) var(--focus-color);
  color: var(--footer-text);
}

.site-footer :is(.form-control, .form-check-input) {
  color: var(--footer-text);
  border-color: rgba(var(--color-background-rgb), 0.45);
}

.site-footer :is(.form-control, .form-check-input):focus {
  border-color: var(--focus-color);
}

.site-footer .form-check-input:checked {
  border-color: var(--color-accent);
}

.site-footer .btn-primary {
  --bs-btn-bg: var(--footer-text);
  --bs-btn-border-color: var(--footer-text);
  --bs-btn-hover-bg: var(--color-surface);
  --bs-btn-hover-border-color: var(--color-surface);
}

.footer-rule {
  border-top: var(--bs-border-width) solid var(--footer-line);
}

/* More room above the columns than an ordinary section: the footer is the page's closing band */
.site-footer-columns.section {
  padding-top: calc(var(--section-y) + 1rem);
  padding-bottom: 2rem;
}

/* Column labels ("Explore", "Contact", the newsletter's heading): one style for all three, small spaced capitals
   in the muted colour, so the content under them carries the footer */
.footer-heading {
  margin-bottom: 1rem;
  color: var(--color-accent-on-dark);
  font-family: var(--font-body);
  font-size: var(--font-size-sm);
  font-weight: 600;
  letter-spacing: 0.12em;
  line-height: var(--line-height-body);
  text-transform: uppercase;
}

/* Footer links: light grey, white on hover (the bottom bar). In the columns, content (links and the address) is
   white with the accent on hover, and the links keep 44px tap targets while negative margins hold them to an even
   2.25rem line. */
.footer-links a {
  display: inline-block;
  padding-block: 0.625rem;
  color: var(--bs-secondary-color);
  text-decoration: none;
  transition: color 0.15s;
}

.footer-links a:hover {
  color: var(--footer-text, var(--color-text-inverse));
}

.site-footer-columns address,
.site-footer-columns .footer-links a {
  color: var(--footer-text);
}

.site-footer-columns .footer-links a {
  margin-block: -0.4375rem;
  font-weight: var(--font-weight-body);
}

.site-footer-columns .footer-links li + li {
  margin-top: 0.25rem;
}

.site-footer-columns .footer-links a:hover {
  color: var(--color-accent-on-dark);
}

/* Social links: bare icons on square 44px targets, outlined on hover. The list's negative margin lines the first
   icon up with the text above it. */
.footer-social {
  margin-left: -0.8125rem;
}

.footer-social-link {
  --bs-btn-color: var(--footer-text);
  --bs-btn-bg: transparent;
  --bs-btn-border-color: transparent;
  --bs-btn-hover-color: var(--color-accent-on-dark);
  --bs-btn-hover-bg: transparent;
  --bs-btn-hover-border-color: transparent;
  --bs-btn-active-color: var(--color-primary);
  --bs-btn-active-bg: var(--color-surface);
  --bs-btn-active-border-color: var(--color-surface);
  --bs-btn-font-size: 1.125rem;
  width: 2.75rem;
  height: 2.75rem;
}

/* The oversized wordmark between the columns and the bottom bar: decorative, faint, and fading out into the rule
   beneath it. Sized to the band (cqi units), so it scales with the page and never widens it. The site name
   fallback takes its size from footer.php (--wordmark-size), smaller for a longer name: a graphic, not text,
   so it sits outside the type scale. */
.footer-wordmark {
  container-type: inline-size;
  overflow: hidden;
  padding-top: 1rem;
  opacity: 0.09;
  pointer-events: none;
  user-select: none;
  /* Only the mask's alpha counts: opaque at the top, clear at the rule */
  -webkit-mask-image: linear-gradient(to bottom, currentColor 30%, transparent 100%);
  mask-image: linear-gradient(to bottom, currentColor 30%, transparent 100%);
}

/* Any logo colours become white. A wide wordmark fills the band; a taller mark keeps to under a quarter of its
   width in height, placed by the Customizer's alignment (.footer-wordmark-left/-center/-right). */
.footer-wordmark-image {
  display: block;
  width: 100%;
  height: auto;
  max-height: 22cqi;
  object-fit: contain;
  object-position: left bottom;
  filter: brightness(0) invert(1);
}

.footer-wordmark-left .footer-wordmark-text {
  margin-left: -0.06em;
}

.footer-wordmark-center {
  text-align: center;
}

.footer-wordmark-center .footer-wordmark-image {
  object-position: center bottom;
}

.footer-wordmark-right {
  text-align: right;
}

.footer-wordmark-right .footer-wordmark-image {
  object-position: right bottom;
}

.footer-wordmark-text {
  display: block;
  /* Pulls the space under the baseline into the rule (and, on the left, the first letter's side bearing back to
     the page edge) */
  margin-bottom: -0.12em;
  color: var(--color-text-inverse);
  font-family: var(--font-heading);
  font-size: var(--wordmark-size, 30cqi);
  font-weight: var(--font-weight-heading-strong);
  letter-spacing: -0.045em;
  line-height: 0.82;
  white-space: nowrap;
}

/* Bottom bar: room below (phones) or to the right (from md) for the fixed back-to-top button, so it never
   covers the last link once the page is scrolled to the end */
.footer-bottom {
  padding-top: 1.75rem;
  padding-bottom: 5.5rem;
}

@media (min-width: 768px) {
  .footer-bottom {
    padding-bottom: 1.75rem;
    padding-right: calc(var(--bs-gutter-x) * 0.5 + 3rem);
  }

  .footer-wordmark-text {
    font-size: var(--wordmark-size-md, 30cqi);
  }
}

@media (min-width: 992px) {
  .footer-wordmark {
    padding-top: 2rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .footer-links a {
    transition: none;
  }
}

/* Floating back-to-top link, shown by js/main.js after one screen of scrolling */
.back-to-top {
  --bs-btn-font-size: 1.25rem;
  --bs-btn-bg: rgba(var(--color-footer-rgb));
  /* White ring separates it from the dark footer; invisible on white pages */
  box-shadow: 0 0 0 1px var(--color-surface);
  z-index: 1030;
  width: 2.75rem;
  height: 2.75rem;
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 0.2s,
    visibility 0.2s;
}

.back-to-top.is-visible {
  opacity: 1;
  visibility: visible;
}

/* Reduced motion: the header no longer slides away, it disappears; its colours still change in a short fade
   (the motion tokens) */
@media (prefers-reduced-motion: reduce) {
  .site-header {
    transition-property: background-color, color;
  }

  .back-to-top {
    transition: none;
  }
}

/* Search results: dark titles, link colour on hover (Bootstrap's .link-dark hover is hard-coded) */
.search-result-title a {
  color: var(--color-primary);
  text-decoration: none;
}

.search-result-title a:hover {
  color: var(--color-accent-strong);
}

/* WordPress core output (search form labels, post navigation headings) */
.screen-reader-text {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* The Turnstile plugin prints a line break after its widget on the ticketing checkout; the layout spaces it already */
.cf-turnstile-br.cf-turnstile-br-ydp-checkout {
  display: none;
}

.cf-turnstile {
  margin: 0 !important;
}

/* Ticket groups (template-parts/components/ticket-options.php): a hairline between groups, the open group's types
   under its own hairline, and the chevron turned while open */
.ticket-group {
  border-bottom: var(--bs-border-width) solid var(--bs-border-color);
}

.ticket-groups > .ticket-group:first-child {
  border-top: var(--bs-border-width) solid var(--bs-border-color);
}

/* The group's own line closes it: its last type drops the .border-bottom utility's line (an !important utility) */
.ticket-group li:last-child {
  border-bottom: 0 !important;
}

/* A group opens and closes at once: the theme never animates height (Bootstrap's .collapsing does) */
.ticket-group .collapsing {
  transition: none;
}

.ticket-group-toggle {
  --bs-btn-font-weight: inherit;
  min-height: 44px;
  text-decoration: none;
}

.ticket-group-icon {
  transition: transform var(--motion-standard) var(--motion-ease);
}

.ticket-group-toggle:not(.collapsed) .ticket-group-icon {
  transform: rotate(180deg);
}

/* A ticket type's description from the editor: short lists and paragraphs */
.ticket-description > :last-child {
  margin-bottom: 0;
}

.ticket-description p,
.ticket-description ul,
.ticket-description ol {
  margin-bottom: 0.25rem;
}

.ticket-description ul,
.ticket-description ol {
  padding-left: 1.1rem;
}

/* The hold countdown on the order page: figures of one width, so the time doesn't shift as it ticks */
.countdown-time {
  font-variant-numeric: tabular-nums;
}

/* Code boxes (js/main.js, from code-verification): six equal boxes that never overflow a phone */
.code-boxes {
  max-width: 21rem;
}

.code-box {
  flex: 1 1 0;
  min-width: 0;
  max-width: 3.25rem;
  padding-right: 0;
  padding-left: 0;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* An invalid code box keeps its red border and the message under the boxes; the field's icon would hide the digit */
.code-box.is-invalid {
  padding-right: 0;
  background-image: none;
}

/* Dialogs take the dialog radius (design direction: 4px) */
.modal {
  --bs-modal-border-radius: var(--radius-xl);
  --bs-modal-inner-border-radius: var(--radius-xl);
}
