/* ============================================================
 TASTE TESTER 2.0

 Ported from the approved mockup. Everything the site already owns was cut
 rather than copied: tokens and skins (juq.css), scrollbars (juq.css),
 box-sizing (juq.css line 43), the tooltip layer (site.js puts .tip on the
 body, so it already escapes the clipping the card does), and the page head
 (.eyebrow / .disp / .pg-sub).

 Feature classes are tt- prefixed. juq.css owns the short global names.
 ============================================================ */

/* ---------- THE FLAVOUR RAMP ----------
 A validated diverging scale, Bitter to Glazed, in two steppings: one for the
 dark surfaces (dark, spicy) and one for the light ones (light, sweet). Both
 clear colourblind separation at 14+ deltaE, normal-vision at 16+, and 3:1
 contrast against all four skin surfaces.

 Mild is a tinted slate, not grey. It leans cool on purpose: both of its
 neighbours are warm, and a yellow midpoint would be indistinguishable from
 either of them.

 These are listed in check-drift.mjs INTENTIONAL_COLOUR. They carry MEANING,
 not styling: a band that changed hue between skins would stop being a band.
 The two steppings exist for contrast against the surface, not for theming. */
:root, :root[data-skin="dark"], :root[data-skin="spicy"] {
--f-bitter:#159084; --f-sour:#98B81A; --f-mild:#7A8FD0;
--f-sweet:#D2761A;  --f-glazed:#B52D8E; --f-flag:#E5484D;
}
:root[data-skin="light"], :root[data-skin="sweet"] {
--f-bitter:#0A6E60; --f-sour:#6F8A08; --f-mild:#4F63AC;
--f-sweet:#AF5D0B;  --f-glazed:#8F1E6C; --f-flag:#C0272D;
}

/* SUB TENURE, one month to ten years.

   ONE HUE, DIM TO BRIGHT, which is the rule for a quantity that has an order:
   a rainbow would make six months and six years look like different KINDS of
   thing rather than different amounts of the same one. The flavour ramp above
   is a rainbow because a band is a category; this is not.

   Gold on purpose. It is the conventional colour for length of service, and it
   is the one warm hue the flavour ramp does not already own outright.

   The steps are Twitch's own milestones, not equal slices: 3, 6 and 12 months
   are where a badge actually changes, so a number just past one of them is a
   thing somebody noticed. Past two years it goes by years, because "38 months"
   is arithmetic the reader has to do.

   Dark first, then a darker set for the light skins, exactly as the flavour
   ramp does: these are for contrast against the surface, not for theming. */
:root, :root[data-skin="dark"], :root[data-skin="spicy"] {
--tn-1:#6E6A5C; --tn-2:#8A8163; --tn-3:#A89A63;
--tn-4:#C7B45E; --tn-5:#E2CB57; --tn-6:#FFE066;
}
:root[data-skin="light"], :root[data-skin="sweet"] {
--tn-1:#565143; --tn-2:#6E6647; --tn-3:#877946;
--tn-4:#9E8C3C; --tn-5:#B29B2E; --tn-6:#C4A80F;
}

/* The offline/online bar rides the SKIN'S OWN ACCENT, by decision, so it reads
 as part of the site rather than a colour flown in from elsewhere.

 It is the one place here not held to the separation floor: in the dark skin
 the accent sits 9.2 deltaE from the Sweet amber. That is safe ONLY because
 solid-versus-hatch carries the whole offline/online distinction, so the hue
 is atmosphere rather than information. Do not reuse this token anywhere the
 colour has to be told apart from a flavour. */
:root { --f-live: var(--accent); }

/* ---------- the build stamp ----------
   Sits tight under the wordmark like a stamp, not a sentence, and uses the same
   two-tone rule the title above it does: the plain word in ink, the one that
   names the thing in the accent. */
.tt-powered {
  display: inline-block; font-weight: 800; font-style: italic;
  text-transform: uppercase; font-size: var(--t-sm); letter-spacing: 0.04em;
  color: var(--muted); margin-top: var(--s-2);
}
.tt-powered b { font-weight: inherit; color: var(--ink); }
.tt-powered em { font-style: inherit; color: var(--accent); }

/* ---------- the one search box ---------- */
.tt-search { position: relative; margin-top: var(--s-8); }
.tt-search-in { display: flex; align-items: center; gap: var(--s-4);
  background: var(--surface); border: var(--bw) solid var(--line-strong);
  border-radius: var(--radius); padding: var(--s-4) var(--s-5); }
.tt-search-in:focus-within { border-color: var(--accent); }
.tt-search-in svg { width: 17px; height: 17px; flex: none; color: var(--muted); }
.tt-search input { flex: 1; min-width: 0; background: transparent; border: 0; outline: none;
  color: var(--ink); font: inherit; font-size: var(--t-md); }
.tt-search input::placeholder { color: var(--muted); }
.tt-clear { background: transparent; border: 0; color: var(--muted); cursor: pointer;
  font-size: var(--t-h3); line-height: 1; padding: 0 var(--s-2); }
.tt-clear:hover { color: var(--ink); }

.tt-drop { position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 60;
  background: var(--surface); border: var(--bw) solid var(--line-strong);
  border-radius: var(--radius); box-shadow: 6px 6px 0 var(--shadow);
  max-height: 60vh; overflow-y: auto; }
.tt-drop[hidden] { display: none; }
.tt-drop-h { padding: var(--s-4) var(--s-5) var(--s-2); border-top: var(--bw) solid var(--line); }
.tt-drop-h:first-child { border-top: 0; }
.tt-sr { width: 100%; display: flex; align-items: center; gap: var(--s-4); cursor: pointer;
  background: transparent; border: 0; text-align: left; color: var(--ink);
  padding: var(--s-3) var(--s-5); }
.tt-sr:hover, .tt-sr.hl { background: var(--surface-2); }
.tt-sr-art { width: 32px; height: 32px; border-radius: var(--radius); flex: none;
  background: var(--surface-2); border: var(--bw) solid var(--line);
  display: grid; place-items: center; font-weight: 900; font-style: italic; color: var(--muted); }

/* The picture lies OVER the initial rather than replacing it, so a slot is
   never empty: before the lookup lands, after a deleted account, and after a
   failed load (tasters.js removes the img, uncovering the letter again). */
