/* ==========================================================================
   EL_RA3I — the shared visual layer.

   One token set, two themes, used by every page. Three rules hold this
   together, and breaking any of them is a defect:

   1. Nothing below this token block hardcodes a colour, size, space or
      duration. Components reference tokens only, so both themes are defined
      once and no component can carry a value that works in only one of them.
   2. Logical properties everywhere — inline-start / inline-end / block, never
      left / right / top / bottom. Arabic then mirrors with dir="rtl" alone,
      with no second stylesheet.
   3. Hierarchy comes from type and space. A border means "this is a separate
      object" (a table, a dialog, an input). It is not default chrome around
      every block.
   ========================================================================== */

/* --- Tokens: colour ------------------------------------------------------
   Warm neutral surfaces against one cool accent. The warmth is deliberate:
   the cold blue-grey near-black is what every generated admin panel uses.
   The accent is a zellige blue, the glazed cobalt of Tunisian tilework.

   Every pair below is verified against WCAG 2.1 AA (4.5:1 text, 3:1 borders
   and focus rings) in both themes — see the contrast table in the step-3
   notes. Changing one of these values means re-checking it.

   Dark surfaces step +5 / +4 / +4 points of HSL lightness, which is what
   elevation-tokens.md asks for; a smaller step disappears on a dark canvas.
   -------------------------------------------------------------------------- */
:root,
[data-theme="dark"] {
  color-scheme: dark;

  --surface-l0: #131211;   /* canvas          — ~60% of the viewport */
  --surface-l1: #211f1c;   /* tables, panels  — ~30% */
  --surface-l2: #2c2926;   /* popovers, hover */
  --surface-l3: #37332f;   /* dialogs */

  --fg: #f4f1ed;           /* 16.6:1 on canvas */
  --fg-muted: #ada69e;     /*  7.8:1 */
  --fg-faint: #938b82;     /*  5.6:1 — the floor for meta text */

  --accent: #6aa6e8;
  --accent-text: #8cbcf0;  /* links and accent-on-surface text */
  --accent-hover: #86b9ef;
  --on-accent: #0a1420;    /* text on an accent fill */
  --accent-wash: rgba(106, 166, 232, 0.12);

  --positive: #6fbf8a;
  --negative: #e89292;
  --notice: #d9a441;
  --positive-wash: rgba(111, 191, 138, 0.12);
  --negative-wash: rgba(232, 146, 146, 0.12);
  --notice-wash: rgba(217, 164, 65, 0.12);

  --border: rgba(244, 241, 237, 0.12);
  --border-strong: rgba(244, 241, 237, 0.2);
  --border-control: rgba(244, 241, 237, 0.38);  /* 3.2:1 on every dark surface */
  --hairline: rgba(244, 241, 237, 0.08);

  /* Dark elevation is edge lighting, never an outer glow or a sticker shadow. */
  --surface-sunken: #050505;   /* -4.2 L* from the canvas; fg-faint 6.1:1 */
  --surface-inset:  #2c2926;   /* one step AWAY from an L1 surface (see below) */
  --edge-light: inset 0 1px 0 rgba(255, 255, 255, 0.05);
  --shadow-l2: 0 4px 16px rgba(0, 0, 0, 0.4);
  --shadow-l3: 0 16px 48px rgba(0, 0, 0, 0.5);
  --scrim: rgba(0, 0, 0, 0.6);
}

[data-theme="light"] {
  color-scheme: light;

  --surface-l0: #f9f7f6;
  --surface-l1: #ffffff;
  --surface-l2: #ffffff;
  --surface-l3: #ffffff;

  --fg: #1a1815;           /* 16.6:1 on canvas */
  --fg-muted: #5c564e;     /*  6.8:1 */
  --fg-faint: #6f6861;     /*  5.1:1 */

  --accent: #1f62a8;
  --accent-text: #1a558f;
  --accent-hover: #184e85;
  --on-accent: #ffffff;
  --accent-wash: rgba(31, 98, 168, 0.08);

  --positive: #2c7a4b;
  --negative: #b13a33;
  --notice: #8a6515;
  --positive-wash: rgba(44, 122, 75, 0.08);
  --negative-wash: rgba(177, 58, 51, 0.08);
  --notice-wash: rgba(138, 101, 21, 0.08);

  --surface-sunken: #eeebe8;   /* -4.2 L* from the canvas; fg-faint 4.6:1 */
  --surface-inset:  #eeebe8;   /* one step AWAY from an L1 surface (see below) */
  --border: rgba(26, 24, 21, 0.12);
  --border-strong: rgba(26, 24, 21, 0.22);
  --border-control: rgba(26, 24, 21, 0.48);     /* 3.1:1 on every light surface */
  --hairline: rgba(26, 24, 21, 0.08);

  /* Light-mode shadow alpha stays under 0.08 — anything heavier reads as a sticker. */
  --edge-light: none;
  --shadow-l2: 0 4px 12px rgba(0, 0, 0, 0.06);
  --shadow-l3: 0 8px 24px rgba(0, 0, 0, 0.07);
  --scrim: rgba(26, 24, 21, 0.4);
}

/* --- Tokens: type --------------------------------------------------------
   Minor Third (1.2) from a 16px base, per scale-math.md. Three weights only.
   The family is the platform UI face on purpose: on the owner's machines that
   is SF Pro, which is the Apple-like register the brief asked for, and it
   costs no network request on a page that must paint before anything else.
   -------------------------------------------------------------------------- */
:root {
  --viewer-width: 380px;
  --viewer-height: 520px;
  --viewer-border: 1px;
  --viewer-focus: 2px;
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;

  --text-meta: 0.75rem;        /* 12px — timestamps, legal, helper. Never body. */
  --text-secondary: 0.875rem;  /* 14px */
  --text-body: 1rem;           /* 16px */
  --text-h4: 1.2rem;
  --text-h3: 1.44rem;
  --text-h2: 1.73rem;
  --text-h1: 2.07rem;
  --text-display: 2.49rem;

  --leading-display: 1.1;
  --leading-heading: 1.2;
  --leading-body: 1.55;
  --leading-meta: 1.4;

  /* --- Tokens: space — 4pt micro, 8pt major ----------------------------- */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-6: 24px;
  --space-8: 32px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;

  /* --- Tokens: radius, sizing ------------------------------------------- */
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 18px;
  --radius-pill: 999px;

  --hit: 44px;                 /* WCAG 2.1 AA floor, from .ux-profile.md */
  --avatar-profile: 56px;
  --avatar-channel: 40px;
  --avatar-row: 32px;
  --vp-medium: 768px;
  --vp-wide: 1280px;
  --prose: 68ch;               /* inside the 65–75ch band */

  /* --- Tokens: motion ---------------------------------------------------- */
  --motion-100: 100ms;
  --motion-150: 150ms;
  --motion-200: 200ms;
  --motion-300: 300ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in: cubic-bezier(0.7, 0, 0.84, 0);

  /* --- Tokens: layering --------------------------------------------------- */
  --z-sticky: 10;
  --nav-height: 56px;
  --anchor-offset: 72px;
  --scrim: rgba(0, 0, 0, 0.6);
  --menu-width: 22.5rem;
  --account-width: 19rem;
  --z-popover: 100;
  --z-dialog: 300;
}

/* --- Base ---------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

* { margin: 0; padding: 0; }

html {
  /* The shell is never width-capped — only the page content is. */
  width: 100%;
  -webkit-text-size-adjust: 100%;
}

body {
  width: 100%;
  min-block-size: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--surface-l0);
  color: var(--fg);
  font-family: var(--font-ui);
  font-size: var(--text-body);
  font-weight: var(--weight-regular);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-weight: var(--weight-semibold);
  line-height: var(--leading-heading);
  letter-spacing: -0.011em;
  text-wrap: balance;
}

h1 { font-size: var(--text-h1); line-height: var(--leading-display); letter-spacing: -0.02em; }
h2 { font-size: var(--text-h2); }
h3 { font-size: var(--text-h3); }
h4 { font-size: var(--text-h4); font-weight: var(--weight-medium); }

p { text-wrap: pretty; }

/* The browser default for <strong> is 700, which is above the three weights this
   system allows. Emphasis inside body copy is semibold, like everything else. */
strong, b { font-weight: var(--weight-semibold); }

/* <code> inside already-small helper text inherits a 0.9em step that took it
   under the 12px floor. Pin it to the floor instead. */
code { font-size: max(var(--text-meta), 0.9em); }
kbd { font-size: max(var(--text-meta), 0.9em); }

a {
  color: var(--accent-text);
  text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
  text-underline-offset: 0.2em;
}
a:hover { text-decoration-color: currentColor; }

/* One focus ring for the whole app. Never removed without this replacement. */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

::selection { background: var(--accent-wash); }

code, kbd { font-family: var(--font-mono); }

hr {
  border: 0;
  block-size: 1px;
  background: var(--hairline);
  margin-block: var(--space-8);
}

/* --- Shell --------------------------------------------------------------- */
.skip-link {
  position: absolute;
  inset-block-start: var(--space-2);
  inset-inline-start: var(--space-2);
  z-index: var(--z-dialog);
  padding: var(--space-2) var(--space-4);
  background: var(--surface-l3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  color: var(--fg);
  transform: translateY(-200%);
  /* MEASURED at 148x43: padding alone left it a pixel under the floor. */
  display: inline-flex;
  align-items: center;
  min-block-size: var(--hit);
}
.skip-link:focus-visible { transform: translateY(0); }

/* The BezBot wordmark. Outfit is loaded for this and nothing else; if it fails, the interface font stands in. */
@font-face {
  font-family: "Outfit";
  src: url("/fonts/outfit-600.woff2") format("woff2");
  font-weight: 600;
  font-display: swap;
}

html { scroll-padding-block-start: var(--anchor-offset); }

.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--z-sticky);
  width: 100%;
  border-block-end: 1px solid var(--hairline);
  background: var(--surface-l0);
}

.site-header__bar {
  width: 100%;
  max-inline-size: var(--vp-wide);
  margin-inline: auto;
  min-block-size: var(--nav-height);
  padding: var(--space-1) var(--space-4);
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.wordmark {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: var(--space-2);
  color: var(--fg);
  text-decoration: none;
  min-block-size: var(--hit);
}
.wordmark:hover { text-decoration: none; }
.wordmark__mark { flex: none; inline-size: var(--space-6); block-size: var(--space-6); }
.wordmark__dot { fill: var(--accent); }
.wordmark__text { display: flex; flex-direction: column; }
/* Latin in every language: the name does not translate. */
.wordmark__name { font-family: "Outfit", var(--font-ui); font-weight: 600; font-size: var(--text-h4); line-height: 1.1; letter-spacing: -0.01em; }
.wordmark__view { font-size: var(--text-meta); line-height: var(--leading-meta); color: var(--fg-muted); white-space: nowrap; }

.site-header__spacer { flex: 1; }

.site-nav__list {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  list-style: none;
}

.site-nav__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  white-space: nowrap;
  cursor: pointer;
  min-block-size: var(--hit);
  padding-inline: var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--fg-muted);
  font-size: var(--text-secondary);
  text-decoration: none;
  transition: color var(--motion-150) var(--ease-out);
}
.site-nav__link:hover { color: var(--fg); text-decoration: none; }
/* The entry icons belong to the collapsed menu; the bar has no room for them. */
.site-nav__link > svg:first-child { display: none; }
summary.site-nav__link { list-style: none; }
summary.site-nav__link::-webkit-details-marker { display: none; }
/* A bar with more than seven entries (an approved streamer's) tightens the links so French still fits on one line. */
.site-nav--dense .site-nav__link { padding-inline: var(--space-2); }
.site-nav__link[aria-current="page"] {
  color: var(--fg);
  font-weight: var(--weight-medium);
  background: var(--surface-l1);
}

.site-header__actions {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--space-1);
}

/* The menu button only exists below the wide breakpoint; the nav list only hides there.
   Qualified with .icon-btn so it outranks that class's own display. */
.icon-btn.nav-toggle { display: none; }
.nav-toggle__close { display: none; }
.site-header[data-nav-open="true"] .nav-toggle__open { display: none; }
.site-header[data-nav-open="true"] .nav-toggle__close { display: inline-flex; }

/* The two header menus. A <details>, so they open with no script. */
.menu { position: relative; }
.menu > summary { list-style: none; }
.menu > summary::-webkit-details-marker { display: none; }
.menu[open] > summary > svg:last-child { transform: rotate(180deg); }
.menu__panel {
  position: absolute;
  inset-block-start: calc(100% + var(--space-1));
  inset-inline-end: 0;
  z-index: var(--z-popover);
  inline-size: min(var(--menu-width), calc(100vw - var(--space-8)));
  background: var(--surface-l2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-l2);
}
.menu__title { padding: var(--space-3) var(--space-3) var(--space-1); font-size: var(--text-meta); color: var(--fg-muted); }
.menu__section { padding: var(--space-1); border-block-start: 1px solid var(--hairline); }
.menu__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  inline-size: 100%;
  min-block-size: var(--hit);
  padding-inline: var(--space-2);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg);
  font: inherit;
  font-size: var(--text-secondary);
  text-align: start;
  cursor: pointer;
}
.menu__item:hover { background: var(--surface-inset); }
.menu__row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); min-block-size: var(--hit); padding-inline: var(--space-2); }
.menu__label { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-secondary); }
.menu__row .lang-switch > svg { display: none; }

/* The account menu. */
.account__panel { inline-size: min(var(--account-width), calc(100vw - var(--space-8))); }
.account__toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-block-size: var(--hit);
  min-inline-size: var(--hit);
  justify-content: center;
  padding-inline: var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  color: var(--fg);
  font-size: var(--text-secondary);
  cursor: pointer;
}
.account__toggle > svg { flex: none; }
.account__bar-name { max-inline-size: 18ch; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
@media (max-width: 1279.98px) { .account__bar-name { display: none; } }
.account__who { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3); }
.account__id { display: flex; flex-direction: column; flex: 1; min-inline-size: 0; }
/* The full name, however long: it wraps here and is never cut off. */
.account__name { overflow-wrap: anywhere; }
.icon-btn.account__close { display: none; flex: none; }
.theme-choice { display: inline-flex; gap: var(--space-1); padding: var(--space-1); border-radius: var(--radius-sm); background: var(--surface-inset); }
.theme-choice__item {
  min-block-size: var(--hit);
  min-inline-size: var(--hit);
  padding-inline: var(--space-3);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-muted);
  font: inherit;
  font-size: var(--text-secondary);
  cursor: pointer;
}
.theme-choice__item[aria-pressed="true"] { color: var(--fg); border-color: var(--border-control); background: var(--accent-wash); }

/* The moderation picker. */
.picker { padding-block-end: var(--space-1); }
.picker__search { position: relative; display: flex; align-items: center; padding: var(--space-1) var(--space-2); }
.picker__search > svg { position: absolute; inset-inline-start: var(--space-4); color: var(--fg-muted); pointer-events: none; }
.picker__search .input { padding-inline-start: var(--space-8); }
.picker__list { list-style: none; padding: var(--space-1); max-block-size: 60vh; overflow-y: auto; }
.picker__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-block-size: var(--hit);
  padding-inline: var(--space-2);
  border-radius: var(--radius-sm);
  color: var(--fg);
  font-size: var(--text-secondary);
  text-decoration: none;
}
.picker__row:hover { background: var(--surface-inset); text-decoration: none; }
.picker__row > .badge, .picker__row > .meta { flex: none; }
.picker__none { padding: var(--space-3); text-align: center; }
.picker__foot { padding: var(--space-2) var(--space-3); border-block-start: 1px solid var(--hairline); }

main {
  flex: 1;
  width: 100%;
  /* A flex item defaults to min-width:auto, which lets it grow past the
     viewport to fit a wide table instead of letting that table scroll inside
     its own frame. This is the whole reason the admin list used to overflow. */
  min-inline-size: 0;
  max-inline-size: var(--vp-wide);
  margin-inline: auto;
  padding: var(--space-12) var(--space-4) var(--space-16);
}

.site-footer {
  width: 100%;
  border-block-start: 1px solid var(--hairline);
  margin-block-start: auto;
}
.site-footer__bar {
  width: 100%;
  max-inline-size: var(--vp-wide);
  margin-inline: auto;
  padding: var(--space-6) var(--space-4);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-6);
  align-items: baseline;
  justify-content: space-between;
  color: var(--fg-faint);
  font-size: var(--text-meta);
  line-height: var(--leading-meta);
}
.site-footer__links { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); }
.site-footer a { color: var(--fg-faint); }
.site-footer a:hover { color: var(--fg); }
/* MEASURED at 35x17. These are navigation links, so they are aimed at, and the
   44px floor applies. The box grows around the text rather than the text
   growing, so the footer looks the same and the target is real. */
.site-footer__links a {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--hit);
}

/* Wider gutters once there is room for them. The narrow value is the minimum
   comfortable tap margin; at desktop the content should not touch the edge. */
