/* fluent2-controls.css —— WinUI 3 / Fluent 控件几何与状态
   几何数值出处：microsoft-ui-xaml *_themeresources.xaml（raw/ 缓存）与 learn.microsoft.com 设计文档
   规则：颜色只用 --fl-* 变量；圆角只用 --fl-radius-*；字号只用 .fl-* 字阶类；时长/缓动只用 --fl-dur-* / --fl-ease-* */

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { scrollbar-gutter: stable; } /* 内容高度变化时滚动条不再消放 → 不产生横向抖动 */
body {
  font-family: var(--fl-font);
  font-size: var(--fl-font-size-body);
  line-height: 20px;
  background: var(--fl-solid-bg-base); /* Mica 网页近似：纯色基底层 */
  color: var(--fl-text-primary);
}

/* ---- 字阶（Type ramp，learn.../typography；勿手写 font-size） ---- */
.fl-caption          { font-size: var(--fl-font-size-caption);      line-height: var(--fl-line-caption);      font-weight: var(--fl-weight-regular); }
.fl-body             { font-size: var(--fl-font-size-body);         line-height: var(--fl-line-body);         font-weight: var(--fl-weight-regular); }
.fl-body-strong      { font-size: var(--fl-font-size-body);         line-height: var(--fl-line-body);         font-weight: var(--fl-weight-semibold); }
.fl-body-large       { font-size: var(--fl-font-size-body-large);   line-height: var(--fl-line-body-large);   font-weight: var(--fl-weight-regular); }
.fl-body-large-strong{ font-size: var(--fl-font-size-body-large);   line-height: var(--fl-line-body-large);   font-weight: var(--fl-weight-semibold); }
.fl-subtitle         { font-size: var(--fl-font-size-subtitle);     line-height: var(--fl-line-subtitle);     font-weight: var(--fl-weight-semibold); }
.fl-title            { font-size: var(--fl-font-size-title);        line-height: var(--fl-line-title);        font-weight: var(--fl-weight-semibold); }
.fl-title-large      { font-size: var(--fl-font-size-title-large);  line-height: var(--fl-line-title-large);  font-weight: var(--fl-weight-semibold); }
.fl-display          { font-size: var(--fl-font-size-display);      line-height: var(--fl-line-display);      font-weight: var(--fl-weight-semibold); }
.fl-text-secondary   { color: var(--fl-text-secondary); }
.fl-text-tertiary    { color: var(--fl-text-tertiary); }
.fl-text-disabled    { color: var(--fl-text-disabled); }

/* ---- 焦点：官方双描边（inner 1px 贴边 + outer 2px 在外），:focus（非 visible）不画框 ---- */
:focus { outline: none; }
:focus-visible {
  outline: none;
  box-shadow: 0 0 0 var(--fl-stroke) var(--fl-focus-stroke-inner),
              0 0 0 calc(var(--fl-stroke) * 2) var(--fl-focus-stroke-outer);
}

/* ---- 触屏点按：只留 :active，关掉 UA 系统高亮 ----
   -webkit-tap-highlight-color 是**可继承**属性，浏览器默认值 ≈ rgba(0,0,0,.18)
   （Android Chrome 偏蓝）。KIT 从不覆盖它，等于把每个元素的点按都交给 UA 去画，
   在图标、列表行、卡片上就是一块生硬的半透明方框 —— 和 Fluent「按下 = 底色压暗一档」
   完全不是一套语言。写 :root 而不是 *（可继承，一处足够，且要覆盖挂在 body 下的
   弹层/对话框/toast —— 写局部容器会漏掉它们）。只关高亮不够，可点类必须自己有 :active，
   否则按下没反应（校验器 R51 会逐类强制）。 */
:root { -webkit-tap-highlight-color: transparent; }

/* ---- 双层系统：Base（导航/命令）+ Content（卡片内容） ---- */
/* 外壳：整页不滚，只有右侧内容区滚（左导航固定）。
   用 :has() 给"带 .fl-shell 的页面"开启应用外壳模式 —— 没用到 shell 的普通长页面仍然照常整页滚动。
   高度必须一路给到确定值（html/body 100% → shell flex:1 + min-height:0），
   只写 min-height 会让 body 被内容撑高、内层滚动整个失效（这个坑踩过）。 */
html:has(.fl-shell) { height: 100%; }
body:has(.fl-shell) { height: 100%; overflow: hidden; display: flex; flex-direction: column; }
.fl-shell { flex: 1; min-height: 0; display: flex; overflow: hidden; position: relative; }
/* position: relative —— 极简档的导航栏与遮罩是 absolute（相对 shell，不盖住 titlebar） */
/* Content layer = 页面叠放容器：所有 .fl-page 放同一网格单元，转场期互相覆盖而不是上下堆叠。
   网格行固定成 1fr（minmax(0,1fr)）：页面必须拿到「确定高度」才能各自成为滚动容器；
   否则 auto 行会被内容撑高，overflow:clip 直接裁掉而不是出滚动条。 */
.fl-content-layer {
  flex: 1; min-width: 0; display: grid;
  grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr);
  background: var(--fl-solid-bg-base); overflow: clip;
}
/* overflow: clip：页面转场会横向平移 ±--fl-page-shift-drill，必须裁掉，否则出现横向滚动条；
   clip 不产生滚动容器（比 hidden 安全）。若页内需要 position:sticky，改 overflow:hidden + overflow-clip-margin。 */

/* 卡片：Content layer 表面，elevation 8（hover 提升视觉），8px 圆角（浮层级容器） */
.fl-card {
  background: var(--fl-card-bg);
  border: var(--fl-stroke) solid var(--fl-card-stroke);
  border-radius: var(--fl-radius-overlay);
  box-shadow: var(--fl-shadow-card);
  padding: var(--fl-space-4);
}
.fl-card.fl-hoverable { cursor: default; transition: background var(--fl-dur-fast) var(--fl-ease-standard); }
.fl-card.fl-hoverable:hover { background: var(--fl-card-bg-secondary); }

/* ---- 标题栏（titlebar 模块） ---- */
.fl-titlebar {
  display: flex; align-items: center; gap: var(--fl-space-2);
  height: var(--fl-control-height); padding: 0 var(--fl-space-2);
  background: var(--fl-solid-bg-base); color: var(--fl-text-primary);
  border-bottom: var(--fl-stroke) solid var(--fl-divider-stroke);
}

/* ---- NavigationView 左导航（nav 模块） ----
   结构/选择规则出处：learn.../design/basics/navigation-basics（顶层页、>5 项、不频繁切换）
   响应式三档（PaneDisplayMode=Auto 的官方默认行为，阈值与响应式断点同值）：
     · ≥1008px  Expanded —— pane 并排展开（--fl-nav-width）
     · 641~1007 Compact  —— 只留图标列（--fl-nav-compact-width=48，NavigationViewCompactPaneLength）
     · ≤640px   Minimal  —— pane 收起，点汉堡从左侧浮出盖住内容 + 遮罩（--fl-smoke），点遮罩/Esc 关闭
   档位由 JS 写 data-nav-mode（对应 XAML 的 AdaptiveTrigger → VisualState），CSS 只认这个属性；
   宽度切换**不做过渡**（过渡 width 会被 layout 量化成台阶，见 fluent2-motion.css 滑块那段）。 */
.fl-nav {
  width: var(--fl-nav-width); flex-shrink: 0;
  position: relative;          /* 指示条层的定位基准（.fl-nav-ind 的 offsetParent） */
  background: var(--fl-layer-fill, var(--fl-solid-bg-secondary));
  border-right: var(--fl-stroke) solid var(--fl-divider-stroke);
  /* 4px 内边距：官方 pane 内容距边缘 4，导航项从 4 起、图标盒 40 宽 → 图标中心恒在 24 */
  padding: var(--fl-space-1); display: flex; flex-direction: column; gap: var(--fl-space-1);
  overflow-y: auto; /* 导航项多时侧栏自己滚，页面本体不动 */
}
/* pane 头部行：官方 NavigationViewPaneHeaderRowMinHeight=40，放 PaneToggleButton(40×36)。
   与导航项同一个原点：按钮盒从 pane 内 4px 起 → 图标中心也是 24。 */