.tt-row-pfp, .tt-sr-art, .tt-pfp { position: relative; overflow: hidden; }
.tt-pfp-img { position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block; }
.tt-sr-i { flex: 1; min-width: 0; }
.tt-sr-t { display: block; font-weight: 700; font-size: var(--t-md); }
.tt-sr-s { display: block; font-family: var(--f-mono); font-size: var(--t-mono); color: var(--muted); margin-top: 2px; }
.tt-sr-tag { font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted);
  border: var(--bw) solid var(--line-strong); border-radius: 2px; padding: 3px var(--s-3); flex: none; }
.tt-sr-tag.add { color: var(--accent); border-color: var(--accent); }
.tt-drop-msg { padding: var(--s-5); font-family: var(--f-mono); font-size: var(--t-mono); color: var(--muted); }

/* ---------- the weekly review, compact ----------
   A stats strip, not an essay: it answers "what was chat like" in one glance
   and opens the full write-up. The detail lives in the same vault modal the
   report cards use, so there is one way to read anything on this page. */
.tt-strip-review { margin-top: var(--s-8); background: var(--surface);
  border: var(--bw) solid var(--line-strong); border-radius: var(--radius); }
.tt-sr-bar { display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-5); padding: var(--s-4) var(--s-6);
  border-bottom: var(--bw) solid var(--line); }
.tt-sr-eyebrow { font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: var(--ls-wide); text-transform: uppercase; color: var(--accent); }
.tt-weeknav { display: flex; align-items: center; gap: var(--s-3); }
.tt-weeknav b { font-family: var(--f-mono); font-size: var(--t-label); font-weight: 700;
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--muted);
  min-width: 168px; text-align: center; }
.tt-wk { width: 26px; height: 26px; flex: none; display: grid; place-items: center; cursor: pointer;
  background: transparent; color: var(--ink); border: var(--bw) solid var(--line-strong);
  border-radius: 2px; }
.tt-wk:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.tt-wk:disabled { opacity: 0.3; cursor: default; }
.tt-wk svg { width: 11px; height: 11px; }

/* Why the newest board is not the week you are standing in. On a Sunday the
   label reads a week behind and looks broken; this says it is not. */
.tt-wknote { font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: var(--ls-wide); text-transform: uppercase; color: var(--muted);
  border: var(--bw) solid var(--line); border-radius: var(--radius);
  padding: 2px var(--s-3); white-space: nowrap; cursor: help; }
@media (max-width: 720px) { .tt-wknote { display: none; } }

/* The body is the clickable part, so the week arrows above never open it. */
.tt-sr-body { width: 100%; text-align: left; cursor: pointer; color: var(--ink);
  background: transparent; border: 0; padding: var(--s-6); display: grid; gap: var(--s-6); }
.tt-sr-body:hover .tt-sr-go { color: var(--ink); }
/* Shown in place of the body when a week has no published write-up. Not a
   button, because there is nothing to open. */
.tt-sr-none { padding: var(--s-6); font-family: var(--f-mono); font-size: var(--t-mono);
  color: var(--muted); line-height: 1.6; }
.tt-sr-headline { font-weight: 900; font-style: italic; text-transform: uppercase;
  font-size: clamp(17px, 2.6vw, 22px); letter-spacing: -0.02em; line-height: 1.25; }
.tt-sr-foot { display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--s-7); flex-wrap: wrap; }
.tt-stats { display: flex; gap: var(--s-8); flex-wrap: wrap; }
.tt-stat { cursor: help; }
.tt-stat-k { font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--muted); }
.tt-stat-v { font-weight: 900; font-style: italic; font-size: var(--t-h2);
  letter-spacing: -0.03em; font-variant-numeric: tabular-nums; margin-top: var(--s-2);
  line-height: 1; }
/* The trend was a whisper next to the median and read as decoration. It is
   the whole point of a weekly score, so it gets a bordered chip of its own. */
.tt-trend { display: inline-flex; align-items: center; gap: var(--s-2);
  font-family: var(--f-mono); font-size: var(--t-mono); font-weight: 700;
  font-style: normal; letter-spacing: 0.04em; font-variant-numeric: tabular-nums;
  border: var(--bw) solid currentColor; border-radius: 2px;
  padding: 2px var(--s-3); margin-left: var(--s-4); vertical-align: 3px; }

/* Chat's own median, eight weeks of it. The board says where people are, this
   says which way the room as a whole is drifting. */
.tt-trendline { display: block; margin-top: var(--s-3); }
.tt-trendline svg { display: block; width: 132px; height: 30px; }
.tt-sr-go { flex: none; font-family: var(--f-mono); font-size: var(--t-label); font-weight: 700;
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--accent);
  padding-bottom: 2px; }

.tt-review-h { font-weight: 900; font-style: italic; text-transform: uppercase;
  font-size: clamp(19px, 3.2vw, 26px); letter-spacing: -0.02em; line-height: 1.15; }
.tt-review-over { margin-top: var(--s-5); font-size: var(--t-md); line-height: 1.65; }

/* Where the whole week landed, in one bar. The only place the ramp is shown
   as a distribution rather than a position. */
.tt-dist-bar { display: flex; gap: 2px; height: 16px; margin-top: var(--s-5); }
.tt-dist-bar.mini { height: 8px; width: 108px; margin-top: var(--s-2); }
.tt-dist-bar i { display: block; border-radius: 2px; cursor: help; min-width: 3px; }
.tt-dist-keys { display: flex; flex-wrap: wrap; gap: var(--s-5); margin-top: var(--s-3); }
.tt-dist-keys span { font-family: var(--f-mono); font-size: var(--t-micro); color: var(--muted);
  display: inline-flex; align-items: center; gap: var(--s-2); }
.tt-dist-keys i { width: 8px; height: 8px; border-radius: 2px; flex: none; }

/* ---------- movers and ends ---------- */
.tt-ends { display: grid; gap: var(--s-6); margin-top: var(--s-5);
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.tt-end-h { font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--muted);
  margin-bottom: var(--s-3); }
