/* `hidden` has to win over the display values set below, and over site.css.
   Without this the flex/block rules beat the UA's [hidden] { display: none }
   and every collapsed row (discount line, code input, card form, success card)
   renders at once. */
[hidden] { display: none !important; }

/* Only what the ticket pages add on top of the copied site.css. Everything structural (bands, wraps, type scale, buttons, pills) comes from the design system, so this file stays small and the page reads as a native part of www.fitbeatfitness.com. */

/* ---------- event page ----------
   Mobile first throughout: one column, big tap targets, the ticket picker directly
   after the hero. Most buyers are on a phone, and the desktop rules below are the
   exception rather than the base case. */

.hero__cta { margin-top: 1.4rem; }

/* What it costs from, and until when, under the proof line and above the button. The
   same quiet mono the eyebrows use, so it reads as a fact about the day rather than a
   second headline. */
.hero__from {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .55rem;
  margin: 1rem 0 0;
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--snow);
}
.hero__from .dot {
  width: 3px; height: 3px; border-radius: 50%;
  background: currentColor; opacity: .55;
}

.tk-prose { max-width: 62ch; }
.tk-prose p { color: var(--slate); }

.tk-sub {
  font-family: var(--mono);
  font-size: .74rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--slate);
  margin: 1.6rem 0 .8rem;
}

.tk-facts {
  display: grid;
  gap: 0;
  margin-top: clamp(1.6rem, 3vw, 2.4rem);
  border-top: 1px solid var(--line);
  max-width: 62ch;
}
.tk-facts > div {
  display: grid;
  grid-template-columns: 1fr;
  gap: .2rem;
  padding: .85rem 0;
  border-bottom: 1px solid var(--line);
}
@media (min-width: 620px) {
  .tk-facts > div { grid-template-columns: 9.5rem minmax(0, 1fr); gap: 1rem; }
}
.tk-facts dt {
  font-family: var(--mono);
  font-size: .72rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--slate);
  padding-top: .2rem;
}
.tk-facts dd { font-weight: 500; }
.tk-facts dd .fine { display: block; font-weight: 400; }

/* ---------- the checkout card: the page's focal point ---------- */

.tk-card {
  background: var(--bone-2);
  border: 1px solid var(--line);
  border-top: 3px solid var(--pulse-mid);
  border-radius: 6px;
  padding: clamp(1.3rem, 2.4vw, 1.8rem);
  box-shadow: var(--shadow-2);
  isolation: isolate;
}
.tk-card .eyebrow { margin-bottom: .55rem; }
.tk-card .price { margin-bottom: .35rem; }
.tk-card .price__v { font-size: clamp(2.3rem, 4vw, 3rem); }

/* ---------- the ticket picker ---------- */

.tk-types { display: grid; gap: .8rem; }

.tk-type {
  border: 1px solid var(--line);
  border-radius: 5px;
  background: var(--bone);
  padding: .95rem 1rem 1rem;
}
/* A row outside its window is dimmed by dimming its own colours, not with opacity
   on the whole row. Opacity took "Releasing 16 September", which is a selling line,
   down to about 2.8:1 against the card; the label below stays at full ink. */
.tk-type--off { background: transparent; }
.tk-type--off .tk-type__name,
.tk-type--off .tk-type__amount { color: var(--slate); }
.tk-type--off .tk-value__viz b { color: var(--slate); }
.tk-type--off .tk-value__viz s { opacity: 1; }
.tk-type--child { background: transparent; }

/* Under ~600px the head stacks: title (with its badge), then price and tier line,
   then the blurb across the full width. Above it, the price goes back into a right
   hand column beside the title and the blurb. The left column is minmax(0, 1fr) so
   it can actually shrink: without that, "Child, Food + Admission (6 to 15)" wrapped
   to four lines beside a price column claiming half the row. */
.tk-type__head { display: grid; gap: .35rem .9rem; }
@media (min-width: 600px) {
  .tk-type__head { grid-template-columns: minmax(0, 1fr) auto; align-items: start; }
  .tk-type__head .tk-type__name { grid-column: 1; grid-row: 1; }
  .tk-type__head .tk-type__price { grid-column: 2; grid-row: 1 / span 2; }
  .tk-type__head .tk-type__blurb { grid-column: 1; grid-row: 2; }
}
.tk-type__name { margin: 0; font-size: 1.05rem; line-height: 1.25; font-weight: 700; min-width: 0; }
.tk-type__blurb { margin: .1rem 0 0; font-size: .88rem; color: var(--slate); max-width: 44ch; }
.tk-type__note { margin: .6rem 0 0; font-size: .82rem; color: var(--slate); }
.tk-type__price {
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .1rem .5rem;
}
@media (min-width: 600px) {
  .tk-type__price { display: block; text-align: right; }
}
.tk-type__amount {
  font-family: var(--display);
  font-weight: 800;
  font-size: 1.5rem;
  letter-spacing: -.02em;
  line-height: 1.1;
}
@media (min-width: 600px) {
  .tk-type__amount { display: block; }
  .tk-type__price .fine { display: block; max-width: 11rem; }
}
.tk-type__hint { margin: .6rem 0 0; font-size: .82rem; color: var(--pulse-deep); font-weight: 500; }

