/* Trash Talk Tour — ZeroWaste.Org 3.0 cut
   Scoped under .tt-root so tokens never leak into the rest of the site.

   The 3.0 kit's own token NAMES (--zw-blue, --radius-lg, --measure…) are
   deliberately not reused here. Custom properties inherit, this stylesheet is
   unlayered, and unlayered CSS outranks Tailwind v4's `@layer theme` — so
   `.tt-root { --radius-lg: 14px }` would silently reset the radius scale for
   every `rounded-lg` utility inside the tour's pages, and the tour's *events*
   page renders shared Tailwind-styled partials under this same body class.
   That is the bug test/assets/brand_tokens_radius_test.rb exists to prevent.
   The kit's VALUES are adopted; its names stay out of the cascade. */

.tt-root {
  /* Grounds and surfaces */
  --tt-paper:        #fdfcfa;
  --tt-surface:      #ffffff;
  --tt-surface-warm: #fbfaf7;
  --tt-panel:        #f7f5f1;

  /* Warm ink scale — headline through eyebrow */
  --tt-ink:     #1c1c1e;
  --tt-ink-2:   #2b2b2f;
  --tt-ink-3:   #4a4a50;
  --tt-muted:   #6b6b70;
  --tt-faint:   #8b8880;
  --tt-quiet:   #9a978f;

  /* Hairlines — warm, never gray-blue, always 1px */
  --tt-border-1:    #ece9e3;
  --tt-border-2:    #e2ded6;
  --tt-border-soft: #eae6df;

  /* Blue is action: buttons, links, focus rings. Nothing decorative is blue. */
  --tt-blue:       #336699;
  --tt-blue-hover: #29527d;
  --tt-blue-tint:  #f2f6fa;

  /* Green measures. Green is never a button. */
  --tt-green: #2f7a63;

  /* The days of a multi-day event, so Saturday and Sunday are told apart at a
     glance. These are new hues rather than a reuse of the two above, because
     both are already spoken for: blue means action here and nothing decorative
     may borrow it, and green means a measurement. Clay and a deeper cut of the
     page's own forest ground keep the chips inside the warm palette instead of
     reading as bolted on. */
  --tt-day-1-ink:  #8f4227;
  --tt-day-1-tint: #fbf1ec;
  --tt-day-1-line: #eeddd3;
  --tt-day-2-ink:  #23604d;
  --tt-day-2-tint: #eef5f2;
  --tt-day-2-line: #d5e6df;

  /* The dark ground the page rounds over */
  --tt-base:       #1b3b31;
  --tt-base-line:  #2a5044;
  --tt-base-quiet: #7fa494;
  --tt-base-body:  #b7cfc4;
  --tt-base-link:  #dcebe4;

  /* Type — two faces, no third. Petrona carries voice, system sans every
     interface surface, mono for the ticket reference lines. */
  --tt-font-display: Petrona, Georgia, serif;
  --tt-font-sans:    system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --tt-font-mono:    "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --tt-text-hero:  clamp(40px, 5.9vw, 66px);
  --tt-text-h2:    35px;
  --tt-text-h3:    18px;
  --tt-text-lead:  19px;
  --tt-text-body:  18px;
  --tt-text-ui:    15px;
  --tt-text-sm:    14px;
  --tt-text-xs:    13px;

  --tt-leading-hero:  1.03;
  --tt-leading-h2:    1.14;
  --tt-leading-lead:  1.6;
  --tt-leading-prose: 1.65;
  --tt-leading-ui:    1.55;

  --tt-tracking-display: -0.022em;
  --tt-tracking-h2:      -0.015em;
  --tt-tracking-eyebrow: 0.06em;

  /* Shape — 10 buttons · 14 inputs · 16 cards · 24 panels · 26 page corners */
  --tt-radius-sm:   10px;
  --tt-radius-lg:   14px;
  --tt-radius-xl:   16px;
  --tt-radius-2xl:  24px;
  --tt-radius-page: 26px;
  --tt-radius-pill: 999px;

  --tt-shadow-card:  0 2px 6px rgba(28, 28, 30, 0.05);
  --tt-shadow-lift:  0 20px 44px rgba(28, 28, 30, 0.14);
  --tt-shadow-float: 0 10px 28px rgba(28, 28, 30, 0.09), 0 2px 6px rgba(28, 28, 30, 0.05);
  --tt-shadow-page:  0 14px 28px rgba(28, 28, 30, 0.16);
  --tt-shadow-ring:  0 0 0 3px rgba(51, 102, 153, 0.18);

  /* Layout */
  --tt-measure:   960px;
  --tt-gutter:    28px;
  --tt-section-y: 80px;
  /* The featured ticket's horizontal padding. Named because its perforation
     bleeds to the card's edges with the negative of this exact value. */
  --tt-featured-pad: 26px;
  /* The featured ticket's top padding, and the ticket card's padding on all
     four sides. Tokenised because the media bands bleed to the card edges with
     a negative margin equal to the padding, so the two numbers must move
     together -- a mismatch leaves the photo inset on one side or overhanging. */
  --tt-featured-pad-top: 22px;
  --tt-ticket-pad: 22px;

  /* Motion — one curve */
  --tt-ease-out:  cubic-bezier(0.2, 0.8, 0.2, 1);
  --tt-dur-ui:    200ms;
  --tt-dur-card:  320ms;
  --tt-tilt-1:    rotate(-1.5deg) translateY(6px);
  --tt-tilt-2:    rotate(1.2deg)  translateY(-4px);
  --tt-tilt-3:    rotate(-0.8deg) translateY(8px);
  --tt-tilt-rest: rotate(0deg) translateY(-8px) scale(1.035);

  font-family: var(--tt-font-sans);
  background: var(--tt-base);
  color: var(--tt-ink);
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Element resets, kept in @layer base on purpose. Tailwind emits every utility
   into @layer utilities, and unlayered CSS outranks any layer no matter the
   specificity — so unlayered, `.tt-root a { color: inherit }` repaints every link
   in the shared event partials with the page ink, invisible on a white card.
   Anything added here must stay a reset a utility is allowed to override. */
@layer base {
  .tt-root *, .tt-root *::before, .tt-root *::after { box-sizing: border-box; }
  .tt-root h1, .tt-root h2, .tt-root h3 {
    margin: 0;
    font-family: var(--tt-font-display);
    font-weight: 600;
  }
  .tt-root p { margin: 0; line-height: var(--tt-leading-ui); }
  .tt-root a { color: inherit; }
  .tt-root img { max-width: 100%; display: block; }
}

/* === The page on a ground ===
   A dark green substrate the paper page rounds over at the bottom. */
.tt-page {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.tt-sheet {
  background: var(--tt-paper);
  border-radius: 0 0 var(--tt-radius-page) var(--tt-radius-page);
  box-shadow: var(--tt-shadow-page);
  overflow: hidden;
}
.tt-container {
  width: 100%;
  max-width: var(--tt-measure);
  margin: 0 auto;
  padding: 0 var(--tt-gutter);
}

.tt-flash {
  background: var(--tt-blue-tint);
  border: 1px solid var(--tt-border-2);
  border-radius: var(--tt-radius-lg);
  color: var(--tt-ink-2);
  padding: 12px 18px;
  font-size: var(--tt-text-sm);
}

/* === Hero ===
   Two columns: the tour's own voice on the left, the one stop it is currently
   promoting on the right. Left-aligned rather than centred — a centred column
   and a card beside it fight each other for the same optical middle. */
.tt-hero {
  position: relative;
  max-width: var(--tt-measure);
  margin: 0 auto;
  padding: 64px var(--tt-gutter) 150px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 330px);
  align-items: start;
  gap: 46px;
  text-align: left;
}
/* Nothing to promote, so nothing to set beside the pitch. */
.tt-hero--solo { grid-template-columns: minmax(0, 1fr); }
.tt-hero-main {
  display: grid;
  gap: 26px;
  justify-items: start;
}
.tt-hero-logo { width: auto; height: 115px; }

.tt-hero-meta {
  display: flex; align-items: center;
  gap: 14px; flex-wrap: wrap;
}
.tt-eyebrow {
  font-size: var(--tt-text-xs);
  line-height: 1.3;
  letter-spacing: var(--tt-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--tt-quiet);
}
.tt-eyebrow-action { color: var(--tt-blue); }
.tt-eyebrow-rule { width: 1px; height: 13px; background: var(--tt-border-2); }

.tt-headline {
  max-width: 700px;
  font-size: var(--tt-text-hero);
  letter-spacing: var(--tt-tracking-display);
  line-height: var(--tt-leading-hero);
  color: var(--tt-ink);
  text-wrap: balance;
}
.tt-root .tt-lede {
  max-width: 580px;
  font-size: var(--tt-text-lead);
  line-height: var(--tt-leading-lead);
  color: var(--tt-ink-3);
  text-wrap: pretty;
}

/* The one stop the hero promotes, cut as a ticket: a stub naming the tour and
   the days it runs, a perforation, then the pitch and a full-width button.
   The column is the same ~330px it always was -- what makes this read as a
   ticket rather than the squat information panel it replaced is the
   proportion, so the body below the tear line has to stay filled. */
.tt-featured {
  display: grid;
  padding: var(--tt-featured-pad-top) var(--tt-featured-pad) 26px;
  transform: rotate(1.4deg);
  background: var(--tt-surface);
  border: 1px solid var(--tt-border-soft);
  border-radius: var(--tt-radius-xl);
  box-shadow: var(--tt-shadow-float);
}
/* The stop's photo, run full bleed across the top of the ticket the way a
   printed ticket carries its artwork. An event's cover is uploaded at whatever
   shape the photographer had, and cropping every one to the same box is what
   keeps a row of tickets reading as a set.

   16:9, and the ratio is the whole design decision. Square was tried first and
   was wrong: in a ~330px column it came out ~330px tall, which is most of the
   card and pushed the pitch and the button down the page. A shallow band reads
   as a ticket's artwork; a tall one reads as a photo with a caption stapled
   underneath.

   The negative margins have to stay equal to .tt-featured's padding, which is
   why all three read tokens -- same contract as .tt-featured-perf below. */
.tt-featured-media {
  margin: calc(var(--tt-featured-pad-top) * -1) calc(var(--tt-featured-pad) * -1) 0;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  /* Inside a 1px border, so one pixel tighter than the card's own radius --
     matching it exactly leaves a hairline of card showing at each corner. */
  border-radius: calc(var(--tt-radius-xl) - 1px) calc(var(--tt-radius-xl) - 1px) 0 0;
  background: var(--tt-border-soft);
}
.tt-featured-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* The stub sits directly under the photo rather than at the top of the card,
   so it needs the padding back that the band's negative margin removed. */
.tt-featured-media + .tt-featured-stub { padding-top: var(--tt-featured-pad-top); }

.tt-featured-stub {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding-bottom: 18px;
}
.tt-featured-ref {
  font-family: var(--tt-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--tt-faint);
  white-space: nowrap;
}
/* Full bleed, so the dashes run out to both edges the way a tear line does.
   The negative margin has to stay equal to .tt-featured's horizontal padding,
   which is why both read the same token. */
.tt-featured-perf {
  height: 1px;
  margin: 0 calc(var(--tt-featured-pad) * -1);
  background: repeating-linear-gradient(to right,
              var(--tt-border-2) 0 6px, transparent 6px 12px);
}
.tt-featured-body {
  display: grid;
  gap: 12px;
  justify-items: start;
  padding-top: 20px;
}
.tt-featured-name {
  font-size: var(--tt-text-h2);
  line-height: 1.12;
  letter-spacing: var(--tt-tracking-display);
  color: var(--tt-ink);
  text-wrap: balance;
}
/* Stacked rather than laid side by side. Two days written out in full come to
   roughly 300px, which does not fit across a 330px card at all, let alone
   beside the tour name -- as a row they wrapped the list onto a third line and
   left the stub half empty. As a column the whole list is one narrow flex item
   that still sits beside the tour name. */
.tt-featured-days {
  margin: 0 0 0 auto; padding: 0; list-style: none;
  display: flex; flex-direction: column;
  align-items: flex-end;
  gap: 5px;
}
/* Each day of a multi-day stop, named in full and painted so the difference
   between one day and the next is visible before the words are read. */
.tt-day {
  padding: 4px 10px 5px;
  border: 1px solid;
  border-radius: var(--tt-radius-pill);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.3;
  white-space: nowrap;
}
.tt-day--1 {
  color: var(--tt-day-1-ink);
  background: var(--tt-day-1-tint);
  border-color: var(--tt-day-1-line);
}
.tt-day--2 {
  color: var(--tt-day-2-ink);
  background: var(--tt-day-2-tint);
  border-color: var(--tt-day-2-line);
}
.tt-featured-place {
  font-size: var(--tt-text-sm);
  font-weight: 600;
  color: var(--tt-ink-3);
}
/* Specificity to match `.tt-root p`, which sets the page's prose size. */
.tt-root .tt-featured-blurb {
  font-size: var(--tt-text-sm);
  line-height: var(--tt-leading-ui);
  color: var(--tt-muted);
  text-wrap: pretty;
}
/* The button is the last thing in the body and wants no gap eaten above it. */
.tt-featured-body .tt-btn { margin-top: 2px; }

@media (max-width: 860px) {
  /* One column, and the card falls below the pitch rather than above it. The
     tour has to introduce itself before it promotes a stop -- hoisting the card
     here pushed the logo and headline off the first screen. Untilted too: at
     full width the rotation swings the corners far enough to clip. */
  .tt-hero {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
    padding-top: 40px;
  }
  .tt-featured { width: 100%; transform: none; }
}

/* === Sections === */
.tt-section {
  background: var(--tt-surface);
  border-top: 1px solid var(--tt-border-1);
}
.tt-section-paper { background: var(--tt-paper); }
.tt-section-inner {
  max-width: var(--tt-measure);
  margin: 0 auto;
  padding: var(--tt-section-y) var(--tt-gutter);
}
/* The stop cards ride up over the seam between the hero and this section. */
.tt-section-overlap { padding-top: 0; }
.tt-overlap-lift { position: relative; top: -60px; margin-bottom: -60px; }

.tt-section-heading { display: grid; gap: 10px; justify-items: start; }
.tt-section-title {
  max-width: 720px;
  font-size: var(--tt-text-h2);
  letter-spacing: var(--tt-tracking-h2);
  line-height: var(--tt-leading-h2);
  color: var(--tt-ink);
  text-wrap: balance;
}
.tt-root .tt-section-lead {
  max-width: 520px;
  font-size: var(--tt-text-lead);
  line-height: var(--tt-leading-lead);
  color: var(--tt-ink-3);
  text-wrap: pretty;
}

.tt-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.tt-grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }

