
*{box-sizing:border-box;margin:0;padding:0}
:root{--fg:#16161a;--muted:#6b6b76;--line:#e8e8ec;--bg:#fff;--soft:#fafafa;
 --accent:#6d28d9;--accent-soft:#f5f3ff;--new:#16a34a;
 --star:#b45309;
 /* Colours that used to be written inline. Each holds byte-for-byte the value it replaced, so
    naming them cannot move the light rendering; they exist so the dark block further down has
    something to reassign. Light stays the default and stays the fallback. */
 --card:#fff;--fg2:#333;--fg3:#3d3d47;--line2:#f4f4f7;--ico-bg:#f1f0f5;
 --on-accent:#fff;--on-tile:#fff;--new-bg:#dcfce7;--new-fg:#15803d;
 --hdr:rgba(255,255,255,.92);--accent-shadow:rgba(109,40,217,.08);
 /* --- P1 design-system tokens (2026-10-15, "purple tide"): new palette radii/shadows/motion --- */
 --brand:#6d28d9;--brand-deep:#4c1d95;--brand-soft:#ede9fe;
 --accent-orange:#f59e0b;--success:#16a34a;
 --r-lg:12px;--r-md:8px;--r-sm:6px;
 --sh-card:0 1px 2px rgba(15,23,42,.05);
 --sh-hover:0 10px 24px -6px rgba(76,29,149,.14);
 --tr:150ms cubic-bezier(.4,0,.2,1)}
html{-webkit-text-size-adjust:100%;color-scheme:light dark}
/* Dark mode, in two halves.
   1. Automatic: it follows the operating system. The :not([data-theme="light"]) guard is what
      lets an explicit Light choice beat a dark OS - without it the toggle could never win, and
      without the media query a visitor who never touches the button still gets dark.
   2. Manual: the same palette, applied when someone on a light OS asks for dark.
   Both halves only REASSIGN the variables declared above. Not one rule below this line differs
   between the two themes, which is why dark mode cannot move the layout.
   Contrast, WCAG 2.1, computed in contrast-check.py: body 15.2:1, muted 7.2:1, accent 8.3:1 on
   the page / 6.8:1 on --accent-soft, button label 8.6:1, new-tag 7.8:1, status dot 8.9:1. The
   roles are the light palette's, not new ones: #17171c / #1d1d24 sit where #fff / #fafafa sat,
   and the accent lightens to #b7a4fb because #6d28d9 on a dark ground measures 2.4:1.
   --on-tile is deliberately absent here: the letter tile carries its own saturated background,
   so its white letter is correct in both themes and inverting it would be the bug. */
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
 --bg:#17171c;--soft:#212129;--card:#1d1d24;--fg:#ececf1;--fg2:#d8d8e0;--fg3:#c9c9d3;
 --muted:#a3a3b0;--line:#32323d;--line2:#282832;--ico-bg:#2a2a34;--accent:#b7a4fb;
 --accent-soft:#292347;--on-accent:#14121d;--new:#3ecf7a;--new-bg:#12331f;--new-fg:#5dd98d;
 --hdr:rgba(23,23,28,.92);--accent-shadow:rgba(183,164,251,.10);--star:#fbbf24;
 /* P1 new tokens, dark reassignment (both halves must stay in sync) */
 --brand:#b7a4fb;--brand-deep:#6d28d9;--brand-soft:#292347;
 --accent-orange:#fbbf24;--success:#3ecf7a;
 --r-lg:12px;--r-md:8px;--r-sm:6px;
 --sh-card:0 1px 2px rgba(0,0,0,.30);
 --sh-hover:0 10px 24px -6px rgba(0,0,0,.55);
 --tr:150ms cubic-bezier(.4,0,.2,1)}}
html[data-theme="dark"]{color-scheme:dark;
 --bg:#17171c;--soft:#212129;--card:#1d1d24;--fg:#ececf1;--fg2:#d8d8e0;--fg3:#c9c9d3;
 --muted:#a3a3b0;--line:#32323d;--line2:#282832;--ico-bg:#2a2a34;--accent:#b7a4fb;
 --accent-soft:#292347;--on-accent:#14121d;--new:#3ecf7a;--new-bg:#12331f;--new-fg:#5dd98d;
 --hdr:rgba(23,23,28,.92);--accent-shadow:rgba(183,164,251,.10);--star:#fbbf24;
 /* P1 new tokens, dark reassignment (both halves must stay in sync) */
 --brand:#b7a4fb;--brand-deep:#6d28d9;--brand-soft:#292347;
 --accent-orange:#fbbf24;--success:#3ecf7a;
 --r-lg:12px;--r-md:8px;--r-sm:6px;
 --sh-card:0 1px 2px rgba(0,0,0,.30);
 --sh-hover:0 10px 24px -6px rgba(0,0,0,.55);
 --tr:150ms cubic-bezier(.4,0,.2,1)}
html[data-theme="light"]{color-scheme:light}
body{font:16px/1.6 -apple-system,BlinkMacSystemFont,'Segoe UI','PingFang SC','Hiragino Sans GB','Microsoft YaHei',sans-serif;
 color:var(--fg);background:var(--bg)}
.mono{font-family:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace}
a{color:inherit;text-decoration:none}
a:hover{color:var(--accent)}
/* Container width, in three steps instead of one 1180px cap. Measured live: a 2560px
   viewport drew the content 1,180px wide and left 690px of dead ground on each side, so
   more than half the screen was unused; even at 1920px it was 370px a side. The steps
   stop at 1,560px on purpose - the widest block on this page is a list row, and beyond
   that the name column keeps stretching without the row gaining any content, which is
   the line-length limit a directory page is supposed to respect anyway. The gutter is a
   clamp so it shrinks with the screen instead of eating it on a phone. */
.wrap{width:100%;max-width:1200px;margin:0 auto;padding:0 clamp(16px,2.2vw,26px)}
@media(min-width:1500px){.wrap{max-width:1360px}}
@media(min-width:1900px){.wrap{max-width:1560px}}
header{border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--hdr);
 backdrop-filter:blur(10px);z-index:30}
.hd{display:flex;align-items:center;justify-content:space-between;height:58px}
.brand{display:flex;align-items:center;gap:9px;font-weight:650;font-size:16px}
.brand svg{width:18px;height:18px}
nav.top{display:flex;gap:4px;align-items:center}
/* The four categories are the site's main entrances. At 13px muted grey they read as fine print -
   everything around them was louder (36px h1, filled CTA). Bigger, in the foreground colour, with an
   icon, so the way in is visible. The active item keeps the accent so "where am I" still differs
   from "what is here". */
/* The h1 states the claim; it does not need to fill the screen. It was two lines of 36px bold -
   about 90px of the page's most valuable space restating what the page is. */
h1.sm{font-size:23px;line-height:1.34;max-width:780px;font-weight:700;letter-spacing:-.01em}
/* Four categories as targets in the hero. Four does not need a sidebar: glama's left column holds
   31 filters, this holds four destinations that each have their own page. */
.catnav{display:grid;grid-template-columns:repeat(auto-fit,minmax(218px,1fr));gap:12px;
  margin:20px 0 4px;
  /* task-10（监工方案 B）：这里原来有 max-width:920px，task-8 改成
     clamp(920px,78%,1320px)，但 78% 是相对内容盒 1508px 解析的 ⇒ 仍是 1176px，
     比同屏 .st-grid/.statband 的 1508 窄 332px（实测 x 都是 526，右边空一截）。
     拉满：4 张卡各 368px，与 .statband 的 368px 完全同宽同列。
     窄屏靠 .st-quick 自己的 @media(max-width:760px)/(max-width:440px) 回落，不受影响。 */
  max-width:none}
.catcard{display:flex;align-items:center;gap:11px;padding:13px 15px;border:1px solid var(--line);
  border-radius:12px;background:var(--card);text-decoration:none;color:var(--fg);min-width:0;
  box-shadow:var(--sh-card);transition:transform var(--tr),box-shadow var(--tr),border-color var(--tr)}
.catcard:hover{border-color:var(--brand);box-shadow:var(--sh-hover);transform:translateY(-2px)}
.catcard .ccic{display:inline-flex;width:30px;height:30px;flex:0 0 30px;align-items:center;
  justify-content:center;border-radius:9px;background:var(--brand-soft);color:var(--brand)}
.catcard .ccic svg{width:18px;height:18px}
.catcard .ccbrand{display:inline-flex;width:30px;height:30px;flex:0 0 30px;align-items:center;
  justify-content:center;border-radius:9px}
.catcard .ccbrand svg{width:18px;height:18px}
.catcard .cctx{display:flex;flex-direction:column;min-width:0}
.catcard .cctx b{font-size:14.5px;font-weight:650}
.catcard .cctx i{font-size:12px;color:var(--muted);font-style:normal;line-height:1.42}
nav.top a{padding:7px 13px;border-radius:8px;font-size:14px;color:var(--fg);
  display:inline-flex;align-items:center;gap:7px;font-weight:500;transition:background var(--tr),color var(--tr)}
nav.top a .nic{display:inline-flex;width:16px;height:16px;flex:0 0 16px}
nav.top a .nic svg{width:16px;height:16px}
nav.top a:hover{background:var(--brand-soft)}
nav.top a:hover{background:var(--brand-soft);color:var(--brand)}
nav.top a.on{color:var(--accent);background:var(--accent-soft);font-weight:600}
.lang{border:1px solid var(--line);border-radius:7px;padding:5px 12px;font-size:13px}
/* The language link and the theme toggle share the header's right edge, in ONE flex child.
   A fourth child of .hd would re-distribute the space-between gaps and re-flow the navigation;
   the header's own geometry is the only thing this change is allowed to move, and it is
   measured before and after rather than assumed. */
.hdact{display:flex;align-items:center;gap:7px}
/* Header CTA. A directory that never asks to be fed starves: the submit entrance sits in
   the header on every page, in accent, because a commercial site puts its growth loop
   where the eye already is. Anchors to #submitform - the honeypot form on the homepage,
   which keeps its id across builds. Hidden with the nav on phones; the tab bar carries
   the mobile entrances instead. */
.cta{background:linear-gradient(135deg,var(--accent),var(--brand-deep));color:var(--on-accent);font-size:13px;font-weight:600;
 padding:7px 14px;border-radius:8px;margin-left:8px;transition:filter var(--tr),box-shadow var(--tr)}
.cta:hover{color:var(--on-accent);filter:brightness(1.07);box-shadow:0 6px 16px -6px var(--accent-shadow)}
@media(max-width:820px){.cta{display:none}}
.tgl{display:flex;align-items:center;justify-content:center;border:1px solid var(--line);
 border-radius:7px;padding:6px 7px;background:none;color:var(--muted);cursor:pointer;line-height:0}
.tgl:hover{border-color:var(--accent);color:var(--accent)}
.tgl svg{width:18px;height:18px;display:block}
.tgl:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* --- 焦点可见性基线（task-9）。实测（Tab 遍历 + 计算样式，1440/390 两档）：
   全页 140 个可聚焦元素里，只有 1 个有显式焦点样式，其余 139 个只靠浏览器默认的
   outline:auto 1px rgb(16,16,16) —— 近黑 1px，在暗底（#17171c）上几乎看不见。
   这一条就是"焦点样式体系"的起点；特异性为 0（伪类），所以不会覆盖任何已有规则：
     .search input:focus 的 box-shadow、.tgl:focus-visible、.cmdk/.st-cmdk 的
     :focus-within 都照旧生效，只是把没有样式的那些补上。
   用 :focus-visible 而非 :focus：鼠标点击不画轮廓、键盘才画。
   var(--brand) 暗色会重映射 #6d28d9→#b7a4fb，实测对比度浅底 7.10:1、暗底 8.26:1
   （WCAG 焦点指示要求 ≥3:1）。outline 不占布局 ⇒ 不影响尺寸、不会引起横向溢出。 */
:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:inherit}
/* Which icon shows follows the EFFECTIVE theme, not the stored choice: with nothing stored the
   page follows the OS, so the button has to show the OS's state too. data-mode is set by the
   head script. With no script at all the moon is shown - "switch to dark" - never both icons. */
.tgl .i-sun{display:none}
html[data-mode="dark"] .tgl .i-sun{display:block}
html[data-mode="dark"] .tgl .i-moon{display:none}
/* The repository a star count was read from. Deliberately link-coloured: on the stars board
   this is the entire evidence for the number in the same row. */
a.repolink{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11.5px;
 color:var(--accent);background:var(--accent-soft);border-radius:5px;padding:1px 6px;
 text-decoration:none;white-space:nowrap}
a.repolink:hover{text-decoration:underline}

.hero{padding:18px 0 12px;border-bottom:1px solid var(--line)}
.crumb{font-size:13px;color:var(--muted);margin-bottom:0}
.crumb a{color:var(--muted)}
h1{font-size:clamp(26px,3.6vw,38px);line-height:1.2;font-weight:680;letter-spacing:-.02em;margin-bottom:10px}
.hero p{color:var(--muted);max-width:660px;font-size:16px}
.hero p a{color:var(--muted)}
.hero p b{color:var(--fg);font-weight:650}
.search{display:flex;gap:8px;max-width:560px;margin-top:12px}
.search input{flex:1;padding:11px 15px;border:1px solid var(--line);border-radius:9px;font:inherit;
 outline:0;transition:border-color .18s,box-shadow .18s}
.search input:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.search button{padding:0 20px;border:0;border-radius:9px;background:var(--accent);color:var(--on-accent);
 font:inherit;font-weight:600;cursor:pointer}
