@import url('/vendor/inter/5.3.0/index.css');
/* 右边这 16px 和设置行一样，是给覆盖式滑块让出的道；不留的话这一块会比上面几行宽出
   一截，它那条上边线直贴到卡片边上。
   上下那两个数也和设置行同一份（`.settingsscroll .settingrow` 的 10px）：这一块是同一
   列里的又一行，上面写 16 下面写 12 的话，它和前一行之间就比上面每两行之间宽出一截，
   同一屏里读得出来。 */
.settingscard .settingsscroll .sidebarsetting{padding:10px 12px 10px 0!important;margin:0 16px 0 0!important}
.settingscard .settingsscroll .settingsortcontrols>[hidden]{display:none}
.board-optional-number{display:flex;align-items:center;gap:12px;flex-direction:row-reverse}.board-number-fields[hidden]{display:none}
.board-number-control input::-webkit-inner-spin-button,.board-number-control input::-webkit-outer-spin-button{appearance:none;margin:0}.board-number-control input{appearance:textfield;-moz-appearance:textfield}
/* `--settings-gap` 是标题和第一行之间那段留白，也是那道影子的门槛：它长在滚动区的上
   内边距上，所以滚掉它就等于两块重合。CSS 和 `app.js` 的判据都读这一个值。 */
.settingscard.settingscard{--settings-gap:16px;width:871px;max-width:calc(100vw - 32px);height:614px;max-height:calc(100dvh - 32px);border-radius:24px;grid-template-columns:274px minmax(0,1fr);grid-template-rows:auto minmax(0,1fr);overflow:clip;background:var(--page)}
.settingscard.settingscard>.board-local-nav{position:relative;grid-column:1;grid-row:1/3;display:flex;flex-direction:column;align-items:stretch;padding:10px;gap:4px;background:var(--ground);border:0}
/* 左栏分块：一个小标题带一组条目。第一块贴着栏顶，后面每块自己往上让 12px 断开。 */
.settingscard.settingscard>.board-local-nav .board-local-nav-caption{margin:12px 0 0;font-size:13px;color:var(--muted);padding:4px 8px 8px}
.settingscard.settingscard>.board-local-nav .board-local-nav-caption:first-child{margin-top:0}
.settingscard.settingscard>.board-local-nav button{flex:0 0 auto;justify-content:flex-start;padding:8px;border:0;border-radius:10px;font-size:14px;min-height:36px;font-weight:500}
.settingscard.settingscard>.board-local-nav button{display:flex;align-items:center;gap:8px}.settingscard.settingscard>.board-local-nav button svg{width:20px;height:20px;fill:currentColor;stroke:none;flex:none}
/* 这一列自己不铺底，当前那一条的填充由 `.navglide` 那块滑过去的玻璃提供——跟筛选条上
   四枚视图、左侧抽屉那一列是同一套做法。两边都铺的话，静止态就是一块不透明的
   `--picked` 压在玻璃上面，切换时只看得见它瞬间换位置，滑动的那块从头到尾被盖住。
   文字色走 `--glass-text`：这一列站在玻璃上，跟着卡片的 `--ink` 走会在玻璃的提亮
   之后偏灰。按钮抬到玻璃之上，玻璃自己是 `z-index:0`。 */
.settingscard.settingscard>.board-local-nav>:is(button,.board-local-nav-caption){position:relative;z-index:1}
.settingscard.settingscard>.board-local-nav button{color:color-mix(in srgb,var(--glass-text) 65%,transparent)}
.settingscard.settingscard>.board-local-nav button[aria-selected=true]{background:none;box-shadow:none;color:var(--glass-text)}
.settingscard.settingscard>.board-local-nav button:hover{color:var(--glass-text)}
/* 这块玻璃扣在一条 10px 圆角的按钮上，跟着它走；`.navglide` 的默认 8px 是给筛选条上
   那排药丸的。 */
.settingscard.settingscard>.board-local-nav>.navglide{border-radius:10px}
/* 顶边那道高光不要：它是给浮在页面上的玻璃打边用的，而这一栏嵌在卡片里、上边贴着卡片
   自己的圆角，那道白线横在「设置」上面，读起来像卡片被切成了上下两截。其余三面的内描边
   和落影照旧。 */
.settingscard.settingscard.settingscard>.board-local-nav{
  box-shadow:inset 1px 0 0 var(--glass-low),inset -1px 0 0 var(--glass-low),inset 0 -1px 0 var(--glass-low),var(--glass-shadow)}
/* 标题和下面那一组之间留 24px：这一栏没有分隔线也不吸顶，标题与内容之间只剩这一段
   留白在说「上面那行是这一页的名字」。12px 和组内两行之间的间距是同一个量级，读下来
   标题像是第一行设置。 */
.settingscard.settingscard .settingshead{grid-column:2;grid-row:1;padding:32px 32px 24px;background:transparent;border:0}
.settingscard .settingshead h2{font-size:20px;font-weight:500;line-height:28px}
.settingscard .settingshead button{width:24px;height:24px;border-radius:50%;background:var(--surface)}
.settingscard .settingshead button svg{width:16px;height:16px}
.settingscard.settingscard .settingsscroll{padding:var(--settings-gap) 32px 32px;min-height:0;overflow-y:auto}
/* 右侧这一栏和配置页是同一套分区：标题与页底是 `--page`，每组开关行坐在一张 `--ground`
   灰卡上，16px 圆角、左内边距 12px，行的分隔线在卡片左沿内 12px 收住——即 BoardUI
   `SettingsCard` 的尺寸。「这台电脑」那张摘要卡也坐在这张灰卡上。 */
.settingscard .settingsscroll>.settinggroup{background:var(--ground);border-radius:16px;padding:0 0 0 12px}
.settingscard .settingsscroll>.settinggroup>h3{display:none}
.settingscard .settingsscroll .settingrow{min-height:52px;padding:10px 10px 10px 0;gap:16px;border-top:0;border-bottom:1px solid var(--line-soft)}
.settingscard .settingsscroll .settingrow:last-child{border-bottom:0}
/* 一组里排在设置行后面的分区（「左侧导航」是唯一一处）不自己画上边线：这一层的线挂在
   行的下沿，两条 1px 落在同一条 y 上就成了一道 2px 的粗线。 */
.settingscard .settingsscroll .settingrow+.sidebarsetting{border-top:0}
.settingscard .settingsscroll .settingrow b{font-size:14px;line-height:20px;font-weight:400}
.settingscard .settingsscroll .settingrow small{font-size:12px;line-height:18px;margin-top:2px;max-width:none}
.settingscard .settingsscroll .gselect{min-width:90px;min-height:32px;height:32px;padding:6px 8px;font-size:13px;border-radius:8px}
.settingscard .board-number-control{gap:5px;font-size:12px}.settingscard .board-number-control input{width:64px;height:32px;padding:6px;border-radius:8px;font-size:13px}
.settingscard .board-number-control button{min-height:32px;padding:4px 8px;font-size:12px}
@media(max-width:760px){.settingscard.settingscard{display:flex;flex-direction:column;width:calc(100vw - 24px);max-width:calc(100vw - 24px)}.settingscard.settingscard>.board-local-nav{flex-direction:row;flex-shrink:0;overflow-x:auto;border-right:0}.settingscard.settingscard>.board-local-nav .board-local-nav-caption{margin:0;padding:0 4px 0 8px;align-self:center;white-space:nowrap}.settingscard.settingscard>.board-local-nav .board-local-nav-caption:first-child{padding-left:0}.settingscard.settingscard .settingshead{padding:16px 20px 12px}.settingscard.settingscard .settingsscroll{padding:var(--settings-gap) 20px 20px;flex:1}}
/* Translucent navigation experiment, using browser-native backdrop compositing. */
/* 底色薄到能看见身后的东西在动，可读性交给 `--glass-lume`：Apple 的 regular 变体
   「blurs and adjusts the luminosity of background content」，压暗（暗色）或提亮（浅色）
   身后那一片，而不是拿一层厚白／厚黑把它盖掉。盖掉的那一版底色要 .68 才读得动字，
   代价是玻璃底下什么都看不见，等于一块磨砂塑料。 */
/* 浅色一档要多压一点饱和：提亮是为了让深色的字站得住，可身后多半是肤色和暖色封面，
   同一步提亮会把它们一起推到溢出，整条读成一片花的。暗色反过来，压暗顺带把彩度也
   压住了，不必额外收。 */
/* `--glass-pick` 是选中那块自己的光学：它不铺一层灰，而是在这块玻璃已经合成好的
   底子上再提一档亮度，所以它跟着身后的内容一起变，暗处淡、亮处也淡，唯独比同一条
   上的邻居亮——铺灰的那种做法在亮内容上会变成一块脏斑。
   `--glass-pick-fill` 是它的保底填充，两档都是白：`brightness()` 乘的是零时那块玻璃
   跟着背景一起黑，得有东西垫着。垫的必须是白——白往上加是加光，跟提亮同向；墨色往上
   加是蒙一层灰，浅色下选中那枚就成了整条上唯一发灰的地方。 */
/* 阴影分三层，一层管一件事：1px 那层是接触影，画出玻璃和它底下那张纸之间的那条缝；
   中间一层是本体投影；最远那层大而极淡，是环境光被这块板挡住留下的那片。单层做不到
   ——同一个模糊半径既要贴着边缘又要铺开一大片，只能取中间值，出来是一圈均匀的灰晕，
   看着像贴在背景上的剪纸，浮不起来。三层都用冷灰 `#111827` 而不是纯黑：这一层底下
   多半是肤色和暖色封面，纯黑压上去发脏。暗色那一档不靠加更多黑——玻璃和背景本来
   就都是深的，再黑也分不出层，分层交给上缘那道 `--glass-rim` 亮线。 */
/* `--glass-pick-shadow` 是选中那一小块自己的影，跟整块浮层的 `--glass-shadow` 分开定，
   但两档都得跟着主题走。写死一个值的后果只在浅色下看得见：整块浮层在浅色里投的是
   0.06 的冷灰，一枚三十像素的圆片却投 0.14 的黑，比托着它的那整块还重，读起来是贴在
   玻璃上的一片纸，而不是玻璃自己亮起来的一块。深色那档比整块淡是对的——那里分层靠的
   是上缘那道亮线，影再重也只是把它按进底色里。 */
/* 滑板那一下的缓动是一条弹簧曲线，不是手挑的贝塞尔：`linear()` 里那串数是把一个
   `stiffness:1700 damping:46 mass:1` 的弹簧按 240Hz 跑完再采样下来的（算法出自
   liquid-gooey 的 spring.ts，MIT）。手挑的贝塞尔只能描出「快出慢收」这一类形状，
   冲过头再荡回来那一段它画不出——四次控制点里没有超出 0..1 的余地。
   313ms、峰值 1.103：冲过落点一成，一次回荡就收住。冲过头多少不必再另算一遍，
   它本来就按这一跳的跨度成比例——弹簧拉得越长，甩过去越远。 */
:root{--spring-pane:linear(0,0.1515,0.3211,0.5922,0.8223,0.937,1.0477,1.096,1.1029,1.0901,1.0641,1.0455,1.021,1.0036,0.9937,0.9905,0.9895,0.9912,0.993,0.9959,0.9983,0.9994,1.0005,1.001,1.0011,1.0009,1.0007,1.0005,1);--spring-pane-ms:313}
/* 按钮和滑块手柄松手回弹走同一套弹簧的短程版：那一下要走的距离只有几个百分点，
   跨度短就得更硬、收得更快，313ms 那一档挂上去会拖成一次缓慢的呼吸。
   208ms、峰值 1.088（stiffness:3600 damping:68 mass:1）。 */
:root{--spring-press:linear(0,0.1659,0.4268,0.6816,0.8795,1.0066,1.084,1.0861,1.069,1.0457,1.0241,1.0079,0.998,0.9933,0.9923,0.9934,0.9954,0.9973,0.9995,1.0003,1.0006,1.0007,1.0005,1.0004,1);--spring-press-ms:208}
/* 面上那两团光是屋里的光源落在玻璃上的反射，位置一直在极慢地挪。钉死的高光会把玻璃
   变成一张贴图——真玻璃对着一屋子的光，人一动、窗外云一过，面上的亮斑就换个地方，
   正是这一点让它读成一块有厚度的实物而不是一层半透明的涂层。
   两团大小和亮度不同，加起来才不像一只手电筒；两条轨迹的周期是 41s 和 67s，互质，
   合起来四十多分钟不重样，看不出循环点在哪。
   两团的色相由 `--glass-tint-a/b` 给：默认是 `--glass-native-a/b`，也就是这块玻璃自带的
   那一档主题色；用户挑了光晕配色之后，页面把前两枚光晕的颜色写到根上，每一块玻璃跟着
   换色相，尺寸、alpha 与轨迹一概不动。alpha 写成 `color-mix` 的百分比而不是颜色里的
   第四个通道，是因为用户给的是不带透明度的色号，而这两团的浓淡是这块材质自己的事。 */