/* The stops row. Three across rather than four: one stop is promoted into the
   hero, so a fourth column had nothing to hold and the row ended in a gap a
   whole card wide. Its own class rather than .tt-grid-3 because the stops need
   a two-up step the prize grid does not. */
.tt-stops-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }

/* === Ticket cards (the off-kilter row) === */
/* Flex column rather than grid so `margin-top: auto` on the CTA pins it to the
   bottom edge — a stop with no seat count would otherwise pull its button up
   and break the row's shared baseline. */
.tt-ticket {
  display: flex;
  flex-direction: column;
  gap: 14px;
  background: var(--tt-surface);
  border: 1px solid var(--tt-border-2);
  border-radius: var(--tt-radius-xl);
  padding: var(--tt-ticket-pad);
  box-shadow: var(--tt-shadow-card);
  transition: transform var(--tt-dur-card) var(--tt-ease-out),
              box-shadow var(--tt-dur-card) var(--tt-ease-out);
}
/* Cycling on 3 to match the three columns, so every card in a column carries
   the same tilt and the row reads as a deliberate fan rather than a jitter. */
.tt-ticket:nth-child(3n+1) { transform: var(--tt-tilt-1); }
.tt-ticket:nth-child(3n+2) { transform: var(--tt-tilt-2); }
.tt-ticket:nth-child(3n+3) { transform: var(--tt-tilt-3); }
.tt-ticket:hover {
  transform: var(--tt-tilt-rest);
  box-shadow: var(--tt-shadow-lift);
}
/* The resting tilts are :nth-child rules at specificity (0,2,0), and specificity
   outranks a media query — a plain `.tt-ticket { transform: none }` override at
   (0,1,0) loses and the tilt survives. Every un-tilt below must therefore match
   the :nth-child form, not the bare class. */