.tt-mini { width: 100%; display: flex; align-items: center; gap: var(--s-4);
  background: transparent; border: 0; border-top: var(--bw) solid var(--line);
  color: var(--ink); text-align: left; cursor: pointer; padding: var(--s-3) var(--s-2); }
.tt-mini:hover { background: var(--surface-2); }
.tt-mini-rank { font-family: var(--f-mono); font-size: var(--t-micro); color: var(--muted);
  width: 14px; flex: none; }
.tt-mini-n { flex: 1; min-width: 0; font-weight: 700; font-size: var(--t-sm);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tt-mini-v { font-family: var(--f-mono); font-size: var(--t-sm); font-weight: 700;
  font-variant-numeric: tabular-nums; flex: none; }

/* A move is two numbers and an arrow, not a sentence. Each number wears the
   band it was in, so crossing a band is visible in the colour change alone. */
.tt-move { display: flex; align-items: center; gap: var(--s-4); margin-top: var(--s-4);
  padding-left: var(--s-2); }
.tt-move-n { font-weight: 900; font-style: italic; font-size: var(--t-h3);
  letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.tt-move-a { color: var(--muted); font-family: var(--f-mono); font-size: var(--t-sm); }
.tt-move-b { font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }

.tt-spots { display: grid; gap: var(--s-5); margin-top: var(--s-5);
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.tt-spot { border: var(--bw) solid var(--line); border-radius: var(--radius);
  padding: var(--s-5) var(--s-6); cursor: pointer; background: transparent;
  color: var(--ink); text-align: left; width: 100%; }
.tt-spot:hover { border-color: var(--accent); }
.tt-spot-cat { font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; }
.tt-spot-who { display: flex; align-items: baseline; gap: var(--s-3); margin-top: var(--s-3); }
.tt-spot-name { font-weight: 900; font-style: italic; text-transform: uppercase;
  font-size: var(--t-h3); letter-spacing: -0.01em; }
.tt-spot-score { font-family: var(--f-mono); font-size: var(--t-mono); font-weight: 700;
  font-variant-numeric: tabular-nums; }
.tt-spot-note { font-size: var(--t-sm); line-height: 1.6; color: var(--muted); margin-top: var(--s-3); }
.tt-spot-q { font-family: var(--f-mono); font-size: var(--t-sm); line-height: 1.5;
  margin-top: var(--s-4); padding-left: var(--s-4); border-left: 3px solid var(--line-strong); }
.tt-review-verdict { margin-top: var(--s-7); padding-top: var(--s-5);
  border-top: var(--bw) solid var(--line); font-weight: 800; font-style: italic;
  font-size: var(--t-lg); }

/* ---------- board controls ---------- */
.tt-boardhead { display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s-5); flex-wrap: wrap; margin-top: var(--s-10); }
.tt-h2 { font-weight: 900; font-style: italic; text-transform: uppercase;
  font-size: var(--t-h2); letter-spacing: -0.02em; }
.tt-controls { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-5);
  align-items: center; }
.tt-chip { font-family: var(--f-mono); font-size: var(--t-label); font-weight: 700;
  letter-spacing: var(--ls-label); text-transform: uppercase; cursor: pointer;
  background: var(--surface); color: var(--muted);
  border: var(--bw) solid var(--line-strong); border-radius: 2px; padding: var(--s-2) var(--s-4);
  display: inline-flex; align-items: center; gap: var(--s-2); }
.tt-chip:hover { color: var(--ink); }
.tt-chip i { width: 8px; height: 8px; border-radius: 2px; display: block; }
.tt-chip[aria-pressed="true"] { color: var(--ink); border-color: currentColor; }
.tt-spacer { flex: 1; }

/* ---------- sort menu ----------
   Not a native <select>: the OS list ignores every token on this page. Same
   treatment as the navbar's settings panel, hard ink border with the accent
   thrown behind it, and the sweet skin swaps that for its soft lift. */
.tt-sortwrap { position: relative; }
.tt-sortbtn { display: inline-flex; align-items: center; gap: var(--s-3);
  font-family: var(--f-mono); font-size: var(--t-label); font-weight: 700;
  letter-spacing: var(--ls-label); text-transform: uppercase; background: var(--surface);
  color: var(--ink); border: var(--bw) solid var(--line-strong); border-radius: 2px;
  padding: var(--s-2) var(--s-4); cursor: pointer; }
.tt-sortbtn:hover, .tt-sortbtn[aria-expanded="true"] { border-color: var(--accent); }
.tt-sortbtn svg { width: 11px; height: 11px; transition: transform 0.18s ease; }
.tt-sortbtn[aria-expanded="true"] svg { transform: rotate(180deg); }
.tt-sortmenu { position: absolute; top: calc(100% + 8px); right: 0; z-index: 60; width: 210px;
  background: var(--surface); border: var(--bw) solid var(--ink); border-radius: var(--radius);
  box-shadow: 7px 7px 0 var(--accent); padding: var(--s-2); display: none; }
[data-skin="sweet"] .tt-sortmenu { border-color: transparent; box-shadow: 0 16px 40px var(--shadow); }
.tt-sortmenu.open { display: block; }
.tt-sortmenu button { width: 100%; text-align: left; cursor: pointer; background: transparent;
  border: 0; color: var(--muted); font-family: var(--f-mono); font-size: var(--t-mono);
  font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  padding: var(--s-3) var(--s-4); border-radius: 2px;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.tt-sortmenu button:hover { color: var(--ink); background: var(--surface-2); }
.tt-sortmenu button[aria-checked="true"] { color: var(--accent-ink); background: var(--accent); }

/* ---------- board rows ----------
   A row is scanned, not read, so state is encoded twice: the score's colour
   AND the band word, plus the run to its right. Nothing here depends on
   colour alone. */
.tt-rows { margin-top: var(--s-6); }
/* The four figures on the right are ONE cluster, not four columns spread
   across whatever width is left. As separate grid tracks the band sat in a
   62px cell that "SWEET" only half filled, so the leftover plus the column gap
   opened a hole between the band and the sparkline that looked like something
   was missing from it. They keep their fixed widths, so every number still
   lines up down the list; what changed is that the slack all goes to the name
   column, where it belongs. */
.tt-row { width: 100%; display: grid; align-items: center; gap: var(--s-5);
  grid-template-columns: 34px 1fr auto auto;
  background: transparent; border: 0; border-top: var(--bw) solid var(--line);
  color: var(--ink); text-align: left; cursor: pointer; padding: var(--s-4) var(--s-3); }
.tt-row:hover { background: var(--surface-2); }
/* outline takes no space and would be painted over by the next row */
.tt-row:hover, .tt-row:focus-visible { position: relative; z-index: 1; }
.tt-row-pfp { width: 34px; height: 34px; border-radius: var(--radius); background: var(--surface-2);
  border: var(--bw) solid var(--line); display: grid; place-items: center;
  font-weight: 900; font-style: italic; color: var(--muted); font-size: var(--t-md); }
/* Two lines, each its own flex row. The badge sits OUTSIDE the ellipsing name:
   when it lived inside, the name's overflow:hidden clipped the badge's own
   bottom border off. Only the text that needs truncating gets overflow. */
.tt-row-who { min-width: 0; }
.tt-row-top { display: flex; align-items: center; gap: var(--s-3); min-width: 0; }
.tt-row-name { font-weight: 700; font-size: var(--t-md); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.tt-row-quiet { flex: none; font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted);
  border: 1px solid var(--line-strong); border-radius: 2px; padding: 2px var(--s-2);
  white-space: nowrap; line-height: 1.2; cursor: help; }
/* WHAT SOMEBODY IS IN THE CHANNEL, beside their name. Built on the same shape
   as .tt-row-quiet so the two sit together without arguing, and deliberately
   quiet: this is context, not a trophy, and the score does not know it exists.
   Prefixed tt-, because juq.css owns short global class names. */
.tt-badge { flex: none; font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  border: 1px solid currentColor; border-radius: 2px; padding: 2px var(--s-2);
  white-space: nowrap; line-height: 1.2; cursor: help; color: var(--muted); }
.tt-badge.mod { color: var(--f-sweet); }
.tt-badge.vip { color: var(--f-glazed); }
/* Earned here, and rare. Founder is one message in 40,000. */
.tt-badge.founder { color: var(--f-glazed); border-style: double; border-width: 3px; }
.tt-badge.broadcaster { color: var(--accent); }
/* Money and gifts put into the channel, and the three monthly leaderboards.
   Deliberately quieter than mod or VIP: they are facts, not rank. */
.tt-badge.gave { color: var(--f-sour); }
.tt-badge.top { color: var(--f-mild); }

/* THE TENURE RAMP. It used to be one flat grey for everything from one month
   to ten years, which is a scale with one step on it. */
.tt-badge.sub { color: var(--tn-1); }
.tt-badge.sub.t2 { color: var(--tn-2); }
.tt-badge.sub.t3 { color: var(--tn-3); }
.tt-badge.sub.t4 { color: var(--tn-4); }
.tt-badge.sub.t5 { color: var(--tn-5); }
.tt-badge.sub.t6 { color: var(--tn-6); }
/* The card header is a heading, so the badges must not inherit its weight or
   its size the way they happily do inside a row. */
.tt-name .tt-badge { font-size: var(--t-micro); vertical-align: middle;
  margin-left: var(--s-3); text-transform: uppercase; }

.tt-row-meta { display: flex; align-items: baseline; gap: var(--s-4);
  min-width: 0; margin-top: var(--s-2); }
.tt-row-verdict { font-family: var(--f-mono); font-size: var(--t-mono); font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: help; }
.tt-row-msgs { flex: none; font-family: var(--f-mono); font-size: var(--t-micro);
  color: var(--muted); font-variant-numeric: tabular-nums; cursor: help; }
/* RIGHT ALIGNED, so the badges end where the score column begins and every
   row's badges finish at the same x. Wrapping rather than scrolling: somebody
   wearing four of them is a fact about them, not an overflow to hide. */
.tt-row-badges { display: flex; align-items: center; justify-content: flex-end;
  flex-wrap: wrap; gap: var(--s-2); max-width: 260px; }
.tt-row-right { display: flex; align-items: center; gap: var(--s-4); }
.tt-row-score { flex: none; width: 46px; text-align: right;
  font-weight: 900; font-style: italic; font-size: var(--t-h2);
  letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
/* Sized to GLAZED, the longest band there is, so nothing wider ever wraps and
   nothing shorter leaves a hole. */
.tt-row-band { flex: none; width: 54px;
  font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; }
.tt-row-spark { flex: none; }
.tt-row-spark svg { display: block; width: 76px; height: 26px; }
.tt-row-delta { flex: none; width: 58px;
  font-family: var(--f-mono); font-size: var(--t-mono); font-weight: 700;
  font-variant-numeric: tabular-nums; text-align: right; }
.tt-row-delta.up { color: var(--f-sweet); }
.tt-row-delta.down { color: var(--f-sour); }
.tt-row-delta.flat { color: var(--muted); }
.tt-row-quiet { font-family: var(--f-mono); font-size: var(--t-micro); color: var(--muted); }
/* Whatever the card has to say when it is not a report: loading, an error, or
   a chatter with nothing stored for the selected week. */
.tt-cardmsg { padding: var(--s-9) var(--s-6); text-align: center; font-family: var(--f-mono);
  font-size: var(--t-mono); color: var(--muted); line-height: 1.7; }
.tt-empty { padding: var(--s-9) 0; text-align: center; font-family: var(--f-mono);
  font-size: var(--t-mono); color: var(--muted); border-top: var(--bw) solid var(--line); }

@media (max-width: 700px) {
  .tt-row { grid-template-columns: 30px 1fr auto auto; gap: var(--s-4); }
  .tt-row-spark, .tt-row-delta { display: none; }
  /* Narrower and stacked rather than dropped. The sparkline and the delta go
     because they are a second look at the score; a badge is the only thing on
     the row that is not. */
  .tt-row-badges { max-width: 96px; gap: 2px; }
}

/* ============================================================
   THE VAULT MODAL + REPORT CARD  (approved, unchanged)
   ============================================================ */
.tt-modal { position: fixed; inset: 0; z-index: 85; display: none;
  align-items: center; justify-content: center; padding: var(--s-7);
  background: color-mix(in srgb, var(--bg) 78%, transparent); }
/* Fade the backdrop rather than letting it snap on under the opening doors. */
.tt-modal.open { display: flex; animation: ttBackdrop 0.34s ease both; }
@keyframes ttBackdrop { from { background-color: transparent; } }
/* And the same on the way out, or the dimming snaps off while the vault is
   still closing. Higher specificity than the rule above, so it wins the
   animation property outright rather than fighting it. */
.tt-modal.open.closing { animation: ttBackdropOut 0.42s ease both; }
@keyframes ttBackdropOut { to { background-color: transparent; } }

/* ---------- vault reveal (ported from pantry) ----------
   The stage is exactly the card's box, so the reveal never takes over the
   whole screen. clip-path does not affect layout, so the sheet keeps its real
   size while the content opens out from the seam. */
.tt-stage { position: relative; width: 620px; max-width: 100%; }
.tt-card { width: 100%; max-height: 88vh; overflow-y: auto;
  background: var(--surface); border: 3px solid var(--accent);
  border-radius: var(--radius); padding: var(--s-7) var(--s-8);
  /* ROUNDED IN THE CLIP, not only in the border-radius. A scrollbar is painted
     outside the rounded clip, so on a long report the hard bar ran straight
     through both right-hand corners and squared them off. clip-path DOES clip a
     scrollbar, and this card is the one place that costs nothing, because it
     already carries no box-shadow for exactly the same reason.
     The radius has to be repeated in the open and shut animations in
     tasters.js, or the corners snap square for the length of the animation. */
  clip-path: inset(0 0 0 0 round var(--radius)); will-change: clip-path; }
/* NO box-shadow, deliberately: clip-path clips a shadow along with everything
   else, so the offset shadow the card used to carry could only ever show as a
   one-pixel artifact along the bottom edge. Definition comes from the frame
   below, which lives OUTSIDE the clip. Same fix pantry already made. */
.tt-frame { position: absolute; inset: 0; border: 3px solid var(--accent);
  border-radius: var(--radius); pointer-events: none; z-index: 2; }
[data-skin="sweet"] .tt-card { border-color: transparent; }
[data-skin="sweet"] .tt-frame { border-color: transparent; box-shadow: 0 22px 60px var(--shadow); }

/* ---------- themed cards ----------
   A few people get staging behind their report card. Written up in
   docs/TASTER-THEMES.md; the registry is at the top of tasters.js.

   POINTER-EVENTS NONE IS LOAD-BEARING, NOT DECORATION. Closing the card by
   clicking the backdrop tests `e.target === modal`, so a layer stretched across
   the modal would swallow every one of those clicks and leave the ✕ as the only
   way out. It is aria-hidden for the same reason it is unclickable: there is
   nothing here to read.

   FIRST CHILD OF THE MODAL, so it paints under .tt-stage on DOM order alone
   rather than starting a z-index argument with the approved card CSS above. */
.tt-theme { position: absolute; inset: 0; overflow: hidden; z-index: 0;
  pointer-events: none;
  /* ONE NUMBER CONTROLS HOW LOUD THE PICTURE IS. Subtle is the whole brief: the
     card in front is opaque, so this only ever tints the dimmed page around it. */
  --tt-theme-a: 0.18;
  /* AND ONE CONTROLS HOW SLOWLY IT ARRIVES. Deliberately long: at 1.6s the flag
     announced itself and read as a page element loading in. It should creep up
     while the card is being read and never be the thing that catches the eye,
     so it takes longer than anybody spends looking at the header.
     The song has its own number, THEME_FADE_MS in tasters.js. */
  --tt-theme-in: 5s;
  /* Leaving is quick and does NOT match arriving. Arriving can be slow because
     there is a card in front of it; leaving has nothing to hide behind, and a
     long one reads as something that failed to stop. Matched to THEME_OUT_MS in
     tasters.js, which does the same job for the song. */
  --tt-theme-out: 3s;
  opacity: 0; transition: opacity var(--tt-theme-in) ease-in; }
.tt-theme.on { opacity: var(--tt-theme-a); }
.tt-theme video { position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block; }
/* ON THE WAY OUT THE LAYER IS HANDED TO THE BODY, because the modal is
   display:none about 420ms after a close and a fade-out inside it is simply
   never seen. Fixed rather than absolute, since it no longer has the fixed
   modal as its containing block; above the modal so the backdrop dimming out
   underneath cannot double-dim it; and still unclickable, which matters more
   here than anywhere, because this is now a full-screen layer sitting over an
   interactive page. */
.tt-theme.tt-theme-out { position: fixed; z-index: 86;
  transition-duration: var(--tt-theme-out); transition-timing-function: ease-out; }

/* The fade is atmosphere rather than information, so it can simply not happen.
   The still frame underneath stays: the picture and the colour are most of it. */
@media (prefers-reduced-motion: reduce) {
  .tt-theme { transition: none; }
}
/* Muted reads as muted, so the icon is not the only thing carrying the state. */
#ttSound[aria-pressed="false"] { color: var(--muted); border-color: var(--line); }

/* ---------- view swap ----------
   Card to link viewer and back is a drill-down, so it slides rather than
   cutting. The card box itself holds still and only its contents move, which
   is why the content lives in its own wrapper. */
.tt-view { will-change: transform, opacity; }

/* ---------- link viewer ----------
   A shared link opens IN the card rather than throwing you out to a new tab,
   so getting back is one button and the card is still underneath it. */
.tt-viewer-top { display: flex; align-items: center; gap: var(--s-4); }
.tt-back { display: inline-flex; align-items: center; gap: var(--s-3); cursor: pointer;
  background: transparent; border: var(--bw) solid var(--line-strong); border-radius: var(--radius);
  color: var(--ink); font-family: var(--f-mono); font-size: var(--t-label); font-weight: 700;
  letter-spacing: var(--ls-label); text-transform: uppercase; padding: var(--s-3) var(--s-4); flex: 1; }
.tt-back:hover { border-color: var(--accent); color: var(--accent); }
.tt-frame-box { margin-top: var(--s-6); position: relative; padding-top: 56.25%;
  border: var(--bw) solid var(--line-strong); border-radius: var(--radius);
  background: var(--surface-2); overflow: hidden; }
.tt-frame-box > div { position: absolute; inset: 0; display: grid; place-items: center;
  text-align: center; padding: var(--s-6); }
/* The embed fills the same 16:9 box the placeholder does, so a clip and a
   host that refuses to embed occupy identical space and the card never jumps. */
.tt-frame-box iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
/* Two exceptions to the 16:9 box, for the platforms that are not 16:9. A reel
   letterboxed into a widescreen frame is mostly black bars. Same shapes the
   links page uses. */
.tt-frame-box.tall { padding-top: 0; height: min(740px, 78vh); display: grid; place-items: center; }
.tt-frame-box.tall iframe { position: static; aspect-ratio: 325/738; height: 100%; width: auto; background: #fff; }
.tt-frame-box.auto { padding-top: 0; min-height: 380px; }
.tt-frame-box.auto iframe { position: static; width: 100%; height: 380px; background: #fff; }
.tt-play { width: 54px; height: 54px; border-radius: 50%; border: 3px solid var(--accent);
  color: var(--accent); display: grid; place-items: center; font-size: var(--t-h3); margin: 0 auto var(--s-5); }
.tt-frame-note { font-family: var(--f-mono); font-size: var(--t-mono); color: var(--muted); line-height: 1.6; }
.tt-viewer-url { margin-top: var(--s-6); font-family: var(--f-mono); font-size: var(--t-sm);
  word-break: break-all; line-height: 1.6; }
.tt-viewer-url b { color: var(--muted); font-weight: 400; }
.tt-open { display: inline-flex; align-items: center; gap: var(--s-3); margin-top: var(--s-6);
  font-family: var(--f-mono); font-size: var(--t-mono); font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--accent); text-decoration: none;
  border: var(--bw) solid var(--accent); border-radius: var(--radius); padding: var(--s-3) var(--s-5); }
.tt-open:hover { background: var(--accent); color: var(--accent-ink); }

.tt-head { display: flex; align-items: center; gap: var(--s-5); }
.tt-pfp { width: 52px; height: 52px; border-radius: var(--radius);
  border: var(--bw) solid var(--line-strong); background: var(--surface-2);
  display: grid; place-items: center; font-weight: 900; font-style: italic;
  font-size: var(--t-h2); color: var(--muted); flex: none; }
.tt-who { flex: 1; min-width: 0; }
.tt-name { font-weight: 900; font-style: italic; text-transform: uppercase;
  font-size: var(--t-h2); letter-spacing: -0.02em; line-height: 1.1; }
.tt-week { font-family: var(--f-mono); font-size: var(--t-mono); color: var(--muted);
  margin-top: 3px; display: inline-block; cursor: help; }
.tt-msgs { font-family: var(--f-mono); font-size: var(--t-micro); color: var(--muted);
  margin-top: var(--s-1); cursor: help; font-variant-numeric: tabular-nums;
  display: flex; align-items: center; }
.tt-x { width: 30px; height: 30px; display: grid; place-items: center; cursor: pointer;
  background: transparent; color: var(--ink); border: var(--bw) solid var(--line-strong);
  border-radius: var(--radius); font-size: var(--t-lg); flex: none; }
.tt-x:hover { border-color: var(--accent); color: var(--accent); }

.tt-score-row { display: flex; align-items: center; gap: var(--s-6);
  margin-top: var(--s-7); padding-top: var(--s-7); border-top: var(--bw) solid var(--line); }
.tt-num { font-weight: 900; font-style: italic; font-size: clamp(42px, 9vw, 54px); line-height: 0.9;
  letter-spacing: -0.05em; font-variant-numeric: tabular-nums; flex: none; cursor: help; }
.tt-num small { font-size: var(--t-md); font-style: normal; font-weight: 700;
  color: var(--muted); letter-spacing: 0; margin-left: 2px; }
.tt-band-name { font-weight: 900; font-style: italic; text-transform: uppercase;
  font-size: var(--t-h3); letter-spacing: 0.02em; cursor: help; display: inline-block; }
.tt-verdict { font-family: var(--f-mono); font-size: var(--t-sm); color: var(--muted); margin-top: var(--s-2); }
.tt-verdict b { font-weight: 700; cursor: help; border-bottom: 1px dotted currentColor; }

.tt-strip { margin-top: var(--s-7); }
.tt-poles { display: flex; justify-content: space-between; margin-bottom: var(--s-3); }
.tt-poles span { font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); cursor: help; }
.tt-strip-bar { display: grid; grid-template-columns: repeat(5, 1fr); gap: 2px; }
/* color-mix, NOT opacity: opacity would drag the tooltip down with it */
.tt-strip-seg { height: 14px; border-radius: 2px; cursor: help;
  background: color-mix(in srgb, var(--seg) 38%, var(--surface)); }
.tt-strip-seg.on { background: var(--seg); }
.tt-marker { position: relative; height: 13px; }
.tt-marker i { position: absolute; top: 1px; transform: translateX(-50%);
  font-style: normal; font-size: var(--t-mono); color: var(--ink); line-height: 1; }
.tt-strip-keys { display: grid; grid-template-columns: repeat(5, 1fr); gap: 2px; }
.tt-strip-keys span { font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); text-align: center; }
.tt-strip-keys span.on { color: var(--ink); }
.tt-scale { position: relative; height: 14px; margin-top: var(--s-2); }
.tt-scale span { position: absolute; top: 0; font-family: var(--f-mono); font-size: var(--t-micro);
  color: var(--muted); font-variant-numeric: tabular-nums; transform: translateX(-50%); }
.tt-scale span:first-child { transform: none; }
.tt-scale span:last-child { transform: translateX(-100%); }

.tt-read { margin-top: var(--s-6); font-size: var(--t-md); line-height: 1.65; }
.tt-sec { margin-top: var(--s-8); padding-top: var(--s-5); border-top: var(--bw) solid var(--line);
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-5); }

.tt-acts { margin-top: var(--s-5); display: grid; gap: var(--s-4); }
.tt-act { display: grid; grid-template-columns: 92px 1fr 22px; align-items: center;
  gap: var(--s-4); cursor: help; }
.tt-act-name { font-family: var(--f-mono); font-size: var(--t-mono); font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase; }
.tt-act-track { height: 10px; background: var(--surface-2); border: var(--bw) solid var(--line);
  border-radius: 2px; overflow: hidden; }
.tt-act-fill { height: 100%; border-radius: 1px; }
.tt-acts-note { margin-top: var(--s-4); font-size: var(--t-micro);
  line-height: 1.5; color: var(--muted); }
.tt-act-wrap { display: grid; }
.tt-has-why .tt-act { grid-template-columns: 92px 1fr 22px 52px; }
.tt-act-why-btn { cursor: pointer; justify-self: end;
  font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted); background: var(--surface-2);
  border: var(--bw) solid var(--line); border-radius: var(--radius);
  padding: var(--s-2) var(--s-3); }
