/* ==========================================================================
   ttce — site.css
   To The Ceiling Entertainment. Single stylesheet; every value below is a
   named token from THEME_BUILD_BRIEF §2, used by reference, never repeated.
   Phase 2: tokens, base, focus, skip link, buttons, header, footer, motion.
   Phase 3 adds the hero, shows, and About bands on top of these tokens.
   ========================================================================== */

/* ---------- Tokens ---------- */
:root {
  /* colour — §2.2 (--panel and --text-mute deliberately not implemented) */
  --black: #000000;
  --off: #0A0A0A;
  --yellow: #FFD800;
  --yellow-hover: #FFE34D;
  --white: #FFFFFF;
  --text-dim: #D8D8D8;
  --text-dim-2: #D0D0D0;
  --grey: #A6A6A6;
  --rule: rgba(255, 255, 255, 0.14);
  --glow-yellow: rgba(255, 216, 0, 0.28);
  --glow-button: rgba(255, 216, 0, 0.45);
  --beam: linear-gradient(180deg, rgba(255, 216, 0, 0.22) 0%,
                          rgba(255, 216, 0, 0.05) 46%,
                          rgba(255, 216, 0, 0) 78%);
  /* Owner ruling 2026-08-22: the exemplar's 0.55/0.25 stops buried the
     theatre entrance; lifted to 0.35/0.15. Phase 9 (tonal balance):
     the ramp to black used to run from 45% to 100%, which put the
     scrim's darkest part exactly over the arch, box office and doors.
     The 0.15 hold now runs to 82% and the blend into the page's black
     ground is compressed into the last 18% of the band. */
  --hero-scrim: linear-gradient(180deg, rgba(0, 0, 0, 0.35) 0%,
                                rgba(0, 0, 0, 0.15) 40%,
                                rgba(0, 0, 0, 0.15) 82%,
                                #000 100%);
  /* C-8 underlay behind the copy. Phase 9 deepened it 0.5 -> 0.56 so
     the heading holds 7:1 over the lifted photograph (measured worst
     pixel sRGB 74 -> 65 behind the heading at 1280/1600). */
  --scrim-floor: rgba(0, 0, 0, 0.56);
  /* Phase 9: shadows opened, highlights held. contrast() runs BEFORE
     brightness() so black lifts to sRGB 0.25 x 0.9 = 57 while clipped
     white lands at 0.75 x 0.9 = 173, about where 55% alone put it
     (140). The marquee's peak stays far from clipping (measured sRGB
     ~122 after the scrim); the arch, box office and frontage come up
     out of black. Source histogram is p50 0.013 / p99 1.0: the night
     photograph has no highlight headroom, so brightness alone could
     not do this. */
  --hero-photo-contrast: 0.5;
  --hero-photo-brightness: 90%;

  /* Ticket calendar frame height before any script runs (Phase 5-R1
     ruling): a compact, deliberate panel — VBO's plugin is itself a
     JS app, so a no-JS visitor sees a blank frame at ANY height and a
     tall baseline is only a void. embed-resize.js sets the expected
     height from measured breakpoints on parse, then VBO's message
     refines it. One value at every width; 600px equals the script's
     clamp floor, so CSS min-height and the clamp agree. */
  --tix-frame-h: 600px;

  /* type — §2.1 */
  --font: "Chivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --size-base: 17px;
  --leading-base: 1.6;
  --weight-base: 300;
  --size-display-hero: clamp(42px, 8.2vw, 100px);
  --size-display-hero-sub: 0.42em;           /* of the hero size */
  --size-display-section: clamp(30px, 4.6vw, 52px);
  --size-kicker: 12px;
  --size-lede: clamp(17px, 1.6vw, 19px);
  --size-hero-body: clamp(17px, 1.9vw, 20px);
  --size-greeting: clamp(19px, 2.2vw, 24px);
  --size-button: 15px;
  --size-button-sm: 13px;
  --size-nav-link: 14px;
  --size-footer-heading: 11px;
  --size-footer-item: 15px;
  --size-legal: 11px;

  /* measure caps */
  --measure-lede: 62ch;
  --measure-hero-body: 52ch;
  --measure-prose: 60ch;
  --measure-hero-heading: 15ch;

  /* spacing and layout — §2.3 */
  --max: 1120px;
  --gutter: 28px;
  --nav-h: 84px;
  --hero-pad-top: 112px;
  --hero-pad-bottom: 88px;
  --shows-pad-top: 84px;
  --shows-pad-bottom: 96px;
  --who-pad: 92px;
  --footer-pad-top: 60px;
  --footer-pad-bottom: 32px;
  --footer-legal-above: 42px;
  --footer-legal-below: 22px;
  --who-gap: 60px;
  --footer-gap: 48px;
  --radius-button: 40px;
  --radius-panel: 4px;
  --hairline: 1px solid var(--rule);
  --shows-rule: 2px solid var(--yellow);

  /* stack rhythm — the 2px-based ramp, named */
  --s-1: 6px;
  --s-2: 8px;
  --s-3: 10px;
  --s-4: 14px;
  --s-5: 16px;
  --s-6: 18px;
  --s-7: 22px;
  --s-8: 26px;
  --s-9: 34px;

  /* motion — §2.5 */
  --ease: 0.18s;

  /* focus — §2.6 */
  --focus-ring: 3px;
  --focus-offset: 3px;
}

/* ---------- Font (self-hosted, C-2) ---------- */
@font-face {
  font-family: "Chivo";
  src: url(/assets/fonts/chivo-variable-latin.499c79a165.woff2) format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ---------- Base ---------- */
* { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
  background: var(--black);
  color: var(--white);
  font-family: var(--font);
  font-size: var(--size-base);
  line-height: var(--leading-base);
  font-weight: var(--weight-base);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img, picture { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
ul { list-style: none; }
.wrap { max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter); }

/* ---------- Focus (visible everywhere, contractual) ---------- */
:focus-visible {
  outline: var(--focus-ring) solid var(--yellow);
  outline-offset: var(--focus-offset);
}
/* Buttons: a contrasting INNER ring — declared in the button section,
   after :hover, so focus always wins the cascade (see V-6 below). */

/* Fragment targets: the sticky header is --nav-h tall, so a plain
   jump parks the section's top edge under it. scroll-margin-top keeps
   every in-page landing (header links, hero buttons, footer links,
   the skip link) clear of the bar — instant jumps included. */
#main, #shows, #who { scroll-margin-top: var(--nav-h); }
/* main is the skip link's target (tabindex=-1): focusable, not
   interactive — no ring around the whole page body. */
#main:focus, #main:focus-visible { outline: none; }

/* ---------- Skip link (C-4) ---------- */
.skip {
  position: absolute;
  left: var(--gutter);
  top: -200px;
  z-index: 100;
  padding: var(--s-3) var(--s-6);
  background: var(--yellow);
  color: var(--black);
  font-size: var(--size-nav-link);
  font-weight: 800;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  border-radius: var(--radius-button);
}
.skip:focus { top: var(--s-4); }

/* ---------- Type tokens as classes ---------- */
.kicker {
  display: block;
  font-size: var(--size-kicker);
  font-weight: 800;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--yellow);
}
.lede {
  color: var(--text-dim);
  font-size: var(--size-lede);
  line-height: var(--leading-base);
  max-width: var(--measure-lede);
}

/* ---------- Buttons (V-6) ---------- */
.btn {
  display: inline-block;
  background: var(--yellow);
  color: var(--black);
  border: 2px solid var(--yellow);
  border-radius: var(--radius-button);
  padding: 0.72em 1.5em;
  font-size: var(--size-button);
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.2;
  cursor: pointer;
  transition: background var(--ease), box-shadow var(--ease), transform var(--ease);
}
.btn:hover {
  background: var(--yellow-hover);
  border-color: var(--yellow-hover);
  box-shadow: 0 0 22px var(--glow-button);
  color: var(--black);
}
.btn:active { transform: translateY(1px); }
.btn-ghost { background: transparent; color: var(--yellow); }
.btn-ghost:hover { background: var(--yellow-hover); color: var(--black); }
.btn-sm { padding: 0.6em 1.2em; font-size: var(--size-button-sm); }
/* Focus on buttons: the offset yellow outline vanishes into a yellow
   fill plus its hover glow, so the ring is a contrasting INNER band —
   black, hugging the edge — with the yellow ring outside it, and the
   hover glow kept as a third layer. Declared after :hover at equal
   specificity so hover can never replace it (the exemplar's failure). */
.btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 var(--focus-ring) var(--black),
              0 0 0 calc(var(--focus-ring) * 2) var(--yellow),
              0 0 22px var(--glow-button);
}

/* ---------- Header / sticky nav bar (V-1) ---------- */
.site-head {
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(0, 0, 0, 0.9);
  backdrop-filter: blur(10px);
  border-bottom: var(--hairline);
}
.nav-in {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--nav-h);
  gap: var(--s-7);
}
.nav-logo img { height: 56px; width: auto; }
.nav-links { display: flex; align-items: center; gap: 28px; }
.nav-list { display: flex; align-items: center; gap: 28px; }
.nav-list a,
.nav-disclosure summary {
  font-size: var(--size-nav-link);
  font-weight: 800;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--white);
  transition: color var(--ease);
}
.nav-list a:hover,
.nav-disclosure summary:hover { color: var(--yellow); }
/* The disclosure control exists at every width in the markup; it shows
   only when the inline list collapses (≤940px, C-4). No JavaScript:
   summary/details is native. */