@media (prefers-reduced-motion: reduce) {
  .tt-ticket:nth-child(3n+1),
  .tt-ticket:nth-child(3n+2),
  .tt-ticket:nth-child(3n+3),
  .tt-ticket:hover { transform: none; transition: none; }
}

/* Same band as the featured ticket, on the same 16:9 crop, reading the stop
   card's own padding token. It is the card's first child, so the flex gap below
   separates it from the stub and no padding needs restoring on top. */
.tt-ticket-media {
  margin: calc(var(--tt-ticket-pad) * -1) calc(var(--tt-ticket-pad) * -1) 0;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: calc(var(--tt-radius-xl) - 1px) calc(var(--tt-radius-xl) - 1px) 0 0;
  background: var(--tt-border-soft);
}
.tt-ticket-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Stacked, not laid side by side. A stop card is ~244px of content and a day
   written out in full runs to ~145px beside a ~95px wordmark, so whether the
   two fit on one line depends on the length of the day's name: "Sunday,
   September 27" fitted and "Saturday, September 26" wrapped, leaving the
   dashed rule at a different height on each card in the row. Stacking makes
   the stub the same height whatever the day is called. */
.tt-ticket-stub {
  display: flex; flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding-bottom: 12px;
  border-bottom: 1px dashed var(--tt-border-2);
}
.tt-ticket-ref {
  font-family: var(--tt-font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--tt-faint);
  white-space: nowrap;
}
.tt-ticket-head { display: grid; gap: 6px; }
.tt-ticket-when {
  font-size: var(--tt-text-xs);
  letter-spacing: var(--tt-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--tt-quiet);
}
.tt-ticket-title {
  font-size: var(--tt-text-h3);
  letter-spacing: -0.01em;
  color: var(--tt-ink);
}
.tt-ticket-venue { font-size: 13px; font-weight: 600; color: var(--tt-ink-3); }
.tt-root .tt-ticket-blurb {
  font-size: var(--tt-text-sm);
  line-height: var(--tt-leading-ui);
  color: var(--tt-muted);
  text-wrap: pretty;
}
.tt-ticket-seats { font-size: var(--tt-text-xs); color: var(--tt-faint); }
/* Grid rather than the default flow: .tt-btn is inline-flex, so a sibling span
   would try to sit beside it and only wrap because .tt-btn-full happens to be
   width:100%. Stacking is the intent, not a side effect of the button's width. */