:root{--glass-fill:rgba(252,253,255,.32);--glass-rim:rgba(255,255,255,.72);--glass-low:rgba(70,80,100,.1);--glass-text:#1d2129;--glass-shadow:0 1px 2px #1118270f,0 8px 18px #11182714,0 24px 48px #11182710;--glass-lift:0 2px 4px #11182714,0 12px 26px #1118271f,0 30px 60px #11182717;--glass-sheen:rgba(255,255,255,.5);--glass-lume:brightness(1.32) saturate(.5);--glass-pick:brightness(1.1) saturate(1.1);--glass-pick-fill:rgba(255,255,255,.52);--glass-pick-shadow:0 1px 2px #1118270f,0 4px 10px #11182714;--glass-native-a:#ffffff;--glass-native-b:#ffffff;--glass-tint-a:var(--glass-native-a);--glass-tint-b:var(--glass-native-b);--glass-drift-a:radial-gradient(20% 20% at 50% 50%,color-mix(in srgb,var(--glass-tint-a) 10%,transparent),color-mix(in srgb,var(--glass-tint-a) 5%,transparent) 42%,transparent 72%);--glass-drift-b:radial-gradient(26% 26% at 50% 50%,color-mix(in srgb,var(--glass-tint-b) 8%,transparent),color-mix(in srgb,var(--glass-tint-b) 4%,transparent) 44%,transparent 74%)}
:root[data-theme="dark"]{--glass-fill:rgba(24,27,33,.24);--glass-rim:rgba(255,255,255,.2);--glass-low:rgba(255,255,255,.05);--glass-text:#eceef3;--glass-shadow:0 1px 2px #00000047,0 10px 22px #00000038,0 28px 56px #0000002b;--glass-lift:0 2px 4px #00000052,0 14px 30px #00000047,0 34px 68px #00000038;--glass-sheen:rgba(230,239,255,.1);--glass-lume:brightness(.5) contrast(1.1);--glass-pick:brightness(1.7) saturate(1.15);--glass-pick-fill:rgba(255,255,255,.13);--glass-pick-shadow:0 1px 2px #00000024,0 6px 14px #0000001f}
@media(prefers-color-scheme:dark){:root:not([data-theme]){--glass-fill:rgba(24,27,33,.24);--glass-rim:rgba(255,255,255,.2);--glass-low:rgba(255,255,255,.05);--glass-text:#eceef3;--glass-shadow:0 1px 2px #00000047,0 10px 22px #00000038,0 28px 56px #0000002b;--glass-lift:0 2px 4px #00000052,0 14px 30px #00000047,0 34px 68px #00000038;--glass-sheen:rgba(230,239,255,.1);--glass-lume:brightness(.5) contrast(1.1);--glass-pick:brightness(1.7) saturate(1.15);--glass-pick-fill:rgba(255,255,255,.13);--glass-pick-shadow:0 1px 2px #00000024,0 6px 14px #0000001f}}
/* WebKit 在能显示 HDR 的屏幕上（iPhone、带 XDR 屏的 Mac）按扩展范围合成滤镜，`brightness()`
   大于 1 算出来的像素比 SDR 白还亮，系统把这几块玻璃当 HDR 内容点亮，页面其余部分相对就暗了
   下去。Chromium 会把滤镜结果收回 SDR，所以只在 WebKit 上换写法：提亮改成往上叠白色填充——
   叠白是在底色和白之间插值，永远到不了白之上。浅色那档的饱和合起来仍是 160%×.5；暗色主体
   本来就是压暗，只换选中那块。 */
@supports (font:-apple-system-body){
  :root{--glass-fill:rgba(252,253,255,.62);--glass-lume:saturate(.5);--glass-pick:none;--glass-pick-fill:rgba(255,255,255,.72)}
  :root[data-theme="dark"]{--glass-pick:none;--glass-pick-fill:rgba(255,255,255,.22)}
  @media(prefers-color-scheme:dark){:root:not([data-theme]){--glass-pick:none;--glass-pick-fill:rgba(255,255,255,.22)}}
}
/* 亮色玻璃用一蓝一灰两团反光建立色差，白色页面上也能辨认移动的光斑；两枚和默认那档
   灰雾配蓝同色，光晕关掉之后界面不会换成另一副色调。两团比深色那档大一圈、浓一档：
   白面反光弱，同一组数值在这里几乎看不见。 */
:root[data-theme="light"]{--glass-native-a:#6686b8;--glass-native-b:#8f98a4;--glass-drift-a:radial-gradient(32% 32% at 50% 50%,color-mix(in srgb,var(--glass-tint-a) 30%,transparent),color-mix(in srgb,var(--glass-tint-a) 16%,transparent) 42%,transparent 72%);--glass-drift-b:radial-gradient(38% 38% at 50% 50%,color-mix(in srgb,var(--glass-tint-b) 25%,transparent),color-mix(in srgb,var(--glass-tint-b) 14%,transparent) 44%,transparent 74%)}
@media(prefers-color-scheme:light){:root:not([data-theme]){--glass-native-a:#6686b8;--glass-native-b:#8f98a4;--glass-drift-a:radial-gradient(32% 32% at 50% 50%,color-mix(in srgb,var(--glass-tint-a) 30%,transparent),color-mix(in srgb,var(--glass-tint-a) 16%,transparent) 42%,transparent 72%);--glass-drift-b:radial-gradient(38% 38% at 50% 50%,color-mix(in srgb,var(--glass-tint-b) 25%,transparent),color-mix(in srgb,var(--glass-tint-b) 14%,transparent) 44%,transparent 74%)}}
/* 光斑铺在一张两倍大的画布上，靠 `background-position` 推着走：画布只有元素两倍大时，
   位置从 0% 到 100% 正好把光斑中心从元素的右下角推到左上角，`-10%` 和 `110%` 那两档
   是让它探出框外一点——真实的光斑不会老老实实待在板子里。半径写 20% 是画布的比例，
   落到元素上就是 40%，跟着元素自己的长宽各向异性地拉成椭圆。
   横竖两根轴各挂一条时长不同的动画：`background-position-x` 和 `-y` 是两个独立属性，
   两条正弦频率不同，合出来是一条李萨如轨迹，不是一个来回滑动的椭圆。 */
@keyframes glassdriftx{
  0%{background-position-x:50%,50%,0}
  12.5%{background-position-x:7.6%,92.4%,0}
  25%{background-position-x:-10%,110%,0}
  37.5%{background-position-x:7.6%,92.4%,0}
  50%{background-position-x:50%,50%,0}
  62.5%{background-position-x:92.4%,7.6%,0}
  75%{background-position-x:110%,-10%,0}
  87.5%{background-position-x:92.4%,7.6%,0}
  100%{background-position-x:50%,50%,0}
}
@keyframes glassdrifty{
  0%{background-position-y:-10%,50%,0}
  12.5%{background-position-y:7.6%,7.6%,0}
  25%{background-position-y:50%,-10%,0}
  37.5%{background-position-y:92.4%,7.6%,0}
  50%{background-position-y:110%,50%,0}
  62.5%{background-position-y:92.4%,92.4%,0}
  75%{background-position-y:50%,110%,0}
  87.5%{background-position-y:7.6%,92.4%,0}
  100%{background-position-y:-10%,50%,0}
}
.board-filter-frame.board-filter-frame.board-filter-frame,.entitytagbar.entitytagbar.entitytagbar,.entitycollectionhead.entitycollectionhead.entitycollectionhead,.drawer.drawer,.drawer.drawer.open,.edge.edge,.top .search.search,.top.top>.ib,.settingscard.settingscard>.board-local-nav{
  background:var(--glass-drift-a),var(--glass-drift-b),linear-gradient(125deg,var(--glass-sheen),transparent 42%,var(--glass-low)),var(--glass-fill);
  background-size:200% 200%,200% 200%,auto;background-repeat:no-repeat,no-repeat,repeat;
  background-position:50% 20%,80% 70%,0 0;
  animation:glassdriftx calc(41s * var(--glow-drift-scale)) linear infinite,glassdrifty calc(67s * var(--glow-drift-scale)) linear infinite;
  animation-play-state:var(--glow-drift-play);
  backdrop-filter:var(--glass-optic,blur(22px)) saturate(160%) var(--glass-lume);-webkit-backdrop-filter:var(--glass-optic,blur(22px)) saturate(160%) var(--glass-lume);
  border:0;box-shadow:inset 0 1px 0 var(--glass-rim),inset 1px 0 0 var(--glass-low),inset -1px 0 0 var(--glass-low),inset 0 -1px 0 var(--glass-low),var(--glass-shadow);
}
/* 侧栏这一块玻璃上的反光归 `.glowlayer`：用户配得了色的三枚光晕按同一套 drift 在这里
   漂。自带那两团留着就是两套光斑叠着走，亮的那一档会把配好的颜色冲淡成灰。
   其余玻璃面仍走自己那两团，只是色相跟着 `--glass-tint-a/b` 换。填充、sheen、内缘亮线
   和 backdrop-filter 全部不动。
   「玻璃原色」那一档（根上挂 `data-glow-native`）例外：光晕整层算作 0，抽屉要把自己
   那两团拿回来，否则侧栏会是全场唯一一块不反光的玻璃。 */
:root:not([data-glow-native]) .drawer.drawer{--glass-drift-a:none;--glass-drift-b:none}
/* 搜索框使用浏览器原生模糊，尺寸变化不依赖异步 SVG 位移贴图。 */
.top .search.search.search{--glass-optic:blur(22px)}
/* 快照里的玻璃使用实底承接光晕；实时页面恢复后再采样背景。 */
html[data-theme-snapshot] :is(.board-filter-frame,.entitytagbar,.entitycollectionhead,.drawer,.edge,.search,.top>.ib,.board-library-menu,.board-glow-menu,.viewglide,.navglide,.settingscard>.board-local-nav,.selectiondock,.batchbar,.tagselection,[data-glass-pane]){backdrop-filter:none!important;-webkit-backdrop-filter:none!important;background-color:var(--ground)!important;transition:none!important}
/* 快照撤掉那一下，材质要淡回来：揭示动画刚停，浮层从实底「啪」地跳成毛玻璃，读起来
   像主题又切了第二次。过渡只写在常态上——进快照那一下正在拍旧状态的快照，拍到一半
   路上的颜色就会闪，所以上面那条规则自己把过渡关掉。 */
.board-filter-frame.board-filter-frame,.entitytagbar.entitytagbar,.entitycollectionhead.entitycollectionhead,.board-library-menu.board-library-menu,.board-glow-menu.board-glow-menu{
  transition:background-color .28s ease,backdrop-filter .28s ease,-webkit-backdrop-filter .28s ease}
.board-filter-frame.board-filter-frame{border-radius:22px;isolation:isolate;color:var(--glass-text);overflow:visible}
.entitytagbar.entitytagbar.entitytagbar,
.entitycollectionhead.entitycollectionhead.entitycollectionhead{border-radius:22px;color:var(--glass-text)}
/* 浮层材质与吸顶归外框，槽位只负责排列内容。 */
.board-filter-frame.board-filter-frame.board-filter-frame.board-filter-frame>[data-filter-row]{position:relative;top:auto;left:auto;
  width:auto;margin:0;min-width:0;z-index:auto;border:0;box-shadow:none;background:none;
  backdrop-filter:none;-webkit-backdrop-filter:none;animation:none}
.board-filter-frame>[data-filter-row]::before,.board-filter-frame>[data-filter-row]::after{display:none}
.board-filter-frame .entityviews{display:flex;flex:none;gap:6px}
.board-filter-frame .entityviews[hidden]{display:none}
/* 玻璃层只把这三格之间的间距收一档，不动它们谁滚谁不滚：整条一起滚的话左端那一档
   也跟着走，而它正是这条筛选条上唯一离开就读不懂的东西。 */
.board-filter-frame .entitytagbar .filterscroll{gap:6px}
.board-filter-frame .entityviews .pill{height:30px;padding:0 10px;font-size:13px;white-space:nowrap}
/* 相接的复核横条由页面的单层玻璃承接；独立横条和骨架使用共享玻璃材质。 */
.entitytagbar .pill,.entitycollectionhead h3{color:var(--glass-text)}
.entitytagbar .pill[data-tag]:not([aria-pressed="true"]){border-color:var(--glass-low);border-style:dashed}
.entitytagbar .pill[data-tag]:not([aria-pressed="true"]):hover{border-style:solid}
/* 标签后面那个数在这块玻璃上要自己降一档。flat 层那条降的是 --muted，而在这一层里
   --muted 和 --ink-2 都映射到 --color-text-secondary，是同一个值——照搬过来，计数
   和标签仍然一样亮。按这一排自己的文字色降档，口径跟未选中的视图胶囊那一档同源。
   13px 的标签配 11px 的数：差一档能看出来，再小就不是附注而是难以辨认了。 */
.board-filter-frame.board-filter-frame .pill .n{margin-left:6px;font-size:11px;
  color:color-mix(in srgb,var(--glass-text) 55%,transparent)}
.board-filter-frame.board-filter-frame .pill:hover .n,
.board-filter-frame.board-filter-frame .pill[aria-pressed="true"] .n{
  color:color-mix(in srgb,var(--glass-text) 80%,transparent)}
/* 这块玻璃回答的是「你在哪儿」：侧栏的当前项、四枚视图里生效的那一枚、实体页正在看
   的那一档媒体，都是位置。白填充垫底、在已经合成好的底子上再提一档亮度、整圈 rim
   描边。铺一层墨色灰是另一种东西——它在亮内容上是块脏斑，浅色下又是整条里唯一发灰的
   地方。 */
.entitytagbar.entitytagbar .pill[aria-pressed="true"]{
  background:linear-gradient(180deg,var(--glass-sheen),transparent 62%),var(--glass-pick-fill);
  backdrop-filter:var(--glass-pick);-webkit-backdrop-filter:var(--glass-pick);
  color:var(--glass-text);border-color:transparent;
  box-shadow:inset 0 0 0 1px var(--glass-rim),var(--glass-pick-shadow)}
/* 上面那条对四枚视图和左端那一档媒体类型都不适用：这两排的填充各由一块 `.viewglide`
   滑过去的玻璃给，四枚视图那块跟首页是同一块。两边都铺的话，静止态是一块不透明的
   填充压在玻璃上面，切换时也只看得见它瞬间换位置，滑动的那块从头到尾被盖在下面。
   选中和悬停都只提字色。 */
.entitytagbar.entitytagbar .pill[data-entity-state],
.entitytagbar.entitytagbar .pill[data-entity-state]:hover,
.entitytagbar.entitytagbar .pill[data-entity-state][aria-pressed="true"],
.entitytagbar.entitytagbar .mediaviewbutton,
.entitytagbar.entitytagbar .mediaviewbutton:hover,
.entitytagbar.entitytagbar .mediaviewbutton[aria-pressed="true"]{
  border:0;background:none;backdrop-filter:none;-webkit-backdrop-filter:none;box-shadow:none}
.entitytagbar.entitytagbar .pill[data-entity-state],
.entitytagbar.entitytagbar .mediaviewbutton{color:color-mix(in srgb,var(--glass-text) 60%,transparent)}
.entitytagbar.entitytagbar .pill[data-entity-state]:hover,
.entitytagbar.entitytagbar .pill[data-entity-state][aria-pressed="true"],
.entitytagbar.entitytagbar .mediaviewbutton:hover,
.entitytagbar.entitytagbar .mediaviewbutton[aria-pressed="true"]{color:var(--glass-text)}
/* 那几枚字形要压在玻璃上面，不然滑过去的时候被盖住一路暗过去——跟首页四枚视图同一条。 */
.entitytagbar.entitytagbar .mediaviewbutton{position:relative;z-index:1}
/* 照片视图下这条只剩左端那一组，后面没有东西可隔；分隔线留着就是一条指向空白的竖线。 */
.entitytagbar[data-media-only] .sep{display:none}
/* 版式、大小这类分段开关问的也是「你在哪儿」。滑块的位置和几何归分段器自己管，这里
   只换材质与配色：那一套是给 flat 面配的，一块灰底衬一枚不透明的白滑块，摆到浮层上
   就是整条里唯一一块实心的面，读起来像贴上去的另一个控件；字色取的也是 flat 面的
   --muted/--ink，跟旁边同一排的排序键差一档。壳撤掉，滑块换成选中态那块玻璃。 */
.entitytagbar.entitytagbar .iconswitch[data-board-segments],
.entitycollectionhead.entitycollectionhead .iconswitch[data-board-segments],
.board-filter-frame.board-filter-frame .iconswitch[data-board-segments]{background:none}
.entitytagbar.entitytagbar .iconswitch>label,
.entitycollectionhead.entitycollectionhead .iconswitch>label,
.board-filter-frame.board-filter-frame .iconswitch>label{
  color:color-mix(in srgb,var(--glass-text) 62%,transparent)}
.entitytagbar.entitytagbar .iconswitch>label:hover,
.entitytagbar.entitytagbar .iconswitch>label:has(input:checked),
.entitycollectionhead.entitycollectionhead .iconswitch>label:hover,
.entitycollectionhead.entitycollectionhead .iconswitch>label:has(input:checked),
.board-filter-frame.board-filter-frame .iconswitch>label:hover,
.board-filter-frame.board-filter-frame .iconswitch>label:has(input:checked){color:var(--glass-text)}
/* 排序键回答的是「这一列按什么排」——一个参数的当前值，不是一个位置，所以不占那块
   玻璃：同一种材质担两种语义，这一排读起来就成了另一组导航。当前值由字自己说：整排
   八九个候选都退到六成，生效的那枚回到满值再加半档字重。只差字重不够——一排等亮度的
   字里，扫一眼看不出哪个粗一点。这一排里的「换一批」不在其中：它是动作不是参数，走下面
   那条强调档，字色由它自己给。 */
.entitycollectionhead.entitycollectionhead .sorts button:not(.batchaction),
.board-filter-frame.board-filter-frame .sorts button:not(.batchaction){
  color:color-mix(in srgb,var(--glass-text) 62%,transparent)}
.entitycollectionhead.entitycollectionhead .sorts button:not(.batchaction):hover,
.board-filter-frame.board-filter-frame .sorts button:not(.batchaction):hover{color:var(--glass-text)}
.entitycollectionhead.entitycollectionhead .sorts button[aria-pressed="true"],
.board-filter-frame.board-filter-frame .sorts button[aria-pressed="true"]{
  background:none;backdrop-filter:none;-webkit-backdrop-filter:none;
  color:var(--glass-text);border-color:transparent;box-shadow:none;font-weight:500}
.board-filter-frame.board-is-stuck::before,.board-filter-frame.board-is-stuck::after{display:none}
.board-filter-frame.board-filter-frame .tagbar{border-radius:22px 22px 0 0}
.board-filter-frame.board-filter-frame .count{border-radius:0 0 22px 22px}
.board-filter-frame.board-filter-frame .pill{color:var(--glass-text)}
.board-filter-frame.board-filter-frame .tagbar .pill:is([data-tag],[data-follow-tag],[data-follow-provider]):not([aria-pressed="true"]){border-color:var(--glass-low)}
/* 四枚视图之间只有一块玻璃在移动，不是四块各自亮灭：Apple 把同一层里的玻璃先合成
   再形变（`GlassEffectContainer` 的 "fluidly morphing Liquid Glass shapes into each
   other"），落到这一排就是先拉长盖住起点和终点、再收拢到新的那一枚。
   几何由 app.js 按当前那枚的实际位置写进来，这里只管形状和材质；四枚自己不画边框，
   一排里唯一的填充就是这块玻璃，看的人不必在四个框里再找哪个亮着。 */
/* `left:0` 不能省：只写 `top` 的话水平方向还是 auto，绝对定位就回落到它作为第一个
   子元素本该待的静态位置——也就是 `.board-filter-frame` 那一圈内边距之后，再叠上按
   `offsetLeft` 算的位移，整块正好右移一个内边距，盖不住选中那枚的左半边。 */
/* 它挂在 `.board-filter-frame` 上而不是 `#tagbar` 里：那一排要横滚，`overflow-x:auto`
   会把另一根轴一起算成滚动，纵向再怎么弹也在框沿被切平。挪到外面这一层，弹过头的那
   几像素落在 `#tagbar` 的内边距里，仍在同一块玻璃的合成范围内——`isolation:isolate`
   把这块玻璃定成了 backdrop root，出了这个框，`--glass-pick` 采不到东西就成了一块
   死白。横向裁切的活由 app.js 接手：滚出这一排的可视范围就收起来。 */
/* 形变走 `scale` 而不是动 `width`：宽度是布局属性，每一帧都要让整份文档重新排版，
   合成线程碰不到它，主线程一忙这块玻璃就跟着卡住。缩放和位移各占一个独立属性，两段
   动画都交给合成线程，主线程正在重算样式时它们照样走完。
   代价是描边和圆角跟着缩放变形——被拉长的那一瞬圆角扁一点、边细一点。这一下恰好就是
   要的：一块软东西被拽着走，本来就该在跑的方向上抻开。
   缩放的原点留在正中，两端一起外扩；位移写在 `translate` 属性上，不看这个原点。 */
.viewglide.viewglide,.drawer.drawer>.navglide,.board-local-nav>.navglide{position:absolute;left:0;top:0;z-index:0;pointer-events:none;
  border-radius:8px;will-change:translate,scale;
  /* 高光从上往下，不走那道 125° 对角线：对角线是按盒子自己的长边铺的，在一枚
     三十来像素高的药丸上，转折点正好落在中间，静止看是左右两块拼起来的。 */
  background:linear-gradient(180deg,var(--glass-sheen),transparent 62%),var(--glass-pick-fill);
  backdrop-filter:var(--glass-pick);-webkit-backdrop-filter:var(--glass-pick);
  /* 描边走满一圈，不只压上缘那一道：这块要能在一排同色的字里被一眼认出来，只有顶上
     一条亮线时，它和邻居的差别全靠那点提亮，亮内容上就分不出来了。
     落影按这块的尺寸缩过：整条筛选条那三层是给一块二十几像素圆角的板算的，原样套到
     一枚三十来像素高的药丸上，最远那层比药丸本身还大一圈，看着是它在发光而不是浮起。 */
  box-shadow:inset 0 0 0 1px var(--glass-rim),var(--glass-pick-shadow)}
.viewglide.viewglide[hidden],.drawer.drawer>.navglide[hidden],.board-local-nav>.navglide[hidden]{display:none}
/* 媒体那一档的按钮是正圆，这块跟着它走：方玻璃扣在圆按钮上，四个角先露出来。 */
.viewglide.viewglide-round{border-radius:50%}
/* 侧栏那一列是竖排，圆角照按钮自己的 10px 走，不跟着那一排药丸的 8px。
   它住在滚动容器外面、抽屉这块玻璃里面，`z-index:-1` 把它压回内容底下：抽屉自己带
   `backdrop-filter`，那一层已经是个层叠上下文，负层号只会落到抽屉的面之上、那一列
   的字之下。写 0 的话它是这层里唯一的定位元素，整块盖住下面所有的字。 */
.drawer.drawer>.navglide{border-radius:10px;z-index:-1}
/* 文字要压在那块玻璃上面，否则滑过去的时候字被盖住一路暗过去。 */
.board-filter-frame.board-filter-frame .tagbar .pill:is([data-state],[data-follow-filter]){position:relative;z-index:1}
/* 按下去那一下归手，弹回来那一下归弹簧。按住立刻缩到 96%——这一步要跟手，隔两百
   毫秒才动读成的是「点了没反应」；松开才交给弹簧，冲过原尺寸一点点再收住，手指离开
   以后那块东西还自己动了一下，捏着的是软的不是一张贴纸。
   缩放走独立的 `scale` 属性：`transform` 那一格上还挂着别的位移，挤进去只能留一个。
   窄栏那条连着写了填充，它自己本来就有一段——`transition` 是整份覆盖，漏掉的那段
   会连同悬停的渐变一起没了。 */
.dnav button,.pill,.sorts button{transition:scale calc(var(--spring-press-ms) * 1ms) var(--spring-press)}
.edge button{transition:scale calc(var(--spring-press-ms) * 1ms) var(--spring-press),background .12s}
.dnav button:active,.pill:active,.sorts button:active,.edge button:active{scale:.96;transition:scale .06s ease-out}
/* 换一批和实体批量键走强调档：这一排其余的是排序开关，它们只是同一份列表的看法，
   而这两枚是动作。面色取全站那两个 token，压上去跟每一颗主按钮一样提亮一档；圆角随这
   一条上的按钮取 7px，不取强调档那副文字键的盒子。选中态归排序键，这两枚只有悬停。 */
.board-filter-frame.board-filter-frame .sorts .batchaction,.entitycollectionhead.entitycollectionhead .sorts .batchaction{color:#fff;background:var(--board-blue);border:0;border-radius:7px;box-shadow:var(--elevation-xs)}
.top.top,body.board-scrolled .top.top{background:transparent;box-shadow:none;backdrop-filter:none;border:0}
/* 顶栏这一条本身不铺任何底：玻璃是搜索框和右边那几个图标钮各自一块，它们中间的空处
   直接通到内容。往那片空处垫一条压制带能让滚上来的字不那么碎，代价是整条顶栏成了一块
   不透光的板——玻璃两边各留一段实色，比穿帮更扎眼，而这一屏铺开玻璃就是为了看见底下
   在动。字碎归字碎，那几块玻璃自己压得住它们各自身后那一片。 */
.top .search.search{border-radius:999px;padding-left:16px}
.top.top>.ib{border-radius:50%}
.drawer.drawer{border-radius:26px}.edge.edge{border-radius:24px}
.drawer.drawer .dnav button:not([aria-pressed="true"]),.edge.edge button:not([aria-pressed="true"]){color:var(--glass-text)}
/* 侧栏的当前项跟筛选条上滑动的那一块是同一种东西：一块提亮的玻璃压在侧栏这块玻璃上，
   白填充垫底、整圈 rim 描边、两层落影。这一屏铺开玻璃之后，一块蓝实底就成了唯一不
   透光的地方，看着像贴上去的另一套控件；蓝色在这套配色里只归焦点环和链接，导航的
   当前项不靠颜色说话，靠它比邻居高出一层。
   抽屉那一列的这块玻璃由 `.navglide` 一块在列间滑，按钮自己只管字色：两边都铺的话，
   静止态是一块不动的底压在滑过来的玻璃上，切换时只看得见它瞬间换位置。窄栏那一列
   是图标，一列里认哪个亮着靠的就是那一格自己，它照旧各铺各的。
   `filter:none` 不能省：抽屉那边给当前项的悬停和按下写了 `brightness(1.08)`，留着
   会把这块玻璃连同它身后的内容一起推亮一档，指过去整块发白。 */
.drawer.drawer.drawer .dnav button[aria-pressed="true"],
.drawer.drawer.drawer .dnav button[aria-pressed="true"]:hover,
.drawer.drawer.drawer .dnav button[aria-pressed="true"]:active{
  background:none;backdrop-filter:none;-webkit-backdrop-filter:none;
  color:var(--glass-text);filter:none;box-shadow:none}
.edge.edge.edge button[aria-pressed="true"],.edge.edge.edge button[aria-pressed="true"]:hover{
  background:linear-gradient(180deg,var(--glass-sheen),transparent 62%),var(--glass-pick-fill);
  backdrop-filter:var(--glass-pick);-webkit-backdrop-filter:var(--glass-pick);
  color:var(--glass-text);filter:none;
  box-shadow:inset 0 0 0 1px var(--glass-rim),var(--glass-pick-shadow)}
/* 窄栏没选中的那些悬停只抬一层薄白：不提亮、不描边、不带影，浮起来这件事整列只有
   一处。那一列是纯图标，认哪个亮着靠的就是那一格自己。 */
.edge.edge.edge button:not([aria-pressed="true"]):hover{
  background:color-mix(in srgb,var(--glass-rim) 26%,transparent);color:var(--glass-text)}
/* 抽屉那一列的悬停归那块会滑的玻璃：指到哪一格它滑过去，指针离开这一列再滑回当前
   项。格子底下再垫一层薄白就是两套反馈同时说话——薄白说「鼠标在这儿」，玻璃说「你
   在这儿」，指针停在别的格上时这两句话指着两个地方。 */
.drawer.drawer.drawer .dnav button:hover{background:none;color:var(--glass-text)}
@supports not (backdrop-filter:blur(1px)){.board-filter-frame.board-filter-frame.board-filter-frame,.entitytagbar.entitytagbar.entitytagbar,.entitycollectionhead.entitycollectionhead.entitycollectionhead,.drawer.drawer,.drawer.drawer.open,.edge.edge,.top .search.search,.settingscard.settingscard.settingscard>.board-local-nav{background:var(--ground);animation:none}}
@media(prefers-reduced-transparency:reduce),(prefers-contrast:more){.board-filter-frame.board-filter-frame.board-filter-frame,.entitytagbar.entitytagbar.entitytagbar,.entitycollectionhead.entitycollectionhead.entitycollectionhead,.drawer.drawer,.drawer.drawer.open,.edge.edge,.top .search.search,.top.top>.ib,.settingscard.settingscard.settingscard>.board-local-nav{background:var(--ground);backdrop-filter:none;-webkit-backdrop-filter:none;animation:none}}
/* 面上那两团光停在 `background-position` 给的那一处，不再挪：它讲的是光在动，而这
   台机器上「减少动态效果」说的就是别让不由我操作的东西自己动。停住之后它还是两团
   高光，玻璃仍有厚度，只是这屋里的光不再走了。 */
@media(prefers-reduced-motion:reduce){.board-filter-frame.board-filter-frame.board-filter-frame,.entitytagbar.entitytagbar.entitytagbar,.entitycollectionhead.entitycollectionhead.entitycollectionhead,.drawer.drawer,.drawer.drawer.open,.edge.edge,.top .search.search,.top.top>.ib{animation:none}}
/* Peach-owned media and analytics layouts. */
html.board-high-contrast .board-filter-frame.board-filter-frame.board-filter-frame,html.board-high-contrast .entitytagbar.entitytagbar.entitytagbar,html.board-high-contrast .entitycollectionhead.entitycollectionhead.entitycollectionhead,html.board-high-contrast .drawer.drawer,html.board-high-contrast .edge.edge,html.board-high-contrast .top .search.search,html.board-high-contrast .top.top>.ib{background:var(--ground);backdrop-filter:none;-webkit-backdrop-filter:none;animation:none}
:root{--board-card-foot:color-mix(in srgb,var(--ground) 92%,var(--ink))}
.followmanage.followmanage{width:100%;max-width:1120px}
.followmanage .fmain{width:100%;max-width:1120px;margin-inline:auto;gap:20px}
.followmanage .fmain>.fsec{border:0;border-radius:18px;background:var(--ground);overflow:visible}
.followmanage .fmain>.fsec>.fsechead{background:transparent;padding:20px 24px 8px;border:0;border-radius:18px 18px 0 0;min-height:56px}
.followmanage .fsechead h3{font-size:16px;font-weight:500;letter-spacing:0;line-height:24px}
.configfieldset.configfieldset:not([data-fieldset-type])>.geist-fieldset-footer,.cleanupfieldset.cleanupfieldset>.geist-fieldset-footer{background:var(--board-card-foot)}
.followmanage .fmain>.fsec>.frows{padding:8px 24px}
@media(max-width:760px){.followmanage .fmain>.fsec>.fsechead{padding:16px}.followmanage .fmain>.fsec>.frows{padding:8px 16px}}
.gridstack .card:not(.junkcard) .pic{border-radius:var(--surface-radius);overflow:hidden}
.top{isolation:isolate}
body.board-scrolled .top{box-shadow:none;border-bottom:0}
/* 吸顶那一刻这块板离开纸面往上抬一档，三层影跟着加重：它盖住内容滚过去，两层之间
   要有东西说明谁在上面。类名写三遍是为了压过上面那组玻璃规则——两条都从
   `.board-filter-frame` 起头，`box-shadow` 整条归特异性高的那一条，少写一遍这里就
   不生效，抬起来的那一档看不出来。 */
.board-filter-frame.board-filter-frame.board-filter-frame.board-is-stuck{box-shadow:inset 0 1px 0 var(--glass-rim),inset 1px 0 0 var(--glass-low),inset -1px 0 0 var(--glass-low),inset 0 -1px 0 var(--glass-low),var(--glass-lift)}
.board-filter-frame.board-is-stuck::before{content:'';position:absolute;left:-16px;right:-16px;top:-9px;height:9px;z-index:-1;background:var(--page);mask-image:linear-gradient(to right,transparent,#000 24px,#000 calc(100% - 24px),transparent);pointer-events:none}
.board-filter-frame .tagbar.is-stuck,.board-filter-frame .count.is-stuck{backdrop-filter:none;-webkit-backdrop-filter:none}
.peach-insights{max-width:1120px;margin:0 auto 40px;color:var(--ink)}
.peach-insights[hidden]{display:none}
:root,[data-theme="light"]{--page:#f7f7f7;--ground:#fff;--surface:#fafafa;--sunk:#f2f2f2;--ink:#171717;--ink-2:#525252;--muted:#737373;--line:#e5e5e5;--line-soft:#ebebeb;--inset:#f0f0f0;--picked:#f0f0f0;--tungsten:#3b82f6;--control-radius:10px;--surface-radius:14px;--floating-radius:20px;--railW:272px}
[data-theme="dark"]{--page:#111;--ground:#1c1c1c;--surface:#232323;--sunk:#171717;--ink:#fafafa;--ink-2:#d4d4d4;--muted:#a3a3a3;--line:#383838;--line-soft:#303030;--inset:#303030;--picked:#303030;--hover:rgba(255,255,255,.07)}
body{background:var(--page)}
.top{background:var(--page);backdrop-filter:none;border-bottom:0;height:64px}
:root{--topH:64px}
.top .search{background:var(--ground);border:1px solid var(--line);border-radius:var(--control-radius)}
.tiers,.tagbar,.javbar{background:var(--page)}
.managebar{background:var(--ground);border:1px solid var(--line);border-radius:14px;padding:6px}
.stats>section,.stats>.fieldset,.fieldset{border-radius:var(--surface-radius)}
.settingscard,.drawer{box-shadow:0 12px 40px light-dark(#0000000d,#00000080)}
.settingscard{border:1px solid var(--line)}
.gridstack .card:not(.junkcard){background:transparent}
/* 强调档不写在这一段：它那一面连同悬停归 `body :is(…).primary` 一处。在这里再写一份
   的话，静止那条会被后面那条压掉、悬停那条却比它重一个类，一颗按钮的静止和悬停就由
   两处规则分别给出。 */
.geist-input,.geist-select,.search{box-shadow:0 1px 2px #00000004}
.configfieldset,[data-geist-fieldset]{border-radius:var(--surface-radius);overflow:hidden}
@media(prefers-color-scheme:dark){:root:not([data-theme]){--page:#111;--ground:#1c1c1c;--surface:#232323;--sunk:#171717;--ink:#fafafa;--ink-2:#d4d4d4;--muted:#a3a3a3;--line:#383838;--line-soft:#303030;--inset:#303030;--picked:#303030;--hover:rgba(255,255,255,.07)}}

/* One sidebar, two states. Navigation and filters share the expanded panel. */
.followmanage .fmain>.fsec{padding:0}
.followmanage .fmain>.fsec>.fsechead{margin:0}
:root{--railW:88px;--board-content:1120px}
body.drawer-open{--railW:296px}
.drawer{left:12px;top:12px;bottom:12px;width:272px;background:var(--ground);backdrop-filter:none;border:1px solid var(--line);border-radius:24px;transform:translateX(calc(-100% - 16px));box-shadow:0 2px 4px #00000003;transition:none}
.drawer.open{transform:none;box-shadow:0 2px 4px #00000003}
.drawerscroll{padding:20px 12px 24px}
.drawer .dnav{gap:4px;margin:16px 0 24px}
.drawer .dnav button{height:40px;padding:8px 12px;gap:12px;font-size:14px;border-radius:10px;line-height:20px;font-weight:400}
.drawer .dnav svg{margin:0;width:18px;height:18px}
.drawer .dnav button[aria-pressed="true"]{background:var(--board-blue);color:white;box-shadow:inset 0 1px 1px #ffffff50,0 1px 2px light-dark(#00000014,#0000008c)}
.drawer h3{font-size:12px;color:var(--muted);font-weight:500}
.drawer .drawertitle,.drawer .drawerhead{font-size:16px}
.scrim.on{display:none}
.top .brand .sub{display:none}

/* Routed management navigation uses BoardUI's underline treatment. */
.managebar{display:block;width:100%;max-width:var(--board-content);margin:20px auto 28px;padding:0;background:none;border:0;border-radius:0;overflow:visible}
.managebar .managebar-toggle{display:none!important}
.managebar .managebar-menu{display:flex!important;position:static;flex-direction:row;flex-wrap:nowrap;gap:4px;width:100%;padding:0;margin:0;border:0;border-bottom:1px solid var(--line);border-radius:0;background:none;box-shadow:none;overflow-x:auto;scrollbar-width:none}
.managebar .managebar-menu button{position:relative;display:inline-flex;flex:none;width:auto;align-items:center;gap:7px;padding:12px 10px;margin:0;min-height:44px;border:0;border-bottom:2px solid transparent;border-radius:0;background:none;color:var(--ink-2);font-size:14px;font-weight:400;white-space:nowrap}
.managebar .managebar-menu button svg{width:16px;height:16px}
/* 选中项是蓝字加蓝线。boardui tabs.tsx 实测：选中标签 text-accent-600，指示条是 tablist
   外面那个 span（h-0.5 bg-accent-600）。Geist 的单色规则不覆盖这一层——board.css 是
   boardui 适配层，它自己就把强调色花在了「你在这一页」上。 */
.managebar .managebar-menu button[aria-pressed="true"]{background:none;color:var(--tungsten);border-bottom-color:var(--tungsten);font-weight:500}
.managebar .managebar-menu button:hover{background:none;color:var(--ink)}
.managebar .managebar-menu button[aria-pressed="true"]:hover{color:var(--tungsten)}
body :is(#manageTitle,#manageCrumb,#manageLede){max-width:var(--board-content);width:100%;margin-left:auto;margin-right:auto}
#manageTitle{font-size:26px;line-height:34px;margin-bottom:24px}

/* Task entry cards and editing panels have different information density. */
/* 管理区每一页的正文跟标题走同一条中线。标题由上面那条 `#manageTitle` 钉在 1120 上，
   正文也得钉到同一个数：`.scraping-page` 和 `.activitypage` 自己声明的 812 窄列比标题
   每边窄 154px，读起来就是正文整块往右缩了一截。 */
.cleanuppage,.configpage,.scraping-page,.activitypage{width:100%;max-width:var(--board-content)}
.cleanupgrid{gap:16px}
.cleanupfieldset{border:1px solid var(--line);border-radius:16px;box-shadow:0 1px 2px #00000003}
.cleanupfieldset>.geist-fieldset-content{padding:20px 20px 16px;min-height:120px}
.cleanupfieldset h3,.cleanupfieldset h2{font-size:16px;line-height:24px;font-weight:500;margin:0 0 12px}
.cleanupfieldset strong{font-size:24px;line-height:32px;font-weight:500;color:var(--ink);letter-spacing:-.02em}
.cleanupfieldset .cleanupmeta{font-size:12px;line-height:18px;margin-top:8px}
.cleanupfieldset>.geist-fieldset-footer{background:transparent;border-top:1px solid var(--line-soft);padding:12px 20px;min-height:56px}
.cleanupfieldset>.geist-fieldset-footer button{font-size:13px}
.cleanupgrid>:is(.cleanupscraping,.cleanupmediarepair){grid-column:1/-1;display:grid;gap:16px}
/* ── 数据管理页照 Board 的 dashboard 模板排：顶上一排 plain stat card（stat-cards.tsx：132px 高、圆角 16、secondary 底、
   内边距 16，32px 的图标格里 20px 字形，标签 Body Medium 次文字色，读数 title-1-medium 24/34）。Peach 把整张卡做成
   按钮——它就是那一页的入口，读数下面那行 Caption 是同一份 payload 里的分项。五张在 1120 内一行摆下，窄了折两列、
   再折一列。上游的卡不可点也没有悬停；悬停抬主文字色 6% 底是 Peach 自己加的，告诉人这张卡按得下去。 ── */
.cleanupstats{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:16px}
.board-plain-stat{display:flex;flex-direction:column;justify-content:space-between;gap:8px;min-width:0;min-height:132px;margin:0;padding:16px;border:0;border-radius:16px;background:var(--color-background-secondary-default);color:var(--color-text-primary);font:var(--board-body);text-align:left;cursor:pointer;transition:background-color .15s ease}
.board-plain-stat:hover{background:color-mix(in srgb,var(--color-text-primary) 6%,var(--color-background-secondary-default))}
.board-plain-stat:disabled{cursor:default}
.board-plain-stat:focus-visible{outline:2px solid var(--color-border-focus-ring);outline-offset:2px}
.board-plain-stat-head{display:flex;align-items:center;gap:8px;min-width:0;color:var(--color-text-secondary);font:var(--board-body-medium);white-space:nowrap}
.board-stat-tile{display:grid;place-items:center;flex:none;width:32px;height:32px;border-radius:6px;background:var(--color-background-primary-default);color:var(--color-text-primary)}
.board-stat-tile svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.board-plain-stat>strong{display:block;margin:auto 0 0;font:var(--board-figure);letter-spacing:-.02em;color:var(--color-text-primary);font-variant-numeric:tabular-nums;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.board-plain-stat>.cleanupmeta{display:block;min-height:16px;margin:0;font:var(--board-caption);color:var(--color-text-tertiary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.board-plain-stat>.cleanupmeta:empty{display:block}
.board-plain-stat .skeleton{height:1em;max-width:60%}
@media(max-width:1119px){.cleanupstats{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:559px){.cleanupstats{grid-template-columns:minmax(0,1fr)}}
/* 读数下面那两张是要做的事，各占一行，与扫描卡同一个左说明右按钮的形状。 */
.cleanupgrid [data-cleanup-task],.resourcesyncbox[data-cleanup-task]{border:1px solid var(--color-separator-border);border-radius:16px;background:var(--color-background-secondary-default);box-shadow:var(--elevation-card)}
.cleanupgrid :is(.cleanupemptyfolders,[data-cleanup-processing]){display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center}
.cleanupgrid :is(.cleanupemptyfolders,[data-cleanup-processing])>:is(.geist-fieldset-content,[data-geist-fieldset-content]){min-height:0;padding:24px}
.cleanupgrid :is(.cleanupemptyfolders,[data-cleanup-processing])>:is(.geist-fieldset-footer,[data-geist-fieldset-footer]){justify-content:flex-end;border:0;padding:24px;background:none;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.cleanupgrid [data-cleanup-processing]>:is(.geist-fieldset-content,[data-geist-fieldset-content]){display:flex;flex-direction:column;gap:8px}
.cleanupgrid [data-cleanup-processing]>:is(.geist-fieldset-content,[data-geist-fieldset-content])>:is(h3,p){margin:0}
.cleanupgrid [data-cleanup-processing] h3{font:var(--board-heading);letter-spacing:0}
.cleanupgrid>.cleanupemptyfolders strong{font:var(--board-body);color:var(--color-text-secondary);letter-spacing:0}
.resourcesyncbox[data-cleanup-task]{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center}
.resourcesyncbox[data-cleanup-task]>.resourcesyncbody{min-height:0;padding:24px}
.resourcesyncbox[data-cleanup-task]>.resourcesyncfooter{align-self:stretch;justify-content:flex-end;min-height:0;padding:24px;border:0;background:none}
.resourcesyncbox[data-cleanup-task] .geist-fieldset-title{margin:0 0 8px;font:var(--board-heading);letter-spacing:0}
/* 来源行和资源同步结果面板取同一份站标；离线那枚跟着结果面板的 offline 用色。 */
.cleanupgrid>.cleanupemptyfolders .cleanupmeta{display:flex;flex-wrap:wrap;align-items:center;gap:6px 14px}
.cleanupsourcemark{display:inline-flex;align-items:center;gap:6px}
.cleanupsourcemark .gselectmark{width:14px;height:14px}
.cleanupsourcemark.cleanupsourcelost{color:var(--drop)}
/* 资源同步的结果照 Board 的 stat cards 排：和数据管理顶上一排读数同一副卡片，
   三个来源带官方站标，缓存与回收站两张读数跟在后面凑成同一行节奏。卡片不是入口，
   不接悬停抬色；在线状态挂在标题行最右，标题行放不下的说明在窄屏折行。 */
.resourcestats{margin:0}
.resourcestat{cursor:default}
.resourcestat:hover{background:var(--color-background-secondary-default)}
.resourcestat-tile svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.resourcestat-tile img{width:20px;height:20px;object-fit:contain}
.resourcestat-state{margin-left:auto;font:var(--board-caption)}
.resourcestat-state.online{color:var(--success)}
.resourcestat-state.offline{color:var(--drop)}
.resourcestat .cleanupmeta{white-space:normal}
/* 检查结果 Note 在空文件夹卡里顶满左右：两侧吃掉内容区的内边距直抵框边，
   侧边不再自带圆角和描边，读起来是卡片自己的一条结果带。 */
.cleanupgrid>.cleanupemptyfolders .cleanupstate .geist-note{margin-inline:-24px;border-inline:0;border-radius:0}
#resourceSyncResult>.cleanupstats{margin:0}
/* 结果槽里三层各管各的间距：读数卡、说明 Note、操作行都不再共享一只面板框。 */
#resourceSyncResult>.geist-note{margin:16px 0 0}
#resourceSyncResult>.resourceapplyrow{margin:16px 0 0;min-height:0;border:0;background:none;padding:0}
/* 首页那条整理提示是正文列里的一条 Note，上下两条线是它自己的收口。少了这个空当，
   两条线一边挨着身份行、一边挨着筛选浮层，看着像三块东西粘在一起。下面照浮层那个数
   留一样宽（上面由 `.tiers` 收尾与 `main` 上沿凑够）。 */
/* 要不要画这一条，得等 `/api/library-processing` 回话才知道，而它一出现就把底下整块
   推下六十来像素。跟交集条同一个处理：高度从 0 走到 auto，二百来毫秒，推的过程看得见
   就不叫跳。那趟任务跑完它自己会消失，缩回去同样是走的。
   容器里常驻一个 `.peach-react`（React 根的宿主，`frontend/src/islands.ts`），所以「有没有
   东西」看的是那一层空不空。 */
#libraryProcessingNotice{overflow:hidden;interpolate-size:allow-keywords;height:auto;
  transition:height .22s cubic-bezier(0,0,.2,1),margin-bottom .22s cubic-bezier(0,0,.2,1)}
#libraryProcessingNotice:empty,#libraryProcessingNotice:has(>.peach-react:empty){height:0}
#libraryProcessingNotice:not(:empty):not(:has(>.peach-react:empty)){margin:0 0 22px}
@media(prefers-reduced-motion:reduce){#libraryProcessingNotice{transition:none}}
.configfieldset{border:1px solid var(--line);border-radius:16px;box-shadow:0 1px 2px #00000003}
.configfieldset>.geist-fieldset-content{padding:24px;gap:20px}
.configfieldset>.geist-fieldset-footer{background:var(--ground);border-top:1px solid var(--line-soft);padding:14px 24px}
.configfieldset h2,.configfieldset h3{font-size:16px;font-weight:500;line-height:24px}
.configfieldset-heading{padding-bottom:16px;border-bottom:1px solid var(--line-soft)}
.configpage>.configgroup{display:none}
.board-local-nav{display:flex;gap:4px;overflow-x:auto;flex:none;border-bottom:1px solid var(--line);margin:0 0 24px;padding:0;scrollbar-width:none}
.board-local-nav button{flex:none;background:none;border:0;border-bottom:2px solid transparent;border-radius:0;padding:10px 12px;font-family:inherit;font-size:14px;font-weight:400;line-height:20px;color:var(--ink-2);cursor:pointer;white-space:nowrap}
.board-local-nav button[aria-selected="true"]{border-bottom-color:var(--tungsten);color:var(--tungsten);font-weight:500}
.board-local-nav button:focus-visible{outline:2px solid var(--tungsten);outline-offset:-3px}
[data-board-group]:not(.board-group-active){display:none!important}
.settingscard{display:grid}
.settingscard>.board-local-nav{margin:0;border:0;border-right:1px solid var(--line-soft);overflow-y:auto}
.settingsscroll{grid-column:2;grid-row:2}
.settingsscroll>.settinggroup{border:0;margin:0}
.settingsscroll .settingrow{grid-template-columns:minmax(0,1fr) auto}
.board-number-control{display:flex;align-items:center;gap:8px}.board-number-control input{width:96px;padding:8px 10px}.board-number-help{font-size:11px!important}.board-number-error{color:#ef6868!important;font-size:12px!important}.board-number-error:empty{display:none}
@media(max-width:600px){.settingsscroll .settingrow{grid-template-columns:1fr;gap:12px}.settingsscroll .settingrow:has(input[type=checkbox]){grid-template-columns:minmax(0,1fr) auto}.board-number-control input{width:110px}}
.pselect,.popmenu{border-radius:12px;border-color:var(--line);box-shadow:0 8px 24px light-dark(#00000012,#00000080)}
.geist-switch,.switchgroup{background:var(--surface);border-radius:10px}
.iconswitch[data-board-segments]{position:relative;display:inline-flex;align-items:center;gap:2px;padding:4px;border:0;border-radius:10px;background:var(--color-background-tertiary-default)}
.iconswitch[data-board-segments]>label{position:relative;z-index:1;border:0;border-radius:6px}
.iconswitch[data-board-segments]>label:has(input:checked){background:transparent;box-shadow:none}
/* 换位走 `translate`，由 `moveGlidePane` 给同一段弹簧动作——这块底板和筛选条上那块
   玻璃说的是同一件事，动法也只有一种。留给这里的只有尺寸：那是布局属性，交给过渡
   平滑就够，跟着位移一起过冲会让它在停下之前先胖出去一圈。 */
.board-segment-thumb{position:absolute;left:0;top:0;pointer-events:none;border-radius:6px;
  will-change:translate,scale;background:var(--color-background-primary-default);box-shadow:var(--elevation-xs)}
.board-segments-ready>.board-segment-thumb{
  transition:width calc(var(--spring-pane-ms,200) * 1ms) ease,height calc(var(--spring-pane-ms,200) * 1ms) ease}
@media(prefers-reduced-motion:reduce){.board-segments-ready>.board-segment-thumb{transition:none}}
.followtask{border-color:var(--line);border-radius:16px}
:root[data-theme="dark"]{--page:#111;--ground:#1c1c1c;--surface:#232323;--sunk:#171717;--ink:#fafafa;--ink-2:#d4d4d4;--muted:#a3a3a3;--line:#383838;--line-soft:#303030;--inset:#303030;--picked:#303030;--hover:rgba(255,255,255,.07);--tungsten:#60a5fa}
/* 侧栏光晕由设置里的「侧栏光晕」一项决定开关：关掉时 --glow-strength 是 0，
   `.glowlayer::before` 的不透明度跟着算成 0。这里不能再压一条 display:none——那会让设置面板上的开关、强度、
   配色和颗粒四个控件全部调不出任何变化，而界面上没有任何东西说得出为什么。 */
.tiers{background:transparent}
/* 面板上沿那道空隙不由自己决定：`.tiers` 收尾留 8px、`main` 上沿又是 14px，它自己那
   8px 还被 `.combo` 的下边距吃掉，加起来 32px，下面却只有 20px，同一块浮层上下差出 12px。
   上面这 22px 改不动（两处都是别的页面共用的），所以自己不再加，下面照同一个数写。 */
.board-filter-frame{position:sticky;top:calc(var(--topH) + 8px);z-index:60;border:0;border-radius:16px;background:var(--ground);margin:0 0 22px;box-shadow:0 2px 14px light-dark(#00000014,#00000066)}
@media(max-width:760px){.board-filter-frame.board-filter-frame.mobile-filter-free{top:var(--filter-free-top)}}
/* 首页那块住在 `body` 底下，两侧没有任何东西给它留白，22px 的圆角直接切在屏幕边沿上；
   资料页那块在 `#index` 里，`main` 的 16px 已经把它让开了。这里补的就是那 16px，取的
   也是 `main` 自己的那个数，所以两页的浮层和底下的网格对在同一条竖线上。 */
body>.board-filter-frame{margin-inline:16px}
.board-filter-frame .tagbar,.board-filter-frame .count{position:relative;top:auto;left:auto;width:auto;margin:0;background:transparent;box-shadow:none;border:0;padding:10px 16px}
.board-filter-frame .tagbar{border-bottom:0;border-radius:16px 16px 0 0}
.board-filter-frame .count{border-radius:0 0 16px 16px;min-width:0}
.board-filter-frame .sorts{position:relative;min-width:0;overflow-x:auto;scrollbar-width:none}
/* 上下半合起来照首页那块浮层量：跟顶栏留 8px、跟下面的网格留 22px，左右不再往外溢 16px，
   两行各 48px。基础层的 `--filterH` 是 58px，那是没有浮层时贴着顶栏的老尺寸，这里不能用它
   算下半的吸顶位置，另起一个只归这块浮层的高度。下半的吸顶位置是上半的下沿，上半没有时
   它自己就是整块，回到顶栏下 8px。 */
:root{--board-filterH:48px}
.entitytagbar{position:sticky;top:calc(var(--topH) + 8px);margin:0;height:var(--board-filterH);gap:6px;padding:8px 12px}
.entitytagbar .entitytags{gap:6px}
.entitytagbar .mediaviewbuttons .mediaviewbutton{flex:0 0 30px;width:30px;height:30px}
.entitycollectionhead{position:sticky;top:calc(var(--topH) + 8px);margin:0 0 22px;padding:8px 12px;min-height:var(--board-filterH);gap:12px}
.entitycollectionhead.is-stuck::after{content:'';position:absolute;inset:0;z-index:-1;border-radius:inherit;
  box-shadow:0 0 24px 4px #00000038,0 8px 20px #00000026;pointer-events:none}
/* 两行合成一块时，吸顶那一档影由整块玻璃自己换成 --glass-lift，这一层不再叠。 */
/* 读数照首页那条 `10,471 个符合` 写：12px、常规字重、不加字距，颜色比标签低一档。
   排序键也跟那边同一套——30px 高、12px 字、7px 圆角，选中态那块玻璃在上面统一给。 */
.entitycollectionhead h3{font-size:12px;font-weight:400;letter-spacing:normal;color:var(--ink-2)}
/* 返回键在这块玻璃上，那圈线和字色都得跟着玻璃取，不然是浮层里唯一一处用 flat 面
   配色的东西；高度跟同一排的排序键对齐。 */
.entitycollectionhead .photoback{height:30px;border-color:var(--glass-low);color:var(--glass-text)}
.entitycollectionhead .sorts{gap:4px}
.entitycollectionhead .sorts button{height:30px;min-height:30px;font-size:12px;padding:0 8px;border:0;border-radius:7px;background:transparent}
/* 浮层下半在手机上仍是一横条：读数在左，控件跟在右边，装不下就整条往右滚。让读数
   和控件各占一行的话，这块玻璃要吃掉三行高度——上半那排标签本来就是横滚的，同一块
   玻璃上一半横滚、一半换行，读起来是两个不同的东西。滚动开在这一条自己身上而不是
   里面的 `.sorts`：套两层横滚，触摸时两层抢同一个手势，而读数留在外层怎么滚都不走，
   控件却已经滑没了。控件那 `margin-left:auto` 只在装得下时把它推到右端，溢出时自动
   失效，所以窄一点也不会在读数和第一枚键之间空出一块。 */
@media(max-width:760px){
  .board-filter-frame .count,.entitycollectionhead{display:flex;flex-wrap:nowrap;align-items:center;gap:10px;
    overflow-x:auto;overflow-y:hidden;scrollbar-width:none;
    overscroll-behavior-inline:contain;touch-action:pan-x pan-y}
  .board-filter-frame .count::-webkit-scrollbar,.entitycollectionhead::-webkit-scrollbar{display:none}
  .board-filter-frame .count>.mono,.entitycollectionhead>h3,.entitycollectionhead>.photoback{flex:none;white-space:nowrap}
  .board-filter-frame .count .sorts,.entitycollectionhead .sorts{flex:none;width:max-content;max-width:none;min-width:0;
    margin-left:auto;overflow:visible;padding:0;margin-block:0}}
[data-overflow-right="true"]{mask-image:linear-gradient(to right,#000 calc(100% - 18px),transparent)}
[data-overflow-left="true"]{mask-image:linear-gradient(to right,transparent,#000 18px)}
[data-overflow-left="true"][data-overflow-right="true"]{mask-image:linear-gradient(to right,transparent,#000 18px,#000 calc(100% - 18px),transparent)}
.drawer #brandHome{display:flex;gap:10px;align-items:center;margin-right:auto;text-decoration:none;color:var(--ink)}
.drawer #brandHome .mark{width:28px;height:28px}.drawer #brandHome h1{font-size:20px;letter-spacing:.02em}.drawer #brandHome .sub{display:none}
.edge::before{content:'';width:28px;height:28px;background:url('/peach-logo.png') center/contain no-repeat;padding:0;margin:4px 0 16px}
.top .search{max-width:none;flex:1 1 0;min-width:0;margin-left:0;margin-right:0}
/* 搜索玻璃从图标的实际矩形形变，建议面板在轮廓收稳后显示。 */
@media(max-width:760px){
  .top .search{display:flex;visibility:hidden;pointer-events:none}
  .top .search.open,.top .search.search-morphing{visibility:visible;pointer-events:auto}
  .top .search.search-morphing{contain:layout;overflow:hidden}
  .top .search.search-morphing .searchmenu{visibility:hidden}
  .top:has(.search.search-morphing){overflow:visible}
  .top:has(.search.search-morphing) #searchBtn{opacity:0}
}
/* 首页的 `#tagbar` 和关注页的 `.followfilters` 是同一条筛选条，规则按类名写、两页共用：
   左端几枚视图记在 `data-state`／`data-follow-filter` 上，右半截的标签记在
   `data-tag`／`data-follow-tag`，来源图标键是 `data-follow-provider`。 */
.board-filter-frame .tagbar{height:48px;gap:6px;padding:8px 12px}
.board-filter-frame .tagbar .pill{height:30px;padding:0 10px;font-size:13px;line-height:20px;border-radius:8px;border:1px solid transparent}
/* 几枚视图自己不铺底，选中那一枚的填充由 `.viewglide` 那块滑过去的玻璃提供：
   两边都铺，静止态就是一块不透明的 `--picked` 压在玻璃上面，切换时也只能看见它
   瞬间换位置，滑动的那块从头到尾被盖住。 */
.board-filter-frame .tagbar .pill:is([data-state],[data-follow-filter]){border:0;background:none;color:color-mix(in srgb,var(--glass-text) 60%,transparent)}
.board-filter-frame .tagbar .pill:is([data-state],[data-follow-filter]):hover,
.board-filter-frame .tagbar .pill:is([data-state],[data-follow-filter])[aria-pressed="true"]{background:none;color:var(--glass-text)}
/* 可加可不加的筛选没生效时是虚线，悬停拉成实线；判据与 flat 层那条同一份，见 03-filterbar.css。 */
.board-filter-frame .tagbar .pill:is([data-tag],[data-follow-tag],[data-follow-provider]):not([aria-pressed="true"]){border:1px dashed var(--line);background:transparent}
.board-filter-frame .tagbar .pill:is([data-tag],[data-follow-tag],[data-follow-provider]):not([aria-pressed="true"]):hover{border-style:solid}
/* 右半截这些是标签，圆角从标签那个 token 取，跟卡片、详情面板、交集条一起走；左边几枚
   是分段器，形状归它自己那一排。线画满两态：填充说的是这条加没加上去，那一圈线说的是
   「这是一颗标签」，两句话不能合成一句讲。玻璃上取 --glass-low、flat 面上取 --line，
   同一个角色各按自己的底选值。 */
.board-filter-frame.board-filter-frame .tagbar .pill:is([data-tag],[data-follow-tag],[data-follow-provider]){border-radius:var(--tag-radius);border-color:var(--glass-low)}
/* 关注页的标签按来源类型着色，选中那一档的线和填充都取那个色：这是它们在卡片上的样子，
   筛选条上不换一套。 */
.board-filter-frame.board-filter-frame .followfilters .pill[class*="r34-"][aria-pressed="true"]{
  border-color:color-mix(in srgb,var(--r34-tag) 72%,transparent);background:color-mix(in srgb,var(--r34-tag) 22%,transparent)}
/* 资料页的标签跟首页筛选条上的标签是同一个控件，只是换了个位置：那边 30px 高、13px
   字，这边还留着 40px 高的大药丸，同一个人的标签在两页上大一圈小一圈。
   计数跟着缩到 Caption。 */
.entitytags .pill{height:30px;padding:0 10px;font-size:13px;line-height:20px;border-radius:var(--tag-radius);border:1px solid var(--glass-low);color:var(--glass-text)}
.entitytags .pill small{margin-left:5px;font:var(--board-caption)}
.board-filter-frame .count{padding:8px 12px;min-height:46px;gap:12px}
.board-filter-frame .sorts{gap:4px}.board-filter-frame .sorts button{height:30px;min-height:30px;font-size:12px;padding:0 8px;border:0;border-radius:7px;background:transparent}
/* 关注页上排最左那两枚是视频／图片，跟资料页那一组同形：自己不铺底，选中那一枚的填充
   由 media 那块滑过去的玻璃给。两边都铺的话，静止态是一块不透明的面压在玻璃上面，
   切换时也只看得见它瞬间换位置。字形要压在玻璃上面，不然滑过去时一路被盖暗。 */
.board-filter-frame .followmediaview{gap:2px}
.board-filter-frame.board-filter-frame .followmediaview .mediaviewbutton{
  flex:0 0 30px;width:30px;height:30px;border-radius:7px;position:relative;z-index:1;
  border:0;background:none;backdrop-filter:none;-webkit-backdrop-filter:none;box-shadow:none;
  color:color-mix(in srgb,var(--glass-text) 60%,transparent)}
.board-filter-frame.board-filter-frame .followmediaview .mediaviewbutton:hover,
.board-filter-frame.board-filter-frame .followmediaview .mediaviewbutton[aria-pressed="true"]{color:var(--glass-text)}
/* 图片墙上的「仅显示图片」是开关不是动作，蓝色留给换一批；它自己不铺底——开着时垫的
   是筛选条上那块滑动玻璃（GLIDE_ROWS.imagesonly），跟版式分段器、媒体那一档同一块料。
   关着和悬停走这一排排序键的规矩（六成字色、悬停提满），按下的字色由上面那条
   `[aria-pressed="true"]` 给，都不另写。 */
/* 资料卡照 Board 的卡排：secondary 底、18px 圆角、不描边，卡底那条带取卡脚那一档色阶。
   标题是 Title 3（24/32、500），别名行 Body 1，外链是 36px 的 secondary Button。 */
.entityhero{border-radius:18px;background:var(--ground);box-shadow:none}
.entityfoot{background:var(--board-card-foot);border-top-color:var(--line-soft)}
.entityhero h2{font-size:24px;font-weight:500;line-height:32px}
.entityhero .alias{font-size:14px;line-height:20px}
.entitylinks a,.entitylinks .private{height:36px;border-radius:10px;border-color:var(--line);font-size:13px}
.entitylinks .iconlink{border-radius:10px}
/* 计数徽标照 tabs.tsx：`rounded-sm px-1 py-px text-caption-1-medium`，未选中黑 10% 底半透明，
   选中换成强调色 12% 底、强调色字。字母表分组卡的字头旁挂的也是这一枚。 */
.board-tab-count{display:inline-block;margin-left:6px;padding:1px 4px;border-radius:4px;font:var(--board-caption);font-weight:500;line-height:16px;
  background:color-mix(in srgb,var(--ink) 10%,transparent);color:var(--ink);opacity:.5;vertical-align:1px}
.board-local-nav button[aria-selected="true"] .board-tab-count{background:color-mix(in srgb,var(--tungsten) 12%,transparent);color:var(--tungsten);opacity:1}
/* 索引页页头下面那排 Tabs（厂牌／事务所、本地／在线）跟浮层留同样的 22px；前置字形 16px。 */
.indextabs{margin:0 0 22px}
.board-tabs button svg{width:16px;height:16px;margin-right:6px;vertical-align:-3px;stroke:currentColor;fill:none;stroke-width:2}
/* 索引格照 Board 的卡排：secondary 底、16px 圆角、不描边，名字 Body 1 Medium、读数 Caption。
   大图版式里图铺满卡宽、文字靠左；紧凑版式是圆头像居中那一屏。 */
.igrid{gap:12px}
.icell{gap:8px;padding:12px;border-radius:16px;background:var(--ground)}
.icell:hover{background:color-mix(in srgb,var(--ink) 6%,var(--ground))}
.icell .nm{font-size:14px;line-height:20px;font-weight:500}
.icell .n{font:var(--board-caption);color:var(--muted)}
.igrid[data-layout="big"] .icell{align-items:stretch;padding:12px}
.igrid[data-layout="big"] .icell .ring{border-radius:10px}
.igrid[data-layout="big"] .icell .nm,.igrid[data-layout="big"] .icell .n{text-align:left}
.igrid[data-layout="big"] .icell .nm{font-size:14px}
/* 字母表的分组卡与卡头：Heading 20/26；一行一枚标签是排名行那一档（36px、圆角 8）。 */
.alphagroup{border-radius:16px;box-shadow:none}
.alphagroup h3{font-size:20px;line-height:26px;font-weight:500}
.alphatag{border-radius:8px}
/* 标签页浮层上排的类型药丸：玻璃上的线取 --glass-low，没选中的是虚线，选中那一枚的色由类型色给。 */
.board-filter-frame .tagcategories .pill{border:1px solid var(--glass-low);background:transparent}
.board-filter-frame .tagcategories .pill:not([aria-pressed="true"]){border-style:dashed}
.board-filter-frame .tagcategories .pill:not([aria-pressed="true"]):hover{border-style:solid}
.board-filter-frame .tagcategories .pill[aria-pressed="true"]{border-color:color-mix(in srgb,var(--tag-color,var(--ink)) 45%,transparent);
  background:color-mix(in srgb,var(--tag-color,var(--ink)) 12%,transparent)}
.board-filter-frame .alphajump button{color:color-mix(in srgb,var(--glass-text) 60%,transparent);border-radius:7px}
.board-filter-frame .alphajump button:hover{color:var(--glass-text)}
/* 「载入更多」是 Board 的 secondary Button：36px、圆角 10、Body Medium。 */
.indexmore,.entitymore{min-height:36px;height:36px;padding:0 12px;border-radius:10px;border-color:var(--line);font-size:14px;font-weight:500;color:var(--ink)}
#grid.gridstack{border:0;background:transparent;padding:0;box-shadow:none;border-radius:0}
#grid.gridstack>.grid{border:0;background:transparent;padding:0;box-shadow:none;border-radius:0}
/* 竖屏带靠底色和网格区分，不再描一圈线：它嵌在两段无边框的网格中间，一条线反而
   把它读成一个可以点开的容器。 */
.shorts-inline{border:0}
@media(pointer:coarse){.board-filter-frame #tagbar .pill{height:36px}.board-filter-frame #tagbar{height:52px}.board-filter-frame .sorts button{height:36px}}
#applyUISetting{padding:8px 12px;border:1px solid var(--line);border-radius:8px;cursor:pointer}
#applyUISetting[hidden]{display:none}

@media(max-width:1000px){.settingscard{width:calc(100vw - 32px)}}
@media(max-width:760px){
  :root,body.drawer-open{--railW:0px}
  .drawer{top:64px;bottom:12px;width:min(320px,calc(100vw - 24px));border-radius:20px;z-index:97}
  /* 窄屏的抽屉盖在内容上面，身后常是整张视频封面，薄玻璃上的导航字读不出来。填充加厚到
     --ground 的 86%，光斑、内缘亮线和模糊照旧。 */
  .drawer.drawer{--glass-fill:color-mix(in srgb,var(--ground) 86%,transparent)}
  .scrim.on{display:block;top:56px}
  .top{z-index:98;background:var(--page)}
  .managebar{width:100%;margin:16px 0 24px}.managebar .managebar-menu{padding:0;gap:0}
  .managebar .managebar-menu button{padding:10px 9px;font-size:13px}.managebar .managebar-menu button svg{display:none}
  .cleanupgrid{grid-template-columns:1fr;gap:12px}
  body.cleanup-layout #manageTitle,body.configuration-layout #manageTitle,body.cleanup-layout #manageCrumb{width:100%;font-size:22px}
  .cleanupfieldset>.geist-fieldset-content{min-height:0;padding:18px}
  .cleanupfieldset strong{font-size:22px}.cleanupfieldset>.geist-fieldset-footer{padding:12px 18px}
  .settingscard{display:flex;flex-direction:column;width:calc(100vw - 24px);max-height:calc(100dvh - 24px)}
  .settingshead{padding:16px 20px}
  .settingscard>.board-local-nav{flex-direction:row;border-right:0;border-bottom:1px solid var(--line);padding:8px 12px;background:var(--ground);overflow-x:auto}
  .settingsscroll{min-height:0;padding:20px;overflow:auto}.settingsscroll .settingrow{gap:16px;flex-wrap:wrap}
  .configfieldset>.geist-fieldset-content{padding:20px}.board-local-nav{gap:0}.board-local-nav button{padding:10px 9px;font-size:13px}
}

/* Settings rows use a shared baseline; controls wrap only on narrow screens. */
.settingscard .settingsscroll .settingrow.settingsortrow{grid-template-columns:minmax(0,1fr) auto;gap:16px;align-items:center;padding-block:12px}
.settingscard .settingsscroll .settingsortcontrols{display:flex;gap:8px;justify-content:end}
.settingscard .settingsscroll .settingsortcontrols>div{flex:0 1 112px;min-width:0}
.settingscard .settingsscroll .settingsortcontrols .gselect{width:112px;min-width:0;padding:0}
.settingscard .settingsscroll .gselectfield{height:32px;padding:0 8px;border-radius:8px;font-size:13px;gap:6px}
.settingscard .settingsscroll .board-number-help{display:none}
.board-number-fields{position:relative}
.settingscard .board-number-control{display:flex;gap:0;height:32px;border:1px solid var(--line);border-radius:10px;background:var(--surface);overflow:hidden;align-items:stretch}
.settingscard .board-number-control input{border:0;box-shadow:none;background:transparent;width:64px;min-width:0;height:30px;border-radius:0;padding:6px 8px;font:inherit;outline:none}
.settingscard .board-number-control:focus-within{box-shadow:0 0 0 3px var(--line);border-color:var(--muted)}
.settingscard .board-number-control>span{display:flex;align-items:center;padding:0 8px;border-left:1px solid var(--line);color:var(--muted);font-size:12px;background:var(--ground)}
.settingscard .board-number-control:has([aria-invalid=true]){border-color:var(--error,#e5484d);box-shadow:0 0 0 2px color-mix(in srgb,var(--error,#e5484d) 15%,transparent)}
.settingscard .board-number-error:not(:empty){position:absolute;z-index:10;right:0;top:calc(100% + 6px);width:max-content;max-width:240px;padding:6px 10px;background:var(--ground);border:1px solid color-mix(in srgb,var(--error,#e5484d) 35%,var(--line));border-radius:8px;box-shadow:0 4px 14px light-dark(#0002,#0008);color:var(--error,#e5484d);font-size:12px;line-height:18px;margin:0}
.settingscard .board-number-error[hidden]{display:none}
.settingscard .board-optional-number{position:relative}
/* 手柄那一下走 `--spring-press`：那条曲线本来就是冲过落点再荡回来一次，18px 的行程上
   读出来正是「过头一点点、退回来、停住」两跳，不必另写一组带 55%／80% 停的关键帧。
   轨道换色仍走自己的钟，它是一次颜色交叉淡入，跟着手柄一起弹会把整枚开关读成在呼吸。
   写成 transition 而不是 animation，是因为 animation 一挂上去，页面载入时已经是开态的
   那几枚会当场各弹一次——这一屏设置里有十几个开关，进页面就是一片抖。 */
.ptoggle{width:42px;height:24px;background:var(--color-background-tertiary-default);border:0;border-radius:999px;transition:background .2s}
.ptoggle::after{width:18px;height:18px;top:3px;left:3px;background:linear-gradient(#fff 44%,#f3f3f3);box-shadow:0 3px 3px #00000008;transition:transform calc(var(--spring-press-ms)*1ms) var(--spring-press);transform:none}
.ptoggle::before{content:'';position:absolute;z-index:1;left:8.25px;top:8.25px;width:7.5px;height:7.5px;border-radius:50%;background:var(--surface);box-shadow:inset 0 0 0 .375px var(--line);transition:transform calc(var(--spring-press-ms)*1ms) var(--spring-press)}
.ptoggle:checked{background:var(--board-blue);box-shadow:inset 0 1.5px 0 #ffffff40,inset 0 0 0 .75px var(--color-accent-400)}
.ptoggle:checked::after{left:3px;transform:translateX(18px)}
.ptoggle:checked::before{transform:translateX(18px);background:linear-gradient(var(--color-accent-700),var(--color-accent-500))}
.ptoggle:disabled{opacity:.5}
#applyUISetting{grid-column:1/-1;width:100%;background:var(--board-blue);color:#fff;border:1px solid var(--color-accent-400);box-shadow:inset 0 1px 1px #ffffff60}
/* 悬停压暗而不是提亮：这枚键铺满一整行，提亮那一档在浅色面上会让它看起来先亮一下再
   被按下去。压暗那一档正好是 `--board-blue-active` 的两级。 */
#applyUISetting:hover{background:var(--board-blue-active);color:#fff}
@media(max-width:760px){.settingscard .settingsscroll .settingrow.settingsortrow{grid-template-columns:1fr;gap:10px}.settingscard .settingsscroll .settingsortcontrols{width:100%}.settingscard .settingsscroll .settingsortcontrols>div{flex:1}.settingscard .settingsscroll .settingsortcontrols .gselect{width:100%}}
@media(prefers-reduced-motion:reduce){.ptoggle,.ptoggle::after,.ptoggle::before{transition:none}}

/* 媒体详情、实体与管理共享卡片层级，播放器仍使用原有播放交互。 */
.stage{border:1px solid var(--line);border-radius:var(--surface-radius);overflow:clip;background:var(--ground);box-shadow:0 2px 8px light-dark(#0000000a,#00000066);--detail-surface:var(--ground)}
.stage:not(.ambient-on){background:var(--ground)}
.stage .side{background:var(--ground);backdrop-filter:none;border-color:var(--line-soft)}
.sidecontent{padding:20px;gap:4px}
.stitle{font-weight:500;line-height:1.5}
.detailtag .tagfilter{padding-inline:8px}
.srctools button,.detailtitletools button{border-radius:8px;background:var(--surface)}
.geist-fieldset,.configfieldset,.cleanupfieldset,.resourcepanel,.resourcesyncbox{border-color:var(--line);border-radius:var(--surface-radius);background:var(--ground);overflow:clip}
.geist-fieldset-footer,.configfieldset>.geist-fieldset-footer{background:var(--surface);border-top:1px solid var(--line-soft)}
.geist-input,.geist-select,.gselectfield{background:var(--surface);border-color:var(--line);border-radius:10px}
.iconswitch{padding:3px;background:var(--surface);border:1px solid var(--line-soft);border-radius:10px}
.iconswitch label{border-radius:8px}
.iconswitch label:has(input:checked){background:var(--ground);box-shadow:0 1px 3px light-dark(#0002,#0009)}
.card{overflow:visible;border-radius:var(--surface-radius)}
.card :is(.pic,.mixstack,.partstack){border-radius:var(--surface-radius)}
.card .info{background:transparent}
@media(max-width:760px){.sidecontent{padding:16px}.stage{border-radius:12px}.stage .side{border-left:0;border-top:1px solid var(--line-soft)}}
/* 单列时媒体、详情栏和队列上下排成一列，总高超过浮窗，滚的是里面那一格内容：`<dialog>`
   在顶层，它自己滚就只能用系统滚动条，全站那条 3px 浮在内容上的轨道挂不上去（轨道得是
   滚动容器的兄弟，挂到浮窗父级上会落进遮罩底下）。浮窗照旧按内容定高、`overflow:clip`
   照旧管横向，上限由这一层自己端着：34px 是浮窗那 16px 上下留白加两条边线，减出来的高度
   与浮窗自己那条 `max-height` 落在同一个数上，浮窗于是不会比这一层高出一条空边。
   浮窗不改成 flex 或 grid：那一下会让内部几处百分比高度取得到定值，整块内容当场缩成
   半屏，浮窗下半截空着。
   视频格吸在这一层顶上，往下翻标签和动作时画面还在；图片不吸——一张竖图就能占满整屏，
   吸住它下面就没有地方可滚。 */
@media(max-width:1080px){
  .stage>.stagescroll{max-height:calc(100dvh - 34px);overflow:hidden auto;overscroll-behavior:contain}
  .stage .vwrap:has(>.video-js){position:sticky;top:0;z-index:3}}
/* 手机上浮窗离屏幕边只留 8px，画面格按视频自己的比例排：竖屏和方形视频装进 16:9 的格子里
   只剩中间一小块画面。比例由播放器读到元数据后写进 `--peach-video-ratio`，读到之前仍是 16:9；
   高度封顶 56dvh，吸顶以后下面至少还有四成屏给详情。
   上沿让出状态栏、下沿按 dvh 停在地址栏之上，浮窗和吸在它顶上的画面不钻到这两条栏底下。 */
@media(max-width:760px){
  .stage{inset:calc(env(safe-area-inset-top) + 8px) 8px auto;margin:0 auto;width:calc(100vw - 16px);max-width:calc(100vw - 16px);
    max-height:calc(100dvh - env(safe-area-inset-top) - 16px)}
  /* 手机上浮窗自己的上限换了一条，滚动层跟着换，两边仍旧差两条边线。 */
  .stage>.stagescroll{max-height:calc(100dvh - env(safe-area-inset-top) - 18px)}
  .vwrap>.video-js{aspect-ratio:var(--peach-video-ratio,16/9);max-height:56dvh}
}
@media(max-width:760px){.settingspanel.settingspanel{padding:12px;grid-template-columns:minmax(0,1fr)}.settingscard.settingscard{width:calc(100vw - 24px);max-width:calc(100vw - 24px);min-width:0}.settingscard .settingsscroll .settingrow:has(.board-optional-number){grid-template-columns:minmax(0,1fr) auto;gap:12px}.settingscard>.board-local-nav{min-width:0;max-width:100%}}
/* 纯图标按钮不继承浏览器按钮的水平内边距。 */
:is(.settingshead button,.srctools button,.detailtitletools button,.sidebarorderrow button,#drawerClose){padding:0;display:inline-grid;place-items:center;line-height:1;flex-shrink:0}
:is(.settingshead button,.srctools button,.detailtitletools button,.sidebarorderrow button,#drawerClose)>svg{display:block;margin:0;flex-shrink:0;align-self:center;justify-self:center}
:is(.settingshead button,.srctools button,.detailtitletools button,.sidebarorderrow button,#drawerClose)[hidden]{display:none}
.closestage{padding:0;display:grid;place-items:center;line-height:1;border-radius:50%;background:var(--surface);color:var(--ink)}
.closestage svg{display:block;margin:0;justify-self:center;align-self:center}

/* BoardUI surface tokens; Peach retains its layouts and specialized media UI. */
:root{--board-motion:.3s cubic-bezier(.4,0,.2,1);--board-dialog-motion:.3s cubic-bezier(.32,.72,0,1);--fs-lg:16px;--fs-xl:20px;--fs-2xl:24px;--control-h:36px}
/* 原地换一样东西的那三档：一枚字形换成另一枚、一行字换成另一行、占位换成真内容。
   三者都是同一件事的不同尺度，所以共用 `--board-motion` 那条缓动，只有时长按跨度分档：
   字形和文字原地不动只换外观走 250ms，骨架换内容要跨整块区域走 400ms。
   `--motion-stagger` 是多位数字按位错峰的步长，它跟时长一样要在 reduced motion 下归零——
   动画时长归零而延迟还在的话，`both` 会把前几位按住不显示，读数看上去缺了几位。 */
/* `--motion-pop` 是「这一枚刚冒出来」那一下：跨度和骨架换内容同为 400ms，缓动却必须
   带超调——徽标从零长到原大小，匀速收尾读成「被撑开的」，过一点再收住才读成「弹出来的」。
   缓动不同就不能借 `--motion-reveal`：那两档的缓动写在 token 里，动画里再写第二条
   缓动是无效声明，整条 `animation` 会被丢掉。 */
:root{--motion-swap:.25s cubic-bezier(.4,0,.2,1);--motion-count:.25s cubic-bezier(.34,1.45,.64,1);--motion-reveal:.4s cubic-bezier(.4,0,.2,1);--motion-stagger:70ms;--motion-pop:.4s cubic-bezier(.34,1.36,.64,1)}
body{font-size:14px;line-height:20px}
button,input,select,textarea{font-family:inherit}
.index .ihead{padding:4px;gap:12px;min-width:0;flex-wrap:wrap}
.index .ihead .geist-search{min-width:140px;margin-right:0}
.index .ihead h2,#manageTitle{font-size:24px;line-height:34px;font-weight:500}
.indexheading{font-size:24px;line-height:34px}
.index .ihead .geist-search input{font-size:14px;line-height:20px}
.insighttoolbar,.tastehead{gap:16px}
/* 进场用 backwards 而不是 both：终点帧本来就是元素的自然状态，保留它只多留下一个
   `filter:blur(0)`。非 none 的 filter 会另起一个 backdrop root，卡片里任何
   backdrop-filter 从此只采样得到卡片自己的内容——左栏的玻璃于是退化成一块半透明色。
   退场那条仍要 both，它的终点（透明）不是自然状态。 */
.settingscard.settingscard{border:0;animation:board-dialog-in var(--board-dialog-motion) backwards}
.settingspanel.closing .settingscard.settingscard{animation:board-dialog-out var(--board-dialog-motion) both}
@keyframes board-dialog-in{from{opacity:0;transform:scale(.85);filter:blur(4px)}to{opacity:1;transform:scale(1);filter:blur(0)}}
@keyframes board-dialog-out{from{opacity:1;transform:scale(1);filter:blur(0)}to{opacity:0;transform:scale(.85);filter:blur(4px)}}
/* 作品详情浮窗进出场跟设置弹层同一组关键帧、同一个时长 token，遮罩也是同一条淡入淡出：
   两个都是盖住整页的弹层，一个缩放着淡进来、另一个直接闪出来的话，读起来像两种东西。
   `backwards` 的理由同上，这里更要紧——`.stage .side` 自己就带 backdrop-filter。
   退场期间收掉指针：浮窗已经在缩小，关闭键和播放器控件还能点到就会收到第二次触发。 */
.stage{animation:board-dialog-in var(--board-dialog-motion) backwards}
.stage::backdrop{animation:settings-backdrop-in .35s cubic-bezier(.4,0,.2,1) both}
.stage.closing{animation:board-dialog-out var(--board-dialog-motion) both;pointer-events:none}
.stage.closing::backdrop{animation:settings-backdrop-out .35s cubic-bezier(.4,0,.2,1) both}
/* 设置弹层左栏跟左侧抽屉走同一张面：两者是同一件事的两种形态——抽屉是全站导航，
   这一栏是设置内部的导航，抽屉上的液态玻璃没有理由进了弹层就换成一块实色。
   整张卡片仍旧自己铺 --page，让那一栏的 backdrop 采样到的是这块实色而不是身后的页面：
   弹层底下压着一层 70% 的黑遮罩，透过去模糊出来的是被压暗的馆藏封面，浅色主题下
   整栏发灰，那一列的字读不出来。抽屉那块玻璃身后是亮着的页面，同一份配方在它那儿
   成立、在这儿不成立——这一栏要的是那块玻璃的材质（漂移的光晕、内缘那圈亮线、
   边缘折射），不是它当时恰好采到的东西。 */
.settingscard.settingscard{background:var(--page)}
.settingscard.settingscard>.settingshead,.settingscard.settingscard>.settingsscroll{background:var(--page)}
/* 这一栏的玻璃不在这里画：它和抽屉、筛选条那几块并在同一条规则上（本文件靠前那条
   液态玻璃名单），连同漂移的光晕、内缘那圈亮线和边缘折射一起。自己另配一份
   `saturate(1.8) blur(20px)` 加两档 frost 色的结果是两块玻璃看着就不是一种材质——
   抽屉是全站导航、这一栏是设置内部的导航，同一件事的两种形态不该有两种光学。 */
html.board-high-contrast .settingscard.settingscard{background:var(--page)}
html.board-high-contrast .settingscard.settingscard>.board-local-nav{background:var(--ground);backdrop-filter:none;-webkit-backdrop-filter:none;animation:none}
/* 标题下那道影子跟左栏那块玻璃是同一份 `--glass-shadow`。裁剪不能省：那三层各带十几到
   几十像素的模糊，往上会糊在标题自己头上、往左会糊到左栏那一列上，要的只是往下那一半。
   它也只在内容压上来时才点亮——这一栏滚到头时标题和第一行之间留着 `--settings-gap`，
   影子出现在那时候就是凭空多了一条线。 */
.settingscard .settingshead{position:relative;z-index:2;clip-path:inset(0 0 -96px 0);transition:box-shadow .2s ease-out}
.settingscard.board-settings-scrolled .settingshead{box-shadow:var(--glass-shadow)}
.settingscard .settingshead h2{line-height:26px}
.drawer .board-sidebar-head #drawerClose{display:none}
.drawer .board-sidebar-head #filterBtn{display:grid;place-items:center;padding:0;width:36px;height:36px;flex:none;border-radius:8px;background:transparent}
.drawer .board-sidebar-head #filterBtn svg{width:20px;height:20px;margin:0}
.drawer .board-sidebar-head{gap:8px;min-height:36px}
.drawer .dnav button span{white-space:nowrap;min-width:0;max-width:190px;overflow:hidden;opacity:1;filter:blur(0);transition:max-width var(--board-motion),opacity var(--board-motion),filter var(--board-motion)}
@media(min-width:761px){
  .edge.edge{display:none}body{transition:padding-left var(--board-motion)}
  .drawer.drawer{width:60px;transform:none;transition:width var(--board-motion);border-radius:24px}
  .drawer.drawer.open{width:260px}body.drawer-open{--railW:284px}
  .drawer .drawerscroll{padding:12px}
  .drawer .dnav button{padding:8px;gap:8px;min-width:36px}
  .drawer .dnav button svg{width:20px;height:20px;flex:none}
  .drawer:not(.open) .dnav button span{max-width:0;opacity:0;filter:blur(4px)}
  .drawer:not(.open) .dnav button{gap:0}
  .drawer:not(.open) .sec{display:none}
  .drawer:not(.open) .board-sidebar-head{flex-direction:column-reverse}
  .drawer:not(.open) #brandHome{margin:0}
  .drawer:not(.open) #brandHome h1{display:none}
  .drawer:not(.open) .board-sidebar-head #filterBtn{height:20px}
}
@media(max-width:760px){
  .drawer.drawer{top:12px;bottom:12px;z-index:102;transform:translateX(calc(-100% - 16px));transition:transform var(--board-dialog-motion)}
  .drawer.drawer.open{transform:translateX(0)}
  /* 暗色画在 ::before 上，遮罩本身 visibility:hidden：它铺满视口、没有子元素、底色半透明，iOS 26 的 Safari
     会把它当压暗层给状态栏取色，一开侧栏状态栏就整块变暗。自带图层的 ::before 不计入外壳的可见内容，
     Safari 跳过这层、沿用顶栏的颜色，点在暗色上仍然落到遮罩身上收起侧栏。 */
  .scrim.scrim.on{top:0;z-index:101;background:none;visibility:hidden}
  .scrim.scrim.on::before{content:'';position:absolute;inset:0;background:#0007;visibility:visible}
  .index .ihead .geist-search{flex-basis:160px}
  .index .ihead .geist-search input,.geist-input,.settingscard .board-number-control input{font-size:16px}
  .settingscard .board-number-control{height:40px}.settingscard .board-number-control input{height:38px}
  .settingscard .settingsscroll .gselect,.settingscard .settingsscroll .gselectfield{height:40px;font-size:14px}
  .settingscard .settingsscroll .board-number-control>span{font-size:14px}
}
@media(prefers-reduced-motion:reduce){:root{--board-motion:0s;--board-dialog-motion:0s;--spring-pane-ms:0;--spring-press-ms:0;--motion-swap:0s;--motion-count:0s;--motion-reveal:0s;--motion-stagger:0ms;--motion-pop:0s}.settingscard .settingshead::after{transition:none}}
/* Stat Cards 的内层读数与底栏；统计卡仍是可键盘切换的视图入口。 */
/* 侧栏分组使用标题行与带计数的叶项。 */
.drawer.drawer{display:flex;flex-direction:column;overflow:hidden}
.drawer .drawerscroll{flex:1;min-height:0;scrollbar-width:none}
.drawer .drawerscroll::-webkit-scrollbar{display:none}
.drawer .ovtrack{display:none}
.drawer #brandHome{min-width:0;border-radius:24px;flex:1}
.drawer #brandHome h1{font-size:14px;line-height:20px;letter-spacing:0;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.board-library-chevron{width:16px;height:16px;flex:none;fill:none;stroke:var(--muted);stroke-width:2}
.board-library-menu{position:fixed;inset:auto;margin:0;box-sizing:border-box;width:265px;max-width:calc(100vw - 32px);padding:10px;border:1px solid var(--line);border-radius:16px;background:var(--ground);color:var(--ink);box-shadow:0 8px 24px light-dark(#0002,#0009);overflow-y:auto;scrollbar-width:none;transform-origin:top left}
.board-library-menu>p{padding:5px 8px 0;margin:0 0 6px;color:var(--muted);font-size:14px;line-height:20px}
.board-library-rows{display:flex;flex-direction:column;gap:4px}
.board-library-rows button{display:flex;align-items:center;gap:8px;padding:6px 8px;min-height:32px;border:0;border-radius:10px;background:transparent;color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.board-library-rows button:hover,.board-library-rows button[aria-pressed=true]{background:var(--hover)}
.board-library-avatar{display:grid;place-items:center;width:20px;height:20px;flex:none;border-radius:50%;background:var(--picked);font-size:12px;color:var(--muted)}
.board-library-avatar img,.board-library-avatar svg{width:20px;height:20px;object-fit:contain;fill:none;stroke:currentColor}.board-sidebar-head .mark{display:grid;place-items:center;border-radius:50%;background:var(--picked);color:var(--ink-2)}.board-sidebar-head .mark>svg,.board-sidebar-head .mark>img{width:24px;height:24px;object-fit:contain;fill:none;stroke:currentColor}
.board-library-avatar[data-color="1"]{background:#bef264;color:#365314}.board-library-avatar[data-color="2"]{background:#fbcfe8;color:#9d174d}
.board-library-rows button>span:last-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.board-library-menu footer{margin:14px -10px 0;padding:14px 18px 8px;border-top:1px solid var(--line)}
.board-library-menu footer button{width:100%}
@media(min-width:761px){.drawer:not(.open) .board-library-chevron{display:none}.drawer:not(.open) .board-sidebar-head{min-height:80px;flex-direction:column-reverse;justify-content:flex-end}.drawer:not(.open) .board-sidebar-head #filterBtn{display:grid;width:36px;height:36px}.drawer:not(.open) #brandHome{justify-content:center;flex:none;width:36px;height:36px;gap:0}.drawer:not(.open) #brandHome .mark{width:28px;height:28px}.drawer:not(.open) .dnav button{width:36px;height:36px;min-height:36px;padding:8px;justify-content:center}}
/* 菜单面板的开合（boardui menu-styles.ts，登记在 docs/BOARD_UI.md）：150ms ease-out，透明度、scale .95、2px 模糊一起进出。
   进场只填起点（backwards），放完就回到没有 transform／filter 的常态，不给面板留一层 blur(0) 光栅；退场填终点，等 dismissMenu 收走。
   缩放原点按开的方向：向下开从上沿长出来，向上开从下沿，侧开从左沿。减少动态效果时由 01-base 的全局规则关掉，dismissMenu 读到 none 就直接藏。 */
@keyframes board-menu-in{from{opacity:0;transform:scale(.95);filter:blur(2px)}}
@keyframes board-menu-out{to{opacity:0;transform:scale(.95);filter:blur(2px)}}
:is(.popmenu,.context-card,.board-library-menu,.searchmenu,.tagpicker):not([hidden]){animation:board-menu-in .15s ease-out backwards;transform-origin:top left}
:is(.popmenu,.context-card,.board-library-menu,.searchmenu,.tagpicker).leaving{animation:board-menu-out .15s ease-out forwards}
:is(.popmenu,.context-card,.board-library-menu)[data-placement=top],.sidebaraddmenu.sidebaraddmenu{transform-origin:bottom left}
.board-library-menu[data-placement=right]{transform-origin:left}
.board-sidebar-foot{display:flex;align-items:center;justify-content:space-between;gap:8px;flex:none;padding:12px}
.board-foot-actions{display:flex;align-items:center;gap:6px}
.board-foot-actions>#settingsBtn{width:36px;height:36px;padding:0;display:grid;place-items:center;border-radius:8px;background:transparent;flex:none}
.board-foot-actions>#settingsBtn svg{width:20px;height:20px;margin:0}
/* 「光晕配色」和它旁边的设置钮是同一排里的两枚图标键，所以穿同一身盒子：36×36、8px
   圆角、透明底、20px 字形、同一条悬停。boardui.com 那枚 Accent color 自带边框、面色底和
   一层 dropdown 薄影，是因为它浮在页面内容上、身后什么都没有；这一枚坐在侧栏自己的面
   上，挨着的设置钮什么都不穿——描一圈框只会让这一对读成两种控件。
   中间是 Remix 的调色盘字形（`#ri-palette-line`，实心路径，按它自己那套用 fill 画），
   说这枚键管什么。右下角放两枚 10px 的小圆，沿同一条竖线叠一半：上面那枚报当前
   预设的第一枚光晕色，下面那枚报强调色、叠在上层（它是按钮和焦点环真会换上的颜色，也是
   光晕关掉后唯一还管用的那一档）。强调色那枚外面一圈侧栏面色的环把两枚分开，整组外沿
   同样一圈环，读起来是浮在钮上的一组，不是钮身上的一块。光晕关掉时只剩强调色那一枚。
   实测见 docs/reference-snapshots/feralui-studio-boardui-accent-measured.md。 */
.board-glow-toggle{position:relative;display:grid;place-items:center;width:36px;height:36px;flex:none;
  padding:0;border:0;border-radius:8px;background:transparent;color:var(--muted);cursor:pointer}
.board-glow-toggle svg{width:20px;height:20px;fill:currentColor;stroke:none}
.board-glow-mark{position:absolute;right:0;bottom:0;display:block;width:10px;height:16px}
.board-glow-mark-glow,.board-glow-mark-accent{position:absolute;width:10px;height:10px;border-radius:50%;
  box-shadow:0 0 0 2px var(--ground)}
.board-glow-mark-glow{left:0;top:0;background:var(--glow-swatch,var(--ink))}
.board-glow-mark-accent{left:0;bottom:0;z-index:1;background:var(--color-accent-500)}
.board-glow-toggle[data-glow-off] .board-glow-mark-glow{display:none}
/* 这一排两枚键悬停只提图标色，不抬底色：它们坐在侧栏那块玻璃上，一块 6px 圆角的灰方片
   盖上去，玻璃在那一格里就断了。顶栏那批 `.ib` 站在实底上，那条抬填充的悬停照旧。 */
.board-glow-toggle:hover,.board-foot-actions>#settingsBtn:hover{background:transparent;color:var(--ink)}
.board-glow-toggle:focus-visible{outline:2px solid var(--tungsten);outline-offset:2px}
/* 这张卡穿的是媒体库选择弹层那身液态玻璃，规则就是同一条，见下面 `.board-library-menu`
   那一行。两张卡都从侧栏开出来、都盖在馆藏上，实底白卡站在一排毛玻璃中间会读成另一个
   产品的控件；在这里还多一层意思——卡上那两团漂动的光斑正是用户在卡里挑的那两枚颜色，
   改一下就在卡自己身上看得见。所以这里只留几何，材质一概不写。 */
.board-glow-menu{box-sizing:border-box;width:248px;max-width:calc(100vw - 32px);padding:10px;gap:0}
.board-glow-head{display:flex;align-items:center;justify-content:space-between;padding:0 4px 8px;color:var(--muted);font-size:12px}
/* 两组之间那条小标题：和头部同一档灰、同一个字号，只是不带右边的文字键。 */
.board-glow-sub{margin:12px 0 0}
.board-glow-reset{padding:0;border:0;background:transparent;color:var(--muted);font:inherit;font-size:12px;cursor:pointer}
.board-glow-reset:hover{color:var(--ink)}
.board-glow-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:6px;padding:0 4px}
/* 类名里写死的 `display` 压得过 `[hidden]` 那条 UA 规则，收起光晕那一组要自己说一遍；
   收起之后「强调色」成了卡里第一样东西，它那 12px 的上间距也一起归零。 */
.board-glow-head[hidden],.board-glow-grid[hidden]{display:none}
.board-glow-grid[hidden]+.board-glow-sub{margin-top:0}
.board-glow-chip{display:grid;place-items:center;width:28px;height:28px;padding:0;border:0;border-radius:50%;background:transparent;cursor:pointer}
.board-glow-chip:focus-visible{outline:2px solid var(--tungsten);outline-offset:2px}
/* 球面那三层白高光是 BoardUI 自己叠出来的，不是一个 radial 就完事：顶上一片大椭圆、
   里面一小片、底下一道反光，缺了底下那道，球看上去是贴纸不是球。 */
.board-glow-ball{position:relative;width:28px;height:28px;border-radius:50%;background:var(--glow-chip);
  box-shadow:inset 0 1px 1px #ffffff6b,inset 0 -1px 2px #0000002e,0 0 0 1px #ffffff29;
  transition:transform .15s ease}
.board-glow-ball::after{content:'';position:absolute;left:14%;right:14%;top:6%;height:38.5%;border-radius:50%;
  background:linear-gradient(#ffffff8a,#ffffff00)}
/* 强调色那一排球按 BoardUI 自己的画法：`radial-gradient(circle closest-side, 亮, 暗)`，
   取的就是这一档真会被换上去的 400 与 600 两级，所以球色不可能和按钮对不上。
   「玻璃原色」那一格画的是这块玻璃自带的两团反光色，一半一半：那一档没有三枚光晕可画，
   拿别的颜色顶上去会让人以为选中它之后侧栏是那个颜色。深色两团同色，球于是是一整颗。 */
.board-glow-ball[data-accent-ball]{--glow-chip:radial-gradient(circle closest-side,var(--color-accent-400),var(--color-accent-600))}
.board-glow-ball[data-glow-native]{--glow-chip:conic-gradient(from -90deg,var(--glass-native-a) 0 50%,var(--glass-native-b) 50% 100%)}
.board-glow-toggle[data-glow-native] .board-glow-mark-glow{background:linear-gradient(135deg,var(--glass-native-a) 50%,var(--glass-native-b) 50%)}
.board-glow-chip:hover .board-glow-ball{transform:scale(1.1)}
.board-glow-chip[aria-pressed=true] .board-glow-ball{box-shadow:inset 0 1px 1px #ffffff6b,0 0 0 1.5px var(--ground),0 0 0 2.5px color-mix(in srgb,var(--ink) 32%,transparent)}
.board-glow-menu footer{margin-top:10px;padding:0 4px}
.board-glow-menu footer .geist-button{width:100%}
.board-theme-toggle{position:relative;isolation:isolate;display:flex;gap:4px;padding:4px;border-radius:24px;background:var(--picked)}
.board-theme-toggle button{display:grid;place-items:center;width:32px;height:32px;flex:none;padding:0;border:0;border-radius:50%;background:transparent;color:var(--muted);cursor:pointer}
.board-theme-toggle button[aria-pressed=true]{color:var(--ink)}
/* 没被选中的那一枚此前悬停毫无反馈：它坐在 `--picked` 的轨道上、身上什么都没有，鼠标
   压上去和没压一样。抬一层 `--hover` 底加提亮图标色，正是这一对旁边那枚滑板给选中项的
   待遇的弱化版。选中那一枚不跟：它身下已经压着白滑板，再叠一层底就是两块面。 */
.board-theme-toggle button:not([aria-pressed=true]):hover{background:var(--hover);color:var(--ink)}
.board-theme-toggle svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2}
/* `will-change` 把这一枚提成自己的合成层。换主题要把 `:root` 上整套变量重写一遍，
   五千个节点跟着重算样式，主线程一口气忙掉二十几毫秒；滑块跟着卡在半路，按下去的
   那一下就是「点了没反应，然后突然到位」。提层之后这段位移归合成线程管，主线程忙它
   的，这一枚照样走完——它跟身后那片重算的内容本来就没有关系。
   缓动跟滑板同一条弹簧：这一列上会动的东西只有一种手感。 */
.board-theme-thumb{position:absolute;z-index:-1;left:4px;top:4px;width:32px;height:32px;background:var(--ground);border-radius:50%;box-shadow:0 1px 3px light-dark(#0001,#0008);will-change:transform;transition:transform calc(var(--spring-pane-ms) * 1ms) var(--spring-pane)}
.board-theme-toggle.is-dark .board-theme-thumb{transform:translateX(36px)}
/* 侧栏收到 60px 时这一列竖着排。`column-reverse` 而不是 `column`：DOM 里明暗键在前，
   是为了展开态那一横排仍是「明暗在左、配色与设置在右」；竖排时要的顺序正好相反，
   boardui.com 那一对就是配色在上、明暗在下。配色钮与设置钮都是 36px，左右各留 10px
   内边距后在 60px 的侧栏里居中，两枚圆心落在同一条竖线上。 */
@media(min-width:761px){.drawer:not(.open) .board-sidebar-foot{flex-direction:column-reverse;padding:12px 10px}.drawer:not(.open) .board-foot-actions{flex-direction:column}.drawer:not(.open) .board-theme-toggle{padding:2px;background:transparent}.drawer:not(.open) .board-theme-toggle button[aria-pressed=true],.drawer:not(.open) .board-theme-thumb{display:none}}
@media(prefers-reduced-motion:reduce){.board-theme-thumb{transition:none}}
.drawer .sec[data-sidebar-group]{border:0;padding:0;margin:4px 0 0}
.drawer .sec[data-sidebar-group]>h3{margin:0 0 4px;letter-spacing:0;text-transform:none;color:var(--muted);font-size:14px;line-height:20px;font-weight:400;gap:4px}
.board-section-toggle{display:flex;align-items:center;gap:8px;flex:1;min-width:0;padding:8px;border:0;border-radius:10px;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}
.board-section-toggle:hover{background:var(--hover)}
.board-sidebar-head #brandHome[aria-expanded=true]{box-shadow:0 0 0 2px var(--line);border-radius:var(--pill-radius)}
.board-sidebar-head #brandHome .mark{display:grid;place-items:center;background:none;border-radius:0}.board-sidebar-head .mark svg,.board-library-avatar svg,.drawer .dnav button svg{width:20px;height:20px;stroke-width:2}.board-library-avatar{background:none;border-radius:0}.board-home-logo{width:24px;height:24px;object-fit:contain;flex:none}.drawer:not(.open) .dnav button:has(.board-home-logo){padding:6px}
.drawer.drawer .dnav button[aria-pressed=true]:hover,.drawer.drawer .dnav button[aria-pressed=true]:active{background:var(--board-blue);color:white;filter:brightness(1.08)}
.board-section-toggle>span{font-size:12px;line-height:20px;font-weight:500;color:var(--muted)}
.vwrap>.gate{box-sizing:border-box;border-radius:inherit}.stage .vwrap{overflow:hidden;border-radius:var(--surface-radius)}
.board-section-toggle svg{order:2;margin-left:auto;width:14px;height:14px;flex:none;fill:none;stroke:currentColor;stroke-width:2;transform:rotate(0deg)}
.board-section-toggle[aria-expanded=true] svg{transform:rotate(90deg)}
.drawer .board-sidebar-body[hidden]{display:none}
.drawer .board-sidebar-body .chips{display:flex;flex-direction:column;gap:2px;padding-left:8px}
.drawer .board-sidebar-body .chip{display:flex;width:100%;min-width:0;min-height:36px;gap:8px;padding:8px;border:0;border-radius:10px;background:transparent;color:var(--muted);font-size:14px;line-height:20px;text-align:left;font-weight:400}
.drawer .board-sidebar-body .chip:hover{background:var(--hover);color:var(--ink)}
.drawer .board-sidebar-body .chip[aria-pressed=true]{color:var(--ink);background:var(--picked)}
.drawer .board-sidebar-body .chip-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.drawer .board-sidebar-body .chip .n{margin-left:auto;flex:none;padding:1px 4px;border-radius:4px;background:var(--surface);color:var(--muted);font-size:12px;line-height:16px}
.drawer .board-sidebar-body .chip svg{flex:none;width:16px;height:16px}
/* 名单末尾那枚展开键跟排名卡上的那枚同一副身量：40×20 药丸居中，14px 箭头，摊开后翻
   过来。它不是名单里的一项，所以不跟条目左对齐——那个位置上一行字会被读成最后一条。 */
.drawer .board-sidebar-body .sidemore{display:grid;place-items:center;width:40px;height:20px;margin:6px auto 2px;padding:0;border:1px solid var(--line);border-radius:999px;background:var(--surface);color:var(--muted);box-shadow:var(--elevation-xs);transition:background-color .15s ease,color .15s ease}
.drawer .board-sidebar-body .sidemore:hover{background:var(--hover);color:var(--ink)}
.drawer .board-sidebar-body .sidemore svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:transform .2s cubic-bezier(0,0,.2,1)}
.drawer .board-sidebar-body .sidemore[aria-expanded=true] svg{transform:rotate(180deg)}
@media(prefers-reduced-motion:reduce){.drawer .board-sidebar-body .sidemore svg{transition:none}}
/* 观看进度与动作分别成组，操作按钮保留各自的可访问名称。 */
.sidecontent .trace{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;padding:0;margin:8px 0 16px}
.sidecontent .trace-metric{min-width:0;padding:14px 12px;background:var(--surface);border-radius:12px}
.sidecontent .trace .lab{font-family:inherit;font-size:13px;line-height:18px;margin:0 0 12px;gap:8px}
.sidecontent .trace .lab>span:last-child{color:var(--ink);font-variant-numeric:tabular-nums}
.sidecontent .trace .bar{height:4px;border-radius:4px}
.sidecontent .fb{display:flex;flex-wrap:wrap;gap:4px;width:100%;padding:0;border:0;background:transparent;overflow:visible;margin:0 0 16px}
.sidecontent .fb button,.sidecontent .fb .fdownload{flex:0 0 36px;width:36px;height:36px;min-width:36px;display:grid;place-items:center;padding:0;border:0;border-radius:8px;background:var(--surface)}
.sidecontent .fb button svg,.sidecontent .fb .fdownload svg{display:block;width:18px;height:18px;margin:0}
.sidecontent .fb button[aria-pressed=true]{box-shadow:inset 0 0 0 1px currentColor}
.sidecontent .fb .dispose{margin-left:auto}
.sidecontent .obtn{min-height:40px;border-radius:10px;padding:8px 12px;font-size:14px;line-height:20px;font-weight:500;background:var(--surface);color:var(--ink);border:1px solid var(--line);gap:8px;box-shadow:inset 0 1px 0 #ffffff0a}
.sidecontent .obtn svg{width:20px;height:20px;color:#ff669d}
.sidecontent .obtn b{font-size:12px;line-height:18px;padding:1px 6px;border-radius:5px;background:var(--picked);font-weight:500}
.sidecontent .obtn:hover{background:var(--hover)}
.board-filter-frame.board-filter-frame .sorts .batchaction:hover,.entitycollectionhead.entitycollectionhead .sorts .batchaction:hover{background:var(--board-blue-hover);color:#fff}
.board-job-progress{display:flex;align-items:center;gap:12px;padding:12px 0;font-size:14px;line-height:20px}
/* 这张卡自己不留内边距，里面每块各带各的。进度环少了这一条，圆环就贴着卡片左沿，
   和它下面那几组链接表的 16px 对不上一条线。 */
.resourcepanel>.board-job-progress{padding:12px 16px}
.board-job-progress svg{flex:none}.board-job-progress circle{fill:none;stroke-width:2.5;stroke-linecap:round}
.board-job-track{stroke:var(--line-soft)}.board-job-fill{stroke:var(--tungsten);transition:stroke-dasharray .3s ease-out}
.board-job-progress small{display:block;color:var(--muted);font-size:12px;line-height:16px;font-variant-numeric:tabular-nums}
@media(prefers-reduced-motion:reduce){.board-job-fill{transition:none}}
.metricstrip,.tastesummaries{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));grid-auto-flow:row;gap:16px;overflow:visible;border:0;background:none}
.tastesummary{display:flex;flex-direction:column;min-width:0;padding:16px 0 0;border:0;border-radius:16px;background:var(--ground);overflow:hidden;text-align:left;box-shadow:0 1px 2px #00000008}
.tastesummary>.board-stat-label{display:flex;align-items:center;gap:8px;padding:0 16px;color:var(--ink-2);font-size:14px;line-height:20px}
.board-stat-icon{display:grid;place-items:center;width:28px;height:28px;border-radius:8px;background:linear-gradient(135deg,color-mix(in srgb,var(--color-accent-400) 15%,transparent),color-mix(in srgb,var(--color-accent-600) 3%,transparent));color:var(--tungsten);flex:none}
.board-stat-icon svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.tastesummary:nth-child(2) .board-stat-icon{color:#a78bfa;background:#a78bfa18}
.tastesummary:nth-child(3) .board-stat-icon{color:#34d399;background:#34d39918}
.tastesummary:nth-child(4) .board-stat-icon{color:#f59e0b;background:#f59e0b18}
.tastesummary>.board-stat-value{padding:12px 16px 16px;font-size:28px;line-height:34px;font-weight:500;color:var(--ink);font-variant-numeric:tabular-nums;letter-spacing:-.02em}
.tastesummary>.board-stat-footer{display:block;padding:10px 16px;background:var(--board-card-foot);margin:auto 0 0;font-size:12px;line-height:18px;color:var(--muted);min-height:38px}
.insightpanel,.tastehero{border:0;border-radius:16px;background:var(--ground);overflow:clip}
.insightcopy{border:0}.insightpanel>header{border:0;padding-top:8px}
@media(max-width:1000px){.metricstrip,.tastesummaries{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}}
@media(max-width:480px){.board-stat-label{padding-inline:12px;font-size:13px;gap:6px}.tastesummary>.board-stat-value{padding:12px;font-size:24px;line-height:34px}.tastesummary>.board-stat-footer{padding:8px 12px}.board-stat-icon{width:24px;height:24px}}

/* 数据按阅读目的分组，标题与内容共享边缘。 */
.insightpage,.tastepage{width:100%;max-width:var(--board-content)}
.followmanage .fmain{gap:28px}
.configfieldset-heading{border:0;padding-bottom:0}.configfieldset{border:0}.configfieldset>.geist-fieldset-footer{border:0}.configfieldset .configfieldset-heading h2{margin:0}
#linkCheckResult:not(:empty),#resourceSyncResult:not(:empty){margin-block:16px 28px}
.board-follow-list{display:grid;border-radius:16px;background:var(--ground);padding:8px 16px}.board-follow-list .fsource.frow{display:grid;grid-template-columns:22px minmax(0,1fr) auto auto auto auto;gap:12px;padding:8px;min-height:48px;border:0;border-radius:8px}.board-follow-list .fsource.frow>b{font-size:13px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:400}.board-follow-list .fsource.selected{background:var(--picked);opacity:1}.board-follow-selection{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:0 0 12px;font-size:13px}.board-follow-selection>label{display:flex;gap:8px;align-items:center}.board-follow-selection>span{margin-right:auto;color:var(--muted)}
@media(max-width:760px){.board-follow-list{padding:8px}}
@media(max-width:760px){body #manageTitle{width:100%}.followmanage .fsechead{gap:8px}}

/* 强调色的十一级色阶。机制照搬 BoardUI：主按钮、焦点环、链接、开关、选中态全都引用
   `--color-accent-*`，换强调色就是把这十一个变量整组指到另一个色相，组件规则一个字不改。
   上游把这一段写在 `@theme` 里（`frontend/src/react/boardui/styles/theme.css` 第 25–45 行），
   默认指向 blue 那一组基元，运行时由它自己的 accent 模块整组改写。
   Peach 这一份排在层叠层之外，所以无论 `/dist/peach-react.css` 里那份 `@layer theme` 怎么
   写，页面上生效的都是这里；React 子树在 `.peach-react` 上重新声明的是语义 token，它们
   本来就引用 `--color-accent-*`，值顺着根继承进去，两边因此不会各说各话。
   色值取 Tailwind v4 色板原文（`tailwindcss/theme.css`），十二个色相绕色轮一圈、六列两行；
   blue 的 400 用 BoardUI 自己那一枚 `#3392ff` 覆盖值，好让默认档的主按钮渐变一字不变。
   每一条都带上 `[data-accent-ball=…]`：侧栏弹层里那十二枚圆球就是拿同一组变量画的，
   球色和真换上去的颜色因此不可能走偏。 */
:root,:root[data-accent=blue],[data-accent-ball=blue]{--color-accent-50:oklch(97% 0.014 254.604);--color-accent-100:oklch(93.2% 0.032 255.585);--color-accent-200:oklch(88.2% 0.059 254.128);--color-accent-300:oklch(80.9% 0.105 251.813);--color-accent-400:#3392ff;--color-accent-500:oklch(62.3% 0.214 259.815);--color-accent-600:oklch(54.6% 0.245 262.881);--color-accent-700:oklch(48.8% 0.243 264.376);--color-accent-800:oklch(42.4% 0.199 265.638);--color-accent-900:oklch(37.9% 0.146 265.522);--color-accent-950:oklch(28.2% 0.091 267.935)}
:root[data-accent=red],[data-accent-ball=red]{--color-accent-50:oklch(97.1% 0.013 17.38);--color-accent-100:oklch(93.6% 0.032 17.717);--color-accent-200:oklch(88.5% 0.062 18.334);--color-accent-300:oklch(80.8% 0.114 19.571);--color-accent-400:oklch(70.4% 0.191 22.216);--color-accent-500:oklch(63.7% 0.237 25.331);--color-accent-600:oklch(57.7% 0.245 27.325);--color-accent-700:oklch(50.5% 0.213 27.518);--color-accent-800:oklch(44.4% 0.177 26.899);--color-accent-900:oklch(39.6% 0.141 25.723);--color-accent-950:oklch(25.8% 0.092 26.042)}
:root[data-accent=orange],[data-accent-ball=orange]{--color-accent-50:oklch(98% 0.016 73.684);--color-accent-100:oklch(95.4% 0.038 75.164);--color-accent-200:oklch(90.1% 0.076 70.697);--color-accent-300:oklch(83.7% 0.128 66.29);--color-accent-400:oklch(75% 0.183 55.934);--color-accent-500:oklch(70.5% 0.213 47.604);--color-accent-600:oklch(64.6% 0.222 41.116);--color-accent-700:oklch(55.3% 0.195 38.402);--color-accent-800:oklch(47% 0.157 37.304);--color-accent-900:oklch(40.8% 0.123 38.172);--color-accent-950:oklch(26.6% 0.079 36.259)}
:root[data-accent=amber],[data-accent-ball=amber]{--color-accent-50:oklch(98.7% 0.022 95.277);--color-accent-100:oklch(96.2% 0.059 95.617);--color-accent-200:oklch(92.4% 0.12 95.746);--color-accent-300:oklch(87.9% 0.169 91.605);--color-accent-400:oklch(82.8% 0.189 84.429);--color-accent-500:oklch(76.9% 0.188 70.08);--color-accent-600:oklch(66.6% 0.179 58.318);--color-accent-700:oklch(55.5% 0.163 48.998);--color-accent-800:oklch(47.3% 0.137 46.201);--color-accent-900:oklch(41.4% 0.112 45.904);--color-accent-950:oklch(27.9% 0.077 45.635)}
:root[data-accent=lime],[data-accent-ball=lime]{--color-accent-50:oklch(98.6% 0.031 120.757);--color-accent-100:oklch(96.7% 0.067 122.328);--color-accent-200:oklch(93.8% 0.127 124.321);--color-accent-300:oklch(89.7% 0.196 126.665);--color-accent-400:oklch(84.1% 0.238 128.85);--color-accent-500:oklch(76.8% 0.233 130.85);--color-accent-600:oklch(64.8% 0.2 131.684);--color-accent-700:oklch(53.2% 0.157 131.589);--color-accent-800:oklch(45.3% 0.124 130.933);--color-accent-900:oklch(40.5% 0.101 131.063);--color-accent-950:oklch(27.4% 0.072 132.109)}
:root[data-accent=emerald],[data-accent-ball=emerald]{--color-accent-50:oklch(97.9% 0.021 166.113);--color-accent-100:oklch(95% 0.052 163.051);--color-accent-200:oklch(90.5% 0.093 164.15);--color-accent-300:oklch(84.5% 0.143 164.978);--color-accent-400:oklch(76.5% 0.177 163.223);--color-accent-500:oklch(69.6% 0.17 162.48);--color-accent-600:oklch(59.6% 0.145 163.225);--color-accent-700:oklch(50.8% 0.118 165.612);--color-accent-800:oklch(43.2% 0.095 166.913);--color-accent-900:oklch(37.8% 0.077 168.94);--color-accent-950:oklch(26.2% 0.051 172.552)}
:root[data-accent=teal],[data-accent-ball=teal]{--color-accent-50:oklch(98.4% 0.014 180.72);--color-accent-100:oklch(95.3% 0.051 180.801);--color-accent-200:oklch(91% 0.096 180.426);--color-accent-300:oklch(85.5% 0.138 181.071);--color-accent-400:oklch(77.7% 0.152 181.912);--color-accent-500:oklch(70.4% 0.14 182.503);--color-accent-600:oklch(60% 0.118 184.704);--color-accent-700:oklch(51.1% 0.096 186.391);--color-accent-800:oklch(43.7% 0.078 188.216);--color-accent-900:oklch(38.6% 0.063 188.416);--color-accent-950:oklch(27.7% 0.046 192.524)}
:root[data-accent=sky],[data-accent-ball=sky]{--color-accent-50:oklch(97.7% 0.013 236.62);--color-accent-100:oklch(95.1% 0.026 236.824);--color-accent-200:oklch(90.1% 0.058 230.902);--color-accent-300:oklch(82.8% 0.111 230.318);--color-accent-400:oklch(74.6% 0.16 232.661);--color-accent-500:oklch(68.5% 0.169 237.323);--color-accent-600:oklch(58.8% 0.158 241.966);--color-accent-700:oklch(50% 0.134 242.749);--color-accent-800:oklch(44.3% 0.11 240.79);--color-accent-900:oklch(39.1% 0.09 240.876);--color-accent-950:oklch(29.3% 0.066 243.157)}
:root[data-accent=indigo],[data-accent-ball=indigo]{--color-accent-50:oklch(96.2% 0.018 272.314);--color-accent-100:oklch(93% 0.034 272.788);--color-accent-200:oklch(87% 0.065 274.039);--color-accent-300:oklch(78.5% 0.115 274.713);--color-accent-400:oklch(67.3% 0.182 276.935);--color-accent-500:oklch(58.5% 0.233 277.117);--color-accent-600:oklch(51.1% 0.262 276.966);--color-accent-700:oklch(45.7% 0.24 277.023);--color-accent-800:oklch(39.8% 0.195 277.366);--color-accent-900:oklch(35.9% 0.144 278.697);--color-accent-950:oklch(25.7% 0.09 281.288)}
:root[data-accent=violet],[data-accent-ball=violet]{--color-accent-50:oklch(96.9% 0.016 293.756);--color-accent-100:oklch(94.3% 0.029 294.588);--color-accent-200:oklch(89.4% 0.057 293.283);--color-accent-300:oklch(81.1% 0.111 293.571);--color-accent-400:oklch(70.2% 0.183 293.541);--color-accent-500:oklch(60.6% 0.25 292.717);--color-accent-600:oklch(54.1% 0.281 293.009);--color-accent-700:oklch(49.1% 0.27 292.581);--color-accent-800:oklch(43.2% 0.232 292.759);--color-accent-900:oklch(38% 0.189 293.745);--color-accent-950:oklch(28.3% 0.141 291.089)}
:root[data-accent=fuchsia],[data-accent-ball=fuchsia]{--color-accent-50:oklch(97.7% 0.017 320.058);--color-accent-100:oklch(95.2% 0.037 318.852);--color-accent-200:oklch(90.3% 0.076 319.62);--color-accent-300:oklch(83.3% 0.145 321.434);--color-accent-400:oklch(74% 0.238 322.16);--color-accent-500:oklch(66.7% 0.295 322.15);--color-accent-600:oklch(59.1% 0.293 322.896);--color-accent-700:oklch(51.8% 0.253 323.949);--color-accent-800:oklch(45.2% 0.211 324.591);--color-accent-900:oklch(40.1% 0.17 325.612);--color-accent-950:oklch(29.3% 0.136 325.661)}
:root[data-accent=rose],[data-accent-ball=rose]{--color-accent-50:oklch(96.9% 0.015 12.422);--color-accent-100:oklch(94.1% 0.03 12.58);--color-accent-200:oklch(89.2% 0.058 10.001);--color-accent-300:oklch(81% 0.117 11.638);--color-accent-400:oklch(71.2% 0.194 13.428);--color-accent-500:oklch(64.5% 0.246 16.439);--color-accent-600:oklch(58.6% 0.253 17.585);--color-accent-700:oklch(51.4% 0.222 16.935);--color-accent-800:oklch(45.5% 0.188 13.697);--color-accent-900:oklch(41% 0.159 10.272);--color-accent-950:oklch(27.1% 0.105 12.094)}
/* Board 的语义色与复合字阶；图表和业务状态独立于交互强调色。
   暗档的 --color-separator-border 比上游 theme.css 的 neutral-800 亮一档：分隔线画在
   --color-background-primary-default 上，而那一档暗色下同为 #262626，线和面同色就是一点
   都看不见。#404040 压在 #262626 上差 11.9 个 CIE 明度，浅色那对（#e5e5e5 压 #fff）是 9.1。 */
:root,:root[data-theme="light"]{--color-text-primary:#0a0a0a;--color-text-secondary:#737373;--color-text-tertiary:#a3a3a3;--color-background-full:#fff;--color-background-primary-default:#fff;--color-background-primary-hover:#f5f5f5;--color-background-secondary-default:#f5f5f5;--color-background-tertiary-default:#e5e5e5;--color-border-button-default:#e5e5e5;--color-border-button-hover:#d4d4d4;--color-border-button-active:#a3a3a3;--color-separator-border:#e5e5e5;--color-border-focus-ring:var(--color-accent-500);--color-text-white:#fff;--color-text-disabled:#d4d4d4;--board-blue:linear-gradient(180deg,var(--color-accent-500),var(--color-accent-600));--board-blue-hover:linear-gradient(180deg,var(--color-accent-400),var(--color-accent-500));--board-blue-active:linear-gradient(180deg,var(--color-accent-600),var(--color-accent-700));--board-red:linear-gradient(180deg,#fb2c36,#e7000b);--board-red-hover:linear-gradient(180deg,#ff6467,#fb2c36);--board-red-active:linear-gradient(180deg,#e7000b,#c10007);--board-red-line:#fb2c36;--board-red-wash:#ffe2e2;--board-red-text:#c10007}
:root[data-theme="dark"]{--color-text-primary:#fafafa;--color-text-secondary:#737373;--color-text-tertiary:#525252;--color-background-full:#121212;--color-background-primary-default:#262626;--color-background-primary-hover:#40404099;--color-background-secondary-default:#171717;--color-background-tertiary-default:#262626;--color-border-button-default:#404040;--color-border-button-hover:#737373;--color-border-button-active:#525252;--color-separator-border:#404040;--color-text-disabled:#262626;--board-red-line:#ff6467;--board-red-wash:color-mix(in srgb,#460809 60%,transparent);--board-red-text:#ffa2a2}
@media(prefers-color-scheme:dark){:root:not([data-theme]){--color-text-primary:#fafafa;--color-text-secondary:#737373;--color-text-tertiary:#525252;--color-background-full:#121212;--color-background-primary-default:#262626;--color-background-primary-hover:#40404099;--color-background-secondary-default:#171717;--color-background-tertiary-default:#262626;--color-border-button-default:#404040;--color-border-button-hover:#737373;--color-border-button-active:#525252;--color-separator-border:#404040;--color-text-disabled:#262626;--board-red-line:#ff6467;--board-red-wash:color-mix(in srgb,#460809 60%,transparent);--board-red-text:#ffa2a2}}
:root{--page:var(--color-background-full);--ground:var(--color-background-secondary-default);--surface:var(--color-background-primary-default);--sunk:var(--color-background-secondary-default);--ink:var(--color-text-primary);--ink-2:var(--color-text-secondary);--muted:var(--color-text-secondary);--line:var(--color-border-button-default);--line-soft:var(--color-separator-border);--picked:var(--color-background-tertiary-default);--inset:var(--color-background-tertiary-default);--hover:var(--color-background-primary-hover);--tungsten:var(--color-border-focus-ring);--chart-0:#2dd4bf;--chart-1:#a3e635;--chart-2:#f472b6;--chart-3:#38bdf8;--board-font:'Inter Variable','Inter','Segoe UI','Microsoft YaHei UI','PingFang SC',sans-serif;--board-body:400 14px/20px var(--board-font);--board-body-medium:500 14px/20px var(--board-font);--board-compact:400 13px/18px var(--board-font);--board-caption:400 12px/16px var(--board-font);--board-heading:500 20px/26px var(--board-font);--board-title:500 32px/44px var(--board-font);--board-figure:500 24px/34px var(--board-font)}
:root[data-theme]{--page:var(--color-background-full);--ground:var(--color-background-secondary-default);--surface:var(--color-background-primary-default);--sunk:var(--color-background-secondary-default);--ink:var(--color-text-primary);--ink-2:var(--color-text-secondary);--muted:var(--color-text-secondary);--line:var(--color-border-button-default);--line-soft:var(--color-separator-border);--picked:var(--color-background-tertiary-default);--inset:var(--color-background-tertiary-default);--hover:var(--color-background-primary-hover);--tungsten:var(--color-border-focus-ring)}
/* 主题选「跟随系统」时根上没有 `data-theme`，`web/css/01-base.css` 深色那一档的
   `--tungsten` 用的是自己那枚蓝的字面值，选择器比上面这条 `:root` 更具体，会把它压住。
   焦点环、链接和数据色跟着强调色走这件事不能只在手动选深色时成立，所以这里按同样的
   具体度接一条回来。 */
@media(prefers-color-scheme:dark){:root:not([data-theme]){--tungsten:var(--color-border-focus-ring)}}
/* 次级按钮压上去时换的那一面。`--hover` 不够用：它照搬 BoardUI 的 `background-primary-hover`，
   暗色那档是 60% 的 #404040 压在 #262626 上，算出来只差几个色阶，上游靠同时点亮边框补足。
   这里要的是不动边、只靠填充说话，所以取同一套面色里的下一档实色——浅色 #e5e5e5、
   暗色 #404040，两档的差都够一眼看见。值全部引用已有 token，不另立色值。 */
:root,:root[data-theme=light]{--control-hover:var(--color-background-tertiary-default)}
:root[data-theme=dark]{--control-hover:var(--color-border-button-default)}
@media(prefers-color-scheme:dark){:root:not([data-theme]){--control-hover:var(--color-border-button-default)}}
/* 这套里的标签不是胶囊，是一枚 8px 的圆角方片——详情面板那颗一直这么画，筛选条和资料
   页的那两排也是。基线主题给 --tag-radius 的是整圆，那是 Peach 自己那套的写法。
   8px 比 --surface-radius 的 14px 小一档：那一档是给卡片、面板这些成块的表面的，
   套到一枚三十像素高的标签上，圆角会吃掉两端的字。改这一个 token 就够了——卡片、详情
   面板、筛选条、交集条和标签骨架都从它取值，一处改完五处一起走。 */
:root{--tag-radius:8px}
body,.disp{font-family:var(--board-font);letter-spacing:0}body{font:var(--board-body)}button,input,textarea,select{font-family:var(--board-font)}
.pagetitle,.listtitle,body #manageTitle,.index .ihead h2,.indexheading,.playlistpage h2{font:var(--board-title);letter-spacing:0}.settingscard .settingshead h2,.configfieldset h2,.configfieldset h3,.cleanupfieldset h3,.followmanage .fsechead h3,.resourcesync>h2{font:var(--board-heading);letter-spacing:0}.metricstrip>button .board-stat-value,.tastesummary>.board-stat-value{font:var(--board-figure);letter-spacing:0}.drawer .dnav button,.board-library-rows button,.settingrow b,.fsource.frow>b{font:var(--board-body)}.fmeta,.settingrow small{font:var(--board-compact)}.board-stat-footer,.board-watch-measures small,.insighttoolbar p{font:var(--board-caption);letter-spacing:.15px}
.geist-button,.fbtn,.resourceaction{background-color:var(--color-background-primary-default);border-color:var(--color-border-button-default);color:var(--color-text-primary);transition:background-color .15s ease,border-color .15s ease,color .15s ease}
/* 悬停只抬填充，那圈线一步不动：按钮静止态已经带一圈 1px，悬停再把它加深，
   鼠标扫过一排次级键就是一排边框忽明忽暗，而键本身并没有变化。 */
.geist-button:hover:not(:disabled),.fbtn:hover:not(:disabled),.resourceaction:hover:not(:disabled){background-color:var(--color-background-primary-hover);color:var(--color-text-primary)}
/* 强调档那一面连同悬停只在下面 `body :is(…).primary` 一处给出。 */
.geist-button.danger:hover:not(:disabled),.fbtn.danger:hover:not(:disabled),.resourceaction.danger:hover:not(:disabled){background:var(--drop);color:#fff}
@media(max-width:760px){.pagetitle,.listtitle,body #manageTitle,.index .ihead h2,.indexheading{font:var(--board-figure)}input.geist-input,.geist-search input{font-size:16px}}

/* 每类骨架保留实际内容的列宽、轮廓和留白。 */
.board-page-skeleton{max-width:var(--board-content);width:100%;margin:auto}
.skeleton-lines{display:grid;gap:12px;min-width:0}
.skeleton-tabs{display:flex;gap:20px;align-items:center;min-height:48px;overflow-x:auto;white-space:nowrap;border-bottom:1px solid var(--line-soft)}
.skeleton-setting{display:flex;justify-content:space-between;align-items:center;min-height:64px}
.skeleton-toggle{width:40px;height:24px;border-radius:var(--pill-radius)}
.skeleton-radar{width:100%;height:260px;clip-path:polygon(50% 0,95% 25%,95% 75%,50% 100%,5% 75%,5% 25%)}
.board-page-skeleton .tastesummary{height:152px}
.board-page-skeleton .tastesummary>b .skeleton{height:34px}
.skeleton-segments>span{display:flex;align-items:center;padding:4px 10px;min-height:28px;border-radius:6px;color:var(--color-text-secondary);font:var(--board-body);white-space:nowrap}
.skeleton-segments>span.skeleton-segment-selected{color:var(--color-text-primary);font:var(--board-body-medium);background:var(--color-background-primary-default);box-shadow:var(--elevation-xs)}
.board-page-skeleton .configpage{display:grid;gap:40px}
.board-page-skeleton .qualitycover,.board-page-skeleton .pic{height:auto}
.board-page-skeleton .dupcover{height:auto;min-height:0}
.board-page-skeleton .playlistcreate{min-width:200px}
.board-page-skeleton .mixcopy{flex:1}
.board-page-skeleton .mav{width:38px;height:38px;border-radius:50%}
.skeleton-detail-media{height:auto;aspect-ratio:16/9;min-width:0;max-height:76vh}
.follow-content-skeleton>.followphotowall .skeletoncard i{aspect-ratio:4/3}
.related-skeleton{flex:none;width:100%;min-height:0}
.related-skeleton>div{display:flex;gap:11px}
.related-skeleton .skeletoncard{flex:0 0 216px}
.postercard-skeleton .skeletoncard{column-gap:10px;row-gap:3px}
body[data-density="dense"] .catalog-skeleton .skeletoncard{padding-top:7px}
body[data-density="dense"] .postercard-skeleton .skeletoncard b{height:1.35em}
body[data-density="dense"] .postercard-skeleton .skeletoncard em{height:1.35em}
body[data-density="dense"] .postercard-skeleton .skeletoncard u{height:30px}
body:is([data-surface="/junk-files"],[data-surface="/trash"]) .catalog-skeleton>div{grid-template-columns:repeat(auto-fill,minmax(min(100%,280px),1fr));gap:20px}
body:is([data-surface="/junk-files"],[data-surface="/trash"]) .catalog-skeleton .skeletoncard{border:1px solid var(--line-soft);border-radius:var(--surface-radius);overflow:hidden;background:var(--ground);padding-bottom:20px}
body[data-surface="/junk-files"] .catalog-skeleton .skeletoncard{grid-template-columns:minmax(0,1fr)}
body[data-surface="/junk-files"] .catalog-skeleton .skeletoncard s{display:none}
body[data-surface="/junk-files"] .catalog-skeleton .skeletoncard :is(b,em,u){grid-column:1;margin-inline:12px;width:calc(100% - 24px)}
.skeleton,.skeletoncard i,.skeletoncard b,.skeletoncard em,.skeletoncard s,.skeletoncard u{background:var(--color-background-tertiary-default);border-radius:8px}.skeletoncard i{border-radius:12px}.postercard-skeleton .skeletoncard{gap:6px 12px}.postercard-skeleton .skeletoncard s{border-radius:50%}.skeleton-cards>div{gap:24px 16px}.cleanup-skeleton .skeletoncard{border:0;border-radius:16px}.cleanup-skeleton .skeletoncard i,.review-skeleton .skeletoncard i{border-radius:8px}.index-skeleton .icell .ring{border-radius:50%}.entityskeletontext .skeleton{height:20px;border-radius:8px}.entityportrait.skeleton{border-radius:16px}.follow-content-skeleton .skeletoncard{padding-bottom:16px}.skeletondashstrip{border:0;gap:16px;background:none}.skeletondashstrip>span{border:0;border-radius:16px;background:var(--ground);min-height:152px}.skeletondashhero,.skeletondashpanel{border:0;border-radius:16px}

/* Board secondary：实体细边框、轻阴影和统一的三档控件尺寸。
   悬停只换填充，那圈线一动不动——按用户要求跟 BoardUI 的强调档对齐（2026-09-12 实测
   boardui.com/components/button：primary 悬停逐项不变；ghost 只把底色换深一档，
   浅色 rgb(219,234,254)→rgb(190,219,255)、暗色 rgb(28,57,142)→rgb(25,60,184)，
   全程没有边）。BoardUI 的 secondary 确实是填充加描边一起变，但它那档的悬停填充在暗色里
   只是 60% 的 #404040 压上去，差几个色阶，必须靠边来补；Peach 不跟这条，改成把填充
   直接抬到 `--control-hover`——那是同一套面色里的下一档实色，两档都一眼看得出，
   边就不必跟着闪。`transition` 只留 `background-color`。 */
body :is(.geist-button,.fbtn,.resourceaction,.batchbar button,.tagselection button,.geist-fieldset-footer>a,.geist-fieldset-footer>button):not(.primary,.danger,.error,.warning){box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;gap:4px;height:36px;min-height:36px;padding:8px 12px;border:1px solid var(--color-border-button-default);border-radius:10px;background:var(--color-background-primary-default);color:var(--color-text-primary);box-shadow:var(--elevation-xs);font:var(--board-body-medium);white-space:nowrap;text-decoration:none;transition:background-color .15s ease}
body :is(.geist-button,.fbtn,.resourceaction,.batchbar button,.tagselection button,.geist-fieldset-footer>a,.geist-fieldset-footer>button):not(.primary,.danger,.error,.warning):hover:not(:disabled,[aria-disabled=true]){background:var(--control-hover)}
/* 药丸、标签和外链卡跟按钮同一条。它们的边各有自己的颜色来源，所以逐类钉回静止值，
   不能统一写成一个 token。 */
body .pill:hover,body .brandpill:hover{border-color:var(--field-ring)}
/* 玻璃条上的药丸这样一来没有任何悬停反馈：那层 `--glass-text` 的权重比基线的
   `.pill:hover` 高，把提亮文字色的那半也一起吃掉了。横排互斥选项的悬停就是提文字色。 */
.board-filter-frame.board-filter-frame .pill:hover{color:var(--ink)}
body .index .index-tags .tg:hover{border-color:color-mix(in srgb,var(--tag-color) 32%,transparent)}
body .entitylinks a:hover{border-color:var(--line)}
body :is(.geist-button,.fbtn,.resourceaction,.batchbar button,.tagselection button):not(.primary,.danger,.error,.warning):is(:disabled,[aria-disabled=true]){background:var(--ground);border-color:var(--line);color:var(--muted);box-shadow:none}
/* 强调档全站一副面，三档渐变各差一个色阶，照 `boardui.com/components/button` 的
   `.bg-button-primary`（2026-09-12 实测）：静止 accent-500→600、悬停 400→500、按下
   600→700。不带边——上游那颗是 `border:0`，这里补一圈透明边会把内容盒压掉 2px，渐变的
   色标跟着错开一像素。
   悬停那一档铺在 `::before` 上淡入，不直接换 `background`：渐变是 background-image，
   它没有插值可言，直接换就是硬切一下。两层交叠着改 opacity 才过渡得起来，这也是上游
   那一份的做法。宿主要 `isolation:isolate`，不然 `z-index:-1` 会把它送到按钮所在层叠
   上下文的底下，铺到卡片背面去。 */
body :is(.geist-button,.fbtn,.resourceaction,.tagselection button).primary:not(:disabled){position:relative;isolation:isolate;background:var(--board-blue);border:0;color:#fff;box-shadow:var(--elevation-xs);transition:box-shadow .15s ease,color .15s ease}
body :is(.geist-button,.fbtn,.resourceaction,.tagselection button).primary:not(:disabled)::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;border-radius:inherit;background:var(--board-blue-hover);opacity:0;transition:opacity .15s ease}
body :is(.geist-button,.fbtn,.resourceaction,.tagselection button).primary:not(:disabled):hover::before{opacity:1}
body :is(.geist-button,.fbtn,.resourceaction,.tagselection button).primary:not(:disabled):active{background:var(--board-blue-active)}
body :is(.geist-button,.fbtn,.resourceaction,.tagselection button).primary:not(:disabled):active::before{opacity:0}
/* 危险档跟强调档同一副做法，照 `boardui.com/components/button` 的 `.bg-button-danger`
   （2026-09-12 实测，与 `.bg-button-primary` 逐字同构）：静止 red-500→600、悬停
   400→500、按下 600→700，悬停那一档铺在 `::before` 上淡入。
   批量条和复核那一排此前各写死过同一对红，一并并到这份 token 上——同一种「删掉就回不来」
   在不同页面读出两种红，用户无从判断哪一种更重。 */
body :is(button.danger,.batchbar button.danger):not(:disabled){position:relative;isolation:isolate;background:var(--board-red);border:0;color:#fff;box-shadow:var(--elevation-xs);transition:box-shadow .15s ease,color .15s ease}
body :is(button.danger,.batchbar button.danger):not(:disabled)::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;border-radius:inherit;background:var(--board-red-hover);opacity:0;transition:opacity .15s ease}
body :is(button.danger,.batchbar button.danger):not(:disabled):hover::before{opacity:1}
body :is(button.danger,.batchbar button.danger):not(:disabled):active{background:var(--board-red-active)}
body :is(button.danger,.batchbar button.danger):not(:disabled):active::before{opacity:0}
:root{--board-card-foot:color-mix(in srgb,var(--ground) 98%,var(--ink))}
.board-sidebar-head #brandHome .mark{color:var(--glass-text)}
.configfieldset>.geist-fieldset-footer,.cleanupfieldset>.geist-fieldset-footer,.resourcesyncfooter,.resourceapplyrow{border-top-left-radius:0;border-top-right-radius:0;background:var(--board-card-foot)}
.followmanage .board-follow-list{display:grid;grid-template-columns:minmax(0,1fr);gap:16px;padding:0;background:none}
.followmanage .board-author-toggle{margin-left:auto;flex:none}.board-author-toggle[aria-expanded=true] svg{transform:rotate(180deg)}
.followmanage .board-follow-list .fsource.frow{min-height:64px;padding:12px 8px}
/* 表格视图在 Board 层套的是 Board 自己的 token：表头次级底、三级字、分隔线色都取自
   boardui 同名变量。外框用 primary 底而不是作者卡那块 --ground：Board 层把 --ground 定成了
   secondary，和表头同色，表头那条带子就没了；boardui 的表格本来就摆在 primary 面上。 */
.followmanage .ftableframe{border:1px solid var(--color-separator-border);border-radius:var(--surface-radius);background:var(--color-background-primary-default);overflow:hidden}.followmanage .ftablewrap{border-radius:0;background:transparent}.followmanage .ftable th{border-top:0}
.followmanage .ftable th{color:var(--color-text-tertiary);background:var(--color-background-secondary-default);border-color:var(--color-separator-border)}
.followmanage .ftable tbody tr{border-color:var(--color-separator-border)}
@media(max-width:760px){.followmanage .fsechead .iconswitch{display:flex}}

/* 导航图形使用同宽槽位；logo 的透明边距按实际可见轮廓适配。 */
.board-home-logo{width:20px;height:20px}.drawer:not(.open) .dnav button:has(.board-home-logo){padding:8px}
.drawer.drawer .dnav button:not([aria-pressed=true]),.edge.edge button:not([aria-pressed=true]),.board-sidebar-head #brandHome .mark{color:var(--color-text-secondary)}
.board-library-menu.board-library-menu,.board-glow-menu.board-glow-menu{background:var(--glass-drift-a),var(--glass-drift-b),linear-gradient(125deg,var(--glass-sheen),transparent 42%,var(--glass-low)),var(--glass-fill);background-size:200% 200%,200% 200%,auto;border:1px solid var(--glass-low);border-radius:22px;color:var(--glass-text);backdrop-filter:blur(22px) saturate(160%) var(--glass-lume);-webkit-backdrop-filter:blur(22px) saturate(160%) var(--glass-lume);box-shadow:inset 0 1px 0 var(--glass-rim),var(--glass-shadow)}
/* 这一列的填充由那块滑过去的玻璃提供，行自己只管文字色：两边都铺的话，静止态是一块
   不透明的底压在玻璃上面，滑动的那块从头到尾被盖住，看到的只有当前项换了个地方亮起来。
   玻璃住在这一列里，所以这一列是它的定位宿主；行要压在它上面，否则滑过去时字被盖住。 */
.board-library-menu .board-library-rows{position:relative}
.board-library-menu .board-library-rows button{position:relative;color:color-mix(in srgb,var(--glass-text) 66%,transparent)}
.board-library-menu .board-library-rows button:is(:hover,[aria-pressed=true]){background:none;box-shadow:none;color:var(--glass-text)}
.board-library-menu .board-library-rows>.viewglide{border-radius:10px}
.board-library-menu footer{border-color:var(--glass-low)}
@media(max-width:760px){.settingscard.settingscard .settingsscroll{padding-top:16px}}
.board-sidebar-head #brandHome:hover{background:var(--color-background-primary-hover);border-radius:var(--pill-radius)}
.drawer .sec[data-sidebar-group]>.board-section-toggle{box-sizing:border-box;display:flex;width:100%;min-height:36px;margin:0 0 4px;padding:8px 10px;gap:8px;border-radius:8px;list-style:none;color:var(--color-text-secondary);font:var(--board-caption)}
.board-section-toggle::-webkit-details-marker{display:none}.drawer .sec[data-sidebar-group]>.board-section-toggle:hover{background:var(--picked)}.board-section-toggle>span{flex:1;min-width:0}.board-section-toggle>svg{order:3;flex:none;margin-left:auto}.drawer .sec[data-sidebar-group]>.fcollapse>.fcollapsebody{padding:0 0 0 10px}
.card:hover .pic::after,.card.selected .pic::after{box-sizing:border-box;border-radius:inherit}.card.selected .pic::after{content:"";position:absolute;inset:0;z-index:6;pointer-events:none;border:2px solid var(--on-media)}.card.selected .pic,.card.selected:hover .pic{box-shadow:none}

/* Board 公开基础控件：尺寸与来源登记在 docs/BOARD_UI.md。 */
.pcheck{vertical-align:middle;align-self:center}.pcheck>span{position:relative;width:16px;height:16px;border:1px solid var(--color-border-button-default);border-radius:4px;background:var(--color-background-primary-default);box-shadow:var(--elevation-xs);transition:background .15s,border-color .15s,box-shadow .15s}
.pcheck input:is(:checked,:indeterminate)+span{color:#fff;border-color:transparent;background:var(--board-blue);box-shadow:inset 0 1px 0 #ffffff40,0 1px 2px #0450e229}
.pcheck input:indeterminate+span svg{visibility:hidden}.pcheck input:indeterminate+span::after{content:'';position:absolute;top:6px;left:3px;width:8px;height:2px;border-radius:1px;background:#fff}
.pcheck input:disabled+span{opacity:.5}.pcheck>span svg{width:14px;height:14px;stroke-width:2}.pcheck:hover>span{border-color:var(--color-border-button-hover)}
input[type=checkbox]:not(.ptoggle):not(.pcheck input):not(.peach-react input){accent-color:var(--color-accent-600);width:16px;height:16px;vertical-align:middle;margin:0;flex:none}
.dual-range .range-base,.dual-range .range-fill{height:6px;top:11px}.dual-range .range-base{background:var(--color-background-tertiary-default);box-shadow:inset 0 1px 1px #0000000f}.dual-range .range-fill{background:linear-gradient(90deg,var(--color-accent-400),var(--color-accent-600));box-shadow:inset 0 1px 0 #ffffff3d,0 1px 2px #0450e229}
body :is(.dual-range input,.photozoom input,.vjs-peach-speed-range)::-webkit-slider-thumb{appearance:none;width:20px;height:20px;border:1px solid var(--color-border-button-default);border-radius:50%;background:radial-gradient(circle at center,#fff 3px,#e5e5e5 3.5px,#fff 4px);box-shadow:0 2px 4px light-dark(#0000001a,#00000080),inset 0 1px 0 #ffffffcc;cursor:grab;transition:scale calc(var(--spring-press-ms) * 1ms) var(--spring-press),box-shadow .15s}
/* 抓住的时候手柄涨一圈，松开按同一条弹簧收回去。位置不参与任何过渡——手柄要贴着
   指针走，给它加一段缓动就是让它落在指针后面，滑块立刻变成拖不准的东西。 */
body :is(.dual-range input,.photozoom input,.vjs-peach-speed-range):active::-webkit-slider-thumb{scale:1.18;transition:scale .06s ease-out}
body :is(.dual-range input,.photozoom input,.vjs-peach-speed-range)::-moz-range-thumb{width:18px;height:18px;border:1px solid var(--color-border-button-default);border-radius:50%;background:radial-gradient(circle at center,#fff 3px,#e5e5e5 3.5px,#fff 4px);box-shadow:0 2px 4px light-dark(#0000001a,#00000080)}
body :is(.photozoom input,.vjs-peach-speed-range)::-webkit-slider-runnable-track{height:6px;border-radius:999px;background:linear-gradient(90deg,var(--color-accent-400) var(--board-range-value,var(--peach-speed-percent,0%)),var(--color-background-tertiary-default) 0);box-shadow:inset 0 1px 1px #0000000f}
body :is(.photozoom input,.vjs-peach-speed-range)::-webkit-slider-thumb{margin-top:-7px}
body :is(.photozoom input,.vjs-peach-speed-range)::-moz-range-track{height:6px;border-radius:999px;background:linear-gradient(90deg,var(--color-accent-400) var(--board-range-value,var(--peach-speed-percent,0%)),var(--color-background-tertiary-default) 0)}
/* 气泡对准手柄居中，越过轨道两端的那一截由 `--range-tip-shift` 收回来（`syncBoardRange`
   量出来的实际溢出）：侧栏只比轨道宽出一点点，伸出去的半截会被侧栏裁掉，读数就只剩
   一半。两端各钉一种对齐只在正好 0% 和 100% 时成立，中间任何位置照样出界。 */
.board-range-tip{position:absolute;z-index:1;bottom:calc(100% + 4px);transform:translateX(calc(-50% + var(--range-tip-shift,0px)));padding:4px 8px;border:1px solid var(--color-border-button-default);border-radius:8px;background:var(--color-background-primary-default);color:var(--color-text-primary);font:var(--board-caption);white-space:nowrap;box-shadow:var(--elevation-xs);pointer-events:none}
/* 刚动过的那枚压在另一枚上面：两端拖到一起时它们会叠，底下那枚报的是自己停下的位置。 */
.board-range-tip[data-range-active]{z-index:2}
/* 两端都常显：这里是唯一报数的地方，藏起来的话不碰滑块就看不出当前筛的是哪一段。 */
.dual-range{margin-top:36px}
.toast{position:relative;align-items:center;gap:12px;width:min(400px,calc(100vw - 32px));padding:16px 44px 16px 16px;border-radius:16px;background:var(--color-background-primary-default);border-color:var(--color-border-button-default);color:var(--color-text-primary);font:var(--board-body);box-shadow:0 12px 24px -4px light-dark(#0000001a,#0000008c),0 4px 8px -2px light-dark(#0000000d,#00000073);overflow:hidden}
.toast.warn{border-color:var(--color-border-button-default)}.toast .board-notification-icon{display:grid;place-items:center;width:40px;height:40px;flex:none;border-radius:50%;background:color-mix(in srgb,var(--color-accent-400) 12%,var(--color-background-primary-default));color:var(--color-accent-600)}.toast.warn .board-notification-icon{background:color-mix(in srgb,#f04452 12%,var(--color-background-primary-default));color:var(--drop)}/* 这枚字形是描边件：不写 `fill:none` 就按 `fill` 的初值涂黑，一个勾会糊成实心箭头。 */
.board-notification-icon svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}.toast p{margin:0}.toast .tclose{position:absolute;right:12px;top:12px}.toast .tact{align-self:center;font-weight:500;color:var(--tungsten)}
.toast.leaving{transform:translateY(8px) scale(.96);filter:blur(3px);transition:height .18s ease-out,margin .18s ease-out,padding .18s ease-out,border-width .18s ease-out,opacity .18s ease-out,transform .18s ease-out,filter .18s ease-out}
.board-notification-timer{position:absolute;bottom:0;left:0;right:0;height:3px;background:var(--color-accent-600);transform-origin:left;animation:board-notification-countdown var(--notification-duration) linear forwards}.toast:hover .board-notification-timer,.toast:focus-within .board-notification-timer{animation-play-state:paused}@keyframes board-notification-countdown{to{transform:scaleX(0)}}
.board-tooltip{box-sizing:border-box;max-width:240px;padding:6px 10px;border:1px solid var(--color-border-button-default);border-radius:8px;background:var(--color-background-primary-default);color:var(--color-text-primary);font:var(--board-caption);white-space:normal;box-shadow:0 12px 24px -4px light-dark(#0000001a,#0000008c),0 4px 8px -2px light-dark(#0000000d,#00000073)}
.board-tooltip{position:fixed;z-index:var(--layer-tooltip);pointer-events:none}.board-tooltip[hidden]{display:none}
body :is(.popmenu,.gselectmenu,.cardmenupanel){box-sizing:border-box;padding:10px;border:1px solid var(--color-border-button-default);border-radius:16px;background:var(--color-background-primary-default);color:var(--color-text-primary);box-shadow:0 12px 24px -4px light-dark(#0000001a,#0000008c),0 4px 8px -2px light-dark(#0000000d,#00000073)}
/* 每一项都在这里定死成「左起一行」，位置和形状写在同一条里。浮层看着浮在页面上方，
   DOM 却长在触发它的那张卡里，于是页面分区给自家 button 写的本地外观照样命中它：整理卡
   的 `.cleanupfieldset button` 带 `justify-content:center`，来源下拉每一项的站标就被推到
   行正中，和触发器里那一枚不在同一列。这里只写形状不写位置的话，那个属性在菜单这一侧
   无人竞争，页面那条就成了唯一声明者。 */
body :is(.popmenu,.gselectmenu,.cardmenupanel)>:is(button,[role=option],[role=menuitem]){display:flex;align-items:center;justify-content:flex-start;width:100%;min-height:36px;padding:8px;gap:8px;border:0;border-radius:10px;background:transparent;color:var(--color-text-secondary);font:var(--board-body);text-align:left;box-shadow:none}
body :is(.popmenu,.gselectmenu,.cardmenupanel)>:is(button,[role=option],[role=menuitem]):is(:hover,:focus-visible,[aria-selected=true]){background:var(--color-background-primary-hover);color:var(--color-text-primary)}
/* 这一条只管「一句话就是一个链接」的那种外链：一行蓝字，没有边、没有底、不占按钮的位置。
   资料页那排外链不在此列——它是一圈药丸，边、底和 4px 内边距都是它自己的，被这里的
   `padding:0` 和 `border:0` 抹平之后那一排就只剩十个光秃秃的图标。
   排除条件写的是那枚圆盘 `.entitylinkicon` 本身，不写「有没有 `<img>`」：常见社媒的标记
   是内联 `<svg>`，一枚 `<img>` 都没有，按后一个判据照样漏进来。只认圆盘还把这条豁免收在
   资料页那一排上，别处的外链——包括包着图的——继续按这条走，不因为多一张图就长出个框。 */
body a:is(.externallink,[target=_blank]):not(:has(.entitylinkicon)):not(.cardlink){display:inline-flex;align-items:center;gap:4px;min-height:20px;padding:0;border:0;border-radius:4px;background:transparent;box-shadow:none;color:var(--tungsten);font-weight:500;text-decoration:none;text-underline-offset:3px}
body a:is(.externallink,[target=_blank]):not(:has(.entitylinkicon)):not(.cardlink):hover{background:transparent;text-decoration:underline;box-shadow:none}.externallink .externalmark{width:18px;height:18px;flex:none}
.board-link-button{display:inline-flex;align-items:center;justify-content:center;justify-self:start;gap:4px;max-width:100%;padding:0;border:0;border-radius:4px;background:transparent;box-shadow:none;color:var(--tungsten);font:inherit;font-weight:500;text-decoration:none;text-underline-offset:3px;transition:color .15s ease}
.board-link-button:hover{background:transparent;text-decoration:underline;box-shadow:none}
.board-link-button:focus-visible{outline:2px solid var(--tungsten);outline-offset:3px}
.board-link-button>svg{width:20px;height:20px;flex:none;fill:none;stroke:currentColor;stroke-width:2;transform:rotate(90deg)}
body :is(.board-chip,.badge){display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:4px 6px;min-height:24px;box-sizing:border-box;border:0;border-radius:6px;background:var(--color-background-tertiary-default);color:var(--color-text-secondary);font:var(--board-caption);white-space:nowrap}
body .board-chip.success{background:color-mix(in srgb,#84cc16 16%,var(--color-background-primary-default));color:#4d7c0f}body .board-chip.error{background:color-mix(in srgb,#f43f5e 12%,var(--color-background-primary-default));color:#e11d48}
.fprovider{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.followmanage .fsource.frow{grid-template-columns:20px minmax(120px,1fr) minmax(100px,auto) auto auto}
:is(.board-button-group,[data-button-group]){display:inline-flex;align-items:center;overflow:hidden;border:1px solid var(--color-border-button-default);border-radius:10px;background:var(--color-background-primary-default);box-shadow:var(--elevation-xs)}
:is(.board-button-group,[data-button-group])>button{height:34px;padding:0 12px;border:0;border-radius:0;box-shadow:none;color:var(--color-text-secondary);font:var(--board-body);white-space:nowrap}
:is(.board-button-group,[data-button-group]):not([data-variant=primary])>button{background:transparent}
:is(.board-button-group,[data-button-group])>button+button{border-left:1px solid var(--color-border-button-default)}
:is(.board-button-group,[data-button-group])>button:is(:hover,[aria-pressed=true],[aria-selected=true]):not(.primary){background:var(--control-hover);color:var(--color-text-primary)}
:is(.board-button-group,[data-button-group])>button:focus-visible{position:relative;z-index:1;outline:2px solid var(--color-border-focus-ring);outline-offset:-2px}
.photolight .photonav{width:36px;height:36px;border:1px solid var(--color-border-button-default);border-radius:10px;background:var(--color-background-primary-default);color:var(--color-text-secondary);box-shadow:var(--elevation-xs)}.photolight .photonav:hover{background:var(--color-background-primary-hover)}.photolight .photonav svg{width:20px;height:20px}.photolight .photonav.swiper-button-disabled{opacity:.4;pointer-events:none}
.board-carousel-pagination{display:flex;align-items:center;justify-content:center;gap:8px;max-width:160px;margin-inline:auto;overflow:hidden;height:28px}.board-carousel-pagination .swiper-pagination-bullet{width:6px;height:6px;flex:none;margin:0!important;border:0;padding:0;border-radius:999px;background:#a3a3a3;opacity:1;transition:width .2s ease-out,background .2s ease-out}.board-carousel-pagination .swiper-pagination-bullet-active{width:16px;background:#fafafa}
@media(prefers-reduced-motion:reduce){.board-tooltip,.board-carousel-pagination .swiper-pagination-bullet{transition:none}}
.board-author-actions{display:flex;align-items:center;gap:8px;margin-left:auto;flex:none}
.board-author-actions .board-author-toggle{margin:0}
.followmanage .fsource.selected{background:var(--color-background-primary-default);box-shadow:none;border-color:var(--color-border-focus-ring)}.followmanage .fsource.selected.disabled{opacity:1}
/* 同底色上的嵌套卡（作者卡里的来源行）按 10px 圆角取 shadow-sm：
   BoardUI 的 shadow-xs 出自 24px 大圆角的 auth-card（2026-09-09 取证登记
   boardui-auth-card），贴地细影在小圆角上只剩一条硬边读成环，sm 多一档 3px 扩散。 */
.followmanage .fsource:has([data-follow-select]):not(tr){border:1px solid var(--color-border-button-default);border-radius:10px;padding:12px 20px 12px 16px;margin:8px 0;cursor:pointer;transition:background-color 150ms ease,border-color 150ms ease;box-shadow:var(--elevation-sm)}
.followmanage .fsource:has([data-follow-select]):hover{background:var(--color-background-primary-hover)}
.followmanage .fsec:has(.board-follow-selection){padding:0;border-radius:18px;background:var(--ground);overflow:visible}.followmanage .fsec>.board-follow-selection{padding:4px 24px 12px}
@media(max-width:1000px){.cleanupgrid :is(.cleanupemptyfolders,[data-cleanup-processing]),.resourcesyncbox[data-cleanup-task]{grid-template-columns:1fr}.cleanupgrid :is(.cleanupemptyfolders,[data-cleanup-processing])>:is(.geist-fieldset-footer,[data-geist-fieldset-footer]),.resourcesyncbox[data-cleanup-task]>.resourcesyncfooter{justify-content:flex-start;padding-top:0}}
.metricstrip>button[aria-selected=true]{background:var(--color-background-primary-default);box-shadow:none}.metricstrip>button[aria-selected=true]::after{box-sizing:border-box}.metricstrip>button[aria-selected=true] .board-stat-footer{background:var(--board-card-foot)}
body .gselectmenu [role=option][aria-selected=true],body .popmenu [aria-checked=true]{background:color-mix(in srgb,var(--color-text-primary) 10%,var(--color-background-primary-default));color:var(--color-text-primary)}
.insightswitch{display:inline-flex;align-items:center;gap:2px;padding:3px;border:1px solid var(--line);border-radius:10px;background:var(--color-background-primary-default);box-shadow:var(--elevation-xs)}.insightswitch label>span{display:flex;align-items:center;min-height:28px;padding:4px 10px;border-radius:7px;color:var(--color-text-secondary);font:var(--board-body-medium)}.insightswitch label:has(input:checked)>span{background:var(--color-background-primary-hover);color:var(--color-text-primary);box-shadow:0 1px 2px light-dark(#0000001a,#0000008c)}
/* 两张活跃图并排。图本身归 React（`frontend/src/react/taste/charts.tsx`），这一条留给
   遗留壳铺的那张骨架：它在这一格里画两块等待中的面板。 */
.board-activity-charts{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1fr);gap:20px;margin:20px 0}
@media(max-width:1000px){.board-activity-charts{grid-template-columns:1fr}}
/* 切换器展开时自己带一圈 2px 描边，导航列表首项又会抬起 hover 底：两者之间留 4px
   的话这两块底色是挨着的，读起来像切换器压在第一项上。 */
.drawer .board-sidebar-head{margin-bottom:0!important}.drawer .dnav{margin-top:12px;gap:4px}.drawer #brandHome{height:36px;min-height:36px;box-sizing:border-box}.drawer .dnav button{height:36px;min-height:36px}
[data-board-tabs]{position:relative!important}[data-board-tabs]::before{content:'';position:absolute;bottom:0;left:0;width:var(--tab-width,0px);height:2px;background:var(--tungsten);transform:translateX(var(--tab-x,0px));pointer-events:none;z-index:1}/* 这条指示条也是「当前落在哪一个」，位移跟着同一条弹簧走。它是伪元素，没法像那几块
   底板一样再挂一段独立的形变——冲过落点再荡回来这一下有，抻开那一下没有。
   宽度另走匀速：跟着弹簧过冲的话，它会在停下之前先抻出邻居的边界。 */
[data-board-tabs].board-tabs-ready::before{
  transition:transform calc(var(--spring-pane-ms,200) * 1ms) var(--spring-pane,ease),
             width calc(var(--spring-pane-ms,200) * 1ms) ease}
body [data-board-tabs] button[aria-selected=true],body .managebar [data-board-tabs] button[aria-pressed=true]{border-bottom-color:transparent}
@media(prefers-reduced-motion:reduce){[data-board-tabs].board-tabs-ready::before{transition:none}}
.followmanage .fsource:has([data-follow-select]){background:var(--color-background-primary-default)}
.followmanage .fsource.selected:has([data-follow-select]){border-color:var(--color-border-focus-ring)}
/* Split Button 照 Geist 实测（`vercel-geist-split-button.md`「悬停」）：两半各是一颗
   带自己填充的按钮，整组只管并排和外圆角，悬停只抬指针下那一半——抬的那一层就是
   `bg-button-primary` 自己的 `::before` 淡入。中缝那条 1px 线是触发档的 `::after`，
   `left:-1px` 盖在主动作最后一列上、上下顶满；它排在后面的那颗里，所以谁在悬停都压在
   两半上面，颜色也不跟着变。线取悬停那一档的起始色（Geist 的线与它的悬停填充同一档灰）。
   主动作那条要自己写底色与字色：同组更宽的通用 hover 会把底换成灰、字换成墨色。
   BoardUI 的 Button 自带 `overflow-hidden`，会把伸出左缘那 1px 裁掉，两半都放开；外圆角
   由按钮组那一层裁。 */
[data-split-button][data-button-group]{position:relative;isolation:isolate}
[data-split-button][data-button-group]>button{position:relative;z-index:1;height:36px;border:0;border-radius:0;box-shadow:none;overflow:visible}
[data-split-button][data-button-group]>button+button{border-left:0}
[data-split-button][data-button-group]>button+button::after{content:"";position:absolute;z-index:2;inset-block:0;left:-1px;width:1px;background:var(--split-seam);pointer-events:none}
[data-split-button][data-variant=primary]{--split-seam:var(--color-accent-400);border:0;background:none;box-shadow:none}
[data-split-button][data-variant=primary]>button:not(:disabled){background:var(--board-blue);color:#fff}
[data-split-button][data-variant=primary]>button:not(:disabled,[aria-disabled=true]):active{background:var(--board-blue-active)}
[data-split-button][data-variant=primary]>button:last-child{width:36px;padding:8px}
/* 骨架里等数据的键（`data-skeleton-action`，原生 `disabled`）不管哪一档都是同一副禁用面：
   `--surface` 底、一圈 `--border-15`、`--muted` 字，不靠 opacity。属性写两遍是为了压过
   同组更宽的 hover 与各档自己的 `:disabled`，这一类规则都排在它前面。
   拆分按钮那一圈画在整组上，两半各自不描边，中缝退成同一色的线。 */
body [data-skeleton-action][data-skeleton-action]:disabled{background:var(--surface);border-color:transparent;box-shadow:0 0 0 1px var(--border-15);color:var(--muted);cursor:not-allowed;opacity:1}
body [data-skeleton-action][data-skeleton-action]:disabled::before{display:none}
body [data-split-button]>[data-skeleton-action][data-skeleton-action]:disabled{box-shadow:none}
[data-split-button]:has(>[data-skeleton-action]:disabled){--split-seam:var(--border-15);box-shadow:0 0 0 1px var(--border-15)}
body [data-cleanup-empty][hidden]{display:none}
body .junkactions button:not(.danger){height:36px;border:1px solid var(--color-border-button-default);border-radius:10px;padding:8px 12px;background:var(--color-background-primary-default);color:var(--ink);box-shadow:var(--elevation-xs);font:var(--board-body-medium)}
body [data-follow-bulk],body [data-follow-status=seen],body [data-follow-status=ignored]{background:color-mix(in srgb,var(--color-accent-400) 16%,var(--color-background-primary-default));color:var(--color-accent-600);border-color:transparent}
.reviewcontrols{border:0;border-radius:20px}.batchbar,.tagselection{background:var(--glass-drift-a),var(--glass-drift-b),linear-gradient(125deg,var(--glass-sheen),transparent 42%,var(--glass-low)),var(--glass-fill);background-size:200% 200%,200% 200%,auto;background-repeat:no-repeat,no-repeat,repeat;background-position:50% 20%,80% 70%,0 0;animation:glassdriftx calc(41s * var(--glow-drift-scale)) linear infinite,glassdrifty calc(67s * var(--glow-drift-scale)) linear infinite;animation-play-state:var(--glow-drift-play);backdrop-filter:var(--glass-optic,blur(22px)) saturate(145%);border:0;box-shadow:inset 0 1px 0 var(--glass-rim),var(--glass-shadow);border-radius:20px}
.reviewtabs{overflow-x:auto!important;overflow-y:hidden;scrollbar-width:none!important;touch-action:pan-x pan-y;overscroll-behavior-x:contain}.reviewtabs::-webkit-scrollbar{display:none!important}.reviewtabs .os-scrollbar{display:none!important}
.settingsscroll .settingrow{margin-right:16px}.settingsscroll .settinggroup{border-bottom:0}
.iconswitch.themeswitch[data-board-segments]{padding:4px;border:0;border-radius:24px;background:var(--picked);gap:4px}.iconswitch.themeswitch[data-board-segments]>label{width:32px;height:32px;border-radius:50%}.themeswitch .board-segment-thumb{border-radius:50%;background:var(--ground)}
.card .pic>.badge{padding:4px;border-radius:10px;background:var(--glass-fill);box-shadow:inset 0 1px 0 var(--glass-rim),var(--glass-shadow);backdrop-filter:blur(16px) saturate(145%)}.card .pic>.badge .src{background:transparent;padding:0;width:20px;height:20px}
body .selectiondock{border:0;border-radius:22px;background:var(--glass-drift-a),var(--glass-drift-b),linear-gradient(125deg,var(--glass-sheen),transparent 42%,var(--glass-low)),var(--glass-fill);background-size:200% 200%,200% 200%,auto;background-repeat:no-repeat,no-repeat,repeat;background-position:50% 20%,80% 70%,0 0;animation:glassdriftx calc(41s * var(--glow-drift-scale)) linear infinite,glassdrifty calc(67s * var(--glow-drift-scale)) linear infinite;animation-play-state:var(--glow-drift-play);backdrop-filter:var(--glass-optic,blur(22px)) saturate(145%);box-shadow:inset 0 1px 0 var(--glass-rim),inset 1px 0 0 var(--glass-low),inset -1px 0 0 var(--glass-low),inset 0 -1px 0 var(--glass-low),var(--glass-shadow)}
/* 玻璃面这一层料只有一份：漂移的两团、那道斜光、底色、内嵌的四条边和落影。认 `data-glass-pane`
   的元素全都拿它，各块自己只留几何、`backdrop-filter` 的饱和度和文字色——那三样本来就一块一个数。
   高对比与 `prefers-reduced-transparency` 的回退在下面同一个属性选择器上，不必各自再写一遍。 */
[data-glass-pane]{border:0;background:var(--glass-drift-a),var(--glass-drift-b),linear-gradient(125deg,var(--glass-sheen),transparent 42%,var(--glass-low)),var(--glass-fill);background-size:200% 200%,200% 200%,auto;background-repeat:no-repeat,no-repeat,repeat;background-position:50% 20%,80% 70%,0 0;animation:glassdriftx calc(41s * var(--glow-drift-scale)) linear infinite,glassdrifty calc(67s * var(--glow-drift-scale)) linear infinite;animation-play-state:var(--glow-drift-play);box-shadow:inset 0 1px 0 var(--glass-rim),inset 1px 0 0 var(--glass-low),inset -1px 0 0 var(--glass-low),inset 0 -1px 0 var(--glass-low),var(--glass-shadow)}
/* React 产物会按构建目标把标准属性折成 `-webkit-backdrop-filter`，当前 Chromium 不认后者。
   标准属性留在不经转换的共享样式表里，数值逐项对齐首页上下两块玻璃。 */
body .peach-react [data-review-filter]{backdrop-filter:var(--glass-optic,blur(22px)) saturate(160%) var(--glass-lume)}
body .peach-react [data-selection-dock]{backdrop-filter:var(--glass-optic,blur(22px)) saturate(145%)}
html.board-high-contrast :is(.selectiondock,.batchbar,.tagselection,.card .badge,[data-glass-pane]){background:var(--ground);backdrop-filter:none;-webkit-backdrop-filter:none;animation:none}
@media(prefers-reduced-transparency:reduce){body :is(.selectiondock,.batchbar,.tagselection,.card .badge,[data-glass-pane]){background:var(--ground);backdrop-filter:none;animation:none}}
@media(prefers-reduced-motion:reduce){body :is(.selectiondock,.batchbar,.tagselection){animation:none}}

/* ── 分段控件（boardui segmented-control.tsx）：口味页的证据切换与工具栏的版式切换同一枚滑块 ──
   轨道 tertiary 底、4px 内边距、10px 圆角、2px 间隔；选项 px 10 / py 4、6px 圆角；选中 Body Medium 主文字色，
   未选 Body Regular 次文字色，悬停只提字色。暗色里 tertiary 与 primary 同值（#262626），滑块得比轨道亮一档
   才看得见；上游 `segmented-control-selected` 的暗色值未取得，这里取主文字色 14% 混进轨道色。 */
.insightswitch[data-board-segments]{position:relative;display:inline-flex;align-items:center;gap:2px;padding:4px;border:0;border-radius:10px;background:var(--color-background-tertiary-default);box-shadow:none}
.insightswitch[data-board-segments] label{position:relative;z-index:1}
.insightswitch[data-board-segments] label>span{display:flex;align-items:center;min-height:28px;height:auto;padding:4px 10px;border-radius:6px;background:transparent;box-shadow:none;color:var(--color-text-secondary);font:var(--board-body);transition:color .2s ease}
.insightswitch[data-board-segments] label:hover>span{color:var(--color-text-primary)}
.insightswitch[data-board-segments] label:has(input:checked)>span{background:transparent;box-shadow:none;color:var(--color-text-primary);font:var(--board-body-medium)}
:root[data-theme="dark"] :is(.iconswitch:not(.themeswitch),.insightswitch,.follow-workspace-switch)>:is(.board-segment-thumb,.skeleton-segment-selected){background:color-mix(in srgb,var(--color-text-primary) 14%,var(--color-background-tertiary-default));box-shadow:0 1px 2px #00000040}
@media(prefers-color-scheme:dark){:root:not([data-theme]) :is(.iconswitch:not(.themeswitch),.insightswitch,.follow-workspace-switch)>:is(.board-segment-thumb,.skeleton-segment-selected){background:color-mix(in srgb,var(--color-text-primary) 14%,var(--color-background-tertiary-default));box-shadow:0 1px 2px #00000040}}
/* 浮层上的分段器（版式、大小这类）跟同一排的圆键、药丸和「仅显示图片」那枚开关一样高
   （30px），滑块就是整枚选项：轨道不留内边距，选项 30px 见方、图标 16px，圆角跟那块滑动
   玻璃同一个 8px。轨道留 3px 的话滑块比旁边那块玻璃矮一圈、圆角也小一档，同一块料在
   同一排里出现两种尺寸。筛选行与排序行上下留白都是 8px，排序滚动容器不再自己多垫。 */
.board-filter-frame.board-filter-frame .iconswitch[data-board-segments],
.entitytagbar.entitytagbar .iconswitch[data-board-segments],
.entitycollectionhead.entitycollectionhead .iconswitch[data-board-segments]{padding:0;border-radius:8px;gap:2px}
.board-filter-frame.board-filter-frame .iconswitch[data-board-segments]>label,
.entitytagbar.entitytagbar .iconswitch[data-board-segments]>label,
.entitycollectionhead.entitycollectionhead .iconswitch[data-board-segments]>label{height:30px;min-height:30px;width:30px;padding:0;border-radius:8px}
.board-filter-frame.board-filter-frame .iconswitch[data-board-segments] svg,
.entitytagbar.entitytagbar .iconswitch[data-board-segments] svg,
.entitycollectionhead.entitycollectionhead .iconswitch[data-board-segments] svg{width:16px;height:16px}
.board-filter-frame.board-filter-frame .iconswitch[data-board-segments]>.board-segment-thumb,
.entitytagbar.entitytagbar .iconswitch[data-board-segments]>.board-segment-thumb,
.entitycollectionhead.entitycollectionhead .iconswitch[data-board-segments]>.board-segment-thumb{border-radius:8px}
/* 这一组是横滚容器，会把里面东西的落影从上下两边裁掉——版式分段器的滑块和「仅显示图片」
   那块玻璃最远那层影落在 14px 外，贴着容器边就只剩一条平切的底。上下各留出这 14px 再
   用负外边距收回，排在行里还是 30px 高，影和聚焦环都露得出来。 */
.count .sorts,.entitycollectionhead .sorts{padding:14px 2px;margin-block:-14px}
/* 浮层上的滑块。深色那两条按主题给的填充和影写在上面，特指度到 0-5-0，所以这里也得
   数够——`[data-board-segments]` 那一节的几何照旧，换掉的只有材质。 */
.entitytagbar.entitytagbar.entitytagbar .iconswitch[data-board-segments]>.board-segment-thumb,
.entitycollectionhead.entitycollectionhead.entitycollectionhead .iconswitch[data-board-segments]>.board-segment-thumb,
.board-filter-frame.board-filter-frame.board-filter-frame .iconswitch[data-board-segments]>.board-segment-thumb{
  background:linear-gradient(180deg,var(--glass-sheen),transparent 62%),var(--glass-pick-fill);
  backdrop-filter:var(--glass-pick);-webkit-backdrop-filter:var(--glass-pick);
  box-shadow:inset 0 0 0 1px var(--glass-rim),var(--glass-pick-shadow)}
.board-filter-frame #count{min-height:48px}
/* ── 下划线 Tabs（boardui tabs.tsx）：管理导航与设置内的分区同一副样子 ──
   1px 基线、选中 2px 蓝线由 `[data-board-tabs]::before` 滑过去；选项 px 10 / py 8、Body 1、间隔 4px；
   选中蓝字 Medium，未选主文字色 Regular。计数徽标 px 4 / py 1、Caption Medium、4px 圆角：选中蓝底蓝字，未选黑 10% 半透明。 */
/* 复核分类长成次级菜单：底下那一屏是同一份复核队列换了个筛法，十枚下划线并排会
   把它读成十块各不相干的内容。药丸走全站横排互斥那一套——选中只有填充，未选中
   悬停只提文字色。键盘行为仍是 tablist，方向键在同一条里移动焦点。 */
/* 药丸的字要和标题同一条左边，所以整排往外挪掉一枚药丸的内边距——对齐看的是文字，
   不是药丸那块底。 */
/* 这一条跟标题、面包屑和下面那块浮层同一条左边。往外挪 12px 能让第一个标签的字
   顶到那条线上，代价是选中那块底色比整页任何东西都往左出去一截。 */
.reviewtabs{margin-inline:0}
.reviewtabs button{height:32px;padding:0 12px;gap:6px;border-radius:var(--control-radius);color:var(--color-text-secondary);font:var(--board-body)}
.reviewtabs button:hover{background:none;color:var(--color-text-primary)}
/* ── 复核队列的分页条照 Board 的 Pagination（pagination.tsx）：nav 两端对齐、gap 8；上一页／下一页是 32px 的次级小键
   （圆角 8、内边距 6/8）；页码 32×32、圆角 8、Body Medium，当前页借次级键的面（primary 底、border-button 描边、xs 阴影），
   其它页码只有文字，悬停 primary-hover 底；「…」是三级文字色。页码格不做过渡：动了背景和阴影，换页时上一枚当前页会
   肉眼可见地淡出。 ── */
.board-pagination{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;margin-top:16px}
.board-pagination>ul{display:flex;align-items:center;gap:2px;margin:0;padding:0;list-style:none}
body .followmanage .board-pagination>.geist-button{height:32px;min-height:32px;padding:6px 8px;border-radius:8px}
.board-pagination>.geist-button svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.board-page,.board-page-dots{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;margin:0;padding:0;border:0;border-radius:8px;background:none;color:var(--color-text-secondary);font:var(--board-body-medium);font-variant-numeric:tabular-nums}
.board-page{cursor:pointer;transition:none}
.board-page:hover{background:var(--color-background-primary-hover);color:var(--color-text-primary)}
.board-page[aria-current="page"]{border:1px solid var(--color-border-button-default);background:var(--color-background-primary-default);color:var(--color-text-primary);box-shadow:var(--elevation-xs)}
.board-page-dots{color:var(--color-text-tertiary)}
/* ── 口味页三个面板的标题同一档：Heading 20/26、上 24 左 24 下 12 ── */
.insightpanel>header:not(:has([role="tablist"])){display:block;min-height:0;padding:24px 24px 12px}
.insightpanel>header h3,.insightcopy>span{margin:0;font:var(--board-heading);color:var(--color-text-primary)}
.insightcopy{padding:24px;gap:0}
/* ── 侧栏收起键（boardui sidebar.tsx）：36px、10px 圆角、次级图标色，悬停与导航项同一层底；收起时与品牌相隔 10px ── */
.drawer .board-sidebar-head #filterBtn{border-radius:0;color:var(--color-text-secondary);transition:color .15s ease}
.drawer .board-sidebar-head #filterBtn:hover{background:var(--color-background-primary-hover);color:var(--color-text-primary)}
@media(min-width:761px){.drawer:not(.open) .board-sidebar-head{gap:10px}}
/* ── 详情页：门挡（脱盘、在线、拉流）铺满播放器格，不再上下留黑；播放器格只圆左上角——右边贴着侧栏，下面接着「接着看」 ── */
.stage .vwrap{border-radius:var(--surface-radius) 0 0 0}
.stage .vwrap>.gate{height:100%;aspect-ratio:auto;border-radius:inherit}
.stage.theater-mode .vwrap{border-radius:var(--surface-radius) var(--surface-radius) 0 0}
@media(max-width:1080px){.stage .vwrap{border-radius:var(--surface-radius) var(--surface-radius) 0 0}}
/* ── 没有图的身份头像（boardui avatar.tsx 的 initials 盘）：主文字色 10% 混底、次文字色首字，不与卡片底同色 ── */
.idface:not(:has(img)){background:color-mix(in srgb,var(--color-text-primary) 10%,var(--color-background-primary-default));color:var(--color-text-secondary)}
/* ── 首页顶部两排。女优是竖排人像格：48px 圆头像在上、名字（Caption）在下，格宽 76、圆角 12——Board 的 Avatar 只到
   lg 36px（avatar.tsx），竖排格无对应，48 取的是它 `size-12` 那一级；厂牌是 40px 的灰 Pill（pill-tab.tsx gray 放大一档）：
   28px 圆标识在左、名字在右。两排都不描边、悬停 primary-hover、选中 tertiary 底主文字色；标签那一排是 30px 的描边药丸，
   厂牌靠更高的身量、圆标识和无边框跟它分开。 ── */
#tiers .tier{gap:4px;padding:0 16px 6px;align-items:center}
#tiers .tier:last-child{padding-bottom:4px}
/* 往右翻的时候这几排从侧栏底下穿过去，不在侧栏那条边上被切平：侧栏是一块玻璃，底下
   有东西在走才看得出它是透的，一整屏都在那条边上齐刷刷停住的话，那块玻璃身后永远是
   同一片空底。左边界仍停在原处——那是这一屏的左对齐线，跟着一起挪等于把整页的对齐线
   也挪了，所以让出去多少宽度就原样加回内边距，滚到头时第一枚还站在原位。窄屏那一档
   的抽屉是盖上来的，没有这条常驻的边，让出去的宽度只会把内容推到屏幕外，所以整段只
   在留了轨道宽度的档位上开。 */
@media(min-width:761px){
  #tiers .tier{margin-left:calc(-1 * var(--railW));padding-left:calc(var(--railW) + 16px)}
  /* 竖屏那一条是块有底的面板，跟着一起铺过去：只让里面那一排越界的话，卡片滑到面板左
     边缘就从自己的底上掉出来，接缝是一条直上直下的硬边。面板铺到视口边上，左边那两个
     圆角也就没有存在的理由了。 */
  .shorts-inline{margin-left:calc(-1 * (var(--railW) + 16px));padding-left:calc(var(--railW) + 32px);
    border-radius:0 var(--floating-radius) var(--floating-radius) 0}
  .shorts-inline .srow{margin-left:calc(-1 * (var(--railW) + 32px));padding-left:calc(var(--railW) + 32px)}
}
/* 关注页顶上那两排跟首页这两排是同一个控件，所以规则一份写全：那边是「谁出的」加
   「哪个厂牌」，这边是「谁发的」加「哪部作品」，人在两页看到的该是同一种东西。它们
   住在 `#stats` 里而不是 `#tiers` 里，只按 id 写的话关注页拿不到这一整套，落回 flat
   层那份 64px 头像加一圈描边，同一个人在两页大小和选中样子都不一样。人物页资料卡底
   那排同台艺人也是这一枚女优头像，同一套规则：悬停抬整格底色，不在圆上描圈。 */
#tiers .av,#tiers .brandpill,
:is(.followauthors,.followworks,.relatedpeople) .av,:is(.followauthors,.followworks) .brandpill{flex:none;border:0;background:transparent;color:var(--color-text-secondary);font:var(--board-body-medium);white-space:nowrap;transition:transform var(--lift-motion,var(--board-motion)),scale calc(var(--spring-press-ms) * 1ms) var(--spring-press),background-color .2s ease-out,color .2s ease-out}
#tiers .av:active,#tiers .brandpill:active,
:is(.followauthors,.followworks,.relatedpeople) .av:active,:is(.followauthors,.followworks) .brandpill:active{scale:.96;transition:scale .06s ease-out}
#tiers .av,:is(.followauthors,.followworks,.relatedpeople) .av{display:flex;flex-direction:column;align-items:center;gap:6px;width:76px;max-width:none;height:auto;padding:6px 4px;border-radius:12px;text-align:center}
#tiers .brandpill,:is(.followauthors,.followworks) .brandpill{display:inline-flex;align-items:center;gap:8px;width:auto;max-width:none;height:40px;padding:6px 12px 6px 6px;border-radius:12px;text-align:left}
#tiers .av:hover,#tiers .brandpill:hover,
:is(.followauthors,.followworks,.relatedpeople) .av:hover,:is(.followauthors,.followworks) .brandpill:hover{background:var(--color-background-primary-hover);color:var(--color-text-primary);border-color:transparent}
#tiers .av[aria-pressed="true"],#tiers .brandpill[aria-pressed="true"],
:is(.followauthors,.followworks,.relatedpeople) .av[aria-pressed="true"],:is(.followauthors,.followworks) .brandpill[aria-pressed="true"]{background:var(--color-background-tertiary-default);color:var(--color-text-primary);border-color:transparent}
#tiers .av .ring,#tiers .brandpill .mk,
:is(.followauthors,.followworks,.relatedpeople) .av .ring,:is(.followauthors,.followworks) .brandpill .mk{position:relative;flex:none;margin:0;border-radius:50%;overflow:hidden;background:color-mix(in srgb,var(--color-text-primary) 10%,var(--color-background-primary-default));color:var(--color-text-secondary)}
#tiers .av .ring,:is(.followauthors,.followworks,.relatedpeople) .av .ring{width:48px;height:48px;font:600 18px/24px var(--board-font)}
#tiers .brandpill .mk,:is(.followauthors,.followworks) .brandpill .mk{width:28px;height:28px;font:600 12px/16px var(--board-font)}
#tiers .av .ring .ini,:is(.followauthors,.followworks,.relatedpeople) .av .ring .ini{font:inherit;color:inherit}
#tiers .av:hover .ring,#tiers .av[aria-pressed="true"] .ring,
:is(.followauthors,.followworks,.relatedpeople) .av:hover .ring,:is(.followauthors,.followworks,.relatedpeople) .av[aria-pressed="true"] .ring{box-shadow:none}
#tiers .av .nm,:is(.followauthors,.followworks,.relatedpeople) .av .nm{display:block;max-width:100%;font:var(--board-caption);color:inherit;text-align:center;overflow:hidden;text-overflow:ellipsis}
/* 关注页的头像是张外站图，自己带着 64px 的身量；圆头像的尺寸归上面那一格，它只负责
   把那一格填满。 */
.followauthors .av .ring .favatar{width:100%;height:100%;border-radius:0;object-fit:cover}
.followauthors .av .ring .favatar.none{display:flex;align-items:center;justify-content:center;background:none;font:inherit;color:inherit}
/* 题材那一枚圆标装的是这个题材下最热的一张作品图，不是烤好边距的厂牌标识：按正中裁
   一个 28px 的圆出来常常只剩一截身子。检出了脸的图由服务端把取景写进 img 自己的
   style，这里这一档只管没检出脸的那些——上四分之一是人像里头最常落的位置。 */
.followworks .brandpill .mk img{object-position:50% 25%}
:is(.followauthors,.followworks,.relatedpeople){gap:4px;align-items:center}
.followworks{padding:0 0 10px;margin:0 0 2px;overscroll-behavior-inline:contain}

/* ── 关注列表整段进框，与「添加关注」同一只卡：头 20/24/8，选择栏与列表左右 24，脚是卡片脚 ──
   作者卡是 primary 面上的一只卡；来源行照 boardui checkbox-card.tsx：10px 圆角、1px border-button-default、
   pl 16 / pr 20 / py 12，悬停 primary-hover 150ms；行距 8px。选中行沿用焦点环色的边（上游 CheckboxCard 只亮勾选框）。 */
.followmanage .board-follow-list{padding:0;background:transparent;gap:16px}
.followmanage .board-follow-list .fsource.frow{min-height:0;margin:0;padding:12px 20px 12px 16px;border:1px solid var(--color-border-button-default);border-radius:10px;background:var(--color-background-primary-default);transition:background-color .15s ease,border-color .15s ease}
.followmanage .board-follow-list .fsource.frow:hover{background:var(--color-background-primary-hover)}
.followmanage .board-follow-list .fsource.selected,.followmanage .board-follow-list .fsource.selected:hover{background:var(--color-background-primary-default);border-color:var(--color-border-focus-ring)}
@media(max-width:760px){.followmanage .fsec>.board-follow-selection{padding:4px 16px 12px}}
/* ── 表格：外框管边线与圆角，里层管横向滚动与两端渐隐。选中行是蓝色 8% 的一层底，不描蓝线（上游选中行样式未取得） ── */
.followmanage .ftable tr.fsource.selected,.followmanage .ftable tr.fsource.selected:hover{background:color-mix(in srgb,var(--tungsten) 8%,var(--color-background-primary-default));border-color:var(--color-separator-border);box-shadow:none}
.followmanage .ftable tbody tr{transition:background-color .15s ease}
.followmanage .ftable tbody tr:last-child{border-bottom:0}
/* ── 分区标题行里的视图开关与同排按钮同高（36px）：轨道 3px、选项 30px，图标 16px、1.8 描边与 fbtn 的字形同粗 ── */
.followmanage .fsechead .iconswitch[data-board-segments]{padding:3px;border-radius:10px;gap:2px}
.followmanage .fsechead .iconswitch[data-board-segments]>label{width:34px;height:30px;border-radius:7px}
.followmanage .fsechead .iconswitch[data-board-segments]>.board-segment-thumb{border-radius:7px}
.followmanage .fsechead .iconswitch svg{width:16px;height:16px;stroke-width:2}
/* ── 勾选框（boardui checkbox-glyph.tsx）：未选 1px border-checkbox-default 加 shadow-xs，悬停边线深一档、底不变；
   选中蓝渐变 + 内嵌高光；勾 2px 圆头，200ms cubic-bezier(.65,0,.35,1) 从零画出。tokens：亮 neutral-300／400，暗 neutral-600／500。
   暗档的默认边线比上游 theme.css 的 neutral-700 亮一档：这颗框的底就是卡面色，形状全靠那 1px 说话，
   而 #404040 压在 #262626 上只差 11 个 CIE 明度（浅色那对是 15），细线在低亮度那头当场消失。 ── */
:root,:root[data-theme="light"]{--color-border-checkbox-default:#d4d4d4;--color-border-checkbox-hover:#a3a3a3}
:root[data-theme="dark"]{--color-border-checkbox-default:#525252;--color-border-checkbox-hover:#737373}
@media(prefers-color-scheme:dark){:root:not([data-theme]){--color-border-checkbox-default:#525252;--color-border-checkbox-hover:#737373}}
.pcheck>span{border-color:var(--color-border-checkbox-default);box-shadow:var(--elevation-xs);transition:background-color .15s ease,border-color .15s ease,box-shadow .15s ease}
.pcheck:hover>span,label:hover>.pcheck>span{border-color:var(--color-border-checkbox-hover);background:var(--color-background-primary-default)}
.pcheck input:is(:checked,:indeterminate)+span{border-color:transparent;background:var(--board-blue);box-shadow:inset 0 2px 0 0 #ffffff40,inset 0 0 0 1px #3b82f6}
.pcheck:hover input:is(:checked,:indeterminate)+span,label:hover>.pcheck input:is(:checked,:indeterminate)+span{border-color:transparent;background:linear-gradient(180deg,#60a5fa,#3b82f6);box-shadow:inset 0 2px 0 0 #ffffff40,inset 0 0 0 1px #3b82f6}
.pcheck>span svg{stroke-dasharray:23;stroke-dashoffset:0}
@keyframes board-check-draw{from{stroke-dashoffset:23px}to{stroke-dashoffset:0}}
.pcheck input:checked+span svg{animation:board-check-draw .2s cubic-bezier(.65,0,.35,1) forwards}
@media(prefers-reduced-motion:reduce){.pcheck input:checked+span svg{animation:none;stroke-dashoffset:0}}

/* 安装后教程：BoardUI NotificationViewport 把教程固定在右下角，内部任务沿用 RareUI
   Task List 的真实状态、完成项后移与打勾，不占当前页面正文的布局空间。
   右下角还住着 Toast 栈和窄屏居中的批量选择条。教程贴着角落放，不为它们留白：层级
   100 压在批量条（180）与 Toast（`--layer-popover`）之下，重叠时它们盖在教程上面。
   Toast 几秒就消失，批量条只在选中时出现，为它们常年空出一截反倒让教程悬在半空。 */
#postSetupTutorial{position:fixed;right:12px;bottom:12px;z-index:100;display:block;width:min(400px,calc(100vw - 24px));max-height:calc(100dvh - 24px);pointer-events:none}
#postSetupTutorial[hidden]{display:none}
.post-setup-notification{pointer-events:auto;display:flex;flex-direction:column;max-height:inherit;overflow:hidden;border:1px solid var(--color-border-button-default);border-radius:16px;background:var(--color-background-primary-default);box-shadow:0 1px 1px light-dark(#0000000d,#00000099),0 4px 4px light-dark(#0000001a,#00000073);animation:post-setup-notification-in .15s ease-out}
.post-setup-notification-head{display:grid;grid-template-columns:40px minmax(0,1fr) 32px;align-items:center;gap:12px;padding:16px}
.post-setup-notification-icon{display:grid;place-items:center;width:40px;height:40px;border-radius:50%;background:var(--color-notification-information-background);color:var(--color-notification-information-foreground)}
.post-setup-notification-icon>svg,.post-setup-error>svg,.post-setup-loading>svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:2}
.post-setup-notification h2{margin:0;color:var(--color-text-primary);font:var(--board-body-medium)}
.post-setup-notification p{margin:4px 0 0;color:var(--color-text-secondary);font:var(--board-body-2-regular)}
.post-setup-collapse{display:grid;place-items:center;width:32px;height:32px;margin:0 -4px 0 0;padding:0;border:0;border-radius:8px;background:transparent;color:var(--color-text-secondary)}
.post-setup-collapse:hover{background:var(--color-background-primary-hover);color:var(--color-text-primary)}
.post-setup-collapse>svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2}
.post-setup-notification[data-collapsed=true]>.post-setup-task-list,.post-setup-notification[data-collapsed=true]>footer{display:none}
.post-setup-task-list{display:grid;gap:0;min-height:0;margin:0;padding:4px;border-block:1px solid var(--color-border-button-default);overflow-y:auto;list-style:none}
.post-setup-task{position:relative;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center}
.post-setup-task+.post-setup-task::before{content:"";position:absolute;inset:0 12px auto;height:1px;background:var(--color-border-button-default);pointer-events:none}
.post-setup-task:has(>a:hover)::before,.post-setup-task:has(>a:hover)+.post-setup-task::before{opacity:0}
.post-setup-task>a{position:relative;display:grid;grid-template-columns:24px minmax(0,1fr) 16px;align-items:center;gap:12px;min-width:0;min-height:62px;padding:10px 8px 10px 12px;border-radius:8px;color:var(--ink);text-decoration:none}
.post-setup-task>a:hover{background:var(--hover)}
.post-setup-task>a>svg{width:16px;height:16px;color:var(--color-text-secondary);fill:none;stroke:currentColor;stroke-width:2}
.post-setup-task>a:hover>svg{color:var(--color-text-primary)}
.post-setup-skip{position:relative;margin-right:8px;padding:6px 8px;border:0;border-radius:var(--control-radius);background:transparent;color:var(--color-text-secondary);font:var(--board-body-2-regular);transition:background-color .15s ease,color .15s ease}
.post-setup-skip:hover{background:var(--color-background-primary-hover);color:var(--color-text-primary)}
.post-setup-check{display:grid;place-items:center;width:24px;height:24px;border:1px solid var(--line);border-radius:50%;color:var(--muted)}
.post-setup-check svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2}
.post-setup-task b,.post-setup-task small{display:block}
.post-setup-task b{font:var(--board-body-medium)}
.post-setup-task small{margin-top:2px;color:var(--muted);font:var(--board-body-2-regular)}
.post-setup-task[data-state=checked] .post-setup-check{border-color:var(--color-accent-500);background:var(--color-accent-500);color:#fff}
.post-setup-task[data-state=checked] b{text-decoration:line-through;color:var(--muted)}
.post-setup-task[data-state=checked]>a{opacity:.72}
.post-setup-notification>footer{padding:12px}
.post-setup-notification>footer>.geist-button{width:100%}
.post-setup-loading{display:flex;flex-direction:row;align-items:center;gap:10px;min-height:54px;padding:16px}
.post-setup-loading p{margin:0}
.post-setup-error{display:grid;grid-template-columns:20px minmax(0,1fr);gap:8px;padding:16px}
.post-setup-error-actions{display:flex;gap:8px;margin-top:12px}
@keyframes post-setup-notification-in{from{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:none}}
@media(min-width:640px){#postSetupTutorial{right:24px;bottom:24px;max-height:calc(100dvh - 48px)}}
@media(max-width:720px){.post-setup-task>a{min-height:58px;padding-left:10px}}
@media(prefers-reduced-motion:reduce){.post-setup-notification{animation:none}.post-setup-task,.post-setup-task>a{transition:none}}
/* ── Board 第三批：主按钮尺寸、配置页白底、通知与提醒、批量条、关注行图标、侧栏切换器 ── */
/* 主按钮与旁边的 Board 按钮同一副盒子：36px、10px 圆角、Body Medium。 */
body :is(.geist-button,.fbtn,.resourceaction,.tagselection button,.geist-fieldset-footer>a,.geist-fieldset-footer>button).primary{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;gap:4px;height:36px;min-height:36px;padding:8px 12px;border-radius:10px;font:var(--board-body-medium);white-space:nowrap}
/* 提醒条与上下内容留 12px：关注页检查结果、扫描卡失败都是同一个 Note。 */
body .followmanage .fwarn{margin:0 0 12px}
body .library-processing [role=alert]>.geist-note{margin-top:12px}
/* 复核页的骨架与别的管理页同宽；分类那一列不悬浮，它是左右分栏里固定的一栏。 */
body .review{width:100%;max-width:var(--board-content);margin:0 auto;box-sizing:border-box}
body .review .reviewcontrols{position:static;z-index:auto;padding-block:0;display:block;border-radius:0}

/* 数据管理子页：结果标题、证据区域和操作栏各有固定归属。 */
.collection-summary{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;padding:20px 24px;margin-bottom:20px;border-radius:var(--surface-radius);background:var(--color-background-primary-default)}
.collection-summary>div{display:grid;gap:8px;min-width:0}
.collection-summary span{font:var(--board-body);color:var(--color-text-secondary)}
.collection-summary strong{font:var(--board-title);color:var(--color-text-primary);font-variant-numeric:tabular-nums}
.collection-summary p{margin:0;color:var(--color-text-secondary);font:var(--board-body)}
/* 浅色下 primary 就是页面底色，这块不描边的面于是整个消失，读起来是数字直接落在页面上。
   深色下 primary 比页面亮一档，本来就分得开——跟重复文件那两块面同一条判据。 */
html:not(.dark) .collection-summary{background:var(--color-background-secondary-default)}
/* 数字回来前占它的位置：跟着 --board-title 的 32px 走，行高 44px 容得下，数字到货不改行高。 */
.collection-summary strong .countskeleton{width:96px;height:32px}
body[data-surface="/review"] .review-workspace{display:grid;grid-template-columns:minmax(0,1fr) 184px;column-gap:24px;align-items:start}
body[data-surface="/review"] .review-workspace>.reviewcontrols{grid-column:2;grid-row:1 / span 4;position:sticky;top:var(--topH);padding:16px 8px;background:var(--color-background-primary-default);border-radius:var(--surface-radius)}
body[data-surface="/review"] .review-category-title{font:var(--board-caption);color:var(--muted);margin:0 12px 12px}
body[data-surface="/review"] .reviewtabs{display:flex;flex-direction:column;gap:4px;align-items:stretch;white-space:normal}
body[data-surface="/review"] .reviewtabs button{height:auto;min-height:40px;text-align:left;justify-content:space-between;padding:10px 12px;white-space:normal}
body[data-surface="/review"] .review-workspace>:is(.reviewsection,.reviewbulktoolbar){grid-column:1;min-width:0}
body[data-surface="/review"] .reviewlist{grid-template-columns:repeat(auto-fill,minmax(min(100%,340px),1fr));gap:20px}
/* 卡片是一块填充的面：底色、圆角和那层极浅的投影都跟到货的卡逐字对上。占位和到货
   差一档底色或圆角，读完数据整片网格会跳一下。 */
.review-skeleton .skeletoncard{border:0;border-radius:16px;background:var(--color-background-secondary-default);box-shadow:0 1px 2px #00000008}
/* 工具条到货之后是一条普通的横条，骨架也就不糊一层玻璃：占位比到货多一层背景的话，
   数据回来那一刻这条会自己褪色。它也不吸顶——粘住一块空壳只是把顶栏下面糊上一层。 */
body .review-skeleton .reviewbulktoolbar{position:static;border-radius:16px;margin-bottom:20px;
  padding:8px 12px;background:var(--color-background-full)}
body[data-surface="/duplicates"] #manageLede{display:none}
/* 「批量保留」就是首页那块悬浮筛选框：外层 `.board-filter-frame` 拿玻璃料、吸顶、`backdrop-filter`
   与 `board-is-stuck` 的抬影，这一排只是它的一格 `[data-filter-row]`。`[data-glass-pane]` 那份料
   不带 `backdrop-filter`，套上去身后的字一个不糊地透出来。里面的键沿用筛选框胶囊的形态：30px 高、
   13px 字、一圈 `--glass-low` 发丝边、不铺填充——flat 面那种实底键摆到玻璃上是整条里唯一一块
   不透光的东西。 */
body[data-surface="/duplicates"] .dupactions{margin:0;padding:10px 16px;flex-wrap:wrap;gap:8px 10px;color:var(--glass-text)}
body[data-surface="/duplicates"] .dupactions h3{margin:0 4px 0 0;font:var(--board-body-medium);color:inherit}
body[data-surface="/duplicates"] .dupactions button{height:30px;padding:0 12px;border:1px solid var(--glass-low);border-radius:var(--pill-radius);background:transparent;color:var(--glass-text);font-size:13px;line-height:1;white-space:nowrap;cursor:pointer}
body[data-surface="/duplicates"] .dupactions button:hover{border-color:var(--glass-rim);background:var(--glass-pick-fill)}
body[data-surface="/duplicates"] .dupactions button[aria-busy="true"]{color:color-mix(in srgb,var(--glass-text) 55%,transparent);cursor:wait}
/* 每组一张卡，头部比正文深一档，两块面自己就分得开，不靠一条细线。深色下正文 primary、头部
   secondary 本来就是这样；浅色下 primary 与页面同是白的，正文于是跟数据管理、复核那几张卡一样
   落到 secondary，头部再深一档取 tertiary。 */
body[data-surface="/duplicates"] .dupgroup{margin-bottom:24px;border-color:var(--line-soft);background:var(--color-background-primary-default)}
body[data-surface="/duplicates"] .duphead{padding:20px;gap:12px;background:var(--color-background-secondary-default)}
html:not(.dark) body[data-surface="/duplicates"] .dupgroup{background:var(--color-background-secondary-default)}
html:not(.dark) body[data-surface="/duplicates"] .duphead{background:var(--color-background-tertiary-default)}
body[data-surface="/duplicates"] .duphead>b{font:var(--board-heading)}
body[data-surface="/duplicates"] .duphead .dupbtns{flex-wrap:wrap;gap:8px}
body[data-surface="/duplicates"] .duprow{grid-template-columns:112px minmax(0,1fr) 84px 84px 84px;padding:16px 20px;gap:12px}
.dupcover{grid-row:span 2;position:relative;aspect-ratio:16/10;padding:0;overflow:hidden;border:0;border-radius:var(--control-radius);background:var(--color-background-tertiary-default);color:var(--muted);cursor:pointer;display:grid;place-items:center}
.dupcover img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain}
.dupcover svg{width:24px;height:24px}
body[data-surface="/duplicates"] .duppath{grid-column:2/-1}
.quality-workspace{max-width:var(--board-content);margin:auto}
body[data-surface="/quality-goals"] .qualitylist{grid-template-columns:repeat(auto-fill,minmax(min(100%,280px),1fr));gap:20px}
body[data-surface="/quality-goals"] .qualityitem{display:grid;grid-template-columns:150px minmax(0,1fr);grid-template-rows:1fr auto;gap:0 16px;padding:12px;overflow:hidden;border:1px solid var(--line-soft);border-radius:var(--surface-radius)}
body[data-surface="/quality-goals"] .qualitycover{position:relative;display:grid;place-items:center;grid-row:1 / span 2;width:150px;aspect-ratio:16/10;border-radius:var(--control-radius);background:var(--color-background-tertiary-default)}
.qualitybody{padding:4px 4px 0;min-width:0}
.qualityactions{display:flex;justify-content:flex-end;padding:8px 4px 0;background:transparent}
/* 垃圾文件的计数行装着两块整宽的面：上面是「待判断 N 个」那块摘要，下面是分类切换。
   这一行仍按目录页的横排走的话，`width:100%` 的摘要把后面那条挤到 0 宽，而它自己
   `min-width:0` 又带横向滚动，于是宽屏上分类切换整条看不见，只剩一块摘要贴着网格。 */
body[data-surface="/junk-files"] #count{flex-direction:column;align-items:stretch;gap:16px;padding-inline:0}
body[data-surface="/junk-files"] .junksummary{width:100%}
body[data-surface="/junk-files"] .collection-summary{margin:0}
body[data-surface="/junk-files"] .junkfilters{width:100%;padding:12px;gap:8px;border-radius:var(--surface-radius);background:var(--color-background-primary-default)}
/* 它是数据管理的子页：摘要、分类条、网格和加载哨兵跟标题、面包屑、区块切换条同宽。
   只有网格那一支铺满内容区时，宽屏上标题居中缩在中间、卡片顶着两边，同一页有两条
   对不上的左边界。 */
body[data-surface="/junk-files"] :is(#count,#grid,#loadSentinel){width:100%;max-width:var(--board-content);margin-inline:auto}
body:is([data-surface="/junk-files"],[data-surface="/trash"]) .gridstack>.grid{grid-template-columns:repeat(auto-fill,minmax(min(100%,280px),1fr));gap:20px}
body:is([data-surface="/junk-files"],[data-surface="/trash"]) .gridstack .card{border:1px solid var(--line-soft);border-radius:var(--surface-radius);background:var(--color-background-primary-default);overflow:hidden;gap:0}
body[data-surface="/trash"] .gridstack .card .pic{border-radius:0}
body[data-surface="/trash"] .gridstack .card>.meta{padding:16px 20px}
body[data-surface="/trash"] #manageLede{padding:20px 24px;background:var(--color-background-primary-default);border-radius:var(--surface-radius);gap:16px;flex-wrap:wrap}
body[data-surface="/trash"] #manageLede>span{font:var(--board-heading)}
html:not(.dark) body[data-surface="/junk-files"] .junkfilters{background:var(--color-background-secondary-default)}
body[data-surface="/junk-files"] .junkmeta{padding:20px}
body[data-surface="/junk-files"] .junkactions{padding:12px;background:var(--color-background-secondary-default);flex-wrap:wrap}
@media(max-width:900px){
 body[data-surface="/review"] .review-workspace{grid-template-columns:1fr}
 body[data-surface="/review"] .review-workspace>.reviewcontrols{position:static;grid-column:1;grid-row:auto!important;margin-bottom:16px}
 body[data-surface="/review"] .reviewtabs{flex-direction:row;flex-wrap:wrap}
 body[data-surface="/review"] .review-workspace>:is(.reviewsection,.reviewbulktoolbar){grid-column:1}
 body[data-surface="/duplicates"] .duprow{grid-template-columns:88px minmax(0,1fr) auto auto}
 body[data-surface="/duplicates"] .dupcover{grid-row:span 2}
 body[data-surface="/duplicates"] .duptitle{grid-column:2/-1}
 body[data-surface="/duplicates"] .duppath{grid-column:1/-1}
}
@media(max-width:600px){
 .collection-summary{padding:16px;align-items:flex-start;flex-direction:column;gap:12px}
 body[data-surface="/review"] .reviewtabs button{min-height:36px;padding:8px}
 body[data-surface="/duplicates"] .duphead{padding:16px}
 body[data-surface="/duplicates"] .duphead .dupbtns{margin:0;width:100%}
 body[data-surface="/duplicates"] .duprow{padding:16px}
}
/* 批量条：隐藏的键真的隐藏（Board 的 inline-flex 曾压过 hidden）；「加入回收站」用 error 按钮的红色渐变。 */
/* 批量条上那颗只是不在上面那份尺寸名单里，面色跟站内每一颗危险键同一份。 */
body .batchbar button.danger{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;gap:4px;height:36px;min-height:36px;padding:8px 12px;border-radius:10px;font:var(--board-body-medium)}
body .batchbar button.danger svg{margin-right:0}
body .batchbar button[hidden],body .batchbar button.danger[hidden]{display:none}
/* 侧栏切换器：32px 圆形标识 + 名字 + 双向箭头，悬停在按钮外 5/6px 处描一圈 2px 线；收起键只有 20px 高的图标。 */
.board-sidebar-head #brandHome{position:relative;flex:0 1 auto;max-width:calc(100% - 28px);gap:8px;padding:2px}
.board-sidebar-head #brandHome::before{content:'';position:absolute;inset:-5px -6px;border:2px solid var(--color-border-button-default);border-radius:999px;opacity:0;transition:opacity .15s ease;pointer-events:none}
.board-sidebar-head #brandHome:hover,.board-sidebar-head #brandHome[aria-expanded=true]{background:none;box-shadow:none}
.board-sidebar-head #brandHome:hover::before,.board-sidebar-head #brandHome[aria-expanded=true]::before{opacity:1}
.board-sidebar-head #brandHome .mark{width:32px;height:32px;border-radius:50%;background:var(--color-background-tertiary-default)}
.board-sidebar-head #brandHome .sub{display:none}
.drawer .board-sidebar-head #filterBtn{width:20px;height:20px;padding:0;background:none;box-shadow:none}
.drawer .board-sidebar-head #filterBtn:hover{background:none;color:var(--color-text-primary)}
@media(min-width:761px){.drawer:not(.open) .board-sidebar-head{min-height:0;gap:10px;align-items:center;justify-content:flex-start}.drawer:not(.open) .board-sidebar-head #filterBtn{width:36px;height:20px}.drawer:not(.open) #brandHome{width:32px;height:32px;min-height:32px;padding:0;max-width:none}.drawer:not(.open) #brandHome .mark{width:32px;height:32px}}
/* 详情页的关闭键压在画面上：亮色主题下白底白晕看不出悬停，用户以 YouTube 为参照——播放器上的键在亮色下也是黑底。 */
.closestage,.closestage:hover{background:rgba(0,0,0,.6);color:#fff}
.closestage:hover:after,.closestage:focus-visible:after{background:rgba(255,255,255,.2)}
.closestage:active:after{background:rgba(255,255,255,.3)}

/* 关注工作区：Board Tabs、读数与 Table 的层级，业务分区保留各自表单。 */
.followmanage .fmanageoverview{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px}
/* 关注管理工作区切换属于分段控件一族：4px 内边距、10px 外圆角、tertiary 灰轨道，
   滑块与色变由 wireBoardSegments 的共享驱动负责，200ms 一条缓动。 */
.follow-workspace-switch{position:relative;display:inline-flex;align-items:center;gap:2px;width:max-content;max-width:100%;min-height:0;padding:4px;border:0;border-radius:10px;background:var(--color-background-tertiary-default);overflow:visible}
.follow-workspace-switch button{position:relative;z-index:1;display:inline-flex;flex:none;align-items:center;gap:6px;height:auto;min-height:28px;margin:0;padding:4px 10px;border:0;border-radius:6px;background:none;box-shadow:none;color:var(--color-text-secondary);font:var(--board-body-medium);white-space:nowrap;cursor:pointer;transition:color .2s cubic-bezier(.4,0,.2,1)}
.follow-workspace-switch button:hover{background:none;color:var(--color-text-primary)}
.follow-workspace-switch button[aria-selected=true]{background:none;color:var(--color-text-primary);box-shadow:none}
.followmanage .fmain>[data-follow-workspace-panel][hidden]{display:none}
.fmanageoverview>div{display:grid;gap:12px;padding:20px 24px;background:var(--ground);border-radius:var(--surface-radius);min-width:0}
.fmanageoverview span{font:var(--board-body-medium);color:var(--muted)}
.fmanageoverview b{font:var(--board-figure);font-variant-numeric:tabular-nums}
.fmanageoverview small{font:var(--board-compact);color:var(--muted);white-space:nowrap}
.followmanage .fmanagenav{display:flex;position:relative;gap:16px;overflow-x:auto;margin:4px 0 0;border-bottom:1px solid var(--line-soft);min-width:0}
.fmanagenav>button{display:inline-flex;align-items:center;gap:8px;flex:none;min-height:44px;padding:8px 10px;border:0;background:transparent;color:var(--muted);font:var(--board-body-medium);cursor:pointer}
.fmanagenav>button:hover{color:var(--ink)}
.fmanagenav>button[aria-selected=true]{color:var(--tungsten)}
.fmanagenav>button>span{padding:1px 5px;border-radius:var(--badge-radius);background:var(--picked);color:var(--muted);font:var(--board-caption);font-variant-numeric:tabular-nums}
.followmanage .fmain>[data-follow-panel][hidden]{display:none}
.followmanage .fmain>[data-follow-panel=sources]{background:transparent}
.followmanage .fmain>[data-follow-panel=sources]>.fsechead{padding:0 0 16px;min-height:48px;gap:10px}
.followmanage [data-follow-panel=sources]>.fsechead h3{font:var(--board-body-medium)}
.followmanage .fmain>[data-follow-panel=sources]>.board-follow-selection{padding:12px 16px;background:var(--ground);border-radius:var(--surface-radius) var(--surface-radius) 0 0;border-bottom:1px solid var(--line-soft)}
.followmanage [data-follow-panel=sources] .board-follow-list{gap:0;background:var(--ground);border-radius:0 0 var(--surface-radius) var(--surface-radius);overflow:hidden}
.followmanage [data-follow-panel=sources] .fsource.frow{padding:12px 16px;border:0;border-radius:var(--control-radius);background:transparent}
.followmanage [data-follow-panel=sources] .fsource.frow.selected{background:var(--picked)}
.followmanage [data-follow-panel=sources] .fsource.frow:hover{background:var(--hover)}
.followmanage [data-follow-panel=sources] .fsource.frow.selected:hover{background:var(--picked)}
.followmanage [data-follow-panel=sources] .ftableframe{border-top:0;border-radius:0 0 var(--surface-radius) var(--surface-radius)}
.followmanage .fmain>[data-follow-panel=add]{max-width:812px;width:100%;justify-self:center}
.followmanage .fmain>[data-follow-panel=credentials]>.frows{gap:0;background:var(--ground);border-radius:var(--surface-radius);overflow:hidden}
@media(max-width:760px){
  .followmanage .fmanageoverview{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
  .fmanageoverview>div{padding:16px;gap:8px}
  .followmanage .fmanagenav{gap:4px}
  .fmanagenav>button{padding-inline:8px;gap:6px}
  .followmanage .fmain>[data-follow-panel=sources]>.fsechead{padding:0 0 12px}
  .followmanage [data-follow-panel=sources]>.fsechead h3{flex-basis:100%}
  .followmanage .fmain>[data-follow-panel=sources]>.board-follow-selection{padding:12px}
  .followmanage [data-follow-panel=sources] .fsource.frow{padding:12px 8px}
}

/* 危险区和警告区。形态照 Vercel 的 Error Fieldset（`vercel.com/geist/fieldset`，
   2026-09-12 实测）：红只上框线和底栏那一条，正文那一格仍是普通底色——整卡铺红会把
   「这段要读」和「这个动作要小心」混成一件事，而要小心的只有底栏右边那一颗。
   色阶取 BoardUI 的红：框线和底色就是它的 `--color-border-error-default` 与
   `--color-background-tertiary-error`；底栏那行字 Vercel 取的是 red-900，即「压在这块底上
   还读得动的那一档红」，在 BoardUI 的 100–950 里对应 red-700，暗色一档反过来取 red-300。
   这几条排在最后，是因为上面给卡描边、给底栏铺面的通用规则有五六条，各自带着自己的
   特指度散在前面；挨条去排除它们要改五处，而这一块本来就是「别的都不算数」的意思。 */
[data-geist-fieldset][data-fieldset-type=error]{border:1px solid var(--board-red-line)}
[data-geist-fieldset][data-fieldset-type=warning]{border:1px solid var(--meter)}
[data-fieldset-type=error]>:is(.geist-fieldset-footer,.resourceapplyrow){border-top:1px solid var(--board-red-line);background:var(--board-red-wash)}
[data-fieldset-type=error]>:is(.geist-fieldset-footer,.resourceapplyrow)>p{color:var(--board-red-text)}
[data-fieldset-type=warning]>:is(.geist-fieldset-footer,.resourceapplyrow){border-top:1px solid var(--meter);background:color-mix(in srgb,var(--meter) 7%,var(--ground))}
[data-fieldset-type=warning]>:is(.geist-fieldset-footer,.resourceapplyrow)>p{color:var(--meter)}

.followmanage .board-follow-list .board-author-actions{width:auto;flex:none}
.board-author-actions [data-follow-author-select]>svg{width:16px;height:16px;flex:none}
.followmanage .followcheckall{margin-left:auto}
.followtoolbaractions{display:flex;align-items:center;gap:8px;margin-left:auto;max-width:100%;flex-wrap:nowrap}
.followmanage [data-follow-collapse-all]{flex:none}
.followmanage [data-follow-collapse-all][hidden]{display:none}
.followmanage .board-follow-selection[hidden]{display:none}
.geist-note-details a{color:var(--ink)}
@container(max-width:460px){.board-author-actions [data-author-select-label]{display:none}.followmanage .board-follow-list .board-author-actions [data-follow-author-select]{width:var(--control-h);height:var(--control-h);padding:0;justify-content:center}}
.followmanage .board-follow-list .fsource.frow>b{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.followmanage .board-follow-list .fprovider{flex-wrap:nowrap;white-space:nowrap}
.followmanage .skeleton-icon{width:32px;height:32px;display:block}
.followmanage .fsource .skeleton{max-width:100%}
.followmanage .favatar.skeleton{display:block}