.nav-disclosure { display: none; position: relative; }
.nav-disclosure summary {
  list-style: none;
  cursor: pointer;
  padding: var(--s-2) 0;
}
.nav-disclosure summary::-webkit-details-marker { display: none; }
.nav-disclosure summary::after { content: " \25BE"; }
.nav-disclosure[open] summary::after { content: " \25B4"; }

/* ---------- Footer (V-9) ---------- */
.site-foot {
  border-top: var(--hairline);
  padding: var(--footer-pad-top) 0 var(--footer-pad-bottom);
}
.f-grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr 1fr;
  gap: var(--footer-gap);
  padding-bottom: var(--footer-legal-above);
}
.f-logo img { height: 72px; width: auto; margin-bottom: var(--s-4); }
.f-h {
  font-size: var(--size-footer-heading);
  font-weight: 800;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  color: var(--yellow);
  margin-bottom: var(--s-4);
}
.f-grid a, .f-grid p, .f-grid address {
  display: block;
  color: var(--grey);
  font-size: var(--size-footer-item);
  font-style: normal;
  margin-bottom: var(--s-2);
  transition: color var(--ease);
}
.f-grid a:hover { color: var(--yellow); }
.f-bar {
  border-top: var(--hairline);
  padding-top: var(--footer-legal-below);
  display: flex;
  justify-content: space-between;
  gap: var(--s-5);
  flex-wrap: wrap;
}
/* C-6: the legal bar uses --grey (≈8.6:1), not the exemplar's #666 */
.f-bar span, .f-bar a {
  font-size: var(--size-legal);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--grey);
  transition: color var(--ease);
}
.f-bar a:hover { color: var(--yellow); }