.tt-ticket-cta {
  margin-top: auto;
  padding-top: 2px;
  display: grid;
  gap: 8px;
}
/* Under the button on both tickets -- the same element, so one rule. Quiet: it
   qualifies the CTA rather than competing with it.

   Left, not centred under the centred button label. Everything else on both
   tickets is left-aligned, and .tt-featured-body carries `justify-items: start`
   while .tt-ticket-cta does not -- so centring here put the same line on the
   left in the hero and in the middle of the grid, which is the disagreement
   between the two surfaces this file keeps warning about. */
.tt-ticket-spots {
  font-size: var(--tt-text-xs);
  color: var(--tt-quiet);
  justify-self: start;
}
.tt-featured-body .tt-ticket-spots { margin-top: -4px; }

.tt-stops-empty {
  font-size: var(--tt-text-lead);
  line-height: var(--tt-leading-lead);
  color: var(--tt-ink-3);
  max-width: 560px;
}

.tt-stops-more {
  margin-top: 30px;
  text-align: center;
  font-size: var(--tt-text-ui);
}

/* === Prizes === */
.tt-prize-card {
  display: grid;
  gap: 0;
  align-content: start;
  background: var(--tt-paper);
  border: 1px solid var(--tt-border-2);
  border-radius: var(--tt-radius-xl);
  overflow: hidden;
}
.tt-prize-media {
  height: 168px;
  border-bottom: 1px solid var(--tt-border-1);
  background: var(--tt-surface-warm);
}
.tt-prize-media img { width: 100%; height: 100%; object-fit: cover; }
.tt-prize-body { display: grid; gap: 8px; padding: 20px; }
.tt-prize-name {
  font-size: var(--tt-text-h3);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--tt-ink);
}
.tt-prize-desc {
  font-size: var(--tt-text-sm);
  line-height: var(--tt-leading-ui);
  color: var(--tt-muted);
  text-wrap: pretty;
}
.tt-prize-sponsor { font-size: var(--tt-text-xs); color: var(--tt-faint); }