.tk-badge {
  display: inline-block;
  vertical-align: middle;
  margin-left: .4rem;
  padding: .2rem .5rem;
  border-radius: 999px;
  background: var(--pulse-mid, #56c7e8);
  color: var(--ink);
  font-family: var(--mono);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* The value line the brief asked to make visual: the menu price struck through,
   the ticket price beside it, then Rory's sentence. */
.tk-value {
  margin: .7rem 0 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .5rem;
  font-size: .88rem;
  color: var(--slate);
}
.tk-value__viz { font-size: 1.05rem; }
.tk-value__viz s { color: var(--slate); opacity: .7; }
.tk-value__viz b { color: var(--pulse-deep); font-size: 1.25rem; }

.tk-type__foot {
  margin-top: .9rem;
  padding-top: .8rem;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .6rem 1rem;
}

/* The stepper is the only control in the picker, and it had no styling at all:
   raw user-agent buttons at 24x21. 44px minimum each way, which is the tap target
   everything else on this page is built to. */
.stepper { display: flex; align-items: center; gap: .35rem; flex: none; margin-left: auto; }
.stepper button {
  width: 44px; height: 44px;
  min-width: 44px; min-height: 44px;
  display: grid; place-items: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bone-2);
  color: var(--ink);
  font-family: var(--body);
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  transition: background-color .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease);
}
.stepper button:hover:not(:disabled) { background: var(--bone); border-color: var(--accent-gfx); }
.stepper button:disabled {
  cursor: default;
  background: transparent;
  border-color: var(--line);
  color: var(--slate);
  opacity: .55;
}
.tk-qty {
  min-width: 3rem;
  height: 44px;
  display: grid;
  place-items: center;
  font-family: var(--mono);
  font-size: 1.15rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* The counter is the urgency driver, so it is the loudest thing in the row: a
   filled pill with the number set large, not a line of small caps. */
.tk-left {
  font-family: var(--mono);
  font-size: .82rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--pulse-deep);
  min-width: 0;
}
.tk-left--pill {
  display: inline-flex;
  align-items: baseline;
  gap: .3rem;
  padding: .3rem .7rem .34rem;
  border-radius: 999px;
  background: var(--ink);
  color: var(--snow, #f2f7fa);
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .04em;
  text-transform: none;
}
.tk-left__n {
  font-family: var(--display);
  font-weight: 800;
  font-size: 1.3rem;
  letter-spacing: -.02em;
  line-height: 1;
}
/* Under ten left, the pill goes red rather than just the text: it is the last
   thing anyone reads before deciding. */
.tk-left--low { background: #9a2617; color: #fff; }

/* A child row draws on the adult row's allocation, so a second identical counter
   would be a lie about how much is left. It says whose pool it shares instead. */
.tk-left--shares {
  font-family: var(--body);
  font-size: .82rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--slate);
}
/* Kept at full ink: "Releasing 16 September" is a selling line, and it is the only
   thing telling a buyer when to come back. */
.tk-left--off {
  font-family: var(--body);
  color: var(--ink);
  font-weight: 600;
  font-size: .86rem;
  text-transform: none;
  letter-spacing: 0;
}

.tk-group {
  margin: 1rem 0 0;
  font-size: .9rem;
  font-weight: 500;
  color: var(--pulse-deep);
}

/* ---------- the add-on picker ---------- */

/* Each counter is now beside the thing it counts: the places on the ticket rows, the
   lunches on the lunch toggle. A counter inside the toggle sits on the label's own
   line, after the price, so the tick reads as one sentence. */
.tk-type--party.tk-type--child { background: transparent; }
.tk-lunch__lead .tk-left { margin-left: .1rem; }

/* The toggle itself: a checkbox row inside the attendee card, one per person, with
   what lunch costs them set beside the label rather than under it. It reads as part
   of that person's details, so it is indented against the card's own edge. */
.tk-lunch {
  align-items: center;
  margin: .2rem 0 .9rem;
  padding: .7rem .8rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--pulse-mid);
  border-radius: 5px;
  background: var(--bone-2);
}
.tk-lunch input { margin-top: 0; }
.tk-lunch__text { display: grid; gap: .15rem; min-width: 0; }
.tk-lunch__lead { display: flex; flex-wrap: wrap; align-items: baseline; gap: .45rem; }
.tk-lunch__was { color: var(--slate); font-weight: 400; }
.tk-lunch__delta {
  font-family: var(--mono);
  font-size: .84rem;
  font-weight: 700;
  letter-spacing: .02em;
  color: var(--pulse-deep);
  white-space: nowrap;
}
.tk-lunch__why { color: var(--slate); }
/* Locked by the schedule rather than by the buyer. The box is disabled, so the row
   says why at full ink instead of greying the sentence that explains it. */
.tk-lunch--locked { border-left-color: var(--line); background: transparent; }
.tk-lunch--locked .tk-lunch__why { color: var(--ink); font-weight: 500; }

/* ---------- attendees ---------- */

.tk-attendee {
  margin-top: .8rem;
  padding: .9rem 1rem 1rem;
  border: 1px solid var(--line);
  border-radius: 5px;
  background: var(--bone);
}
.tk-attendee__head {
  margin: 0 0 .7rem;
  display: flex;
  gap: .6rem;
  align-items: baseline;
  justify-content: space-between;
}
/* "Ticket 3" must never break across two lines; the ticket type beside it is the
   long half and is the one allowed to wrap. */
.tk-attendee__head b {
  font-family: var(--mono);
  font-size: .74rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  white-space: nowrap;
  flex: none;
}
.tk-attendee__head span { font-size: .86rem; color: var(--slate); text-align: right; min-width: 0; }