/* ---------- Hero band (V-2) ---------- */
.hero { position: relative; overflow: hidden; background: var(--black); }
.hero-media { position: absolute; inset: 0; z-index: 0; }
.hero-media picture, .hero-media img { width: 100%; height: 100%; }
/* The theme's treatment of whatever is uploaded: darkened, full
   greyscale, object-position from the design's vertical framing.
   Owner ruling 2026-08-22: lifted from the exemplar's 28% so the
   theatre entrance reads; C-8 still holds (measured, see commit). */
.hero-media img {
  object-fit: cover;
  object-position: center 30%;
  filter: contrast(var(--hero-photo-contrast))
          brightness(var(--hero-photo-brightness))
          grayscale(100%);
}
.hero-media::after { content: ""; position: absolute; inset: 0; background: var(--hero-scrim); }
.beam {
  position: absolute;
  top: -14%;
  z-index: 1;
  pointer-events: none;
  width: 46vw;
  height: 118%;
  opacity: 0.5;
  background: var(--beam);
}
.beam-l { left: 2%; transform: skewX(15deg); }
.beam-r { right: 2%; transform: skewX(-15deg); }
.hero-in {
  position: relative;
  z-index: 2;
  padding: var(--hero-pad-top) 0 var(--hero-pad-bottom);
  text-align: center;
}
/* C-8: the deterministic scrim floor. A feathered solid-black underlay
   behind the heading block, flat across the text and fading only
   outside it. The brightness filter already caps any upload at sRGB 71
   behind the heading (≈6.8:1 for --yellow); the floor takes the
   theoretical worst case lower still so the pass is a guarantee of the
   design, not a property of the current photograph. */
.hero-copy { position: relative; }
/* Owner note 2026-08-22: the floor must never read as a shape. It is
   a FULL-WIDTH vertical band — the same family as the scrim above it —
   feathered top and bottom, so there is no lateral edge to see; the
   photo stays continuous across the hero. */