.fl-nav-panehead {
  flex-shrink: 0; display: flex; align-items: center;
  height: calc(var(--fl-nav-toggle-h) + var(--fl-space-1));
}
.fl-nav-toggle {
  width: var(--fl-nav-toggle-w); height: var(--fl-nav-toggle-h);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0; padding: 0; cursor: pointer;
  border: 0; border-radius: var(--fl-radius-control); background: transparent;
  color: var(--fl-text-primary);
  transition: background var(--fl-dur-fast) var(--fl-ease-standard);
}
.fl-nav-toggle:hover { background: var(--fl-subtle-fill-hover); }
.fl-nav-toggle:active { background: var(--fl-subtle-fill-pressed); color: var(--fl-text-secondary); }
.fl-nav-glyph { width: 16px; height: 16px; display: block; }
/* 图标盒：官方 NavigationViewIconBoxWidth=40（图标 16 居中于 40 盒，左右各 12），
   所以图标中心恒在 pane 内 4+20=24 处 —— 展开态和紧凑态是同一个位置。 */
.fl-nav-icon {
  width: 16px; height: 16px; flex-shrink: 0; display: block;
  box-sizing: content-box; padding: 0 var(--fl-space-3);
}
.fl-nav-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 紧凑档：48px 图标列。内边距 4 → 导航项 40 宽（与官方 compact item 一致），图标水平居中 */
.fl-nav[data-nav-mode="compact"] {
  width: var(--fl-nav-compact-width);
  padding: var(--fl-space-1);
}
.fl-nav[data-nav-mode="compact"] .fl-nav-panehead { margin-left: 0; padding: 0; }
.fl-nav[data-nav-mode="compact"] .fl-nav-item {
  justify-content: center; gap: 0; padding: 0;
}
.fl-nav[data-nav-mode="compact"] .fl-nav-label { display: none; }

/* 极简档：pane 变成盖在内容上的浮层，从左侧滑出（SplitView Pane 的 overlay 行为）。
   开关对称用 ControlNormal 250ms —— pane 是布局元素，和菜单那种轻量弹层不同档。
   visibility 走 0s + 延迟，保证关闭动画播完才真正隐藏。 */
.fl-nav[data-nav-mode="minimal"] {
  position: absolute; left: 0; top: 0; bottom: 0; z-index: 45;
  width: var(--fl-nav-width);
  /* 浮层态用 Acrylic（官方 LeftMinimal 的 NavigationViewDefaultPaneBackground）：
     并排态的 --fl-layer-fill 只有 30% 不透明，浮起来会透出下面的正文 */
  background: var(--fl-acrylic-bg);
  -webkit-backdrop-filter: blur(60px) saturate(125%);
  backdrop-filter: blur(60px) saturate(125%);
  box-shadow: var(--fl-shadow-flyout);
  transform: translateX(-100%); visibility: hidden;
  transition: transform var(--fl-dur-control-normal) var(--fl-ease-standard),
              visibility 0s linear var(--fl-dur-control-normal);
}
.fl-nav[data-nav-mode="minimal"][data-nav-open="1"] {
  transform: none; visibility: visible;
  transition: transform var(--fl-dur-control-normal) var(--fl-ease-standard),
              visibility 0s linear;
}
/* 遮罩（SmokeFillColorDefault）：只在极简档存在；点它关闭 pane */
.fl-nav-scrim {
  position: absolute; inset: 0; z-index: 44;
  background: var(--fl-smoke);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity var(--fl-dur-control-normal) var(--fl-ease-standard),
              visibility 0s linear var(--fl-dur-control-normal);
}
.fl-nav-scrim[data-open="1"] {
  opacity: 1; visibility: visible; pointer-events: auto;
  transition: opacity var(--fl-dur-control-normal) var(--fl-ease-standard),
              visibility 0s linear;
}
/* 展开/紧凑档手动收起（点 pane 头部汉堡）：pane 直接让位，内容占满，汉堡移到内容左上。
   这里**不能过渡 width** —— layout 会把每帧宽度量化，看到的是 3 级台阶而不是平滑收起。 */
.fl-nav[data-nav-mode="expanded"][data-nav-open="0"],
.fl-nav[data-nav-mode="compact"][data-nav-open="0"] {
  width: 0; padding: 0; border-right-width: 0; overflow: hidden;
}
/* 极简档收起时，汉堡浮在内容左上角（官方 minimal 的 PaneToggleButton 也压在内容上）；
   pane 打开后由 pane 头部那个代替，这个隐藏 */
.fl-nav-toggle-float { position: absolute; left: 0; top: 0; z-index: 46; display: none; }
.fl-nav[data-nav-open="0"] ~ .fl-nav-toggle-float { display: inline-flex; }
/* 汉堡浮在内容上时要给它让位，否则会压住 Infobar 左侧的 severity 条（官方 minimal 的
   toggle 也是独占内容左上一格，内容不会被它盖住） */
.fl-shell:has(.fl-nav[data-nav-open="0"]) > .fl-content-layer {
  padding-left: var(--fl-nav-toggle-w);
}
.fl-nav-item {
  position: relative; display: flex; align-items: center; gap: 0;
  min-height: var(--fl-nav-item-height); /* NavigationViewItemOnLeftMinHeight 36（不是控件标准高 32） */
  /* 左内边距 0：图标盒自己的 12px 内边距就是它的左边距（官方 4 + 40 盒 = 文字从 44 开始） */
  padding: 0 var(--fl-space-2) 0 0;
  border-radius: var(--fl-radius-indicator); color: var(--fl-text-primary);
  text-decoration: none; cursor: pointer; border: 0; background: transparent; width: 100%;
  font: inherit; text-align: left;
  transition: background var(--fl-dur-fast) var(--fl-ease-standard);
}
/* 没有图标的导航项：文字直接从 16px 开始（否则贴着左边缘） */
.fl-nav-item:not(:has(.fl-nav-icon)) { padding-left: var(--fl-space-4); }
.fl-nav-item:hover { background: var(--fl-subtle-fill-hover); }
.fl-nav-item:active { background: var(--fl-subtle-fill-pressed); color: var(--fl-text-secondary); }
.fl-nav-item[aria-current="page"] { background: var(--fl-subtle-fill-hover); font-weight: var(--fl-weight-semibold); }
/* 选中指示条：3×16 胶囊（NavigationViewSelectionIndicatorWidth/Height/Radius）
   默认由 JS 挂一个独立的 .fl-nav-ind 层来画，以便做"拉伸→收缩"的移动动画。
   注意（录屏实测）：拉伸峰值固定 1.6×（16→25.6），**始终落在所在导航项内部**，
   条不会跨过项间隙、也不会跑出按钮；换项瞬间是"旧项塌缩 + 新项直接满高出现"。
   没有 JS 时退回每项的 ::before。 */
.fl-nav-item[aria-current="page"]::before {
  content: ""; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: var(--fl-nav-indicator-w); height: var(--fl-nav-indicator-h);
  border-radius: var(--fl-radius-indicator); background: var(--fl-accent-fill);
}
/* JS 挂上指示条层之后，关掉每项的静态胶囊，否则会看到两条 */
.fl-nav[data-fl-indicator="on"] .fl-nav-item[aria-current="page"]::before { content: none; }

.fl-nav-ind {
  position: absolute; left: 0; top: 0;
  width: var(--fl-nav-indicator-w); height: var(--fl-nav-indicator-h);
  border-radius: var(--fl-radius-indicator);
  background: var(--fl-accent-fill);
  pointer-events: none; opacity: 0;
  /* 锚点由 JS 按方向切换：旧条锚"尾部边"（往下的方向=顶边）往目标长；
     新条锚"头部边"（往下的方向=底边）往回缩。1.6× 单向生长 = 中心只挪 4.8px，
     项高 36 - 条高 16 = 20px 余量，所以两侧都不会越界。 */
  transform-origin: 50% 0;
  will-change: transform, opacity;
}
/* 过渡期两层：ghost 在旧项里长/塌，pill 在新项里收 */
.fl-nav-ind[data-role="ghost"] { z-index: 1; }
.fl-nav-ind[data-role="pill"] { z-index: 2; }

