/* ==========================================================================
   tgindex — design system + public site
   --------------------------------------------------------------------------
   One restrained accent, a cool neutral scale, soft layered elevation and a
   modular 4px spacing / fluid type scale. All values come from design tokens
   below so the whole site (public + admin) stays aligned; dark mode is a
   first-class theme. Public-only treatments are scoped under `body.public`,
   shared tokens/components stay forward-compatible with the admin panel.

   Conventions (see docs/ui-design-system.md):
   - radius scale: xs 8 · sm 10 · md 12 (buttons/inputs) · lg 16 (cards) ·
     xl 20 (large panels) · full (chips/pills/avatars)
   - elevation: xs/sm (resting) · default (raised) · lg (overlays/drawer)
   - accent: --primary + --primary-600 (hover) + --primary-700 (active)
   - motion: --dur/--ease, always disabled under prefers-reduced-motion
   ========================================================================== */

:root {
  color-scheme: light;

  /* neutrals — cool slate */
  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-2: #eef1f6;
  --surface-3: #e5eaf2;
  --text: #0f172a;
  --text-soft: #5a6478;
  --text-faint: #616b7a; /* AA on white and on the tinted surfaces (4.77-5.4) */
  --primary-text: #a34400; /* primary as text on light surfaces (6.21 on white) */
  --border: #e6e9f0;
  --border-strong: #d5dae4;

  /* brand accent — sampled from logo.png: vivid blue -> cyan gradient */
  --primary: #e26000;
  --primary-600: #c65300;
  --primary-700: #a34400;
  --primary-ink: #1f1200; /* dark ink on the orange gradient (AA/AAA); see --primary-text for text-only accents */
  /* entity type accents (type badges); dark values live with the dark tokens */
  --type-channel: #1d4ed8;
  --type-group: #047857;
  --type-robot: #7c3aed;
  --primary-weak: #fdeede;
  --primary-weak-2: #fff6ee;
  --ring: rgba(226, 96, 0, .30);
  --accent-1: #e26000;
  --accent-2: #ff9e1b;

  /* semantic */
  --ok: #16a34a;
  --ok-weak: #e8f6ee;
  --warn: #b45309;
  --warn-weak: #fbf1e2;
  --danger: #dc2626;
  --danger-weak: #fdecec;

  /* elevation */
  --shadow-xs: 0 1px 2px rgba(16, 24, 40, .04);
  --shadow-sm: 0 1px 2px rgba(16, 24, 40, .05), 0 1px 3px rgba(16, 24, 40, .04);
  --shadow: 0 2px 4px rgba(16, 24, 40, .05), 0 12px 28px rgba(16, 24, 40, .08);
  --shadow-lg: 0 18px 48px rgba(16, 24, 40, .16);

  /* radii */
  --radius-xs: 8px;
  --radius-sm: 10px;
  --radius-md: 12px;
  --radius-lg: 16px;
  --radius-full: 999px;
  --radius: var(--radius-lg);      /* legacy alias */

  /* modular spacing scale (4px base) */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 20px; --s6: 28px; --s7: 40px; --s8: 56px;

  /* fluid type scale */
  --fs-300: .82rem; --fs-400: .95rem; --fs-500: 1rem; --fs-600: 1.12rem;
  --fs-700: clamp(1.3rem, 1.1rem + 1vw, 1.6rem);
  --fs-800: clamp(1.55rem, 1.2rem + 1.6vw, 2.1rem);

  /* motion */
  --dur: .18s;
  --ease: cubic-bezier(.2, .8, .2, 1);

  --measure: 68ch;            /* comfortable reading measure */
  --maxw: 1100px;
  --header-h: 60px;
  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Noto Sans SC", sans-serif;
}

/* dark theme tokens (system preference, unless the user forced light) */
@media (prefers-color-scheme: dark) {
  :root:not(.theme-light) {
    color-scheme: dark;
    --bg: #0b0e14;
    --surface: #12161e;
    --surface-2: #1a2029;
    --surface-3: #222a35;
    --text: #e8ecf3;
    --text-soft: #97a1b2;
    --text-faint: #8b95a8; /* AA on dark surfaces (6.01) */
    --primary-text: #ffb763; /* primary as text on dark surfaces (10.5) */
    --border: #232b36;
    --border-strong: #313b48;
    --primary: #ff9422;
    --primary-600: #e8851a; /* hover: darker, matching the light theme semantics */
    --primary-700: #cc7314; /* active */
    --type-channel: #93c5fd;
    --type-group: #6ee7b7;
    --type-robot: #c4b5fd;
    --primary-weak: #331a05;
    --primary-weak-2: #241204;
    --ring: rgba(255, 148, 34, .35);
    --accent-1: #ff9422;
    --accent-2: #ffb74a;
    --ok: #34d399;
    --ok-weak: #102a20;
    --warn: #fbbf24;
    --warn-weak: #2a2110;
    --danger: #f87171;
    --danger-weak: #2a1717;
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4), 0 1px 3px rgba(0, 0, 0, .3);
    --shadow: 0 2px 4px rgba(0, 0, 0, .35), 0 12px 28px rgba(0, 0, 0, .4);
    --shadow-lg: 0 18px 48px rgba(0, 0, 0, .55);
  }
}

/* manual dark theme (toggle) — wins over system preference */
html.theme-dark {
  color-scheme: dark;
  --bg: #0b0e14;
  --surface: #12161e;
  --surface-2: #1a2029;
  --surface-3: #222a35;
  --text: #e8ecf3;
  --text-soft: #97a1b2;
  --text-faint: #8b95a8;
  --primary-text: #ffb763;
  --border: #232b36;
  --border-strong: #313b48;
  --primary: #ff9422;
  --primary-600: #e8851a;
  --primary-700: #cc7314;
  --type-channel: #93c5fd;
  --type-group: #6ee7b7;
  --type-robot: #c4b5fd;
  --primary-weak: #331a05;
  --primary-weak-2: #241204;
  --ring: rgba(255, 148, 34, .35);
  --accent-1: #ff9422;
  --accent-2: #ffb74a;
  --ok: #34d399;
  --ok-weak: #102a20;
  --warn: #fbbf24;
  --warn-weak: #2a2110;
  --danger: #f87171;
  --danger-weak: #2a1717;
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4), 0 1px 3px rgba(0, 0, 0, .3);
  --shadow: 0 2px 4px rgba(0, 0, 0, .35), 0 12px 28px rgba(0, 0, 0, .4);
  --shadow-lg: 0 18px 48px rgba(0, 0, 0, .55);
}

/* ---------- base ---------- */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-feature-settings: "kern" 1, "liga" 1;
  accent-color: var(--primary);
}
::selection { background: var(--primary-weak); color: var(--text); }
a { color: var(--primary-text); text-decoration: none; word-break: break-word; }
a:hover { text-decoration: underline; }
/* anchors that draw their own hover surface (cards, rows, nav items, chips)
   never underline: feedback comes from elevation/border/background instead.
   Plain text links (.see-more-btn, .footer-link) keep the underline. */
.tn-card:hover, .see-all-btn:hover, .friend-link-card:hover, .ad-card:hover, .rec-list-item:hover,
.latest-card-item:hover, .rel-card:hover, .topbar-nav-item:hover, .drawer-nav-item:hover,
.type-side-item:hover, .md-bottom-nav-item:hover,
.subnav .pill:hover, .typefilter .pill:hover, .quick-tag:hover,
.toggle:hover, .toggles .submit-link:hover, .topbar-tools .submit-link:hover { text-decoration: none; }
:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: var(--radius-xs); }
@media (forced-colors: active) { :focus-visible { outline-color: Highlight; } }

h1, h2, h3 { line-height: 1.2; letter-spacing: -.022em; margin: 0 0 .5em; text-wrap: balance; font-weight: 700; }
h1 { font-size: var(--fs-800); }
h2 { font-size: var(--fs-700); }
p { margin: 0 0 1em; text-wrap: pretty; }

.wrap { box-sizing: border-box; width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 var(--s5); }