.hero-copy::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: -12%;
  bottom: -18%;
  left: 50%;
  /* Phase 9: wider than the viewport. At exactly 100vw the band's
     anti-aliased left edge fell inside the viewport on phones and that
     one pixel column carried only half the floor (measured alpha 0.39
     against 0.78); the heading's worst pixel lived there. Overhanging
     both sides leaves no lateral edge anywhere, which is the rule. */
  width: 120vw;
  transform: translateX(-50%);
  pointer-events: none;
  /* flat from the copy's top edge down (the marquee above it stays
     untouched); feathered only where nothing needs the guarantee */
  background: linear-gradient(180deg,
                              rgba(0, 0, 0, 0) 0%,
                              var(--scrim-floor) 10%,
                              var(--scrim-floor) 85%,
                              rgba(0, 0, 0, 0) 100%);
}
.hero h1 {
  font-size: var(--size-display-hero);
  line-height: 0.86;
  font-weight: 900;
  letter-spacing: -0.015em;
  text-transform: uppercase;
  color: var(--yellow);
  text-shadow: 0 0 26px var(--glow-yellow);
  margin: var(--s-6) auto 0;
  max-width: var(--measure-hero-heading);
}
.hero h1 .sub {
  display: block;
  color: var(--white);
  font-size: var(--size-display-hero-sub);
  line-height: 1.05;
  letter-spacing: 0.005em;
  margin-top: 0.55em;
  text-shadow: none;
}
.hero-lede {
  color: var(--text-dim);
  font-size: var(--size-hero-body);
  max-width: var(--measure-hero-body);
  margin: var(--s-8) auto 0;
}
.hero-cta {
  display: flex;
  gap: var(--s-4);
  justify-content: center;
  flex-wrap: wrap;
  margin-top: var(--s-9);
}

/* ---------- Shows band (V-3 / V-4 / V-11) ---------- */
.shows { padding: var(--shows-pad-top) 0 var(--shows-pad-bottom); }
.shows-head {
  border-bottom: var(--shows-rule);
  padding-bottom: var(--s-6);
  margin-bottom: var(--s-8);
}
/* C-7: the h2 wears the kicker treatment unchanged — .kicker sets
   size, weight, tracking, transform and colour; nothing else applies. */
.shows-head .lede { margin-top: var(--s-1); max-width: var(--measure-hero-body); }
.tix-panel {
  border: var(--hairline);
  background: var(--off);
  border-radius: var(--radius-panel);
  overflow: hidden;
}
/* Unpopulated embed slot (G-1): the panel has nothing to frame, so it
   steps out and the section head stands alone — deliberate, not a
   collapsed box or a broken frame. */
.tix-panel:empty { display: none; }
/* The platform's own frame and fallback link live inside; the theme
   styles the panel (and the platform's restylable aspect container)
   only. No-JS height baseline for the ticket calendar: the platform's
   default 16/9 box is built for video; a ticket list wants the full
   screen below the header — capped so it is never a wall, floored so
   it is never a letterbox. True fit-to-content needs the platform's
   auto-height enhancement (owner decision, platform-side). */
.tix-panel .forge-embed-frame {
  aspect-ratio: auto;
  min-height: 600px;                    /* = the script's clamp floor (MIN 600) */
  height: var(--tix-frame-h);
}
.tix-panel .forge-embed-fallback { padding: var(--s-5) var(--s-6); }
.tix-panel .forge-embed-fallback a { color: var(--yellow); }
/* Declared AFTER the everyday fallback-link rules above at equal
   specificity, so the no-JS CTA wins the cascade (colour included). */
/* No-JS visitor (scripting: none — Chrome/Edge 120+, Firefox 113+,
   Safari 17+): VBO's plugin cannot run, so the blank frame goes and
   the panel carries the platform's fallback link as the primary call
   to action — the hero's solid pill, the accepted focus treatment.
   Browsers without the feature ignore this block and keep the compact
   600px panel with the plain link: unstyled, never broken. The link's
   text and href are the platform's (C-11 open) — styled only. */
@media (scripting: none) {
  .tix-panel .forge-embed-frame { display: none; }
  .tix-panel .forge-embed-fallback { padding: var(--s-8) var(--s-6); margin-top: 0; }
  .tix-panel .forge-embed-fallback a {
    display: inline-block;
    background: var(--yellow);
    color: var(--black);
    border: 2px solid var(--yellow);
    border-radius: var(--radius-button);
    padding: 0.72em 1.5em;
    font-size: var(--size-button);
    font-weight: 800;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    line-height: 1.2;
    transition: background var(--ease), box-shadow var(--ease), transform var(--ease);
  }
  .tix-panel .forge-embed-fallback a:hover {
    background: var(--yellow-hover);
    border-color: var(--yellow-hover);
    box-shadow: 0 0 22px var(--glow-button);
  }
  .tix-panel .forge-embed-fallback a:active { transform: translateY(1px); }
  .tix-panel .forge-embed-fallback a:focus-visible {
    outline: none;
    box-shadow: 0 0 0 var(--focus-ring) var(--black),
                0 0 0 calc(var(--focus-ring) * 2) var(--yellow),
                0 0 22px var(--glow-button);
  }
}
/* The platform's iframe is in the tab order; the theme styles the
   panel, never the frame — so the PANEL wears the focus ring while
   the frame inside it holds focus. */