/* ---- 按钮（Button XAML：Padding 11,5,11,6；Rest elevation 2 / Pressed 1；圆角 4） ---- */
.fl-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--fl-space-2);
  min-height: var(--fl-control-height);
  /* 纵向内边距必须左右对称：XAML 的 ButtonPadding=11,5,11,6 是给 XAML ContentPresenter
     的字基线对齐用的，照搬到 flex 居中盒里会让文字整体下沉 2px（5 vs 6 再叠 12/8 更明显）。
     这里上下各 4，居中交给 align-items:center。 */
  padding: var(--fl-space-1) var(--fl-btn-pad-h);
  border-radius: var(--fl-radius-control);
  border: var(--fl-stroke) solid var(--fl-control-stroke);
  background: var(--fl-control-fill-default);
  color: var(--fl-text-primary);
  font: inherit;
  line-height: 1.35;
  box-shadow: var(--fl-shadow-e2); /* Control elevation 2 (Rest) */
  cursor: pointer; text-decoration: none;
  transition: background var(--fl-dur-fast) var(--fl-ease-standard);
}
.fl-btn:hover { background: var(--fl-control-fill-secondary); }
/* 官方控件状态海拔：Rest/Hover=2、Pressed=1（阴影瞬时切换，不做过渡，1px 级无感） */
.fl-btn:active { background: var(--fl-control-fill-tertiary); box-shadow: var(--fl-shadow-e1); }
.fl-btn:disabled, .fl-btn[aria-disabled="true"] {
  background: var(--fl-control-fill-disabled);
  border-color: var(--fl-control-stroke); color: var(--fl-text-disabled); box-shadow: none;
}
.fl-btn-accent {
  background: var(--fl-accent-fill); border-color: var(--fl-control-stroke-on-accent);
  color: var(--fl-text-on-accent-primary);
}
/* accent 状态档位：XAML AccentFillColorSecondaryBrush=Default@0.9、TertiaryBrush=Default@0.8
   （用档位色过渡，不用 filter:brightness —— filter 无法平滑过渡，是「点击瞬跳」的来源） */
.fl-btn-accent:hover { background: var(--fl-accent-fill-hover); }
.fl-btn-accent:active { background: var(--fl-accent-fill-pressed); box-shadow: var(--fl-shadow-e1); }
.fl-btn-subtle { background: var(--fl-control-fill-transparent, transparent); border-color: transparent; box-shadow: none; }
.fl-btn-subtle:hover { background: var(--fl-subtle-fill-hover); }
.fl-btn-subtle:active { background: var(--fl-subtle-fill-pressed); }

/* ---- 文本输入（TextBox XAML：MinHeight 32、Padding 10,5,6,6） ---- */
.fl-input, .fl-select {
  min-height: var(--fl-control-height);
  padding: var(--fl-text-pad-t) var(--fl-text-pad-r) var(--fl-text-pad-b) var(--fl-text-pad-l);
  border-radius: var(--fl-radius-control);
  border: var(--fl-stroke) solid var(--fl-control-stroke);
  border-bottom-color: var(--fl-control-strong-fill); /* Win11 底边加重 */
  background: var(--fl-control-fill-default);
  color: var(--fl-text-primary); font: inherit;
  transition: border-color var(--fl-dur-fast) var(--fl-ease-standard), background var(--fl-dur-fast) var(--fl-ease-standard);
}
.fl-input::placeholder { color: var(--fl-text-tertiary); }
.fl-input:hover, .fl-select:hover { background: var(--fl-control-fill-secondary); }
.fl-input:focus-visible, .fl-select:focus-visible {
  border-bottom-color: var(--fl-accent-fill);
  box-shadow: 0 0 0 var(--fl-stroke) var(--fl-focus-stroke-inner),
              0 0 0 calc(var(--fl-stroke) * 2) var(--fl-focus-stroke-outer);
}
.fl-input:disabled { background: var(--fl-control-fill-disabled); color: var(--fl-text-disabled); }

/* ---- ToggleSwitch（knob 12x12，on=accent） ---- */
/* ---- ToggleSwitch（XAML ToggleSwitch_themeresources：轨道 40×20、旋钮 12、开态位移 X=20，
        hover 旋钮 14 / pressed 17，全用 ControlFasterAnimationDuration=83ms + FastOutSlowIn 曲线） ---- */
.fl-switch { --fl-knob: 12px; --fl-knob-x: 20px; display: inline-flex; align-items: center; gap: var(--fl-space-2); cursor: pointer; }
.fl-switch:hover  { --fl-knob: 14px; --fl-knob-x: 18px; }  /* XAML hover Value 14（右缘保持一致） */
.fl-switch:active { --fl-knob: 17px; --fl-knob-x: 15px; }  /* XAML pressed Value 17 */
.fl-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.fl-switch .fl-switch-track {
  width: 40px; height: 20px; border-radius: var(--fl-space-3);
  border: var(--fl-stroke) solid var(--fl-control-strong-fill);
  background: var(--fl-control-fill-default); position: relative;
  transition: background var(--fl-dur-fast) var(--fl-ease-standard),
              border-color var(--fl-dur-fast) var(--fl-ease-standard);
}
.fl-switch .fl-switch-track::after {
  content: ""; position: absolute; top: 50%; left: var(--fl-space-1); transform: translateY(-50%);
  width: var(--fl-knob); height: var(--fl-knob); border-radius: 50%;
  background: var(--fl-text-secondary);
  transition: transform var(--fl-dur-fast) var(--fl-ease-standard),
              width var(--fl-dur-fast) var(--fl-ease-standard),
              height var(--fl-dur-fast) var(--fl-ease-standard),
              background var(--fl-dur-fast) var(--fl-ease-standard);
}
.fl-switch input:checked + .fl-switch-track { background: var(--fl-accent-fill); border-color: var(--fl-accent-fill); }
.fl-switch input:checked + .fl-switch-track::after { transform: translate(var(--fl-knob-x), -50%); background: var(--fl-text-on-accent-primary); }
.fl-switch input:focus-visible + .fl-switch-track {
  box-shadow: 0 0 0 var(--fl-stroke) var(--fl-focus-stroke-inner),
              0 0 0 calc(var(--fl-stroke) * 2) var(--fl-focus-stroke-outer);
}

/* ---- CheckBox / RadioButton ----
   几何：方框 20×20（CheckBoxSize）、圆角 4（ControlCornerRadius）、描边 1（CheckBoxBorderThickness）
   勾号：SVG 描画（官方 ListViewItem CheckGlyph 的 2.5 描边宽，见 --fl-glyph-stroke），
        不是文本字符 —— 文本 ✓ 无法描画、字重随字体漂移，且在中文字体下会被替换成异体字。
   状态：底色 83ms（官方 XAML 该控件是 DiscreteObjectKeyFrame 瞬时切色，此处保留 83ms 避免硬切，
        属登记级偏离，见 KIT 规则 12）；勾号描绘 167ms（= ControlFastAnimationDuration）。 */
.fl-check, .fl-radio { position: relative; display: inline-flex; align-items: center; gap: var(--fl-space-2); cursor: pointer; }
.fl-check input, .fl-radio input {
  position: absolute; opacity: 0;
  width: 1px; height: 1px; clip-path: inset(50%); /* 视觉隐藏但保留可聚焦命中区（0×0 会让辅助技术拿不到） */
}
/* 方框视觉是共用的：.fl-check / .fl-radio 用它，列表多选列也用它（状态分别由 :checked 与行的 aria-selected 驱动） */
.fl-box {
  width: var(--fl-check-size); height: var(--fl-check-size); flex-shrink: 0;
  border-radius: var(--fl-radius-control);
  border: var(--fl-check-stroke) solid var(--fl-control-strong-fill);
  background: var(--fl-control-fill-default);
  display: inline-flex; align-items: center; justify-content: center;
  transition: background var(--fl-dur-control-faster) var(--fl-ease-standard),
              border-color var(--fl-dur-control-faster) var(--fl-ease-standard);
}
.fl-radio .fl-box { border-radius: 50%; }

/* hover / pressed（未选中档；选中档写在后面，优先级更高） */
.fl-check:hover .fl-box, .fl-radio:hover .fl-box { background: var(--fl-control-fill-secondary); }
.fl-check:active .fl-box, .fl-radio:active .fl-box { background: var(--fl-control-fill-tertiary); }

/* 选中档（必须排在 hover/pressed 之后） */
.fl-check input:checked + .fl-box, .fl-radio input:checked + .fl-box,
.fl-check input:indeterminate + .fl-box {
  background: var(--fl-accent-fill); border-color: var(--fl-accent-fill); color: var(--fl-text-on-accent-primary);
}
.fl-check:hover input:checked + .fl-box, .fl-radio:hover input:checked + .fl-box,
.fl-check:hover input:indeterminate + .fl-box { background: var(--fl-accent-fill-hover); border-color: var(--fl-accent-fill-hover); }
.fl-check:active input:checked + .fl-box, .fl-radio:active input:checked + .fl-box,
.fl-check:active input:indeterminate + .fl-box { background: var(--fl-accent-fill-pressed); border-color: var(--fl-accent-fill-pressed); }

