.section_audience-saying {
  --audience-ink: #131313;
  --audience-paper: #fff;
  --audience-canvas: #f2f2f2;
  --audience-canvas-hover: #e8e8e6;
  --audience-muted: #626262;
  /* Border ink as a bare RGB triplet so every hairline can be written
     rgb(var(--audience-edge) / N%) and flip with the theme in one place
     (dark-on-light here, light-on-dark below). */
  --audience-edge: 19 19 19;
  --audience-accent: var(--base--green, #b7fe02);
  position: relative;
  z-index: 1;
  overflow: clip;
  /* Section rhythm (Mena 2026-08-18): every other homepage section is
     .padding-section-large = 4.5rem top and bottom, so section-to-section
     reads 144px. This section used clamp(7rem,11vw,10.5rem) = 158px@1440 /
     168px@1920 and its background is the SAME white/near-black as the page,
     so the extra padding bought no band separation — it just opened a 230px
     hole before About Us. Matched to the site rhythm. */
  padding: 4.5rem 0;
  background: var(--bg-color--bg-default);
  color: var(--text-color--text-primary);
}

.audience-saying__layout {
  display: grid;
  grid-template-columns: minmax(17rem, 0.72fr) minmax(35rem, 1.28fr);
  align-items: center;
  gap: clamp(3rem, 7vw, 8rem);
}

.audience-saying__intro {
  position: relative;
  z-index: 3;
}

/* The heading now ends in a morphing word (Mena 2026-08-18), so it can no
   longer be width-clamped to 8.5ch and balanced — the morph box is absolutely
   positioned and sized per phrase by title-morph.js, and a ch-clamp would wrap
   mid-phrase as the word changes. */
.audience-saying__intro h2 {
  margin: 1.8rem 0 0;
  font-size: clamp(3rem, 4.6vw, 5.4rem);
  font-weight: 500;
  letter-spacing: -0.065em;
  line-height: 1.04;
}

.audience-saying__lead {
  font-weight: 500;
}

/* .hvo-am is the REFERENCE morph stage: Mena accepted its feel on a physical
   iPhone on 2026-08-27 and asked for every other morph to match it. Its
   geometry, filter, weight and phone layout were therefore lifted verbatim
   into the SHARED GOO STAGE block in title-morph/title-morph.css and now
   apply to all six stages from there. Nothing stage-specific is left here.
   Historical note worth keeping: the geometry was itself measured rather than
   guessed. An earlier attempt used vertical-align:baseline with height 1.1em
   and a 0.28em margin, which measured 5px of baseline offset (the word sat
   visibly high) and a 13px gap where the font's own word space is 5px.
   vertical-align:top with height 1.12em measures 0px offset, and the gap
   comes from a real space character in the markup rather than a margin. */

.audience-saying__intro-copy {
  max-width: 28rem;
  margin: 2rem 0 0;
  color: var(--text-color--text-secondary);
  font-size: clamp(1rem, 1.2vw, 1.2rem);
  line-height: 1.55;
}

/* Moved out of the intro header and under the deck (Mena 2026-08-18), so it
   sits below the deck with the thing it controls. (It used to sit under a
     "Swipe or drag the stack" hint, removed 2026-08-28.) */
.audience-saying__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

.audience-saying__button {
  display: grid;
  width: 3rem;
  height: 3rem;
  padding: 0;
  border: 1px solid color-mix(in srgb, currentColor 20%, transparent);
  border-radius: 999px;
  color: var(--text-color--text-primary);
  background: transparent;
  cursor: pointer;
  place-items: center;
  /* Two quick taps on an arrow read as double-tap-to-zoom on iOS and
     zoomed the whole page (Mena 2026-08-31). manipulation keeps tap and
     pan but drops the double-tap gesture on these controls. */
  touch-action: manipulation;
  transition:
    color 220ms ease,
    background-color 220ms ease,
    transform 220ms ease;
}

.audience-saying__button svg {
  width: 1.1rem;
  height: 1.1rem;
}

.audience-saying__button:hover {
  color: var(--audience-ink);
  background: var(--audience-accent);
  transform: translateY(-2px);
}

.audience-saying__button:active {
  transform: translateY(0) scale(0.94);
}

.audience-saying__button:focus-visible,
.audience-comment-card a:focus-visible {
  outline: 2px solid #55b9f4;
  outline-offset: 4px;
}

.audience-saying__count {
  min-width: 5.8rem;
  margin-left: 0.4rem;
  font-family: Geistmono, "Geist Mono", ui-monospace, monospace;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.audience-saying__current {
  color: var(--text-color--text-primary);
}

.audience-saying__total {
  color: var(--text-color--text-secondary);
}

.audience-saying__stage {
  position: relative;
  width: min(100%, 44rem);
  min-width: 0;
  margin-inline: auto;
  perspective: 1500px;
  perspective-origin: 50% 46%;
}

.audience-saying__swiper.swiper {
  width: calc(100% - 3.5rem);
  height: 41rem;
  overflow: visible;
}

.audience-saying__swiper .swiper-wrapper {
  align-items: stretch;
}

.audience-saying__swiper .swiper-slide {
  height: 100%;
  border-radius: 1.75rem;
  background: transparent;
  backface-visibility: hidden;
  transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform;
}

.audience-saying__swiper .swiper-slide-shadow {
  border-radius: 1.75rem;
  background: transparent !important;
  opacity: 0 !important;
}

/* The "Swipe or drag the stack" hint and its .audience-saying__gesture rules
   were removed 2026-08-28 at Mena's request. audience-saying.js still looks
   the element up for its desktop entrance but filters out the miss, so
   nothing else needed changing. */

.audience-comment-card {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  overflow: hidden;
  padding: clamp(1.55rem, 3.2vw, 2rem);
  border: 1px solid rgb(var(--audience-edge) / 11%);
  border-radius: 1.75rem;
  color: var(--audience-ink);
  background: var(--audience-paper);
  box-shadow: none;
  backface-visibility: hidden;
  isolation: isolate;
  transform-style: preserve-3d;
}

.audience-comment-card::before {
  position: absolute;
  z-index: 0;
  inset: 0;
  border-radius: inherit;
  /* Fallback follows the theme too, for the case where the slide has no
     inline --audience-card-back. */
  background: var(--audience-card-back, var(--audience-canvas));
  content: "";
  opacity: 1;
  pointer-events: none;
  transition: opacity 140ms ease-out;
}

.audience-comment-card > * {
  position: relative;
  z-index: 1;
}

.audience-saying__swiper
  .swiper-slide-active
  .audience-comment-card::before {
  opacity: 0;
  transition-duration: 0ms;
}

.audience-saying__swiper .swiper-slide-active .audience-comment-card::before,
.audience-saying__swiper .swiper-slide-prev .audience-comment-card::before,
.audience-saying__swiper .swiper-slide-next .audience-comment-card::before {
  will-change: opacity;
}

.audience-saying__swiper
  .swiper-slide:not(.swiper-slide-active)
  .audience-comment-card {
  border-color: rgb(var(--audience-edge) / 17%);
}

.audience-saying__swiper .swiper-slide-prev .audience-comment-card,
.audience-saying__swiper .swiper-slide-next .audience-comment-card {
  box-shadow:
    0 2px 2px rgb(var(--audience-edge) / 8%),
    0 16px 34px rgb(var(--audience-edge) / 18%);
}

.audience-saying__swiper .swiper-slide-active .audience-comment-card {
  box-shadow:
    0 3px 3px rgb(var(--audience-edge) / 4%),
    0 34px 82px rgb(var(--audience-edge) / 17%),
    0 1px 0 rgb(255 255 255 / 80%) inset;
}

.audience-comment-card__header,
.audience-commenter,
.audience-comment-card__facts,
.audience-like-count,
.audience-channel {
  display: flex;
  align-items: center;
}

.audience-comment-card img[data-audience-src] {
  visibility: hidden;
}

.audience-comment-card__header {
  justify-content: space-between;
  gap: 1rem;
}

.audience-commenter {
  min-width: 0;
  gap: 0.75rem;
}

.audience-commenter__avatar {
  position: relative;
  display: grid;
  flex: 0 0 auto;
  width: 2.75rem;
  height: 2.75rem;
  overflow: hidden;
  border: 1px solid rgb(var(--audience-edge) / 9%);
  border-radius: 50%;
  color: #fff;
  background:
    radial-gradient(circle at 28% 24%, hsl(var(--avatar-hue) 82% 72%), transparent 42%),
    hsl(var(--avatar-hue) 55% 34%);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  isolation: isolate;
  place-items: center;
}

.audience-commenter__initials {
  position: relative;
  z-index: 0;
}

.audience-commenter__avatar img {
  position: absolute;
  z-index: 1;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  object-fit: cover;
}

.audience-commenter__copy {
  display: grid;
  min-width: 0;
  gap: 0.22rem;
}

.audience-commenter__copy strong {
  overflow: hidden;
  font-size: 0.92rem;
  font-weight: 600;
  line-height: 1.1;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.audience-commenter__copy small {
  color: var(--audience-muted);
  font-size: 0.72rem;
  line-height: 1.2;
}

.audience-comment-card__source {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
}

.audience-comment-card__rank {
  display: inline-flex;
  min-width: 2.4rem;
  min-height: 2rem;
  align-items: center;
  justify-content: center;
  color: var(--audience-ink);
  font-family: Geistmono, "Geist Mono", ui-monospace, monospace;
  font-size: 0.94rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-decoration: none;
  transition: opacity 160ms ease;
}

.audience-comment-card__rank:hover {
  opacity: 0.55;
}

.audience-comment-card__body {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  flex-direction: column;
  /* SAFE centring (Mena 2026-08-18). Plain `center` spills overflow off BOTH
     ends, so an over-tall quote loses its first line off the top of the card,
     under the header — the start of the sentence, i.e. the part that matters.
     `safe center` centres while there is room and falls back to start
     alignment the moment the content is taller than the box, so the quote can
     only ever be cut at the END. This is the always-on backstop; the JS fit
     below is what should keep it from overflowing at all. */
  justify-content: safe center;
  padding: 1.35rem 0 1.1rem;
}

.audience-comment-card.is-density-critical .audience-comment-card__body {
  justify-content: flex-start;
}

.audience-comment-card__quote {
  --quote-min: 1.05rem;
  display: block;
  flex: 0 0 auto;
  margin: 0;
  padding: 0;
  border: 0;
  font-size: clamp(2.35rem, 3.8vw, 3.65rem);
  font-weight: 500;
  letter-spacing: -0.044em;
  line-height: 1.035;
  text-wrap: balance;
  white-space: pre-line;
}

.audience-comment-card__quote.is-punchy {
  font-size: clamp(4rem, 6.2vw, 5.9rem);
  letter-spacing: -0.052em;
  line-height: 0.98;
}

.audience-comment-card__quote.is-short {
  font-size: clamp(3.15rem, 5vw, 4.7rem);
  line-height: 1;
}

.audience-comment-card__quote.is-medium {
  font-size: clamp(2.45rem, 3.9vw, 3.65rem);
}

.audience-comment-card__quote.is-long {
  font-size: clamp(1.95rem, 3vw, 2.8rem);
  letter-spacing: -0.036em;
  line-height: 1.075;
}

.audience-comment-card__quote.is-very-long {
  font-size: clamp(1.6rem, 2.35vw, 2.2rem);
  letter-spacing: -0.026em;
  line-height: 1.11;
}

.audience-comment-card__timecode {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 0.3rem;
  padding: 0.38rem 0.52rem 0.36rem;
  border: 1px solid rgb(var(--audience-edge) / 14%);
  border-radius: 999px;
  color: var(--audience-ink);
  background: var(--audience-canvas);
  font-family: Geistmono, "Geist Mono", ui-monospace, monospace;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  line-height: 1;
  text-decoration: none;
  transition: border-color 160ms ease, background-color 160ms ease;
}

.audience-comment-card__timecode svg {
  width: 0.64rem;
  height: 0.64rem;
  fill: currentColor;
}

.audience-comment-card__timecode:hover {
  border-color: rgb(var(--audience-edge) / 28%);
  background: var(--audience-canvas-hover);
}

.audience-comment-card__quote.has-timecode {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  gap: clamp(0.55rem, 1.4vh, 0.8rem);
}

.audience-comment-card__quote-text {
  display: block;
  min-width: 0;
}

.audience-comment-card__original {
  display: grid;
  flex: 0 0 auto;
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  gap: 0.38rem;
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  margin-top: clamp(1rem, 2.2vh, 1.45rem);
  color: var(--audience-muted);
}

.audience-comment-card__original-label,
.audience-comment-card__facts,
.audience-comment-card__original-label {
  color: var(--audience-ink);
}

.audience-comment-card__original p {
  display: -webkit-box;
  max-width: 100%;
  overflow: hidden;
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.45;
  text-overflow: ellipsis;
  white-space: normal;
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.audience-comment-card__facts {
  justify-content: space-between;
  gap: 1rem;
  margin-top: 0;
  padding-top: 1rem;
  border-top: 1px solid rgb(var(--audience-edge) / 11%);
  color: var(--audience-muted);
}

.audience-comment-card__facts > span:last-child {
  color: var(--audience-ink);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.055em;
}

.audience-like-count {
  gap: 0.5rem;
}

/* The facts-row channel is a PHONE-only copy of the block that lives inside
   the video link. Hidden here so desktop is exactly as it was. */
.audience-channel--facts {
  display: none;
}

.audience-like-count svg {
  width: 0.95rem;
  height: 0.95rem;
  fill: currentColor;
}

.audience-video-context {
  display: grid;
  grid-template-areas: "thumb copy reach";
  grid-template-columns: 10.75rem minmax(0, 1fr) auto;
  gap: 0.9rem;
  min-height: 7.15rem;
  margin-top: 1rem;
  padding: 0.5rem 0.95rem 0.5rem 0.5rem;
  border-radius: 1.1rem;
  color: var(--audience-ink);
  background: var(--audience-canvas);
  text-decoration: none;
  transition: background-color 160ms ease;
}

.audience-video-context:hover {
  background: var(--audience-canvas-hover);
}

.audience-video-context__thumbnail {
  position: relative;
  grid-area: thumb;
  align-self: center;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 0.75rem;
  background: #222;
}

.audience-video-context__thumbnail img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 360ms cubic-bezier(0.22, 1, 0.36, 1);
}

.audience-video-context:hover .audience-video-context__thumbnail img {
  transform: scale(1.04);
}

.audience-video-context__duration {
  position: absolute;
  right: 0.35rem;
  bottom: 0.35rem;
  padding: 0.2rem 0.32rem;
  border-radius: 0.3rem;
  color: #fff;
  background: rgb(19 19 19 / 88%);
  font-family: Geistmono, "Geist Mono", ui-monospace, monospace;
  font-size: 0.55rem;
  line-height: 1;
}

.audience-video-context__copy {
  display: grid;
  grid-area: copy;
  min-width: 0;
  align-content: center;
  gap: 0.38rem;
}

.audience-video-context__copy > small {
  color: var(--audience-muted);
}

.audience-video-context__copy > strong {
  display: -webkit-box;
  overflow: hidden;
  font-size: 0.88rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.2;
  text-overflow: ellipsis;
  white-space: normal;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.audience-channel {
  min-width: 0;
  gap: 0.42rem;
  color: var(--audience-muted);
  font-family: "Plus Jakarta Sans", Arial, sans-serif;
  font-size: 0.66rem;
  font-style: normal;
  font-variant: normal;
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 1.2;
  text-transform: none;
}

.audience-channel img {
  flex: 0 0 auto;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 50%;
  object-fit: cover;
}

.audience-channel__copy {
  display: flex;
  min-width: 0;
  align-items: baseline;
  gap: 0.28rem;
  overflow: hidden;
  white-space: nowrap;
}

.audience-channel__name {
  overflow: hidden;
  /* was a hardcoded #555: 1.9:1 on the dark card, a WCAG AA failure. The
     six sibling muted rules in this file already use the variable, and the
     dark block at the end of this file redefines it for the whole section,
     which is why every other muted string adapts and this one did not. */
  color: var(--audience-muted);
  font-weight: 500;
  text-overflow: ellipsis;
}

.audience-channel__separator {
  flex: 0 0 auto;
  opacity: 0.58;
}

.audience-channel__subscribers {
  flex: 0 0 auto;
}

/* Phone (Mena 2026-08-28): "get rid of the sub count on mobile cards, that
   should let the whole name be visible". Exactly right about the cause. The
   row is nowrap with overflow hidden, and the separator and the count are
   flex:0 0 auto, so they hold their width while .audience-channel__name is the
   only flexible thing left and takes the ellipsis. Removing them hands the
   whole row back to the name. Desktop has the width for both and keeps them. */
@media (max-width: 767px) {
  .audience-channel__separator,
  .audience-channel__subscribers {
    display: none;
  }
}

.audience-video-context__reach {
  display: grid;
  grid-area: reach;
  align-content: center;
  justify-items: end;
  gap: 0.25rem;
  text-align: right;
}

.audience-video-context__reach strong {
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1;
}

.audience-video-context__reach small {
  color: var(--audience-muted);
  font-size: 0.65rem;
  line-height: 1;
}

.audience-saying__status {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Dark mode (Mena 2026-08-18: "the audience voices cards dont adapt to
   dark mode"). The section itself always used the site's theme tokens, so
   its background flipped to near-black — but the CARD palette was four
   hardcoded LIGHT values with no dark counterpart, so white cards with
   near-black text sat on a near-black section. The previous
   `html[data-theme="dark"] .audience-comment-card` rule re-declared
   `color: var(--audience-ink); background: var(--audience-paper)` — the
   very same variables — so it was a no-op for colour and only carried
   box-shadow. Fixed at the source: redefine the palette once here and all
   18 consumers (cards, chips, timecodes, dividers, muted text) follow. */
html[data-theme="dark"] .section_audience-saying {
  --audience-ink: var(--text-color--text-primary, #fff);
  /* one step above the #131313 section so the card still reads as a
     raised surface without going as pale as --bg-color--bg-secondary */
  --audience-paper: #1e1e1e;
  --audience-canvas: #2b2b2b;
  --audience-canvas-hover: #363636;
  --audience-muted: var(--text-color--text-secondary, #c7c7c7);
  --audience-edge: 255 255 255;
}

html[data-theme="dark"] .audience-comment-card {
  box-shadow: none;
}

html[data-theme="dark"]
  .audience-saying__swiper
  .swiper-slide-prev
  .audience-comment-card,
html[data-theme="dark"]
  .audience-saying__swiper
  .swiper-slide-next
  .audience-comment-card {
  box-shadow:
    0 2px 2px rgb(0 0 0 / 12%),
    0 16px 34px rgb(0 0 0 / 28%);
}

html[data-theme="dark"]
  .audience-saying__swiper
  .swiper-slide-active
  .audience-comment-card {
  /* The light theme's inset highlight is a white hairline meant to catch
     light on a white card; on a dark card it reads as a bright seam, so
     it is dialled down rather than dropped. */
  box-shadow:
    0 3px 3px rgb(0 0 0 / 12%),
    0 30px 70px rgb(0 0 0 / 34%),
    0 1px 0 rgb(255 255 255 / 6%) inset;
}

html[data-theme="dark"] .audience-comment-card img {
  filter: none;
}

@media (max-width: 1100px) {
  .audience-saying__layout {
    grid-template-columns: minmax(15rem, 0.6fr) minmax(31rem, 1.4fr);
    gap: 3rem;
  }

  .audience-saying__swiper.swiper {
    height: 40rem;
  }
}

@media (max-width: 900px) {
  /* Padding override removed 2026-08-18: it only existed to scale the old
     oversized desktop value down. The base 4.5rem now matches the site's
     section rhythm at every width. */

  .audience-saying__layout {
    grid-template-columns: minmax(0, 1fr);
    gap: 4rem;
  }

  /* This block used to lay the intro out as a two-column grid: eyebrow tag,
     headline and subline stacked in column one, the arrows pinned to column
     two. All four of those are gone now (2026-08-18) — the subline and the
     eyebrow tag were removed, and the controls moved under the deck — so the
     header is a lone headline and the grid is deleted rather than left behind
     as dead rules. */

  .audience-saying__intro h2 {
    max-width: 11ch;
  }

  .audience-saying__stage {
    width: min(100%, 43rem);
  }

  /* Card scale-down (Mena 2026-08-18): the desktop 40rem card towered
     on smaller screens. */
  .audience-saying__swiper.swiper {
    height: 34rem;
  }
}

@media (max-width: 600px) {
  /* Padding override removed 2026-08-18 — see the 900px note above. */

  .audience-saying__layout {
    gap: 3rem;
  }

  .audience-saying__intro {
    display: block;
  }

  .audience-saying__intro h2 {
    max-width: 9ch;
    margin-top: 1.35rem;
    font-size: clamp(3rem, 15vw, 4.3rem);
  }

  .audience-saying__intro-copy {
    max-width: 22rem;
    margin-top: 1.35rem;
    font-size: 0.95rem;
  }

  .audience-saying__controls {
    margin-top: 1.5rem;
  }

  .audience-saying__swiper.swiper {
    /* Mena 2026-08-28: "i hate how this section is touching the edges of the
       screen. make it smaller so i can see it fully."

       The deck is Swiper's cards effect with default perSlideOffset 8px and
       perSlideRotate 2deg, so the two cards behind the top one sit at 8px/16px
       across and 2deg/4deg of tilt. At this 31rem (496px) card height a 4deg
       tilt throws the corner a further (496/2)*sin(4deg) = 17px sideways, so
       the fan reaches about 33px past the top card. The old 1.7rem total gave
       it only 13.6px per side, which is why the back cards were being sliced
       off by the viewport. 5rem total = 40px per side clears the whole fan
       with room to spare. */
    width: calc(100% - 5rem);
    /* was 40.5rem — a 648px tower on a 375px phone (Mena 2026-08-18) */
    height: 31rem;
  }

  .audience-comment-card {
    padding: 1.35rem;
    border-radius: 1.45rem;
  }

  .audience-saying__swiper .swiper-slide,
  .audience-saying__swiper .swiper-slide-shadow {
    border-radius: 1.45rem;
  }

  .audience-commenter__avatar {
    width: 2.45rem;
    height: 2.45rem;
  }

  .audience-commenter__copy strong {
    max-width: 9rem;
    font-size: 0.82rem;
  }

  .audience-commenter__copy small {
    font-size: 0.64rem;
  }

  .audience-comment-card__rank {
    min-width: 2rem;
    min-height: 1.8rem;
    font-size: 0.82rem;
  }

  .audience-comment-card__quote {
    --quote-min: 1rem;
    /* Ceiling that no bucket may exceed: the size at which the LONGEST WORD
       still fits the card. 64vw is the card's text column at this deck inset
       and card padding; 0.56em is the measured average glyph advance for this
       face at this tracking, with headroom. --quote-longest comes from
       audience-saying.js. Every bucket below is min()'d against it, so a long
       word steps the type down instead of being clipped. */
    --quote-cap: calc(64vw / (0.56 * var(--quote-longest, 1)));
    font-size: min(clamp(2rem, 8vw, 2.65rem), var(--quote-cap));
  }

  .audience-comment-card__quote.is-punchy {
    font-size: min(clamp(2.75rem, 12.5vw, 3.7rem), var(--quote-cap));
    line-height: 0.99;
  }

  .audience-comment-card__quote.is-short {
    font-size: min(clamp(2.35rem, 10vw, 3.15rem), var(--quote-cap));
  }

  .audience-comment-card__quote.is-medium {
    font-size: min(clamp(1.95rem, 8vw, 2.55rem), var(--quote-cap));
  }

  .audience-comment-card__quote.is-long {
    font-size: min(clamp(1.55rem, 6.5vw, 2rem), var(--quote-cap));
  }

  .audience-comment-card__quote.is-very-long {
    font-size: min(clamp(1.3rem, 5.3vw, 1.65rem), var(--quote-cap));
    line-height: 1.13;
  }

  .audience-comment-card__body {
    padding: 1rem 0 0.85rem;
  }

  .audience-comment-card__original {
    grid-template-columns: 1fr;
    gap: 0.35rem;
    margin-top: 1.2rem;
  }

  .audience-comment-card__original p {
    font-size: 0.74rem;
  }

  .audience-comment-card__facts {
    padding-top: 0.85rem;
    font-size: 0.56rem;
  }

  /* Video row on a phone (Mena 2026-08-28: the thumbnail "looks forced", he
     wants it the same height as the title/channel/views block, the way it
     reads on desktop).

     It looked forced for two reasons, both fixed here.

     1. The box was pinned to min-height 6.4rem = 102px while its content only
        needed about 72px, so a 56px thumbnail floated in a box nearly twice
        its height. The min-height is gone; the row now hugs its content.

     2. The views sat on their own third row, so the text column was three rows
        tall against a two-row thumbnail and the two could never agree. Views
        now share the channel's row. Measured at 440px: title 2 lines + channel
        row = 52.8px, and the existing 6.25rem thumbnail is 56.3px, so they
        agree within 3.5px with NO change to the card width.

     Widening the card was the other candidate and it does not work. Matching a
     three-row text block needs a 127px thumbnail, which leaves 160px for the
     title, which wraps to more lines, which makes the block taller again. It
     never converges. The card would have to reach about 421px on a 440px
     screen, leaving 9px of margin for a card fan that needs 33px, which is the
     edge-clipping we had just removed.

     `display: contents` on the copy wrapper promotes the title and the channel
     row into THIS grid so views can sit beside the channel, which they cannot
     do while they live in different parents. The thumbnail spans both rows, so
     grid sizes the rows to it and the two columns end up the same height by
     construction rather than by a hardcoded number. */
  /* Phone swap (Mena 2026-08-28): "remove the like count and replace that with
     the channel pfp and name, then put the views where the channel currently
     is. comment like count isnt that important."

     Right call. Squeezing the channel name and the views onto one row inside
     the video block left the name a sliver, which is why it read "Dude ...".
     The facts row is nearly empty by comparison, so the channel gets that
     whole row and the views take the roomier slot below the title.

     The two channel copies come from ONE template in audience-saying.js and
     only one is ever displayed. */
  .audience-like-count {
    display: none;
  }

  .audience-channel--facts {
    display: flex;
    min-width: 0;
  }

  .audience-video-context .audience-channel {
    display: none;
  }

  .audience-video-context {
    grid-template-areas:
      "thumb title"
      "thumb reach";
    grid-template-columns: 6.25rem minmax(0, 1fr);
    gap: 0.25rem 0.7rem;
    min-height: 0;
    padding-right: 0.65rem;
  }

  .audience-video-context__copy {
    display: contents;
  }

  .audience-video-context__copy > strong {
    grid-area: title;
    align-self: end;
  }

  /* The thumbnail spans both rows and is the tallest item, so it sets the row
     heights. Ending the title and starting the views brings them together in
     the middle, level with the thumbnail, instead of splitting to the edges. */
  .audience-video-context__reach {
    grid-area: reach;
    align-self: start;
    justify-self: start;
  }

  .audience-video-context__copy > strong {
    font-size: 0.75rem;
  }

  .audience-channel {
    font-size: 0.58rem;
  }

  .audience-video-context__reach {
    display: flex;
    align-items: baseline;
    gap: 0.35rem;
  }

  .audience-video-context__reach strong {
    font-size: 0.78rem;
  }

  .audience-video-context__reach small {
    font-size: 0.58rem;
  }
}

@media (max-width: 350px) {
  .audience-saying__swiper.swiper {
    height: 39.5rem;
  }

  .audience-comment-card {
    padding: 1.15rem;
  }

  .audience-commenter__copy strong {
    max-width: 7.2rem;
  }

  .audience-video-context {
    grid-template-columns: 5.35rem minmax(0, 1fr);
  }

  .audience-channel img {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .audience-comment-card::before,
  .audience-saying__button,
  .audience-video-context__thumbnail img {
    transition: none;
  }

  .audience-saying__button:hover,
  .audience-video-context:hover .audience-video-context__thumbnail img {
    transform: none;
  }
}

/* ── Header-on-top conform (Mena 2026-08-18) ─────────────────────────
   Site-wide pattern pass: every section leads with its text block on
   top, centered — at EVERY breakpoint (the first cut scoped this to
   desktop and left tablet/phone on the old left-aligned side-layout
   rules; Mena flagged the mismatch). These rules sit after the ≤900px
   block so they override its intro grid. */
.audience-saying__layout {
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  gap: clamp(3rem, 5vw, 4.5rem);
}

.audience-saying__intro {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.audience-saying__intro-copy {
  margin-top: 1.6rem;
  max-width: 34rem;
}

.audience-saying__controls {
  justify-content: center;
  align-self: center; /* the old ≤900 grid pinned these to the right */
  margin-top: 1.9rem;
}

/* Cohesion (Mena 2026-08-18): the headline uses the template's
   section-h2 tokens at every breakpoint — same size as Expertise,
   Pricing, How it works — instead of the old oversized side-layout
   scale. */
.audience-saying__intro h2 {
  max-width: none;
  font-size: var(--_typography---h2--font-size);
  line-height: var(--_typography---h2--line-height);
  letter-spacing: var(--_typography---h2--letter-spacing);
}


/* ══ LAST IN THE FILE ON PURPOSE ═══════════════════════════════════════════
   The touch deck is a MODE override, not a width override, so it has to
   outrank every width query above it rather than sit among them.

   This was got wrong first time and Mena felt it within minutes ("swiping
   through the comments cards, its laggy all of a sudden"). Written above the
   width queries, the 600px block below-and-after it still won on source
   order, so his phone kept `width: calc(100% - 5rem)` and `height: 31rem`,
   both of which exist purely to give the FAN room for its 8px offset and
   4deg tilt. On a track that inset is dead space, and the fixed height is
   actively expensive: cards overflow it, so fitQuote's binary search runs to
   full depth on every card on every virtual re-render, mid-drag. With the
   track's content-driven height almost nothing overflows and the same search
   settles on the first probe.

   Source order is the whole mechanism here. Anything added below this block
   that targets the deck will silently win on phones. Add it inside. */
/* ── Touch deck: the sliding track ────────────────────────────────────────
   Pairs with TOUCH_DECK in audience-saying.js, which swaps Swiper's "cards"
   effect for a plain slide on touch devices. The comment there carries the
   reasoning and Mena's acceptance. Same query on both sides, deliberately
   pointer-based rather than width-based, so a phone in landscape stays a
   track. Everything below only unwinds the 3D deck presentation; the card's
   own type, colour and layout are untouched. */
@media (hover: none), (pointer: coarse) {
  .audience-saying__stage {
    /* The fan's 3D space. A sliding track has no depth to render, and leaving
       the perspective on gives the compositor a 3D context to maintain for
       every slide it moves. */
    perspective: none;
    perspective-origin: 50% 50%;
  }

  .audience-saying__swiper.swiper {
    /* Full bleed of its column: the track supplies its own inset via
       slidesPerView, so the 3.5rem the fan reserved for its side cards would
       double up. Height is content-driven because slides are no longer
       absolutely stacked. */
    width: 100%;
    height: auto;
    overflow: visible;
  }

  .audience-saying__swiper .swiper-wrapper {
    align-items: stretch;
  }

  .audience-saying__swiper .swiper-slide {
    height: auto;
    /* All three of these exist to serve the fan's 3D space and cost real
       compositor work once there is no 3D left. On the track Swiper moves the
       WRAPPER, not the individual slides, so promoting every slide to its own
       layer with will-change buys nothing and multiplies the layers iOS has
       to keep around. */
    backface-visibility: visible;
    transform-style: flat;
    will-change: auto;
  }

  .audience-saying__swiper .audience-comment-card {
    backface-visibility: visible;
    transform-style: flat;
  }

  .audience-saying__swiper .swiper-slide .audience-comment-card {
    height: 100%;
  }

  /* The grey back-card (Mena 2026-08-28: "i dont like the grey on the light
     mode the white card is better"). It exists to fake the fan's stacked
     paper: on the fanned deck the neighbours sit BEHIND the active card, so
     they are tinted down. On a track they sit BESIDE it in full view, and the
     tint just reads as a discoloured card. */
  .audience-saying__swiper .audience-comment-card::before {
    opacity: 0;
    transition: none;
  }

  /* Matching the flat presentation: on a track the neighbours are peers, not
     background, so they carry the same edge and shadow as the active card. */
  .audience-saying__swiper
    .swiper-slide:not(.swiper-slide-active)
    .audience-comment-card {
    border-color: rgb(var(--audience-edge) / 17%);
  }
}