.search button:hover{filter:brightness(1.08)}

.tally{display:flex;gap:28px;flex-wrap:wrap;padding:10px 0;border-bottom:1px solid var(--line);font-size:13px;line-height:1.4}
.tally b{font-weight:650}
.tally span{color:var(--muted)}

.fields{display:flex;gap:7px;flex-wrap:wrap;padding:13px 0 4px}
.chip{border:1px solid var(--line);border-radius:999px;padding:5px 13px;font-size:13px;
 color:var(--muted);cursor:pointer;transition:all .16s;background:var(--card)}
.chip:hover{border-color:var(--accent);color:var(--accent);background:var(--brand-soft)}
.chip.on{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}

section{padding:17px 0}
h2{font-size:14px;font-weight:650;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;
 margin-bottom:14px}
.secnote{font-size:12px;color:var(--muted);margin:-6px 0 12px}
.rowmore{text-align:right;padding:11px 14px 2px;font-size:13px}
.rows{border:1px solid var(--line);border-radius:11px;overflow:hidden;box-shadow:var(--sh-card)}
.row{display:grid;grid-template-columns:minmax(0,1fr) 120px 84px;gap:12px;align-items:center;padding:11px 14px}
.row a{display:block;width:100%;min-width:0}
.row .lead{display:flex;gap:10px;align-items:center;min-width:0}
.row .lead>div{min-width:0;flex:1}
.row:last-child{border-bottom:0}
.row:hover{background:var(--soft)}
.row+.row{border-top:1px solid var(--line2)}
.ico{width:22px;height:22px;border-radius:6px;object-fit:cover;background:var(--ico-bg);flex:none;display:block}
.ico.fb{display:flex;align-items:center;justify-content:center;font-weight:650;font-size:12px;color:var(--on-tile)}
.row .lead{display:flex;gap:11px;align-items:flex-start}
.row .lead>div{min-width:0}
.row .nm{font-weight:600;font-size:15px;line-height:20px}
.row .nm{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.row .nm .mono{white-space:nowrap}
.row .nm .mono{font-weight:500;font-size:12px;color:var(--muted);display:inline-block;vertical-align:1px;line-height:1}
/* task-84: README 引用区块。行高放宽以便长文可读；上边线做区隔。 */
.rd{margin-top:20px;padding-top:16px;border-top:1px solid var(--line)}
.rd h2{font-size:16px;margin:0 0 6px}
.rdnote{color:var(--muted);font-size:12.5px;margin:0 0 10px}
.rdbody{line-height:1.7;font-size:14.5px;white-space:normal;word-break:break-word}
/* task-81: 数据来源与时效区块 —— 与既有属性表同形，加一条上边线做区隔。 */
.prov{margin-top:14px;padding-top:12px;border-top:1px solid var(--line)}
.prov dt{color:var(--muted)}
.prov dd .mono{font-size:12px}
/* task-76: 源标签与条目名之间加一个分隔符 ' · '。
   实测（浏览器里量的）: 原来 margin-right 已有 7px，但 7px 在 15px 字旁读起来仍像连在一起，
   于是 "awesome" + "rohitg00/kubectl-mcp-server" 被读成 "awesomerohitg00/kubectl-mcp-server"。
   ★ 用 ::after 而不是在 HTML 里插文本: ::after 生成的是伪元素，不会被
     .nm 的 text-overflow:ellipsis 裁掉（ellipsis 只作用于文本节点）。 */
.row .nm .mono{margin-right:4px}
.row .nm .mono::after{content:'\00a0\00b7';color:var(--muted);opacity:.65}
/* task-77: 窄屏隐藏源标签，把空间让给【条目名】本身。
   实测（390px 视口）: .row .nm 宽 218px，而标签 'awesome' + margin 占 66px（30%），
   于是那一行只能显示 'aweso…' —— 用户看不到条目名。
   4/4 行被截断，其中 3 行【去掉标签就能完整显示】。
   ★ 标签信息量低（只显示源名第一段，如 'awesome'；完整来源在详情页"来源"区），
     所以窄屏隐藏它【不是丢信息，是把空间还给内容】。 */
@media(max-width:820px){.row .nm .mono{display:none}}
/* The description line carries the field tags at its end. As plain inline content inside a
   nowrap/overflow:hidden box, text-overflow:ellipsis never reached them: it only applies to
   inline text, and a .tag is an inline-block, so the tags kept marching right and were cut
   off by the box instead. Measured live at 390px: twelve tags with their right edge at up to
   805px on a 390px viewport, i.e. invisible - not a scrollbar, the field names were simply
   gone, which is the only place on a row that says what kind of tool it is. The text now
   lives in its own box that takes the ellipsis, and the tags are fixed-width items beside
   it, so a narrow row drops words from the description and keeps both field names. */
.row .ln{font-size:13px;color:var(--muted);margin-top:1px;line-height:17px;
 display:flex;align-items:center;gap:5px;min-width:0}
.row .ln .lntxt{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.row .ln .tag{flex:0 0 auto;line-height:1}
.row .ln.none{color:var(--muted);font-style:italic}
.row .meta{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.row .meta .num{font-weight:650;color:var(--fg)}
.tag{display:inline-block;font-size:12px;padding:1.5px 7px;border-radius:var(--r-sm);
 background:var(--soft);color:var(--muted);margin-right:5px}
.tag.new{background:var(--new-bg);color:var(--new-fg);font-weight:600}
.tag.gold{background:rgba(245,158,11,.14);color:var(--accent-orange);font-weight:600}
.row .tag{margin-right:5px}
.row .lead .ln .tag:last-child{margin-right:6px}
/* A link drawn INSIDE a row line has to stay on that line. `.row a{display:block;width:100%}`
   was written for the row's single wrapper link; on the stars board the provenance link lives
   in the name line, and block display gave each one its own line of text - measured at a
   137.3px row. Scoped to links inside .nm/.ln, which no other page puts there. */
.row .nm a,.row .ln a{display:inline;width:auto}
/* The provenance chip is a 1px-padded inline-block. Left at the line's 20px it measures 22px,
   and an inline-block taller than the strut grows the whole line box: the stars board came out
   at 62/63px while every other board was 61px. A shorter line-height inside the chip keeps the
   row identical to the rest of the site without hiding the link. */
.row a.repolink{line-height:16px}
.pager{display:flex;gap:6px;flex-wrap:wrap;align-items:center;padding:18px 0 4px;font-size:13px}
.pager a{padding:5px 11px;border:1px solid var(--line);border-radius:7px;color:var(--muted)}
.pager a:hover{border-color:var(--accent);color:var(--accent)}
.pager a.on{background:var(--accent);border-color:var(--accent);color:var(--on-accent);font-weight:600}
.pager .pi{color:var(--muted);padding:5px 4px}

.item{max-width:760px;padding:34px 0 60px}
.item h1{font-size:26px}
.item .lead{font-size:16px;color:var(--fg2);margin:16px 0 22px;padding-left:14px;border-left:3px solid var(--accent)}
.item dl{display:grid;grid-template-columns:110px minmax(0,1fr);gap:9px 16px;font-size:13px;margin:22px 0}
.item dt{color:var(--muted)}
.item dd{overflow-wrap:anywhere}
.copy{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--line);background:var(--card);
 border-radius:8px;padding:8px 14px;font:inherit;font-size:13px;cursor:pointer;margin-top:6px}
.copy:hover{border-color:var(--accent);color:var(--accent)}
.copy code{font-family:'JetBrains Mono',monospace;font-size:13px}

footer{border-top:1px solid var(--line);margin-top:34px;padding:30px 0 40px;
 color:var(--muted);font-size:13px;box-shadow:inset 0 3px 0 -2px var(--brand)}
footer .wrap{display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
/* Homepage footer is a multi-column site footer; the simple .wrap flex rule above is for
   the two-line footers of detail/board pages, so this page gets its own wrapper class
   (0,2,0 beats .footer .wrap at 0,1,1). */
.wrap.fwrap{display:block}
.fcols{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1fr) minmax(0,1fr);gap:28px;padding-bottom:24px}
.fbrand{font-weight:700;font-size:15.5px;color:var(--fg);margin-bottom:9px}
.fcol p{font-size:12.5px;line-height:1.65;margin:0 0 6px;max-width:430px}
.fcol .fmeta{font-size:12px;opacity:.85}
.fcol h4{font-size:12px;font-weight:650;color:var(--fg);margin-bottom:10px}
.fcol a{display:block;font-size:12.5px;color:var(--muted);padding:3.5px 0}
.fcol a:hover{color:var(--accent)}
.fbar{display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;
 border-top:1px solid var(--line);padding-top:15px;font-size:12px}
@media(max-width:820px){.fcols{grid-template-columns:minmax(0,1fr);gap:20px}}

/* Board grid. It used to be auto-fit/minmax(340px,1fr), which is where the hole came from:
   the number of blocks is not fixed, and auto-fit only ever fits whole columns - it cannot
   fill a short last row. Columns are explicit now, the homepage offers thirteen boards
   (a short one drops itself, so the live count is 12 or 13), and a short last row is closed
   by spanning instead of leaving a gap. Three column counts, each with its own remainder
   rules, because 12 divides by 4 and 3 evenly but 13 is 4n+1 / 3n+1:
     >=1900px  4 columns  (4x3 = 12; the 13th spans the whole last row)
     1180-1900 3 columns  (3x4 = 12; the 13th spans 3)
     <=1180px  2 columns  (2n+1 spans 2)
     <=820px   1 column   (every span withdrawn - see the !important below) */
/* Scenario pages: a shortlist per job. .stiles is the hub grid, .thin marks a group whose
   measured hit count is below three so the page admits it instead of padding. */
/* Compact section strip. The 16 section tiles keep their icon, href and class so the requirement
   they encode ("has an icon, click goes straight in") still holds - they are simply icon buttons
   now, with the name and count moved to title/aria-label. This is what keeps the homepage from
   growing a second screen of cards. */
.sstrip{display:flex;flex-wrap:wrap;gap:8px;padding:6px 0}
.sstrip .stile{width:38px;height:38px;padding:0;display:grid;place-items:center;
  border:1px solid var(--line);border-radius:10px;background:var(--card);color:var(--muted)}
.sstrip .stile:hover{border-color:var(--line2);color:var(--fg)}
.sstrip .stile svg{width:18px;height:18px}
.stiles{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;padding:6px 0}
/* task-10：这里试过 auto-fit，但实测【无效】—— 三页的块数是 21 / 16 / 9：
     2560 → 列=6，行分布 [6,3]，末行填充 0.5
     1440 → 列=4，行分布 [4,4,1]，末行填充 0.25
   auto-fit 只在"轨道数 > 块数"时才折叠空轨道；9 块配 6 条轨道时 6 条全被占，
   一条都不折叠 ⇒ 不留空轨道了，但末行照样塌。
   ⇒ 改用【显式 3 列】：9 = 3×3 满、21 = 3×7 满、16 = 3×5+1（仅此页末行 1 个）。
   卡片宽随容器（1440 下 w=1148 → 三列各约 373px；2560 下 1508 → 约 493px），
   与 .stiles 里 .sname/.sdesc 这种多行文本卡相称，不会过宽。
   窄屏回落见下面两条 media。
   ★ 16 块的那两页（/en/section/ · /zh/section/，已全站核查：块数分布 {21:2,16:2,9:2}）
     在 3 列下是 3×5+1，末行只剩一个、右边空两列（实测填充 0.333）。
     我试过两种收尾：
       a) 让最后一块 span 3（撑满末行）—— 填充率到 1.0，但那一块被拉成 1148px 宽，
          它的名字与计数分居左右两端，看起来像个错误元素（我截图目视过，不好看）。
       b) 这几页改用 4 列：16 = 4×4 整除 ⇒ 末行满且每块仍一样宽。
     选 b。选择器要【恰好 16 块】：:has(> :nth-child(16)) 单独用会连 21 块那页一起命中
     （它也有第 16 个孩子，实测 21 块页被改成 4 列、末行 [4,4,4,4,4,1] 填充 0.25，更差），
     所以必须再加 :not(:has(> :nth-child(17))) 把它排除。 */
@media(max-width:760px){.stiles{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:440px){.stiles{grid-template-columns:minmax(0,1fr)}}
.stiles:has(> :nth-child(16)):not(:has(> :nth-child(17))){grid-template-columns:repeat(4,minmax(0,1fr))}
@media(max-width:760px){.stiles:has(> :nth-child(16)):not(:has(> :nth-child(17))){grid-template-columns:repeat(2,minmax(0,1fr))}}
/* task-10（监工派单）：原为 auto-fill，与 .st-grid 同一根因 —— auto-fill 会先开出
   所有能放下的轨道再摆块，于是"块数 < 轨道数"时右侧留下空轨道。
   实测容器 1508px 下 minmax(230px,1fr) 会开出 6 条轨道，块少时右侧留空。
   auto-fit 折叠空轨道；"块数 ≥ 轨道数"时两者行为相同 ⇒ 对填满的页面零影响。
   作用页：/en/r/ · /en/section/ · /en/scene/（首页无此元素）。 */
.stiles .stile{display:flex;flex-direction:column;gap:4px;border:1px solid var(--line);
  border-radius:12px;padding:14px 16px;background:var(--card);text-decoration:none;min-width:0;
  box-shadow:var(--sh-card);transition:transform var(--tr),box-shadow var(--tr),border-color var(--tr)}
.stiles .stile:hover{border-color:var(--line2);box-shadow:var(--sh-hover);transform:translateY(-2px)}
.stiles .sname{font-weight:650;font-size:15px}
.stiles .scount{font-size:12px;color:var(--muted)}
.stiles .sdesc{font-size:12px;color:var(--muted);line-height:1.45}
.thin{font-size:11px;font-weight:400;color:var(--muted);margin-left:8px}
.bgrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;padding:6px 0 0}
.bgrid> :last-child:nth-child(3n+2){grid-column:span 2}
.bgrid> :last-child:nth-child(3n+1){grid-column:span 3}
/* Four blocks on a 2x2 grid reads better than one card stretched across three columns -
   but only below 1900px, where three or four columns would each be too narrow to hold a
   board's name and metric on one line. On a wide screen four boards belong in one row. */
@media(max-width:1899px){
 @supports selector(:has(*)){
  .bgrid:has(> :last-child:nth-child(4)){grid-template-columns:repeat(2,minmax(0,1fr))}
  .bgrid:has(> :last-child:nth-child(4))> :last-child{grid-column:auto}}}
/* Wide screens: four columns. The three-column spans must be withdrawn first or they leak
   into this breakpoint; then the four-column remainders do the same job one step wider. */
@media(min-width:1900px){
 .bgrid{grid-template-columns:repeat(4,minmax(0,1fr))}
 .bgrid> :last-child:nth-child(3n+2),.bgrid> :last-child:nth-child(3n+1){grid-column:auto}
 .bgrid> :last-child:nth-child(4n+3){grid-column:span 2}
 .bgrid> :last-child:nth-child(4n+2){grid-column:span 3}
 .bgrid> :last-child:nth-child(4n+1){grid-column:span 4}}
/* Two columns: the same idea with 2n+1, so 5 blocks lay out 2 + 2 + (1 spanning 2). The
   three-column spans must be withdrawn first or they leak into this breakpoint. */
@media(max-width:1180px){
 .bgrid{grid-template-columns:repeat(2,minmax(0,1fr))}
 .bgrid> :last-child:nth-child(3n+2),.bgrid> :last-child:nth-child(3n+1){grid-column:auto}
 .bgrid> :last-child:nth-child(2n+1){grid-column:span 2}}
/* One column: every span rule has to be withdrawn, and it has to be !important to win.
   `.bgrid>*` scores 0,1,0 against 0,3,0 for `.bgrid> :last-child:nth-child(2n+1)`, so a
   plain reset loses to the very rule it is meant to turn off, and a span wider than the
   explicit column count does not clamp - the grid creates an implicit column and the page
   overflows sideways, which is a worse defect than the hole these rules close. */
@media(max-width:820px){.bgrid>*{grid-column:auto!important}}
.bblock{border:1px solid var(--line);border-radius:12px;padding:14px 16px;background:var(--card);min-width:0;
 box-shadow:var(--sh-card);transition:border-color var(--tr),box-shadow var(--tr),transform var(--tr)}
.bblock:hover{border-color:var(--brand);box-shadow:var(--sh-hover);transform:translateY(-2px)}
.bblock h3{display:flex;align-items:center;gap:7px;font-size:13px;font-weight:650;margin-bottom:10px}
/* One mark per board, so the six blocks can be told apart before reading a heading. The
   two star-shaped ones are deliberately different: 'pick' is a bookmark (a curated entry),
   'stars' is the star the GitHub count is measured in. */
.bico{width:22px;height:22px;flex:none;display:flex;align-items:center;justify-content:center;
 border-radius:7px;background:var(--brand-soft);color:var(--brand)}
.bico svg{width:14px;height:14px}
.brows{display:flex;flex-direction:column;min-width:0}
.brow{display:flex;gap:10px;align-items:center;padding:4px 0;min-width:0;border-bottom:1px solid var(--line2);
 transition:background var(--tr)}
.brow:last-child{border-bottom:0}
.brow:hover{background:var(--brand-soft)}
/* The #1 row leads the board: glama and toolify both weight it visually. A left accent bar,
   a bigger name and a coloured rank do it without touching row geometry, so the 5-row block
   keeps its exact height. Scoped to rows that carry a real rank number - an empty-state row
   (.brow.empty) must not wear a winner's bar. */
.brow:first-child{position:relative;padding-left:10px}
.brow:first-child::before{content:"";position:absolute;left:0;top:4px;bottom:4px;width:3px;
 border-radius:2px;background:var(--accent)}
.brow:first-child .rk{color:var(--accent);font-weight:700}
.brow:first-child .bnm{font-size:14px}
.brow.empty::before{display:none}
.rk{width:16px;flex:none;color:var(--muted);font-size:12px;font-weight:650;
 font-family:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace}
.bnm{font-size:13px;font-weight:600;line-height:18px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bln{font-size:12px;color:var(--muted);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;line-height:1.32;min-height:calc(1.32em * 2)}
.bmeta{flex:none;font-size:12px;color:var(--muted);text-align:right}
.bmore{text-align:right;padding-top:6px;font-size:13px}

.statusline{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:9px 14px;
 background:var(--soft);border:1px solid var(--line);border-radius:999px;font-size:13px;
 color:var(--muted);margin-bottom:0;width:fit-content}
.statusline .dot{width:7px;height:7px;border-radius:50%;background:var(--new);flex:none}
.status-head{margin-bottom:16px}
.statusline b{color:var(--fg);font-weight:600}

/* Section tiles: explicit 4 / 2 / 1 instead of auto-fill. auto-fill fits whole columns and
   then leaves the remainder of the last row empty, which at 1560px put eight tiles in a row
   of six plus a row of two - four visible holes on the widest screens. Four columns makes the
   eight sections two clean rows; at two columns they are four clean rows. The three steps are
   chosen so the current section count (8, even) always divides evenly. */
.sgrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;padding:6px 0 2px}
@media(max-width:1100px){.sgrid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:520px){.sgrid{grid-template-columns:minmax(0,1fr)}}
.stile{display:flex;align-items:center;gap:8px;padding:12px 10px;border:1px solid var(--line);
 border-radius:11px;background:var(--card);transition:border-color .16s,box-shadow .16s,transform .16s}
.stile:hover{border-color:var(--accent);box-shadow:0 2px 10px var(--accent-shadow);transform:translateY(-1px);color:inherit}
.sico{width:30px;height:30px;flex:none;display:flex;align-items:center;justify-content:center;
 border-radius:9px;background:var(--brand-soft);color:var(--brand)}
.sico svg{width:19px;height:19px}
/* Brand tiles carry their own saturated background, so the soft-wash treatment above
   must not tint them. The inset ring separates dark tiles from a dark page. */
.sico.brand{box-shadow:inset 0 0 0 1px rgba(128,128,150,.28)}
.sname{font-size:12px;font-weight:600;flex:none;min-width:0;white-space:nowrap}
.scount{font-size:12px;color:var(--muted);flex:none;margin-left:auto}
/* --- redesign additions (2026-10-12): star colour, hero, badges, actions, tab bar, ⌘K, save --- */
.st{color:var(--star);font-weight:650}
.row .meta .st{font-weight:600}
.hero{padding:30px 0 10px}
.hero h1{font-size:clamp(28px,3.8vw,42px);line-height:1.14;font-weight:720;letter-spacing:-.025em;margin-bottom:12px;max-width:780px}
.hero .sub{color:var(--muted);font-size:16px;max-width:660px;margin-bottom:20px}
.hero .sub b{color:var(--fg2);font-weight:650}
.searchbig{display:flex;gap:9px;max-width:760px;margin-bottom:24px}
.searchbig .field{flex:1;min-height:52px;display:flex;align-items:center;gap:10px;border:1px solid var(--line);
 background:var(--card);border-radius:12px;padding:0 15px;height:48px;transition:border-color var(--tr),box-shadow var(--tr)}
.searchbig .field:focus-within{border-color:var(--brand);box-shadow:0 0 0 4px var(--brand-soft)}
.searchbig .field svg{width:17px;height:17px;color:var(--muted);flex:none}
.searchbig .field input{flex:1;border:none;background:none;font:inherit;font-size:16px;color:var(--fg);outline:none;min-width:0;height:48px}
.searchbig .field input::placeholder{color:var(--muted)}
.searchbig .field kbd{margin-left:auto;font-family:inherit;font-size:11px;border:1px solid var(--line);
 border-radius:5px;padding:2px 6px;background:var(--soft);color:var(--muted);cursor:pointer}
.statband{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:4px 0 8px}
.stat{border:1px solid var(--line);background:var(--card);border-radius:11px;padding:13px 16px;
 box-shadow:var(--sh-card)}
.stat .n{font-size:23px;font-weight:720;letter-spacing:-.02em;font-variant-numeric:tabular-nums;
 font-family:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace}
.stat .n em{font-style:normal;color:var(--new);font-size:12.5px;font-weight:650;margin-left:6px}
.stat .l{font-size:12.5px;color:var(--muted);margin-top:2px}
.badges{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:12px}
.item .actions{display:flex;gap:9px;flex-wrap:wrap;margin:16px 0 22px}
.btn{display:inline-flex;align-items:center;gap:7px;border:0;border-radius:9px;background:var(--accent);
 color:var(--on-accent);font:inherit;font-size:13px;font-weight:650;padding:9px 15px;cursor:pointer;
 transition:filter var(--tr),box-shadow var(--tr)}
.btn:hover{filter:brightness(1.08)}
.btn.ghost{background:none;border:1px solid var(--line);color:var(--fg2)}
.btn.ghost:hover{border-color:var(--accent);color:var(--accent);filter:none}
.btn.ghost.on{border-color:var(--star);color:var(--star)}
.btn code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12.5px}
.fav{flex:none;border:none;background:none;cursor:pointer;color:var(--muted);padding:4px 6px;line-height:0;border-radius:6px}
.fav:hover{color:var(--star);background:var(--soft)}
.fav.on{color:var(--star)}
.fav svg{width:14px;height:14px}
.cmdk{position:fixed;inset:0;background:rgba(15,15,22,.44);backdrop-filter:blur(3px);z-index:100;
 display:none;align-items:flex-start;justify-content:center;padding:12vh 20px 20px}
.cmdk.open{display:flex}
.cmdk .panel{width:min(640px,100%);background:var(--card);border:1px solid var(--line);border-radius:var(--r-lg);
 box-shadow:0 2px 6px rgba(20,20,30,.06),0 16px 44px rgba(20,20,30,.16);overflow:hidden;animation:pop .16s ease}
@keyframes pop{from{opacity:0;transform:scale(.98) translateY(-6px)}to{opacity:1;transform:none}}
.cmdk .in{display:flex;align-items:center;gap:11px;padding:15px 17px;border-bottom:1px solid var(--line);
 transition:box-shadow var(--tr)}
.cmdk .in:focus-within{box-shadow:inset 0 0 0 2px var(--brand)}
.cmdk .in svg{width:17px;height:17px;color:var(--muted);flex:none}
.cmdk .in input{flex:1;border:none;background:none;font:inherit;font-size:15.5px;color:var(--fg);outline:none}
.cmdk .in kbd{font-family:inherit;font-size:11px;border:1px solid var(--line);border-radius:5px;padding:2px 6px;color:var(--muted)}
.cmdk .list{max-height:46vh;overflow:auto;padding:6px}
.cmdk .grp{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--brand);padding:10px 12px 5px}
.cmdk .it{display:flex;align-items:center;gap:11px;padding:9px 12px;border-radius:9px;cursor:pointer;
 transition:background var(--tr)}