/* 禁用档 */
.fl-check input:disabled ~ .fl-box, .fl-radio input:disabled ~ .fl-box {
  background: var(--fl-control-fill-disabled);
  border-color: var(--fl-control-strong-fill-disabled);
}
.fl-check input:disabled:checked ~ .fl-box, .fl-radio input:disabled:checked ~ .fl-box,
.fl-check input:disabled:indeterminate ~ .fl-box {
  background: var(--fl-accent-fill-disabled); border-color: var(--fl-accent-fill-disabled);
  color: var(--fl-text-on-accent-disabled);
}
.fl-check input:disabled ~ span, .fl-radio input:disabled ~ span { color: var(--fl-text-disabled); cursor: default; }

/* 勾号：中心线 + pathLength="1"，靠 stroke-dashoffset 描画
   终态由 :checked 决定（未选中态才写 dashoffset:1），动画只由 transition 承担 ——
   reduced-motion 时只需关掉 transition，勾号自动是终态，不会"永远不出现" */
.fl-check-glyph { width: var(--fl-check-glyph); height: var(--fl-check-glyph); display: block; overflow: visible; }
.fl-check-glyph path {
  fill: none; stroke: currentColor; stroke-width: var(--fl-glyph-stroke);
  stroke-linecap: butt; stroke-linejoin: miter;
  stroke-dasharray: 1;
  transition: stroke-dashoffset var(--fl-dur-control-fast) var(--fl-ease-standard);
}
.fl-check-glyph .fl-check-dash { display: none; }
.fl-check input:not(:checked):not(:indeterminate) + .fl-box .fl-check-glyph path { stroke-dashoffset: 1; }
.fl-check input:indeterminate + .fl-box .fl-check-glyph .fl-check-mark { display: none; }
.fl-check input:indeterminate + .fl-box .fl-check-glyph .fl-check-dash { display: block; }

/* 单选内点：12（RadioButtonCheckGlyphSize）；hover 1.167 / pressed 0.833 由 --fl-radio-boost 叠乘，
   不用 width 过渡（会触发布局） */
.fl-radio .fl-box::after {
  content: ""; width: var(--fl-radio-glyph); height: var(--fl-radio-glyph);
  border-radius: 50%; background: var(--fl-text-on-accent-primary);
  transform: scale(calc(var(--fl-radio-on, 0) * var(--fl-radio-boost, 1)));
  transition: transform var(--fl-dur-control-normal) var(--fl-ease-standard);
}
.fl-radio input:checked + .fl-box::after { --fl-radio-on: 1; }
.fl-radio:hover .fl-box::after { --fl-radio-boost: 1.167; }
.fl-radio:active .fl-box::after { --fl-radio-boost: 0.833; }

.fl-check input:focus-visible + .fl-box, .fl-radio input:focus-visible + .fl-box {
  box-shadow: 0 0 0 var(--fl-stroke) var(--fl-focus-stroke-inner),
              0 0 0 calc(var(--fl-stroke) * 2) var(--fl-focus-stroke-outer);
}

/* ---- Slider（XAML Slider_themeresources）
       几何：SliderTrackThemeHeight=4、SliderInnerThumbWidth=12、SliderThumbCornerRadius=10
       配色四档（轨道填充 SliderTrackValueFill 与 thumb SliderThumbBackground 同档）：
         rest=AccentFillColorDefault、PointerOver=AccentFillColorSecondary、
         Pressed=AccentFillColorTertiary、Disabled=AccentFillColorDisabled
       轨道底 SliderTrackFill=ControlStrongFillColorDefault（Disabled 走 ControlStrongFillColorDisabled）

       thumb 是**两层**（照 XAML 模板拆）：
         外框 = ControlSolidFillColorDefault 的实心圆盘（SliderOuterThumbBackground），直径 20，**任何状态下都不变**；
         内点 = 12px 的 accent 圆（SliderInnerThumb，模板里只对这个 Ellipse 做 ScaleTransform）。
       模板的 VisualState 只动内点：Normal 0.86→12 / PointerOver 1.167→14 / Pressed 0.71→10 / Disabled 1.167→14。

       伪元素没有子元素，怎么"只缩内点、不动外框"？**缩放 + 环宽反向补偿**：
         transform: scale(--fl-slider-scale)        内点 1 / 1.1667 / 0.8333
         box-shadow: 0 0 0 --fl-slider-ring 实色     环宽 = (20 / scale − 12) / 2
       两者相乘恒等于 20，所以 scale 变大时环变窄、外框不动。

       ⚠ 为什么用 transform 而不是改 width/height（这轮返工的根因）：
         改宽高走 layout，Chromium 对伪元素盒宽会量化取整，实测整个过渡只有
         12.0 / 13.3 / 13.9 三级台阶 —— 看着就是"跳一下"，完全没有曲线的样子。
         transform 走合成器，逐帧亚像素插值（实测能拿到 8 级以上连续值）。
       ⚠ 但**不能直接 scale 了事**：环也会跟着放大（早期版本就这么错，用户原话"外框从来都不会变大小"），
         必须同时用 ring = (20/scale − 12)/2 反向补偿。
       ⚠ `background-size` 在 ::-webkit-slider-thumb 上不会过渡（实测直接跳变），
         "固定 20 盒子 + 背景图圆点"的方案不成立。

       注意：填充段**不设 transition** —— 它必须与 thumb 逐帧一致，加过渡会把拖动变成拖影 */
.fl-slider {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: var(--fl-control-height);
  background: transparent; cursor: pointer;
  /* --fl-slider-pct：0..1 的单位数，由 M.slider.auto() 写入；缺省 0 = 无填充段（等价旧观感，不会画错） */
  --fl-slider-pct: 0;
  --fl-slider-accent: var(--fl-accent-fill);
  --fl-slider-rest: var(--fl-control-strong-fill);
  /* 外框直径 20 = 内点 12 + 2 × 环宽 4；三态恒定 */
  --fl-slider-thumb: 20px;
  /* 内点缩放：rest 1 → hover 1.1667(14px) → pressed 0.8333(10px)。
     **用 transform 缩放而不是改 width**：改宽高走 layout，Chromium 会把伪元素的盒宽
     量化到整像素，实测只有 12.0 / 13.3 / 13.9 三级台阶（看着像"跳一下"）；
     transform 走合成器，逐帧亚像素插值，才是曲线该有的样子。 */
  --fl-slider-scale: 1;
  /* 填充宽 = 半内点 + 比例 ×（轨道宽 - 内点宽）
     thumb 盒宽恒 = --fl-slider-inner（缩放不参与布局），所以填充基准也跟着恒定。 */
  --fl-slider-fill: calc(var(--fl-slider-inner) / 2
                   + (100% - var(--fl-slider-inner)) * var(--fl-slider-pct));
}
/* 状态反馈用**不透明**的混色，不用 alpha 档位：AccentFillColorSecondary/Tertiary 是 10%/20% 透明，
   叠在卡片上会让填充段和 thumb 看起来"变透明/发灰"（暗色更明显，蓝底透出灰环形）。
   混色方向跟着主题走：亮色主题文字色=黑 → hover 变深、暗色主题文字色=白 → hover 变亮，
   两个主题都是"实色变一档"，不会有透出底层的问题。 */
.fl-slider:not(:disabled):hover  {
  --fl-slider-accent: color-mix(in srgb, var(--fl-accent-fill) 90%, var(--fl-text-primary));
}
.fl-slider:not(:disabled):active {
  --fl-slider-accent: color-mix(in srgb, var(--fl-accent-fill) 80%, var(--fl-text-primary));
}
.fl-slider:disabled {
  cursor: default;
  --fl-slider-scale: 1.1667;               /* 模板 Disabled 也是 1.167（内点反而更大） */
  --fl-slider-accent: var(--fl-accent-fill-disabled);
  --fl-slider-rest: var(--fl-control-strong-fill-disabled);
}