/* ---------- step one on a desktop (add-on picker only) ----------
   The add-on picker asks two questions with two answers each: how many adults and how
   many children, then who every one of them is. On a phone that is one column and
   stays one column. From 900px it is a waste of the page to run two ticket rows and
   six or eight attendee blocks down a single narrow strip, so both become two up.
   Every selector here is behind a class the classic picker never gets, or behind the
   picker's own data attribute, so the live page is untouched by all of it.

   The wrap this lives in is wider too, but only for step one: `tk-wrap-checkout` hands
   the narrow measure straight back to step two, the confirmation, the pending card and
   the fine print, which are the same width they have always been. */
.tk-wrap-checkout > .tk-pay,
.tk-wrap-checkout > .tk-done,
.tk-wrap-checkout > .tk-pending,
.tk-wrap-checkout > .tk-fineprint {
  max-width: min(100%, calc(820px - 2 * var(--gut)));
  margin-inline: auto;
}
/* Below the two-column breakpoint step one has nothing to spend the extra width on
   either, so it keeps the narrow measure with everything else. */
@media (max-width: 899px) {
  .tk-wrap-checkout > #checkout-card {
    max-width: min(100%, calc(820px - 2 * var(--gut)));
    margin-inline: auto;
  }
}

@media (min-width: 900px) {
  .tk-types--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }

  /* The heading and the closing line are about the whole list, so they span it; the
     blocks themselves lose the stacked margin the single column gave them and take
     the grid's gap instead. The two in a row stretch to match rather than sitting at
     their own heights: one of a pair carries an age field or the gluten warning and
     the other does not, and left to themselves they leave a hole in the column. */
  .tk-attendees--pair {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1rem;
    align-items: stretch;
  }
  .tk-attendees--pair > .tk-sub,
  .tk-attendees--pair > .fine { grid-column: 1 / -1; }
  .tk-attendees--pair > .tk-attendee { margin-top: 0; }

  /* Two fields is a row, not a column, once there is room for it. The two consent
     boxes are sentences and stay across the pair. */
  .tk-checkout[data-picker="addon"] .tk-buyer {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 1rem;
    align-items: start;
  }
  .tk-checkout[data-picker="addon"] .tk-buyer > .tk-sub,
  .tk-checkout[data-picker="addon"] .tk-buyer > .tk-check { grid-column: 1 / -1; }

  /* A block button across the whole of a wide card is a target nobody was aiming at.
     It keeps a button's measure and sits under the middle of the form. display: flex
     rather than the button's own inline-flex, because an inline box cannot be centred
     by its own auto margins. */
  .tk-checkout[data-picker="addon"] #continue {
    display: flex;
    max-width: 26rem;
    margin-inline: auto;
  }
}

.tk-warn {
  margin: .2rem 0 .9rem;
  padding: .7rem .8rem;
  border-left: 3px solid #9a2617;
  background: rgba(154, 38, 23, .06);
  font-size: .85rem;
  color: var(--ink);
}

.tk-check {
  display: flex;
  gap: .6rem;
  align-items: flex-start;
  margin: .8rem 0;
  font-size: .9rem;
  line-height: 1.5;
}
.tk-check input { margin-top: .25rem; width: 1.15rem; height: 1.15rem; flex: none; }

/* ---------- step two: paying ---------- */

.tk-summary { list-style: none; margin: 0 0 1rem; padding: 0; display: grid; gap: .4rem; font-size: .95rem; }
.tk-summary li { display: flex; justify-content: space-between; gap: 1rem; }
.tk-summary__total {
  padding-top: .5rem;
  border-top: 1px solid var(--line);
  font-weight: 700;
  font-size: 1.05rem;
}