.cmdk .it:hover,.cmdk .it.sel{background:var(--brand-soft)}
.cmdk .it .t{flex:1;min-width:0}
.cmdk .it .t .n{font-size:13.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cmdk .it .t .d{font-size:11.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cmdk .it .r{font-size:11.5px;color:var(--muted);font-variant-numeric:tabular-nums;flex:none;display:flex;align-items:center;gap:6px}
.cmdk .foot{display:flex;gap:12px;padding:9px 15px;border-top:1px solid var(--line);font-size:11.5px;color:var(--muted);flex-wrap:wrap}
.cmdk .foot kbd{font-family:inherit;border:1px solid var(--line);border-radius:4px;padding:0 5px}
.tabbar{display:none;position:fixed;left:0;right:0;bottom:0;background:var(--hdr);backdrop-filter:blur(12px);
 border-top:1px solid var(--line);z-index:50;padding:7px 8px calc(7px + env(safe-area-inset-bottom))}
.tabbar .t{display:flex;justify-content:space-around}
.tabbar a{display:flex;flex-direction:column;align-items:center;gap:3px;font-size:10.5px;color:var(--muted);padding:4px 10px;border-radius:9px;font-weight:550;
 transition:color var(--tr),background var(--tr)}
.tabbar a:hover{color:var(--brand)}
.tabbar a.on{color:var(--accent)}
.tabbar svg{width:19px;height:19px}
@media(max-width:1020px){.statband{grid-template-columns:repeat(2,minmax(0,1fr))}}
/* Narrow rows: two columns, with the name/description spanning both and the metric and the
   date sitting side by side underneath. Dropping to one column put each of them on its own
   line, so a row was four stacked lines tall - measured at 390px, fifteen rows wasted about
   500px on two numbers that fit on one line together. */
@media(max-width:820px){.row{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:2px 12px}
 /* 两列布局：.lead 独占整行（描述宽度最大），星数与日期在其下一行并排。
    这是【为窄屏设计】的形态 —— 见上面 484-487 行的原注。
    task-35: 它在 820 那档的缺点是元信息被推到第二行、且左右两端相距 642.6px；
    所以 621–820 区间改用单行（见下面的规则）。 */
 .row .lead{grid-column:1/-1}
 .row .meta{text-align:left}
 .row .meta:last-child{text-align:right}}
/* task-35: 单行（与桌面同构）只作用在【放得下】的中段 621–820：
     固定开销 = 星数 47 + 日期 32 + 间隔 24 + 内边距 28 ≈ 131px，
     给描述留 >=480px（桌面档 494px 同量级）⇒ 视口 >=621px。
   ★ 实测依据：620 及以下用单行时 .lead 只剩 201–371px、8/8 行描述被截断（比两列差）；
     621 以上 .lead >= 475px，截断数与两列布局持平，而行高从 122.6 降到 94。 */
@media(min-width:621px) and (max-width:820px){.row{grid-template-columns:minmax(0,1fr) auto auto;gap:2px 12px}
 .row .lead{grid-column:auto}
 .row .meta{text-align:right}}
 nav.top{display:none}.tally{gap:18px}
 .tabbar{display:block}body{padding-bottom:66px}
 .searchbig .field kbd{display:none}.bgrid{grid-template-columns:minmax(0,1fr)}
 .infogrid{grid-template-columns:minmax(0,1fr)!important}}

/* ==========================================================================
   P1 · SkillTide 阶段一设计系统升级（2026-10-15，"紫色潮汐"）
   规范 §3：首页新类契约。P2 在 en/zh 首页使用以下类；此处只做视觉，
   不动任何 wiring。所有新 token 已注入 :root 与两处 dark 块。
   ========================================================================== */

/* --- .st-hero：hero 容器 + 背景光晕 --- */
.st-hero{position:relative;overflow:hidden;padding:44px 0 26px;border-bottom:1px solid var(--line)}
.st-hero .st-glow{position:absolute;inset:0;pointer-events:none;
 background:radial-gradient(620px 260px at 16% -10%,rgba(109,40,217,.14),transparent 70%),
            radial-gradient(520px 220px at 88% 0%,rgba(245,158,11,.10),transparent 70%)}
html[data-mode="dark"] .st-hero .st-glow{
 background:radial-gradient(620px 260px at 16% -10%,rgba(183,164,251,.16),transparent 70%),
            radial-gradient(520px 220px at 88% 0%,rgba(251,191,36,.10),transparent 70%)}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .st-hero .st-glow{
 background:radial-gradient(620px 260px at 16% -10%,rgba(183,164,251,.16),transparent 70%),
            radial-gradient(520px 220px at 88% 0%,rgba(251,191,36,.10),transparent 70%)}}