/* === Team === */
.tt-member { display: grid; gap: 12px; align-content: start; }
.tt-member-portrait {
  height: 200px;
  background: var(--tt-paper);
  border: 1px solid var(--tt-border-2);
  border-radius: var(--tt-radius-lg);
  overflow: hidden;
}
.tt-member-portrait img { width: 100%; height: 100%; object-fit: cover; }
.tt-member-initials {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--tt-font-display);
  font-size: 40px; font-weight: 600;
  color: var(--tt-quiet);
  background: var(--tt-surface-warm);
}
.tt-member-body { display: grid; gap: 4px; }
.tt-member-name {
  font-size: var(--tt-text-body);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--tt-ink);
}
.tt-member-role { font-size: var(--tt-text-sm); color: var(--tt-blue); }

/* === Sponsors and outreach partners === */
.tt-partner-group { display: grid; gap: 18px; }
.tt-sponsor { display: grid; gap: 10px; align-content: start; }
.tt-sponsor-logo {
  height: 130px;
  background: var(--tt-paper);
  border: 1px solid var(--tt-border-2);
  border-radius: var(--tt-radius-lg);
  overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  padding: 18px;
}
.tt-sponsor-logo img { max-height: 100%; width: auto; object-fit: contain; }
.tt-sponsor-mark {
  font-family: var(--tt-font-display);
  font-size: 34px;
  font-weight: 600;
  line-height: 1;
  color: var(--tt-quiet);
}
.tt-sponsor-name { font-size: var(--tt-text-sm); font-weight: 600; color: var(--tt-ink-2); }
.tt-sponsor-note { font-size: var(--tt-text-xs); color: var(--tt-faint); }