.tk-hold {
  margin: 0 0 1rem;
  padding: .6rem .8rem;
  border-radius: 4px;
  background: var(--bone);
  font-size: .9rem;
  text-align: center;
}
.tk-hold b { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* ---------- the floating buy bar ---------- */

/* One row: the date and the from-price on the left, the way to the picker on the
   right. Both facts are rendered server-side from the sale snapshot, so the bar can
   never quote a price the picker below it does not.

   checkout.js hides it while the hero or the picker is on screen and for the whole
   of step two, which is where it used to sit on top of Continue, the terms boxes
   and Back. With no JavaScript it just stays put, which is a working link. */
.tk-sticky {
  position: fixed;
  left: 1rem; right: 1rem; bottom: 1rem;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  padding: .4rem .4rem .4rem 1.1rem;
  border-radius: 999px;
  background: var(--ink);
  color: var(--snow, #f2f7fa);
  box-shadow: var(--shadow-2);
}
.tk-sticky[hidden] { display: none; }

.tk-sticky__facts {
  margin: 0;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: .5rem;
  font-size: .85rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}
.tk-sticky__facts span { overflow: hidden; text-overflow: ellipsis; }
.tk-sticky__facts .dot { flex: none; width: 4px; height: 4px; border-radius: 50%; background: var(--pulse); }

.tk-sticky__go { flex: none; min-height: 40px; padding: .5rem 1.15rem; font-size: .88rem; }

/* On a wide screen the bar is only worth its space where the picker is a long way
   down the page, which is the story flow. Everywhere else it stays a phone thing. */
@media (min-width: 860px) {
  .tk-sticky { display: none; }
  .tk-sticky--wide {
    display: flex;
    left: 50%; right: auto;
    transform: translateX(-50%);
    width: min(28rem, calc(100% - 3rem));
  }
  body:has(.tk-sticky--wide) .foot { padding-bottom: 6rem; }
}

/* The bar floats over the page, so the last thing on the page needs somewhere to
   go under it. */
@media (max-width: 859px) {
  .foot { padding-bottom: 6rem; }
}

/* ---------- run of day, highlights, terms, FAQ ---------- */


.tk-run { display: grid; gap: 0; border-top: 1px solid var(--line); margin-top: 1.6rem; }
.tk-run > div { display: grid; grid-template-columns: 4.5rem minmax(0, 1fr); gap: 1rem; padding: .7rem 0; border-bottom: 1px solid var(--line); }
.tk-run dt { font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 600; }
.tk-run dd { margin: 0; }

/* ---------- the day beside its schedule (story flow only) ----------
   One column on a phone: the prose reads first and the line follows it, which is the
   order the source is written in, so nothing here reorders anything. From 900px the
   pair splits into roughly three fifths of prose and two of schedule, with the gap
   opened up and the two blocks centred against each other so they read as a
   composition rather than as a panel dropped beside the text. The section takes a
   wrap between the narrow one every other section uses and the full width the photo
   grids take, because two columns inside 820px leaves neither of them enough. */
.wrap-day { width: 100%; max-width: 1060px; margin-inline: auto; padding-inline: var(--gut); }

.tk-day { display: grid; gap: clamp(1.8rem, 3.5vw, 3rem); align-items: start; }
@media (min-width: 900px) {
  .tk-day {
    grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
    column-gap: clamp(2.5rem, 5vw, 4.5rem);
    align-items: center;
  }
  /* The prose is capped at 62ch and the column is not, so the left half can leave a
     ragged edge in the middle. The schedule is pushed the other way, hard against the
     section's right edge, which is what makes the pair read as two columns. */
  .tk-day > .tk-line { justify-self: end; width: 100%; max-width: 24rem; }
}

/* ---------- the run of day as a route map (story flow only) ----------
   An ink band for the title, the same dark blue the nav is set on, and then the stops
   on the band's own background with no box around them: the card that used to be here
   read as something stuck onto the section rather than part of it. The rail is drawn
   per stop rather than once down the list, so it can stop at the first and last dots
   instead of running past them, and the segments abut into one continuous line. */
.tk-line {
  /* How far down a stop its dot sits, measured from the row's own top edge: the row's
     padding plus half a line of the text beside it. The rail is cut at this height on
     the two terminals and every dot is offset to it, so the line and its stations are
     positioned off one number and cannot drift apart. */
  --stop-pad: .5rem;
  --stop-dot: 1.26rem;
  --stop-rail: .85rem;
}
.tk-line__head {
  margin: 0;
  padding: .7rem 1.05rem .78rem;
  background: var(--ink);
  color: var(--snow, #f2f7fa);
}
.tk-line__stops {
  list-style: none;
  margin: 0;
  padding: 1.1rem 0 .3rem;
  display: grid;
  gap: 0;
}
.tk-line__stop {
  position: relative;
  display: grid;
  grid-template-columns: 1.7rem 3.4rem minmax(0, 1fr);
  align-items: start;
  gap: 0 .85rem;
  padding: var(--stop-pad) 0;
}
.tk-line__stop::before {
  content: '';
  position: absolute;
  left: calc(var(--stop-rail) - 1px);
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--pulse);
}
.tk-line__stop--first::before { top: var(--stop-dot); }
.tk-line__stop--last::before { bottom: auto; height: var(--stop-dot); }
.tk-line__dot {
  grid-column: 1;
  justify-self: center;
  align-self: start;
  position: relative;
  z-index: 1;
  width: .58rem;
  height: .58rem;
  margin-top: calc(var(--stop-dot) - var(--stop-pad) - .29rem - 2px);
  border: 2px solid var(--accent-gfx);
  border-radius: 50%;
  background: var(--bone-2);
}
/* The terminals are filled and a size larger, the way a route map marks the ends of
   a line, so the day looks like it starts and finishes somewhere. */
.tk-line__stop--first .tk-line__dot,
.tk-line__stop--last .tk-line__dot {
  width: .78rem;
  height: .78rem;
  margin-top: calc(var(--stop-dot) - var(--stop-pad) - .39rem - 2px);
  background: var(--accent-gfx);
}
.tk-line__time {
  grid-column: 2;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .08em;
  line-height: 1.75;
  color: var(--accent-txt);
}
.tk-line__what {
  grid-column: 3;
  font-size: .95rem;
  line-height: 1.45;
  padding-top: .07rem;
  min-width: 0;
}
.tk-line__note { margin: .5rem 0 0; padding-left: calc(1.7rem + .85rem); }


.tk-faq { margin-top: 1.6rem; max-width: 68ch; }
.tk-faq details { border-bottom: 1px solid var(--line); padding: .85rem 0; }
.tk-faq summary { cursor: pointer; font-weight: 600; list-style: none; }
.tk-faq summary::-webkit-details-marker { display: none; }
.tk-faq summary::after { content: '+'; float: right; font-family: var(--mono); color: var(--slate); }
.tk-faq details[open] summary::after { content: '\2212'; }
.tk-faq p { margin: .6rem 0 0; color: var(--slate); }
.tk-faq details[open] summary { margin-bottom: .1rem; }

/* The way out of the pending card, quiet under the reference. */
.tk-pending__out { margin-top: .9rem; }
.tk-pending__out .tk-textlink { display: inline; }

/* discount code: present but discreet until wanted */
.tk-code-row { padding-top: .9rem; }
.tk-code-input { display: flex; gap: .5rem; }
.tk-code-msg {
  margin: .55rem 0 0;
  font-size: .86rem;
  color: var(--pulse-deep);
  font-weight: 500;
}
.tk-code-msg--err { color: #9a2617; }

.tk-textlink {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: .88rem;
  color: var(--pulse-deep);
  text-decoration: underline;
  text-underline-offset: .18em;
  cursor: pointer;
}
.tk-textlink:hover { text-decoration-thickness: 2px; }
.tk-textlink--center { display: block; width: 100%; margin-top: .9rem; text-align: center; }

.tk-total { margin: 1.1rem 0 1.25rem; display: grid; gap: .4rem; }
.tk-total__line { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; }
.tk-total__line dt { font-size: .92rem; color: var(--slate); }
.tk-total__line dd { margin: 0; font-variant-numeric: tabular-nums; }
.tk-total__line--big { padding-top: .45rem; border-top: 1px solid var(--line); }
.tk-total__line--big dt { font-family: var(--mono); font-size: .74rem; text-transform: uppercase; letter-spacing: .14em; }
.tk-total__line--big dd {
  font-family: var(--display);
  font-weight: 800;
  font-size: 1.75rem;
  letter-spacing: -.03em;
}

#express { min-height: 48px; }

/* One line above the payment form when PayNow leads, from lib/content.mjs. */
.tk-pay-lead {
  margin: 0 0 1rem;
  font-size: .88rem;
  text-align: center;
  color: var(--slate);
}

.tk-or {
  display: flex; align-items: center; gap: .75rem;
  margin: 1rem 0;
  font-family: var(--mono); font-size: .7rem;
  text-transform: uppercase; letter-spacing: .16em;
  color: var(--slate);
}
.tk-or::before, .tk-or::after { content: ''; flex: 1; height: 1px; background: var(--line); }

.tk-field { display: block; margin-bottom: .9rem; }
.tk-field > span {
  display: block;
  font-family: var(--mono); font-size: .72rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: .12em; color: var(--slate);
  margin-bottom: .35rem;
}

.tk-card input[type='text'],
.tk-card input[type='email'],
.tk-card input[type='tel'],
.tk-card input[type='number'],
.tk-card select {
  width: 100%;
  padding: .78rem .9rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--bone-2);
  color: var(--ink);
  font-family: var(--body);
  font-size: 1rem;
}
.tk-card input:focus-visible,
.tk-card select:focus-visible { border-color: var(--accent-gfx); }

/* The field the error message is about. Colour is not the only signal: the message
   names the field, and the cursor is put in it. */
.tk-card input[aria-invalid="true"],
.tk-card select[aria-invalid="true"] {
  border-color: #9a2617;
  box-shadow: inset 0 0 0 1px #9a2617;
}
.tk-check input[aria-invalid="true"] { outline: 2px solid #9a2617; outline-offset: 2px; }
.tk-field--narrow input { max-width: 8rem; }
.tk-card #code { text-transform: uppercase; letter-spacing: .06em; font-family: var(--mono); }

#payment-element { margin-bottom: 1rem; }
#pay-card { margin-top: .25rem; }

.tk-msg { margin: .9rem 0 0; font-size: .92rem; min-height: 0; }
.tk-msg:empty { margin: 0; }
.tk-msg--err { color: #9a2617; font-weight: 500; }

/* A standing fact rather than a response to anything, so it reads as a note and
   not as an error, and nothing clears it. */
.tk-note {
  margin: 0 0 .9rem;
  padding: .7rem .8rem;
  border-left: 3px solid var(--accent-gfx);
  background: var(--bone);
  font-size: .86rem;
  color: var(--ink);
}

.tk-diag {
  margin: 1rem 0 0;
  padding: .8rem .9rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--bone);
  font-family: var(--mono);
  font-size: .72rem;
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--slate);
}

.tk-closed { margin-top: 1rem; }
.tk-fineprint { margin-top: 1rem; }

/* ---------- success state ---------- */

.tk-done { border-top-color: var(--pulse-mid); }
.tk-done .lead { margin-bottom: 1rem; }
.tk-tickets { list-style: none; margin: 0 0 1rem; padding: 0; display: grid; gap: .9rem; }
.tk-ticket-item {
  display: flex; align-items: center; gap: 1rem; margin: 0;
  padding: .9rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--bone);
}
.tk-ticket-item img { width: 110px; height: 110px; flex: none; background: #fff; }
.tk-ticket-code {
  display: block;
  font-size: 1.2rem; font-weight: 600; letter-spacing: .12em;
  margin-bottom: .3rem;
}

/* ---------- single ticket page ---------- */

.tk-ticket-head { text-align: center; }
.tk-ticket-head .eyebrow { margin-bottom: .6rem; }
.tk-ticket { text-align: center; }
.tk-qr {
  width: min(340px, 78vw);
  margin: 0 auto 1.2rem;
  padding: 14px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 6px;
  box-shadow: var(--shadow-1);
}
.tk-qr img { width: 100%; height: auto; }
.tk-bigcode {
  font-size: clamp(1.5rem, 6vw, 2.1rem);
  font-weight: 600;
  letter-spacing: .16em;
  margin: 0 0 .8rem;
}
.tk-ticket .fine { margin-top: 1rem; word-break: break-word; }

/* Apple's badge, at its own proportions. Apple's marketing agreement forbids
   recolouring or reshaping it, so there is no border, no background and no hover
   tint here: only the size, and the focus ring the rest of the site uses. */
.tk-wallet { margin: 0 0 1rem; }
.tk-wallet a { display: inline-block; border-radius: 5px; line-height: 0; }
.tk-wallet img { width: 111px; height: 35px; display: block; }

/* ---------- used / void stamp over the QR ----------
   A pill under the code is easy to miss on a phone held up at a door, and a
   screenshot of a spent ticket looks identical to a fresh one. This sits across
   the QR itself, so a used ticket cannot be passed off as unused. */
.tk-qr { position: relative; isolation: isolate; }
.tk-qr--stamped img { opacity: .35; filter: grayscale(1); }
.tk-stamp {
  position: absolute;
  inset: 14px;
  margin: 0;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: .1rem;
  text-align: center;
  background: rgba(11, 22, 34, .82);
  color: #fff;
  border-radius: 4px;
}
.tk-stamp b {
  font-size: clamp(1.8rem, 9vw, 3rem);
  font-weight: 800;
  letter-spacing: .12em;
  line-height: 1;
  transform: rotate(-8deg);
}
.tk-stamp span {
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  opacity: .85;
  transform: rotate(-8deg);
}

/* ---------- paid, tickets not issued yet ---------- */
.tk-pending { border-top-color: var(--pulse-mid); }
.tk-pending .lead { margin-bottom: .8rem; }
.tk-pending .mono { word-break: break-all; }

/* ---------- find my tickets ---------- */
.tk-find { display: grid; gap: .9rem; max-width: 26rem; margin: 1.2rem 0 .6rem; }

/* ---------- photographs: one scrolling strip, two shapes ---------- */

/* The gallery and the venue are the same component with a different slide width. No
   library and no script: overflow scrolling plus scroll-snap is the whole mechanism,
   which means it works with JavaScript off, respects the platform's own momentum and
   costs nothing to load.

   `--strip-h` is the row's height, and the pictures are sized from it rather than
   cropped into a box, so a portrait frame stays portrait and simply takes less width. */
.tk-gallery__intro { max-width: 56ch; margin-top: .8rem; }

.sec { overflow-x: clip; }

.tk-strip {
  display: flex;
  gap: .6rem;
  margin-top: 1.8rem;
  padding-bottom: .5rem;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  /* No scrollbar. The strip loops and drifts on its own, so a bar under it was a
     control nobody needed and a grey line across a band of photographs. It is the bar
     that is hidden and not the overflow: touch, wheel, trackpad, a drag and the arrow
     keys all still scroll the strip, which is why this is three vendor properties
     rather than overflow: hidden. */
  scrollbar-width: none;
  -ms-overflow-style: none;
  /* The fade at the right edge is the scroll hint: it says there is more without
     printing a sentence saying so. It is dropped once the strip is scrolled to the
     end by the browser's own overflow shadow doing nothing, which is honest enough. */
  -webkit-overflow-scrolling: touch;
}
.tk-strip::-webkit-scrollbar { display: none; }
.tk-strip:focus-visible { outline: 2px solid var(--pulse); outline-offset: 4px; }

.tk-strip__item {
  margin: 0;
  position: relative;
  flex: 0 0 auto;
  overflow: hidden;
  border-radius: 4px;
  background: var(--ink);
  scroll-snap-align: start;
}
.tk-strip__item img { display: block; }
.tk-strip__item figcaption {
  position: absolute; inset: auto 0 0 0;
  padding: 1.4rem .9rem .7rem;
  font-family: var(--mono); font-size: .68rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--snow);
  background: linear-gradient(to top, rgba(11, 22, 34, .85), rgba(11, 22, 34, 0));
}

/* Last year: a compact row of thumbnails at their own aspect ratio, so twelve photos
   cost one band of the page instead of a screen and a half of it.

   Both strips are sized off `--strip-h` and the two values are close on purpose: the
   thumbnails came up from 200px and the venue frames came down from 300px so the two
   bands read as the same component seen twice, which is what they are, rather than a
   small strip and a big one. */
.tk-strip--row { --strip-h: 240px; }
.tk-strip--row .tk-strip__item img { height: var(--strip-h); width: auto; max-width: none; }
.tk-strip--row .tk-strip__item { scroll-snap-align: start; }

/* The venue: one frame at a time, snapped to centre. Full-bleed across the viewport
   with the neighbouring frames peeking in at both edges, because a lone frame that
   fills its box reads as a picture, not a carousel; the peek is what says "swipe". */
.tk-strip--single {
  --strip-h: 250px;
  gap: .8rem;
  scroll-snap-type: x mandatory;
}
/* The frame narrowed with the height it lost, 520 to 440 for 300 to 250, so the crop is
   the one that was chosen and not a squashed version of it: the landscape photographs
   still lose a little off the top and bottom rather than most of it, and the two
   portrait ones still read as a band across the middle of the picture. */
.tk-strip--single .tk-strip__item--full {
  flex: 0 0 min(440px, 82vw);
  scroll-snap-align: start;
}
.tk-strip--single .tk-strip__item--full img {
  width: 100%;
  height: var(--strip-h);
  object-fit: cover;
}

/* Both strips span the whole screen: the first frame touches the left edge of the
   viewport, not the text column above it, and the rest run off the right, which is
   what says "there is more". The negative inline margins undo the section's gutter
   and whatever the centred column left either side of it, whatever the width. The
   right padding keeps the last frame off the edge once it is scrolled to the end. */
.tk-strip {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  padding-left: 0;
  padding-right: var(--gut);
  scroll-padding-left: 0;
}

.tk-venue__mrt { margin: .6rem 0 0; color: var(--slate); max-width: 56ch; }
/* The same two map links the confirmation email prints, quiet under the MRT line. */
.tk-venue__maps { margin: .35rem 0 0; }

@media (max-width: 700px) {
  .tk-strip--row { --strip-h: 190px; }
  .tk-strip--single { --strip-h: 200px; }
}

/* ---------- a heading with something beside it ---------- */

/* .shead is a grid of stacked rows, so a section that wants a mark next to its title
   puts the title and the mark in one flex row and hands the grid a single child. Only
   the venue asks for this; every other section still hands the grid a bare h2.

   It wraps, and on a phone it is a column outright: the mark drops under the title and
   lands left, because space-between with one item on the line is flex-start. */
.shead__row {
  display: flex;
  position: relative;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1.2rem 2rem;
}
.shead__row h2 { margin: 0; }
/* The title and the lines under it, as one block beside the mark. It does not stretch
   to the mark's height: the mark is a good deal taller than the two lines, and spreading
   the text to meet its bottom edge opened a hole between the title and the address. */
.shead__stack {
  display: flex;
  flex-direction: column;
}
.shead__stack .shead__lines { margin-top: .45rem; }

/* The quiet lines under a heading: where the place is, off the event row. Smaller than
   .lead and in the muted ink, so the title still carries the section on its own. */
.shead__lines {
  margin: 0;
  font-size: .95rem;
  line-height: 1.55;
  color: var(--slate);
}

/* ---------- the partnership mark ---------- */

/* Our crest, a times sign, the venue's badge, sitting to the right of the venue heading.
   Placement is the row's job, so there is no justify-content here. The two marks are
   deliberately not the same height: the badge is tall and narrow, so cut to the crest's
   height it reads as the smaller of the two. The crest is the ink cut, because this band
   lands on bone or on white depending on the flow, never on the nav's ink. */
.tk-lockup {
  display: flex;
  align-items: center;
  gap: 1.6rem;
  margin: 0;
  height: 10.8rem;
}
.tk-lockup img { display: block; width: auto; }
.tk-lockup__crest { height: 7.4rem; }
.tk-lockup__badge { height: 10.8rem; }
.tk-lockup__x {
  font-size: 1.7rem;
  line-height: 1;
  color: var(--slate);
}
/* On a wide screen the mark is lifted out of the flow and hung in the heading's top
   right corner, its top on the title's top. In the flow it made the row as tall as
   itself, and everything after the heading started below the badge rather than beside
   it. The paragraphs it now sits beside are capped near 56ch, so they never reach it. */
@media (min-width: 901px) {
  .tk-lockup { position: absolute; top: 0; right: 0; }
}

@media (max-width: 900px) {
  .shead__row { flex-direction: column; align-items: flex-start; }
  .tk-lockup { gap: 1.1rem; }
  .tk-lockup__crest { height: 5.2rem; }
  .tk-lockup__badge { height: 6.4rem; }
  .tk-lockup__x { font-size: 1.3rem; }
}

/* ---------- the two reels ---------- */

/* ---------- the reels, self-hosted ---------- */

/* Two 9:16 players, side by side and centred in the wrap on a desktop, a scroll-snap row
   on a phone. The row borrows the strip's conventions rather than the strip itself: these
   are two items, not twelve, and they do not loop, so they want none of the clone or the
   drift machinery, only the same snapping and the same edge-to-edge measure. */
.tk-reels {
  display: flex;
  gap: 2rem;
  justify-content: center;
  margin-top: 2rem;
}
.tk-reels__item { margin: 0; min-width: 0; flex: 0 0 300px; }

.tk-reel {
  position: relative;
  border: 1px solid var(--line);
  border-radius: 4px;
  overflow: hidden;
  background: var(--ink);
  aspect-ratio: 9 / 16;
}
.tk-reel__video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The picture is the control: reels.js toggles play on a tap, so the cursor should
     say the frame is tappable rather than selectable. */
  cursor: pointer;
}
/* Bottom left, over the picture, in the same quiet mono the eyebrows are set in. The
   pill is ink at two thirds so the label survives a bright frame and a dark one. */