.st-hero-eyebrow{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:650;
 color:var(--brand);background:var(--brand-soft);border-radius:var(--r-sm);padding:4px 11px;margin-bottom:14px}
.st-hero-title{font-size:clamp(30px,4.2vw,46px);line-height:1.12;font-weight:760;letter-spacing:-.025em;
 max-width:820px;margin-bottom:14px;
 background:linear-gradient(120deg,var(--fg) 55%,var(--brand) 100%);
 -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.st-hero-sub{color:var(--muted);font-size:16px;max-width:660px;line-height:1.65}

/* --- .st-quick：快捷入口容器（.catnav 的卡片网格化），item 即 .catcard --- */
/* 效果图（2026-10-15 EN/ZH 版）里四张快捷卡是 2x2 大卡，不是一行四张小的。
   改 .st-quick 而不是 .catnav —— 后者会被这里盖掉（同特异性、后定义）。 */
/* 效果图里四张快捷卡是【一行 4 张】（卡片区只占约 75px 高，榜块紧随其后）。
   我上一轮按"2x2"改过，是看错了 —— 改回一行。窄屏才回落单列。 */
.st-quick{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:12px;margin:18px 0 4px}
/* task-10：显式 4 列，与 .statband 同构（它也是 repeat(4,minmax(0,1fr))）。
   原为 repeat(auto-fit,minmax(200px,1fr))，实测 2560 下的列值来自
   .catnav 的 minmax(218px,1fr) 与容器宽的相互作用，不是显式声明 —— 不稳定的来源。
   窄屏仍由下面两条 media 回落（≤760px 两列、≤440px 一列），4 列只在 ≥761px 生效。 */
@media(max-width:760px){.st-quick{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:440px){.st-quick{grid-template-columns:minmax(0,1fr)}}
.st-quick-item{display:flex;align-items:center;gap:11px;padding:14px 16px;border:1px solid var(--line);
 border-radius:var(--r-lg);background:var(--card);box-shadow:var(--sh-card);text-decoration:none;color:var(--fg);min-width:0;
 transition:transform var(--tr),box-shadow var(--tr),border-color var(--tr)}
.st-quick-item:hover{border-color:var(--brand);box-shadow:var(--sh-hover);transform:translateY(-2px)}

/* --- .st-stat：统计数字升级载体 --- */
.st-stat{border:1px solid var(--line);background:var(--card);border-radius:var(--r-lg);
 padding:14px 16px;box-shadow:var(--sh-card)}
.st-stat .n,.st-stat .st-n{font-family:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
 font-size:24px;font-weight:720;letter-spacing:-.02em;font-variant-numeric:tabular-nums;color:var(--brand)}
.st-stat .l{font-size:12.5px;color:var(--muted);margin-top:2px}

/* --- .st-section：板块容器 + 品牌紫装饰线标题 --- */
.st-section{padding:22px 0}
.st-section-title{display:flex;align-items:center;gap:9px;font-size:15px;font-weight:700;
 color:var(--fg);margin-bottom:14px}
h1.st-section-title{margin:0 0 14px}
.st-section-title::after{content:"";flex:0 0 44px;height:2px;border-radius:1px;
 background:linear-gradient(90deg,var(--brand),var(--brand-soft))}

/* --- .st-grid：通用卡片网格 --- */
.st-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:14px;padding:6px 0}
/* task-8：原为 auto-fill。auto-fill 会先开出所有能放下的轨道再摆块，
   于是"块数 < 轨道数"时右侧留下【空轨道】。实测容器 1508px 下开出 5 条 290px 轨道、
   只有 4 块 ⇒ 填充率 4/5 = 0.8（首页 "Rankings" 那个 .st-grid 就是 4 块）。
   auto-fit 会折叠空轨道，4 块即撑满 4 列；并且在"块数 ≥ 轨道数"时
   auto-fit 与 auto-fill 行为完全相同 ⇒ 对其它用到 .st-grid 的页面零影响。 */
.st-grid-card{border:1px solid var(--line);background:var(--card);border-radius:var(--r-lg);
 padding:16px;box-shadow:var(--sh-card);
 transition:transform var(--tr),box-shadow var(--tr),border-color var(--tr)}
.st-grid-card:hover{border-color:var(--brand);box-shadow:var(--sh-hover);transform:translateY(-2px)}

/* --- .st-cmdk：命令面板视觉增强层（叠加在 .cmdk 之上） --- */
.st-cmdk .panel{border-radius:var(--r-lg);
 box-shadow:0 24px 60px -12px rgba(15,23,42,.28);backdrop-filter:blur(6px)}
.st-cmdk .grp{color:var(--brand)}
.st-cmdk .it:hover,.st-cmdk .it.sel{background:var(--brand-soft)}
.st-cmdk .in:focus-within{box-shadow:inset 0 0 0 2px var(--brand)}

/* --- .st-tabbar：移动 tabbar 美化层（叠加在 .tabbar 之上） --- */
.st-tabbar{background:var(--hdr);backdrop-filter:blur(14px);border-top:1px solid var(--line)}
.st-tabbar a{border-radius:var(--r-md)}
.st-tabbar a:hover{color:var(--brand);background:var(--brand-soft)}
.st-tabbar a.on{color:var(--brand);background:var(--brand-soft)}

/* --- .st-tide：潮汐图形（圆 + 上涌曲线，纯 CSS，用于页脚/hero 点缀） --- */
.st-tide{display:inline-block;width:44px;height:16px;position:relative;overflow:hidden;
 vertical-align:middle;border-radius:8px;background:var(--brand-soft)}
.st-tide::before{content:"";position:absolute;left:50%;bottom:-4px;width:14px;height:14px;
 margin-left:-7px;border-radius:50% 50% 0 0;background:linear-gradient(180deg,var(--brand),var(--brand-deep))}

/* --- .st-btn / .st-btn-ghost：通用按钮 --- */
.st-btn{display:inline-flex;align-items:center;gap:7px;border:0;border-radius:var(--r-md);
 background:linear-gradient(135deg,var(--accent),var(--brand-deep));color:var(--on-accent);
 font:inherit;font-size:13.5px;font-weight:650;padding:10px 18px;cursor:pointer;
 box-shadow:0 4px 14px -4px var(--accent-shadow);
 transition:filter var(--tr),box-shadow var(--tr),transform var(--tr)}
.st-btn:hover{filter:brightness(1.08);box-shadow:var(--sh-hover);transform:translateY(-1px)}
.st-btn-ghost{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--line);
 border-radius:var(--r-md);background:var(--card);color:var(--fg2);
 font:inherit;font-size:13.5px;font-weight:600;padding:9px 17px;cursor:pointer;
 transition:border-color var(--tr),color var(--tr),background var(--tr)}
.st-btn-ghost:hover{border-color:var(--brand);color:var(--brand);background:var(--brand-soft)}

/* --- .st-badge 系列：金银铜徽章（P3 榜单备用，本阶段仅实现） --- */
.st-badge{display:inline-flex;align-items:center;gap:4px;font-size:12px;font-weight:650;
 padding:2px 9px;border-radius:var(--r-sm);background:var(--brand-soft);color:var(--brand)}