.tix-panel:has(iframe:focus-visible) {
  outline: var(--focus-ring) solid var(--yellow);
  outline-offset: var(--focus-offset);
}

/* ---------- About band (V-5) ---------- */
.who {
  border-top: var(--hairline);
  background: var(--off);
  padding: var(--who-pad) 0;
}
.who-in {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: var(--who-gap);
  align-items: center;
}
.who-photo img {
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  filter: grayscale(100%) contrast(108%);
  border: var(--hairline);
}
.sec {
  font-size: var(--size-display-section);
  font-weight: 900;
  text-transform: uppercase;
  line-height: 0.92;
  letter-spacing: -0.01em;
  margin: var(--s-4) 0 var(--s-5);
}
.sec em { font-style: normal; color: var(--yellow); }
.hey {
  font-size: var(--size-greeting);
  font-weight: 700;
  color: var(--white);
  margin-bottom: var(--s-6);
}
.who-body p {
  color: var(--text-dim-2);
  margin-bottom: var(--s-5);
  max-width: var(--measure-prose);
}
.who-body strong { color: var(--yellow); font-weight: 800; }
.who-copy .btn { margin-top: var(--s-3); }

/* ---------- Breakpoints — §2.4 ---------- */
@media (max-width: 940px) {
  :root { --who-gap: 38px; }
  .who-in { grid-template-columns: 1fr; }
  .who-photo { max-width: 400px; }
  /* C-4: the inline links collapse into the disclosure; the ticket
     button stays in the bar at every width. */
  .nav-links > .nav-list { display: none; }
  .nav-disclosure { display: block; }
  .nav-disclosure .nav-list {
    position: absolute;
    right: 0;
    top: calc(100% + var(--s-2));
    min-width: 12rem;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    background: rgba(0, 0, 0, 0.96);
    border: var(--hairline);
    border-radius: var(--radius-panel);
    padding: var(--s-2) 0;
  }
  .nav-disclosure .nav-list a { display: block; padding: var(--s-3) var(--s-6); }
  .f-grid { grid-template-columns: 1fr 1fr; }

  /* Touch targets (Phase 8 audit, ≤940 only — desktop untouched):
     every tappable element is at least 44 CSS px tall, stacked
     targets sit on a ≥44px pitch. Measured shortfalls: summary 38px,
     revealed links 42px, ticket button 35px, footer links 24px, legal
     link 18px, fallback link 17px. */
  .nav-disclosure summary { display: flex; align-items: center; min-height: 44px; padding: 0 var(--s-2); }
  .nav-disclosure .nav-list a { display: flex; align-items: center; min-height: 44px; }
  .btn { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; }
  .f-grid a { display: flex; align-items: center; min-height: 44px; margin-bottom: 0; }
  .f-bar a { display: inline-flex; align-items: center; min-height: 44px; }
  .tix-panel .forge-embed-fallback a { display: inline-flex; align-items: center; min-height: 44px; }
}
@media (max-width: 720px) {
  :root {
    /* C-8 on phones: the cover crop puts the marquee's brightest neon
       directly behind the heading, so the floor (still a full-width
       band, never a shape) goes deeper than desktop. Phase 9-R1: 0.78
       was tuned against the old 55% photograph and an anti-aliased
       band edge that no longer exists; swept 0.78 -> 0.30 at 320, 375,
       393, 412. Lowest value holding the heading at 7:1 everywhere is
       0.58 (7.48); 0.62 is one step of margin above it (8.19 to 8.30,
       lede 8.01 to 8.61), and it lets the arch and doors show. */
    --scrim-floor: rgba(0, 0, 0, 0.62);
    --gutter: 18px;
    --hero-pad-top: 72px;
    --hero-pad-bottom: 60px;
    --shows-pad-top: 60px;
    --shows-pad-bottom: 72px;
    --footer-gap: 34px;
  }
  .f-grid { grid-template-columns: 1fr; }
  .beam { width: 66vw; opacity: 0.42; }
}

/* ---------- Reduced motion — §2.5, the exemplar's block, kept ---------- */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; scroll-behavior: auto !important; }
  html { scroll-behavior: auto; }
}