@media (min-width: 768px) {
  .site-header__bar,
  .site-footer__bar,
  main { padding-inline: var(--space-8); }
  main { padding-block: var(--space-16) var(--space-20); }
}

/* --- Page head and sections ---------------------------------------------
   Grouping is spacing and type. No wrapper border, no card.
   -------------------------------------------------------------------------- */
.page-head { margin-block-end: var(--space-12); }
.page-head__eyebrow {
  display: block;
  font-size: var(--text-secondary);
  color: var(--fg-faint);
  margin-block-end: var(--space-2);
}
.page-head h1 { margin-block-end: var(--space-3); }
.page-head__lead {
  color: var(--fg-muted);
  max-inline-size: var(--prose);
}

.section { margin-block-end: var(--space-12); }
.section:last-child { margin-block-end: 0; }
.section__head { margin-block-end: var(--space-4); }
.section__head h2 { font-size: var(--text-h3); }
.section__head h3 { font-size: var(--text-h4); }
.section__note {
  color: var(--fg-muted);
  font-size: var(--text-secondary);
  max-inline-size: var(--prose);
  margin-block-start: var(--space-1);
}

.stack > * + * { margin-block-start: var(--space-4); }
.stack-tight > * + * { margin-block-start: var(--space-2); }
.stack-loose > * + * { margin-block-start: var(--space-8); }

.prose { max-inline-size: var(--prose); }
.prose h2 { font-size: var(--text-h3); margin-block: var(--space-8) var(--space-3); }
.prose h2:first-child { margin-block-start: 0; }
.prose p + p { margin-block-start: var(--space-4); }
.prose p { color: var(--fg-muted); }

.meta {
  font-size: var(--text-meta);
  line-height: var(--leading-meta);
  color: var(--fg-faint);
}
.muted { color: var(--fg-muted); }
/* Kick account and channel identities share one size-aware, decorative avatar. */
.identity { display: inline-flex; align-items: center; gap: var(--space-2); min-inline-size: 0; max-inline-size: 100%; }
.identity__name { min-inline-size: 0; overflow-wrap: anywhere; }
.avatar {
  --avatar-size: var(--avatar-row);
  position: relative; display: inline-grid; place-items: center; flex: none;
  inline-size: var(--avatar-size); block-size: var(--avatar-size);
  border-radius: 50%; overflow: hidden; color: var(--fg-muted); background: var(--surface-l2);
}
.avatar--profile { --avatar-size: var(--avatar-profile); }
.avatar--channel { --avatar-size: var(--avatar-channel); }
.avatar__fallback { display: grid; place-items: center; inline-size: 100%; block-size: 100%; }
.avatar__fallback svg { inline-size: 55%; block-size: 55%; }
.avatar img { position: absolute; inset: 0; display: block; inline-size: 100%; block-size: 100%; object-fit: cover; }
.avatar img[hidden] { display: none; }
.page-head__identity { gap: var(--space-4); }
.page-head__identity h1 { min-inline-size: 0; overflow-wrap: anywhere; }
.choice__text { min-inline-size: 0; }
.reasons__name.identity { align-self: center; }

.row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
.row-between {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  align-items: flex-start;
  justify-content: space-between;
}

/* --- Panel: the one bordered object --------------------------------------
   Used where something genuinely is a separate object — a data table, a
   dialog, a status card. Not a wrapper for every block.
   -------------------------------------------------------------------------- */
.panel {
  background: var(--surface-l1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--edge-light);
}
.panel__body { padding: var(--space-6); }
.panel__head {
  padding: var(--space-4) var(--space-6);
  border-block-end: 1px solid var(--hairline);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  align-items: baseline;
  justify-content: space-between;
}
.panel__head h2, .panel__head h3 { font-size: var(--text-h4); }

/* --- Buttons -------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-block-size: var(--hit);
  padding-inline: var(--space-4);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--surface-l2);
  color: var(--fg);
  font: inherit;
  font-size: var(--text-secondary);
  font-weight: var(--weight-medium);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--motion-150) var(--ease-out),
              border-color var(--motion-150) var(--ease-out),
              opacity var(--motion-150) var(--ease-out);
}
.btn:hover { text-decoration: none; }
.btn svg { inline-size: 16px; block-size: 16px; flex: none; }

.btn-primary { background: var(--accent); color: var(--on-accent); }
.btn-primary:hover { background: var(--accent-hover); }

.btn-secondary { background: transparent; border-color: var(--border-control); color: var(--fg); }
.btn-secondary:hover { background: var(--surface-l1); border-color: var(--fg-faint); }

.btn-quiet { background: transparent; color: var(--fg-muted); padding-inline: var(--space-3); }
.btn-quiet:hover { background: var(--surface-l1); color: var(--fg); }

.btn-danger { background: transparent; border-color: var(--border-control); color: var(--negative); }
.btn-danger:hover { background: var(--negative-wash); border-color: var(--negative); }

.btn-sm { min-block-size: var(--hit); font-size: var(--text-meta); padding-inline: var(--space-3); }
.btn-block { inline-size: 100%; }

/* Square icon-only control. Every one carries an aria-label AND a tooltip. */
.icon-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--hit);
  block-size: var(--hit);
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg-muted);
  cursor: pointer;
  transition: color var(--motion-150) var(--ease-out),
              background var(--motion-150) var(--ease-out);
}
.icon-btn:hover { color: var(--fg); background: var(--surface-l1); }
.icon-btn svg { inline-size: 20px; block-size: 20px; }

/* A real tooltip surface, not title="" — title is too slow and cannot be read
   by a keyboard user, which is half the point of labelling an icon. */
.tooltip-host { position: relative; display: inline-flex; }
.tooltip {
  position: absolute;
  inset-block-start: calc(100% + var(--space-1));
  inset-inline-end: 0;
  z-index: var(--z-popover);
  padding: var(--space-1) var(--space-2);
  background: var(--surface-l3);
  color: var(--fg);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-l2);
  font-size: var(--text-meta);
  line-height: var(--leading-meta);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--motion-150) var(--ease-out);
}
.tooltip-host:hover .tooltip,
.tooltip-host:focus-within .tooltip { opacity: 1; }

/* --- Forms ---------------------------------------------------------------
   Every control has a visible label. Placeholders are format hints only.
   -------------------------------------------------------------------------- */
.field { display: block; margin-block-end: var(--space-6); max-inline-size: var(--prose); }
.field:last-child { margin-block-end: 0; }

.label {
  display: block;
  font-size: var(--text-secondary);
  font-weight: var(--weight-medium);
  color: var(--fg);
  margin-block-end: var(--space-2);
}
.label__optional { color: var(--fg-faint); font-weight: var(--weight-regular); }

.hint {
  font-size: var(--text-meta);
  line-height: var(--leading-meta);
  color: var(--fg-faint);
  margin-block-start: var(--space-2);
}

.input,
.select,
.textarea {
  inline-size: 100%;
  min-block-size: var(--hit);
  padding: var(--space-2) var(--space-3);
  background: var(--surface-l1);
  /* SC 1.4.11: in light mode this is white on an off-white page, so the border
     is the only thing that says a field is here. It has to be seen. */
  border: 1px solid var(--border-control);
  border-radius: var(--radius-sm);
  color: var(--fg);
  font: inherit;
  font-size: var(--text-body);
  transition: border-color var(--motion-150) var(--ease-out);
}
.input:hover, .select:hover, .textarea:hover { border-color: var(--fg-faint); }
.textarea { min-block-size: calc(var(--hit) * 2); resize: vertical; line-height: var(--leading-body); }
.input::placeholder, .textarea::placeholder { color: var(--fg-faint); }

.select {
  /* Chevron drawn as a background so no extra element is needed; mirrors with
     dir=rtl because the position is logical. */
  appearance: none;
  padding-inline-end: var(--space-8);
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - var(--space-4)) calc(50% + 2px),
                       calc(100% - var(--space-3)) calc(50% + 2px);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
[dir="rtl"] .select {
  /* The two gradient halves have to keep their ORDER, not just move to the
     other end. Mirroring only the positions put the right half of the chevron
     on the left of the left half, and the pair rendered as two squares instead
     of an arrow. A chevron is symmetric about its vertical axis, so once the
     halves are in the right order there is nothing else to mirror. */
  background-position: var(--space-3) calc(50% + 2px), var(--space-4) calc(50% + 2px);
}

.input-row { display: flex; gap: var(--space-2); align-items: stretch; }
.input-row .input { flex: 1; min-inline-size: 0; }

.input-mono { font-family: var(--font-mono); font-size: var(--text-secondary); }

/* Checkbox and radio: a real control with a real label, sized to the hit floor. */
.choice {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3);
  min-block-size: var(--hit);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color var(--motion-150) var(--ease-out),
              background var(--motion-150) var(--ease-out);
}
.choice:hover { border-color: var(--border-strong); }
.choice:has(:checked) { border-color: var(--accent); background: var(--accent-wash); }
.choice input { inline-size: 18px; block-size: 18px; margin-block-start: 2px; accent-color: var(--accent); flex: none; }
.choice__text { font-size: var(--text-secondary); }
.choice__title { display: block; font-weight: var(--weight-medium); color: var(--fg); }
.choice__note { display: block; color: var(--fg-muted); font-size: var(--text-meta); line-height: var(--leading-meta); margin-block-start: var(--space-1); }

.choice-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-2);
}

/* Toggle: a checkbox that reads as a switch. The state is also in the label
   text, so meaning never depends on the visual alone. */
.toggle {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-block-size: var(--hit);
  cursor: pointer;
}
.toggle input {
  appearance: none;
  inline-size: 44px;
  block-size: 26px;
  flex: none;
  border-radius: 999px;
  background: var(--surface-l2);
  /* A switch in its off state is told apart from the page by this edge. */
  border: 1px solid var(--border-control);
  position: relative;
  cursor: pointer;
  transition: background var(--motion-150) var(--ease-out);
}
.toggle input::after {
  content: "";
  position: absolute;
  inset-block-start: 3px;
  inset-inline-start: 3px;
  inline-size: 18px;
  block-size: 18px;
  border-radius: 999px;
  background: var(--fg-muted);
  transition: transform var(--motion-150) var(--ease-out), background var(--motion-150) var(--ease-out);
}
.toggle input:checked { background: var(--accent); border-color: var(--accent); }
.toggle input:checked::after { background: var(--on-accent); transform: translateX(18px); }
[dir="rtl"] .toggle input:checked::after { transform: translateX(-18px); }

.form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
  margin-block-start: var(--space-8);
  padding-block-start: var(--space-6);
  border-block-start: 1px solid var(--hairline);
}

/* --- Table: always an L1 surface with hairlines --------------------------- */
.table-frame {
  background: var(--surface-l1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--edge-light);
  overflow: hidden;
  min-inline-size: 0;
}
/* The one inner scroll region a view is allowed. The table keeps its 12px+ type
   and scrolls here rather than squeezing cells or widening the page.

   `contain: paint` is doing real work: without it a wide table inside an
   overflow-x:auto wrapper still contributes to the ROOT's scrollable overflow,
   so the table scrolled inside its frame AND the whole page scrolled sideways
   at 375px. Measured, not assumed — scrollX went from 424 to 0. */
.table-scroll {
  overflow-x: auto;
  min-inline-size: 0;
  contain: paint;
}
.table-scroll table { min-inline-size: max-content; }

table {
  inline-size: 100%;
  border-collapse: collapse;
  font-size: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
thead th {
  text-align: start;
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-meta);
  font-weight: var(--weight-medium);
  color: var(--fg-faint);
  border-block-end: 1px solid var(--border);
  white-space: nowrap;
}
tbody td {
  padding: var(--space-4);
  border-block-start: 1px solid var(--hairline);
  vertical-align: top;
}
tbody tr:first-child td { border-block-start: 0; }
.cell-primary { color: var(--fg); font-weight: var(--weight-medium); }
.cell-actions { white-space: nowrap; text-align: end; }
.cell-actions .row { justify-content: flex-end; gap: var(--space-1); }

/* --- Badge: semantic state, not decoration -------------------------------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-meta);
  line-height: var(--leading-meta);
  font-weight: var(--weight-medium);
  white-space: nowrap;
}
/* The neutral badge carries a state on the picture pages — Held, Declined — so
   it needs a surface, and it sits on top of an L1 row rather than on the canvas.
   That is a different problem from the segmented track below, and it took a
   screenshot to see: --surface-sunken is darker than the canvas, which is right
   in the light theme (where L1 is white, so separating means going grey) and
   wrong in the dark one, where a near-black chip on a #211f1c row reads as a
   hole punched through the table.
   --surface-inset is "one step away from L1", and the direction is the theme's:
   lighter in dark, darker in light. */
.badge-neutral { background: var(--surface-inset); color: var(--fg-muted); }
.badge-positive { background: var(--positive-wash); color: var(--positive); }
.badge-negative { background: var(--negative-wash); color: var(--negative); }
.badge-notice { background: var(--notice-wash); color: var(--notice); }
.badge-accent { background: var(--accent-wash); color: var(--accent-text); }
.badge__dot { inline-size: 6px; block-size: 6px; border-radius: 999px; background: currentColor; flex: none; }

/* --- Empty state: lives inside the frame, never replaces it --------------- */
.empty {
  padding: var(--space-12) var(--space-6);
  text-align: center;
}
.empty h3 { font-size: var(--text-h4); margin-block-end: var(--space-2); }
.empty p { color: var(--fg-muted); font-size: var(--text-secondary); max-inline-size: 48ch; margin-inline: auto; }
.empty .btn { margin-block-start: var(--space-6); }

/* --- Flash ---------------------------------------------------------------- */
.flash {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-inline-start: 3px solid var(--fg-faint);
  border-radius: var(--radius-sm);
  background: var(--surface-l1);
  font-size: var(--text-secondary);
  margin-block-end: var(--space-8);
}
.flash svg { inline-size: 18px; block-size: 18px; flex: none; margin-block-start: 1px; }
/* The live-update notice reuses the flash look; it only needs to line its button up and to honour [hidden]. */
.live-notice { justify-content: space-between; align-items: center; }
.live-notice[hidden], .live-decision[hidden] { display: none; }
.flash-ok { border-inline-start-color: var(--positive); }
.flash-ok svg { color: var(--positive); }
.flash-err { border-inline-start-color: var(--negative); }
.flash-err svg { color: var(--negative); }

/* --- Dialog: destructive confirmation ------------------------------------ */
dialog.dialog {
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  background: var(--surface-l3);
  color: var(--fg);
  inline-size: min(440px, calc(100vw - var(--space-8)));
  box-shadow: var(--shadow-l3);
}
dialog.dialog::backdrop { background: var(--scrim); }
.dialog__body { padding: var(--space-6); }
.dialog__body h2 { font-size: var(--text-h4); margin-block-end: var(--space-2); }
.dialog__body p { color: var(--fg-muted); font-size: var(--text-secondary); }
.dialog__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  justify-content: flex-end;
  padding: var(--space-4) var(--space-6);
  border-block-start: 1px solid var(--hairline);
}

/* --- Key/value list (profile metadata, channel facts) --------------------- */
.kv { display: grid; gap: var(--space-4); }
.kv > div { display: grid; gap: var(--space-1); }
.kv dt { font-size: var(--text-meta); line-height: var(--leading-meta); color: var(--fg-faint); }
.kv dd { font-size: var(--text-body); color: var(--fg); }
@media (min-width: 768px) {
  .kv { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
}

/* --- Stat line: the dashboard glance, no boxes ---------------------------- */
.stats { display: grid; gap: var(--space-8); grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); }
.stat__value { font-size: var(--text-h2); font-weight: var(--weight-semibold); line-height: var(--leading-heading); letter-spacing: -0.02em; }
.stat__label { font-size: var(--text-meta); line-height: var(--leading-meta); color: var(--fg-faint); margin-block-start: var(--space-1); }

/* --- Centred single-purpose pages: auth, status --------------------------- */
.centred {
  width: 100%;
  max-inline-size: 420px;
  margin-inline: auto;
  padding-block: var(--space-8);
}
.centred-wide { max-inline-size: 560px; }
.centred .page-head { text-align: center; margin-block-end: var(--space-8); }
.centred .page-head__lead { margin-inline: auto; }

/* --- Narrow ---------------------------------------------------------------
   Chrome collapses to a menu button; the same destinations stay reachable.
   -------------------------------------------------------------------------- */