.fl-slider::-webkit-slider-runnable-track {
  height: var(--fl-slider-track);
  border-radius: calc(var(--fl-slider-track) / 2);
  background-color: var(--fl-slider-rest);   /* 渐变解析失败时的兜底：仍是能看的整条轨道 */
  /* 两个同位置停点 = 硬边界（不是色带渐变） */
  background-image: linear-gradient(to right,
    var(--fl-slider-accent) var(--fl-slider-fill),
    var(--fl-slider-rest) var(--fl-slider-fill));
}
/* RTL：填充段改从右侧起算（Firefox 的 ::-moz-range-progress 随 direction 自动翻转，不需要另写） */
[dir="rtl"] .fl-slider::-webkit-slider-runnable-track {
  background-image: linear-gradient(to left,
    var(--fl-slider-accent) var(--fl-slider-fill),
    var(--fl-slider-rest) var(--fl-slider-fill));
}
.fl-slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  box-sizing: border-box;
  /* ⚠ 环宽必须在 thumb 自身上算（写在 .fl-slider 上会按静止态算死成 4px，hover 时外框变 22）。
     外框恒 20 的推导：scale × (内点 + 2 × 环宽) = 20
       ⇒ 环宽 = (20 / scale − 内点) / 2
     实测：scale 1.1667 → 环 2.571（缩放后视觉 3.0），puck 仍是 20。 */
  --fl-slider-ring: calc((var(--fl-slider-thumb) / var(--fl-slider-scale) - var(--fl-slider-inner)) / 2);
  /* 盒子恒为静止内点（12），尺寸靠 transform 缩放 → 合成器逐帧插值，不经过 layout 取整 */
  width: var(--fl-slider-inner); height: var(--fl-slider-inner);
  margin-top: calc((var(--fl-slider-track) - var(--fl-slider-inner)) / 2);
  border: 0; border-radius: var(--fl-slider-radius);
  background: var(--fl-slider-accent);
  box-shadow: 0 0 0 var(--fl-slider-ring) var(--fl-control-solid-fill); /* 外框 20（SliderOuterThumbBackground） */
  transform: scale(var(--fl-slider-scale));
  transform-origin: 50% 50%;          /* 绕圆心缩放，中心始终落在当前值上 */
  will-change: transform;
  /* 时长按模板**逐状态**给（XAML 三个 VisualState 的 KeyTime 不一样，别用一个值糊过去）：
       PointerOver / Pressed：ControlNormalAnimationDuration = 250ms
       Normal（悬停移开、缩回）：ControlFastAnimationDuration = 167ms
     CSS 过渡取的是**目标态**的时长，所以基态写 167、hover/active 各自覆盖成 250。
     曲线三态都是 ControlFastOutSlowIn = cubic-bezier(0,0,0,1)（= --fl-ease-standard）。 */
  transition:
    transform var(--fl-dur-control-fast) var(--fl-ease-standard),
    box-shadow var(--fl-dur-control-fast) var(--fl-ease-standard);
}
.fl-slider:not(:disabled):hover::-webkit-slider-thumb  {
  --fl-slider-scale: 1.1667;                              /* 12 → 14 */
  transition-duration: var(--fl-dur-control-normal);      /* 放大 250ms */
}
.fl-slider:not(:disabled):active::-webkit-slider-thumb {
  --fl-slider-scale: 0.8333;                              /* 12 → 10 */
  transition-duration: var(--fl-dur-control-normal);      /* 按下 250ms */
}
.fl-slider:focus-visible { outline: none; }
/* 焦点环要画在外框之外：先保留外框那一圈，再加两层细环 */
.fl-slider:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 var(--fl-slider-ring) var(--fl-control-solid-fill),
              0 0 0 calc(var(--fl-slider-ring) + var(--fl-stroke)) var(--fl-focus-stroke-inner),
              0 0 0 calc(var(--fl-slider-ring) + var(--fl-stroke) * 2) var(--fl-focus-stroke-outer);
}

/* Firefox：填充段用原生的 ::-moz-range-progress，几何由引擎算，不需要渐变 */
.fl-slider::-moz-range-track {
  height: var(--fl-slider-track);
  border-radius: calc(var(--fl-slider-track) / 2);
  background: var(--fl-slider-rest);
}
.fl-slider::-moz-range-progress {
  height: var(--fl-slider-track);
  border-radius: calc(var(--fl-slider-track) / 2);
  background: var(--fl-slider-accent);
}
.fl-slider::-moz-range-thumb {
  box-sizing: border-box;
  --fl-slider-ring: calc((var(--fl-slider-thumb) / var(--fl-slider-scale) - var(--fl-slider-inner)) / 2);
  width: var(--fl-slider-inner); height: var(--fl-slider-inner);
  border: 0; border-radius: var(--fl-slider-radius);
  background: var(--fl-slider-accent);
  box-shadow: 0 0 0 var(--fl-slider-ring) var(--fl-control-solid-fill);
  transform: scale(var(--fl-slider-scale));
  transition:
    transform var(--fl-dur-control-fast) var(--fl-ease-standard),
    box-shadow var(--fl-dur-control-fast) var(--fl-ease-standard);
}
.fl-slider:not(:disabled):hover::-moz-range-thumb  {
  --fl-slider-scale: 1.1667;
  transition-duration: var(--fl-dur-control-normal);
}
.fl-slider:not(:disabled):active::-moz-range-thumb {
  --fl-slider-scale: 0.8333;
  transition-duration: var(--fl-dur-control-normal);
}
.fl-slider:focus-visible::-moz-range-thumb {
  box-shadow: 0 0 0 var(--fl-slider-ring) var(--fl-control-solid-fill),
              0 0 0 calc(var(--fl-slider-ring) + var(--fl-stroke)) var(--fl-focus-stroke-inner),
              0 0 0 calc(var(--fl-slider-ring) + var(--fl-stroke) * 2) var(--fl-focus-stroke-outer);
}

/* ---- 表盘（连续型动效的宿主）：指针绕表盘圆心旋转 ----
   .fl-dial 定尺寸；.fl-dial-hand 从圆心向上画，transform-origin 落在自身底边 = 圆心；
   旋转动画加在 .fl-dial-hand 本身（.fl-tick / .fl-continuous），不要再套一层容器 */
.fl-dial { position: relative; width: 96px; height: 96px; flex-shrink: 0; }
.fl-dial-hand {
  position: absolute; left: 50%; bottom: 50%;
  width: 2px; margin-left: -1px; border-radius: 1px;
  background: var(--fl-text-primary);
  transform-origin: 50% 100%;
}
.fl-dial-hub {
  position: absolute; left: 50%; top: 50%;
  width: 8px; height: 8px; margin: -4px 0 0 -4px;
  border-radius: 50%; background: var(--fl-text-primary);
}

/* ---- 列表（ListView）----
   行结构（对应 Win11 设置页实测形态）：图标 + 主标题/副标题 + 尾部区域（数值/开关/箭头）
   六档背景严格对应 XAML ListViewItemPresenter（顺序即语义，勿按字母序重排 ——
   选中+hover 必须写在 :hover 之后，否则同权重会被 .fl-listitem:hover 抢走）：
     Rest                SubtleFillColorTransparent → --fl-control-fill-transparent
     PointerOver         SubtleFillColorSecondary   → --fl-subtle-fill-hover
     Pressed             SubtleFillColorTertiary    → --fl-subtle-fill-pressed
     Selected            SubtleFillColorSecondary   → --fl-subtle-fill-hover
     SelectedPointerOver SubtleFillColorTertiary    → --fl-subtle-fill-pressed
     SelectedPressed     SubtleFillColorSecondary   → --fl-subtle-fill-hover
   注意：Tertiary 比 Secondary 更淡，所以「选中+hover」比「仅选中」略淡是官方行为，不是 bug。 */
.fl-list { display: flex; flex-direction: column; min-width: var(--fl-list-min-width); }

.fl-listitem {
  --fl-check-col: 0px;   /* 多选模式下由 .fl-list[data-multiselect] 改成 40.5px */
  position: relative;
  display: grid;
  /* 第 1 列 = 多选勾选列（平时 0 宽），第 2 列 = 行内容
     minmax(0,1fr) 是省略号生效的关键：否则长标题会把尾部箭头挤出容器 */
  grid-template-columns: var(--fl-check-col) minmax(0, 1fr);
  align-items: center;
  min-height: var(--fl-list-item-height);      /* ListViewItemMinHeight 40（单行） */
  padding: 0 var(--fl-space-3);
  border-radius: var(--fl-radius-control);
  background: var(--fl-control-fill-transparent);
  cursor: pointer;
  transition: background var(--fl-dur-control-faster) var(--fl-ease-standard),
              grid-template-columns var(--fl-dur-control-faster) var(--fl-ease-standard);
}
/* 多选模式：腾出 40.5px（= -ListViewItemContentOffsetX）给勾选列，内容整体右移
   用列宽过渡而不是 transform —— transform 会让尾部箭头冲出右内边距 */
