/* Round 22 · V3 · the testimonials section (#words) and its Testimonials options (body.words--N).
   Loads after v3.css, so a rule here wins over an equal one there. Owned by the testimonials builder.
   One markup, three ways to set the two quotes side by side; the face, the colours and the controls come from the
   other options. Text only: no screens, films, photos, logos, avatars or ratings. All three keep both quotes in view
   at once, at the same size; each differs from choice 2 on one thing only:
     1 In two panels · FRAMING. The pair level, as in 2, but each quote is held in its own panel (the components option's
                       card): number at the top, quote under it, both credits pinned to the panels' foot on one line.
     2 Side by side  · an editorial pair under a rule, a hairline between them, both credits on one baseline. (Untouched.)
     3 Staggered     · POSITION. Open type, as in 2, but the second quote steps down: its rule starts on the line where the
                       first quote is signed, so the first quote's credit rule runs on into the second quote's rule.
                       Each quote arrives on its own as you reach it.
   Phone (under 900px): all three stack, one quote under the other. 1 keeps its two panels; 3 keeps its step as an
   indent: the second quote and its rule start 48px in.
   Grid: 12 columns, 24px gutter (4 and 16px on a phone). Spacing scale only: 4 8 12 16 24 32 48 64 96 128 160 200. */

/* ── shared ─────────────────────────────────────────────────── */
#words {
  --tm-fs-ph: calc(clamp(22px, 2.4vw + 13px, 27px) * var(--ds2));   /* round 23: a quote on a phone stays well under the heading */
  --tm-lh: 1.1;                 /* the quotes' leading, set per face */
  --tm-w: var(--w-d2);          /* the quotes' weight */
  --tm-mark: var(--accent);     /* the hanging opening mark */
  --tm-ease: cubic-bezier(.16, 1, .3, 1);   /* expo out */
}
body.type--1 #words { --tm-lh: 1.1; --tm-w: 500; }      /* Clash Display: sharp and a little narrow; 500 keeps a long quote light */
body.type--2 #words { --tm-lh: 1.08; --tm-w: 500; }     /* Cabinet Grotesk: 700 shouts across four lines; 500 reads */
body.type--3 #words { --tm-lh: 1.16; --tm-w: 500; }     /* Syne: wide, needs air between lines */
body.type--4 #words { --tm-lh: 1.14; --tm-w: 500; }     /* Sora: big x-height and round, a touch more air */
body.type--5 #words { --tm-lh: 1.26; --tm-w: 500; }     /* Panchang: very wide and set small, so the lines need the most air */
body.type--6 #words { --tm-lh: 1.12; --tm-w: 500; }     /* Geist */

.tm__head { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: 24px; align-items: last baseline; }
.tm__h { grid-column: 1 / 8; max-width: none; }
#words .tm__note { grid-column: 9 / 13; justify-self: end; margin: 0; text-wrap: pretty; }
body.comp--3 #words .tm__note { border-radius: 4px; }

.tm__count, .tm__rules { display: none; }
.tm__list { position: relative; }
.tm__item { position: relative; margin: 0; min-width: 0; }
.tm__q { margin: 0; }
.tm__text {
  position: relative;
  font-family: var(--f-d); font-weight: var(--tm-w); letter-spacing: var(--t-d2); font-variation-settings: var(--fvs);
  text-transform: var(--case-d); line-height: var(--tm-lh); color: var(--ink);
  text-wrap: balance; font-kerning: normal; font-variant-numeric: lining-nums;
}
/* the opening mark hangs outside the text block; every word is a window it can rise through */
.tm__hang { position: absolute; right: 100%; top: 0; color: var(--tm-mark); }
.tw, .tm__hang { display: inline-block; vertical-align: top; overflow: hidden; }
.tw { padding: .08em .06em .2em; margin: -.08em -.06em -.2em; }
.tm__hang { padding: .08em .05em .2em .02em; margin: -.08em 0 -.2em; }
.twi { display: inline-block; }