@media (max-width: 767.98px) {
  main { padding-block: var(--space-8) var(--space-12); }

  /* A phone: the account menu rises from the bottom as a sheet over a scrim. */
  .account[open] > summary::before { content: ""; position: fixed; inset: 0; background: var(--scrim); z-index: var(--z-popover); cursor: default; }
  .account__panel {
    position: fixed;
    inset-block: auto 0;
    inset-inline: 0;
    inline-size: auto;
    max-block-size: 85vh;
    overflow-y: auto;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    border-inline: 0;
    border-block-end: 0;
  }
  .icon-btn.account__close { display: inline-flex; }
  .account__toggle { border: 0; padding-inline: 0; }
  .account__toggle > svg { display: none; }

  .page-head { margin-block-end: var(--space-8); }
  h1 { font-size: var(--text-h2); }
  .stats { gap: var(--space-6); }
  .form-actions > .btn { flex: 1; }
  .cell-actions, .cell-actions .row { text-align: start; justify-content: flex-start; }
}

/* Without JavaScript the menu button cannot open anything, so the links are
   shown instead of being unreachable. */
.no-js .icon-btn.nav-toggle { display: none; }
.no-js [data-hide-without-script] { display: none; }

/* Below the wide breakpoint the bar cannot hold every destination: a menu button opens the same list, as a full panel. */
@media (max-width: 1179.98px) {
  .icon-btn.nav-toggle { display: inline-flex; }
  .site-nav {
    display: none;
    position: fixed;
    inset-block: calc(var(--nav-height) + 1px) 0;
    inset-inline: 0;
    z-index: var(--z-popover);
    overflow-y: auto;
    background: var(--surface-l0);
    padding: var(--space-3) var(--space-4) var(--space-8);
  }
  .site-header[data-nav-open="true"] .site-nav { display: block; }
  .site-nav__list { flex-direction: column; align-items: stretch; gap: var(--space-1); }
  .site-nav__link, .site-nav--dense .site-nav__link { display: flex; padding-inline: var(--space-3); font-size: var(--text-body); color: var(--fg); }
  .site-nav__link > svg:first-child { display: block; color: var(--fg-muted); flex: none; }
  .menu > summary.site-nav__link > svg:last-child { margin-inline-start: auto; }
  .site-nav__picker .menu__panel {
    position: static;
    inline-size: auto;
    background: transparent;
    border: 0;
    box-shadow: none;
  }
  .picker__list { max-block-size: none; overflow: visible; }

  .no-js .site-header { position: static; }
  .no-js .site-nav { display: block; position: static; padding: 0; }
  .no-js .site-header__bar { flex-wrap: wrap; }
  .no-js .site-nav { order: 3; flex-basis: 100%; }
}

/* --- Reduced motion -------------------------------------------------------
   Scoped rather than a blanket reset: every transition in this file animates
   only opacity, colour or transform, so removing transform and shortening the
   rest leaves every state change still visible.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: var(--motion-100) !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
  .toggle input::after { transition: background var(--motion-100) ease; }
  .skip-link { transition: none; }
}

/* --- Ordered steps --------------------------------------------------------
   Numbers because these genuinely are a sequence, not because a number beside
   a heading looks designed.
   -------------------------------------------------------------------------- */
.numbered {
  list-style: decimal;
  padding-inline-start: var(--space-6);
  color: var(--fg-muted);
}
.numbered li::marker { color: var(--fg-faint); font-variant-numeric: tabular-nums; }
.numbered li + li { margin-block-start: var(--space-2); }

/* --- Landing --------------------------------------------------------------
   The one place this interface raises its voice. Everything else stays quiet. Scoped to the landing page's own classes.
   -------------------------------------------------------------------------- */
.landing { display: grid; gap: var(--space-16); }
.landing-hero { display: grid; gap: var(--space-12); align-items: center; padding-block: var(--space-12) var(--space-4); }
.landing-hero__copy { display: grid; gap: var(--space-6); justify-items: start; min-inline-size: 0; inline-size: 100%; }
.landing-badge {
  display: inline-flex; align-items: center; margin: 0; padding: var(--space-1) var(--space-3);
  border: 1px solid var(--accent); border-radius: 999px; background: var(--accent-wash);
  color: var(--accent-text); font-size: var(--text-meta); line-height: var(--leading-meta);
}
.landing-hero h1 { inline-size: 100%; font-size: var(--text-display); line-height: var(--leading-display); letter-spacing: -0.03em; margin: 0; }
.landing-hero h1 span { display: block; }
.landing-hero h1 span:nth-child(2) { color: var(--accent-text); }
.landing-hero__lead { font-size: var(--text-h4); line-height: 1.45; color: var(--fg-muted); max-inline-size: var(--prose); margin: 0; }
.landing-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.landing-actions .btn { min-block-size: var(--hit); }
[dir="rtl"] .landing .btn svg:last-child:not(:first-child) { transform: scaleX(-1); }
.landing-trust { display: inline-flex; align-items: center; gap: var(--space-2); margin: 0; color: var(--fg-muted); font-size: var(--text-secondary); }
.landing-trust svg { inline-size: 16px; block-size: 16px; flex: none; }
/* The hero illustration: three product areas around the BezBot mark. Abstract shapes and the application's own labels, no data. */
.landing-stage {
  position: relative; display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); grid-template-rows: auto auto;
  gap: var(--space-4); align-items: start; min-inline-size: 0; padding: var(--space-4);
  background: var(--surface-l1); border: 1px solid var(--border); border-radius: var(--radius-lg);
}
.landing-stage::before, .landing-stage::after { content: ""; position: absolute; pointer-events: none; border-color: var(--border-strong); border-style: dashed; border-width: 0; }
.landing-stage::before { inset-block: var(--space-6); inset-inline-start: 50%; border-inline-start-width: 1px; }
.landing-stage::after { inset-inline: var(--space-6); inset-block-start: 62%; border-block-start-width: 1px; }
.stage-card {
  position: relative; z-index: 1; display: grid; gap: var(--space-3); align-content: start; min-inline-size: 0; padding: var(--space-4);
  background: var(--surface-l2); border: 1px solid var(--border); border-radius: var(--radius-md);
}
.stage-card--mod { grid-row: 1 / span 2; align-self: stretch; align-content: start; box-shadow: var(--shadow-l2); }
.stage-card--game { grid-column: 2; }
.stage-card--rewards { grid-column: 2; margin-inline-start: calc(var(--space-4) * -1); box-shadow: var(--shadow-l2); }
.stage-card__head { display: flex; align-items: center; gap: var(--space-2); margin: 0; font-size: var(--text-secondary); font-weight: var(--weight-semibold); min-inline-size: 0; }
.stage-card__head > span:last-child { overflow-wrap: anywhere; }
.stage-card__icon { display: grid; place-items: center; flex: none; inline-size: 28px; block-size: 28px; border-radius: var(--radius-sm); background: var(--accent-wash); color: var(--accent); }
.stage-card__icon svg { inline-size: 16px; block-size: 16px; }
.stage-card__caption { margin: 0; font-size: var(--text-meta); line-height: var(--leading-meta); color: var(--fg-muted); }
.stage-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.stage-rows li { display: flex; align-items: center; gap: var(--space-2); min-inline-size: 0; }
.stage-rows .badge { flex: none; }
.stage-dot { flex: none; inline-size: 24px; block-size: 24px; border-radius: 50%; background: var(--surface-inset); border: 1px solid var(--border); }
.stage-bar { flex: 1 1 auto; min-inline-size: 16px; block-size: 8px; border-radius: 999px; background: var(--surface-inset); }
.stage-bar--short { flex-basis: 40%; flex-grow: 0; }
.stage-pill { flex: none; inline-size: 44px; block-size: 20px; border-radius: 999px; border: 1px dashed var(--border-strong); }
.stage-picture { position: relative; display: block; overflow: hidden; aspect-ratio: 16 / 9; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--surface-inset); }
.stage-picture i { position: absolute; border-radius: 50%; filter: blur(7px); }
.stage-picture i:nth-child(1) { inline-size: 46%; block-size: 70%; inset-inline-start: 8%; inset-block-start: 22%; background: var(--accent); opacity: 0.7; }
.stage-picture i:nth-child(2) { inline-size: 34%; block-size: 50%; inset-inline-end: 10%; inset-block-start: 8%; background: var(--fg-faint); opacity: 0.55; }
.stage-picture i:nth-child(3) { inline-size: 40%; block-size: 38%; inset-inline-end: 22%; inset-block-end: -8%; background: var(--accent-text); opacity: 0.35; }
.stage-field { display: block; block-size: 24px; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--surface-inset); }
.stage-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); }
.stage-tiles > span { display: grid; gap: var(--space-2); padding: var(--space-2); border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-inset); }
.stage-tiles i { display: block; aspect-ratio: 4 / 3; border-radius: var(--radius-sm); background: var(--accent-wash); border: 1px solid var(--border); }
.stage-tiles b { display: block; block-size: 6px; inline-size: 70%; border-radius: 999px; background: var(--border-strong); }
.stage-mark {
  position: absolute; z-index: 2; left: 50%; top: 62%; translate: -50% -50%; display: grid; place-items: center;
  inline-size: 44px; block-size: 44px; border-radius: 50%; background: var(--surface-l1); border: 1px solid var(--border-strong);
}
.stage-mark svg { inline-size: 24px; block-size: 24px; }
@media (max-width: 767.98px) {
  .landing-stage { padding: var(--space-3); gap: var(--space-3); }
  .stage-card { padding: var(--space-3); gap: var(--space-2); }
  .stage-card--rewards { margin-inline-start: calc(var(--space-3) * -1); }
  .stage-card__caption { display: none; }
  .stage-rows li:nth-child(n+3) { display: none; }
  .stage-card__icon { inline-size: 24px; block-size: 24px; }
}
.landing-section { display: grid; gap: var(--space-8); padding-block-start: var(--space-12); border-block-start: 1px solid var(--hairline); scroll-margin-block-start: var(--space-8); }
.landing-section__head { display: grid; gap: var(--space-2); }
.landing-section__head h2 { font-size: var(--text-h3); margin: 0; }
.landing-section__head p { margin: 0; }
.landing-cards, .landing-points, .landing-how { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-4); }
.landing-cards { grid-template-columns: minmax(0, 1fr); }
.landing-card { display: grid; gap: var(--space-2); align-content: start; padding: var(--space-6); background: var(--surface-l1); border: 1px solid var(--border); border-radius: var(--radius-md); }
.landing-card h3 { font-size: var(--text-body); font-weight: var(--weight-semibold); margin: var(--space-2) 0 0; }
.landing-card p { margin: 0; color: var(--fg-muted); font-size: var(--text-secondary); }
.landing-card__icon { display: grid; place-items: center; inline-size: 40px; block-size: 40px; flex: none; background: var(--surface-l2); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--accent); }
.landing-card__icon svg { inline-size: 20px; block-size: 20px; }
.landing-points { grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }
.landing-points li { display: flex; gap: var(--space-4); align-items: flex-start; }
.landing-points h3 { font-size: var(--text-body); font-weight: var(--weight-medium); margin: 0 0 var(--space-1); }
.landing-points p { margin: 0; color: var(--fg-muted); font-size: var(--text-secondary); }
.landing-how { grid-template-columns: minmax(0, 1fr); gap: var(--space-6); }
.landing-how li { display: grid; gap: var(--space-3); align-content: start; }
.landing-how p { margin: 0; font-size: var(--text-body); }
.landing-how__n { display: grid; place-items: center; inline-size: 32px; block-size: 32px; border: 1px solid var(--accent); border-radius: 50%; background: var(--accent-wash); color: var(--accent-text); font-size: var(--text-secondary); font-variant-numeric: tabular-nums; }
.landing-band { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-4) var(--space-8); padding: var(--space-8); margin-block-end: var(--space-8); background: var(--surface-l1); border: 1px solid var(--border); border-radius: var(--radius-lg); }
.landing-band h2 { font-size: var(--text-h4); margin: 0 0 var(--space-1); }
.landing-band p { margin: 0; font-size: var(--text-secondary); }
.landing-band .btn { min-block-size: var(--hit); }

