@charset "UTF-8";
/*
 * theme.json owns the design tokens (color/font/spacing, under logical
 * names editors can change in Site Editor → Styles). These custom
 * properties are aliases onto those presets — never a hardcoded value —
 * so a token change in Styles cascades through every component here
 * automatically.
 */
:root {
  --c-background: var(--wp--preset--color--background);
  --c-surface: var(--wp--preset--color--surface);
  --c-foreground: var(--wp--preset--color--foreground);
  --c-border: var(--wp--preset--color--border);
  --c-primary: var(--wp--preset--color--primary);
  --c-primary-dark: var(--wp--preset--color--primary-dark);
  --c-accent: var(--wp--preset--color--accent);
  --c-accent-dark: var(--wp--preset--color--accent-dark);
  --c-accent-secondary: var(--wp--preset--color--accent-secondary);
  --c-hero-background: var(--wp--preset--color--hero-background);
  --c-ticket-background: var(--wp--preset--color--ticket-background);
  --f-heading: var(--wp--preset--font-family--heading);
  --f-body: var(--wp--preset--font-family--body);
  --f-detail: var(--wp--preset--font-family--detail);
  /* Matches .ott-header's real rendered height (padding-block 1.2rem top
   * and bottom, plus its tallest inline content, the CTA button) so hero
   * top padding and anchor scroll-margin can both stay in sync with the
   * fixed header via one shared value instead of two guesses. */
  --ott-header-height: clamp(4.75rem, 4rem + 2vw, 5.5rem);
}

html {
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
.wp-block-heading {
  text-transform: uppercase;
  letter-spacing: 0.01em;
  text-wrap: balance;
  line-height: 0.98;
}

.ott-eyebrow {
  font-family: var(--f-detail);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--c-accent);
  margin-bottom: 1rem;
}

.wp-block-button__link {
  font-family: var(--f-body);
  font-weight: 700;
  font-size: 0.85rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-radius: 3px !important;
  padding: 0.95em 1.7em !important;
  transition: transform 120ms ease, background 120ms ease;
}

.wp-block-button__link:hover {
  transform: translateY(-1px);
}

.wp-block-button.is-style-outline > .wp-block-button__link {
  border: 2px solid var(--c-background);
  color: var(--c-background);
}

.wp-block-button.is-style-outline > .wp-block-button__link:hover {
  background: var(--c-background);
  color: var(--c-primary);
}

.ott-main {
  /* Every top-level template block gets an automatic margin-block-start
   * from :where(.wp-site-blocks) > *, in the page's own background color.
   * <main> used to sit lower in template flow, but since the
   * make-homepage-directly-editable refactor it's the first top-level
   * block after the header (hero/highlights now render nested inside it,
   * via post-content), so it's the one that needs the override now — see
   * templates/front-page.html. Without this, there'd be a thin gap of
   * Background color between the header and the hero even though both
   * should sit flush. */
  margin-block-start: 0 !important;
}

.ott-header {
  background: var(--c-primary);
}

.ott-header .wp-block-group {
  padding-block: 1.2rem;
  justify-content: flex-start;
  gap: 1.5rem;
}

.ott-header nav.wp-block-navigation {
  margin-inline-start: auto;
}

.ott-header-logo {
  font-family: var(--f-heading);
  color: var(--c-background);
  font-size: 1.2rem;
  line-height: 1;
  text-decoration: none;
}

.ott-header-logo span {
  display: block;
  font-family: var(--f-detail);
  text-transform: none;
  letter-spacing: 0.04em;
  font-size: 0.58rem;
  color: var(--c-accent);
  margin-top: 0.3rem;
}