/* a11y: skip link */
.skip-link { position: absolute; left: -9999px; top: 0; background: var(--primary); color: var(--primary-ink); padding: var(--s2) var(--s4); border-radius: 0 0 var(--radius-md) 0; z-index: 100; font-weight: 600; }
.skip-link:focus { left: 0; text-decoration: none; }

/* ---------- buttons ---------- */
.btn, button {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 40px;
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
  padding: 0 var(--s4); border-radius: var(--radius-md); cursor: pointer; font: inherit; font-weight: 600;
  box-shadow: var(--shadow-xs);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
              color var(--dur) var(--ease), transform .12s var(--ease), box-shadow var(--dur) var(--ease);
}
.btn:hover, button:hover { background: var(--surface-2); border-color: var(--text-faint); text-decoration: none; }
.btn:active, button:active { transform: translateY(1px); box-shadow: none; }
.btn.primary, button.primary {
  background-color: var(--primary);
  background-image: linear-gradient(135deg, var(--accent-1), var(--accent-2));
  color: var(--primary-ink); border-color: transparent;
  box-shadow: 0 1px 2px color-mix(in srgb, var(--primary) 30%, transparent),
    0 6px 16px color-mix(in srgb, var(--accent-2) 28%, transparent);
}
.btn.primary:hover, button.primary:hover { background-image: linear-gradient(135deg, var(--primary-600), var(--accent-2)); border-color: transparent; }
.btn.primary:active, button.primary:active { background-image: none; background-color: var(--primary-700); }
.btn.danger { background: var(--danger); color: #fff; border-color: transparent; }
.btn.danger:hover { background: color-mix(in srgb, var(--danger) 86%, #000); }
.btn.ghost { background: transparent; border-color: var(--border-strong); box-shadow: none; color: var(--text-soft); }
.btn.ghost:hover { background: var(--surface-2); color: var(--text); border-color: var(--text-faint); }
.btn.small, button.small { min-height: 32px; padding: 0 var(--s3); font-size: var(--fs-300); border-radius: var(--radius-sm); }
.btn:disabled, button:disabled { opacity: .55; cursor: not-allowed; transform: none; box-shadow: none; }

/* ---------- cards / grid ---------- */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-sm);
  padding: var(--s5); margin: 0 0 var(--s4);
}
.card form { margin: 0; }

/* narrow centered cards (submit / report / legal forms) */
.card.narrow { max-width: 520px; margin: var(--s6) auto; }
.card.narrow h1 { font-size: var(--fs-700); margin-bottom: var(--s3); }
.card.narrow form { margin-top: var(--s4); }
.card.narrow label { display: block; margin: var(--s3) 0; }
.card.narrow textarea { width: 100%; box-sizing: border-box; resize: vertical; min-height: 96px; }
.card.narrow .actions-row { justify-content: center; }
.grid {
  /* Responsive column grid, no stretching: every card is an equal 1fr
     column and the page serves 54 cards. Each range below trims the tail
     with nth-child so only complete rows are visible — the served count
     always lands in the 50~54 window:
       1 col 54 · 2 cols 54 (27 rows) · 3 cols 51 (17 rows)
       4 cols 52 (13 rows) · 5 cols 50 (10 rows) · 6 cols 54 (9 rows)
     Column counts and trim rules are scoped to their exact viewport range
     (min+max) so they never leak into a neighbouring breakpoint. */
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s4);
}
.grid > .entity { min-width: 0; }
@media (min-width: 640px) and (max-width: 1179.98px) {
  .grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1180px) and (max-width: 1239.98px) {
  .grid { grid-template-columns: repeat(3, 1fr); }
  .grid > .entity:nth-child(n+52) { display: none; }
}
@media (min-width: 1240px) and (max-width: 1549.98px) {
  .grid { grid-template-columns: repeat(4, 1fr); }
  .grid > .entity:nth-child(n+53) { display: none; }
}
@media (min-width: 1550px) and (max-width: 1859.98px) {
  .grid { grid-template-columns: repeat(5, 1fr); }
  .grid > .entity:nth-child(n+51) { display: none; }
}
@media (min-width: 1860px) {
  .grid { grid-template-columns: repeat(6, 1fr); }
}

/* pagination: centered between the content and the footer */
.pager {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--s3);
  margin: var(--s7) 0 var(--s3);
  flex-wrap: wrap;
}
.pager .btn { min-width: 120px; text-align: center; }
.pager-status { color: var(--text-soft); font-size: var(--fs-400); font-variant-numeric: tabular-nums; }
.pager-jump { display: inline-flex; align-items: center; gap: var(--s2); }
.pager-jump input {
  width: 64px; padding: 6px var(--s2); font-size: var(--fs-400); text-align: center;
  border: 1px solid var(--border-strong); border-radius: var(--radius-xs);
  background: var(--surface); color: var(--text);
}
.pager-jump input:focus { outline: 2px solid transparent; border-color: var(--primary); box-shadow: 0 0 0 4px var(--ring); }

/* ---------- admin log board ---------- */
.log-row td { vertical-align: top; }
.log-row .msg { word-break: break-word; max-width: 520px; }
.log-fields {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
  font-size: .78rem; color: var(--text-soft); word-break: break-all; max-width: 480px;
}
.nowrap { white-space: nowrap; }
.log-badge-warn { background: var(--warn-weak); color: var(--warn); }
.log-badge-error, .log-badge-fatal { background: var(--danger-weak); color: var(--danger); }
.log-badge-info { background: var(--primary-weak-2); color: var(--primary); }
.log-badge-debug { background: var(--surface-2); color: var(--text-faint); }
.log-row.log-error td, .log-row.log-fatal td { background: color-mix(in srgb, var(--danger) 4%, transparent); }