@media (min-width: 600px) { .landing-cards, .landing-points { grid-template-columns: repeat(2, minmax(0, 1fr)); } .landing-how { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px) {
  .landing-hero { padding-block-start: var(--space-16); }
  .landing-hero__copy { grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--space-8); }
  .landing-badge, .landing-title, .landing-hero__lead { grid-column: 1 / -1; }
  .landing-hero .landing-title span { display: inline-block; }
  .landing-hero__lead { max-inline-size: calc(var(--prose) + var(--space-16)); }
  .landing-actions { grid-column: 1; }
  .landing-trust { grid-column: 2; align-self: center; justify-self: end; }
  .landing-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .landing-points { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .landing-how { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 767.98px) {
  .landing { gap: var(--space-12); }
  .landing-hero { gap: var(--space-8); padding-block-start: var(--space-6); }
  .landing-hero h1 { font-size: var(--text-h1); }
  .landing-hero__lead { font-size: var(--text-body); }
  .landing-actions { flex-direction: column; align-items: stretch; inline-size: 100%; }
  .landing-actions .btn, .landing-band .btn { justify-content: center; inline-size: 100%; }
  .landing-band { padding: var(--space-6); }
}

@keyframes landing-reveal {
  from { opacity: 0; transform: translateY(var(--space-2)); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: no-preference) {
  .landing-title span,
  .landing-hero__lead,
  .landing-badge,
  .landing-actions,
  .landing-trust,
  .landing > .landing-section,
  .landing > .landing-band {
  animation: landing-reveal calc(var(--motion-300) * 12) cubic-bezier(0.22, 1, 0.36, 1) both;
}
  .landing-title span:nth-child(1) { animation-delay: calc(var(--motion-100) * 4); }
  .landing-title span:nth-child(2) { animation-delay: calc(var(--motion-100) * 8); }
  .landing-title span:nth-child(3) { animation-delay: calc(var(--motion-100) * 12); }
  .landing-hero__lead { animation-delay: calc(var(--motion-100) * 16); }
  .landing-badge, .landing-actions, .landing-trust { animation-delay: calc(var(--motion-100) * 20); }
  .landing > .landing-section, .landing > .landing-band { animation-delay: calc(var(--motion-100) * 22); }
}

/* --- Utilities ------------------------------------------------------------ */
.visually-hidden {
  position: absolute;
  inline-size: 1px; block-size: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* The state counts double as filter links. A link is a control, so it gets a
   control's tap area — MEASURED at 68x21 before this. The badge keeps its own
   size; the area around it is what grew. */
.summary-row a.badge {
  min-block-size: var(--hit);
  padding-inline: var(--space-3);
}

/* A one-line summary above a table: counts and state, not a KPI strip. */
.summary-row {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  margin-block-end: var(--space-4);
  color: var(--fg-muted);
  font-size: var(--text-secondary);
}

/* Stacked facts inside one table cell: the primary value, then its context. */
td .meta { display: block; margin-block-start: var(--space-1); }
td .badge + .badge { margin-inline-start: var(--space-1); }

/* --- Disclosure ----------------------------------------------------------- */
.disclosure summary {
  cursor: pointer;
  color: var(--accent-text);
  font-size: var(--text-secondary);
  min-block-size: var(--hit);
  display: flex;
  align-items: center;
}
.disclosure summary::marker { color: var(--fg-faint); }
.disclosure__body {
  margin-block-start: var(--space-2);
  font-size: var(--text-secondary);
  color: var(--fg-muted);
}
.disclosure__body > div + div { margin-block-start: var(--space-1); }
.note-key { color: var(--fg-faint); }

/* --- File input and its preview ------------------------------------------- */
.file-input { padding: var(--space-2); line-height: 1.6; }
.file-input::file-selector-button {
  margin-inline-end: var(--space-3);
  min-block-size: 32px;
  padding-inline: var(--space-3);
  border: 1px solid var(--border-control);
  border-radius: var(--radius-sm);
  background: var(--surface-l2);
  color: var(--fg);
  font: inherit;
  font-size: var(--text-secondary);
  cursor: pointer;
}
.image-preview {
  display: block;
  max-inline-size: 100%;
  max-block-size: 220px;
  margin-block-start: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

/* A control that is working. The label says so too, so the state is never
   carried by motion or colour alone. */
[aria-busy="true"] { opacity: 0.7; cursor: progress; }

/* --- Settings layout ------------------------------------------------------
   Section nav beside the fields on wide, stacked above them on narrow — never
   a side rail squeezed next to a form on a phone.
   -------------------------------------------------------------------------- */
.settings-layout { display: grid; gap: var(--space-8); }
.settings-body { min-inline-size: 0; }
.settings-nav ul { list-style: none; display: flex; flex-wrap: wrap; gap: var(--space-1); }
.settings-nav a {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--hit);
  padding-inline: var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--fg-muted);
  font-size: var(--text-secondary);
  text-decoration: none;
}
.settings-nav a:hover { color: var(--fg); background: var(--surface-l1); }

@media (min-width: 768px) {
  .settings-layout { grid-template-columns: 200px minmax(0, 1fr); gap: var(--space-12); align-items: start; }
  .settings-nav { position: sticky; inset-block-start: calc(var(--nav-height) + var(--space-6)); }
  .settings-nav ul { flex-direction: column; gap: 0; }
  .settings-nav a { display: flex; }
}

fieldset { border: 0; }
.field-pair {
  display: grid;
  gap: var(--space-4) var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  max-inline-size: var(--prose);
}
/* A field-pair is a field group, so it spaces like one. Without this it had no
   bottom margin of its own — it only ever looked right because an <h3> with its
   own top margin happened to follow it, and the moment a fieldset followed
   instead, the next legend sat flush against the hint above it. */
.field-pair { margin-block-end: var(--space-6); }
.field-pair:last-child { margin-block-end: 0; }
.field-pair .field { margin-block-end: 0; }
.section h3.section__head { font-size: var(--text-h4); margin-block: var(--space-8) var(--space-4); }

/* --- Validation ----------------------------------------------------------
   Set only after a field has been left once (see public/js/app.js). The border
   AND the message carry the state, so it is never colour alone.
   -------------------------------------------------------------------------- */
.input.is-invalid,
.select.is-invalid,
.textarea.is-invalid { border-color: var(--negative); }
.hint-error { color: var(--negative); }

/* --- Long-form legal pages ------------------------------------------------
   Prose at the reading measure, with a contents index beside it once there is
   room. The index is the page's structural surface; the prose itself stays on
   the canvas, because a card around a legal document is the chrome this
   redesign exists to remove.
   -------------------------------------------------------------------------- */
.legal-layout { display: grid; gap: var(--space-8); }
.legal-index h2 { font-size: var(--text-secondary); color: var(--fg-faint); font-weight: var(--weight-medium); margin-block-end: var(--space-3); }
.legal-index__list { list-style: none; counter-reset: legal; }
.legal-index__list li { counter-increment: legal; }
.legal-index__list a {
  display: block;
  padding-block: var(--space-2);
  min-block-size: var(--hit);
  font-size: var(--text-secondary);
  color: var(--fg-muted);
  text-decoration: none;
}
.legal-index__list a:hover { color: var(--fg); }

@media (min-width: 768px) {
  .legal-layout { grid-template-columns: minmax(0, 1fr) minmax(0, 17rem); gap: var(--space-12); align-items: start; }
  /* Index after the prose in the source so a screen reader hears the document
     first, but placed beside it visually. */
  .legal-index { grid-column: 2; grid-row: 1; position: sticky; inset-block-start: calc(var(--nav-height) + var(--space-6)); }
  .legal-layout .prose { grid-column: 1; grid-row: 1; }
}

/* ==========================================================================
   STEP 4 — THE ADMIN AREA
   Four pages: an approvals inbox, two filtered lists over the picture bank,
   and one operational view over the upload log. Everything below is built from
   the tokens at the top of this file; there is no new colour and no new size.
   ========================================================================== */

/* --- A heading with a control beside it ----------------------------------- */
.page-head__row { display: flex; flex-wrap: wrap; gap: var(--space-6); align-items: flex-end; justify-content: space-between; }
.page-head__row > div:first-child { min-inline-size: 0; }
/* The page's scope, not a filter: which channel's uploads this page is about. */
.scope-picker { min-inline-size: min(100%, 22rem); }
.scope-picker .input-row { margin-block-start: var(--space-2); }
.scope-picker .select { min-inline-size: 0; }

/* A label that sits on the same line as the thing it labels. Still a real
   <label>, still visible — this only changes where it sits. */
.label-inline { display: inline-block; margin-block-end: var(--space-2); }

/* A note under a region, explaining a rule rather than a value. */
.page-note {
  margin-block-start: var(--space-6);
  color: var(--fg-faint);
  font-size: var(--text-meta);
  line-height: var(--leading-meta);
  max-inline-size: var(--prose);
}

/* --- List toolbar: search, and the one Filters control -------------------- */
.list-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4) var(--space-8);
  align-items: flex-end;
  margin-block-end: var(--space-4);
}
.list-search { flex: 1 1 18rem; min-inline-size: 0; max-inline-size: 26rem; }
.list-search .label { margin-block-end: var(--space-2); }
.filters > summary { gap: var(--space-2); }
.filters > summary svg { inline-size: 18px; block-size: 18px; }

/* The Filters control is a compact item in the toolbar while it is shut, and
   takes a full-width line of its own once it is open.
   MEASURED, not assumed: as an ordinary `flex: 0 0 auto` item the <details>
   shrinks to the width of its summary (67px at 375), while the panel inside it
   still asks for its 13rem columns — so the fields rendered to the right of the
   viewport and gave the page 260px of horizontal scroll. Both halves of the fix
   are needed: the row below lets an open panel claim the width, and the
   `min(13rem, 100%)` stops auto-fit demanding a column wider than its container
   at any width in between. */
.list-toolbar > .disclosure,
.range-row > .disclosure { flex: 1 1 100%; min-inline-size: 0; }
.filters__body {
  min-inline-size: 0;
  margin-block-start: var(--space-4);
  padding: var(--space-6);
  background: var(--surface-l1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--edge-light);
}
.filters__grid {
  display: grid;
  gap: var(--space-4) var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
  margin-block-end: var(--space-6);
}
.filters__grid .field { margin-block-end: 0; max-inline-size: none; }

@media (min-width: 768px) {
  /* Shut, it sits inline with the rest of the toolbar. Open, it still gets its
     own line, because three fields beside a search box is a scrum. */
  .list-toolbar > .disclosure:not([open]),
  .range-row > .disclosure:not([open]) { flex: 0 0 auto; }
  .range-row > .disclosure:not([open]) { margin-inline-start: auto; }
}

/* --- Active filter chips -------------------------------------------------- */
.chips {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  margin-block-end: var(--space-4);
}
/* A chip is interactive — it removes its own filter — which is the only reason
   it is allowed to be a pill at all. Static metadata stays plain text. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-block-size: var(--hit);
  padding-inline: var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--fg-muted);
  font-size: var(--text-meta);
  text-decoration: none;
  transition: color var(--motion-150) var(--ease-out), border-color var(--motion-150) var(--ease-out);
}
.chip:hover { color: var(--fg); border-color: var(--fg-faint); text-decoration: none; }
.chip__x { display: inline-flex; }
.chip__x svg { inline-size: 14px; block-size: 14px; }

/* --- Picture rows -------------------------------------------------------- */
/* A text cell's max-content is its longest line laid out flat, and a table told
   `min-inline-size: max-content` inherits that. MEASURED: the answer and state
   columns made the picture table 1270px wide inside a 1214px frame, so at 1280 —
   where everything should fit — the Mark broken button was clipped and the table
   scrolled for 56px. Capping the two prose columns caps the table. */
.cell-text { max-inline-size: 26ch; }
/* The secondary prose columns get a tighter cap than the answer, which is the
   primary cell and earns the width. */
.cell-text--tight { max-inline-size: 19ch; }

/* TRIED AND REVERTED: pinning the actions column to the inline-end edge, so the
   buttons stay put while the row scrolls. It is the standard answer and it was
   wrong here — the three labelled buttons are 265px of a 341px viewport, so the
   pinned column covered the picture, the answer and the uploader, and the table
   became a column of buttons with nothing to judge. A screenshot said so.
   The narrow path is the one the List/Index catalog names: the table scrolls
   inside its region, and the always-visible workflow is the tick box in the
   first column plus the bulk bar beneath, which needs no sideways scrolling at
   all. The per-row buttons are the convenience, not the only route. */

.cell-pick { inline-size: var(--hit); }
/* The label is the hit target, so the 44px floor is met by the row's tappable
   area rather than by the 18px box the browser draws. */
.pick {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: var(--hit);
  min-block-size: var(--hit);
  cursor: pointer;
}
.pick input { inline-size: 18px; block-size: 18px; accent-color: var(--accent); }

.cell-thumb { inline-size: 96px; }
.thumb {
  display: block;
  inline-size: 96px;
  block-size: 62px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--surface-l2);
  border: 1px solid var(--hairline);
}
.thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; display: block; }
/* Nothing to request: the stored file is gone, so a placeholder stands in
   rather than a broken-image glyph the browser chooses for us. */
.thumb-gone { display: flex; align-items: center; justify-content: center; color: var(--fg-faint); }
.thumb-gone svg { inline-size: 24px; block-size: 24px; }
/* The other half of the same story: a remote URL we could not know was dead
   until the browser tried it. app.js marks the cell, and the row then looks the
   same as one whose file was already known to be missing, instead of showing
   whatever broken-image mark the browser felt like drawing. */
.cell-thumb[data-dead] .thumb { background: var(--surface-l2); }
.cell-thumb[data-dead] img { display: none; }

/* --- Bulk actions -------------------------------------------------------- */
/* The three per-row decision forms. Present in the DOM, outside the flow, and
   never focusable, because they hold nothing but hidden inputs. */
.offscreen-form { display: contents; }
.bulk-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-4);
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-4);
  border-block-start: 1px solid var(--hairline);
  /* Inside the table frame, so it separates from L1, not from the canvas. */
  background: var(--surface-inset);
}
.bulk-bar__count { font-size: var(--text-meta); color: var(--fg-muted); margin: 0; }
.approve-all { margin-block-start: var(--space-4); }

/* --- Pagination ---------------------------------------------------------- */
.pager {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-4);
  align-items: center;
  justify-content: space-between;
  margin-block-start: var(--space-4);
}
.pager__state { font-size: var(--text-meta); color: var(--fg-faint); margin: 0; }
/* A page you cannot reach keeps its label. It is dimmed and it does not react,
   but it never becomes an unlabelled outline. */
.is-disabled { color: var(--fg-faint); border-color: var(--hairline); cursor: default; }
.is-disabled:hover { background: transparent; border-color: var(--hairline); }

/* --- Segmented control: tabs and ranges ---------------------------------- */
.segmented {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  padding: var(--space-1);
  /* A recessed track with the selected item raised out of it. The other way
     round — a raised track with a more-raised item — cannot work in the light
     theme, where L1, L2 and L3 are all white. */
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--edge-light);
}
.segmented__item {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--hit);
  padding-inline: var(--space-4);
  border-radius: var(--radius-sm);
  font-size: var(--text-secondary);
  color: var(--fg-muted);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--motion-150) var(--ease-out), background-color var(--motion-150) var(--ease-out);
}
.segmented__item:hover { color: var(--fg); background: var(--surface-l2); text-decoration: none; }
/* Weight as well as surface, so the current item is not told by colour alone. */
.segmented__item.is-current {
  color: var(--fg);
  background: var(--surface-l1);
  font-weight: var(--weight-medium);
  box-shadow: var(--edge-light);
}
.segmented-tabs { margin-block-end: var(--space-8); }

/* --- The approvals feed -------------------------------------------------- */
/* Rows, not a table: no headers, no sort. The frame is the row divider plus the
   surface, which is the list chrome an inbox is allowed. */
.feed {
  list-style: none;
  background: var(--surface-l1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--edge-light);
  overflow: hidden;
}
.feed__row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4) var(--space-6);
  align-items: flex-start;
  justify-content: space-between;
  padding: var(--space-4) var(--space-6);
  /* The leading accent lives here as a transparent border so a waiting row can
     colour it in without the row shifting by 3px. */
  border-inline-start: 3px solid transparent;
}
.feed__row + .feed__row { border-block-start: 1px solid var(--hairline); }
/* "Unread": the accent AND the weight, never the colour by itself. */
.feed__row.is-waiting { border-inline-start-color: var(--accent); background: var(--surface-l2); }
.feed__row.is-waiting .feed__title { font-weight: var(--weight-semibold); }
.feed__main { min-inline-size: 0; flex: 1 1 18rem; }
.feed__title {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
  font-size: var(--text-body);
  font-weight: var(--weight-medium);
  color: var(--fg);
  margin: 0;
}
.feed__meta {
  margin-block-start: var(--space-1);
  font-size: var(--text-meta);
  line-height: var(--leading-meta);
  color: var(--fg-muted);
  overflow-wrap: anywhere;
}
.feed__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }

/* --- Upload activity ----------------------------------------------------- */
.range-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4) var(--space-8);
  align-items: flex-end;
  margin-block-end: var(--space-8);
}
.range-row .label-inline { margin-block-end: 0; align-self: center; }

/* The <dl> form of the metric strip. Same sizes as .stat__value / .stat__label;
   a definition list is simply the honest element for a label and its number. */
.stats { margin-block-end: var(--space-12); }
.stats dt { font-size: var(--text-meta); line-height: var(--leading-meta); color: var(--fg-faint); }
.stats dd {
  font-size: var(--text-h2);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-heading);
  letter-spacing: -0.02em;
  margin: 0;
  font-variant-numeric: tabular-nums;
}
.stats dd.stat-alert { color: var(--notice); }

/* The chart. Markup and tokens: the only computed value is each bar's height,
   which is data, not a design decision. */
.chart {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  block-size: 9rem;
  padding: var(--space-4);
  background: var(--surface-l1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--edge-light);
}
.chart__col { flex: 1 1 0; min-inline-size: 2px; block-size: 100%; display: flex; align-items: flex-end; }
.chart__stack { inline-size: 100%; block-size: 100%; display: flex; flex-direction: column; justify-content: flex-end; }
/* --bar-height is the one value a template is allowed to set, because it is the
   measurement being drawn. The property, the floor and the rounding live here. */
.chart__bar { display: block; inline-size: 100%; border-radius: 1px; block-size: var(--bar-height, 0%); }
.chart__bar--accepted { background: var(--accent); }
.chart__bar--rejected { background: var(--negative); }
.chart__axis {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  align-items: center;
  justify-content: space-between;
  margin-block-start: var(--space-2);
  font-size: var(--text-meta);
  color: var(--fg-faint);
}
.chart__legend { display: inline-flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.chart__key { inline-size: 10px; block-size: 10px; border-radius: 2px; display: inline-block; }
.chart__key--accepted { background: var(--accent); }
.chart__key--rejected { background: var(--negative); }
.chart__key--rejected + * { margin-inline-start: 0; }

/* `minmax(0, 1fr)` rather than the implicit `auto` track, at BOTH widths.
   BISECTED, not assumed: with an implicit auto column the track was sized by the
   rate tables' max-content (533px) instead of by the 343px container, and the
   page gained 260px of horizontal scroll even though each table was already
   inside its own overflow region. `auto` zeroes a scroll container's MIN-content
   contribution, not its max-content one, so the track has to be told it may
   not grow. */
.two-up { display: grid; gap: var(--space-8); grid-template-columns: minmax(0, 1fr); }
/* The rate boards are three short columns, not a wide data table, so they wrap
   to the space they have instead of going max-content and scrolling. MEASURED:
   with the global rule they clipped "0 accepted · 14 refused" at 1280, which is
   the number the page exists to show. */
.two-up .table-scroll table { min-inline-size: 0; }
.board-title {
  font-size: var(--text-secondary);
  font-weight: var(--weight-medium);
  color: var(--fg-muted);
  margin-block-end: var(--space-3);
}

@media (min-width: 768px) {
  .two-up { grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: start; }
}

/* The scope picker's own submit button is only needed without scripting; with
   it, changing the select submits the form. Hidden by the class app.js adds,
   so the no-JS path keeps a visible, labelled control. */
:root:not(.no-js) [data-hide-when-scripted] { display: none; }

/* ==========================================================================
   STEP 5 — THE STREAMER'S OWN PAGES
   ========================================================================== */

/* The one action a dashboard carries, beside the heading rather than in a row
   of buttons underneath it. */
.page-head__action { flex: 0 0 auto; }

/* A line carrying a single call to action under the metric strip. */
.summary-line { margin-block-end: var(--space-8); }

/* A heading inside a settings group. Groups are named for what a streamer is
   trying to do, so a group can hold more than one feature — Games holds both
   Guess the Blur and the quiz — and each needs its own name without becoming a
   second-level section with its own description block. */
.subsection {
  font-size: var(--text-h4);
  font-weight: var(--weight-medium);
  color: var(--fg);
  margin-block: var(--space-8) var(--space-4);
}
.section > .subsection:first-of-type { margin-block-start: var(--space-4); }

/* Danger zone: last, separated, and bounded so it cannot be mistaken for part
   of the form above it. The border is the separation — the elevation reference
   asks for border before shadow, and a red wash behind a whole region would be
   the kind of alarm that stops being read. */
.danger-zone {
  margin-block-start: var(--space-16);
  padding: var(--space-6);
  border: 1px solid var(--negative);
  border-radius: var(--radius-md);
  background: var(--negative-wash);
}
.danger-zone .section__head { margin-block-end: var(--space-4); }
.danger-zone h2 { font-size: var(--text-h4); }

/* ==========================================================================
   STEP 6 — THE VIEWER'S SIDE
   ========================================================================== */

/* --- Wizard steps --------------------------------------------------------
   Adding a picture is two steps and used to look like one page that sometimes
   appeared. This says where you are. It is type and weight, not a progress
   graphic: two steps do not need a chart. */
.steps {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-6);
  margin-block-end: var(--space-6);
  font-size: var(--text-secondary);
  color: var(--fg-faint);
}
.steps__item { display: inline-flex; align-items: center; gap: var(--space-2); }
.steps__item.is-current { color: var(--fg); font-weight: var(--weight-medium); }
.steps__item a { color: inherit; }
/* The number is the only circle on the page, and it earns it: it is what makes
   "1" and "2" read as a sequence rather than as two labels. */