.tm__no { display: block; font-family: var(--f-l); font-weight: var(--w-l); font-size: 13px; line-height: 1.4; letter-spacing: .04em; color: var(--muted); font-variant-numeric: tabular-nums; }
.tm__by { display: flex; align-items: center; gap: 16px; margin: 0; font-family: var(--f-l); font-weight: var(--w-l); font-size: 15px; line-height: 1.4; text-transform: var(--tt-l); letter-spacing: var(--ls-l); color: var(--muted); }
/* the three faces whose labels are set in small capitals: Manrope, Supreme, and Geist Mono (a mono runs wide, so smaller) */
body.type--3 .tm__by, body.type--5 .tm__by { font-size: 12.5px; }
body.type--6 .tm__by { font-size: 12px; }
.tm__rule { flex: none; width: 48px; height: 1px; background: var(--accent); transform-origin: 0 50%; }
body.colour--2 .tm__rule { background: var(--ink); }      /* the acid colour stays for the marks, not the rules */
/* in 1 and 3 a long credit can wrap on a phone: the rule then stays on its first line instead of floating between two */
body.words--1 .tm__by, body.words--3 .tm__by { align-items: flex-start; }
body.words--1 .tm__rule, body.words--3 .tm__rule { margin-top: calc(.7em - .5px); }
.tm__bym { display: block; min-width: 0; overflow: hidden; padding: .1em 0; margin: -.1em 0; }
.tm__byi { display: block; }

/* ── 1 · in two panels ────────────────────────────────────────
   The same level pair at the same size as 2; the difference is the frame. Each quote sits in its own panel, which takes
   its fill, edge, corner and shadow from the components option (so it always matches the site's other cards), lit very
   faintly from its top corner. The number keeps the top of the panel, the quote follows it, and the credit is pinned to
   the foot, so the two credits share a line however long either quote runs. */
body.words--1 .tm__head { margin-bottom: 96px; }
body.words--1 .tm__list { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: 24px; }
body.words--1 .tm__item {
  grid-column: span 6; display: flex; flex-direction: column; align-items: stretch; min-height: 440px;
  padding: 40px 48px 48px 64px;
  background: radial-gradient(120% 90% at 0% 0%, color-mix(in srgb, var(--accent) 7%, transparent), transparent 62%), var(--card-bg);
  border: 1px solid var(--card-line); border-radius: var(--card-r); box-shadow: var(--card-shadow);
}
/* the outline-only cards (comp--3) carry no fill, so the light would float on nothing: leave it out there */
body.comp--3.words--1 .tm__item { background: var(--card-bg); }
body.words--1 .tm__no { margin-bottom: 64px; }
body.words--1 .tm__q { font-size: calc(clamp(26px, 2.5vw, 40px) * var(--ds2)); }
body.words--1 .tm__by { margin-top: auto; padding-top: 64px; }

/* ── 2 · side by side ─────────────────────────────────────────
   Both quotes at a calmer size in two columns under one rule, a hairline between them; each number sits in the
   margin on its quote's first baseline, the marks hang, and both credits share one baseline at the foot. */
body.words--2 .tm__head { margin-bottom: 96px; }
body.words--2 .tm__list {
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); grid-template-rows: auto auto; column-gap: 24px; row-gap: 64px;
  padding: 64px 0;
}
body.words--2 .tm__rules { display: block; position: absolute; inset: 0; pointer-events: none; }
.tm__rl { position: absolute; display: block; background: var(--line-2); }
.tm__rl--top { left: 0; right: 0; top: 0; height: 1px; transform-origin: 0 50%; }
.tm__rl--end { left: 0; right: 0; bottom: 0; height: 1px; transform-origin: 0 50%; background: var(--line); }
.tm__rl--mid { left: 50%; top: 0; bottom: 0; width: 1px; transform-origin: 50% 0; }
body.words--2 .tm__item { grid-row: 1 / -1; display: grid; grid-template-columns: subgrid; grid-template-rows: subgrid; }
body.words--2 .tm__item:nth-of-type(1) { grid-column: 1 / 7; }
body.words--2 .tm__item:nth-of-type(2) { grid-column: 7 / 13; }
/* each number stands just before its quote's hanging mark, on the first line's baseline (--tm-hw: the mark's width, measured) */
body.words--2 .tm__no { grid-column: 1; grid-row: 1; align-self: first baseline; justify-self: end; margin-right: calc(var(--tm-hw, 20px) - 10px); }
body.words--2 .tm__q { grid-column: 2 / -1; grid-row: 1; align-self: first baseline; font-size: calc(clamp(26px, 2.5vw, 40px) * var(--ds2)); padding-right: 24px; }
body.words--2 .tm__by { grid-column: 2 / -1; grid-row: 2; align-self: start; }