.tt-act-why-btn:hover { color: var(--accent); border-color: var(--accent); }
.tt-act-why-btn[aria-expanded="true"] { color: var(--ink); border-color: var(--line-strong); }
/* Holds the column open on rows with nothing to show, so the bars stay level. */
.tt-act-why-non { display: block; }

/* THE SLIDE, done with grid rather than max-height. A max-height slide needs a
   guessed pixel ceiling: too low and long quotes are cut off, too high and the
   "close" spends most of its time animating empty space. 0fr to 1fr animates
   to the content's real height with nothing to guess.

   NOT [hidden]: this panel has to be in the layout to animate out of it, and a
   class setting display would beat the [hidden] rule anyway, which is a trap
   this repo has fallen into five times. Collapsed it has zero height and its
   contents are visibility:hidden, so it is out of the tab order too. */
.tt-act-why { display: grid; grid-template-rows: 0fr; margin-top: 0;
  transition: grid-template-rows .22s ease, margin-top .22s ease; }
.tt-act-why > .tt-why-in { overflow: hidden; visibility: hidden;
  transition: visibility .22s; }
.tt-act-why.open { grid-template-rows: 1fr; margin-top: var(--s-3); }
.tt-act-why.open > .tt-why-in { visibility: visible; }
@media (prefers-reduced-motion: reduce) {
  .tt-act-why, .tt-act-why > .tt-why-in { transition: none; }
}