.steps__n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 1.5rem;
  block-size: 1.5rem;
  border-radius: 50%;
  border: 1px solid var(--border-strong);
  font-size: var(--text-meta);
  font-variant-numeric: tabular-nums;
}
.steps__item.is-current .steps__n { border-color: var(--accent); color: var(--accent-text); }
.steps__item.is-done .steps__n { border-color: var(--border-strong); }

/* --- Reason rows ---------------------------------------------------------
   A name and a sentence saying why it is unavailable, or what happened to an
   upload. Deliberately not a table: there are no columns to compare and no
   sort anyone would want. */
.reasons {
  list-style: none;
  background: var(--surface-l1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--edge-light);
  overflow: hidden;
}
.reasons__row {
  display: grid;
  gap: var(--space-1) var(--space-6);
  padding: var(--space-4) var(--space-6);
}
.reasons__row + .reasons__row { border-block-start: 1px solid var(--hairline); }
.reasons__name { font-weight: var(--weight-medium); color: var(--fg); }
.reasons__name.meta { font-weight: var(--weight-regular); }
.reasons__why { color: var(--fg-muted); font-size: var(--text-secondary); }
@media (min-width: 768px) {
  .reasons__row { grid-template-columns: minmax(8rem, 14rem) minmax(0, 1fr); align-items: baseline; }
}

/* --- Channel cards -------------------------------------------------------
   One card per channel the viewer is known in. A card here is a genuine
   separate object — one channel's figures have nothing to do with the next
   one's — which is the only case the surfaces rule allows a border for. */
.cards { display: grid; gap: var(--space-6); }
@media (min-width: 768px) {
  .cards { grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr)); }
}
.channel-card { display: flex; flex-direction: column; }
.channel-card .panel__body { flex: 1; display: flex; flex-direction: column; gap: var(--space-6); }
/* The card's floor: the action sits at the bottom of every card in a row, whatever the cards above it hold. */
.channel-card__foot { margin-block-start: auto; padding-block-start: var(--space-4); border-block-start: 1px solid var(--hairline); display: grid; gap: var(--space-2); }
.channel-card__foot .hint { margin: 0; }
.note-card .panel__body { flex: 1; }

/* The score block: the points line, then the progress toward a voice pass. */
.score { display: grid; gap: var(--space-2); }
.score__line { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-3); align-items: baseline; }
.score__line strong { font-size: var(--text-h4); font-weight: var(--weight-semibold); }

/* A native <progress>, so it is announced as one and needs no ARIA. The label
   beside it carries the numbers; this is the picture of them, never the only
   copy. Both vendor tracks are set because neither inherits the other's. */
.meter {
  inline-size: 100%;
  block-size: var(--space-2);
  appearance: none;
  border: none;
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  overflow: hidden;
}
.meter::-webkit-progress-bar { background: var(--surface-sunken); border-radius: var(--radius-sm); }
.meter::-webkit-progress-value { background: var(--accent); border-radius: var(--radius-sm); }
.meter::-moz-progress-bar { background: var(--accent); border-radius: var(--radius-sm); }

.card-actions { margin: 0; }

/* A short note beside a status badge in a table cell, for the one thing a
   badge cannot say: what it means for the person reading it. */
.cell-why {
  display: block;
  margin-block-start: var(--space-1);
  max-inline-size: 22ch;
  font-size: var(--text-meta);
  line-height: var(--leading-meta);
  color: var(--fg-faint);
}

/* A section that follows a form or a list frame rather than another section.
   `.section` only ever carried a bottom margin, which was enough while every
   page was a stack of sections; step 6 puts one after the picker's form and
   after the pictures table, where it landed hard against the control above. */
form + .section,
.table-frame + .section,
.cards + .section { margin-block-start: var(--space-12); }

/* ==========================================================================
   STEP 7 — THREE LANGUAGES, TWO DIRECTIONS
   ========================================================================== */

/* --- The language switch -------------------------------------------------
   Header chrome, so it is as small as a control with three readable options
   can be. The globe is the affordance; the label is visually hidden because
   the control already shows the language it is set to, which is the thing a
   label here would have said. */
.lang-switch { display: inline-flex; align-items: center; gap: var(--space-2); }
.lang-switch > svg { flex: none; color: var(--fg-muted); }
.lang-switch__select {
  min-inline-size: 0;
  inline-size: auto;
  padding-inline: var(--space-3) var(--space-8);
  font-size: var(--text-secondary);
}
/* The globe is a second signifier for a control that already names itself.
   At phone width the header has a wordmark, this, the theme switch and the
   menu button, and the wordmark is the thing that must not be squeezed. */
@media (max-width: 767.98px) {
  .lang-switch > svg { display: none; }
}

/* ==========================================================================
   STEP 7 — ARABIC, FRENCH, AND RIGHT TO LEFT
   ========================================================================== */

/* Almost nothing here, which is the point: step 3 wrote every rule with logical
   properties, so the layout mirrors on dir="rtl" alone. What is left is the
   handful of things a logical property cannot express. */

/* An icon that depicts direction rather than a thing. One mark qualifies — see
   partials/icons.njk for why the others do not. */
[dir="rtl"] .icon--mirror { transform: scaleX(-1); }

/* <progress> fills from the inline start in every engine EXCEPT WebKit, which
   fills the -webkit-progress-value box from the physical left whatever the
   direction is. The element is mirrored and the inner value box mirrored back,
   so the fill grows from the right in Arabic and from the left everywhere
   else, in all three engines. */
[dir="rtl"] .meter { transform: scaleX(-1); }
[dir="rtl"] .meter::-webkit-progress-value { transform: scaleX(-1); }

/* Technical strings that are Latin whatever the page language is: a URL, a Kick
   slug, an address, a file name, an identifier. Arabic is bidirectional, so a
   run like "overlay/blur?bid=100&token=7f3c" dropped into an RTL paragraph has
   its punctuation reordered by the bidi algorithm and comes out unreadable —
   and, worse, copy-pasteable only in the wrong order. These are isolated so
   they keep their own direction without affecting the line around them. */
.ltr,
/* <code> in this app is only ever a URL, a path or a command, and the overlay
   URL field is the only monospace input there is. Both are technical strings
   by definition, so they get the treatment without each call site asking. */
code,
.input-mono {
  direction: ltr;
  unicode-bidi: isolate;
  text-align: start;
}

/* A control that has no effect under the chosen mode: dimmed and explained, never disabled
   (a disabled checkbox is not submitted, so saving would silently change the setting). The
   class is set from the saved value; :has() follows the live selection before saving. */
.irrelevant-note { display: none; }
.irrelevant-when-commons.is-irrelevant .irrelevant-note,
#uploads:has(input[name="blur_source_pref"][value="commons_only"]:checked) .irrelevant-note { display: block; }
.irrelevant-when-commons.is-irrelevant .toggle,
#uploads:has(input[name="blur_source_pref"][value="commons_only"]:checked) .irrelevant-when-commons .toggle { color: var(--fg-faint); }

/* --- Guess the Blur round history (pages/rounds.njk) ----------------------------------------------------
   A round is a panel; a player is a native <details>. Nothing here is a new surface or colour: panels, the
   table frame and the badges are the existing ones, and every gap is an existing token. Logical properties
   only, and every cell can wrap, so a long guess or name never widens the page. */
.rounds-bar { margin-block-end: var(--space-4); }
.round + .round { margin-block-start: var(--space-6); }
.round__head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.round__title { font-size: var(--text-h4); margin: 0; }
.round__facts { display: grid; gap: var(--space-3) var(--space-6); grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); margin: 0; }
.round__facts dt { color: var(--fg-muted); font-size: var(--text-secondary); }
.round__facts dd { margin: 0; overflow-wrap: anywhere; }
.players { list-style: none; margin: 0; padding: 0; }
.players > li + li { margin-block-start: var(--space-2); }
.player { border-block-end: 1px solid var(--hairline); }
.player__sum {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1) var(--space-4);
  min-block-size: var(--hit); padding-block: var(--space-2); cursor: pointer;
}
.player__name { font-weight: var(--weight-medium); overflow-wrap: anywhere; }
.player__attempts { color: var(--fg-muted); font-size: var(--text-secondary); }
.player__last { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-1) var(--space-3); min-inline-size: 0; overflow-wrap: anywhere; }
.player__guess { font-family: var(--font-mono); }
.player .table-frame { margin-block: var(--space-2) var(--space-4); }
.check-inline { display: inline-flex; align-items: center; gap: var(--space-2); min-block-size: var(--hit); }
.round__fix { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-4); }
.round__fix .hint { flex: 1 1 18rem; margin: 0; }
.recipients { margin: 0; padding-inline-start: var(--space-6); }
.explain { margin: 0; padding-inline-start: var(--space-6); }

/* --- Rewards (Prompt 24) --------------------------------------------------
   The catalogue is visual-first media, so the chatter's view of it is a grid of thumbnails; the streamer's own list is
   a table. Everything uses the tokens above and logical properties; motion is a short fade and it is switched off by
   the global prefers-reduced-motion rule. */
.reward-thumb {
  display: block;
  inline-size: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--surface-l2);
  border: 1px solid var(--hairline);
}
.reward-thumb img { inline-size: 100%; block-size: 100%; object-fit: cover; display: block; }
.reward-thumb__none { display: flex; align-items: center; justify-content: center; block-size: 100%; color: var(--fg-faint); }
.reward-thumb__none svg { inline-size: 28px; block-size: 28px; }
.reward-thumb--small { inline-size: 96px; border-radius: var(--radius-sm); }

.reward-grid {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr));
  gap: var(--space-6);
}
.reward-card { display: flex; flex-direction: column; gap: var(--space-3); min-inline-size: 0; }
@media (prefers-reduced-motion: no-preference) {
  .reward-card { animation: reward-in var(--motion-300) var(--ease-out) both; }
  @keyframes reward-in { from { opacity: 0; } to { opacity: 1; } }
}
.reward-card__title { font-size: var(--text-body); font-weight: var(--weight-medium); overflow-wrap: anywhere; }
.reward-card__desc { color: var(--fg-muted); font-size: var(--text-secondary); overflow-wrap: anywhere; }
.reward-card__meta { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); align-items: center; justify-content: space-between; color: var(--fg-muted); font-size: var(--text-secondary); font-variant-numeric: tabular-nums; }
.reward-price { color: var(--fg); font-weight: var(--weight-medium); }

.balance { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2) var(--space-3); margin-block-end: var(--space-6); }
.balance__n { font-size: var(--text-h2); font-weight: var(--weight-medium); font-variant-numeric: tabular-nums; }
.balance__label { color: var(--fg-muted); font-size: var(--text-secondary); }

.meter-row { display: grid; gap: var(--space-1); max-inline-size: var(--prose); }
.meter-row + .meter-row { margin-block-start: var(--space-3); }
.meter-row__label { display: flex; justify-content: space-between; gap: var(--space-4); font-size: var(--text-secondary); color: var(--fg-muted); font-variant-numeric: tabular-nums; }
progress.meter {
  appearance: none; -webkit-appearance: none;
  inline-size: 100%; block-size: 8px; border: 0; border-radius: 999px; background: var(--surface-inset); overflow: hidden;
}
progress.meter::-webkit-progress-bar { background: var(--surface-inset); border-radius: 999px; }
progress.meter::-webkit-progress-value { background: var(--accent); border-radius: 999px; }
progress.meter::-moz-progress-bar { background: var(--accent); border-radius: 999px; }

.preview { max-inline-size: 40rem; }
.preview img, .preview video { display: block; inline-size: 100%; block-size: auto; max-block-size: 60vh; object-fit: contain; border-radius: var(--radius-md); background: var(--surface-sunken); border: 1px solid var(--hairline); }

.filters { margin-block-end: var(--space-4); min-inline-size: 0; max-inline-size: 100%; }
.filters > summary { display: inline-flex; align-items: center; gap: var(--space-2); min-block-size: var(--hit); padding-inline: var(--space-3); cursor: pointer; border: 1px solid var(--border-control); border-radius: var(--radius-sm); color: var(--fg); list-style: none; }
.filters > summary::-webkit-details-marker { display: none; }
.filters[open] > summary { background: var(--surface-l1); }
.filters__panel { display: flex; flex-wrap: wrap; gap: var(--space-4); align-items: flex-end; padding-block: var(--space-4); }
.filters__panel .field { margin-block-end: 0; min-inline-size: min(12rem, 100%); }
.toolbar { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: flex-end; margin-block-end: var(--space-4); }
.toolbar .field { margin-block-end: 0; flex: 1 1 14rem; max-inline-size: 28rem; }
.chips { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; margin-block-end: var(--space-4); }

.state-list { list-style: none; display: grid; gap: var(--space-3); max-inline-size: var(--prose); }
.state-list li { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.state-list__name { flex: 1 1 12rem; }
.cell-actions { white-space: nowrap; }
.cell-actions form { display: inline; }
.dropzone-note { color: var(--fg-muted); font-size: var(--text-secondary); }
.steps-list { padding-inline-start: var(--space-6); max-inline-size: var(--prose); color: var(--fg-muted); font-size: var(--text-secondary); }
.steps-list li + li { margin-block-start: var(--space-2); }
@media (prefers-reduced-motion: no-preference) {
  .badge-notice .badge__dot { animation: reward-pulse calc(var(--motion-300) * 5) ease-in-out infinite; }
  @keyframes reward-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
}

/* Safety: ban notices, appeals and the administrator's case page. Tokens only; logical properties. */
ul.stack { list-style: none; padding: 0; }
.facts { display: grid; grid-template-columns: max-content 1fr; gap: var(--space-2) var(--space-6); margin-block: var(--space-4); }
.facts dt { color: var(--fg-muted); font-size: var(--text-secondary); }
.facts dd { margin: 0; overflow-wrap: anywhere; }
@media (max-width: 480px) { .facts { grid-template-columns: 1fr; gap: var(--space-1); } .facts dd { margin-block-end: var(--space-3); } }
.case-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
.case-grid > * { min-inline-size: 0; }
.timeline { list-style: none; padding: 0; display: grid; gap: var(--space-2); }
.timeline li { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); align-items: baseline; padding-block: var(--space-2); border-block-end: 1px solid var(--hairline); }
.timeline time { color: var(--fg-muted); font-size: var(--text-secondary); font-variant-numeric: tabular-nums; }

/* Chatter View / Streamer View: the view label and switch inside the account menu. */
.site-nav__view form { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }

/* --- Global Content Library picker -----------------------------------------
   One markup (partials/library-picker.njk) in two places: the dialog on the catalogue page and a plain page. The panel is a
   column: head, a scrolling body, a foot that stays in view. Tokens and logical properties only, so Arabic mirrors. */
dialog.dialog--library {
  inline-size: min(60rem, calc(100vw - var(--space-8)));
  max-block-size: calc(100dvh - var(--space-8));
  overflow: hidden;
}
dialog.dialog--library[open] { display: flex; flex-direction: column; }
.library__slot { display: flex; flex-direction: column; min-block-size: 0; flex: 1 1 auto; }
.library__note { padding: var(--space-6); color: var(--fg-muted); }
.library, .library__form { display: flex; flex-direction: column; min-block-size: 0; flex: 1 1 auto; }
.library-page .library { min-block-size: auto; }
.library-page .library__form { border: 1px solid var(--hairline); border-radius: var(--radius-lg); background: var(--surface-l1); }
.library__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); padding: var(--space-6); border-block-end: 1px solid var(--hairline); }
.library__head h2 { font-size: var(--text-h3); margin-block-end: var(--space-1); }
.library__lead { color: var(--fg-muted); font-size: var(--text-secondary); max-inline-size: var(--prose); }
.library__body { padding: var(--space-6); overflow-y: auto; min-block-size: 0; flex: 1 1 auto; }
.library__tools { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-6); align-items: flex-end; margin-block-end: var(--space-2); }
.library__tools .field { margin-block-end: 0; flex: 1 1 14rem; max-inline-size: 24rem; }
.library__grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: var(--space-4);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 12rem), 1fr));
}
.library__card { min-inline-size: 0; }
.library__card[hidden] { display: none; }
.library__tile {
  position: relative; display: flex; flex-direction: column; gap: var(--space-2); block-size: 100%;
  padding: var(--space-3); border: 1px solid var(--hairline); border-radius: var(--radius-md); background: var(--surface-l1);
}
.library__tile--pick { cursor: pointer; }
.library__tile--pick:hover { border-color: var(--border-strong); }
.library__tile:has(.library__check:checked) { border-color: var(--accent); background: var(--surface-l2); }
.library__tile:has(.library__check:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.library__check { position: absolute; inset-block-start: var(--space-4); inset-inline-start: var(--space-4); inline-size: 20px; block-size: 20px; accent-color: var(--accent); z-index: 1; }
.library__card.is-imported .library__tile { background: var(--surface-inset); }
.library__title { font-weight: var(--weight-medium); overflow-wrap: anywhere; }
.library__desc { color: var(--fg-muted); font-size: var(--text-secondary); overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.library__meta { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-3); justify-content: space-between; margin-block-start: auto; color: var(--fg-muted); font-size: var(--text-secondary); font-variant-numeric: tabular-nums; }
.library__foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-2); padding: var(--space-4) var(--space-6); border-block-start: 1px solid var(--hairline); }
.library__count { margin-inline-end: auto; color: var(--fg-muted); font-size: var(--text-secondary); }
@media (prefers-reduced-motion: no-preference) {
  .library__tile { transition: border-color var(--motion-150) var(--ease-out), background-color var(--motion-150) var(--ease-out); }
}
@media (max-width: 480px) {
  .library__head, .library__body, .library__foot { padding-inline: var(--space-4); }
  .library__foot .btn { flex: 1 1 100%; }
}