/* ---------- admin dashboard ---------- */
.dash-stats {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--s3);
  margin: var(--s4) 0;
}
.dash-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: var(--s4); display: flex; flex-direction: column; gap: 4px; box-shadow: var(--shadow-xs);
}
.dash-card b { font-size: 1.6rem; font-weight: 760; font-variant-numeric: tabular-nums; }
.dash-card span { color: var(--text-faint); font-size: var(--fs-300); }
.dash-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: var(--s4);
}
.dash-panel {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: var(--s4); min-width: 0;
}
.dash-panel h2 { font-size: var(--fs-500); margin: 0 0 var(--s3); }
.chart { width: 100%; height: auto; max-width: 640px; }
.chart.pie { max-width: 160px; }
.c-grid { stroke: var(--border); stroke-width: 1; }
.c-line { fill: none; stroke: #e26000; stroke-width: 2; stroke-linejoin: round; }
.c-area { fill: rgba(226, 96, 0, .12); stroke: none; }
.c-dot { fill: #e26000; }
.c-ax { fill: var(--text-faint); font-size: 10px; }
.dash-legend { list-style: none; display: flex; flex-direction: column; gap: 4px; margin: var(--s3) 0 0; padding: 0; }
.dash-legend li { display: flex; align-items: center; gap: 8px; font-size: var(--fs-300); color: var(--text-soft); }
.dash-legend i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }

/* form action rows: save + restore-defaults side by side, equal height */
.actions-row { display: flex; gap: var(--s3); align-items: center; margin-top: var(--s3); }
.actions-row form { margin: 0; }

/* ---------- entity card (uniform size, icon meta) ---------- */
.entity {
  position: relative;
  display: flex; flex-direction: column; gap: 6px;
  min-width: 0;
  height: 180px; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: var(--s4); box-shadow: var(--shadow-sm); text-decoration: none; color: inherit;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.entity:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: color-mix(in srgb, var(--primary) 35%, var(--border)); text-decoration: none; }
/* stretched link: the whole card stays clickable without wrapping the card
   in an <a> — nested anchors are illegal HTML and browsers would tear the
   card DOM apart at the first inner link. */
.entity .card-link { position: absolute; inset: 0; z-index: 1; border-radius: inherit; }
.entity .title a { color: inherit; text-decoration: none; }
.entity .verified { position: relative; z-index: 2; }
.entity-head { display: flex; align-items: stretch; gap: var(--s3); flex: none; }
.entity .avatar { flex: none; width: 54px; height: 54px; border-radius: var(--radius-md); font-size: 1.4rem; }
.avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; display: block; }
.entity .headtext { display: flex; flex-direction: column; justify-content: space-between; min-width: 0; padding-right: 30px; }
.entity .title {
  font-weight: 650; font-size: var(--fs-500); line-height: 1.3; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.entity .handle { font-size: var(--fs-300); color: var(--text-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.entity .desc {
  color: var(--text-soft); font-size: var(--fs-400); line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  min-height: calc(2 * 1.5em);
}
.entity .meta {
  position: absolute; left: var(--s4); right: var(--s4); bottom: var(--s4);
  display: flex; align-items: center; gap: var(--s4);
  color: var(--text-faint); font-size: var(--fs-300); font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden;
}
.entity .meta .stat { display: inline-flex; flex-direction: row; align-items: center; gap: 5px; flex: 1 1 0; min-width: 0; white-space: nowrap; }
.entity .meta .stat svg { width: 14px; height: 14px; fill: currentColor; opacity: .6; flex: none; }
.entity .meta b { color: var(--text); font-weight: 650; font-size: 12px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.entity .verified {
  position: absolute; top: 10px; right: 10px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: var(--radius-full);
  background: var(--ok-weak);
  color: var(--ok); font-size: 1rem; font-weight: 800; line-height: 1;
}

/* ---------- badges ---------- */
.badge { display: inline-block; padding: 2px 9px; border-radius: var(--radius-full); font-size: .73rem; font-weight: 650; letter-spacing: .01em; }
.badge.ok { background: var(--ok-weak); color: var(--ok); }
.badge.warn { background: var(--warn-weak); color: var(--warn); }
.badge.danger { background: var(--danger-weak); color: var(--danger); }

/* ---------- misc shared ---------- */
.muted { color: var(--text-soft); }
.muted.center { text-align: center; padding: var(--s7) 0; }
.row { display: flex; gap: var(--s3); flex-wrap: wrap; align-items: center; }
.row-actions { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; }
.notice { padding: var(--s3) var(--s4); border-radius: var(--radius-sm); background: var(--primary-weak); color: var(--text); margin: var(--s4) 0; font-size: var(--fs-400); }
.notice.err { background: var(--danger-weak); color: var(--danger); }
.taglist, .tags { display: flex; gap: var(--s2); flex-wrap: wrap; }
.tag { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-full); padding: 3px 11px; font-size: var(--fs-400); color: var(--text-soft); }
fieldset { border: 1px solid var(--border); border-radius: var(--radius-sm); padding: var(--s3) var(--s4); margin: var(--s4) 0; }
legend { color: var(--text-soft); font-size: var(--fs-300); padding: 0 var(--s2); }
label { display: block; margin: var(--s4) 0; }
label span { display: block; font-size: var(--fs-400); color: var(--text-soft); margin-bottom: var(--s2); }
input, select, textarea {
  width: 100%; padding: var(--s2) var(--s3); border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--text); font: inherit; transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
input:focus, select:focus, textarea:focus { outline: 2px solid transparent; border-color: var(--primary); box-shadow: 0 0 0 4px var(--ring); }
input[type=checkbox], input[type=radio] { width: auto; }
table { width: 100%; border-collapse: collapse; background: var(--surface); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); }
th, td { text-align: left; padding: var(--s3); border-bottom: 1px solid var(--border); }
th { background: var(--surface-2); font-weight: 600; color: var(--text-soft); }
/* public /stats: fixed narrow label column (shaded field-name cells keep one
   width across every section) + flexible, right-aligned value column. */
/* --- about: public stats tiles (merged /stats page, 2026-09-14) --- */
.pub-stats { margin-top: var(--s2); }
.pub-stats-periods, .pub-stats-totals { display: grid; gap: var(--s3); margin: var(--s3) 0; }
.pub-stats-caption { display: block; margin: var(--s4) 0 var(--s2); }
.pub-stats-periods { grid-template-columns: repeat(4, 1fr); }
.pub-stats-totals { grid-template-columns: repeat(3, 1fr); }
.pub-stat-tile {
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-md);
  padding: var(--s3) var(--s4); display: flex; flex-direction: column; gap: var(--s2); min-width: 0;
}
.pub-stat-head { color: var(--text-soft); font-size: var(--fs-400); font-weight: 600; }
.pub-stat-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s2); }
.pub-stat-row span { color: var(--text-faint); font-size: var(--fs-300); }
.pub-stat-row b, .pub-stat-big { font-variant-numeric: tabular-nums; font-weight: 760; letter-spacing: -.01em; }
.pub-stat-row b { font-size: var(--fs-500); }
.pub-stat-big { font-size: 1.5rem; }
.pub-stats .muted { margin: var(--s2) 0 0; }
@media (max-width: 900px) { .pub-stats-periods { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .pub-stats-periods, .pub-stats-totals { grid-template-columns: 1fr; } }
.hx-loading, #listing.htmx-swapping { opacity: .5; transition: opacity var(--dur) var(--ease); }
:target, #listing { scroll-margin-top: calc(var(--header-h) + var(--s4)); }

/* ---------- footer ---------- */
footer.foot { color: var(--text-soft); font-size: var(--fs-400); margin-top: var(--s8); border-top: 1px solid var(--border); background: var(--surface); }
footer.foot .wrap { display: flex; gap: var(--s4); justify-content: center; align-items: center; padding: var(--s6) var(--s5) var(--s8); flex-wrap: wrap; text-align: center; }
footer.foot .foot-links { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center; }
footer.foot .foot-links a { color: var(--text-soft); }
footer.foot .foot-links a:hover { color: var(--primary-text); text-decoration: none; }
.foot-stats { display: inline-flex; align-items: center; }
.foot-stats svg { display: block; }

/* =====================================================================
   PUBLIC SITE (body.public)
   ===================================================================== */
body.public { display: flex; flex-direction: column; min-height: 100vh;
  --maxw: 1680px;
  /* brand-tinted hero wash: blue -> cyan, echoing the logo gradient */
  background:
    radial-gradient(1100px 460px at 50% -160px, var(--primary-weak), transparent 72%),
    radial-gradient(720px 340px at 84% -130px, color-mix(in srgb, var(--accent-2) 12%, transparent), transparent 70%),
    var(--bg);
}
@media (min-width: 1860px) { body.public { --maxw: 1856px; } }
body.public main { flex: 1 0 auto; }
footer.foot { flex-shrink: 0; }

/* a11y: visibly-hidden but screen-reader available */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

/* hero */
.hero { padding: 45px 0 var(--s6); text-align: center; }
.hero-search { margin: 0 auto; }
.detail-search { margin: var(--s4) auto var(--s5); }

/* category navigation — under the search box. Two-level: parents with
   children open a dropdown on hover / keyboard focus. */
.catnav { display: flex; gap: var(--s2); flex-wrap: wrap; justify-content: center; margin-top: var(--s5); }
.catnav a {
  color: var(--text-soft); padding: var(--s2) var(--s4); border-radius: var(--radius-full);
  border: 1px solid var(--border); background: var(--surface); font-size: var(--fs-400); font-weight: 550;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease), transform .12s var(--ease), background var(--dur) var(--ease);
}
.catnav a:hover { color: var(--primary); border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); background: var(--primary-weak); text-decoration: none; transform: translateY(-1px); }
.catnav .cat-item { position: relative; display: inline-flex; align-items: center; }
.catnav .cat-item > a { border-radius: var(--radius-full) 0 0 var(--radius-full); border-right: 0; padding-right: calc(var(--s2) - 2px); }
.catnav .cat-caret {
  display: inline-flex; align-items: center; padding: var(--s2) var(--s3);
  border: 1px solid var(--border); border-radius: 0 var(--radius-full) var(--radius-full) 0; background: var(--surface);
  color: var(--text-faint); font-size: var(--fs-300); margin-left: -1px;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.catnav .cat-item:hover .cat-caret, .catnav .cat-item:focus-within .cat-caret { color: var(--primary); border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); }