.tt-why-in > * { margin-left: 92px; }
.tt-why-lead { font-size: var(--t-micro); color: var(--muted);
  padding-bottom: var(--s-2); }
.tt-act-quote { display: flex; align-items: baseline; gap: var(--s-3);
  font-size: var(--t-sm); line-height: 1.4; color: var(--ink);
  padding: var(--s-2) 0; }
.tt-act-quote .tt-q::before { content: '“'; }
.tt-act-quote .tt-q::after { content: '”'; }
.tt-q-at { flex: none; margin-left: auto; white-space: nowrap;
  font-family: var(--f-mono); font-size: var(--t-micro); color: var(--muted); }
/* Sized to the line rather than to a fixed box: an emote in running text is a
   word, and one that stands taller than its neighbours makes the row jump. */
.tt-act-quote .ch-emote { height: 1.6em; vertical-align: -0.4em; }
@media (max-width: 560px) {
  .tt-why-in > * { margin-left: 0; }
  .tt-act-quote { flex-wrap: wrap; gap: var(--s-2); }
  .tt-q-at { margin-left: 0; }
}} }

.tt-act-val { font-family: var(--f-mono); font-size: var(--t-mono); font-weight: 700;
  text-align: right; font-variant-numeric: tabular-nums; }

.tt-split-head { display: flex; justify-content: space-between; margin-top: var(--s-5); }
.tt-split-head span { font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; cursor: help; color: var(--f-live); }
.tt-split-bar { display: flex; gap: 2px; margin-top: var(--s-3); height: 12px; }
.tt-split-bar i { display: block; border-radius: 2px; cursor: help; }
/* One hue, two fills. Solid is on air, hatch is the gaps. */
.tt-split-bar i.tt-on { background: var(--f-live); }
.tt-split-bar i.tt-off {
  background-color: color-mix(in srgb, var(--f-live) 12%, var(--surface));
  background-image: repeating-linear-gradient(45deg, var(--f-live) 0 2px, transparent 2px 5px);
  box-shadow: inset 0 0 0 1px var(--f-live);
}
.tt-split-foot { display: flex; justify-content: space-between; margin-top: var(--s-3); }
.tt-split-foot span { font-family: var(--f-mono); font-size: var(--t-mono); color: var(--muted);
  font-variant-numeric: tabular-nums; }