/* --- Background synchronisation, loading and progress (IDEA-010 Batch 0) ------------------------------------------------
   One vocabulary for every page that polls (public/js/poll.js drives data-sync-state; partials/sync.njk holds the markup).
   A routine poll changes an icon and nothing else: no spinner over content, no dimming, no layout shift (the line reserves its
   height). Only a meaningful state changes the sentence, and only those are announced. Motion: the one rotation is switched off
   by the global prefers-reduced-motion rule above (animation-iteration-count: 1 at 0.01ms), so it is a still icon there. */
.sync {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
  min-block-size: var(--space-8);
  margin-block-end: var(--space-2);
  font-size: var(--text-meta);
  color: var(--fg-muted);
}
.sync__i { display: none; flex: none; line-height: 0; }
.sync__i svg { inline-size: 14px; block-size: 14px; }
.sync[data-sync-state="syncing"] .sync__i--syncing,
.sync[data-sync-state="reconnecting"] .sync__i--syncing,
.sync[data-sync-state="done"] .sync__i--done,
.sync[data-sync-state="offline"] .sync__i--offline,
.sync[data-sync-state="degraded"] .sync__i--alert,
.sync[data-sync-state="failed"] .sync__i--alert,
.sync[data-sync-state="forbidden"] .sync__i--lock,
.sync[data-sync-state="signed-out"] .sync__i--lock { display: inline-flex; }
.sync[data-sync-state="done"] { color: var(--positive); }
.sync[data-sync-state="offline"],
.sync[data-sync-state="reconnecting"],
.sync[data-sync-state="degraded"],
.sync[data-sync-state="failed"] { color: var(--notice); }
.sync[data-sync-state="forbidden"],
.sync[data-sync-state="signed-out"] { color: var(--negative); }
.sync__time { font-variant-numeric: tabular-nums; }
.sync [hidden] { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .sync[data-sync-state="syncing"] .sync__i--syncing svg,
  .sync[data-sync-state="reconnecting"] .sync__i--syncing svg { animation: sync-spin calc(var(--motion-300) * 4) linear infinite; }
  @keyframes sync-spin { to { transform: rotate(360deg); } }
}
[dir="rtl"] .sync__i--syncing svg { scale: -1 1; }   /* the arrows turn the same way the text reads */

/* Initial loading, only for a fragment that is genuinely not there yet: bars where the content will be, never a full-page spinner. */
.skeleton { display: grid; gap: var(--space-2); }
.skeleton__bar { block-size: var(--space-4); border-radius: var(--radius-sm); background: var(--surface-inset); }
.skeleton__bar:nth-child(2) { inline-size: 80%; }
.skeleton__bar:nth-child(3) { inline-size: 55%; }
@media (prefers-reduced-motion: no-preference) {
  .skeleton__bar { animation: reward-pulse calc(var(--motion-300) * 5) ease-in-out infinite; }
}

/* A real upload: a native progress element (the same look as the storage meters) and a sentence. */
.upload { display: grid; gap: var(--space-2); max-inline-size: var(--prose); }
.upload[hidden] { display: none; }
.upload__text { margin: 0; font-size: var(--text-secondary); color: var(--fg-muted); font-variant-numeric: tabular-nums; }

/* A live pending counter on an existing navigation entry or button (IDEA-010). Tokens only; hidden until filled. */
.count-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 1.25rem;
  padding-inline: var(--space-2);
  margin-inline-start: var(--space-2);
  border-radius: 999px;
  background: var(--accent-wash);
  color: var(--accent-text);
  font-size: var(--text-meta);
  font-variant-numeric: tabular-nums;
  line-height: 1.25rem;
}
.count-badge[hidden] { display: none; }
.btn-primary .count-badge { background: var(--on-accent); color: var(--accent); }

/* A value that just changed under the chatter's eyes (IDEA-010 B1): a soft wash that fades. No motion beyond the fade, and none at all
   under reduced motion (the text still changes; screen readers get the sentence from the live regions, not from this). */
@media (prefers-reduced-motion: no-preference) {
  .is-changed { animation: rw-changed calc(var(--motion-300) * 6) ease-out; }
  @keyframes rw-changed { from { background: var(--accent-wash); } to { background: transparent; } }
}

/* ==========================================================================
   /me: the profile header, tab counts, numbered pager, stacked pictures list
   ========================================================================== */
.profile-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
  margin-block-end: var(--space-8);
  padding-block-end: var(--space-6);
  border-block-end: 1px solid var(--hairline);
}
.profile-head__who { gap: var(--space-4); min-inline-size: 0; }
.profile-head__who h1 { margin: 0; overflow-wrap: anywhere; }
.profile-head__who .page-head__eyebrow { margin-block-end: 0; }
.profile-head__action { margin: 0; }
.profile-stats { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-8); margin: 0; }
.profile-stats > div { display: grid; gap: var(--space-1); }
.profile-stats dt { font-size: var(--text-meta); line-height: var(--leading-meta); color: var(--fg-faint); }
.profile-stats dd { margin: 0; font-size: var(--text-h3); font-weight: var(--weight-semibold); }
.profile-stats__note { margin: var(--space-2) 0 0; }
.profile-links { display: flex; flex-wrap: wrap; gap: var(--space-4); margin-block-end: var(--space-6); }
.me-intro { margin-block-end: var(--space-6); }

.segmented__count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 1.5rem;
  margin-inline-start: var(--space-2);
  padding-inline: var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--accent-wash);
  color: var(--accent-text);
  font-size: var(--text-meta);
  line-height: var(--leading-meta);
}

.pager--numbered { margin-block-start: var(--space-6); flex-wrap: wrap; gap: var(--space-3) var(--space-6); }
/* A section after a pager (the pictures that did not go through) keeps the distance a section keeps after a table. */
.pager + .section { margin-block-start: var(--space-12); }
.pager__pages { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); list-style: none; margin: 0; padding: 0; }
.pager__page, .pager__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: var(--hit);
  min-block-size: var(--hit);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--fg);
  font-size: var(--text-secondary);
  text-decoration: none;
}
.pager__arrow { border-color: var(--border); }
a.pager__page:hover, a.pager__arrow:hover { background: var(--surface-l2); text-decoration: none; }
.pager__page[aria-current="page"] { border-color: var(--border-control); background: var(--accent-wash); color: var(--accent-text); font-weight: var(--weight-medium); }
.pager__gap { min-inline-size: var(--hit); text-align: center; color: var(--fg-faint); }
[dir="rtl"] .pager__arrow svg { transform: scaleX(-1); }

/* A phone: each picture becomes a short card of its own instead of a row that scrolls sideways. */
@media (max-width: 767.98px) {
  .table-cards { min-inline-size: 0; inline-size: 100%; }
  .table-cards, .table-cards tbody, .table-cards tr, .table-cards td { display: block; }
  .table-cards thead { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); }
  .table-cards tr { display: grid; gap: var(--space-2); padding: var(--space-4); border-block-end: 1px solid var(--hairline); }
  .table-cards tr:last-child { border-block-end: 0; }
  .table-cards td { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-1) var(--space-3); padding: 0; border: 0; }
  .table-cards td::before { content: attr(data-label); font-size: var(--text-meta); color: var(--fg-faint); }
  .table-cards td[data-label=""]::before { display: none; }
  .table-cards td[data-label=""] { display: grid; justify-content: stretch; }
  .table-cards .cell-why { max-inline-size: none; }
}

/* --- Settings, Batch 3 ---------------------------------------------------
   Grouped section list, the mobile section sheet, panels round the controls that act on their own, and the docked save bar. Nothing
   here changes what a control does: the markup, names and form targets are the ones the page already had.
   -------------------------------------------------------------------------- */
.settings-layout { padding-block-end: 8rem; }
@media (max-width: 767.98px) { .settings-layout { padding-block-end: 13rem; } }
/* The page already keeps anchors clear of the header (html scroll-padding); only the phone's sticky Sections button needs more. */
@media (max-width: 767.98px) { .settings-body .section { scroll-margin-block-start: var(--space-16); } }
.settings-nav a { justify-content: space-between; gap: var(--space-2); }
.settings-nav a[aria-current="location"] { color: var(--fg); background: var(--surface-l1); }
.settings-nav__group { margin-block-start: var(--space-2); padding-block-start: var(--space-2); border-block-start: 1px solid var(--hairline); }
.settings-nav__danger a { color: var(--negative); }
.settings-nav__mark { flex: none; inline-size: var(--space-2); block-size: var(--space-2); border-radius: 50%; background: var(--notice); }
.settings-nav__mark[hidden] { display: none; }

.settings-sections { display: none; }
@media (max-width: 767.98px) {
  .settings-layout.is-enhanced > .settings-nav { display: none; }
  .settings-layout.is-enhanced > .settings-sections:not([hidden]) {
    display: block;
    position: sticky;
    inset-block-start: var(--nav-height);
    z-index: var(--z-sticky);
    padding-block: var(--space-2);
    background: var(--surface-l0);
  }
  .settings-sections .btn { inline-size: 100%; }
}
dialog.sheet {
  position: fixed;
  inset-block: auto 0;
  inset-inline: 0;
  margin: 0;
  inline-size: 100%;
  max-inline-size: none;
  max-block-size: 80vh;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-start-start-radius: var(--radius-lg);
  border-start-end-radius: var(--radius-lg);
  background: var(--surface-l3);
  color: var(--fg);
}
dialog.sheet:not([open]) { display: none; }
dialog.sheet::backdrop { background: var(--scrim); }
.sheet__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding: var(--space-4); border-block-end: 1px solid var(--hairline); }
.sheet__title { font-size: var(--text-h4); margin: 0; }
.sheet__body { padding: var(--space-2) var(--space-4) var(--space-6); overflow-y: auto; max-block-size: calc(80vh - 5rem); }
.sheet__body ul { list-style: none; margin: 0; padding: 0; }
.sheet__body a { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); min-block-size: var(--hit); padding-inline: var(--space-3); border-radius: var(--radius-sm); color: var(--fg); text-decoration: none; }
.sheet__body a[aria-current="location"] { background: var(--surface-l1); }
.sheet__body li.settings-nav__group { margin-block-start: var(--space-2); }
@media (min-width: 768px) { dialog.sheet { display: none; } }

.action-panel {
  display: grid;
  gap: var(--space-3);
  max-inline-size: var(--prose);
  margin-block: var(--space-4);
  padding: var(--space-4);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
  background: var(--surface-l1);
}
.action-panel > * { margin: 0; }
.action-panel__label { font-size: var(--text-meta); color: var(--fg-faint); }
.action-panel__title { font-size: var(--text-h4); }
.settings-body .settings-part + .settings-part { margin-block-start: var(--space-8); }

.field.is-dirty { position: relative; }
.field.is-dirty::before { content: ""; position: absolute; inset-block: 0; inset-inline-start: calc(-1 * var(--space-3)); inline-size: 2px; border-radius: 1px; background: var(--notice); }
.field-unsaved { margin-inline-start: var(--space-2); font-size: var(--text-meta); font-weight: var(--weight-semibold); color: var(--notice); }
.section__head h2 .badge { margin-inline-start: var(--space-3); vertical-align: middle; }

.save-bar {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: var(--z-sticky);
  background: var(--surface-l2);
  border-block-start: 1px solid var(--border-strong);
}
.save-bar__inner {
  max-inline-size: var(--vp-wide);
  margin-inline: auto;
  padding: var(--space-3) var(--space-4);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}
.save-bar__status { flex: 1 1 14rem; min-inline-size: 0; margin: 0; overflow-wrap: anywhere; color: var(--fg-muted); font-size: var(--text-secondary); }
.save-bar__actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.save-bar[data-state="dirty"] { border-block-start: 2px solid var(--notice); }
.save-bar[data-state="dirty"] .save-bar__status { color: var(--fg); font-weight: var(--weight-semibold); }
.save-bar[data-state="failed"] { border-block-start: 2px solid var(--negative); }
.save-bar[data-state="failed"] .save-bar__status { color: var(--negative); }
.save-bar[data-state="saving"] .save-bar__status { color: var(--fg); }
@media (max-width: 767.98px) {
  .save-bar__actions { inline-size: 100%; }
  .save-bar__actions > .btn { flex: 1 1 auto; }
}
.settings-carried { margin-block-end: var(--space-4); }

/* Settings uses the full content column, as board 35 does: the prose cap that suits a paragraph on its own left the fields, panels and
   notes in a narrow strip with the right half of the page empty. */
.settings-body .section__note,
.settings-body .hint,
.settings-body .field-pair,
.settings-body .action-panel,
.settings-body .state-list,
.settings-body .steps-list { max-inline-size: none; }
.settings-body .field-pair { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.settings-body .field { max-inline-size: none; }
.settings-body .field > .input[type="number"] { max-inline-size: 20rem; }

/* On and off read differently at a glance: an enabled panel is solid with a positive edge, a disabled one stays dashed. The badge inside
   still says it in words. */
.action-panel.is-on { border-style: solid; border-color: var(--positive); background: var(--positive-wash); }
.settings-link-row { margin-block: var(--space-4); }

/* --- Contribution pages, Batch 4 ------------------------------------------
   The channel picker (a list of four to a page) and the picture form (the form beside a "what happens next" panel). Layout and states only:
   every rule about who may contribute is on the server.
   -------------------------------------------------------------------------- */
.contribute .page-head { margin-block-end: var(--space-8); }
.contribute--narrow { max-inline-size: 560px; margin-inline: auto; }
.contribute--narrow .page-head { text-align: center; }
.contribute--narrow .page-head__lead { margin-inline: auto; }

.channel-find { display: grid; gap: var(--space-2); margin-block-end: var(--space-6); }
.channel-find__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }
.channel-find__box { position: relative; flex: 0 1 26rem; min-inline-size: 14rem; }
.channel-find__box > svg { position: absolute; inset-inline-start: var(--space-3); inset-block-start: 50%; translate: 0 -50%; color: var(--fg-muted); pointer-events: none; }
.channel-find__box .input { padding-inline-start: var(--space-8); }
.channel-find__count { margin: 0; margin-inline-start: auto; }

.channel-rows { list-style: none; display: grid; gap: var(--space-3); margin: 0 0 var(--space-6); padding: 0; }
.channel-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-4);
  min-block-size: 5rem;
  padding: var(--space-4) var(--space-6);
  background: var(--surface-l1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.channel-row__name { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin: 0; font-weight: var(--weight-semibold); }
.channel-row__slug { font-size: var(--text-h4); overflow-wrap: anywhere; }
.channel-row__note { margin: var(--space-1) 0 0; color: var(--fg-muted); font-size: var(--text-secondary); }
.channel-row__action .btn { white-space: nowrap; }
.btn.is-disabled { background: transparent; border-color: var(--hairline); color: var(--fg-muted); cursor: not-allowed; pointer-events: none; }
@media (max-width: 767.98px) {
  .channel-row { grid-template-columns: auto minmax(0, 1fr); padding: var(--space-4); }
  .channel-row__action { grid-column: 1 / -1; }
  .channel-row__action .btn { inline-size: 100%; }
  .channel-find__count { margin-inline-start: 0; flex-basis: 100%; }
  .channel-find__box { flex-basis: 100%; }
}

.crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-block-end: var(--space-6); color: var(--fg-muted); font-size: var(--text-secondary); }
.crumbs a { color: inherit; }
.crumbs__sep { display: inline-flex; }
.crumbs__sep svg { inline-size: 1em; block-size: 1em; }
[dir="rtl"] .crumbs__sep, [dir="rtl"] .contribute__link svg { transform: scaleX(-1); }
.contribute__grid { display: grid; gap: var(--space-8); }
@media (min-width: 992px) { .contribute__grid { grid-template-columns: minmax(0, 40rem) minmax(0, 25.5rem); justify-content: start; gap: var(--space-8) var(--space-12); align-items: start; } }
.contribute__main { min-inline-size: 0; }
.contribute--form .page-head { margin-block-end: var(--space-6); }
.contribute__after { align-items: center; gap: var(--space-4); }
.contribute__link { display: inline-flex; align-items: center; gap: var(--space-1); color: var(--accent-text); }
.contribute__link svg { inline-size: 1em; block-size: 1em; }