.ott-header .wp-block-navigation__container {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1.5rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.ott-header .wp-block-navigation a {
  display: inline-block;
  padding: 0.5rem 0.25rem;
  color: var(--c-background);
  font-weight: 600;
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
}

.ott-header .wp-block-navigation a:hover {
  color: var(--c-accent);
}

.ott-header .wp-block-navigation a.is-active {
  color: var(--c-accent);
  text-decoration: underline;
  text-underline-offset: 0.3em;
}

/* Homepage only: the header overlays the hero from first paint (transparent,
 * fixed to the viewport) and switches to its normal solid background once
 * homepage-nav.js observes the hero has scrolled out from under it. See
 * templates/front-page.html for the scoping wrapper and design.md Decision
 * 1/2 for why `fixed` + an explicit wrapper class, not `sticky`/`absolute`
 * or the implicit `home` body class. */
.ott-header-hero-overlay .ott-header {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 20;
  background: transparent;
}

.ott-header-hero-overlay .ott-header.is-scrolled {
  background: var(--c-primary);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

/* Hero Background is its own token, independent of Primary — otherwise
 * editing the header/footer color would also repaint the hero. The darker
 * lower edge lives on a separate .ott-hero::before overlay rather than as a
 * second background-image value on .ott-hero itself, so an editor's own
 * per-instance background-color or background-image pick (written by
 * WordPress as a class or inline style on .ott-hero) can never collide with
 * or replace the scrim — they're different CSS properties on different
 * boxes. .ott-hero's own background-color/background-image intentionally
 * carry no !important: WordPress's per-block "Background color" picker
 * applies either a .has-{slug}-background-color{...!important} utility
 * class (preset colors) or an inline style (custom colors/images), and both
 * already beat a plain, unqualified rule here — so leaving it unqualified
 * lets an editor's per-instance pick win deterministically, while the
 * theme's default color still applies when nothing has been picked. */
/* Wave divider: cut into .ott-hero's own bottom edge via mask-image, not a
 * shape painted on top of it. Whatever paints the hero — the flat color
 * below today, a photo or video later — gets the wavy edge for free, and
 * what shows through the notches is simply the page's own background
 * (styles.color.background in theme.json, the same "background" preset
 * .ott-highlights already uses) sitting behind the hero in the normal
 * stacking order — nothing here has to know or match that color itself.
 *
 * clip-path: polygon() was tried first, but polygon() only ever draws
 * straight segments — even with extra points baked in to fake a curve, it
 * still reads as faceted/hard at normal viewing size. mask-image gets real
 * curve interpolation by pointing at an SVG <path> that uses actual cubic
 * Bezier commands.
 *
 * Rather than stretch one big curve non-uniformly across the hero's full
 * width (which would distort crest shape differently at every viewport
 * width), the mask is a single small wave *tile* repeated edge-to-edge via
 * mask-repeat: repeat-x at a fixed pixel size — crests stay a constant
 * physical size at any viewport, wider viewports just show more copies.
 * The tile is built from two cubic Beziers (crest→trough, trough→crest),
 * each using the "control points share their nearest endpoint's y" trick,
 * which gives a horizontal (zero-slope) tangent at every crest and trough —
 * and because both tile edges land exactly on a crest with the same y and
 * the same zero slope, copies tile with no visible seam or kink. The
 * rightmost copy may get cropped by the hero's own width, same as any
 * repeating background image — expected, not a bug.
 *
 * Depth is capped at 64px (0-8 range mapped into a 0-64 viewBox) to stay
 * clear of .ott-hero-grid's padding-bottom, whose floor is 72px
 * (clamp(4.5rem, 9vw, 6rem) bottoms out at 4.5rem below an ~800px
 * viewport) — so the wave never bites into the grid's own content.
 *
 * $ott-wave-path/$ott-wave-tile-w/$ott-wave-depth are the single source of
 * truth at the Sass level (edit them here, not in two places): packaged
 * once into $ott-wave-mask and emitted once as the --ott-wave-mask custom
 * property, which both the prefixed and unprefixed mask declarations then
 * reference, so the compiled CSS also only states the data URI once. */
.ott-hero {
  position: relative;
  background-color: var(--c-hero-background);
  padding-block: clamp(2rem, 5vw, 3.5rem) 0;
  --ott-wave-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 64' preserveAspectRatio='none'%3E%3Cpath d='M0,8 C45,8 45,56 90,56 C135,56 135,8 180,8 L180,0 L0,0 Z' fill='%23000'/%3E%3C/svg%3E");
  mask: linear-gradient(#000, #000) top/100% calc(100% - 40px) no-repeat, var(--ott-wave-mask) left bottom/325px 40px repeat-x;
  -webkit-mask: linear-gradient(#000, #000) top/100% calc(100% - 40px) no-repeat, var(--ott-wave-mask) left bottom/325px 40px repeat-x;
}

.ott-hero::before {
  /* Kept on a separate layer from .ott-hero's own background so an
   * editor-picked background image (written by WordPress as an inline
   * background-image style on .ott-hero itself) can't collide with and
   * replace this scrim — they're different CSS properties on different
   * boxes, so neither can clobber the other. The wave-edge mask above
   * applies to .ott-hero as a whole compositing group, so it clips this
   * pseudo-element too without needing its own mask. */
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: linear-gradient(180deg, transparent 0%, transparent 82%, rgba(0, 0, 0, 0.35) 100%);
}

.ott-hero-grid {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
  /* Homepage-only: the header overlays the hero as a fixed, transparent
   * layer (see header.scss's .ott-header-hero-overlay rules), so the grid
   * needs its own extra top clearance to keep the title/CTA out from under
   * it — .ott-hero's own padding-block top isn't enough on its own. */
  padding-top: var(--ott-header-height);
  padding-bottom: clamp(4.5rem, 9vw, 6rem);
}

@media (max-width: 820px) {
  .ott-hero-grid {
    grid-template-columns: 1fr;
  }
}
.ott-hero-title {
  color: var(--c-background);
  font-size: clamp(2.75rem, 2.1rem + 3.2vw, 5.5rem);
}

.ott-hero-title em {
  font-style: normal;
  color: var(--c-accent);
}

.ott-hero-sub {
  color: var(--c-border);
  max-width: 46ch;
}

/* Perforation notches are cut as real transparent holes (via mask), not
 * painted dots — a painted dot has to match whatever sits behind the card,
 * which breaks the moment that background changes. A mask alone would also
 * cut straight through the border, erasing it right where the notch is. So
 * the ring is built from two nested layers: .ticket-card is the border
 * color, masked at the full notch radius; .ticket-card-inner sits inset by
 * --border-w and is masked at a proportionally smaller radius, so a rim of
 * the border color still traces the curve. --border-w is 0 by default
 * (flush, no border) — set --border-w plus the three color tokens to get a
 * bordered ticket. */
.ticket-card {
  --notch-r: 10px;
  --border-w: 0px;
  --ticket-border: transparent;
  --ticket-fill: var(--c-primary);
  --ticket-fg: var(--c-background);
  background: var(--ticket-border) !important;
  border-radius: 14px;
  padding: var(--border-w);
  mask: radial-gradient(circle var(--notch-r) at 0 50%, transparent 99%, black 100%) 0 0/51% 100% no-repeat, radial-gradient(circle var(--notch-r) at 100% 50%, transparent 99%, black 100%) 100% 0/51% 100% no-repeat;
  -webkit-mask: radial-gradient(circle var(--notch-r) at 0 50%, transparent 99%, black 100%) 0 0/51% 100% no-repeat, radial-gradient(circle var(--notch-r) at 100% 50%, transparent 99%, black 100%) 100% 0/51% 100% no-repeat;
}

.ticket-card-inner {
  background: var(--ticket-fill) !important;
  color: var(--ticket-fg);
  border-radius: calc(14px - var(--border-w));
  padding: clamp(1.5rem, 3vw, 2.25rem);
  mask: radial-gradient(circle calc(var(--notch-r) - var(--border-w)) at 0 50%, transparent 99%, black 100%) 0 0/51% 100% no-repeat, radial-gradient(circle calc(var(--notch-r) - var(--border-w)) at 100% 50%, transparent 99%, black 100%) 100% 0/51% 100% no-repeat;
  -webkit-mask: radial-gradient(circle calc(var(--notch-r) - var(--border-w)) at 0 50%, transparent 99%, black 100%) 0 0/51% 100% no-repeat, radial-gradient(circle calc(var(--notch-r) - var(--border-w)) at 100% 50%, transparent 99%, black 100%) 100% 0/51% 100% no-repeat;
}

.ticket-card .wp-block-buttons {
  margin-top: 1.25rem;
}

.ticket-card .wp-block-button {
  width: 100%;
}

.ticket-card .wp-block-button__link {
  width: 100%;
  justify-content: center;
  text-align: center;
}

.ott-hero-ticket {
  width: 100%;
  max-width: 400px;
  margin-inline: auto 0;
  --border-w: 2px;
  --ticket-border: var(--c-foreground);
  --ticket-fill: var(--c-ticket-background);
  --ticket-fg: var(--c-foreground);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
}

/* Ticket Background is its own token, independent of Accent — otherwise
 * editing any button/link on the site would also repaint the ticket.
 * A gold fill reads as a "golden ticket" against the dusk hero. Accent
 * Secondary and Border, used for this text elsewhere, drop under 4.5:1 on
 * the default Ticket Background — this card uses Foreground for primary
 * text (7.8:1) and Primary for secondary text (5.9:1) instead. If Ticket
 * Background is changed to a darker color, revisit these two pairings. */
.ott-hero-ticket .ott-ticket-date {
  font-family: var(--f-detail);
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-primary);
  border-bottom: 1px dashed rgba(36, 26, 18, 0.2);
  padding-bottom: 1rem;
  margin-bottom: 1rem;
}

.ott-hero-ticket .ott-tier {
  border-bottom-color: rgba(36, 26, 18, 0.2);
}

.ott-hero-ticket .ott-tier-desc {
  color: var(--c-primary);
}

.ott-hero-ticket .ott-tier-price {
  color: var(--c-primary);
}

.ott-tier {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding-block: 0.9rem;
  border-bottom: 1px dashed var(--c-border);
}

/* :last-of-type would match by tag name ("div"), and the trailing buttons
   wrapper is also a div — so it'd silently stop matching the third tier
   the moment any other div-based block follows. Scoping to the dedicated
   .ott-tier-list wrapper's :last-child is unambiguous regardless of what
   comes after. */
.ott-tier-list > .ott-tier:last-child {
  border-bottom: none;
}

.ott-tier-name {
  font-weight: 700;
  text-transform: uppercase;
  font-size: 0.9rem;
  letter-spacing: 0.04em;
}

.ott-tier-desc {
  display: block;
  font-family: var(--f-detail);
  font-size: 0.68rem;
  margin-top: 0.25rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--c-border);
}

.ott-tier-price {
  font-family: var(--f-detail);
  font-size: 1.25rem;
  font-weight: 600;
  white-space: nowrap;
  color: var(--c-accent);
}

.ott-highlights {
  background: var(--c-background);
  padding-block: 3rem 3.5rem;
  scroll-margin-top: var(--ott-header-height);
}

.ott-highlights-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(1.1rem, 2.5vw, 1.75rem);
}

@media (max-width: 900px) {
  .ott-highlights-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 520px) {
  .ott-highlights-grid {
    grid-template-columns: 1fr;
  }
}
.ott-icon-badge {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--c-accent-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.75rem;
}

.ott-icon-badge svg {
  width: 26px;
  height: 26px;
}

.ott-highlights-grid h3 {
  font-family: var(--f-body);
  text-transform: none;
  letter-spacing: 0;
  font-size: 1.25rem;
  color: var(--c-primary);
}

.ott-highlights-grid p {
  font-size: 0.88rem;
  opacity: 0.85;
  max-width: 32ch;
}

.ott-footer {
  background: var(--c-primary-dark);
  color: var(--c-border);
  padding-block: 3.5rem 1.75rem;
}

.ott-footer h2, .ott-footer h4 {
  color: var(--c-background);
}

.ott-footer-loc {
  font-family: var(--f-detail);
  color: var(--c-accent);
  font-size: 0.85rem;
  margin-top: 0.75rem;
  display: block;
}

.ott-footer h4 {
  font-family: var(--f-detail);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--c-accent);
  margin-bottom: 0.9rem;
}

.ott-footer ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.ott-footer a {
  text-decoration: none;
  color: var(--c-border);
  font-size: 0.9rem;
}

.ott-footer a:hover {
  color: var(--c-background);
}

.ott-ticket-stub {
  border: 2px dashed rgba(241, 230, 201, 0.28);
  border-radius: 8px;
  padding: 1.25rem 1.5rem;
  margin-block: 0 2rem;
}

.ott-ticket-stub form {
  display: flex;
  align-items: stretch;
  gap: 0.75rem;
}

.ott-ticket-stub input {
  background: transparent;
  border: 1px solid var(--c-border);
  border-radius: 4px;
  color: var(--c-background);
  padding: 0.7em 1em;
  font-family: var(--f-body);
  font-size: 0.9rem;
  min-width: 200px;
}

.ott-ticket-stub input::placeholder {
  color: var(--c-border);
}

.ott-footer-bottom {
  border-top: 1px solid rgba(241, 230, 201, 0.28);
  margin-top: 1.5rem;
  padding-top: 1.25rem;
  font-family: var(--f-detail);
  font-size: 0.72rem;
}