.fl-list[data-multiselect] .fl-listitem { --fl-check-col: var(--fl-list-check-offset); }

/* 行内容：图标 + 主副标题 + 尾部区域（数值/开关/箭头） */
.fl-list-content {
  grid-column: 2;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  column-gap: var(--fl-space-3);
  min-width: 0;
}

/* 两行档：图标 + 主标题 + 副标题，行高 64（KIT 自定，见 tokens 注释） */
.fl-listitem[data-lines="2"] {
  min-height: var(--fl-list-item-height-two-line);
  padding-top: var(--fl-space-2);
  padding-bottom: var(--fl-space-2);
}

/* 勾选列：列宽为 0 时靠 overflow 裁掉，不外溢到内容上 */
.fl-listitem-check {
  grid-column: 1;
  display: inline-flex; align-items: center; min-width: 0;
  overflow: hidden;
}
/* 多选列的勾选状态由行的 aria-selected 驱动（不在 role="option" 里嵌套 checkbox，避免 ARIA 冲突） */
.fl-listitem[aria-selected="true"] .fl-box {
  background: var(--fl-accent-fill); border-color: var(--fl-accent-fill);
  color: var(--fl-text-on-accent-primary);
}
.fl-listitem[aria-selected="true"]:hover .fl-box { background: var(--fl-accent-fill-hover); border-color: var(--fl-accent-fill-hover); }
.fl-listitem[aria-selected="true"] .fl-check-glyph path { stroke-dashoffset: 0; }
.fl-listitem:not([aria-selected="true"]) .fl-check-glyph path { stroke-dashoffset: 1; }

.fl-list-lead {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--fl-icon-size); height: var(--fl-icon-size);
  flex-shrink: 0; color: var(--fl-text-primary);
}
.fl-list-lead > * { width: 100%; height: 100%; display: block; }

.fl-list-text { display: flex; flex-direction: column; min-width: 0; }
.fl-list-text > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fl-list-sub { color: var(--fl-text-secondary); }
.fl-listitem:not([data-lines="2"]) .fl-list-sub { display: none; }

/* 尾部箭头：仅静态右向。若要做「展开/收起」旋转，请换 SVG ——
   border 三角在中途旋转会短暂变成菱形 */
.fl-list-chevron {
  width: 8px; height: 8px; flex-shrink: 0;
  border-right: var(--fl-stroke) solid var(--fl-text-secondary);
  border-bottom: var(--fl-stroke) solid var(--fl-text-secondary);
  transform: rotate(-45deg);
  margin-right: var(--fl-space-1);
}

/* 六档背景（顺序即语义） */
.fl-listitem:not([aria-disabled="true"]):hover { background: var(--fl-subtle-fill-hover); }
.fl-listitem:not([aria-disabled="true"]):active { background: var(--fl-subtle-fill-pressed); }
.fl-listitem[aria-selected="true"] { background: var(--fl-subtle-fill-hover); }
.fl-listitem[aria-selected="true"]:hover { background: var(--fl-subtle-fill-pressed); }
.fl-listitem[aria-selected="true"]:active { background: var(--fl-subtle-fill-hover); }

/* 选中指示条：3×16、圆角 1.5（ListViewItemSelectionIndicatorCornerRadius）
   用 transition 而非 animation —— 在两行之间来回换选是可逆状态，keyframe 会"两条同时长出来" */
.fl-listitem::before {
  content: ""; position: absolute; left: 0; top: 50%;
  width: var(--fl-nav-indicator-w); height: var(--fl-nav-indicator-h);
  margin-top: calc(var(--fl-nav-indicator-h) / -2);
  border-radius: var(--fl-radius-list-indicator);
  background: var(--fl-accent-fill);
  transform: scaleY(0); opacity: 0;      /* 只动合成友好属性，不动 height */
  transition: transform var(--fl-dur-control-faster) var(--fl-ease-standard),
              opacity var(--fl-dur-control-faster) var(--fl-ease-linear);
}
.fl-listitem[aria-selected="true"]::before { transform: scaleY(1); opacity: 1; }

/* 分组分隔线：独立兄弟元素（几何上与行背景不重叠，不需要"有背景就隐藏"的动态逻辑） */
.fl-list-sep {
  height: var(--fl-stroke); flex-shrink: 0;
  margin: var(--fl-space-1) var(--fl-space-3);
  background: var(--fl-divider-stroke);
  border: 0;
}

/* ListViewItemDisabledThemeOpacity = 0.3 */
.fl-listitem[aria-disabled="true"] { opacity: 0.3; cursor: default; }

/* ---- 设置页列表（settings 模块）----
   对齐 Win11 设置类应用的"组 → 行"造型（实测自 2026-10-21 录屏）：
     · 组默认**不套卡片**，直接铺在页面底色上；只有需要分区时才 data-card
     · 行 = 图标 20 + 主标题 + 副标题 + 右侧控件/数值/箭头，两行行高 56（--fl-settings-row-h）
     · 行与行之间默认**没有分隔线**（录屏里语音包两行之间确实无线）；
       需要分隔时写 data-divided，线会自动左缩到文字起点，与图标列对齐
     · hover 是整行浅填充 + 圆角 4，不做"每行一个胶囊"（那是 ListViewItem 的形态，不是设置行） */
.fl-settings { display: flex; flex-direction: column; gap: var(--fl-space-6); }

.fl-settings-header {
  margin: 0;
  font-size: var(--fl-font-size-body);
  line-height: var(--fl-line-body);
  font-weight: var(--fl-weight-semibold);
  color: var(--fl-text-primary);
}
/* 组说明：紧跟在 header 下面，说明这组设置是干什么的 */
.fl-settings-desc {
  margin: var(--fl-space-1) 0 0;
  font-size: var(--fl-font-size-caption);
  line-height: var(--fl-line-caption);
  color: var(--fl-text-secondary);
}

.fl-settings-group { display: flex; flex-direction: column; }
/* 可选卡片造型：Windows 11 23H2 之后部分页面用卡片分组 */
.fl-settings-group[data-card] {
  padding: var(--fl-space-1) 0;
  background: var(--fl-card-bg);
  border: var(--fl-stroke) solid var(--fl-card-stroke);
  border-radius: var(--fl-radius-control);
}

.fl-settings-row {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  column-gap: var(--fl-space-3);
  min-height: var(--fl-settings-row-h);
  padding: var(--fl-space-1) var(--fl-space-3);
  border-radius: var(--fl-radius-control);
  /* 默认不可点（纯展示行）；可点行用 button / a / [tabindex] 自带 cursor */
  transition: background var(--fl-dur-control-faster) var(--fl-ease-standard);
}
button.fl-settings-row, a.fl-settings-row, .fl-settings-row[tabindex] { cursor: pointer; }
button.fl-settings-row, a.fl-settings-row {
  width: 100%; border: 0; background: transparent; color: inherit;
  font: inherit; text-align: left; text-decoration: none;
}
.fl-settings-row:hover { background: var(--fl-subtle-fill-hover); }
.fl-settings-row:active { background: var(--fl-subtle-fill-pressed); }
.fl-settings-row[aria-disabled="true"] { opacity: 0.3; cursor: default; }
.fl-settings-row[aria-disabled="true"]:hover,
.fl-settings-row[aria-disabled="true"]:active { background: transparent; }

.fl-settings-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--fl-icon-size); height: var(--fl-icon-size); flex-shrink: 0;
  color: var(--fl-text-secondary);
}
.fl-settings-icon > * { width: 100%; height: 100%; display: block; }

.fl-settings-text { display: flex; flex-direction: column; min-width: 0; }
.fl-settings-title {
  font-size: var(--fl-font-size-body);
  line-height: var(--fl-line-body);
  color: var(--fl-text-primary);
}
.fl-settings-sub {
  font-size: var(--fl-font-size-caption);
  line-height: var(--fl-line-caption);
  color: var(--fl-text-secondary);
}
.fl-settings-title,
.fl-settings-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 单行档：没有副标题时行高回到 40（= ListViewItemMinHeight，视觉上更紧凑） */
.fl-settings-row:not(:has(.fl-settings-sub)) { min-height: var(--fl-list-item-height); }