/* ── 3 · staggered ────────────────────────────────────────────
   Open type at the same size as 2, number in the margin, mark hanging; the difference is where the second quote sits.
   Each quote has its own rule over its own six columns, and the second steps down so its rule lies on the line of the
   first quote's credit rule (--tm-off, measured by v3-words.js; 200px until it is). Read left to right, the first
   quote's credit runs on into the second quote's rule: one line, two steps. */
body.words--3 .tm__head { margin-bottom: 96px; }
body.words--3 .tm__list { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: 24px; align-items: start; padding-bottom: 32px; }
body.words--3 .tm__item { display: grid; grid-template-columns: subgrid; grid-template-rows: auto auto; row-gap: 64px; padding-top: 64px; }
body.words--3 .tm__item::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px; background: var(--line-2); transform-origin: 0 50%; }
body.words--3 .tm__item:nth-of-type(1) { grid-column: 1 / 7; }
body.words--3 .tm__item:nth-of-type(2) { grid-column: 7 / 13; margin-top: var(--tm-off, 200px); }
body.words--3 .tm__no { grid-column: 1; grid-row: 1; align-self: first baseline; justify-self: end; margin-right: calc(var(--tm-hw, 20px) - 10px); }
body.words--3 .tm__q { grid-column: 2 / -1; grid-row: 1; align-self: first baseline; font-size: calc(clamp(26px, 2.5vw, 40px) * var(--ds2)); padding-right: 24px; }
body.words--3 .tm__by { grid-column: 2 / -1; grid-row: 2; align-self: start; }

/* ── the reveals: set by v3-words.js only when the quotes are still below the screen ──
   1 and 2 arrive once, together, when the pair reaches the screen; 3 arrives quote by quote (the class sits on each
   quote rather than on the section). Transforms and opacity only. */
#words.tm--pre .twi, #words .tm__item.tm--pre .twi { transform: translate3d(0, 118%, 0); }
#words.tm--pre .tm__byi, #words .tm__item.tm--pre .tm__byi { transform: translate3d(0, 110%, 0); }
#words.tm--pre .tm__no, #words .tm__item.tm--pre .tm__no { opacity: 0; transform: translate3d(0, 12px, 0); }
#words.tm--pre .tm__rule, #words.tm--pre .tm__rl--top, #words.tm--pre .tm__rl--end { transform: scaleX(0); }
#words.tm--pre .tm__rl--mid { transform: scaleY(0); }
#words .tm__item.tm--pre .tm__rule, body.words--3 #words .tm__item.tm--pre::before { transform: scaleX(0); }
body.words--1 #words.tm--pre .tm__item { opacity: 0; transform: translate3d(0, 48px, 0); }
#words.tm--in .twi, #words.tm--in .tm__byi, #words.tm--in .tm__no, #words.tm--in .tm__rule, #words.tm--in .tm__rl,
#words .tm__item.tm--in .twi, #words .tm__item.tm--in .tm__byi, #words .tm__item.tm--in .tm__no, #words .tm__item.tm--in .tm__rule {
  transition: transform 1.4s var(--tm-ease), opacity 1s var(--tm-ease); transition-delay: var(--d, 0s);
}
#words.tm--in .tm__rl--top, #words.tm--in .tm__rl--end { transition-duration: 1.6s; }
#words.tm--in .tm__rl--mid { transition-duration: 1.8s; }
#words.tm--in .tm__item { transition: border-color 1.4s var(--tm-ease); }
body.words--1 #words.tm--in .tm__item { transition: transform 1.6s var(--tm-ease), opacity 1.2s var(--tm-ease); transition-delay: var(--d, 0s); }
body.words--3 #words .tm__item.tm--in::before { transition: transform 1.6s var(--tm-ease); }