.catnav .cat-sub {
  display: none; position: absolute; top: calc(100% + 6px); left: 0; z-index: 40;
  flex-direction: column; min-width: 180px; padding: var(--s2);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow);
}
.catnav .cat-item:hover .cat-sub, .catnav .cat-item:focus-within .cat-sub { display: flex; }
.catnav .cat-sub a { border: 0; background: none; padding: var(--s2) var(--s3); border-radius: var(--radius-xs); transform: none; }
.catnav .cat-sub a:hover { transform: none; background: var(--primary-weak); }
.catnav a.cat-all { color: var(--primary); border-style: dashed; }

/* visible page heading + subcategory chip row on hub pages */
.subnav { display: flex; gap: var(--s2); flex-wrap: wrap; margin: var(--s3) 0; }
.subnav .pill, .typefilter .pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: var(--s1) var(--s3); border-radius: var(--radius-full);
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text-soft); font-size: var(--fs-300); font-weight: 600;
  text-decoration: none; transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.subnav .pill:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); color: var(--text); }
.subnav .pill .cnt { color: var(--text-faint); font-variant-numeric: tabular-nums; }

/* detail-page tag chips (listing cards do not show tags) */
a.tag:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); color: var(--primary); text-decoration: none; }

/* all-categories hub page: compact cards; each row sizes to its own content
   (no global row stretching) and the action chip is pinned to the card foot. */
.cat-tree { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--s4); margin-top: var(--s4); align-items: stretch; }
.cat-block {
  display: flex; flex-direction: column; gap: var(--s3);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: var(--s4); box-shadow: var(--shadow-xs);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.cat-block:hover { border-color: color-mix(in srgb, var(--primary) 35%, var(--border)); box-shadow: var(--shadow-sm); transform: translateY(-2px); }
.cat-block h2 { font-size: var(--fs-500); margin: 0; display: flex; align-items: baseline; gap: var(--s2); }
.cat-block h2 a { color: var(--text); }
.cat-block h2 a:hover { color: var(--primary); text-decoration: none; }
.cat-block .subnav { margin: 0; margin-top: auto; }
.cnt { color: var(--text-faint); font-size: var(--fs-300); font-weight: 500; font-variant-numeric: tabular-nums; }

@media (max-width: 680px) {
  .catnav { overflow-x: auto; flex-wrap: nowrap; justify-content: flex-start; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
  .catnav::-webkit-scrollbar { display: none; }
  .catnav a, .catnav .cat-item > a, .catnav .cat-caret { white-space: nowrap; }
  .catnav .cat-sub { display: none !important; }
}

/* detail / profile */
.breadcrumb { color: var(--text-faint); font-size: var(--fs-400); margin: var(--s5) 0 var(--s3); }
.breadcrumb a { color: var(--text-soft); }
.breadcrumb .sep { margin: 0 var(--s2); }
/* detail profile card: same family as the related/latest cards (chips,
   avatar treatment, radius) with one clear reading order — identity,
   description, meta strip, actions. The QR stays desktop-only: a phone
   cannot scan its own screen. */
.card.profile { position: relative; display: block; max-width: 960px; margin: var(--s5) auto 0; padding: var(--s5) var(--s6); }
.profile-head { display: flex; align-items: center; gap: var(--s4); }
.profile-avatar { flex: none; width: 72px; height: 72px; border-radius: var(--radius-lg); font-size: 2rem; }
.profile-ident { display: flex; flex-direction: column; gap: 6px; min-width: 0; flex: 1 1 auto; }
/* Entity names wrap in full (never truncated): the h1 is the page's identity
   anchor for readers, screen readers and SEO. Long unbroken tokens break, and
   the verified mark keeps the first line's baseline instead of drifting to the
   vertical centre of a multi-line name. */
.profile-name { display: flex; align-items: baseline; gap: var(--s2); margin: 0; font-size: clamp(1.3rem, 2.4vw, var(--fs-800)); font-weight: 760; letter-spacing: -.01em; line-height: 1.25; }
.profile-name-text { min-width: 0; overflow-wrap: anywhere; text-wrap: pretty; }
.profile-name .fa-circle-check { flex: none; color: var(--primary); font-size: .85em; }
.profile-handle { color: var(--text-faint); font-size: var(--fs-400); }
.profile-chips { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; margin-top: var(--s2); }
/* the floating QR occupies the card's top-right ~7rem: reserve that lane so
   long names and the badge row wrap instead of running under the code */
@media (min-width: 681px) {
  .card.profile.has-qr .profile-head { padding-right: 7rem; }
  .card.profile.has-qr .profile-chips { padding-right: 7rem; }
}
.profile-chips .latest-category-badge { text-decoration: none; }
.profile-chips .latest-category-badge:hover { color: var(--primary); background: var(--primary-weak); }
/* audience (members / MAU) sits inline after the badges, home/latest meta
   language: small icon + bold value + tiny label */
.profile-stat { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-300); color: var(--text-faint); white-space: nowrap; }
.latest-category-badge + .profile-stat { margin-left: var(--s2); }
.profile-stat svg { width: 15px; height: 15px; fill: currentColor; opacity: .55; flex: none; }
.profile-stat b { color: var(--text); font-weight: 700; font-size: var(--fs-400); font-variant-numeric: tabular-nums; }
/* QR floats in the card's top-right corner (label centred underneath) so it
   never stretches the identity row: the badge row keeps its tight 8px rhythm
   under the avatar. Desktop only - a phone cannot scan its own screen. */
.profile-qr { position: absolute; top: var(--s5); right: var(--s6); display: flex; flex-direction: column; align-items: center; gap: 4px; color: var(--text-faint); font-size: var(--fs-300); }
/* 82px plate (border-box) = 72px code + 4px quiet zone + 1px outline, so the
   scannable square matches the 72px avatar exactly */
.profile-qr img { width: 82px; height: 82px; border: 1px solid color-mix(in srgb, var(--primary) 35%, var(--border)); border-radius: var(--radius-md); padding: 4px; background: #fff; }
/* report page: the reported entity shown as a boxed summary above the form */
.report-target { padding: var(--s3); border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface-2); margin-bottom: var(--s4); }
.report-target .avatar { flex: none; width: 54px; height: 54px; border-radius: var(--radius-md); overflow: hidden; }
.report-target .avatar img { width: 54px; height: 54px; }
/* the report summary kept the old generic .handle styling; scope it here now
   that the detail card no longer uses that class */
.report-target .headtext { min-width: 0; }
.report-target .title { font-weight: 650; color: var(--text); overflow-wrap: anywhere; }
.report-target .handle { color: var(--text-faint); font-size: var(--fs-300); }
.type-pill { text-transform: capitalize; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-full); padding: 1px 10px; font-size: var(--fs-300); color: var(--text-soft); }
/* full description, never clamped: wraps naturally on every viewport; an
   empty description keeps exactly one line of height */
.desc-lg { color: var(--text); margin: var(--s4) 0 0; max-width: var(--measure); white-space: pre-wrap; overflow-wrap: anywhere; text-wrap: pretty; min-height: 1.65em; }
.profile-updated { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: var(--s1) var(--s2); margin: var(--s2) 0 0; color: var(--text-faint); font-size: var(--fs-300); font-variant-numeric: tabular-nums; line-height: 1.35; }
.profile-updated i { opacity: .65; }
.card.profile .tags { margin-top: var(--s3); }
.card.profile .notice.err { margin: var(--s3) 0 0; }
.profile-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); margin-top: 0; padding-top: var(--s4); border-top: 1px solid var(--border); }
.profile-cta { min-height: 44px; padding: 0 var(--s5); }
.profile-secondary { display: flex; flex-wrap: wrap; gap: var(--s2); margin-left: auto; }
.profile-secondary .btn {
  border-color: color-mix(in srgb, var(--primary) 35%, var(--border));
  color: var(--text-soft); background: transparent; box-shadow: none;
}
.profile-secondary .btn:hover {
  border-color: color-mix(in srgb, var(--primary) 70%, var(--border));
  color: var(--primary); background: var(--primary-weak-2);
}
.actions { margin-top: var(--s2); }
.copy.done { color: var(--ok); border-color: var(--ok); }
.section-title { font-size: var(--fs-700); font-weight: 700; margin: var(--s7) 0 var(--s4); padding-bottom: var(--s3); border-bottom: 1px solid var(--border); }