.tt-delta { font-family: var(--f-mono); font-size: var(--t-mono); font-weight: 700;
  padding: 3px var(--s-3); border-radius: 2px; border: var(--bw) solid currentColor;
  white-space: nowrap; cursor: help; }
.tt-chart { margin-top: var(--s-5); width: 100%; overflow-x: auto; }
.tt-chart svg { display: block; width: 100%; height: auto; min-width: 460px; }
/* The invisible hover columns over the chart. They light their own slice on
   hover so you can see which week you are reading. */
.tt-chart .tt-hit { cursor: help; }
.tt-chart .tt-hit:hover, .tt-chart .tt-hit:focus-visible {
  fill: color-mix(in srgb, var(--ink) 7%, transparent); outline: none;
}
.tt-legend { display: flex; flex-wrap: wrap; gap: var(--s-5); margin-top: var(--s-4); }
.tt-legend span { font-family: var(--f-mono); font-size: var(--t-micro); color: var(--muted);
  display: inline-flex; align-items: center; gap: var(--s-2); }
.tt-key { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.tt-key.hollow { background: var(--surface); border: 2px solid var(--f-mild); }
.tt-key.gap { background: transparent; border: 2px dashed var(--line-strong); border-radius: 2px; }

.tt-lines { margin-top: var(--s-5); display: grid; gap: var(--s-3); }
.tt-line { font-family: var(--f-mono); font-size: var(--t-sm); line-height: 1.55;
  background: var(--surface-2); border-left: 3px solid var(--line-strong);
  border-radius: 2px; padding: var(--s-3) var(--s-4); cursor: help; }

.tt-flag { margin-top: var(--s-6); border: var(--bw) solid var(--f-flag);
  border-radius: var(--radius); background: color-mix(in srgb, var(--f-flag) 10%, var(--surface)); }
.tt-flag-head { width: 100%; display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4); cursor: pointer; background: transparent; border: 0;
  padding: var(--s-4) var(--s-5); color: var(--f-flag); text-align: left; }