/* ── phone ──────────────────────────────────────────────────── */
@media (max-width: 899px) {
  .tm__head { grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: 16px; align-items: start; }
  .tm__h, #words .tm__note { grid-column: 1 / -1; justify-self: start; }
  #words .tm__note { margin-top: 24px; }
  /* on a phone the mark hangs inside the text's own margin, level with the numbers above it */
  .tm__q { padding-left: .5em; }
  .tm__by { font-size: 14px; }
  body.type--3 .tm__by, body.type--5 .tm__by { font-size: 12px; }
  body.type--6 .tm__by { font-size: 11.5px; }
  .tm__rule { width: 32px; }

  /* 1: the two panels stack, 16px apart, each still a panel */
  body.words--1 .tm__head { margin-bottom: 64px; }
  body.words--1 .tm__list { display: grid; grid-template-columns: minmax(0, 1fr); row-gap: 16px; }
  body.words--1 .tm__item { grid-column: 1; min-height: 0; padding: 24px 20px 32px 24px; }
  body.words--1 .tm__no { margin-bottom: 32px; }
  body.words--1 .tm__q { font-size: var(--tm-fs-ph); }
  body.words--1 .tm__by { padding-top: 40px; }

  body.words--2 .tm__head { margin-bottom: 64px; }
  body.words--2 .tm__list { display: block; padding: 0; }
  body.words--2 .tm__rules { display: none; }
  body.words--2 .tm__item { display: block; padding: 32px 0 48px; border-top: 1px solid var(--line-2); }
  body.words--2 .tm__item:last-of-type { border-bottom: 1px solid var(--line); }
  body.words--2 .tm__item:nth-of-type(2) .tm__no { padding-left: 0; }
  body.words--2 .tm__no { margin: 0 0 24px; justify-self: start; }
  body.words--2 .tm__q { font-size: var(--tm-fs-ph); padding-right: 0; }
  body.words--2 .tm__by { margin-top: 32px; }
  #words.tm--pre .tm__item { border-color: transparent; }

  /* 3: they stack, and the step becomes an indent: the second quote and its rule start 48px in (a full column
     squeezed the second quote to eight lines in the narrower faces) */
  body.words--3 .tm__head { margin-bottom: 64px; }
  body.words--3 .tm__list { display: block; padding-bottom: 0; }
  body.words--3 .tm__item { display: block; padding-top: 32px; }
  body.words--3 .tm__item:nth-of-type(2) { margin: 64px 0 0 48px; }
  body.words--3 .tm__no { margin: 0 0 24px; justify-self: start; }
  body.words--3 .tm__q { font-size: var(--tm-fs-ph); padding-right: 0; }
  body.words--3 .tm__by { margin-top: 32px; }
}

/* ── round 23 · the testimonials on a phone (body.tp--N, under 900px only) ──
   Whichever wide layout is picked, a phone shows one of these. The quotes stay under the heading in size.
     1 Swipe the panels · the two panels side by side in one row you slide, the next one peeking in (the wide pick, kept)
     2 Open list        · no panels: a large opening mark, the quote, the credit, a hairline between
     3 One at a time    · two tabs with the clients' names; tap one to read its quote */