/* auth (admin login) */
.auth { display: grid; place-items: center; min-height: 100vh; padding: var(--s4); }
.auth .card { width: 100%; max-width: 380px; }

@media (max-width: 680px) {
  .wrap { padding: 0 var(--s4); }
  .hero { padding: 32px 0 var(--s5); }
  .searchbar { margin-left: 0; width: 100%; }
  .searchbar input { flex: 1; min-width: 0; }
  .site-head .wrap { gap: var(--s3); }
  .card.profile { padding: var(--s4); margin-top: var(--s4); }
  .profile-avatar { width: 60px; height: 60px; border-radius: var(--radius-md); }
  .profile-qr { display: none; }
  .profile-cta { width: 100%; }
  .profile-secondary { margin-left: 0; width: 100%; }
  .profile-secondary .btn { flex: 1 1 auto; }
}

/* legal pages (terms / privacy / about / stats): centered readable column */
.legal { max-width: 760px; margin: var(--s6) auto; }
.legal h1 { font-size: var(--fs-700); margin-bottom: var(--s5); }
.legal h2 { font-size: var(--fs-500); margin: var(--s5) 0 var(--s2); }
.legal h3 { font-size: var(--fs-400); margin: var(--s4) 0 var(--s1); color: var(--text); }
.legal p { color: var(--text-soft); line-height: 1.7; max-width: var(--measure); }
.legal .lead { font-size: var(--fs-500); color: var(--text); }
.legal ul { color: var(--text-soft); line-height: 1.7; max-width: var(--measure); padding-left: 1.2em; margin: 0 0 1em; }
.legal li { margin: .35em 0; }
.legal li strong, .legal p strong { color: var(--text); }
.legal a { color: var(--primary); }

/* ad area: its own 4/2/1-column grid (same breakpoints as the home
   latest-grid), deliberately independent of the entity .grid so a row of
   image ads is always 4, 2 or 1 - never 3 (the .grid 3/5/6-column
   breakpoints used to wrap a four-ad row as 3+1). Image ads span two
   columns by default (.w1 = one column, used when a full row of four fits);
   text ads take one full-width row each. */
.ad-area {
  display: grid; gap: var(--s3); grid-template-columns: repeat(4, 1fr);
  margin: var(--s4) 0 var(--s5);
}
@media (max-width: 1180px) { .ad-area { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 680px) { .ad-area { grid-template-columns: 1fr; } .ad-area > *:nth-child(n+3) { display: none; } }
.ad-area > .ad-card, .ad-area > .ad-text { min-width: 0; }
.ad-card {
  grid-column: span 2; display: flex; flex-direction: column; position: relative;
  overflow: hidden; border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--surface); box-shadow: var(--shadow-sm); max-width: 100%;
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}
.ad-card.w1 { grid-column: span 1; }
.ad-card img { display: block; width: 100%; height: auto; }
.ad-card .ad-caption {
  display: block; padding: var(--s3) var(--s4);
  font-size: var(--fs-300); color: var(--text-soft);
  border-top: 1px solid var(--border);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ad-card .ad-badge {
  position: absolute; top: 8px; right: 8px; z-index: 1;
  padding: 1px 8px; border-radius: var(--radius-full);
  background: rgba(15, 23, 42, .55); color: #fff;
  border: 1px solid rgba(255, 255, 255, .28);
  font-size: .68rem; font-weight: 650; letter-spacing: .06em;
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
.ad-card:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); box-shadow: var(--shadow); }
.ad-text {
  grid-column: 1 / -1; display: flex; align-items: center; gap: var(--s3);
  min-width: 0; padding: var(--s3) var(--s4);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--surface-2); font-size: var(--fs-400);
  color: var(--text); text-decoration: none;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.ad-text:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); background: var(--surface); }
.ad-text .ad-chip {
  flex: none; padding: 1px 8px; border-radius: var(--radius-full);
  background: color-mix(in srgb, var(--primary) 16%, transparent); color: var(--primary);
  font-size: .68rem; font-weight: 650; letter-spacing: .06em;
}
.ad-text .ad-text-body { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ad-text:hover .ad-text-body { color: var(--primary); }
@media (max-width: 1180px) {
  /* two/one-column ad grid: every card is one column wide */
  .ad-area .ad-card, .ad-area .ad-card.w1 { grid-column: auto; }
}

/* entity type filter pills (pill base shared with .subnav above) */
.typefilter { display: flex; gap: var(--s2); flex-wrap: wrap; margin: var(--s3) 0; }
.typefilter .pill .cnt { color: var(--text-faint); font-variant-numeric: tabular-nums; }
.typefilter .pill:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); color: var(--text); }
.typefilter .pill.active { border-color: transparent; background: var(--primary); color: var(--primary-ink); box-shadow: 0 1px 2px color-mix(in srgb, var(--primary) 30%, transparent); }
.typefilter .pill.active .cnt { color: inherit; opacity: .9; }
@media (max-width: 680px) { .typefilter { overflow-x: auto; flex-wrap: nowrap; } .typefilter .pill { white-space: nowrap; } }

/* --- portal home, type-nav pages, detail enhancements --- */

.home-sec { margin: var(--s5) 0 var(--s6); }
.home-sec .section-title { display: flex; align-items: baseline; gap: var(--s3); margin-bottom: var(--s3); }


/* type-nav hub pages */

.tn-section { margin-bottom: var(--s6); scroll-margin-top: calc(var(--header-h) + var(--s4)); }
.tn-section-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); margin: var(--s4) 0 var(--s3); }
.tn-section-title { font-size: var(--fs-600); margin: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* unified "查看全部" button: primary-tinted border, aligned with section titles */
.see-all-btn {
  display: inline-flex; align-items: center; gap: var(--s1); flex: 0 0 auto;
  padding: 2px var(--s3); border-radius: var(--radius-full);
  border: 1px solid color-mix(in srgb, var(--primary) 45%, var(--border));
  background: var(--surface); color: var(--primary-text);
  font-size: var(--fs-300); font-weight: 600; text-decoration: none; white-space: nowrap;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.see-all-btn:hover { background: var(--primary-weak); border-color: var(--primary); color: var(--primary-600); }
.see-all-btn .cnt { color: var(--text-faint); font-variant-numeric: tabular-nums; }
/* hub entity cards: 4-up grid, fixed-height card (avatar + name/members + 2-line desc) */
.tn-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s3); }
.tn-card {
  display: flex; flex-direction: column; gap: var(--s2);
  height: 118px; padding: var(--s3); box-sizing: border-box; overflow: hidden;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  text-decoration: none; color: inherit; min-width: 0;
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.tn-card:hover { transform: translateY(-2px); border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); box-shadow: var(--shadow-sm); }
.tn-card-head { display: flex; align-items: center; gap: var(--s2); min-width: 0; }
.tn-card-avatar { width: 40px; height: 40px; border-radius: var(--radius-sm); object-fit: cover; flex: 0 0 auto; }
.tn-card-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.tn-card-title { font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tn-card-title .verified { color: var(--primary); margin-left: var(--s1); }
.tn-card-members { display: inline-flex; align-items: center; gap: 4px; color: var(--text-soft); font-size: var(--fs-300); font-variant-numeric: tabular-nums; }
.tn-card-members svg { width: 14px; height: 14px; fill: currentColor; opacity: .6; flex: none; }
.tn-card-desc { margin: 0; color: var(--text-soft); font-size: var(--fs-300); line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
@media (max-width: 1180px) { .tn-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 680px) { .tn-grid { grid-template-columns: 1fr; } }


/* detail page */

/* ============================================================
   tgnav-style shell: topbar, three-panel home, latest cards,
   quick-tags, mobile bottom nav, multi-column footer.
   ============================================================ */

/* --- topbar --- */
body.public .md-topbar {
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
  position: sticky; top: 0; z-index: 20;
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  -webkit-backdrop-filter: saturate(150%) blur(12px);
  backdrop-filter: saturate(150%) blur(12px);
  border-bottom: 1px solid var(--border);
}
.topbar-inner { display: flex; align-items: center; gap: var(--s4); min-height: calc(var(--header-h) + 2px); padding: var(--s2) var(--s4); }
.topbar-brand { display: flex; align-items: center; gap: var(--s2); flex: 0 0 auto; }
.md-icon-button {
  display: none; border: none; background: none; color: var(--text-soft);
  font-size: 1.1rem; cursor: pointer; padding: var(--s2); border-radius: var(--radius-xs);
}
.md-icon-button:hover { background: var(--surface-2); }
.topbar-nav { display: flex; align-items: center; gap: var(--s1); flex: 1 1 auto; overflow-x: auto; }
.topbar-nav-item {
  display: inline-flex; align-items: center; gap: var(--s1);
  padding: var(--s2) var(--s3); border-radius: var(--radius-full);
  color: var(--text-soft); text-decoration: none; font-size: var(--fs-400); white-space: nowrap;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.topbar-nav-item i { font-size: .95em; }
.topbar-nav-item:hover { color: var(--primary); background: var(--primary-weak); }
.topbar-nav-item.active { color: var(--primary-ink); background: var(--primary); font-weight: 600; box-shadow: 0 1px 2px color-mix(in srgb, var(--primary) 30%, transparent); }
.topbar-tools { display: flex; align-items: center; gap: var(--s2); margin-left: auto; }

/* --- hero search (clickable box + Ctrl+K badge) --- */
body.public .hero .hero-title {
  max-width: 560px; margin: 0 auto 24px;
  font-size: clamp(1.1rem, 4.5vw, 1.75rem); line-height: 1.3;
  text-wrap: balance;
}
.hero-search { position: relative; }
.hero-search .search-icon { position: absolute; left: var(--s4); top: 50%; transform: translateY(-50%); color: color-mix(in srgb, var(--primary) 45%, var(--border)); }
/* specificity > .searchbar input so the icon's reserved left padding is not
   overridden by the later shared searchbar rule (the icon is absolute and the
   placeholder must start past it) */
.searchbar.hero-search input { padding-left: var(--s7); padding-right: 120px; }

/* --- quick tags --- */
[hidden] { display: none !important; }

.quick-tags-container { display: flex; flex-wrap: wrap; gap: var(--s2); margin: var(--s3) 0 var(--s4); }
.quick-tag {
  display: inline-flex; align-items: center; gap: var(--s1);
  padding: var(--s1) var(--s3); border-radius: var(--radius-full);
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text-soft); text-decoration: none; font-size: var(--fs-400);
}
.quick-tag i { color: var(--primary); }
.quick-tag:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); color: var(--primary); }