.st-badge-gold{background:rgba(245,158,11,.16);color:var(--accent-orange)}
.st-badge-silver{background:rgba(148,163,184,.18);color:#64748b}
.st-badge-bronze{background:rgba(180,83,9,.14);color:var(--star)}

/* --- .st-fields：领域区容器（.fields/.chip 升级层）；.st-foot：页脚品牌区 --- */
.st-fields{display:flex;gap:8px;flex-wrap:wrap;padding:14px 0}
.st-fields .chip:hover{border-color:var(--brand);color:var(--brand);background:var(--brand-soft)}
.st-foot{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;
 padding:18px 0 6px;border-top:2px solid var(--brand-soft)}

/* ==========================================================================
   P3 · 榜单/领域可视化 + P4 · 条目页卡片化（2026-10-15，纯追加）
   实际标记（已对照线上样例页）：r/* 榜页、f/* 领域页、s/* 详情页相关区
   均为 .rows > .row；排名号 = row 首个 .meta 内 .num:not(.st)（形如 #1，
   仅 r/* 页有）；star 数 = .num.st。f/* 每行 .tag 同为领域名、无区分标记。
   ========================================================================== */

/* --- P3.1 前三名金银铜排位徽章：只命中 r/* 榜页（排名号 .num 无 .st 修饰） --- */
.rows .row:nth-child(-n+3) .meta .num:not(.st){
 display:inline-flex;align-items:center;justify-content:center;min-width:26px;height:20px;
 padding:0 7px;border-radius:var(--r-sm);
 font-family:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
 font-weight:700;font-size:11.5px;letter-spacing:0}
.rows .row:nth-child(1) .meta .num:not(.st){background:linear-gradient(135deg,var(--accent-orange),#d97706);color:#fff}
.rows .row:nth-child(2) .meta .num:not(.st){background:rgba(148,163,184,.28);color:var(--fg2)}
.rows .row:nth-child(3) .meta .num:not(.st){background:linear-gradient(135deg,#b45309,#92400e);color:#fff}

/* --- P3.2 star 数数字强调：等宽 + 琥珀色药丸（无 DOM 可做进度条轨道，走数字强调路线） --- */
.row .meta .num.st{font-family:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
 font-weight:700;background:rgba(180,83,9,.10);border-radius:var(--r-sm);padding:1px 6px}
html[data-theme="dark"] .row .meta .num.st{background:rgba(251,191,36,.14)}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .row .meta .num.st{background:rgba(251,191,36,.14)}}

/* --- P3.3 榜单行 hover 品牌浅紫底 + 卡片静默阴影（追加，特异性 0,2,0 高于基线 .row:hover） --- */
.rows .row:hover{background:var(--brand-soft)}
.rows{box-shadow:var(--sh-card)}

/* --- P3.4 f/* 领域页芯片：统一浅紫精致标签（每行 .tag 无领域区分标记，无法分域配色） --- */
.row .ln .tag{background:var(--brand-soft);color:var(--brand);border-radius:var(--r-sm);
 font-weight:500;padding:2px 8px}

/* --- P4 条目详情页卡片化：dl 信息卡 / off 标签 / 按钮过渡 --- */
.item dl{background:var(--soft);border:1px solid var(--line);border-radius:var(--r-lg);
 padding:16px 18px;box-shadow:var(--sh-card)}
.item dl dt{font-weight:600}
.tag.off{background:none;border:1px dashed var(--line);color:var(--muted);font-weight:500}

/* --- hero 波浪：按 2026-10-15 效果图加强 -------------------------------------------
   效果图里 hero 顶部有一条明显的紫色波浪，是首屏的视觉主角。
   原来的 .st-glow 是两团 14% 透明度的径向光，在浅色底上几乎看不出来 ——
   这是"设计改了但看不出区别"的第二层原因（第一层是浏览器缓存）。
   这里用多层渐变拼出波浪：顶部一个大椭圆做波峰，再叠一道浅色浪脊，
   下面保留原有的两团暖色光。light / dark 两套值都写，沿用本文件既有的双写模式。 */
.st-hero .st-glow{background:
  radial-gradient(125% 118% at 50% -44%, rgba(109,40,217,.34), rgba(109,40,217,.12) 40%, transparent 66%),
  radial-gradient(96% 54% at 50% -16%, rgba(255,255,255,.50), transparent 62%),
  radial-gradient(620px 260px at 16% -10%, rgba(109,40,217,.10), transparent 70%),
  radial-gradient(520px 220px at 88% 0%, rgba(245,158,11,.08), transparent 70%)}
@media(prefers-color-scheme:dark){
  .st-hero .st-glow{background:
    radial-gradient(125% 118% at 50% -44%, rgba(139,92,246,.42), rgba(139,92,246,.14) 40%, transparent 66%),
    radial-gradient(96% 54% at 50% -16%, rgba(255,255,255,.13), transparent 62%),
    radial-gradient(620px 260px at 16% -10%, rgba(183,164,251,.14), transparent 70%),
    radial-gradient(520px 220px at 88% 0%, rgba(251,191,36,.08), transparent 70%)}
  html[data-theme="light"] .st-hero .st-glow{background:
    radial-gradient(125% 118% at 50% -44%, rgba(109,40,217,.34), rgba(109,40,217,.12) 40%, transparent 66%),
    radial-gradient(96% 54% at 50% -16%, rgba(255,255,255,.50), transparent 62%),
    radial-gradient(620px 260px at 16% -10%, rgba(109,40,217,.10), transparent 70%),
    radial-gradient(520px 220px at 88% 0%, rgba(245,158,11,.08), transparent 70%)}}
html[data-theme="dark"] .st-hero .st-glow{background:
  radial-gradient(125% 118% at 50% -44%, rgba(139,92,246,.42), rgba(139,92,246,.14) 40%, transparent 66%),
  radial-gradient(96% 54% at 50% -16%, rgba(255,255,255,.13), transparent 62%),
  radial-gradient(620px 260px at 16% -10%, rgba(183,164,251,.14), transparent 70%),
  radial-gradient(520px 220px at 88% 0%, rgba(251,191,36,.08), transparent 70%)}
/* ===== 按豆包效果图施工（2026-10-15 EN/ZH 版）=================================
   效果图里三样最显眼的东西，上一轮我一样都没做，这一轮补上。 */

/* ① 波浪：SVG 铺满 .st-glow，上缘贴顶、下缘起伏。
   .st-glow 本身还留着径向渐变，两者叠起来是"波带 + 光晕"。 */
.st-wave{position:absolute;left:0;right:0;top:0;width:100%;height:240px;display:block}

/* ② 金银铜奖牌：圆底白字，盖掉 .rk 原来的灰数字。
   .brow .rk.rk-gold 特异性 0,3,0 高于 .rk 的 0,1,0，能稳定覆盖。 */
.brow .rk.rk-gold,.brow .rk.rk-silver,.brow .rk.rk-bronze{
  width:20px;height:20px;border-radius:50%;display:inline-flex;align-items:center;
  justify-content:center;font-size:11px;font-weight:750;color:#fff;
  font-family:inherit;letter-spacing:0}
.brow .rk.rk-gold{background:linear-gradient(135deg,#fbbf24,#d97706);
  box-shadow:0 1px 3px rgba(217,119,6,.35)}
.brow .rk.rk-silver{background:linear-gradient(135deg,#cbd5e1,#94a3b8);
  box-shadow:0 1px 3px rgba(148,163,184,.35)}
.brow .rk.rk-bronze{background:linear-gradient(135deg,#d8a06a,#b45309);
  box-shadow:0 1px 3px rgba(180,83,9,.32)}
@media(prefers-color-scheme:dark){
  /* task-4（2026-10-15）：这 3 条原来【漏了 guard】—— 项目里所有其他暗色规则都写成
     :root:not([data-theme="light"]) .SEL{dark}，而它们只写了裸选择器，于是
     媒体为暗时无论手动选什么都命中暗色值；实测"系统暗 + 手动浅色"下奖牌呈现暗色那套
     （#fcd34d→#f59e0b），与"系统亮"不一致。补上 guard 后与全项目写法统一，
     且自动两条路径行为完全不变（无属性时 :not([data-theme="light"]) 仍为真）。
     注：这里【不补】html[data-theme="light"] 反向规则 —— 那会让写法更碎、
     且构建期审计断言（见 build_index 尾部 _css_manual_light_audit）会强制统一写法。 */
  :root:not([data-theme="light"]) .brow .rk.rk-gold{
    background:linear-gradient(135deg,#fcd34d,#f59e0b)}
  :root:not([data-theme="light"]) .brow .rk.rk-silver{
    background:linear-gradient(135deg,#e2e8f0,#94a3b8)}
  :root:not([data-theme="light"]) .brow .rk.rk-bronze{
    background:linear-gradient(135deg,#e0b184,#c2703a)}}
html[data-theme="dark"] .brow .rk.rk-gold{background:linear-gradient(135deg,#fcd34d,#f59e0b)}
html[data-theme="dark"] .brow .rk.rk-silver{background:linear-gradient(135deg,#e2e8f0,#94a3b8)}
html[data-theme="dark"] .brow .rk.rk-bronze{background:linear-gradient(135deg,#e0b184,#c2703a)}

/* ③ statusline 去掉胶囊：效果图里 hero 顶部没有那个圆角框。
   信息保留（"最后更新 昨天 · 7,604 条 · 来自 4 个来源"），只是变素。 */
.statusline{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:0;
  background:none;border:0;border-radius:0;font-size:12.5px;color:var(--muted);
  margin-bottom:12px}

/* ===== hero 改成效果图那样的浅紫渐变面板（2026-10-15 重新对齐 ZH 效果图）=========
   第一版我把 hero 做成"白底 + 顶部一条通栏紫带"，方向就错了。
   效果图是一块【独立面板】：浅紫渐变、圆角底边，里面装丝带 / 标题 / 副标题 / 搜索框；
   4 个数字牌在面板【外面】的白底上（.statband 是 .wrap 的子元素，本来就在面板外）。 */

/* 面板本身：浅紫 → 白的纵向渐变 + 圆角底边 */
.st-hero{
  background:linear-gradient(180deg,#ede9fe 0%,#f5f3ff 42%,#ffffff 100%);
  border-bottom:0;border-radius:0 0 26px 26px;
  padding:34px 0 30px;margin-bottom:2px}

/* 背景氛围：极淡的两团光留在后面（原来的 .st-glow 保留，但降得很淡） */
.st-hero .st-glow{background:
  radial-gradient(900px 320px at 18% -20%, rgba(139,92,246,.13), transparent 70%),
  radial-gradient(760px 280px at 86% -14%, rgba(245,158,11,.07), transparent 70%)}
@media(prefers-color-scheme:dark){
  .st-hero{background:linear-gradient(180deg,#241f36 0%,#1c1a28 42%,#17171c 100%)}
  .st-hero .st-glow{background:
    radial-gradient(900px 320px at 18% -20%, rgba(139,92,246,.22), transparent 70%),
    radial-gradient(760px 280px at 86% -14%, rgba(251,191,36,.07), transparent 70%)}}
html[data-theme="dark"] .st-hero{background:linear-gradient(180deg,#241f36 0%,#1c1a28 42%,#17171c 100%)}
html[data-theme="dark"] .st-hero .st-glow{background:
  radial-gradient(900px 320px at 18% -20%, rgba(139,92,246,.22), transparent 70%),
  radial-gradient(760px 280px at 86% -14%, rgba(251,191,36,.07), transparent 70%)}
html[data-theme="light"] .st-hero{background:linear-gradient(180deg,#ede9fe 0%,#f5f3ff 42%,#ffffff 100%)}
/* task-3（2026-10-15）：把 .st-glow 的"跟随系统"与"手动切换"两条路径收敛到同一套值。
   原来这里叠了【两组历史规则】：一组是 620px 两团光（早期版），一组是 900px 两团光
   （2026-10-15 效果图那版）。因为
     · 浅色 900px 规则写在【无媒体查询】处（特异性 0,2,0）
     · 暗色 620px 规则写在 @media(prefers-color-scheme:dark){:root:not([data-theme="light"]) …}
       （特异性 0,3,0，靠 :not 赢了顺序）
   于是【系统为暗】时无论手动选什么都命中 620px 那套，系统为亮时命中 900px 那套 ——
   同一个"暗色 hero"在两条路径下不是同一个渐变（实测 background-image 字符串不同）。
   下面两条把它们收敛：暗色媒体路径 = 手动暗色的值（900px/.22），
   手动浅色 = 自动浅色的值（900px/.13）。自动浅色外观不变。 */
@media(prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .st-hero .st-glow{background:
    radial-gradient(900px 320px at 18% -20%, rgba(139,92,246,.22), transparent 70%),
    radial-gradient(760px 280px at 86% -14%, rgba(251,191,36,.07), transparent 70%)}}
html[data-theme="light"] .st-hero .st-glow{background:
  radial-gradient(900px 320px at 18% -20%, rgba(139,92,246,.13), transparent 70%),
  radial-gradient(760px 280px at 86% -14%, rgba(245,158,11,.07), transparent 70%)}

/* 丝带：居中、固定宽度，坐在标题上方 */
.st-ribbon{display:flex;justify-content:center;margin:2px 0 14px}
.st-ribbon svg{width:340px;max-width:74%;height:auto;display:block}
@media(max-width:680px){.st-ribbon svg{width:250px}}

/* 搜索框：改成通栏 + 更高（效果图里它占满面板宽度、约 56px 高、圆角更大） */
.searchbig{display:flex;gap:9px;max-width:100%;margin-bottom:0}
.searchbig .field{flex:1;display:flex;align-items:center;gap:11px;border:1px solid rgba(109,40,217,.18);
  background:var(--card);border-radius:15px;padding:0 18px;height:56px;
  box-shadow:0 2px 10px rgba(76,29,149,.07);
  transition:border-color var(--tr),box-shadow var(--tr)}
.searchbig .field:focus-within{border-color:var(--brand);box-shadow:0 0 0 4px var(--brand-soft)}
.searchbig .field svg{width:19px;height:19px;color:var(--muted);flex:none}

/* 数字牌跟着面板走：面板下沿和它之间留一点气口 */
.statband{margin-top:20px}

/* ===== 区块呼吸感：对齐效果图（2026-10-15 第二轮）=============================
   效果图里"最近收录"那张卡片内部更舒展：行与行之间有间距，卡片有横向内边距。
   现状 .rows 已有边框/圆角/阴影（本来就是卡片），只是太紧。 */
.rows{padding:6px 18px}
.rows > .row{padding:9px 0}
.rowmore{margin-top:10px}

/* 「更多榜单」标题与上方"最近收录"的间距：效果图里两片内容之间有明确分隔 */
#rows ~ p.rowmore{margin-bottom:4px}

/* ===== 对齐效果图：数字牌（2026-10-15 第三轮）=================================
   效果图里四个数字牌：数字是【深色】、数字与标签都【居中】。
   豆包设计系统把数字设成了 var(--brand) 紫色（.st-stat .n），效果图里没有用紫色，
   这里覆盖回正文色。 */
.st-stat{text-align:center}
.st-stat .n,.st-stat .st-n{color:var(--fg)}
/* 标签也跟着居中（原来 .st-stat .l 没有对齐设置，继承即可，但显式写更稳） */
.st-stat .l{text-align:center}

/* ===== 对齐效果图：区块留白（效果图各区块之间气口更大）===================== */
.st-section{padding:26px 0}
.statband{margin-top:22px;margin-bottom:6px}
.catnav{margin-bottom:6px}

/* ===== 对齐效果图：「最近收录」的标题在卡片【内部】=========================
   效果图里"最近收录"是卡片左上角的一部分，行在它下面；原来是 <h2> 在卡片外面。 */
.rows .rowshead{font-size:16px;font-weight:700;letter-spacing:-.01em;
  margin:0;padding:14px 0 10px;border-bottom:1px solid var(--line)}

/* ===== 对齐豆包 GLASS 效果图（2026-10-15 第四轮：hero 居中 + 玻璃球 + 玻璃质感）=====
   前三轮把面板、丝带、奖牌做完了，但对照效果图还差四样：
   ① hero 是【居中排版】（状态行/标题/副标题/搜索框全居中），线上是左对齐；
   ② 效果图 hero 里散布 5 个半透明紫色玻璃球，线上一颗都没有；
   ③ 丝带在效果图里位于【副标题与搜索框之间】、约 700px 宽，原来在 hero 顶部、340px；
   ④ 数字牌/快捷卡在效果图里是【半透明玻璃】（底下透出紫色面板），且数字牌左上角有小图标、
      内容左对齐 —— 第三轮读成"居中"是误读，效果图里 7,604 / +1,740 都贴着卡片左缘。 */

/* ① 居中：statusline 是 width:fit-content 的 flex，margin auto 即居中；
   标题/副标题带 max-width，auto 边距居中；搜索框收窄居中（效果图约占面板宽 55%）。
   效果图 H1 是纯色深文字，盖掉 P1 的渐变字（background-clip:text）。 */
.st-hero{text-align:center;padding:46px 0 34px}
.st-hero .statusline{margin:0 auto 14px}
.st-hero .st-hero-title{margin-left:auto;margin-right:auto;text-align:center;
  background:none;-webkit-text-fill-color:var(--fg)}
.st-hero .st-hero-sub{margin-left:auto;margin-right:auto;text-align:center}
.st-hero .searchbig{margin:0 auto 22px;max-width:760px}

/* 内容层叠次序：玻璃球和光晕在底层，文字/卡片在上 */
.st-hero .status-head,.st-hero .st-ribbon,.st-hero .searchbig,.st-hero .statband,
.st-hero .quickh,.st-hero .catnav{position:relative;z-index:1}

/* ② 玻璃球：径向渐变高光 + 内阴影，5 颗的位置按效果图摆（左下大、右上中、其余小）。
   球体超出 hero 边缘的部分由 .st-hero 的 overflow:hidden 裁掉，和效果图一致。 */
.st-orbs{position:absolute;inset:0;pointer-events:none}
.st-orbs i{position:absolute;border-radius:50%;display:block;
  background:radial-gradient(circle at 32% 28%,rgba(255,255,255,.92),rgba(196,181,253,.55) 42%,rgba(124,58,237,.60) 82%);
  box-shadow:inset -6px -8px 16px rgba(76,29,149,.16),0 12px 26px -10px rgba(76,29,149,.30);
  opacity:.9}
.st-orbs .o1{width:96px;height:96px;left:3.5%;bottom:5%}
.st-orbs .o2{width:34px;height:34px;left:12.5%;top:9%}
.st-orbs .o3{width:46px;height:46px;right:5%;top:15%}
.st-orbs .o4{width:22px;height:22px;right:15%;top:50%}
.st-orbs .o5{width:16px;height:16px;left:23%;top:58%}
@media(max-width:820px){
  .st-orbs .o1{width:62px;height:62px;left:2%}
  .st-orbs .o3{width:34px;height:34px}
  .st-orbs .o4,.st-orbs .o5{display:none}}
@media(prefers-color-scheme:dark){:root:not([data-theme="light"]) .st-orbs i{
  background:radial-gradient(circle at 32% 28%,rgba(255,255,255,.30),rgba(139,92,246,.34) 42%,rgba(76,29,149,.52) 82%);
  box-shadow:inset -6px -8px 16px rgba(0,0,0,.35),0 12px 26px -10px rgba(0,0,0,.5);opacity:.55}}
html[data-theme="dark"] .st-orbs i{
  background:radial-gradient(circle at 32% 28%,rgba(255,255,255,.30),rgba(139,92,246,.34) 42%,rgba(76,29,149,.52) 82%);
  box-shadow:inset -6px -8px 16px rgba(0,0,0,.35),0 12px 26px -10px rgba(0,0,0,.5);opacity:.55}

/* ③ 丝带：挪到副标题与搜索框之间（DOM 注入点已改），放宽到 700px、居中 */
.st-ribbon{display:flex;justify-content:center;margin:2px auto 18px}
.st-ribbon svg{width:min(700px,92%);max-width:92%;height:auto;display:block}
@media(max-width:680px){.st-ribbon svg{width:260px}}

/* ④ 玻璃质感：数字牌/快捷卡半透明 + 背滤模糊，透出下面的紫色面板。
   作用域限定 .st-hero 内 —— 领域页的 .statband 不在 hero 里，保持原样。 */
.st-hero .st-stat{background:rgba(255,255,255,.62);border-color:rgba(255,255,255,.8);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
.st-hero .st-quick-item{background:rgba(255,255,255,.60);border-color:rgba(255,255,255,.8);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px)}
@media(prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .st-hero .st-stat,
  :root:not([data-theme="light"]) .st-hero .st-quick-item{
    background:rgba(29,29,36,.55);border-color:rgba(255,255,255,.09)}}
html[data-theme="dark"] .st-hero .st-stat,
html[data-theme="dark"] .st-hero .st-quick-item{
  background:rgba(29,29,36,.55);border-color:rgba(255,255,255,.09)}

/* 数字牌改回左对齐 + 左上角小图标（第三轮的居中是对效果图的误读） */
.st-stat{text-align:left}
.st-stat .n,.st-stat .st-n{text-align:left}
.st-stat .l{text-align:left}
.st-stat .sic{display:inline-flex;width:26px;height:26px;align-items:center;justify-content:center;
  border-radius:8px;background:var(--brand-soft);color:var(--brand);margin-bottom:7px}
.st-stat .sic svg{width:15px;height:15px}

/* 「快捷入口」小标题：效果图里它在数字牌与快捷卡之间，深色半粗、左对齐。
   h2 基线带 uppercase，必须显式复位，否则 "Quick access" 变成全大写。 */
.quickh{font-size:15px;font-weight:700;letter-spacing:-.01em;color:var(--fg);
  margin:24px 0 4px;text-align:left;text-transform:none}

/* 快捷卡图标分色：效果图四张卡依次是紫 / 蓝 / 绿 / 靛 */
.st-quick-item:nth-child(2) .ccic{background:#e0f2fe;color:#0369a1}
.st-quick-item:nth-child(3) .ccic{background:#d1fae5;color:#047857}
.st-quick-item:nth-child(4) .ccic{background:#e0e7ff;color:#4f46e5}
@media(prefers-color-scheme:dark){
  :root:not([data-theme="light"]) .st-quick-item:nth-child(2) .ccic{background:#0c4a6e;color:#7dd3fc}
  :root:not([data-theme="light"]) .st-quick-item:nth-child(3) .ccic{background:#064e3b;color:#6ee7b7}
  :root:not([data-theme="light"]) .st-quick-item:nth-child(4) .ccic{background:#312e81;color:#a5b4fc}}
html[data-theme="dark"] .st-quick-item:nth-child(2) .ccic{background:#0c4a6e;color:#7dd3fc}
html[data-theme="dark"] .st-quick-item:nth-child(3) .ccic{background:#064e3b;color:#6ee7b7}
html[data-theme="dark"] .st-quick-item:nth-child(4) .ccic{background:#312e81;color:#a5b4fc}

/* ===== 对齐效果图（2026-10-15 第五轮：通栏 hero + 细节修正）=====================
   第四轮上线后实测发现的问题：
   ① hero 还包在 .wrap 里，紫色面板两边留白 —— 效果图是【通栏】。
      markup 已改为 hero 在外、wrap 在内；这里去掉圆角（通栏不需要）。
   ② 大玻璃球 bottom:5% 正好压在快捷卡上 —— 效果图里它浮在波浪左侧的空白处。
   ③ 搜索框 56px 比效果图厚，收到 50px。
   ④ 区块标题继承了 h2 的 uppercase，效果图是正常大小写。
   ⑤ 玻璃卡在紫底上对比太弱，补一点阴影让它立起来。 */
.st-hero{border-radius:0}
.st-orbs .o1{top:52%;bottom:auto;left:-26px}
.st-orbs .o4{top:42%}
.st-hero .searchbig .field{height:50px}
.st-section-title{text-transform:none;letter-spacing:-.01em}
.rows .rowshead{text-transform:none;color:var(--fg)}
.st-hero .st-stat,.st-hero .st-quick-item{box-shadow:0 2px 12px rgba(76,29,149,.08)}

/* ===== 首页下半部分改版（2026-10-15 DeepSeek 接手）================================
   交接单第三节，三件事。全部规则只追加，不改上面任何一条旧规则。
   ① 核心三榜（mcp/agent/skills）从 .bgrid 里抽出来，做成一行 3 张宽卡 —— 效果图最下缘
      露出的那半行。宽卡保留 bblock + <h3><span class="bico">，所以 check-site 的
      "榜块 >=16 / 每个榜块标题带图标" 两条断言数到的还是同一批块。
   ② Sections 图标条 + 场景 chip + 平台 chip + 领域 chip 四个区合成一个 .st-browse 面板。
   ③ 提交卡换品牌浅紫底 + 标题图标 + 紫渐变按钮（订阅卡、关于卡保持白底）。
   列数全部用显式 repeat()，不用 auto-fit —— auto-fit 只放得下整列，补不了最后一行，
   这正是一个月前 .bgrid 出洞的原因。所有轨道写 minmax(0,1fr)，禁止裸 1fr（c_layout 断言）。 */

/* --- ① 宽卡一行 3 张。显式 3 / 2 / 1 列，没有余数，因此不可能出现网格洞。 ---------- */
.st-bwide{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;padding:6px 0 0}
/* 栅格项默认 min-width:auto，宽卡里的长榜名会把轨道顶宽 —— 显式声明 0 让它能收缩。 */
.st-bwide>*{min-width:0}
@media(max-width:1365px){.st-bwide{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:1023px){.st-bwide{grid-template-columns:minmax(0,1fr)}}
.bblock.bwide{display:grid;grid-template-columns:196px minmax(0,1fr);gap:18px;align-items:start;padding:16px}
/* 宽卡的头部：40px 图标圆牌（交接单第三节①要求"左侧 40px 图标圆牌，--brand-soft 底"）。
   类名沿用 .bico，尺寸靠 .bblock.bwide 这个作用域放大 —— 见 board_wide() 的注释：
   check-site 数"榜块"用的正则要求 <h3><span class="bico" 原样出现。 */
/* 宽卡的头部必须是 <div class="bblock bwide"> 紧跟 <h3><span class="bico"> —— 中间不能夹
   <div class="bwide-head">。check-site 数"榜块"的正则 [^>]*>\s*<h3> 只吃"同一个标签的右尖括号
   后面紧跟 <h3>"这一种形状，夹一层 div 它就一个都数不到（实测 18 -> 15，正好掉到阈值 16 以下）。 */
.bblock.bwide h3{font-size:16px;font-weight:700;line-height:1.3;margin-bottom:9px;gap:10px;
  align-items:flex-start}
.bblock.bwide .bico{width:40px;height:40px;border-radius:11px}
.bblock.bwide .bico svg{width:21px;height:21px}
.bwide-txt{min-width:0}
.bwide-eb{display:block;font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--brand);margin-bottom:4px}
.bwide-desc{font-size:12px;color:var(--muted);line-height:1.45;max-width:64ch}
/* 榜行与左侧头部分栏：宽屏上是一条竖线，窄屏上换成横线（见 1023 断点的 media query）。 */
.bwide-body{min-width:0;border-left:1px solid var(--line2);padding-left:18px}
.bwide-body .bmore{padding-top:8px}
@media(max-width:1023px){
  .bblock.bwide{grid-template-columns:minmax(0,1fr);gap:11px}
  .bwide-body{border-left:0;border-top:1px solid var(--line2);padding-left:0;padding-top:9px}
  .bwide-txt{margin-bottom:11px}}

/* --- ② Browse 面板：一个带边框的大面板 + 三列 ------------------------------------------------- */
/* 三列的断点定在 1300px 而不是 1365：1440 是三列时每列 ~330px，够放 chip；一旦掉到两列，
   第三列的 chip 会整块掉到第二行，第一行右侧留下一大片空档（1440 实测：三列剩两列、右侧 350px 空）。
   1024 按交接单要求是两列，1300 这个断点正好落在两者之间。 */
.st-browse{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--card);
  box-shadow:var(--sh-card);padding:18px 20px 20px;margin:6px 0 4px}
.st-browse-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:4px}
.st-browse-head h2{margin:0}
.st-browse-note{font-size:12px;color:var(--muted)}
.st-browse-cols{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px 26px;padding-top:14px}
.st-browse-col{min-width:0;border-top:1px solid var(--line2);padding-top:14px}
.st-browse-col .st-section-title{font-size:13px;margin-bottom:11px}
.st-browse .sstrip{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;padding:0}
.st-browse .sstrip .stile{width:auto;height:40px}
.st-browse .fields{padding:0;gap:7px}
.st-browse-more{display:inline-flex;align-items:center;gap:5px;margin-top:11px;font-size:12.5px;
  font-weight:600;color:var(--brand);text-decoration:none}
.st-browse-more:hover{text-decoration:underline}
/* task-1（2026-10-15）：21 个领域 chip 并进列 3 之后的"限两行"。
   交接单第三节② 要求"领域多，限两行 + 全部领域 →"。做法是**限可见高度**，不是截短列表，
   也不是把标签截成省略号：21 个 chip 全部留在 DOM 里（check-site 的 c_homepage_regions
   数的是产物 HTML 里的 /{lang}/f/ 链接数，删掉任何一个 chip 都会少一个），
   只把列 3 的可见高度压到两行，余下靠滚动取用。

   为什么是 max-height + overflow-y:auto，而不是"把 chip 压小硬塞进两行"：
   实测（真 site.css + 真 21 个领域 + 真列宽，headless Chrome 量每档的标签截断数）：
       视口1440 列3=351px、chip 平均宽 130px ⇒ 每行只放得下 2 个
       flex 自然折行      7 行 / 246px   截断 0/21   ← 不截断
       grid 4 列          6 行 / 210px   截断 12/21
       grid 6 列          4 行 / 138px   截断 20/21
       grid 12 列         2 行 /  65px   截断 21/21  ← 两行只能靠"每个标签都截断"换到
   结论：在 351px 列宽下，"两行 + 全部可见 + 标签可读"三者不能同时成立。
   交接单同时要求"限两行"和"全部领域 →"出口，所以取"限两行 + 滚动 + 不截断标签"：
   标签保住可读性，余下领域既可滚动取用，也有「全部领域 →」这个正式出口。
   副作用如实记录：第 3 行起需滚动才可见（DOM 里全在、可 Tab、可读屏）。

   68px 的来历：.chip 实测高 33px（13px 字号 + 5px 上下内边距 + 1px 边框），
   两行 + 7px 行间距 = 33*2 + 7 = 73px；实测 window 若超过两行会露出第三行的一半，
   所以取 68px（两行 + 2px），保证只露完整的两行。

   不写 ::-webkit-scrollbar 颜色规则：那会把"滚动条颜色"变成一个需要在暗色模式里
   再写两遍的写死颜色；不写则浏览器按亮/暗自动着色，没有颜色需要三写
   （与文件尾部阶段 3 那条判据一致：只列"真需要第三遍"的规则）。 */
.st-browse-fields{max-height:73px;overflow-y:auto;overscroll-behavior:contain}
/* 分隔线：没有它，平台 chip 和领域 chip 连排成一片，两个语义在视觉上糊在一起。 */
.st-browsediv{height:1px;background:var(--line2);margin:11px 0 9px}
@media(max-width:1299px){.st-browse-cols{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:1023px){.st-browse-cols{grid-template-columns:minmax(0,1fr);gap:16px}}
@media(max-width:820px){.st-browse{padding:15px 14px 17px}.st-browse .sstrip{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media(max-width:400px){.st-browse .sstrip{grid-template-columns:repeat(3,minmax(0,1fr))}}

/* --- ③ 提交卡：品牌浅紫底。三级类名压过 .st-grid-card 的两级，因此不必写 !important -------- */
.bblock.st-grid-card.st-submit{background:var(--brand-soft);border-color:#ddd6fe}
/* task-3（2026-10-15）实测补的一条：上面那条只在"无媒体查询"处，而暗色那条写在
   @media(prefers-color-scheme:dark){:root:not([data-theme="light"]) ...} 里 ——
   :not([data-theme="light"]) 对"没有 data-theme 属性"也为真，于是【系统为暗 + 手动切浅色】
   时卡片仍然是暗的（实测 rgb(36,31,61) 而非 rgb(237,233,254)）。
   手动浅色必须显式声明，否则它拿不到浅色值。自动跟随 / 手动暗两条路径的值不变。 */
@media(prefers-color-scheme:dark){
  html[data-theme="light"] .bblock.st-grid-card.st-submit{background:var(--brand-soft);
    border-color:#ddd6fe}
  html[data-theme="light"] .bblock.st-grid-card.st-submit:hover{border-color:var(--brand)}}
.bblock.st-grid-card.st-submit:hover{border-color:var(--brand)}
.bblock.st-grid-card.st-submit .sh3{display:flex;align-items:center;gap:9px;font-size:14px;font-weight:700}
.st-submit-ico{width:26px;height:26px;flex:none;display:flex;align-items:center;justify-content:center;
  border-radius:8px;background:var(--card);color:var(--brand)}
.st-submit-ico svg{width:15px;height:15px}
.st-btn-w{width:100%;justify-content:center}

/* ===== More rankings 的 10 块网格：列数与补位（task-7，2026-10-15）=====================
   用户直接报的问题："下半部分榜单没对齐"。实测（真浏览器 6 宽度 × EN/ZH）改前：
     4 列档（≥1400）    10 = 4+4+2 → 末行只占 3/4 列，第 4 列空着     ← 用户看到的
     3 列档（1300-1399）10 = 3+3+3+1 → 最后一块跨 3 列独占整行       ← 一个突兀的大卡
     2 列档（1024-1299）10 = 5×2 整齐
     1 列档（≤1023）     10 × 1 整齐
   判定口径用【填充率】（末行占用列数 / 总列数 == 1.0），不是"无空轨道"——
   后者查的是 auto-fill 的行尾空轨道，看不到"末行只填 2/4 列"这种不齐。

   修法（保留全部 10 个榜，纯 CSS）：
     ① 4 列档：最后两块各占 2 列 ⇒ 4+4+(2+2) 铺满
     ② 3 列档：10 在 3 列下结构性无解（10 = 3n+1 ⇒ 末行必然只剩一块）
              ⇒ 降到 2 列，10 = 5×2 整齐
   注意 2 列档下 10 块【不需要任何补位】——多一条 span 反而会造出"满行孤块"。
   踩过的三个坑：
     · 不可写 :last-child:nth-last-child(2)：二者互斥（不能既是最后一个又是倒数第二个），
       matches() 恒 false、规则永不命中。
     · 不能用"同特异性再写一条 grid-column:auto"压回 span：Chrome 在简写+简写平手上按
       声明位置决胜，同块内后写的 auto 仍输给前面的 span 2（最小复现 A/B/C/D 已验证）。
     · 同一个值在本区出现多次时，按"改一处"的字符串锚点容易改错档（1399 与 1299 的 3n+1
       条款一字不差）——所以这个区整体重写，不再做局部替换。
   旧网格（首屏 4 块）的规则一个字没动：它仍靠 :has(...:nth-child(4)) 保持 2 列。 */
.bgrid.st-more{grid-template-columns:repeat(4,minmax(0,1fr))}
.bgrid.st-more> :last-child:nth-child(4n+2){grid-column:span 2}
@media(min-width:1400px){
  .bgrid.st-more> :nth-last-child(-n+2){grid-column:span 2}}
@media(max-width:1399px){
  /* 3 列下 10 = 3n+1 无解，降到 2 列。!important 必需：1299 档也设了 grid-template-columns，
     同特异性下后写的会盖回来（实测不加仍是 3 列）。 */
  .bgrid.st-more{grid-template-columns:repeat(2,minmax(0,1fr))!important}
  .bgrid.st-more> :last-child:nth-child(3n+2),
  .bgrid.st-more> :last-child:nth-child(3n+1){grid-column:auto}}
@media(max-width:1023px){.bgrid.st-more{grid-template-columns:minmax(0,1fr)}}

/* 暗色模式三写纪律。读 token 的那些规则（background:var(--card) 等）本身已经做过暗色
   重映射，三写是空操作；这里把"确实需要第三遍"的两处（写死了浅色的地方）列出来，
   其余保持 token 写法。 */
@media(prefers-color-scheme:dark){:root:not([data-theme="light"]) .bblock.st-grid-card.st-submit{background:#241f3d;border-color:#3b3363}}
html[data-theme="dark"] .bblock.st-grid-card.st-submit{background:#241f3d;border-color:#3b3363}
@media(prefers-color-scheme:dark){:root:not([data-theme="light"]) .st-submit-ico{background:rgba(255,255,255,.06)}}
html[data-theme="dark"] .st-submit-ico{background:rgba(255,255,255,.06)}
@media(prefers-color-scheme:dark){:root:not([data-theme="light"]) .bblock.bwide .bico{background:var(--brand-soft);color:var(--brand)}}
html[data-theme="dark"] .bblock.bwide .bico{background:var(--brand-soft);color:var(--brand)}
@media(prefers-color-scheme:dark){:root:not([data-theme="light"]) .bwide-eb{color:var(--brand)}}
html[data-theme="dark"] .bwide-eb{color:var(--brand)}
@media(prefers-color-scheme:dark){:root:not([data-theme="light"]) .bblock.st-grid-card.st-submit:hover{border-color:var(--brand)}}
html[data-theme="dark"] .bblock.st-grid-card.st-submit:hover{border-color:var(--brand)}

/* ===== 窄屏三条（task-27，2026-10-15）=========================================
   全部由 Playwright 的 computed 值定位，不是读 CSS 文本。只【追加】规则，
   不改上面任何一条旧规则。

   ① Copy install 在 390 下折成 2 行，高度 59.6px ≈ h1 的 62.4px ⇒ 按钮压过标题。
      根因: `.copy code` 是 flex item，没有 nowrap/overflow，命令文本在窄屏折行。
      ★ text-overflow:ellipsis 在这里不起作用 —— 它只作用于【行内文本】，
        而这个 code 是 flex item，所以必须用 overflow-x:auto（让它可以横向滚动）。
      ★ max-width:100% 要【两处都写】: code 的百分比相对父级解析，
        父级 .copy 本身会被内容撑宽，只给 code 加等于没加（实测过）。
   ② 首页底部三卡（提交 / 订阅 / 关于）在 2 轨道宽度下末行只占半行（填充 0.49，
      右半整块空白）。让独占末行的那张卡跨满整行 —— 同 .the-row 用过的手法。
      ★ 用属性选择器锁定这一个容器，因为 1180=3 轨道 / 1440=4 轨道，
        在 3、4 轨道下让末块跨满会凭空多出一整行（比原来的洞更糟）。
        这个容器是全站唯一带 inline auto-fit 的 .st-section。 */
/* ① copy 按钮只在 ≤560 生效。实测 390=59.6px（标签折行，h1 才 62.4px）；
      820=1024=38.8px（正常）⇒ 缺陷只在很窄的宽度出现。
      让 code 单行并可横向滚动 + 缩一档字，实测 390/560=37.2px，561 回到 38.8px（边界干净）。
      ★ text-overflow:ellipsis 在这里没用 —— 它只作用于行内文本，而 code 是 flex item。 */
/* ① task-37 (C)：≤620 让描述折成 2 行。实测那里描述行最窄（390 时 .lntxt 仅 143px、
   描述原文 1,639px），单行必然截断（8/8 行以 … 结尾）。折 2 行后截断 0/8，
   代价是行高 122.6 → 139.6（+17px/行）。
   ★ 621 以上不加（实测那里加这条规则完全无效果，因为 .lntxt 更宽、本来就 1 行）；
     621–820 的单行 meta 布局也不受影响（行高仍 94）。 */
@media(max-width:620px){
  .row .ln .lntxt{white-space:normal;overflow:visible;text-overflow:clip;
    display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
}
@media(max-width:560px){
  .copy{padding:9px 12px;gap:6px;font-size:12px;max-width:100%}
  .copy code{font-size:11.5px;white-space:nowrap;overflow-x:auto;min-width:0;
    flex:0 1 auto;scrollbar-width:thin}
}
/* ② 首页底部三卡（提交/订阅/关于）。容器是全站唯一带 inline auto-fit 的 .st-section。
      实测它的轨道数：视口 ≤910（容器 ≤895px）2 轨道；≥920（容器 ≥905px）3 轨道；
      1440 是 4 轨道。2 轨道时末行只有第三张卡 ⇒ 右半整块空白（填充 0.49）。
      ⇒ 只在这个区间让末块跨满整行；外边界取 935 并把容器锁成 2 列：918~935 有一段"3 轨挤进来但放不下第三张"的坏区间（实测 918 第一行只占 0.643）。
      ★ 教训（我第一版踩的）：外边界写成 1023 会在 3 轨道下也让末块跨满，
        第一行掉到 0.645 —— 那是【修复引入的新缺陷】。
      ★ 也不加 :nth-child(odd)：它只在 2 轨道下需要，加了反而在 3 轨道下误判。
      手法同 .the-row，不改列数（auto-fit 与 minmax(290px) 原样）。 */
@media(min-width:561px) and (max-width:935px){
  /* 在这个区间把它【锁成 2 列】：auto-fit 原本会让 3 条 290px 轨道刚好挤进来
     （3×290.328+2×16=903），但三张卡仍 2+1 换行 ⇒ 第一行只占 0.643。
     2×minmax(0,1fr) 比 3×290 宽，三张卡干净地 2+1，末张跨满 ⇒ 两行都填满。 */
  .st-section[style*="auto-fit"]{grid-template-columns:repeat(2,minmax(0,1fr))!important}
  .st-section[style*="auto-fit"] > .bblock:last-child{grid-column:1/-1}
}


/* ===== task-143/147/151/155：AI 工具行图标 · 域名 ↗ · 徽章墙 · 主页两扇门 =====
   ★ 这些规则原先被我直接 append 到 /opt/site/site.css ⇒ 每次构建被覆盖
     （site.css 是 build-frontend.py 生成的投影，真源是这里的 CSS 常量）。
     现在补进真源。 */
img.aico,.aico{width:22px;height:22px;border-radius:6px;flex:none;object-fit:contain;
 background:var(--ico-bg);display:block}
html[data-theme="dark"] img.aico,html[data-mode="dark"] img.aico,
html[data-theme="dark"] .aico.fb,html[data-mode="dark"] .aico.fb{
 box-shadow:0 0 0 1px rgba(255,255,255,.22)}
@media (prefers-color-scheme:dark){
 :root:not([data-theme="light"]) img.aico,
 :root:not([data-theme="light"]) .aico.fb{box-shadow:0 0 0 1px rgba(255,255,255,.22)}}

.adom{display:inline-block;margin-left:8px;font-size:11.5px;color:var(--muted);
 font-weight:500;letter-spacing:.01em;white-space:nowrap}
.row:hover .adom{color:var(--brand)}

.qbadges{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
 margin:10px 0 4px;padding:9px 12px;border:1px solid var(--line);border-radius:var(--r-lg);
 background:var(--card)}
.qbadges .qbl{font-size:11.5px;color:var(--muted);font-weight:600;letter-spacing:.02em;
 margin-right:2px;white-space:nowrap}
img.qbadge{height:20px;width:auto;display:block;border-radius:4px}
html[data-theme="dark"] .qbadges,html[data-mode="dark"] .qbadges{
 background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.12)}
html[data-theme="dark"] img.qbadge,html[data-mode="dark"] img.qbadge{
 background:#fff;padding:1px 2px;border-radius:4px;opacity:.92}
@media (prefers-color-scheme:dark){
 :root:not([data-theme="light"]) .qbadges{background:rgba(255,255,255,.05);
  border-color:rgba(255,255,255,.12)}
 :root:not([data-theme="light"]) img.qbadge{background:#fff;padding:1px 2px;
  border-radius:4px;opacity:.92}}
@media(max-width:560px){.qbadges{gap:6px;padding:8px 10px}.qbadges .qbl{width:100%}}

/* task-168: 两扇门 → 【三扇门】等宽等高（lead 的决定）——
   ★ 用户报过"有的横有的竖"，所以三门的视觉权重必须相同，不许一门大两门小；
     "我要做一件事"放最左（阅读起点），但【尺寸与另两门完全一致】。 */
.twodoors{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;margin:18px 0 6px}
.tdoor{display:flex;align-items:flex-start;gap:14px;padding:18px 20px;
 border:1px solid var(--line);border-radius:var(--r-lg);background:var(--card);
 box-shadow:var(--sh-card);text-decoration:none;color:var(--fg);min-width:0;
 transition:transform var(--tr),box-shadow var(--tr),border-color var(--tr)}
.tdoor:hover{border-color:var(--brand);box-shadow:var(--sh-hover);transform:translateY(-2px)}
.tdic{flex:0 0 40px;width:40px;height:40px;border-radius:11px;display:flex;
 align-items:center;justify-content:center;background:var(--brand-soft);color:var(--brand)}
.tdic svg{width:22px;height:22px}
.tdtx{display:flex;flex-direction:column;gap:3px;min-width:0}
.tdtx b{font-size:16.5px;font-weight:720;letter-spacing:-.01em}
.tdtx i{font-size:13px;color:var(--muted);font-style:normal;line-height:1.5}
.tdtx em{font-size:11.5px;color:var(--brand);font-style:normal;font-weight:650}
.tdmore{margin-top:10px}
@media(max-width:700px){.twodoors{grid-template-columns:minmax(0,1fr)}}

/* task-158: AI 工具行的【中文界面】正向标签 + 图例
   ★ 只标正向（有证据才标）；图例说明防"没标签=不支持中文"的误读。 */
.tag.cnok{background:var(--brand-soft);color:var(--brand);font-weight:650}
.cnlegend{font-size:12.5px;color:var(--muted);margin:2px 0 12px;line-height:1.6}
.cnlegend b{color:var(--fg)}
.tag.cncn{background:var(--card);color:var(--muted);border:1px solid var(--line);font-weight:600}

/* task-162: 任务页（C 端主入口）—— 给答案，不给列表。
   每个工具回答三件: 为什么推荐 · 免费吗 · 怎么开始。 */
.taskask{font-size:clamp(22px,3vw,30px);font-weight:750;letter-spacing:-.02em;margin:6px 0 8px}
.tgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:14px;margin:16px 0 6px}
.tcard{border:1px solid var(--line);background:var(--card);border-radius:var(--r-lg);
 padding:16px 18px;box-shadow:var(--sh-card);min-width:0}
.tchead{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:8px}
.tname{font-size:16px;font-weight:720;color:var(--fg);text-decoration:none}
.tname:hover{color:var(--brand);text-decoration:underline}
.tcwhy{font-size:13.5px;line-height:1.6;margin-bottom:6px}
.tcmore{font-size:12.5px;color:var(--muted);line-height:1.6}
.tcwhy b,.tcmore b{display:inline-block;min-width:64px;color:var(--fg);font-weight:650;
 margin-right:6px}
@media(max-width:560px){.tgrid{grid-template-columns:minmax(0,1fr)}.tcwhy b,.tcmore b{min-width:0;display:block}}

/* task-163: 主页【任务快捷带】+【三扇门】+ 任务总览列表
   ★ lead 的原则: 加一个（任务带）就减一个（场景磁贴）—— 主页区块数净持平或净减少。 */
/* task-169: 任务带的小标题（小字，不抢 H1 权重） */
.taskh{font-size:14px;font-weight:700;color:var(--fg);margin:16px 0 4px}
/* task-170: 【按实际条数自适应】—— 我原来写死 repeat(4,...) 是按"8 个任务"设计的，
   而现在只有 3 个任务 ⇒ 第 4 列空着，实测卡片 280px×3 = 880px，容器 1148px，
   ★ 右边空约 270px，截图上一眼像"没做完"。
   改成 auto-fit + minmax: 无论 3 个还是 8 个任务都铺满、不留空列。 */
.taskstrip{display:flex;flex-wrap:wrap;gap:8px;margin:0;min-width:0}
/* task-171: 紧凑 chips —— 小标题与 chips 同一行，视觉重量【低于门】 */
.taskbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:14px 0 4px}
.taskbar .taskh{margin:0}
.taskstrip a{display:inline-flex;align-items:center;padding:5px 11px;border:1px solid var(--line);
 border-radius:999px;background:var(--card);text-decoration:none;color:var(--fg);
 font-size:13px;font-weight:600;white-space:nowrap}
.taskstrip a:hover{border-color:var(--brand);color:var(--brand)}
.taskstrip a{display:block;padding:11px 13px;border:1px solid var(--line);border-radius:var(--r-md);
 background:var(--card);text-decoration:none;color:var(--fg);min-width:0}
.taskstrip a:hover{border-color:var(--brand)}
.taskstrip b{display:block;font-size:14px;font-weight:700;margin-bottom:2px}
.taskstrip i{display:block;font-size:11.5px;color:var(--muted);font-style:normal;line-height:1.45}
.threedoors{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px;margin:16px 0 6px}
.tasklist{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:12px;margin:16px 0}
.taskitem{display:block;padding:14px 16px;border:1px solid var(--line);border-radius:var(--r-lg);
 background:var(--card);box-shadow:var(--sh-card);text-decoration:none;color:var(--fg)}
.taskitem:hover{border-color:var(--brand);box-shadow:var(--sh-hover)}
.taskitem b{display:block;font-size:15.5px;font-weight:720;margin-bottom:3px}
.taskitem i{display:block;font-size:12.5px;color:var(--muted);font-style:normal;line-height:1.5}
.taskitem em{display:inline-block;margin-top:6px;font-size:11.5px;color:var(--brand);
 font-style:normal;font-weight:650}
@media(max-width:900px){.taskstrip{grid-template-columns:repeat(2,minmax(0,1fr))}
 .threedoors{grid-template-columns:minmax(0,1fr)}}
@media(max-width:440px){.taskstrip{grid-template-columns:minmax(0,1fr)}}
.pricelegend{font-size:12.5px;color:var(--muted);margin:2px 0 12px;line-height:1.6}
/* task-175: 干净官网可验证声明（事实陈述，非营销话术） */
.cleanclaim{font-size:12.5px;color:var(--muted);margin:2px 0 10px;line-height:1.6;
 padding:8px 12px;border-left:2px solid var(--brand);background:var(--brand-soft);
 border-radius:0 var(--r-md) var(--r-md) 0}
.linknote{font-size:11.5px;color:var(--muted);align-self:center;white-space:nowrap}
/* task-177: 视觉隐藏但读屏可见（无障碍） */
.vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
 clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* task-180: MCP 配置骨架（可复制）—— 从「看」到「能用」 */
.cfgblock{margin:12px 0;border:1px solid var(--line);border-radius:var(--r-lg);
 background:var(--card);padding:12px 14px}
.cfgh{font-size:12.5px;font-weight:650;color:var(--fg);margin-bottom:8px}
.cfgwrap{display:flex;gap:8px;align-items:flex-start;flex-wrap:wrap}
.cfgpre{flex:1;min-width:0;margin:0;padding:10px 12px;overflow-x:auto;
 background:var(--brand-soft);border-radius:var(--r-md);font-size:12.5px;
 font-family:ui-monospace,SFMono-Regular,Menlo,monospace;white-space:pre-wrap;
 word-break:break-all}
.cfgcopy{flex:none;white-space:nowrap}
.cfgnote{font-size:11.5px;color:var(--muted);margin-top:8px;line-height:1.6}
/* task-184: FAQ 折叠（数据驱动） */
.faqblock{margin:14px 0;border-top:1px solid var(--line);padding-top:12px}
.faqh{font-size:13px;font-weight:650;color:var(--fg);margin-bottom:8px}
details.faq{border:1px solid var(--line);border-radius:var(--r-md);margin-bottom:8px;background:var(--card)}
details.faq summary{cursor:pointer;padding:10px 12px;font-size:13px;font-weight:600;list-style:none}
details.faq summary::-webkit-details-marker{display:none}
details.faq summary::before{content:'▸ ';color:var(--brand)}
details.faq[open] summary::before{content:'▾ '}
details.faq .faqa{padding:0 12px 12px;font-size:12.5px;color:var(--muted);line-height:1.65}
/* task-185: 更新可见化（7 天条形，折进数字牌那一格） */
/* task-186 实测定位: 我原想「折进那一格」，模板插入点在 statband 之前，
   实际渲染成数字牌【上方】的一条窄带（实测 y=466 vs 数字牌 y=565）。
   如实报此点，并用 CSS 把它贴到数字牌那一块: 收紧下边距 + 右对齐。 */
.updtrend{display:flex;align-items:center;justify-content:flex-end;gap:8px;
margin:0 0 -6px;font-size:11.5px;color:var(--muted);flex-wrap:wrap}
.updtrend .utb{letter-spacing:1px;color:var(--brand);font-size:13px;line-height:1}
.scnote{font-size:11.5px;color:var(--muted);font-weight:400;line-height:1.5;
 margin:2px 0 8px;max-width:44ch}
.tag.price-free{background:var(--brand-soft);color:var(--brand);font-weight:650}
.tag.price-unk{background:transparent;color:var(--muted);border:1px dashed var(--line)}
/* task-190: /mcp/ 页面（分发 skilltide-mcp） */
.mcph1{font-size:clamp(24px,3.4vw,34px);font-weight:760;letter-spacing:-.02em;margin:6px 0 8px}
.mcpwho{font-size:12.5px;color:var(--muted);border-left:2px solid var(--brand);
 padding:8px 12px;background:var(--brand-soft);border-radius:0 var(--r-md) var(--r-md) 0;margin:10px 0}
.mcprow{border:1px solid var(--line);border-radius:var(--r-md);padding:10px 12px;margin-bottom:8px}
.mcprow code{font-size:12.5px;color:var(--brand);font-weight:650}
.mcprow p{margin:5px 0 0;font-size:12.5px;color:var(--muted);line-height:1.6}
.mcpdiff{border-left:2px solid var(--line2);padding:2px 0 2px 12px;margin-bottom:10px}
.mcpdiff b{font-size:13px}
.mcpdiff p{margin:3px 0 0;font-size:12.5px;color:var(--muted);line-height:1.6}
.mcpcode{max-height:520px;overflow:auto;border:1px solid var(--line);border-radius:var(--r-lg);
 background:var(--card)}
.mcpcode pre{margin:0;padding:14px;font-size:11.5px;line-height:1.55;
 font-family:ui-monospace,SFMono-Regular,Menlo,monospace;white-space:pre;overflow-x:auto}

/* task-199: 首页【新手从这里开始】—— 8 张工具卡（首屏可点的东西） */
.nb-block{margin:16px 0 6px}
.nb-h{font-size:17px;font-weight:730;margin:0 0 4px}
.nb-note{font-size:12.5px;color:var(--muted);margin:0 0 10px}
.nb-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:10px}
.nb-card{display:flex;flex-direction:column;gap:4px;padding:12px 14px;min-width:0;
 border:1px solid var(--line);border-radius:var(--r-lg);background:var(--card);
 box-shadow:var(--sh-card);text-decoration:none;color:var(--fg)}
.nb-card:hover{border-color:var(--brand);box-shadow:var(--sh-hover);transform:translateY(-2px)}
.nb-nm{font-size:14.5px;font-weight:700}
.nb-one{font-size:12px;color:var(--muted);line-height:1.5;display:-webkit-box;
 -webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.nb-tags{display:flex;gap:5px;flex-wrap:wrap;margin-top:2px}
.nb-tag{font-size:10.5px;font-style:normal;padding:1px 6px;border-radius:999px;
 background:var(--brand-soft);color:var(--brand);font-weight:600}
.nb-more{font-size:12.5px;margin:8px 0 0}

/* task-209: 任务页【横向对比表】（哪个好用）—— 窄屏可横向滚动 */
.cmp{margin:20px 0 6px}
.cmp h2{font-size:16px;font-weight:720;margin:0 0 8px}
.cmpwrap{overflow-x:auto;-webkit-overflow-scrolling:touch;border:1px solid var(--line);
 border-radius:var(--r-lg);background:var(--card)}
.cmptab{border-collapse:collapse;width:100%;min-width:560px;font-size:12.5px}
.cmptab th,.cmptab td{padding:9px 11px;text-align:left;border-bottom:1px solid var(--line2);
 vertical-align:top}
.cmptab th{font-weight:650;font-size:11.5px;color:var(--muted);white-space:nowrap;
 background:var(--brand-soft)}
.cmptab tr:last-child td{border-bottom:0}
.cmptab td:first-child{font-weight:650;white-space:nowrap}
.cmpnote{font-size:11.5px;color:var(--muted);margin:7px 0 0;line-height:1.6}

/* task-219: 详情页标签云（真实字段 + 真实条目数） */
.tcloud{margin:22px 0 6px}
.tcloud h2{font-size:16px;font-weight:720;margin:0 0 9px}
.tcloud-tags{display:flex;flex-wrap:wrap;gap:8px}
.tcloud-tag{display:inline-flex;align-items:center;gap:7px;padding:6px 12px;
 border:1px solid var(--line);border-radius:999px;background:var(--card);
 font-size:12.5px;font-weight:600;color:var(--fg);text-decoration:none}
.tcloud-tag:hover{border-color:var(--brand);background:var(--brand-soft);color:var(--brand)}
.tcloud-n{font-size:11px;font-weight:500;color:var(--muted);
 border-left:1px solid var(--line);padding-left:7px}
.tcloud-tag:hover .tcloud-n{color:var(--brand);border-left-color:var(--brand)}
.tcloud-note{font-size:11.5px;color:var(--muted);margin:9px 0 0;line-height:1.6}