.tk-reel__sound {
  position: absolute;
  left: .6rem;
  bottom: .6rem;
  padding: .35rem .7rem;
  border: 0;
  border-radius: 999px;
  background: rgba(11, 22, 34, .66);
  color: var(--snow);
  font-family: var(--mono);
  font-size: .66rem;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  cursor: pointer;
}
.tk-reel__sound:hover { background: rgba(11, 22, 34, .82); }
.tk-reel__sound:focus-visible { outline: 2px solid var(--pulse); outline-offset: 2px; }

.tk-reels__item figcaption {
  margin-top: .9rem;
  font-size: .92rem;
  line-height: 1.5;
  color: var(--slate);
}

/* On a phone the pair is a snap row that runs off the right edge, the same gesture the
   photo strips ask for: one reel takes about 70% of the screen and the second peeks in,
   which is what says there is another one. */
@media (max-width: 700px) {
  .tk-reels {
    display: flex;
    gap: .8rem;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    -ms-overflow-style: none;
    -webkit-overflow-scrolling: touch;
    justify-content: flex-start;
    width: 100vw;
    margin-inline: calc(50% - 50vw);
    padding: 0 var(--gut) .5rem;
    scroll-padding-left: var(--gut);
  }
  .tk-reels::-webkit-scrollbar { display: none; }
  .tk-reels__item { flex: 0 0 70vw; scroll-snap-align: start; }
}