/* --- recommendations row: 力荐 (when present) + hot channel/group/bot,
       all four as equal-width cards in one row --- */
.featured-section { margin: var(--s5) 0; }
.recommendations-panels {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s4);
}
.recommendations-panels.has-picks { grid-template-columns: repeat(4, 1fr); }
.rec-panel {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: var(--s4); display: flex; flex-direction: column; min-width: 0; box-shadow: var(--shadow-sm);
}
.rec-panel-header { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); margin-bottom: var(--s3); }
.rec-panel-title { display: flex; align-items: center; gap: var(--s2); font-size: var(--fs-500); margin: 0; line-height: 1.3; }
.rec-panel-title i { color: var(--primary); width: 1em; text-align: center; flex: 0 0 1em; }
.refresh-btn {
  display: inline-flex; align-items: center; gap: var(--s1);
  border: 1px solid color-mix(in srgb, var(--primary) 45%, var(--border)); background: transparent; color: var(--text-soft);
  border-radius: 6px; padding: 1px var(--s2); font-size: var(--fs-300); line-height: 1.5; cursor: pointer;
  min-height: 24px; /* override the generic 40px button min-height: flat chip */
}
.refresh-btn:hover { color: var(--primary); border-color: color-mix(in srgb, var(--primary) 75%, var(--border)); }
.refresh-btn i { transition: transform .5s; }
.refresh-btn:active i { transform: rotate(360deg); }
@media (prefers-reduced-motion: reduce) { .refresh-btn i { transition: none; } .refresh-btn:active i { transform: none; } }

.rec-list { display: grid; gap: var(--s1); flex: 1 1 auto; align-content: start; }
.rec-list-item {
  display: flex; align-items: center; gap: var(--s3); padding: var(--s2);
  border-radius: var(--radius-sm); text-decoration: none; color: inherit; min-width: 0;
  transition: background var(--dur) var(--ease);
}
.rec-list-item:hover { background: var(--primary-weak-2); }
.rec-item-avatar { width: 40px; height: 40px; border-radius: var(--radius-sm); object-fit: cover; flex: 0 0 auto; transition: transform var(--dur) var(--ease); }
.rec-list-item:hover .rec-item-avatar { transform: scale(1.04); }
.rec-item-title {
  flex: 1 1 auto; min-width: 0; font-size: var(--fs-400); font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rec-item-title .verified { color: var(--primary); margin-left: var(--s1); }
.rec-panel-footer { margin-top: var(--s3); }
.see-more-btn {
  display: inline-flex; align-items: center; gap: var(--s1);
  font-size: var(--fs-400); color: var(--primary-text); text-decoration: none;
}
.see-more-btn:hover { text-decoration: underline; }
.rec-list .empty { padding: var(--s4); text-align: center; }

/* --- latest cards --- */
.latest-section { margin: var(--s5) 0; }
.section-title-bar { display: flex; align-items: center; margin: var(--s4) 0 var(--s3); }
.title-large { font-size: var(--fs-600); margin: 0; text-wrap: balance; }
.section-title-icon { color: var(--primary); margin-right: var(--s2); font-size: .9em; }
.latest-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s3); }
.latest-card-item {
  display: flex; align-items: center; gap: var(--s3); padding: var(--s3);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  text-decoration: none; color: inherit; min-width: 0;
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}
/* hover: quiet lift + layered elevation + accent border (underlining is
   suppressed by the shared anchor rule at the top of this file) */