.tt-flag-head:hover { background: color-mix(in srgb, var(--f-flag) 12%, transparent); }
.tt-flag-title { font-family: var(--f-mono); font-size: var(--t-sm); font-weight: 700; }
.tt-flag-arrow { width: 14px; height: 14px; flex: none; transform: rotate(180deg); transition: transform 0.2s ease; }
.tt-flag-head[aria-expanded="true"] .tt-flag-arrow { transform: rotate(0deg); }
.tt-flag-msgs { display: grid; grid-template-rows: 0fr; min-height: 0; transition: grid-template-rows 0.28s ease; }
.tt-flag-msgs.open { grid-template-rows: 1fr; }
.tt-flag-msgs-inner { overflow: hidden; }
.tt-flag-msg { font-family: var(--f-mono); font-size: var(--t-sm); line-height: 1.55; color: var(--ink);
  padding: var(--s-3) var(--s-5); border-top: var(--bw) solid color-mix(in srgb, var(--f-flag) 30%, transparent); }
.tt-flag-msg time { color: var(--muted); font-size: var(--t-micro); display: block; margin-top: 3px; }

.tt-links { margin-top: var(--s-5); }
/* A button needs an explicit background or the UA button face wins and the
   row renders as a light grey slab on the dark skins. */
.tt-link { width: 100%; display: flex; align-items: center; gap: var(--s-4);
  padding: var(--s-3) var(--s-2); background: transparent; border: 0;
  border-top: var(--bw) solid var(--line); color: var(--ink);
  text-align: left; cursor: pointer; }