.fl-settings-action {
  display: inline-flex; align-items: center; gap: var(--fl-space-2);
  color: var(--fl-text-secondary); flex-shrink: 0;
}

/* 分隔线：data-divided，左侧缩进到文字起点（行左 padding + 图标 20 + 列间距 12 = 44），
   右侧与行右 padding 对齐；最后一行不再画 */
.fl-settings-row[data-divided]::after {
  content: ""; position: absolute; left: calc(var(--fl-space-3) + var(--fl-icon-size) + var(--fl-space-3));
  right: var(--fl-space-3); bottom: 0; height: var(--fl-stroke);
  background: var(--fl-divider-stroke);
}
.fl-settings-row[data-divided]:last-child::after { display: none; }
/* 没有图标列时，缩进退回行内边距，线从文字左缘开始 */
.fl-settings-row[data-divided]:not(:has(.fl-settings-icon))::after { left: var(--fl-space-3); }

/* ---- 细滚动条（.fl-scroll / .fl-page / .fl-nav）----
   浏览器默认滚动条是 17px 带上下箭头的方块，在 Acrylic 弹层里非常出戏。
   Win11 的做法是「细、圆头、无箭头、指针落在滚动条上才变粗」：

     · 命中区 12px；静止画 6px（3px 透明 border + content-box 裁出）
       —— 曾用过 2px / 4px，用户两次反馈"看不见"：弹层又小、底色又是 Acrylic，低于 6px 就是不可见；
     · **变粗只认指针在 thumb 上**（`::-webkit-scrollbar-thumb:hover`）。
       绝不能把 `:hover` 挂在容器上：`.fl-page:hover` 在鼠标位于页面任何位置时都成立，
       结果整页的滚动条永远处于"变粗"态（这是用户明确报的 bug）；
       也不能用 `:focus-within`：下拉一展开焦点自动进 listbox，等于一打开就变粗；
     · 拖动（`:active`）与 hover 同宽，不再继续变粗（曾经收到 0 直接画满 12px 命中区）；
     · 轨道永远透明，不占视觉空间。

   ⚠ 关键坑：Chromium 116+ 里，只要元素上出现 `scrollbar-width` / `scrollbar-color` 的非 auto 值，
     `::-webkit-scrollbar-*` 全部失效（标准属性优先）。所以两套写法必须互斥：
       默认（Firefox）用标准属性；支持 webkit 伪元素的引擎里先把它们重置回 auto，再写伪元素样式。
     写成"两套并存"的结果是 Chrome 里悄悄退化成原生 Fluent 滚动条（默认半透明、悬停才显形），
     表现为"看不见滚动条 / 鼠标一进就变粗"，而且控制台零报错。 */
:is(.fl-scroll, .fl-page, .fl-nav) {
  scrollbar-width: thin;
  scrollbar-color: var(--fl-control-strong-fill) transparent;
}

@supports selector(::-webkit-scrollbar) {
  :is(.fl-scroll, .fl-page, .fl-nav) { scrollbar-width: auto; scrollbar-color: auto; }  /* 让位给下面的伪元素写法 */
  :is(.fl-scroll, .fl-page, .fl-nav)::-webkit-scrollbar { width: 12px; height: 12px; }
  :is(.fl-scroll, .fl-page, .fl-nav)::-webkit-scrollbar-track,
  :is(.fl-scroll, .fl-page, .fl-nav)::-webkit-scrollbar-corner { background: transparent; }
  :is(.fl-scroll, .fl-page, .fl-nav)::-webkit-scrollbar-button { display: none; }  /* 去掉上下箭头与双箭头 */
  :is(.fl-scroll, .fl-page, .fl-nav)::-webkit-scrollbar-thumb {
    /* 颜色直接用 ControlStrongFillColorDefault（暗 55% 白 / 亮 45% 黑）：
       再往上混透明等于自己把对比度稀释掉，Acrylic 底上直接消失 */
    background: var(--fl-control-strong-fill);
    background-clip: content-box;
    border: 3px solid transparent;      /* 12 - 3×2 = 视觉 6px */
    border-radius: 999px;
    min-height: 28px;
  }
  /* 只认「指针落在 thumb 上」。容器 hover 一定不能写，见上方注释。
     ⚠ 悬停态的规则会**整体接管**该部件的绘制（不是常规层叠）：这里必须把
       `background-clip` 与**完整的 border 简写**再写一遍。
       只写 `border-width: 2px` 是无效的 —— 没有 border-style 就等于没有边框，
       thumb 会回弹成整个 12px 命中区（实测 6px → 12px），这是「悬停突然变粗」的真因。 */
  :is(.fl-scroll, .fl-page, .fl-nav)::-webkit-scrollbar-thumb:hover,
  :is(.fl-scroll, .fl-page, .fl-nav)::-webkit-scrollbar-thumb:active {
    background: var(--fl-text-secondary);   /* 暗 77% 白 / 亮 62% 黑，再深一档 */
    background-clip: content-box;
    border: 2px solid transparent;          /* 12 - 2×2 = 视觉 8px */
  }
}

/* ---- ComboBox（自绘）----
   为什么自绘：原生 <select> 的 <option> 面板由操作系统绘制，暗色主题下会漏白底、
   且无法承载 hover/selected 状态与开合动画。`<select class="fl-select">` 仅作无 JS 回退保留。
   闭合态几何同 TextBox：高 32、padding 10,5,6,6、圆角 4、底边加重；
   箭头 12×12（DropDownGlyph），距右缘 14（Margin 0,0,14,0）。
   弹层：Acrylic + elevation 32 + 圆角 8（OverlayCornerRadius）+ 描边 2（ComboBoxPopupBorderThemeThickness）、
        min-width 80、最大高 504（15 项一屏）；项高 32、圆角 3（ComboBoxItemCornerRadius）、
        选中胶囊圆角 1.5（ComboBoxItemPillCornerRadius）。
   开合复用 .fl-overlay（opacity 83ms + 位移 8px + 缩放 .98）：官方 XAML 里没有 popup 时长，
   按 motion 的 Consistent 规则"同一入口的表面以相同方式开合"，与 flyout/dialog 同档。 */
.fl-combo { position: relative; display: inline-block; min-width: var(--fl-combo-min-width); }