.latest-card-item:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
  box-shadow: var(--shadow-sm);
}
.latest-card-item:active { transform: translateY(0); box-shadow: var(--shadow-xs); }
.latest-card-avatar {
  width: 48px; height: 48px; border-radius: var(--radius-sm); object-fit: cover; flex: 0 0 auto;
  transition: transform var(--dur) var(--ease);
}
.latest-card-item:hover .latest-card-avatar { transform: scale(1.04); }
.latest-card-body { display: flex; flex-direction: column; gap: var(--s1); min-width: 0; }
.latest-card-title { font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.latest-card-badges { display: flex; gap: var(--s1); flex-wrap: nowrap; }
.latest-type-badge, .latest-category-badge {
  font-size: var(--fs-300); padding: 0 var(--s2); border-radius: var(--radius-full); white-space: nowrap;
}
.latest-type-badge { color: var(--primary-text); background: var(--primary-weak); }
/* colour the type badges by content type (.t-<type> on cards stays a layout hook) */
.latest-type-badge.label-channel { color: var(--type-channel); background: color-mix(in srgb, var(--type-channel) 12%, transparent); }
.latest-type-badge.label-group { color: var(--type-group); background: color-mix(in srgb, var(--type-group) 12%, transparent); }
.latest-type-badge.label-robot { color: var(--type-robot); background: color-mix(in srgb, var(--type-robot) 12%, transparent); }
.latest-category-badge { color: var(--text-soft); background: var(--surface-2); }

/* --- related cards (detail page): the home latest-card language plus a
   fixed two-line description, a bottom-left audience stat (blank when
   Telegram does not provide one) and the verified mark in the top-right
   corner (same fa-circle-check treatment as the home hot lists) --- */
.rel-card {
  position: relative; display: flex; flex-direction: column; gap: var(--s2);
  min-width: 0; height: 176px; overflow: hidden; padding: var(--s3);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  text-decoration: none; color: inherit;
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}
.rel-card:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
  box-shadow: var(--shadow-sm);
}
.rel-card:active { transform: translateY(0); box-shadow: var(--shadow-xs); }
.rel-head { display: flex; align-items: center; gap: var(--s3); flex: none; }
.rel-avatar { width: 48px; height: 48px; border-radius: var(--radius-sm); object-fit: cover; flex: 0 0 auto; }
.rel-body { display: flex; flex-direction: column; gap: var(--s1); min-width: 0; flex: 1 1 auto; padding-right: 22px; }
.rel-title { font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rel-badges { display: flex; gap: var(--s1); flex-wrap: nowrap; overflow: hidden; }
.rel-badges .latest-category-badge { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.rel-desc {
  color: var(--text-soft); font-size: var(--fs-400); line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  min-height: calc(2 * 1.5em);
}
.rel-meta {
  position: absolute; left: var(--s3); bottom: var(--s3);
  display: inline-flex; align-items: center; gap: 5px;
  color: var(--text-faint); font-size: var(--fs-300); font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden;
}
.rel-meta svg { width: 14px; height: 14px; fill: currentColor; opacity: .6; flex: none; }
.rel-meta b { color: var(--text); font-weight: 650; font-size: 12px; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.rel-verified { position: absolute; top: 10px; right: 10px; z-index: 1; color: var(--primary); font-size: 1rem; line-height: 1; }

/* --- friend links --- */
.friend-links-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--s3); }
.friend-link-card {
  display: flex; flex-direction: column; gap: var(--s1); padding: var(--s3);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  text-decoration: none; color: inherit; min-width: 0;
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}
.friend-link-card:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--primary) 45%, var(--border));
  box-shadow: var(--shadow-sm);
}
.friend-link-title { font-weight: 600; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.friend-link-desc { font-size: var(--fs-300); color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.footer-link { color: var(--text-soft); text-decoration: none; font-size: var(--fs-400); }
.footer-link:hover { color: var(--primary); }

/* --- mobile bottom nav --- */
.md-bottom-nav {
  display: none; position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  border-top: 1px solid var(--border);
  padding: var(--s1) 0 calc(var(--s1) + env(safe-area-inset-bottom));
}
.md-bottom-nav-item {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
  color: var(--text-faint); text-decoration: none; font-size: var(--fs-300);
  padding: var(--s2) 0;
}
.md-bottom-nav-item i { font-size: 1.05rem; }
.md-bottom-nav-item.active { color: var(--primary); }

/* --- drawer (real side drawer) --- */
.md-drawer {
  position: fixed; top: 0; bottom: 0; left: 0; z-index: 40;
  padding-left: env(safe-area-inset-left);
  width: 264px; max-width: 84vw;
  display: flex; flex-direction: column;
  background: var(--surface); border-right: 1px solid var(--border);
  padding: var(--s4) var(--s4) calc(var(--s4) + env(safe-area-inset-bottom));
  padding-top: calc(var(--s4) + env(safe-area-inset-top));
  overflow-y: auto; overscroll-behavior: contain;
  transform: translateX(-100%); transition: transform .24s var(--ease);
}
.md-drawer-header { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); margin-bottom: var(--s4); }
.md-drawer-nav { display: flex; flex-direction: column; gap: var(--s1); flex: 1 1 auto; }
.drawer-nav-item {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3); border-radius: var(--radius-sm);
  color: var(--text-soft); text-decoration: none; font-size: var(--fs-400);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.drawer-nav-item i { width: 20px; text-align: center; font-size: 1.05em; }
.drawer-nav-item:hover { background: var(--primary-weak); color: var(--primary); }
.drawer-nav-item.active { background: var(--primary); color: var(--primary-ink); font-weight: 600; }
.md-drawer-foot { border-top: 1px solid var(--border); padding-top: var(--s3); display: flex; flex-direction: column; gap: var(--s1); }
.drawer-overlay {
  position: fixed; inset: 0; z-index: 35; background: rgba(0,0,0,.5);
  opacity: 0; pointer-events: none; transition: opacity .2s var(--ease);
}
body.public.drawer-open .md-drawer { transform: translateX(0); box-shadow: var(--shadow-lg); }
body.public.drawer-open .drawer-overlay { opacity: 1; pointer-events: auto; }
@media (prefers-reduced-motion: reduce) {
  .md-drawer, .drawer-overlay { transition: none; }
}

/* wide admin tables: scroll horizontally on narrow screens instead of
   squeezing 12+ columns (residual item 5; public pages keep their layout) */
@media (max-width: 900px) {
  body:not(.public) table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

/* --- responsive --- */
@media (max-width: 1180px) {
  .recommendations-panels, .recommendations-panels.has-picks { grid-template-columns: repeat(2, 1fr); }
  .latest-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 680px) {
  .recommendations-panels, .recommendations-panels.has-picks { grid-template-columns: 1fr; }
  .latest-grid { grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
  .md-icon-button { display: inline-flex; }
  .topbar-nav { display: none; }
  .topbar-nav-item { white-space: nowrap; }
  /* hide the text submit in the crowded mobile topbar (reachable from the
     drawer footer); high specificity so it wins over .toggle's display */
  .topbar-tools .submit-link, .toggles .submit-link { display: none; }
  .md-bottom-nav { display: flex; }
  body.public { padding-bottom: calc(var(--s8) + env(safe-area-inset-bottom)); }
  body.public .hero .hero-title { font-size: var(--fs-700); margin-bottom: 24px; }
  .searchbar.hero-search input { padding-right: var(--s4); }
}

/* --- compliance touches --- */
body.public { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
body.public.drawer-open { overflow: hidden; }

/* site announcement bar: full-width, attached to the header's bottom edge */
.site-announce { background: var(--primary-weak); border-bottom: 1px solid var(--border); font-size: var(--fs-300); }
.site-announce-inner { display: flex; align-items: center; gap: var(--s2); padding-top: var(--s2); padding-bottom: var(--s2); }
.site-announce .fa-bullhorn { flex: none; color: var(--primary); }
.announcement-text { flex: 1 1 auto; min-width: 0; color: var(--text-soft); overflow-wrap: anywhere; }
.announcement-text a { color: var(--primary); font-weight: 600; }
.announcement-close {
  flex: 0 0 auto; border: none; background: none; color: inherit; cursor: pointer;
  padding: var(--s1); border-radius: var(--radius-xs); opacity: .7;
}
.announcement-close:hover { opacity: 1; background: var(--surface-2); }

/* ============================================================
   Lazy-render + skeleton polish (public)
   ============================================================ */
/* NB: no content-visibility here. Its implicit paint containment clipped the
   translateY hover lift (first/last-row borders and edge shadows). The grids
   are tiny (<=8 cards) so lazy rendering bought nothing anyway. */
.friend-links-grid {
  content-visibility: auto;
  contain-intrinsic-size: auto 1200px;
}
.home-sec { content-visibility: auto; contain-intrinsic-size: auto 180px; }

/* avatar skeleton: shimmer placeholder under the image */
.rec-item-avatar, .latest-card-avatar, .rel-avatar, .entity .avatar img, .profile .avatar img {
  background: linear-gradient(110deg, var(--surface-2) 8%, var(--surface-3) 18%, var(--surface-2) 33%);
  background-size: 200% 100%;
  animation: avatar-shimmer 1.3s linear infinite;
}
img.img-loaded { animation: none; }
@keyframes avatar-shimmer {
  to { background-position-x: -200%; }
}
@media (prefers-reduced-motion: reduce) {
  .rec-item-avatar, .latest-card-avatar, .rel-avatar, .entity .avatar img, .profile .avatar img { animation: none; }
}

/* shuffle indicator: refresh button spins while an htmx swap is in flight */
.refresh-btn.htmx-request i { animation: spin .6s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
/* live search feedback: the magnifier spins while htmx waits for results */
.searchbar.htmx-request .search-icon { animation: spin .8s linear infinite; }
@media (prefers-reduced-motion: reduce) {
  .refresh-btn.htmx-request i { animation: none; }
}

/* --- type-nav layout: left category sidebar + content --- */
.type-layout { display: flex; gap: var(--s4); align-items: flex-start; }
/* Category names drive the width: the zh layout keeps its 165px floor at
   default sizes, while longer English labels (or browser font scaling) grow
   it to fit; capped at 360px so it can never crowd the content, with the
   label ellipsis as the graceful fallback beyond that. */
.type-side {
  width: fit-content; flex: 0 0 auto; min-width: 165px; max-width: 360px;
  position: sticky; top: calc(var(--header-h) + var(--s3));
  max-height: calc(100vh - var(--header-h) - var(--s6));
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md);
  padding: var(--s3);
}
.type-side-title { margin: 0 0 var(--s2); font-size: var(--fs-500); }
.type-side-nav { display: flex; flex-direction: column; gap: 2px; }
.type-side-item { display: flex; align-items: center; gap: var(--s2);
  display: flex; justify-content: space-between; align-items: center; gap: var(--s2);
  padding: var(--s2) var(--s3); border-radius: var(--radius-xs);
  color: var(--text-soft); text-decoration: none; font-size: var(--fs-400);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.type-side-item:hover { background: var(--primary-weak); color: var(--primary); }
.type-side-icon { width: 22px; text-align: center; color: var(--primary); flex: 0 0 auto; font-size: var(--fs-400); }
.type-side-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.type-side-item.active .type-side-icon { color: var(--primary-ink); }
.type-main { flex: 1 1 auto; min-width: 0; }
@media (max-width: 900px) {
  .type-layout { display: block; }
  .type-side { display: none; }
}

/* --- type nav / sub-page polish --- */
.type-side-item.active { background: var(--primary); color: var(--primary-ink); font-weight: 600; }
.type-side-item.active .cnt { color: inherit; opacity: .8; }
.page-title { font-size: var(--fs-700); margin: var(--s3) 0 var(--s4); }

/* --- header / footer / submit adjustments --- */
.topbar-nav { justify-content: center; }
footer.foot { padding: var(--s2) 0; } /* compact footer: collapses the default .wrap paddings below */
footer.foot .wrap { padding-block: 0; }
.footer-link { font-size: var(--fs-300); line-height: 1.2; }
.foot-links { display: flex; justify-content: center; align-items: center; gap: var(--s2); flex-wrap: wrap; }

/* ---------- legacy header (site-head) — kept for non-topbar pages ---------- */
.site-head {
  position: sticky; top: 0; z-index: 20;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  -webkit-backdrop-filter: saturate(140%) blur(10px);
}
.site-head .wrap { display: flex; align-items: center; gap: var(--s5); flex-wrap: wrap; padding: var(--s3) var(--s5); min-height: var(--header-h); }
.brand { font-weight: 750; font-size: 1.6rem; color: var(--text); display: inline-flex; align-items: center; gap: var(--s3); letter-spacing: -.02em; }
.brand:hover { text-decoration: none; }
.brand .logo { color: var(--primary); font-size: 1.1em; line-height: 1; }
body.public .brand .logo { height: 40px; width: 40px; border-radius: var(--radius-md); object-fit: contain; display: block; color: inherit; }
.nav { display: flex; gap: var(--s1); flex-wrap: wrap; margin-left: var(--s5); }
.nav a { color: var(--text-soft); padding: var(--s2) var(--s3); border-radius: var(--radius-full); font-size: var(--fs-400); transition: background var(--dur) var(--ease), color var(--dur) var(--ease); }
.nav a:hover { color: var(--text); background: var(--surface-2); text-decoration: none; }
.nav a.active { color: var(--primary); background: var(--primary-weak); font-weight: 600; }

.toggles { margin-left: auto; display: flex; gap: var(--s2); align-items: center; }
/* text-sized submit button in the header tool group (public `.topbar-tools`
   and the legacy `.toggles` admin group) — auto width so the label never
   overflows the square icon-button box */
.toggles .submit-link, .topbar-tools .submit-link {
  width: auto; height: 38px; padding: 0 var(--s3); border-radius: var(--radius-md);
  font-size: .82rem; font-weight: 650; white-space: nowrap;
  border: 1px solid color-mix(in srgb, var(--primary) 45%, var(--border)); background: color-mix(in srgb, var(--surface) 86%, transparent);
  box-shadow: var(--shadow-xs); color: var(--text-soft);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.toggles .submit-link:hover, .topbar-tools .submit-link:hover { color: var(--text); border-color: color-mix(in srgb, var(--primary) 75%, var(--border)); background: var(--surface); transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; padding: 0; border-radius: var(--radius-md);
  border: 1px solid color-mix(in srgb, var(--primary) 45%, var(--border)); background: color-mix(in srgb, var(--surface) 86%, transparent);
  color: var(--text-soft); cursor: pointer; font: inherit; font-weight: 650; font-size: .82rem;
  box-shadow: var(--shadow-xs);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease), background var(--dur) var(--ease), transform .12s var(--ease), box-shadow var(--dur) var(--ease);
}
.toggle:hover { color: var(--text); border-color: color-mix(in srgb, var(--primary) 75%, var(--border)); background: var(--surface); transform: translateY(-1px); box-shadow: var(--shadow-sm); }
.toggle:active { transform: translateY(0); }
.toggle svg { width: 19px; height: 19px; display: block; }
.lang-toggle { width: 38px; height: 38px; border-radius: var(--radius-md); letter-spacing: .03em; }
.theme-toggle .i-sun { fill: none; stroke: currentColor; stroke-width: 1.7; }
.theme-toggle .i-moon { fill: currentColor; stroke: none; }
.theme-toggle .i-sun { display: none; }
.theme-toggle .i-moon { display: block; }
html.theme-dark .theme-toggle .i-sun { display: block; }
html.theme-dark .theme-toggle .i-moon { display: none; }
@media (prefers-color-scheme: dark) {
  html:not(.theme-light) .theme-toggle .i-sun { display: block; }
  html:not(.theme-light) .theme-toggle .i-moon { display: none; }
}

.searchbar { display: flex; gap: var(--s2); align-items: center; width: 100%; max-width: 560px; }
.searchbar input {
  flex: 1 1 auto; min-width: 0;
  padding: var(--s2) var(--s4); border: 1px solid color-mix(in srgb, var(--primary) 45%, var(--border)); border-radius: var(--radius-full);
  background: var(--surface); color: var(--text); font: inherit;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.searchbar input:focus { outline: 2px solid transparent; border-color: var(--primary); box-shadow: 0 0 0 4px var(--ring); }
.searchbar button, .searchbar .btn { white-space: nowrap; }

/* ---------- dashboard: full-width charts + 2-col pie grid ---------- */
.dash-panel-wide { width: 100%; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--s4); margin-bottom: var(--s4); min-width: 0; }
.dash-panel-wide h2 { font-size: var(--fs-500); margin: 0 0 var(--s3); }
.dash-panel-wide svg { display: block; margin: 0 auto; max-width: 100%; height: auto; }
.dash-grid-c2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s4); }
.dash-grid-c1 { display: grid; grid-template-columns: 1fr; gap: var(--s4); }
.dash-grid-c2 .dash-panel { display: flex; flex-direction: column; align-items: center; text-align: center; }
.dash-grid-c2 .dash-panel h2 { align-self: flex-start; }
.dash-grid-c2 .dash-panel > svg { max-width: 100%; height: auto; }
.dash-legend { list-style: none; display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 16px; margin: var(--s3) 0 0; padding: 0; }
.dash-legend li { display: flex; align-items: center; gap: 6px; font-size: var(--fs-300); color: var(--text-soft); white-space: nowrap; }
@media (max-width: 760px) {
  .dash-grid-c2 { grid-template-columns: 1fr; }
}

/* respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition: none !important; animation: none !important; }
   .friend-link-card:hover, .ad-card:hover,
  .latest-card-item:hover, .latest-card-item:active,
  .rel-card:hover, .rel-card:active { transform: none; }
}

/* --- mobile touch targets (>=44px) for high-frequency controls --- */
@media (max-width: 760px) {
  .refresh-btn { min-height: 44px; min-width: 44px; justify-content: center; }
  .announcement-close { min-width: 44px; min-height: 44px; }
  .toggle { width: 44px; height: 44px; }
  .pager .btn { min-height: 44px; }
  .pager-jump input, .pager-jump .btn { min-height: 44px; }
}

/* error page (bilingual 404/410/500) */
.errpage { text-align: center; }
.errpage h1 { font-size: var(--fs-700); }