.tt-link:hover { background: var(--surface-2); }
.tt-link:first-child { border-top: 0; }
.tt-link-host { font-family: var(--f-mono); font-size: var(--t-sm); color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.tt-link-host b { color: var(--muted); font-weight: 400; }
.tt-link-n { font-family: var(--f-mono); font-size: var(--t-mono); font-weight: 700;
  color: var(--muted); font-variant-numeric: tabular-nums; flex: none; }

@media (max-width: 620px) {
  .tt-card { padding: var(--s-6) var(--s-5); box-shadow: 5px 5px 0 var(--accent); }
  .tt-act { grid-template-columns: 78px 1fr 20px; }
  .tt-strip-keys span { letter-spacing: 0; }
  .tt-poles span, .tt-split-head span { letter-spacing: 0.04em; }
}

/* ---------- something off ----------

   Last thing on the card, and quiet. It is not an action anybody came here to
   take, and a loud control next to the score would invite arguing with the
   number instead of reading it. */
.tt-wrong { margin-top: var(--s-7); padding-top: var(--s-5); border-top: var(--bw) solid var(--line); }
.tt-wrong-btn {
  cursor: pointer; width: 100%;
  display: flex; align-items: center; justify-content: center; gap: var(--s-3);
  background: var(--surface-2); color: var(--ink);
  border: var(--bw) solid var(--line-strong); border-radius: var(--radius);
  padding: var(--s-5) var(--s-6);
  font-size: var(--t-sm); font-weight: 700; letter-spacing: 0;
  text-transform: none;
}
.tt-wrong-btn::before { content: '\1F6A9'; font-size: var(--t-md); line-height: 1; }
.tt-wrong-btn:hover { border-color: var(--accent); color: var(--accent); }

.tt-wrong-form { margin-top: var(--s-5); display: flex; flex-direction: column; gap: var(--s-4); }
.tt-wrong-form[hidden] { display: none; }
.tt-wrong-lead { font-size: var(--t-sm); color: var(--muted); line-height: 1.55; }
.tt-wrong-rs { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.tt-wrong-r {
  cursor: pointer; font-size: var(--t-sm); font-weight: 700;
  padding: var(--s-3) var(--s-4);
  color: var(--muted); background: var(--surface-2);
  border: var(--bw) solid var(--line-strong); border-radius: var(--radius);
}
.tt-wrong-r:hover { color: var(--ink); border-color: var(--accent); }
.tt-wrong-r.on { color: var(--accent-ink); background: var(--accent); border-color: var(--accent); }
.tt-wrong-why {
  width: 100%; resize: vertical; min-height: 74px;
  background: var(--surface-2); color: var(--ink);
  border: var(--bw) solid var(--line-strong); border-radius: var(--radius);
  padding: var(--s-4); font: inherit; font-size: var(--t-sm);
}
.tt-wrong-why:focus { outline: none; border-color: var(--accent); }
.tt-wrong-foot { display: flex; align-items: center; gap: var(--s-4); }
.tt-wrong-foot .btn { margin-left: auto; }
.tt-wrong-note { font-family: var(--f-mono); font-size: var(--t-micro); color: var(--muted); }
.tt-wrong-done { font-size: var(--t-sm); color: var(--accent); line-height: 1.55; }
.tt-wrong-send {
  margin-left: auto; cursor: pointer; font: inherit; font-family: var(--f-mono);
  font-size: var(--t-micro); font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--accent); background: transparent; padding: var(--s-3) var(--s-5);
  border: var(--bw) solid var(--accent); border-radius: var(--radius);
}
.tt-wrong-send:hover { background: var(--accent); color: var(--accent-ink); }
.tt-wrong-send[disabled] { opacity: 0.45; cursor: default; background: transparent; color: var(--accent); }
.tt-wrong-note.err { color: var(--f-sour); }

/* An emote code is a picture, not a word. "NgL a good mod should not be a
   hatewatcher" is not the line that was sent: rendering NgL as three letters
   quietly rewrites what somebody said into something they did not say. */
.tt-emote {
  height: 18px; width: auto; vertical-align: -4px;
  display: inline-block; margin: 0 1px;
}

/* A REFUSED WEEK READS AS AN EXPLANATION, not as a verdict. Muted and
   bordered so it is legible as the site talking about itself rather than as
   something somebody was judged to be. */
.tt-refused { border-left: 2px solid var(--line-strong); padding-left: var(--s-3); color: var(--muted); }