.tm__tabs, .swipe-dots { display: none; }
@media (max-width: 899px) {
  body:is(.tp--1, .tp--2, .tp--3) .tm__q { padding-left: 0; font-size: var(--tm-fs-ph); }
  body:is(.tp--1, .tp--2, .tp--3) .tm__hang { position: static; }
  body:is(.tp--1, .tp--2, .tp--3) .tm__rules { display: none; }
  body:is(.tp--1, .tp--2, .tp--3) .tm__head { margin-bottom: 48px; }

  /* 1 · swipe the panels */
  body.tp--1:is(.words--1, .words--2, .words--3) .tm__list {
    display: flex; gap: 12px; padding: 0; margin-inline: calc(-1 * clamp(20px, 3.5vw, 56px)); padding-inline: clamp(20px, 3.5vw, 56px);
    scroll-padding-inline: clamp(20px, 3.5vw, 56px); overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior-x: contain; scrollbar-width: none;
  }
  body.tp--1 .tm__list::-webkit-scrollbar { display: none; }
  body.tp--1:is(.words--1, .words--2, .words--3) .tm__item {
    flex: 0 0 min(84%, 440px); scroll-snap-align: start; display: flex; flex-direction: column; min-height: 0; margin: 0;
    padding: 24px 24px 28px; border: 1px solid var(--card-line); border-radius: var(--card-r); box-shadow: none;
    background: radial-gradient(120% 90% at 0% 0%, color-mix(in srgb, var(--accent) 7%, transparent), transparent 62%), var(--card-bg);
  }
  body.tp--1:is(.words--1, .words--2, .words--3) .tm__no { margin: 0 0 32px; }
  body.tp--1:is(.words--1, .words--2, .words--3) .tm__by { margin-top: auto; padding-top: 32px; }
  body.tp--1 #words .swipe-dots { display: flex; }

  /* 2 · open list */
  body.tp--2:is(.words--1, .words--2, .words--3) .tm__list { display: block; padding: 0; }
  body.tp--2:is(.words--1, .words--2, .words--3) .tm__item {
    display: block; min-height: 0; margin: 0; padding: 32px 0 40px; background: none; box-shadow: none; border: 0; border-radius: 0; border-top: 1px solid var(--line-2);
  }
  body.tp--2:is(.words--1, .words--2, .words--3) .tm__item:last-of-type { border-bottom: 1px solid var(--line); }
  body.tp--2:is(.words--1, .words--2, .words--3) .tm__no { display: none; }
  body.tp--2 .tm__hang { display: block; width: fit-content; font-size: 3.4em; line-height: .9; height: .56em; margin-bottom: 12px; }
  body.tp--2:is(.words--1, .words--2, .words--3) .tm__by { margin-top: 24px; padding-top: 0; }

  /* 3 · one at a time */
  body.tp--3 .tm__tabs { display: flex; gap: 4px; padding: 4px; margin-bottom: 24px; border-radius: 999px; box-shadow: inset 0 0 0 1px var(--line-2); width: fit-content; max-width: 100%; }
  body.tp--3.comp--3 .tm__tabs { border-radius: 4px; }
  .tm__tab { min-height: 44px; padding: 0 18px; border: 0; border-radius: 999px; background: transparent; color: var(--muted); font-family: var(--f-l); font-weight: var(--w-l); font-size: var(--sz-l, 13px); text-transform: var(--tt-l); letter-spacing: var(--ls-l); cursor: pointer; transition: background-color .3s, color .3s; white-space: nowrap; }
  body.comp--3 .tm__tab { border-radius: 2px; }
  .tm__tab[aria-selected="true"] { background: color-mix(in srgb, var(--bg) 48%, #ffffff 18%); color: var(--ink); }
  .tm__tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  body.tp--3:is(.words--1, .words--2, .words--3) .tm__list { display: grid; grid-template-columns: minmax(0, 1fr); padding: 0; }
  body.tp--3:is(.words--1, .words--2, .words--3) .tm__item {
    grid-area: 1 / 1; display: flex; flex-direction: column; min-height: 0; margin: 0; padding: 28px 24px 28px;
    border: 1px solid var(--card-line); border-radius: var(--card-r); box-shadow: none; background: var(--card-bg);
    transition: opacity .5s var(--tm-ease), transform .6s var(--tm-ease);
  }
  body.tp--3:is(.words--1, .words--2, .words--3) .tm__item:not(.is-on) { opacity: 0; visibility: hidden; transform: translate3d(0, 12px, 0); }
  body.tp--3:is(.words--1, .words--2, .words--3) .tm__no { margin: 0 0 24px; }
  body.tp--3:is(.words--1, .words--2, .words--3) .tm__by { margin-top: auto; padding-top: 32px; }
}
/* the dots under a sliding row (testimonials 1 on a phone, "easy to say yes" 1 on a phone) */
.swipe-dots { justify-content: center; gap: 8px; margin-top: 24px; }
.swipe-dots i { width: 6px; height: 6px; border-radius: 999px; background: var(--line-2); transition: width .4s cubic-bezier(.22,1,.36,1), background-color .3s; }
.swipe-dots i.is-on { width: 20px; background: var(--ink); }