.tt-outreach-group {
  display: grid; gap: 18px;
  padding-top: 34px;
  border-top: 1px solid var(--tt-border-1);
}
/* The 4px this carried was tuned against the row of name pills the Partners
   group used to be -- a single short line, where the prompt reading as its
   continuation was fine. Under a grid of logo tiles it ran straight into the
   org names. Matched to the 34px that separates the two groups above it. */
.tt-root .tt-partner-prompt {
  max-width: 560px;
  margin-top: 34px;
  font-size: var(--tt-text-sm);
  line-height: var(--tt-leading-ui);
  color: var(--tt-muted);
  text-wrap: pretty;
}

/* === Links and buttons === */
.tt-root .tt-link {
  color: var(--tt-blue);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.tt-root .tt-link:hover { color: var(--tt-blue-hover); }

.tt-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 18px;
  border: 1px solid transparent;
  border-radius: var(--tt-radius-sm);
  font-family: var(--tt-font-sans);
  font-size: var(--tt-text-ui);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--tt-dur-ui) var(--tt-ease-out),
              color var(--tt-dur-ui) var(--tt-ease-out);
}
.tt-root .tt-btn-primary { background: var(--tt-blue); color: #ffffff; }
.tt-root .tt-btn-primary:hover { background: var(--tt-blue-hover); color: #ffffff; }
.tt-root .tt-btn-quiet {
  background: var(--tt-surface);
  border-color: var(--tt-border-2);
  color: var(--tt-ink-2);
}
.tt-root .tt-btn-quiet:hover { background: var(--tt-surface-warm); }
.tt-btn:focus-visible { outline: none; box-shadow: var(--tt-shadow-ring); }
.tt-btn-full { width: 100%; }

/* === FAQ === */
.tt-faq { display: grid; gap: 12px; margin-top: 44px; }
.tt-faq-item {
  background: var(--tt-paper);
  border: 1px solid var(--tt-border-2);
  border-radius: var(--tt-radius-lg);
}
.tt-faq-item summary {
  cursor: pointer; list-style: none;
  padding: 18px 22px;
  font-size: var(--tt-text-h3);
  font-weight: 600;
  color: var(--tt-ink);
  display: flex; justify-content: space-between; align-items: center; gap: 16px;
}
.tt-faq-item summary::-webkit-details-marker { display: none; }
.tt-faq-item summary span[aria-hidden] {
  font-size: 22px; line-height: 1; color: var(--tt-quiet);
  transition: transform 150ms var(--tt-ease-out);
}
.tt-faq-item[open] summary { border-bottom: 1px solid var(--tt-border-1); }
.tt-faq-item[open] summary span[aria-hidden] { transform: rotate(45deg); }
.tt-faq-answer {
  padding: 16px 22px;
  color: var(--tt-ink-3);
  font-size: var(--tt-text-ui);
  line-height: var(--tt-leading-lead);
}
.tt-faq-answer p + p { margin-top: 12px; }

/* === Signup === */
.tt-signup-wrap { max-width: 460px; margin: 36px auto 0; text-align: left; }
.tt-signup { display: grid; gap: 16px; }
.tt-signup label {
  display: block;
  margin-bottom: 6px;
  font-size: var(--tt-text-sm);
  font-weight: 600;
  color: var(--tt-ink-2);
}
.tt-signup input[type="text"]:not([style*="display:none"]),
.tt-signup input[type="email"] {
  width: 100%;
  padding: 12px 14px;
  background: var(--tt-surface);
  border: 1px solid var(--tt-border-2);
  border-radius: var(--tt-radius-lg);
  font-family: var(--tt-font-sans);
  font-size: var(--tt-text-ui);
  color: var(--tt-ink);
}
.tt-signup input[type="text"]:not([style*="display:none"]):focus,
.tt-signup input[type="email"]:focus {
  outline: none;
  border-color: var(--tt-blue);
  box-shadow: var(--tt-shadow-ring);
}
.tt-signup-actions { display: flex; gap: 12px; }
.tt-signup-error {
  background: var(--tt-blue-tint);
  border: 1px solid var(--tt-border-2);
  border-radius: var(--tt-radius-lg);
  padding: 12px 16px;
  margin-bottom: 16px;
  font-size: var(--tt-text-sm);
  color: var(--tt-ink-2);
}
.tt-signup-success {
  display: grid; gap: 8px; justify-items: center; text-align: center;
  padding: 28px 24px;
  background: var(--tt-surface);
  border: 1px solid var(--tt-border-2);
  border-radius: var(--tt-radius-xl);
}
.tt-signup-success-check {
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--tt-radius-pill);
  background: var(--tt-panel);
  color: var(--tt-green);
}
.tt-signup-success-title {
  font-family: var(--tt-font-display);
  font-size: 22px; font-weight: 600;
  color: var(--tt-ink);
}
.tt-signup-success-body { font-size: var(--tt-text-sm); color: var(--tt-ink-3); }

/* === Header and footer, on the dark ground === */
.tt-topbar { position: relative; z-index: 2; }
.tt-topbar-inner {
  display: flex; align-items: center; justify-content: center;
  padding: 22px 0 18px;
}
.tt-logo-chip img { height: 34px; width: auto; }

.tt-footer {
  max-width: var(--tt-measure);
  margin: 0 auto;
  padding: 26px var(--tt-gutter) 34px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
  font-size: var(--tt-text-sm);
  color: var(--tt-base-quiet);
}
.tt-root .tt-footer a {
  color: var(--tt-base-link);
  text-decoration: underline;
  text-decoration-color: rgba(255, 255, 255, 0.45);
}
.tt-footer-links { display: flex; gap: 18px; }

/* === Responsive === */
@media (max-width: 900px) {
  .tt-grid-4 { grid-template-columns: repeat(2, 1fr); }
  .tt-stops-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 760px) {
  .tt-grid-3 { grid-template-columns: 1fr; }
  .tt-stops-grid { grid-template-columns: 1fr; }
  /* The overlap only reads as a bouquet in a row. Stacked, it just collides. */
  .tt-overlap-lift { top: 0; margin-bottom: 0; }
  .tt-ticket:nth-child(3n+1),
  .tt-ticket:nth-child(3n+2),
  .tt-ticket:nth-child(3n+3),
  .tt-ticket:hover { transform: none; }
  .tt-section-inner { padding: 56px var(--tt-gutter); }
  .tt-section-overlap { padding-top: 56px; }
  .tt-hero { padding-bottom: 56px; }
}
@media (max-width: 560px) {
  .tt-root { --tt-gutter: 20px; }
  .tt-grid-4 { grid-template-columns: 1fr; }
  /* The eyebrow wraps to two lines here, leaving the divider stranded. */
  .tt-eyebrow-rule { display: none; }
  .tt-footer { justify-content: center; text-align: center; }
  .tt-signup-actions { flex-direction: column; align-items: stretch; }
}