.channel-pick {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: var(--space-3) var(--space-4);
  margin-block-end: var(--space-8);
  padding: var(--space-4) var(--space-6);
  background: var(--surface-l1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.channel-pick__label { margin: 0; color: var(--fg-muted); font-size: var(--text-meta); }
.channel-pick__name { margin: 0; font-size: var(--text-h3); font-weight: var(--weight-semibold); overflow-wrap: anywhere; }
.channel-pick__change { grid-column: 1 / -1; justify-self: start; }
@media (max-width: 767.98px) { .channel-pick__change { justify-self: stretch; } }

.dropzone {
  position: relative;
  display: grid;
  justify-items: center;
  gap: var(--space-2);
  padding: var(--space-8) var(--space-4);
  text-align: center;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
}
.dropzone:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.dropzone.is-over { border-color: var(--accent); background: var(--accent-wash); }
/* The real file input covers the zone: a click anywhere opens the picker and a dropped file lands in the same input. */
.dropzone__input { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; opacity: 0; cursor: pointer; }
.dropzone__icon { display: grid; place-items: center; inline-size: 3.5rem; block-size: 3.5rem; border-radius: var(--radius-md); background: var(--surface-l2); color: var(--fg-muted); }
.dropzone.has-file .dropzone__icon { display: none; }
.dropzone__title { font-weight: var(--weight-semibold); overflow-wrap: anywhere; }
.dropzone__or { color: var(--fg-muted); font-size: var(--text-secondary); }
.dropzone .image-preview { max-block-size: 14rem; max-inline-size: 100%; }
.contribute__optional { margin-block-end: var(--space-6); }
.contribute__review { margin-block-end: var(--space-4); }

.contribute__aside .panel__body h2 { font-size: var(--text-h4); }
.next-steps { list-style: none; display: grid; gap: var(--space-4); margin: var(--space-4) 0 0; padding: 0; }
.next-steps li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--space-3); align-items: start; }
.next-steps__n { display: grid; place-items: center; inline-size: 2rem; block-size: 2rem; border: 1px solid var(--accent); border-radius: 50%; color: var(--accent-text); font-weight: var(--weight-semibold); }
.flash[hidden] { display: none; }
.channel-find__box .input { padding-inline-start: 2.75rem; }
.contribute__optional { min-inline-size: 0; }
@media (max-width: 767.98px) {
  .contribute .form-actions { flex-direction: column-reverse; align-items: stretch; }
  .contribute .form-actions .btn { inline-size: 100%; }
}

/* The picker's pager: numbered on wide screens, Previous / Page X of Y / Next on phones. */
.contribute .pager--simple { display: none; }
.contribute .pager--simple .btn { min-block-size: var(--hit); }
[dir="rtl"] .contribute .pager--simple .btn svg { transform: scaleX(-1); }
@media (max-width: 767.98px) {
  .contribute .pager-wide { display: none; }
  .contribute .pager--simple { display: flex; margin-block-start: var(--space-6); }
}
.contribute__after { margin-block: var(--space-4) var(--space-6); }

/* --- Chatter Rewards, Batch 5 ----------------------------------------------
   The hub (a grid of channel cards), a channel's two balance cards, and the information chips on a catalogue card. Layout and states only.
   -------------------------------------------------------------------------- */
.rw-head .crumbs { margin-block-end: var(--space-4); }
.rw-head__who { align-items: center; gap: var(--space-4); }
.rw-head__who h1 { margin: 0; overflow-wrap: anywhere; }
.rw-head__who .page-head__lead { margin-block: var(--space-1) 0; }

.voice-entry {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--space-4);
  margin-block-end: var(--space-6);
  padding: var(--space-4) var(--space-6);
  background: var(--surface-l1);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.voice-entry__icon, .balance-card__icon { display: grid; place-items: center; inline-size: 2.5rem; block-size: 2.5rem; border-radius: var(--radius-md); background: var(--surface-l2); color: var(--accent-text); }
.voice-entry__text h2 { font-size: var(--text-h4); margin: 0; }
.voice-entry__text p { margin: var(--space-1) 0 0; color: var(--fg-muted); font-size: var(--text-secondary); }
.btn svg { flex: none; }
@media (max-width: 767.98px) {
  .voice-entry { grid-template-columns: auto minmax(0, 1fr); padding: var(--space-4); }
  .voice-entry > .btn { grid-column: 1 / -1; }
}

.channel-cards { list-style: none; display: grid; gap: var(--space-4); margin: 0 0 var(--space-6); padding: 0; grid-template-columns: 1fr; }
@media (min-width: 640px) { .channel-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 992px) { .channel-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.channel-tile { display: flex; flex-direction: column; gap: var(--space-1); min-inline-size: 0; padding: var(--space-6); background: var(--surface-l1); border: 1px solid var(--border); border-radius: var(--radius-md); }
.channel-tile__head { margin-block-end: var(--space-3); }
.channel-tile__head .identity__name { font-weight: var(--weight-semibold); font-size: var(--text-h4); overflow-wrap: anywhere; }
.channel-tile__label { margin: 0; color: var(--fg-muted); font-size: var(--text-meta); }
.channel-tile__n { margin: 0; font-size: var(--text-h2); font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; }
.channel-tile__items { margin: 0 0 var(--space-4); color: var(--fg-muted); font-size: var(--text-secondary); padding-block-end: var(--space-4); border-block-end: 1px solid var(--hairline); }
.channel-tile__open { inline-size: 100%; margin-block-start: auto; }
[dir="rtl"] .channel-tile__open svg, [dir="rtl"] .rw-head .crumbs__sep { transform: scaleX(-1); }

.balance-cards { display: grid; gap: var(--space-4); margin-block-end: var(--space-4); grid-template-columns: 1fr; }
@media (min-width: 768px) {
  .balance-cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: stretch;
  }
}
.balance-card { display: grid; gap: var(--space-3); min-inline-size: 0; padding: var(--space-6); background: var(--surface-l1); border: 1px solid var(--border); border-radius: var(--radius-md); }
.balance-card > * { margin: 0; }
.balance-card__head { display: flex; align-items: center; gap: var(--space-3); }
.balance-card__title { flex: 1; min-inline-size: 0; font-size: var(--text-secondary); font-weight: var(--weight-medium); color: var(--fg-muted); overflow-wrap: anywhere; }
.balance-card__n { font-size: var(--text-h1, var(--text-h2)); font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; line-height: 1.1; }
.balance-card__word { font-size: var(--text-h2); font-weight: var(--weight-semibold); color: var(--fg-muted); }
.balance-card__note { color: var(--fg-muted); font-size: var(--text-secondary); }
.balance-card__fine { color: var(--fg-muted); font-size: var(--text-meta); text-align: center; }
.balance-card__open { inline-size: 100%; }
.balance-card__skeleton { block-size: 2.25rem; inline-size: 7rem; border-radius: var(--radius-sm); background: var(--surface-l2); }
[data-voice-state] { display: grid; gap: var(--space-3); }
[data-voice-state] > * { margin: 0; }
[data-voice-state][hidden] { display: none; }
.flash-warn { border-inline-start-color: var(--notice); }
.flash-warn svg { color: var(--notice); }

.chips { list-style: none; display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0; padding: 0; }
.chip { display: inline-flex; align-items: center; gap: var(--space-1); min-block-size: 1.75rem; padding: 0 var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--fg); font-size: var(--text-meta); font-variant-numeric: tabular-nums; }
.chip svg { inline-size: 0.875rem; block-size: 0.875rem; }
.chip--unknown { border-style: dashed; color: var(--fg-muted); }

/* Catalogue cards: four to a row on wide screens, and the price, state and Redeem button sit at the foot of every card so a row lines up. */
.reward-grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr)); }
.reward-card .reward-card__meta { margin-block-start: auto; }
.reward-card [data-rw-form] .btn { inline-size: 100%; white-space: normal; text-wrap: balance; }

/* --- Media previews, Batch 6 ---------------------------------------------------
   The live element is laid over the thumbnail, so starting and stopping a preview changes nothing about the card's size. The whole
   thumbnail is the control (one large target for a finger), with a small play or stop mark in its corner. */
.reward-thumb { position: relative; }
.reward-thumb__toggle { position: absolute; inset: 0; z-index: 2; display: flex; align-items: flex-end; justify-content: flex-start; padding: var(--space-2); border: 0; border-radius: inherit; background: transparent; color: var(--fg); cursor: pointer; }
.reward-thumb__icon { display: grid; place-items: center; inline-size: 2rem; block-size: 2rem; border-radius: 50%; background: var(--scrim); border: 1px solid var(--border-strong); }
.reward-thumb__icon svg { inline-size: 0.875rem; block-size: 0.875rem; }
.reward-thumb--small .reward-thumb__icon { inline-size: 1.5rem; block-size: 1.5rem; }
.reward-thumb--small .reward-thumb__icon svg { inline-size: 0.625rem; block-size: 0.625rem; }
.reward-thumb__live { position: absolute; inset: 0; z-index: 1; inline-size: 100%; block-size: 100%; object-fit: cover; display: block; background: var(--surface-l2); }
.reward-thumb__live[hidden] { display: none; }
.reward-thumb.is-previewing { outline: 2px solid var(--accent); outline-offset: -2px; }
.reward-thumb.is-previewing .reward-thumb__icon { background: var(--accent); color: var(--on-accent); }
.reward-thumb.is-failed .reward-thumb__icon { border-style: dashed; opacity: 0.6; }
.reward-thumb__toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* --- Streamer Rewards catalogue, Batch 7 (boards 28 and 34) ----------------------------------------------------------------------
   Fixed columns that fit the content width without scrolling: the media chips fold under the title, the price and cooldown are narrow, and
   Edit, Enable or Disable and Remove stay on every row. On phones each row becomes a card (board 34). Layout only. */
.reward-table { inline-size: 100%; table-layout: fixed; border-collapse: collapse; }
.reward-table th, .reward-table td { vertical-align: middle; padding: var(--space-3) var(--space-3); text-align: start; }
.reward-table th.cell-pick, .reward-table td.cell-pick { inline-size: 3.25rem; }
.reward-table th.cell-thumb, .reward-table td.cell-thumb { inline-size: 7.5rem; }
.reward-table th.cell-num, .reward-table td.cell-num { inline-size: 5.5rem; font-variant-numeric: tabular-nums; }
.reward-table th:nth-child(6), .reward-table td:nth-child(6) { inline-size: 7rem; }
.reward-table th:nth-child(7), .reward-table td:nth-child(7) { inline-size: 24rem; }
.reward-table tbody tr:has(input[data-bulk-item]:checked) { background: var(--accent-wash); box-shadow: inset 3px 0 0 var(--accent); }
[dir="rtl"] .reward-table tbody tr:has(input[data-bulk-item]:checked) { box-shadow: inset -3px 0 0 var(--accent); }
.reward-row__title { display: block; font-weight: var(--weight-medium); overflow-wrap: anywhere; }
.reward-row__type { display: block; margin-block-start: var(--space-1); }
.reward-table tbody tr .chips { margin-block-start: var(--space-2); }
.cell-actions { white-space: normal; }
.reward-table .cell-actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-2); }
.reward-table .cell-actions form { margin: 0; }
.cell-actions__move { display: inline-flex; gap: 0; }
.btn-danger-quiet { background: transparent; color: var(--negative); border: 1px solid var(--negative); }
.btn-danger-quiet:hover { background: var(--negative-wash); }
.pick__text { color: var(--fg-muted); font-size: var(--text-secondary); }

[data-bulk-form] > .bulk-bar { position: sticky; inset-block-end: 0; z-index: var(--z-sticky); margin-block-start: var(--space-3); padding: var(--space-3) var(--space-4); background: var(--surface-l2); border: 1px solid var(--border); border-radius: var(--radius-md); }
[data-bulk-form] > .bulk-bar.is-active { border-color: var(--accent); background: var(--accent-wash); }

@media (min-width: 768px) { .reward-table .pick__text { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } }
@media (max-width: 767.98px) {
  .reward-table thead th:not(.cell-pick) { display: none; }
  .reward-table, .reward-table tbody, .reward-table thead, .reward-table thead tr { display: block; }
  .reward-table thead th.cell-pick { display: block; inline-size: auto; padding: var(--space-3) var(--space-4); }
  .reward-table tbody { display: grid; gap: var(--space-3); padding: var(--space-3); }
  .reward-table tbody tr { display: grid; grid-template-columns: auto 5.5rem minmax(0, 1fr); gap: var(--space-2) var(--space-3); align-items: start; padding: var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface-l1); }
  .reward-table td { display: block; inline-size: auto !important; padding: 0; }
  .reward-table td.cell-pick { grid-column: 1; grid-row: 1; align-self: center; }
  .reward-table td.cell-thumb { grid-column: 2; grid-row: 1; }
  .reward-table td.cell-title { grid-column: 3; grid-row: 1; }
  .reward-table td.cell-num, .reward-table td[data-md-cell="status"] { grid-column: 1 / -1; display: flex; justify-content: space-between; gap: var(--space-3); }
  .reward-table td[data-label]::before { content: attr(data-label); color: var(--fg-muted); font-size: var(--text-meta); }
  .reward-table td.cell-actions { grid-column: 1 / -1; justify-content: flex-start; }
  .reward-table td.cell-actions .btn { min-block-size: var(--hit); }
  [data-bulk-form] > .bulk-bar { margin-inline: var(--space-2); }
}
/* The foot bar sits over rows as the page scrolls, so it must be opaque; the highlight is laid on top of an opaque surface. */
[data-bulk-form] > .bulk-bar { background: var(--surface-l2); display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-2) var(--space-4); }
[data-bulk-form] > .bulk-bar.is-active { background: var(--surface-l2); box-shadow: inset 0 0 0 999px var(--accent-wash); }
[data-bulk-form] > .bulk-bar .row { flex-wrap: wrap; }
[data-bulk-clear][hidden] { display: none; }

/* In the search row the toolbar already spaces itself; the details element's own bottom margin made its summary sit above the Apply button. */
.list-toolbar > details.disclosure.filters:not([open]) {
  margin-block-end: 0;
}

/* The /rewards search row. Measured: the shared `.filters` rule gives the details element a bottom margin of 16px, and a row aligned to its
   bottom edge honours margins, so shut it left Filters 16px above Apply and the Search box, and open it left the Status dropdown 16px above the
   Search input. The selectors above (`.list-toolbar > details.disclosure.filters`) belong to the other toolbar's markup and never matched this one.
   Margin and panel padding are removed here, in this component only, so the three controls and the dropdowns share the row's bottom edge; the
   space above the row keeps the quota note from crowding the Filters control. */
.rewards-toolbar { margin-block-start: var(--space-6); }
.rewards-toolbar > .filters { margin-block-end: 0; }
.rewards-toolbar > .filters > .filters__panel { padding-block-end: 0; }
/* On a phone the search box takes its own row, so Filters and Apply stay side by side on the row beneath it. */
@media (max-width: 767.98px) { .toolbar:has(> .filters) > .field { flex: 1 1 100%; max-inline-size: none; } }

/* --- Streamer dashboard, Batch 8 (boards 24 and 31) ---------------------------------------------------------------------------------
   Two overlay panels, two channel-management cards, ten rounds to a page, a searchable chatter list. Layout only. */