/* ---------- the Partner Village ---------- */

/* Four tiles, 2x2 on a phone and four across from 700px. A logo slot on top of a caption,
   and the caption prints the name and what they bring whether or not a logo file exists,
   so the grid reads the same with none of them, some of them or all four. */
.tk-partners {
  list-style: none;
  margin: 2rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.4rem;
}
.tk-partner { min-width: 0; }
/* The tile is a link, and looks like a tile: no underline, no link colour, the plate and
   the two lines exactly as they read when there was nothing to click. The hover is the
   plate coming forward, which is the affordance a logo wall wants, and the focus ring is
   the browser's own so a keyboard lands somewhere visible. */
.tk-partner__link {
  display: block;
  color: inherit;
  text-decoration: none;
  border-radius: 4px;
}
.tk-partner__link .tk-partner__logo { transition: border-color .18s ease, box-shadow .18s ease; }
.tk-partner__link:hover .tk-partner__logo {
  border-color: var(--ink-3, #4a5568);
  box-shadow: 0 2px 10px rgb(11 22 34 / 10%);
}
.tk-partner__link:hover .tk-partner__name { text-decoration: underline; text-underline-offset: .18em; }
.tk-partner__link:focus-visible { outline: 2px solid var(--accent-txt, #16719a); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
  .tk-partner__link .tk-partner__logo { transition: none; }
}
/* A fixed plate, not a fixed image: the logos arrive at whatever aspect ratio their owners
   drew them in, and contain inside one height is what makes a wide wordmark and a round
   badge sit on the same line. Every slot is the same white plate, with or without a file
   in it, so the one vendor still waiting on a logo is the same object as the other three
   rather than a placeholder next to them; white because two of the marks are drawn for
   white (a black badge, a cream wordmark) and the bone band would swallow them. */
.tk-partner__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 118px;
  padding: 1rem 1.2rem;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: #fff;
}
/* Fill the plate, do not merely fit inside it. Under max-width alone an SVG with an
   intrinsic size draws at that size and nothing scales it up, so the one vector mark here
   sat at 162px in a 233px box and its tile read as the empty one of the four. Sizing the
   box and letting contain do the fitting treats every logo the same, whatever it arrived
   as: a wide wordmark ends up limited by the width, a square badge by the height. */
.tk-partner__logo img { width: 100%; height: 100%; object-fit: contain; }
/* No logo yet: the name set in the display face on the same plate, a mark of its own
   rather than an empty box waiting for a file. */
.tk-partner__logo--mark { background: #fff; }
.tk-partner__mark {
  font-family: var(--display);
  font-weight: 800;
  font-size: 1.05rem;
  letter-spacing: -.02em;
  line-height: 1.15;
  text-align: center;
}
.tk-partner__name {
  margin: .8rem 0 .15rem;
  font-weight: 700;
  font-size: .98rem;
  text-align: center;
}
.tk-partner__what { margin: 0; color: var(--slate); font-size: .9rem; line-height: 1.45; text-align: center; }

@media (min-width: 700px) {
  .tk-partners { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1.8rem; }
  /* Four across, so the plates go wide and short and a long wordmark fills every pixel of
     one while the square badges sit in the middle of theirs with air either side. The cap
     buys that wordmark the same margins the others get by their shape. Only here: at phone
     widths the plates are narrow enough that a wordmark needs all of it. */
  .tk-partner__logo img { max-width: 86%; }
}

/* ---------- ticket page additions ---------- */

.tk-ticket .tk-attendee {
  margin: 0 0 .2rem;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(1.3rem, 5vw, 1.8rem);
  letter-spacing: -.02em;
}
.tk-type-name { margin: 0 0 1.2rem; color: var(--slate); font-size: .95rem; }
.tk-meal {
  display: grid;
  gap: .3rem;
  margin: 1rem auto 0;
  max-width: 22rem;
  text-align: left;
}
.tk-meal > div { display: flex; justify-content: space-between; gap: 1rem; padding: .5rem 0; border-bottom: 1px solid var(--line); }
.tk-meal dt { font-family: var(--mono); font-size: .72rem; text-transform: uppercase; letter-spacing: .12em; color: var(--slate); }
.tk-meal dd { margin: 0; font-weight: 500; text-align: right; }
.tk-upsell { margin-top: 1.4rem; }

.tk-ticket-who { display: block; font-weight: 700; }
.tk-ticket-item .fine { display: block; }

/* ---------- the kitchen link, and the printable labels ---------- */

.kt { max-width: 44rem; margin: 0 auto; padding: 1.5rem 1rem 4rem; }
.kt h1 { margin: 0 0 .2rem; }
.kt__stamp { color: var(--slate); font-size: .85rem; margin: 0 0 1.5rem; }
.kt__counts { display: grid; gap: .5rem; margin: 0 0 2rem; padding: 0; list-style: none; }
.kt__counts li { display: flex; justify-content: space-between; gap: 1rem; padding: .7rem .9rem; border: 1px solid var(--line); border-radius: 4px; background: var(--bone); }
.kt__counts b { font-family: var(--mono); font-size: 1.15rem; }
.kt__group { margin: 0 0 1.6rem; }
.kt__group h3 { margin: 0 0 .5rem; }
.kt__names { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: .4rem; }
.kt__names li { padding: .3rem .6rem; border: 1px solid var(--line); border-radius: 999px; font-size: .88rem; background: var(--bone); }

.lbl { display: grid; grid-template-columns: repeat(2, 1fr); gap: .5rem; padding: 1rem; }
.lbl__item { border: 1px dashed #999; border-radius: 4px; padding: .8rem; break-inside: avoid; }
.lbl__name { font-size: 1.25rem; font-weight: 700; margin: 0 0 .2rem; }
.lbl__meal { font-size: 1rem; margin: 0 0 .2rem; }
.lbl__meta { font-size: .75rem; color: #555; margin: 0; font-family: var(--mono); }
@media print {
  .lbl { grid-template-columns: repeat(3, 1fr); }
  .no-print, .nav, .foot { display: none !important; }
}

/* the share control on a ticket, and on the done list */
.tk-share { margin: .6rem 0 0; }
.tk-share-btn { background: none; border: 0; padding: 0; cursor: pointer; font: inherit; }