.fl-combo-btn {
  display: inline-flex; align-items: center; justify-content: space-between; gap: var(--fl-space-2);
  width: 100%; min-height: var(--fl-control-height);
  padding: var(--fl-text-pad-t) var(--fl-combo-glyph-gap) var(--fl-text-pad-b) var(--fl-text-pad-l);
  border-radius: var(--fl-radius-control);
  border: var(--fl-stroke) solid var(--fl-control-stroke);
  border-bottom-color: var(--fl-control-strong-fill);
  background: var(--fl-control-fill-default);
  color: var(--fl-text-primary); font: inherit; text-align: left; cursor: pointer;
  transition: background var(--fl-dur-control-faster) var(--fl-ease-standard),
              border-color var(--fl-dur-control-faster) var(--fl-ease-standard);
}
.fl-combo-btn:hover { background: var(--fl-control-fill-secondary); }
.fl-combo-btn:active { background: var(--fl-control-fill-tertiary); }
/* 展开态：底边转 accent（官方 ComboBox 聚焦/展开的底边高亮） */
.fl-combo-btn[aria-expanded="true"] {
  background: var(--fl-control-fill-secondary);
  border-bottom-color: var(--fl-accent-fill);
}
.fl-combo-value { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fl-combo-chevron {
  width: var(--fl-combo-glyph); height: var(--fl-combo-glyph); flex-shrink: 0;
  fill: none; stroke: var(--fl-text-secondary); stroke-width: 1.5px; stroke-linecap: round;
  transition: transform var(--fl-dur-control-faster) var(--fl-ease-standard);
}
.fl-combo-btn[aria-expanded="true"] .fl-combo-chevron { transform: rotate(180deg); }

/* 弹层：必须 position:fixed 且由 JS portal 到 body —— .fl-content-layer 有 overflow:clip（R26 强制），
   留在页内会被裁掉。任何情况下都不要给它加 transition: top/left（每帧 layout，是新的抖动源）。 */
.fl-combo-popup {
  position: fixed; z-index: 40;
  min-width: var(--fl-combo-popup-min-width);
  /* 宽度上限：不写的话 nowrap 的长选项会把弹层撑到视口外，右侧滚动条直接被窗口裁掉
     （看起来就是"没有滚动条"）。左右各留 8px，保证圆角与阴影不被切。 */
  max-width: calc(100vw - var(--fl-space-4));
  max-height: var(--fl-combo-max-h);
  overflow-y: auto;
  overscroll-behavior: contain;   /* 滚到弹层尽头不要穿透到页面 */
  padding: var(--fl-space-1);
  background: var(--fl-acrylic-bg);
  -webkit-backdrop-filter: blur(60px) saturate(125%);
  backdrop-filter: blur(60px) saturate(125%);
  border: var(--fl-combo-popup-stroke) solid var(--fl-card-stroke);
  border-radius: var(--fl-radius-overlay);
  box-shadow: var(--fl-shadow-flyout);
}

.fl-combo-item {
  position: relative;
  display: flex; align-items: center; gap: var(--fl-space-2);
  min-height: var(--fl-control-height);
  padding: 0 var(--fl-space-3);
  border-radius: var(--fl-radius-combo-item);
  cursor: pointer;
  /* 不折行：折行会让 4 个选项的弹层也超出高度、凭空长出一条滚动条；
     超长文字走省略号（配合弹层的 max-width），否则 nowrap 会把弹层撑到视口外 */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background var(--fl-dur-control-faster) var(--fl-ease-standard);
}
/* 键盘高亮用 data-active（与鼠标 hover 同档视觉，但两者互不干扰） */
.fl-combo-item:hover,
.fl-combo-item[data-active="true"] { background: var(--fl-subtle-fill-hover); }
.fl-combo-item[aria-selected="true"] { background: var(--fl-subtle-fill-hover); }
.fl-combo-item[aria-selected="true"]::before {
  content: ""; position: absolute; left: 0; top: 50%;
  width: var(--fl-nav-indicator-w); height: var(--fl-nav-indicator-h);
  margin-top: calc(var(--fl-nav-indicator-h) / -2);
  border-radius: var(--fl-radius-combo-pill); background: var(--fl-accent-fill);
}
.fl-combo-item[aria-selected="true"]:hover,
.fl-combo-item[aria-selected="true"][data-active="true"] { background: var(--fl-subtle-fill-pressed); }
.fl-combo-item[aria-disabled="true"] { opacity: 0.3; cursor: default; }
.fl-combo-item[aria-disabled="true"]:hover { background: transparent; }
/* 按下态：关掉 UA 高亮之后，只有 hover 的类会「点下去完全没反应」——
   档位与 .fl-btn-subtle / .fl-listitem / .fl-settings-row 一致（不引入新语义） */
.fl-combo-item:not([aria-disabled="true"]):active { background: var(--fl-subtle-fill-pressed); }
/* 已选中的项在六档语义里整体上移一档（hover 已是 pressed 档），所以按下回到 hover 档；
   照抄 .fl-listitem[aria-selected="true"]:active —— 否则按下反而变淡，像被取消选中 */
.fl-combo-item[aria-selected="true"]:active { background: var(--fl-subtle-fill-hover); }

/* ---- Acrylic 浮层（flyout / contextmenu 模块）----
   官方：Acrylic 只用于瞬态轻触消失表面；elevation 32；圆角 8 */
.fl-flyout {
  position: absolute; min-width: 160px;
  background: var(--fl-acrylic-bg);
  -webkit-backdrop-filter: blur(60px) saturate(125%); /* Acrylic 网页近似 */
  backdrop-filter: blur(60px) saturate(125%);
  border: var(--fl-stroke) solid var(--fl-card-stroke);
  border-radius: var(--fl-radius-overlay);
  box-shadow: var(--fl-shadow-flyout);
  padding: var(--fl-space-1);
  z-index: 30;
}
.fl-flyout-item {
  display: block; width: 100%; text-align: left;
  min-height: var(--fl-control-height); padding: 0 var(--fl-space-3);
  border: 0; background: transparent; color: var(--fl-text-primary);
  font: inherit; border-radius: var(--fl-radius-control); cursor: pointer;
  transition: background var(--fl-dur-fast) var(--fl-ease-standard);
}
.fl-flyout-item:hover { background: var(--fl-subtle-fill-hover); }
/* 按下态（菜单项的 hover 档是 subtle-hover，按下压到 pressed，和列表行同一语义） */
.fl-flyout-item:active { background: var(--fl-subtle-fill-pressed); }

/* ---- ContentDialog（dialog 模块）----
   官方：Padding 24、MaxWidth 548、MinHeight 184；Smoke 遮罩；elevation 128；圆角 8 */
.fl-dialog {
  width: min(548px, calc(100vw - var(--fl-space-12)));
  min-height: 184px;
  background: var(--fl-solid-bg-secondary);
  border: var(--fl-stroke) solid var(--fl-card-stroke);
  border-radius: var(--fl-radius-overlay);
  box-shadow: var(--fl-shadow-dialog);
  padding: var(--fl-space-6);
  position: fixed; left: 50%; top: 50%;
  translate: -50% -50%; /* 居中用独立 translate 属性：transform 留给 .fl-overlay 的开合动效，两者互不覆盖 */
  z-index: 50;
}
/* 回退：不支持 translate 属性的浏览器改用 transform 居中（此时需显式把打开态摆正） */
@supports not (translate: -50% -50%) {
  .fl-dialog { transform: translate(-50%, -50%); } /* fl-lint-ignore */
  .fl-dialog.fl-overlay.fl-open { transform: translate(-50%, -50%); } /* fl-lint-ignore */
  .fl-dialog.fl-overlay:not(.fl-open) { transform: translate(-50%, calc(-50% + 8px)) scale(0.98); } /* fl-lint-ignore */
}
.fl-dialog-title { margin: 0 0 var(--fl-space-3); }
.fl-dialog-actions { display: flex; gap: var(--fl-space-2); justify-content: flex-end; margin-top: var(--fl-space-6); }
.fl-smoke-backdrop { position: fixed; inset: 0; background: var(--fl-smoke); z-index: 40; }

/* ---- InfoBar（infobar 模块）---- */
.fl-infobar {
  display: flex; align-items: flex-start; gap: var(--fl-space-3);
  padding: var(--fl-space-3) var(--fl-space-4);
  border-radius: var(--fl-radius-control);
  background: var(--fl-card-bg); border: var(--fl-stroke) solid var(--fl-card-stroke);
}
.fl-infobar[data-severity="success"] { border-left: calc(var(--fl-space-1) - 1px) solid var(--fl-success); }
.fl-infobar[data-severity="caution"] { border-left: calc(var(--fl-space-1) - 1px) solid var(--fl-caution); }
.fl-infobar[data-severity="critical"] { border-left: calc(var(--fl-space-1) - 1px) solid var(--fl-critical); }

/* ---- 命令栏（toolbar 模块）：核心高频命令在画布，其余收进命令栏 ---- */
.fl-toolbar { display: flex; align-items: center; gap: var(--fl-space-2); padding: var(--fl-space-2) 0; }

/* ---- 主题切换 ---- */
[data-theme="dark"] .fl-only-light { display: none; }
[data-theme="light"] .fl-only-dark { display: none; }

/* 页面容器：转场由 fluent2-motion.js 控制（禁直接切类，检查器规则 6）
   所有页面占同一网格单元 → 转场期新旧页重叠而非上下堆叠，不产生布局跳变 */
.fl-page {
  grid-area: 1 / 1;
  align-self: stretch; min-height: 0;
  padding: var(--fl-space-4);
  overflow-y: auto; overflow-x: hidden;   /* 每个页面各自滚，切页各记各的位置 */
  scrollbar-gutter: stable;               /* 有无滚动条都留位，切页时内容不横移 */
}
/* 页面保持透明：转场是「旧页淡出退场 → 新页滑入」两拍（见 fluent2-motion.css）。
   涂不透明底会变成"整块面板压过去"的硬边擦除，和 Win11 录屏不一样。 */
.fl-page:not(.fl-current):not(.fl-page-leaving) { display: none; }
.fl-page-leaving { pointer-events: none; } /* 离场页不拦截新页的点击 */