.dash-panels { display: grid; gap: var(--space-4); grid-template-columns: 1fr; }
@media (min-width: 768px) { .dash-panels { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.dash-card { display: grid; align-content: start; gap: var(--space-3); min-inline-size: 0; padding: var(--space-6); background: var(--surface-l1); border: 1px solid var(--border); border-radius: var(--radius-md); }
.dash-card > * { margin: 0; }
.dash-card__head { display: flex; align-items: flex-start; gap: var(--space-4); }
.dash-card__icon { flex: none; display: grid; place-items: center; inline-size: 2.5rem; block-size: 2.5rem; border-radius: var(--radius-md); background: var(--surface-l2); color: var(--accent-text); }
.dash-card__title { font-size: var(--text-h4); margin: 0; overflow-wrap: anywhere; }
.dash-card__title .badge { margin-inline-start: var(--space-2); vertical-align: middle; }
.dash-card__note { margin: var(--space-1) 0 0; color: var(--fg-muted); font-size: var(--text-secondary); }
.dash-card .input-row { margin: 0; }
.dash-card .hint { margin-block-start: 0; }
.dash-more { margin-block-start: var(--space-3); }
.dash-more a { display: inline-flex; align-items: center; gap: var(--space-1); color: var(--accent-text); }
[dir="rtl"] .dash-more svg, [dir="rtl"] .dash-card .btn svg:last-child:not(:first-child) { transform: scaleX(-1); }
.chatter-search { margin-block-end: var(--space-4); }
.chatter-search .label { display: block; margin-block-end: var(--space-1); }
[data-dash-region="rounds"] .pager, [data-rr-region="chatters"] .pager { margin-block-end: var(--space-2); }

/* --- Ban form: chatter autocomplete (/safety/bans/new) --------------------
   One combobox scoped to the owner's channel. The panel is in flow, not floating, so it never covers the fields below and needs no z-index.
   -------------------------------------------------------------------------- */
.ban-layout { display: grid; gap: var(--space-8); grid-template-columns: minmax(0, 1fr); align-items: start; }
@media (min-width: 1024px) { .ban-layout { grid-template-columns: minmax(0, 560px) minmax(0, 320px); justify-content: center; } }
.ban-layout .page-head { margin-block-end: var(--space-6); }
.ban-channel { padding: var(--space-3) var(--space-4); margin-block-end: var(--space-6); background: var(--surface-l1); border: 1px solid var(--border); border-radius: var(--radius-md); inline-size: 100%; gap: var(--space-3); }
.ban-channel__label { display: block; }
.ban-help__title { font-size: var(--text-body); margin-block-end: var(--space-3); }
.ban-help__list { padding-inline-start: var(--space-4); color: var(--fg-muted); font-size: var(--text-secondary); display: grid; gap: var(--space-2); }
.combo__box { position: relative; }
.combo__icon { position: absolute; inset-inline-start: var(--space-3); inset-block: 0; display: grid; place-items: center; color: var(--fg-faint); pointer-events: none; }
.combo__icon svg { inline-size: 16px; block-size: 16px; }
.combo__input { padding-inline-start: calc(var(--space-3) + 16px + var(--space-2)); }
.combo__panel { margin-block-start: var(--space-2); background: var(--surface-l1); border: 1px solid var(--border); border-radius: var(--radius-md); box-shadow: var(--shadow-l2); overflow: hidden; }
.combo__head, .combo__foot { margin: 0; padding: var(--space-2) var(--space-4); font-size: var(--text-meta); line-height: var(--leading-meta); color: var(--fg-faint); }
.combo__foot { border-block-start: 1px solid var(--hairline); }
.combo__list { list-style: none; margin: 0; padding: var(--space-1); }
.combo__list:empty { display: none; }
.combo__option { display: flex; align-items: center; gap: var(--space-3); min-block-size: var(--hit); padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); cursor: pointer; }
.combo__option:hover, .combo__option[aria-selected="true"] { background: var(--surface-l2); }
.combo__option[aria-selected="true"] { outline: 2px solid var(--accent); outline-offset: -2px; }
.combo__name { flex: 1; min-inline-size: 0; overflow-wrap: anywhere; }
.combo__name mark { background: transparent; color: var(--accent-text); font-weight: var(--weight-semibold); }
.combo__count { flex: none; color: var(--fg-muted); font-size: var(--text-meta); }
.combo__state { padding: var(--space-3) var(--space-4); text-align: center; color: var(--fg-muted); font-size: var(--text-secondary); }
.combo__state:empty { display: none; }
.combo__state strong { display: block; color: var(--fg); margin-block-end: var(--space-1); overflow-wrap: anywhere; }
.combo__state .skeleton { text-align: start; }
.combo__chosen { display: flex; align-items: center; gap: var(--space-3); min-block-size: var(--hit); padding: var(--space-2) var(--space-3); background: var(--surface-l1); border: 1px solid var(--border); border-radius: var(--radius-md); }
.combo__chosen .identity__name { flex: 1; }
.combo [hidden] { display: none; }

/* --- Streamer /uploads: row actions, dialogs, moderators (Batch 10) ----------
   Scoped to the streamer page's own classes (.review-table, .row-menu, .mod-table, .dialog--sheet); the shared review partial renders
   the same markup as before for /admin/uploads, /admin/images and /moderate.
   -------------------------------------------------------------------------- */
.flash-info { border-inline-start-color: var(--accent); }
.flash-info svg { color: var(--accent-text); }
.uploads-mods-note { align-items: center; flex-wrap: wrap; }
.uploads-mods-note > span { flex: 1 1 16rem; min-inline-size: 0; }
.uploads-mods-note__link { display: inline-flex; align-items: center; gap: var(--space-1); min-block-size: var(--hit); color: var(--accent-text); }
[dir="rtl"] .uploads-mods-note__link svg { transform: scaleX(-1); }
.section__head--row { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: var(--space-3) var(--space-6); }
.section__head--row > div { flex: 1 1 18rem; min-inline-size: 0; }
#chatter-uploads, #moderators { scroll-margin-block-start: var(--space-8); }

.review-table .row-actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-2); }
.review-table .cell-actions { white-space: normal; }
.review-table .cell-actions .btn { min-block-size: var(--hit); }
.review-table .cell-actions .pick { min-block-size: var(--hit); }
.review-table tbody tr:has(input[data-bulk-item]:checked) { background: var(--accent-wash); box-shadow: inset 3px 0 0 var(--accent); }
[dir="rtl"] .review-table tbody tr:has(input[data-bulk-item]:checked) { box-shadow: inset -3px 0 0 var(--accent); }

.row-menu { display: inline-flex; }
.row-menu__panel {
  inline-size: 14rem; padding: var(--space-1);
  background: var(--surface-l2); color: var(--fg); border: 1px solid var(--border-strong); border-radius: var(--radius-md); box-shadow: var(--shadow-l2);
}
.row-menu__panel:popover-open { display: block; }
.no-js .row-menu [data-dialog-open] { display: none; }
.row-menu__panel .menu__item svg { inline-size: 16px; block-size: 16px; flex: none; }
.row-menu__panel .menu__item--danger { color: var(--negative); }
.row-menu__panel .menu__item--danger:hover { background: var(--negative-wash); }
.row-menu__panel form, .row-menu__panel button { margin: 0; }

dialog.dialog--sheet { margin: auto; inline-size: min(480px, calc(100vw - var(--space-8))); max-block-size: calc(100dvh - var(--space-8)); overflow: auto; }
dialog.dialog--sheet .dialog__body .field { max-inline-size: none; }
dialog.dialog--sheet .dialog__body .meta { margin-block-end: var(--space-4); overflow-wrap: anywhere; }
dialog.dialog--sheet .dialog__body h2 { overflow-wrap: anywhere; }
dialog.dialog--sheet .dialog__actions .btn { min-block-size: var(--hit); }
dialog.dialog--sheet .input-row { flex-wrap: wrap; }
dialog.dialog--sheet .input-row .select { flex: 1 1 14rem; min-inline-size: 0; }

.mod-table .cell-actions { white-space: normal; }
.mod-table .cell-actions .btn { min-block-size: var(--hit); }
.mod-table .identity .avatar { background: var(--accent-wash); color: var(--accent-text); font-size: var(--text-meta); font-weight: var(--weight-semibold); }

@media (max-width: 767.98px) {
  .review-table, .review-table tbody, .review-table thead, .review-table thead tr { display: block; }
  .table-scroll .review-table, .table-scroll .mod-table { min-inline-size: 0; inline-size: 100%; }
  .review-table .meta, .review-table .cell-primary, .mod-table .cell-primary { overflow-wrap: anywhere; }
  .review-table thead th:not(.cell-pick) { display: none; }
  .review-table thead th.cell-pick { display: block; inline-size: auto; padding: var(--space-3) var(--space-4); }
  .review-table tbody { display: grid; gap: var(--space-3); padding: var(--space-3); }
  .review-table tbody tr { display: grid; grid-template-columns: auto 5rem minmax(0, 1fr); gap: var(--space-2) var(--space-3); align-items: start; padding: var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface-l1); }
  .review-table td { display: block; inline-size: auto !important; padding: 0; min-inline-size: 0; }
  .review-table td.cell-pick { grid-column: 1; grid-row: 1 / span 3; align-self: start; }
  .review-table td.cell-thumb { grid-column: 2; grid-row: 1 / span 3; }
  .review-table td:nth-child(3), .review-table td:nth-child(4), .review-table td:nth-child(5) { grid-column: 3; }
  .review-table td.cell-actions { grid-column: 1 / -1; }
  .review-table .row-actions { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto; gap: var(--space-2); }
  .review-table .row-actions .pick { grid-column: 1 / -1; }
  .review-table .row-actions .btn:not(.icon-btn) { inline-size: 100%; justify-content: center; }
  .review-table .row-actions > .btn:only-of-type { grid-column: 1 / span 2; }
  .review-table .row-actions .row-menu { grid-column: 3; }
  .review-table .row-actions .row-menu > .icon-btn { inline-size: var(--hit); block-size: var(--hit); border: 1px solid var(--border); border-radius: var(--radius-sm); display: grid; place-items: center; }
  dialog.dialog--sheet { margin: auto 0 0; inline-size: 100%; max-inline-size: none; border-radius: var(--radius-lg) var(--radius-lg) 0 0; border-inline: 0; border-block-end: 0; }
  dialog.dialog--sheet .dialog__actions { flex-direction: column-reverse; align-items: stretch; }
  .mod-table, .mod-table tbody, .mod-table thead, .mod-table thead tr { display: block; }
  .mod-table thead { display: none; }
  .mod-table tbody { display: grid; gap: var(--space-3); padding: var(--space-3); }
  .mod-table tbody tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-1) var(--space-3); align-items: center; padding: var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface-l1); }
  .mod-table td { display: block; padding: 0; min-inline-size: 0; }
  .mod-table td:first-child { grid-column: 1; grid-row: 1; }
  .mod-table td.cell-actions { grid-column: 2; grid-row: 1 / span 4; }
  .mod-table td[data-label] { grid-column: 1; display: flex; gap: var(--space-2); font-size: var(--text-meta); color: var(--fg-muted); }
  .mod-table td[data-label]::before { content: attr(data-label); color: var(--fg-faint); }
}

/* Batch 10 corrections: air between the Moderators text and its table; the More menu where the Popover API is missing (the panel is moved
   to <body> by public/js/uploads-review.js while open, so the table's overflow and containment cannot clip it). */
#moderators .table-frame { margin-block-start: var(--space-6); }
.no-popover .row-menu__panel { display: none; position: fixed; z-index: var(--z-popover); margin: 0; }
.no-popover .row-menu__panel.is-open { display: block; }
/* The shared confirmation dialog: the global `* { margin: 0 }` reset removed the browser's auto margins, which left it in the top-left corner. */
#confirm-dialog { margin: auto; }

/* --- Rounds: list beside the open round (Batch 11) ---------------------------
   Scoped to the rounds page's own classes. Wide: both panes. Narrow: the list (no ?round) or the open round (?round), so the page
   needs no script to switch between them; the selection bar sticks to the bottom of the open round.
   -------------------------------------------------------------------------- */
.rounds-split { display: grid; gap: var(--space-6); grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); align-items: start; }
.rounds-list ul { list-style: none; margin: 0; padding: var(--space-2); display: grid; gap: var(--space-1); }
.rounds-item {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  min-block-size: var(--hit); padding: var(--space-3) var(--space-4);
  border: 1px solid transparent; border-radius: var(--radius-sm); color: inherit; text-decoration: none;
}
.rounds-item:hover { background: var(--surface-l2); }
.rounds-item.is-selected { background: var(--accent-wash); border-color: var(--accent); }
.rounds-item__main { display: grid; gap: var(--space-1); min-inline-size: 0; }
.rounds-item__title { font-weight: var(--weight-semibold); overflow-wrap: anywhere; }
.rounds-item__meta { font-size: var(--text-meta); line-height: var(--leading-meta); color: var(--fg-muted); }
.rounds-item__badges { display: flex; flex-direction: column; align-items: flex-end; gap: var(--space-1); flex: none; }
.rounds-item__badges .badge svg { inline-size: 12px; block-size: 12px; }
.rounds-pager { margin-block-start: var(--space-3); }
.rounds-detail { display: flex; flex-direction: column; gap: var(--space-4); min-inline-size: 0; }
.rounds-detail > * { margin: 0; }
.rounds-detail__head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: var(--space-2) var(--space-4); }
.rounds-detail__head h2 { overflow-wrap: anywhere; }
.rounds-detail__badges { display: inline-flex; flex-wrap: wrap; gap: var(--space-2); }
.rounds-crumb { display: none; align-items: center; gap: var(--space-2); font-size: var(--text-secondary); color: var(--fg-muted); }
.rounds-crumb a { color: var(--fg-muted); display: inline-flex; align-items: center; min-block-size: var(--hit); }
.rounds-crumb svg { inline-size: 14px; block-size: 14px; }
[dir="rtl"] .rounds-crumb svg { transform: scaleX(-1); }
.rounds-select {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: var(--space-3) var(--space-4); background: var(--surface-l1); border: 1px solid var(--border); border-radius: var(--radius-md);
}
.rounds-select.is-active { border-color: var(--accent); background: var(--accent-wash); }
.rounds-select__text { flex: 1 1 14rem; min-inline-size: 0; overflow-wrap: anywhere; font-size: var(--text-secondary); }
.rounds-select .btn { min-block-size: var(--hit); }
.rounds-select .btn:disabled { opacity: 0.55; cursor: not-allowed; }
.rounds-reverse { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.rounds-reverse .hint { margin: 0; }
.attempts-table tr[hidden] { display: none; }
.attempts-table .attempt--pick { cursor: pointer; }
.attempts-table .attempt--pick:hover { background: var(--surface-l2); }
.attempts-table tbody tr:has(input:checked) { background: var(--accent-wash); box-shadow: inset 3px 0 0 var(--accent); }
[dir="rtl"] .attempts-table tbody tr:has(input:checked) { box-shadow: inset -3px 0 0 var(--accent); }
.attempts-table .cell-pick { inline-size: var(--hit); }
.attempts-table .identity { margin-inline-end: var(--space-2); }
.attempts-table .identity .avatar { background: var(--accent-wash); color: var(--accent-text); font-size: var(--text-meta); font-weight: var(--weight-semibold); }
.attempts-pager { margin-block-start: 0; }
.attempts-pager[hidden] { display: none; }
.rounds-empty .panel__body { text-align: center; display: grid; justify-items: center; gap: var(--space-2); padding-block: var(--space-12); }
.rounds-empty__icon { display: grid; place-items: center; inline-size: var(--hit); block-size: var(--hit); border-radius: 50%; background: var(--surface-l2); color: var(--fg-muted); }

@media (max-width: 767.98px) {
  .rounds-split { grid-template-columns: minmax(0, 1fr); }
  .rounds-page:not(.rounds-page--detail) .rounds-detail { display: none; }
  .rounds-page--detail .rounds-list-wrap, .rounds-page--detail .page-head { display: none; }
  .rounds-crumb { display: flex; }
  .rounds-detail .round__facts { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3) var(--space-4); }
  .rounds-select { order: 99; position: sticky; inset-block-end: 0; z-index: var(--z-sticky); background: var(--surface-l2); }
  .rounds-select.is-active { background: var(--surface-l2); box-shadow: inset 0 0 0 999px var(--accent-wash); }
  .rounds-select .btn { inline-size: 100%; justify-content: center; }
  .rounds-fixhint { order: 98; }
  .table-scroll .attempts-table { min-inline-size: 0; inline-size: 100%; }
  .attempts-table, .attempts-table tbody, .attempts-table thead, .attempts-table thead tr { display: block; }
  .attempts-table thead { display: none; }
  .attempts-table tbody { display: grid; gap: var(--space-2); padding: var(--space-3); }
  .attempts-table tbody tr { display: grid; grid-template-columns: var(--hit) minmax(0, 1fr); gap: var(--space-1) var(--space-3); align-items: center; padding: var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface-l1); }
  .attempts-table tbody tr[hidden] { display: none; }
  .attempts-table td { display: block; padding: 0; min-inline-size: 0; grid-column: 2; }
  .attempts-table td.cell-pick { grid-column: 1; grid-row: 1 / span 4; align-self: center; }
  .attempts-table td[data-label]::before { content: attr(data-label) ": "; color: var(--fg-faint); font-size: var(--text-meta); }
  .attempts-table td:nth-child(2)::before { content: none; }
  .attempts-table td:nth-child(3) { font-weight: var(--weight-semibold); }
  .attempts-table td:nth-child(3)::before { content: none; }
  .attempts-table td:nth-child(n+4) { font-size: var(--text-meta); color: var(--fg-muted); }
}

/* Batch 11 corrections: the moderation queue's link to the rounds sits apart from the table above it, and the rounds list and the text
   above it are not touching. Both rules are scoped to those two places. */
.queue-more { margin-block: var(--space-6) var(--space-2); }
.rounds-page [data-rr-region="main"] { margin-block-start: var(--space-6); }
