@mooncellwiki/prts-design-css 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -0
  3. package/dist/prts-design.css +6762 -0
  4. package/dist/prts-design.min.css +2 -0
  5. package/package.json +55 -0
  6. package/src/arknights/archive.css +21 -0
  7. package/src/arknights/attrs.css +11 -0
  8. package/src/arknights/camp.css +8 -0
  9. package/src/arknights/dialogue.css +7 -0
  10. package/src/arknights/dossier.css +13 -0
  11. package/src/arknights/elite.css +5 -0
  12. package/src/arknights/enemy.css +12 -0
  13. package/src/arknights/event.css +14 -0
  14. package/src/arknights/hero.css +11 -0
  15. package/src/arknights/index.css +41 -0
  16. package/src/arknights/item.css +32 -0
  17. package/src/arknights/kv.css +15 -0
  18. package/src/arknights/level.css +9 -0
  19. package/src/arknights/materials.css +6 -0
  20. package/src/arknights/module.css +49 -0
  21. package/src/arknights/news.css +6 -0
  22. package/src/arknights/op-card.css +26 -0
  23. package/src/arknights/op-row.css +6 -0
  24. package/src/arknights/phase-tabs.css +8 -0
  25. package/src/arknights/pot-list.css +7 -0
  26. package/src/arknights/potential.css +4 -0
  27. package/src/arknights/profession.css +16 -0
  28. package/src/arknights/range.css +10 -0
  29. package/src/arknights/rarity.css +21 -0
  30. package/src/arknights/rich-text.css +18 -0
  31. package/src/arknights/skill-levels.css +13 -0
  32. package/src/arknights/skill-matrix.css +25 -0
  33. package/src/arknights/skill-sheet.css +30 -0
  34. package/src/arknights/skill.css +28 -0
  35. package/src/arknights/sp.css +15 -0
  36. package/src/arknights/stage.css +22 -0
  37. package/src/arknights/table-numerals.css +7 -0
  38. package/src/arknights/talent-table.css +30 -0
  39. package/src/arknights/talent.css +7 -0
  40. package/src/arknights/trust.css +4 -0
  41. package/src/arknights/voice.css +21 -0
  42. package/src/base/catlinks.css +64 -0
  43. package/src/base/collapsible.css +10 -0
  44. package/src/base/forms.css +121 -0
  45. package/src/base/index.css +20 -0
  46. package/src/base/media.css +26 -0
  47. package/src/base/notices.css +17 -0
  48. package/src/base/print.css +11 -0
  49. package/src/base/references.css +9 -0
  50. package/src/base/root.css +16 -0
  51. package/src/base/special-pages.css +43 -0
  52. package/src/base/tabber.css +31 -0
  53. package/src/base/tables.css +45 -0
  54. package/src/base/toc.css +19 -0
  55. package/src/base/typography.css +133 -0
  56. package/src/bridge-codex.css +98 -0
  57. package/src/chrome/body.css +13 -0
  58. package/src/chrome/footer.css +34 -0
  59. package/src/chrome/header.css +104 -0
  60. package/src/chrome/index.css +29 -0
  61. package/src/chrome/keyart.css +15 -0
  62. package/src/chrome/layout.css +15 -0
  63. package/src/chrome/local-nav.css +17 -0
  64. package/src/chrome/page-header.css +68 -0
  65. package/src/chrome/responsive.css +127 -0
  66. package/src/chrome/search-palette.css +121 -0
  67. package/src/chrome/shell.css +4 -0
  68. package/src/chrome/sidebar-tree.css +36 -0
  69. package/src/chrome/sidebar.css +39 -0
  70. package/src/chrome/special-pages.css +4 -0
  71. package/src/chrome/theme-toggle.css +10 -0
  72. package/src/chrome/toc.css +38 -0
  73. package/src/components/accordion.css +10 -0
  74. package/src/components/avatar.css +8 -0
  75. package/src/components/badge.css +16 -0
  76. package/src/components/breadcrumb.css +7 -0
  77. package/src/components/button.css +45 -0
  78. package/src/components/card.css +28 -0
  79. package/src/components/cbox.css +18 -0
  80. package/src/components/chip.css +9 -0
  81. package/src/components/dialog.css +14 -0
  82. package/src/components/divider.css +8 -0
  83. package/src/components/dropdown.css +30 -0
  84. package/src/components/empty.css +5 -0
  85. package/src/components/fab.css +9 -0
  86. package/src/components/form.css +66 -0
  87. package/src/components/heading.css +11 -0
  88. package/src/components/index.css +38 -0
  89. package/src/components/keyframes.css +14 -0
  90. package/src/components/message.css +21 -0
  91. package/src/components/pagination.css +11 -0
  92. package/src/components/panel.css +15 -0
  93. package/src/components/progress.css +19 -0
  94. package/src/components/skeleton.css +5 -0
  95. package/src/components/spinner.css +23 -0
  96. package/src/components/stat.css +12 -0
  97. package/src/components/stepper.css +14 -0
  98. package/src/components/table.css +17 -0
  99. package/src/components/tabs.css +29 -0
  100. package/src/components/tag.css +26 -0
  101. package/src/components/timeline.css +13 -0
  102. package/src/components/title-reset.css +8 -0
  103. package/src/components/toast.css +14 -0
  104. package/src/components/tooltip.css +31 -0
  105. package/src/decor/bilingual.css +6 -0
  106. package/src/decor/brackets.css +6 -0
  107. package/src/decor/chevrons.css +5 -0
  108. package/src/decor/corner.css +12 -0
  109. package/src/decor/glyph.css +7 -0
  110. package/src/decor/halftone.css +13 -0
  111. package/src/decor/index.css +18 -0
  112. package/src/decor/inverse.css +4 -0
  113. package/src/decor/patterns.css +7 -0
  114. package/src/decor/stripes.css +10 -0
  115. package/src/decor/type.css +10 -0
  116. package/src/forced-colors.css +54 -0
  117. package/src/index.css +18 -0
  118. package/src/scope.css +120 -0
  119. package/src/search-palette.js +549 -0
  120. package/src/sidebar-tree.js +220 -0
  121. package/src/standalone.css +12 -0
  122. package/src/tokens.css +665 -0
  123. package/src/utilities.css +43 -0
@@ -0,0 +1,121 @@
1
+ /*! PRTS Design · chrome/search-palette.css — Search palette 悬浮搜索面板 · 依赖:tokens.css · components/ */
2
+ /* ═══ Search palette(悬浮搜索面板)═══
3
+ * 参考 Citizen 的 Command Palette(starcitizen.tools):搜索不再是页眉里的一条输入框,而是一块居中悬浮的「终端窗口」。
4
+ * 页眉里的 form.ak-header__search 在有 JS 时被 search-palette.js 换成 button.ak-search-trigger(长得像输入框),
5
+ * 真正的 <form id="searchform"> 被原样搬进面板顶部 —— #searchInput / action / hidden title 都还在,Gadget 与无 JS 提交不受影响。
6
+ * DOM(由 JS 生成,类名即契约):
7
+ * .ak-palette-backdrop
8
+ * .ak-palette[role=dialog]
9
+ * __head [ __back ] __icon [ __chip ] form.__form > input#searchInput [ __clear ] __close __loading
10
+ * __body > __viewport > __list[role=listbox] > __group[role=group] > __label + __item[role=option] > __link( __thumb __text( __title __desc ) __meta ) + __actions
11
+ * | __empty( __empty-title __empty-desc __shortcuts )
12
+ * __foot __foot-left __hints > span > kbd.ak-kbd
13
+ * 开:点触发器 / 手机图标 / 键 "/"、Ctrl(⌘)K、accesskey F。关:Esc(有字先清空)/ 点遮罩 / 关闭按钮 / 选中结果。
14
+ * 高亮:↑↓ 循环,回车打开;⇧回车全文搜索;结果未到时回车走 MW 原生 Go(精确跳转,无则全文)。 */
15
+ .ak-palette-backdrop { position: fixed; inset: 0; z-index: var(--ak-z-modal); background: var(--ak-bg-overlay); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); animation: ak-fade-in var(--ak-dur-normal) var(--ak-ease-out); }
16
+ .ak-palette { --_top: clamp(48px, 10vh, 120px); --_head-h: 56px; --_foot-h: 40px; position: fixed; z-index: calc(var(--ak-z-modal) + 1); top: var(--_top); left: 0; right: 0; margin-inline: auto; width: min(720px, calc(100vw - var(--ak-gutter) * 2)); max-height: calc(100vh - var(--_top) * 2);
17
+ display: flex; flex-direction: column; background: var(--ak-bg-surface); color: var(--ak-fg); border: 1px solid var(--ak-border); border-top-width: 3px; border-image: linear-gradient(var(--ak-accent) 3px, var(--ak-border) 3px) 3 1 1 1; box-shadow: var(--ak-shadow-lg); font-size: var(--ak-fs-sm); line-height: 1.4; animation: ak-palette-in var(--ak-dur-normal) var(--ak-ease-out); }
18
+ .ak-palette[hidden], .ak-palette-backdrop[hidden] { display: none !important; }
19
+ .ak-palette.is-closing { animation: ak-palette-out var(--ak-dur-fast) var(--ak-ease-in) forwards; pointer-events: none; }
20
+ .ak-palette-backdrop.is-closing { animation: ak-fade-out var(--ak-dur-fast) var(--ak-ease-in) forwards; }
21
+ @keyframes ak-palette-in { from { opacity: 0; transform: translateY(-8px); clip-path: inset(0 0 100% 0); } to { opacity: 1; transform: none; clip-path: inset(0 0 0 0); } }
22
+ @keyframes ak-palette-out { to { opacity: 0; transform: translateY(-6px); } }
23
+ @keyframes ak-fade-out { to { opacity: 0; } }
24
+ /* 头:图标 · [模式 chip] · 输入 · [清空] · 关闭 · 进度条 */
25
+ .ak-palette__head { position: relative; flex: none; display: flex; align-items: center; gap: 4px; height: var(--_head-h); padding-right: 10px; border-bottom: 1px solid var(--ak-border); }
26
+ .ak-palette__icon { flex: none; width: 20px; height: 20px; margin: 0 14px 0 18px; color: var(--ak-fg-muted); }
27
+ .ak-palette__back { display: none; flex: none; width: 32px; height: 32px; margin-left: 10px; padding: 0; border: 0; background: transparent; color: var(--ak-fg-secondary); cursor: pointer; place-items: center; }
28
+ .ak-palette__back:hover { background: var(--ak-bg-hover); color: var(--ak-fg); }
29
+ .ak-palette__back svg { width: 18px; height: 18px; }
30
+ .ak-palette.has-mode .ak-palette__back { display: grid; }
31
+ .ak-palette.has-mode .ak-palette__icon { margin-left: 4px; }
32
+ .ak-palette__chip { display: none; flex: none; align-items: center; height: 24px; margin-right: 6px; padding: 0 10px; background: var(--ak-accent); color: var(--ak-accent-fg); font: 700 var(--ak-fs-xs)/1 var(--ak-font-label); letter-spacing: .08em; text-transform: uppercase; } /* 模式标签:主色实底矩形块 */
33
+ .ak-palette.has-mode .ak-palette__chip { display: inline-flex; }
34
+ .ak-palette__form { flex: 1; min-width: 0; display: flex; align-items: center; margin: 0; }
35
+ .ak-palette__form input[type="search"], .ak-palette__form input[type="text"] { flex: 1; min-width: 0; height: var(--_head-h); margin: 0; padding: 0; border: 0; border-radius: 0; background: transparent; color: inherit; font: inherit; font-size: var(--ak-fs-body); line-height: var(--_head-h); outline: 0; box-shadow: none; appearance: none; -webkit-appearance: none; }
36
+ .ak-palette__form input::placeholder { color: var(--ak-fg-subtle); }
37
+ .ak-palette__form input::-webkit-search-cancel-button, .ak-palette__form input::-webkit-search-decoration { -webkit-appearance: none; display: none; }
38
+ .ak-palette__form button, .ak-palette__form .searchButton, .ak-palette__form .ak-search__icon, .ak-palette__form .ak-search__icon-wrap, .ak-palette__form .ak-search__kbd { display: none; } /* 表单自带的图标(皮肤里可能包在 label.ak-search__icon-wrap 里,给 #searchInput 当可见标签)/ 键帽 / 无 JS 提交按钮在面板里不需要 */
39
+ @supports (-webkit-touch-callout: none) { .ak-palette__form input[type="search"] { font-size: 16px; } } /* iOS Safari:≥16px 才不会聚焦时自动缩放页面 */
40
+ .ak-palette__clear, .ak-palette__close { flex: none; display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 28px; min-width: 28px; padding: 0 4px; border: 1px solid transparent; background: transparent; color: var(--ak-fg-muted); font: inherit; font-size: var(--ak-fs-xs); cursor: pointer; }
41
+ .ak-palette__clear:hover, .ak-palette__close:hover { color: var(--ak-fg); border-color: var(--ak-border-strong); }
42
+ .ak-palette__clear:focus-visible, .ak-palette__close:focus-visible, .ak-palette__back:focus-visible { outline: 2px solid var(--ak-focus); outline-offset: -2px; }
43
+ .ak-palette__clear { display: none; }
44
+ .ak-palette.has-query .ak-palette__clear { display: inline-flex; }
45
+ .ak-palette__clear svg { width: 16px; height: 16px; }
46
+ .ak-palette__close > span { display: none; } /* 桌面只显示 Esc 键帽;手机换成文字「取消」 */
47
+ .ak-palette__loading { position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: transparent; visibility: hidden; }
48
+ .ak-palette.is-loading .ak-palette__loading { visibility: visible; }
49
+ @media (forced-colors: active) { .ak-palette__loading { background: Canvas; } } /* 强制色下保留 forced-colors.css 给 .ak-progress 的 Canvas 轨道:骨架在它之后加载,上面同特指度的 transparent 会盖掉 */
50
+ /* 体:高度过渡容器(JS 用 ResizeObserver 把 __viewport 的高度写到 __body 上) */
51
+ .ak-palette__body { flex: 1 1 auto; min-height: 0; overflow: hidden; transition: height var(--ak-dur-normal) var(--ak-ease-out); }
52
+ .ak-palette__list { max-height: calc(100vh - var(--_top) * 2 - var(--_head-h) - var(--_foot-h) - 4px); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; margin: 0; padding: 6px 0; list-style: none; }
53
+ .ak-palette__list:empty { padding: 0; }
54
+ .ak-palette__group + .ak-palette__group { margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--ak-border-subtle); }
55
+ .ak-palette__group--tail { margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--ak-border-subtle); } /* 末尾固定的「全文搜索」 */
56
+ .ak-palette__label { display: flex; align-items: baseline; gap: 8px; padding: 8px 16px 4px; font: 700 var(--ak-fs-overline)/1 var(--ak-font-label); letter-spacing: var(--ak-tracking-overline); text-transform: uppercase; color: var(--ak-fg-muted); }
57
+ .ak-palette__label .ak-en { color: var(--ak-fg-subtle); font-size: 10px; letter-spacing: var(--ak-tracking-caps); }
58
+ .ak-palette__label small { margin-left: auto; font: 500 10px/1 var(--ak-font-mono); letter-spacing: 0; text-transform: none; color: var(--ak-fg-subtle); }
59
+ .ak-palette__item { position: relative; display: flex; align-items: stretch; margin: 0; }
60
+ .ak-palette__item::before { display: none !important; }
61
+ .ak-palette__link { flex: 1; min-width: 0; display: flex; align-items: center; gap: 12px; padding: 7px 16px 7px 14px; border: 0; border-left: 2px solid transparent; background: transparent; color: inherit; font: inherit; text-align: left; text-decoration: none; cursor: pointer; }
62
+ .ak-palette__link:hover, .ak-palette__link:visited { color: inherit; text-decoration: none; }
63
+ .ak-palette__item.is-active { background: var(--ak-accent-subtle); } /* 淡青底铺满整行(含右侧动作列) */
64
+ .ak-palette__item.is-active > .ak-palette__link { border-left-color: var(--ak-accent); } /* 左 2px 青条:与侧栏当前项 / 菜单项同一套语言 */
65
+ .ak-palette__item.is-active .ak-palette__title { color: var(--ak-fg); }
66
+ .ak-palette__thumb { flex: none; width: 40px; height: 40px; display: grid; place-items: center; overflow: hidden; background: var(--ak-bg-surface-3); border: 1px solid var(--ak-border); color: var(--ak-fg-muted); }
67
+ .ak-palette__thumb > img { width: 100%; height: 100%; object-fit: cover; display: block; }
68
+ .ak-palette__thumb > svg { width: 20px; height: 20px; }
69
+ .ak-palette__thumb--icon { background: var(--ak-bg-surface-2); }
70
+ .ak-palette__thumb--dark { background: #1d1f20; border-color: #1d1f20; color: #fff; } /* 命令 / 全文搜索:深底白线稿(.ak-glyph-box) */
71
+ .ak-palette__thumb--mono { font: 700 15px/1 var(--ak-font-mono); }
72
+ .ak-palette__thumb--sm { width: 32px; height: 32px; }
73
+ .ak-palette__text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
74
+ .ak-palette__title { display: flex; align-items: baseline; gap: 8px; min-width: 0; font-size: var(--ak-fs-body); font-weight: 600; color: var(--ak-fg); }
75
+ .ak-palette__title > bdi { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
76
+ .ak-palette__title mark { background: none; color: inherit; font-weight: 400; } /* Codex 约定:已输入部分常规、补全部分加粗 */
77
+ .ak-palette__title .ak-en { flex: none; font-size: 10px; font-weight: 700; color: var(--ak-fg-subtle); }
78
+ .ak-palette__desc { font-size: var(--ak-fs-xs); color: var(--ak-fg-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
79
+ .ak-palette__desc .ak-icon { width: 12px; height: 12px; vertical-align: -2px; margin-right: 3px; }
80
+ .ak-palette__meta { flex: none; display: flex; align-items: center; gap: 8px; margin-left: 4px; color: var(--ak-fg-muted); font-size: var(--ak-fs-xs); white-space: nowrap; }
81
+ .ak-palette__meta .ak-prof { --_s: 22px; }
82
+ .ak-palette__meta .ak-rarity { font-size: 11px; }
83
+ .ak-palette__meta .ak-kbd { color: var(--ak-fg-muted); }
84
+ /* 行内动作(目前只有最近访问的「移除 ×」):始终占位、非高亮时不可见 —— 同组每行宽度一致,高亮时右侧元数据不会跳 */
85
+ .ak-palette__actions { flex: none; display: flex; align-items: center; gap: 2px; padding-right: 8px; visibility: hidden; }
86
+ .ak-palette__item.is-active > .ak-palette__actions, .ak-palette__item:focus-within > .ak-palette__actions { visibility: visible; }
87
+ .ak-palette__action { display: grid; place-items: center; width: 28px; height: 28px; padding: 0; border: 1px solid transparent; background: transparent; color: var(--ak-fg-muted); cursor: pointer; }
88
+ .ak-palette__action:hover, .ak-palette__action:focus-visible { border-color: var(--ak-border-strong); color: var(--ak-fg); outline: 0; }
89
+ .ak-palette__action svg { width: 14px; height: 14px; }
90
+ /* 空态:提示 + 快捷入口 */
91
+ .ak-palette__empty { padding: 20px 0 14px; }
92
+ .ak-palette__empty--compact { padding: 4px 0 12px; border-top: 1px solid var(--ak-border-subtle); } /* 最近访问下方:只剩快捷入口 */
93
+ .ak-palette__empty-title { margin: 0 20px 6px; font-size: var(--ak-fs-body); font-weight: 700; }
94
+ .ak-palette__empty-desc { margin: 0 20px 10px; color: var(--ak-fg-muted); }
95
+ .ak-palette__empty-desc .ak-kbd { margin: 0 2px; }
96
+ .ak-palette__shortcuts { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 16px 0; }
97
+ .ak-palette__shortcut { display: inline-flex; align-items: center; height: 28px; padding: 0 12px; border: 1px solid var(--ak-border-strong); color: var(--ak-fg-secondary); font-size: var(--ak-fs-xs); font-weight: 500; text-decoration: none; }
98
+ .ak-palette__shortcut:hover { border-color: var(--ak-accent); color: var(--ak-accent); text-decoration: none; }
99
+ .ak-palette__notice { padding: 14px 16px; color: var(--ak-fg-muted); }
100
+ .ak-palette__notice--error { color: var(--ak-danger); }
101
+ /* 脚:左说明 · 右快捷键 */
102
+ .ak-palette__foot { flex: none; display: flex; align-items: center; gap: 12px; height: var(--_foot-h); padding: 0 12px 0 16px; border-top: 1px solid var(--ak-border); background: var(--ak-bg-surface-2); color: var(--ak-fg-muted); font-size: var(--ak-fs-xs); }
103
+ .ak-palette__foot-left { flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px; overflow: hidden; white-space: nowrap; }
104
+ .ak-palette__foot-left .ak-en { color: var(--ak-fg-subtle); font-size: 10px; }
105
+ .ak-palette__foot-btn { display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 6px; border: 0; background: transparent; color: var(--ak-fg-muted); font: inherit; font-size: var(--ak-fs-xs); cursor: pointer; }
106
+ .ak-palette__foot-btn:hover { color: var(--ak-fg); }
107
+ .ak-palette__hints { display: flex; align-items: center; gap: 12px; margin-left: auto; white-space: nowrap; }
108
+ .ak-palette__hints > span { display: inline-flex; align-items: center; gap: 4px; }
109
+ .ak-palette__hints .ak-kbd { color: var(--ak-fg-muted); }
110
+ .ak-palette__live { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
111
+ @media (hover: none) and (pointer: coarse) { .ak-palette__hints { display: none; } } /* 触屏不显示键盘提示 */
112
+ @media (max-width: 639px) {
113
+ .ak-palette { --_top: 8px; left: 8px; right: 8px; width: auto; max-height: calc(100dvh - 16px); }
114
+ .ak-palette__list { max-height: calc(100dvh - 16px - var(--_head-h) - var(--_foot-h) - 4px); }
115
+ .ak-palette__icon { margin: 0 10px 0 14px; }
116
+ .ak-palette__close .ak-kbd { display: none; }
117
+ .ak-palette__close > span { display: inline; }
118
+ .ak-palette__meta .ak-tag, .ak-palette__title .ak-en { display: none; } /* 窄行:省掉类型标签与英文副标 */
119
+ .ak-palette__foot-left .ak-en { display: none; }
120
+ }
121
+ @media (prefers-reduced-motion: reduce) { .ak-palette, .ak-palette-backdrop, .ak-palette.is-closing, .ak-palette-backdrop.is-closing { animation: none; } .ak-palette__body { transition: none; } }
@@ -0,0 +1,4 @@
1
+ /*! PRTS Design · chrome/shell.css — body.skin-arknights / .ak-skip 跳转链接(.ak-sr-only 在 utilities.css:组件也用它) · 依赖:tokens.css · components/ */
2
+ body.skin-arknights { margin: 0; min-height: 100vh; display: flex; flex-direction: column; }
3
+ .ak-skip { position: absolute; left: 8px; top: 8px; z-index: 9999; background: var(--ak-accent); color: var(--ak-accent-fg); padding: 8px 12px; font-weight: 700; line-height: 1.3; transform: translateY(calc(-100% - 12px)); } /* 完全移出视口(此前 top:-40px 会在页眉顶部露出一条青色边) */
4
+ .ak-skip:focus { transform: none; }
@@ -0,0 +1,36 @@
1
+ /*! PRTS Design · chrome/sidebar-tree.css — Sidebar tree 多层展开 · 悬停飞出 · 依赖:tokens.css · components/ */
2
+ /* ── Sidebar tree(多层展开) ── */
3
+ .ak-tree__branch > .ak-tree__label { padding-right: 32px; }
4
+ .ak-tree__branch > b.ak-tree__label, .ak-tree__branch > span.ak-tree__label { font-weight: 600; color: var(--ak-fg-secondary); }
5
+ .ak-tree__branch.is-open > .ak-tree__label, .ak-tree__branch.is-current-path > .ak-tree__label { color: var(--ak-fg); }
6
+ .ak-tree__branch.is-current-path > .ak-tree__label { border-left-color: var(--ak-accent-muted); }
7
+ .ak-tree__toggle { position: absolute; top: 0; right: 0; width: 32px; height: 30px; margin: 0; padding: 0; border: 0; background: transparent; color: var(--ak-fg-muted); cursor: pointer; display: grid; place-items: center; }
8
+ .ak-tree__toggle::before { content: ""; width: 6px; height: 6px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translate(-1px, 0) rotate(-45deg); transition: transform var(--ak-dur-fast) var(--ak-ease); }
9
+ .ak-tree__branch.is-open > .ak-tree__toggle::before { transform: translate(0, -1px) rotate(45deg); }
10
+ .ak-tree__toggle:hover, .ak-tree__branch.is-current-path > .ak-tree__toggle { color: var(--ak-accent); }
11
+ .ak-tree__toggle:focus-visible { outline: 2px solid var(--ak-accent); outline-offset: -2px; }
12
+ .ak-sidebar li > ul { display: none; position: relative; margin: 0 0 4px; padding-left: 12px; }
13
+ .ak-sidebar li > ul::before { content: ""; position: absolute; left: 11px; top: 2px; bottom: 2px; border-left: 1px solid var(--ak-border); } /* 缩进导轨 */
14
+ .ak-tree__branch.is-current-path > ul::before { border-left-color: var(--ak-accent-muted); }
15
+ .ak-tree__branch.is-open > ul { display: block; animation: ak-tree-in var(--ak-dur-fast) var(--ak-ease); }
16
+ .ak-sidebar li li > a, .ak-sidebar li li > b, .ak-sidebar li li > .ak-tree__label { padding-top: 5px; padding-bottom: 5px; font-size: calc(var(--ak-fs-sm) - 1px); }
17
+ .ak-sidebar li li li > a, .ak-sidebar li li li > b, .ak-sidebar li li li > .ak-tree__label { color: var(--ak-fg-muted); }
18
+ .ak-sidebar li li li > a:hover, .ak-sidebar li li li > b:hover { color: var(--ak-fg); }
19
+ @keyframes ak-tree-in { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
20
+ @media (prefers-reduced-motion: reduce) { .ak-tree__branch.is-open > ul { animation: none; } .ak-tree__toggle::before, .ak-portlet--collapsible > .ak-portlet__title::after { transition: none; } }
21
+ /* 桌面悬停飞出(peek):由 sidebar-tree.js 生成到 body 下,position:fixed 不受侧栏 overflow 裁切 */
22
+ .ak-flyout { position: fixed; z-index: var(--ak-z-dropdown); min-width: 184px; max-width: 300px; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; background: var(--ak-bg-surface); border: 1px solid var(--ak-border); border-left-width: 2px; border-image: linear-gradient(to right, var(--ak-accent) 2px, var(--ak-border) 2px) 1 1 1 2; box-shadow: var(--ak-shadow-lg); padding: 4px 0 6px; font-size: var(--ak-fs-sm); animation: ak-flyout-in var(--ak-dur-fast) var(--ak-ease); }
23
+ @keyframes ak-flyout-in { from { opacity: 0; transform: translateX(-4px); } to { opacity: 1; transform: none; } }
24
+ .ak-flyout__title { padding: 6px 14px 4px; font: 700 var(--ak-fs-overline)/1 var(--ak-font-label); letter-spacing: var(--ak-tracking-overline); text-transform: uppercase; color: var(--ak-fg-subtle); }
25
+ .ak-flyout ul { list-style: none; margin: 0; padding: 0; }
26
+ .ak-flyout li::before { display: none !important; }
27
+ .ak-flyout li > a, .ak-flyout li > b, .ak-flyout li > .ak-tree__label { display: flex; align-items: center; gap: 8px; padding: 6px 14px; color: var(--ak-fg-secondary); font-weight: 400; text-decoration: none; border-left: 2px solid transparent; white-space: nowrap; cursor: pointer; }
28
+ .ak-flyout li > b, .ak-flyout li > span.ak-tree__label { font-weight: 600; color: var(--ak-fg); cursor: default; }
29
+ .ak-flyout li > a:hover { color: var(--ak-fg); background: var(--ak-bg-hover); border-left-color: var(--ak-accent); text-decoration: none; }
30
+ .ak-flyout li.is-current > a, .ak-flyout a.selflink, .ak-flyout a.mw-selflink { color: var(--ak-accent); font-weight: 700; }
31
+ .ak-flyout li > ul { display: block; padding-left: 12px; }
32
+ .ak-flyout a.external { background: none; padding-right: 14px; }
33
+ .ak-flyout .ak-tree__toggle { display: none; }
34
+ @media (prefers-reduced-motion: reduce) { .ak-flyout { animation: none; } }
35
+
36
+ .ak-sidebar__foot { font-size: var(--ak-fs-xs); color: var(--ak-fg-subtle); padding: var(--ak-space-3) 10px; border-top: 1px solid var(--ak-border); margin-top: var(--ak-space-5); }
@@ -0,0 +1,39 @@
1
+ /*! PRTS Design · chrome/sidebar.css — Sidebar 侧栏 · 依赖:tokens.css · components/ */
2
+ /* ═══ Sidebar ═══
3
+ * 内容来源两种都支持(见文档站 /guide/skin-template#侧栏与-menusidebar):
4
+ * a) MediaWiki:Sidebar 门户 → .ak-portlet > h3.ak-portlet__title + ul
5
+ * b) PRTS #MenuSidebar 原始 wikitext 树 → p(分组标题)+ ul > li > (a|b) [+ ul …任意深度]
6
+ * 多层展开由 sidebar-tree.js 增强:li.ak-tree__branch(.is-open) > .ak-tree__label + button.ak-tree__toggle + ul.ak-tree__list
7
+ */
8
+ .ak-sidebar { position: sticky; top: calc(var(--ak-header-h) + var(--ak-space-6)); max-height: calc(100vh - var(--ak-header-h) - var(--ak-space-6)); overflow-y: auto; overscroll-behavior: contain; font-size: var(--ak-fs-sm); scrollbar-width: thin; padding-right: 4px; }
9
+ .ak-sidebar__panel { display: block; }
10
+ .ak-portlet { margin-bottom: var(--ak-space-5); }
11
+ /* 分组标题:门户 h3 / MW 原生 heading / 原始 p */
12
+ .ak-portlet__title, .ak-sidebar .vector-menu-heading, .ak-sidebar h3, .ak-sidebar p { font: 700 var(--ak-fs-overline)/1 var(--ak-font-label); letter-spacing: var(--ak-tracking-overline); text-transform: uppercase; color: var(--ak-fg-muted); margin: 0 0 6px; padding: 0 0 6px 10px; border-left: 2px solid var(--ak-theme-accent); display: flex; align-items: center; gap: 6px; } /* 分组条用活动主色(--ak-theme-accent):活动主题换色时侧栏跟着换,当前项 / 链接仍是 --ak-accent */
13
+ .ak-sidebar ul + p, .ak-sidebar ul + h3, .ak-sidebar div + p { margin-top: var(--ak-space-5); }
14
+ .ak-sidebar p:empty, .ak-sidebar li.mw-empty-elt, .ak-sidebar li:empty { display: none; }
15
+ .ak-portlet ul, .ak-sidebar ul { list-style: none; margin: 0; padding: 0; }
16
+ .ak-portlet li::before, .ak-sidebar li::before { display: none !important; }
17
+ .ak-sidebar li { position: relative; }
18
+ /* 行:链接 a / 非链接标签 b(PRTS 用粗体 b 表示有子级的分组项) */
19
+ .ak-portlet li a, .ak-sidebar li a, .ak-sidebar li > b, .ak-sidebar li > span, .ak-sidebar li > .ak-tree__label { display: flex; align-items: center; gap: 8px; padding: 6px 10px; color: var(--ak-fg-secondary); font-weight: 400; text-decoration: none; border-left: 2px solid transparent; line-height: 1.4; transition: color var(--ak-dur-fast), background var(--ak-dur-fast), border-color var(--ak-dur-fast); cursor: pointer; } /* 1.4:行高 = 6 + 20 + 6 = 32,与 .ak-tree__toggle 的 30px 对得齐;正文的 1.7 会把行撑到 34 */
20
+ .ak-portlet li a:hover, .ak-sidebar li a:hover, .ak-sidebar li > b:hover, .ak-sidebar li > span:hover, .ak-sidebar .ak-tree__branch.is-peek > .ak-tree__label { color: var(--ak-fg); background: var(--ak-bg-hover); border-left-color: var(--ak-border-strong); text-decoration: none; }
21
+ .ak-portlet li.is-active > a, .ak-portlet li.selected > a, .ak-sidebar li.is-active > a, .ak-sidebar li.selected > a, .ak-sidebar li.is-current > a, .ak-sidebar a.selflink, .ak-sidebar a.mw-selflink { color: var(--ak-accent); border-left-color: var(--ak-accent); font-weight: 700; background: var(--ak-accent-subtle); }
22
+ .ak-sidebar a.selflink, .ak-sidebar a.mw-selflink { cursor: default; }
23
+ .ak-sidebar a.external { background: none; padding-right: 10px; } /* 去掉 MW 外链图标 */
24
+ .ak-sidebar li > a.new { color: var(--ak-link-new); } /* MW 红链 */
25
+ .ak-sidebar li > span:not(.ak-tree__label) { flex-wrap: wrap; cursor: default; } /* 非链接行(Widget 渲染成 <span>):里面可以夹行内链接 */
26
+ .ak-sidebar li > span:not(.ak-tree__label) a { color: var(--ak-link); }
27
+ .client-nojs .ak-sidebar li > ul { display: block; } /* 无 JS:所有层级展开 */
28
+ .ak-sidebar__head { display: none; } /* 抽屉抬头(标题 + 关闭钮):只在 <1120 的抽屉里出现,见 responsive.css */
29
+ .ak-overlay--sidebar, .ak-overlay--drawer { animation: ak-fade-in var(--ak-dur-fast) var(--ak-ease); } /* 抽屉遮罩(.ak-overlay 本体在 components/dialog.css;由 JS 生成) */
30
+ .ak-portlet li a .ak-icon { width: 16px; height: 16px; opacity: .7; }
31
+ .ak-portlet--grid ul { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; }
32
+ .ak-portlet--grid li a { border: 1px solid var(--ak-border); padding: 8px; justify-content: center; text-align: center; font-size: var(--ak-fs-xs); }
33
+ .ak-portlet--grid li a:hover { border-color: var(--ak-accent); }
34
+ /* 可折叠门户(整组) */
35
+ .ak-portlet--collapsible > .ak-portlet__title { cursor: pointer; user-select: none; }
36
+ .ak-portlet--collapsible > .ak-portlet__title::after { content: ""; margin-left: auto; margin-right: 12px; width: 6px; height: 6px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg); transition: transform var(--ak-dur-fast); }
37
+ .ak-portlet--collapsible.is-collapsed > .ak-portlet__title::after { transform: rotate(-45deg); }
38
+ .ak-portlet--collapsible.is-collapsed > ul { display: none; }
39
+ .ak-portlet--collapsible > .ak-portlet__title:focus-visible { outline: 2px solid var(--ak-accent); outline-offset: 2px; }
@@ -0,0 +1,4 @@
1
+ /*! PRTS Design · chrome/special-pages.css — Special pages / forms container · 依赖:tokens.css · components/ */
2
+ /* ═══ Special pages / forms container ═══ */
3
+ .mw-special-Search .ak-body, .ns-special .ak-body { padding: var(--ak-space-5); }
4
+ .skin-arknights .mw-htmlform-field-HTMLTextField, .skin-arknights .oo-ui-fieldLayout { margin-bottom: var(--ak-space-3); }
@@ -0,0 +1,10 @@
1
+ /*! PRTS Design · chrome/theme-toggle.css — Theme toggle 外观切换 · 依赖:tokens.css · components/ */
2
+ /* ═══ Theme toggle (3-state: os / day / night) ═══ */
3
+ .ak-theme-toggle { display: inline-flex; border: 1px solid var(--ak-border-strong); }
4
+ .ak-theme-toggle > button { all: unset; box-sizing: border-box; cursor: pointer; width: 30px; height: 28px; display: grid; place-items: center; color: var(--ak-fg-muted); transition: background var(--ak-dur-fast), color var(--ak-dur-fast); }
5
+ .ak-theme-toggle > button + button { border-left: 1px solid var(--ak-border); }
6
+ .ak-theme-toggle > button:hover { color: var(--ak-fg); background: var(--ak-bg-hover); }
7
+ .ak-theme-toggle > button:focus-visible { outline: 2px solid var(--ak-focus); outline-offset: -2px; }
8
+ .ak-theme-toggle > button.is-active, .ak-theme-toggle > button[aria-pressed="true"] { background: var(--ak-accent); color: var(--ak-accent-fg); } /* 选中项用强调色实底(游戏 selected_back / toggle_on):页眉里 --ak-accent 已重映射为 --ak-theme-accent,亮暗主题下都是同一块青,不再黑白反色。aria-pressed 与 .is-active 等价(Skin:Arknights 的 theme.js 两个都写) */
9
+ .ak-theme-toggle svg, .ak-theme-toggle .ak-icon { width: 15px; height: 15px; } /* 图标可以是 sprite 的 <svg> 或皮肤的 <span class="ak-icon ak-icon--x">(OOUI mask) */
10
+ @media (prefers-reduced-motion: reduce) { .ak-theme-toggle > button { transition: none; } }
@@ -0,0 +1,38 @@
1
+ /*! PRTS Design · chrome/toc.css — TOC 目录导轨 / 折叠条 · 依赖:tokens.css · components/ */
2
+ /* ═══ TOC ═══
3
+ * 一份 DOM、两种形态(不做第二份目录,也不用角落浮动按钮):
4
+ * ≥1400 绝对定位进 .ak-main 右侧预留的导轨,.ak-toc__inner 粘性跟随滚动;
5
+ * <1400 变成由二级吸顶栏「本页目录」拉下来的浮层,顶边始终贴着吸顶栏下沿。
6
+ * 开合是纯 CSS:.ak-toc-cb(checkbox,在 .ak-local-nav 里)+ label.ak-local-nav__toc。
7
+ * 浮层与按钮不是兄弟节点:JS 把 checkbox 状态镜像到 html.ak-toc-open(主路径,不依赖 :has(),老内核的手机浏览器也是真浮层);
8
+ * 无 JS 时用 body:has() 桥接;既无 JS 又不支持 :has() 才退回正文流内的静态卡片。
9
+ * → 无 JS 也完全可用;JS 只负责生成条目、scrollspy、阅读进度、收起页眉、点击外部关闭与开着时锁住页面滚动。 */
10
+ .ak-toc { position: absolute; top: 0; right: 0; bottom: 0; width: var(--ak-toc-w); font-size: var(--ak-fs-xs); }
11
+ .ak-toc__inner { position: sticky; top: calc(var(--ak-header-h) + var(--ak-space-6)); max-height: calc(100vh - var(--ak-header-h) - var(--ak-space-8)); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
12
+ .ak-toc__title { display: block; font: 700 var(--ak-fs-overline)/1 var(--ak-font-label); letter-spacing: var(--ak-tracking-overline); text-transform: uppercase; color: var(--ak-fg-muted); margin: 0 0 8px; padding-left: 10px; border-left: 2px solid var(--ak-theme-accent); }
13
+ .ak-toc__top { display: none; } /* 浮层首项「回到顶部」:仅 <1400 出现,届时 .ak-fab 隐藏(手机上浮动按钮太挡视野) */
14
+ .ak-toc ul { list-style: none; margin: 0; padding: 0; border-left: 1px solid var(--ak-border); }
15
+ .ak-toc ul ul { border-left: 0; } /* 竖线只画在最外层:子 ul 没有内边距、左缘紧贴父 ul 的边框,再各画 1px 就会在二级条目旁叠成 2px(粗细忽大忽小),二级项的高亮条也跟着右偏 1px;层级靠 a 的 padding-left(22 / 34)表达 */
16
+ .ak-toc li::before { display: none !important; }
17
+ .ak-toc li a { display: block; padding: 4px 10px; color: var(--ak-fg-muted); text-decoration: none; border-left: 2px solid transparent; margin-left: -1px; line-height: 1.45; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
18
+ .ak-toc li a:hover { color: var(--ak-fg); }
19
+ .ak-toc li.is-active > a, .ak-toc li.vector-toc-list-item-active > a { color: var(--ak-accent); border-left-color: var(--ak-accent); font-weight: 700; }
20
+ .ak-toc li li a { padding-left: 22px; }
21
+ .ak-toc li li li a { padding-left: 34px; }
22
+ .ak-toc .tocnumber { display: none; }
23
+ .ak-toc__progress { height: 2px; background: var(--ak-border); margin: 0 0 8px; overflow: hidden; }
24
+ .ak-toc__progress > i { display: block; height: 100%; width: var(--_p, 0%); background: var(--ak-accent); transition: width .1s linear; }
25
+ /* ── 皮肤按核心 data-toc 渲染出的目录(Skin:Arknights)比预览多几样:一级项加粗;父项右侧的折叠钮(标题多时默认收起子节,$wgArknightsTableOfContentsCollapseAtCount);
26
+ * 当前小节的祖先路径提亮;核心给的 .tocnumber 序号不显示。条目类名:li.ak-toc__item(--parent)(.is-collapsed)(.is-active-path) > a + button.ak-toc__toggle + ul */
27
+ .ak-toc__inner > ul > li > a { font-weight: 600; color: var(--ak-fg-secondary); } /* 一级项:比子节重一档 */
28
+ .ak-toc li.is-active-path > a { color: var(--ak-fg); }
29
+ .ak-toc li.ak-toc__item--parent > a { padding-right: 26px; } /* 给折叠钮留位 */
30
+ .ak-toc__num { display: none; }
31
+ .ak-toc__toggle { position: absolute; top: 3px; right: 2px; width: 22px; height: 20px; margin: 0; padding: 0; border: 0; background: transparent; color: var(--ak-fg-subtle); cursor: pointer; display: grid; place-items: center; }
32
+ .ak-toc__toggle::before { content: ""; width: 6px; height: 6px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-1px) rotate(45deg); transition: transform var(--ak-dur-fast) var(--ak-ease); }
33
+ .ak-toc__toggle:hover { color: var(--ak-accent); }
34
+ .ak-toc__toggle:focus-visible { outline: 2px solid var(--ak-focus); outline-offset: -2px; }
35
+ .ak-toc li { position: relative; }
36
+ .ak-toc li.is-collapsed > .ak-toc__toggle::before { transform: translate(-1px, 0) rotate(-45deg); }
37
+ .ak-toc li.is-collapsed > ul { display: none; }
38
+ @media (prefers-reduced-motion: reduce) { .ak-toc__toggle::before { transition: none; } }
@@ -0,0 +1,10 @@
1
+ /*! PRTS Design · components/accordion.css — Accordion 手风琴(details) · 依赖:tokens.css */
2
+ /* ═══ Accordion / Details ═══ */
3
+ .ak-details { border: 1px solid var(--ak-border); background: var(--ak-bg-surface); margin: 0 0 var(--ak-space-2); }
4
+ .ak-details > summary { list-style: none; cursor: pointer; padding: var(--ak-space-3) var(--ak-space-4); font-weight: 700; display: flex; align-items: center; gap: var(--ak-space-3); user-select: none; }
5
+ .ak-details > summary::-webkit-details-marker { display: none; }
6
+ .ak-details > summary::before { content: "+"; font-family: var(--ak-font-label); font-weight: 700; font-size: 18px; color: var(--ak-accent); width: 16px; line-height: 1; transition: transform var(--ak-dur-fast); }
7
+ .ak-details[open] > summary::before { content: "−"; }
8
+ .ak-details[open] > summary { border-bottom: 1px solid var(--ak-border); background: var(--ak-bg-surface-2); }
9
+ .ak-details__body { padding: var(--ak-space-3) var(--ak-space-4); }
10
+ .ak-details__body > :last-child { margin-bottom: 0; }
@@ -0,0 +1,8 @@
1
+ /*! PRTS Design · components/avatar.css — Avatar 头像 · 依赖:tokens.css */
2
+ /* ═══ Avatar ═══ */
3
+ .ak-avatar { --_s: 40px; width: var(--_s); height: var(--_s); flex: none; background: var(--ak-bg-surface-3); border: 1px solid var(--ak-border); overflow: hidden; display: inline-grid; place-items: center; font: 700 calc(var(--_s) * .4)/1 var(--ak-font-label); color: var(--ak-fg-muted); position: relative; }
4
+ .ak-avatar > img { width: 100%; height: 100%; object-fit: cover; display: block; }
5
+ .ak-avatar--xs { --_s: 24px; } .ak-avatar--sm { --_s: 32px; } .ak-avatar--lg { --_s: 56px; } .ak-avatar--xl { --_s: 80px; }
6
+ .ak-avatar--round { border-radius: 50%; }
7
+ .ak-avatar__status { position: absolute; right: 0; bottom: 0; width: 25%; height: 25%; background: var(--ak-success); border: 2px solid var(--ak-bg-surface); }
8
+ .ak-avatar-group { display: inline-flex; } .ak-avatar-group > .ak-avatar:not(:first-child) { margin-left: -8px; }
@@ -0,0 +1,16 @@
1
+ /*! PRTS Design · components/badge.css — Badge 计数徽标 · 依赖:tokens.css */
2
+ /* Count badge(通知计数 / 未读点)—— 默认黄(次强调「提示」),不走红:红只留给危险与 NEW/BREAKING,
3
+ 未读数不是高危信息。Echo 的 alerts 类(回退 / 权限变更)才用 --danger;NEW 角标是 .ak-tag--new,不是徽标 */
4
+ /* 数字是正文字体 + tabular-nums,不用 Bender:Bender Bold 在 11px 下笔画比思源黑体细、字形也窄(数字墨迹约 4×8px 对 6×9px),黑字落在 18px 黄圆里读不清;
5
+ Naive UI / Ant Design / Nuxt UI 的计数徽标也都是继承正文字体 + 等宽数字,只靠尺寸和底色区分。
6
+ border-box:min-width = height,单个数字就是正圆,两位数以上才拉成胶囊(之前 content-box 让 18px + 左右 5px 内距永远是 28×18 的长条,数字浮在中间像没对齐)。
7
+ padding-bottom 1px:思源黑体 hhea 上伸 1160 / 下伸 288 不对称,line-height:1 时数字重心比盒子中线低约 0.7px,用 1px 底内距抬回来(Bender 是 920/180,没这个问题) */
8
+ .ak-badge { display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box; min-width: 18px; height: 18px; padding: 0 5px 1px;
9
+ font: 700 12px/1 var(--ak-font-body); font-variant-numeric: tabular-nums; background: var(--ak-accent-2); color: var(--ak-accent-2-fg); border-radius: var(--ak-radius-pill); }
10
+ .ak-badge--dot { min-width: 8px; width: 8px; height: 8px; padding: 0; }
11
+ .ak-badge--accent { background: var(--ak-accent); color: var(--ak-accent-fg); }
12
+ .ak-badge--danger { background: var(--ak-red-600); color: #fff; }
13
+ /* 徽标骑在别的元素右上角(Vue AkBadge 包住内容时,同 Naive NBadge 的默认插槽):外壳只负责定位,徽标本身的长相不变。
14
+ 徽标中心压在角上(translate 50% / -50%),圆点与计数同一个锚点;页眉铃铛那枚是 chrome/header.css 自己定位的,不走这里 */
15
+ .ak-badge-wrap { position: relative; display: inline-flex; vertical-align: middle; }
16
+ .ak-badge-wrap > .ak-badge { position: absolute; top: 0; right: 0; z-index: 1; transform: translate(50%, -50%); pointer-events: none; }
@@ -0,0 +1,7 @@
1
+ /*! PRTS Design · components/breadcrumb.css — Breadcrumb 面包屑 · 依赖:tokens.css */
2
+ /* ═══ Breadcrumb / Pagination ═══ */
3
+ .ak-breadcrumb { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; font-size: var(--ak-fs-xs); color: var(--ak-fg-muted); list-style: none; padding: 0; margin: 0 0 var(--ak-space-3); }
4
+ .ak-breadcrumb li::before { display: none !important; }
5
+ .ak-breadcrumb li + li::before { content: ""; display: inline-block !important; position: static; width: 5px; height: 5px; border-right: 1px solid var(--ak-fg-subtle); border-top: 1px solid var(--ak-fg-subtle); transform: rotate(45deg); margin: 0 6px 1px 2px; background: none; }
6
+ .ak-breadcrumb a { color: var(--ak-fg-muted); } .ak-breadcrumb a:hover { color: var(--ak-accent); }
7
+ .ak-breadcrumb [aria-current] { color: var(--ak-fg); font-weight: 600; }
@@ -0,0 +1,45 @@
1
+ /*! PRTS Design · components/button.css — Button 按钮 · Button group · 依赖:tokens.css */
2
+ /* ═══ Button ═══ */
3
+ .ak-btn {
4
+ --_bg: var(--ak-bg-surface-2); --_fg: var(--ak-fg); --_bd: var(--ak-border-strong);
5
+ display: inline-flex; align-items: center; justify-content: center; gap: var(--ak-space-2);
6
+ min-height: 36px; padding: 0 var(--ak-space-4); font: 600 var(--ak-fs-sm)/1 var(--ak-font-body);
7
+ color: var(--_fg); background: var(--_bg); border: 1px solid var(--_bd); border-radius: var(--ak-radius);
8
+ cursor: pointer; user-select: none; white-space: nowrap; text-decoration: none; position: relative;
9
+ transition: background var(--ak-dur-fast) var(--ak-ease), color var(--ak-dur-fast), border-color var(--ak-dur-fast), transform var(--ak-dur-fast), box-shadow var(--ak-dur-fast);
10
+ }
11
+ .ak-btn:hover { --_bg: var(--ak-bg-surface-3); --_bd: var(--ak-fg-muted); text-decoration: none; color: var(--_fg); }
12
+ .ak-btn:active { transform: translateY(1px); }
13
+ .ak-btn:is(:visited, :active) { color: var(--_fg); } /* 链接形态(<a>):宿主 / 正文的 a:visited、a:active 是 (0,1,1),压得过 .ak-btn 的颜色,这里 (0,2,0) 压回来(:hover 上面已写) */
14
+ .ak-btn:focus-visible { outline: 2px solid var(--ak-focus); outline-offset: 2px; }
15
+ .ak-btn:disabled, .ak-btn.is-disabled, .ak-btn[aria-disabled="true"] { opacity: .45; cursor: not-allowed; pointer-events: none; }
16
+ .ak-btn--primary { --_bg: var(--ak-accent); --_fg: var(--ak-accent-fg); --_bd: var(--ak-accent); }
17
+ .ak-btn--primary:hover { --_bg: var(--ak-accent-hover); --_bd: var(--ak-accent-hover); box-shadow: 0 0 0 3px var(--ak-accent-subtle); }
18
+ .ak-btn--contrast { --_bg: var(--ak-bg-inverse); --_fg: var(--ak-fg-inverse); --_bd: var(--ak-bg-inverse); } /* 游戏内 btn_on:黑白反转 */
19
+ .ak-btn--contrast:hover { --_bg: var(--ak-fg-secondary); --_bd: var(--ak-fg-secondary); }
20
+ .ak-btn--outline { --_bg: transparent; --_fg: var(--ak-accent); --_bd: var(--ak-accent); }
21
+ .ak-btn--outline:hover { --_bg: var(--ak-accent-subtle); }
22
+ .ak-btn--ghost { --_bg: transparent; --_fg: var(--ak-fg-secondary); --_bd: transparent; }
23
+ .ak-btn--ghost:hover { --_bg: var(--ak-bg-hover); --_fg: var(--ak-fg); }
24
+ .ak-btn--danger { --_bg: var(--ak-red-800); --_fg: #fff; --_bd: var(--ak-red-800); }
25
+ .ak-btn--danger:hover { --_bg: var(--ak-red-700); --_bd: var(--ak-red-700); }
26
+ .ak-btn--danger.ak-stripes { background-image: repeating-linear-gradient(-45deg, transparent 0 var(--ak-stripe-size), rgba(255,255,255,.10) var(--ak-stripe-size) calc(var(--ak-stripe-size) * 2)); }
27
+ .ak-btn--link { --_bg: transparent; --_bd: transparent; --_fg: var(--ak-link); min-height: 0; padding: 0; }
28
+ .ak-btn--link:hover { text-decoration: underline; }
29
+ .ak-btn--xs { min-height: 24px; padding: 0 var(--ak-space-2); font-size: var(--ak-fs-xs); }
30
+ .ak-btn--sm { min-height: 30px; padding: 0 var(--ak-space-3); font-size: var(--ak-fs-xs); }
31
+ .ak-btn--lg { min-height: 44px; padding: 0 var(--ak-space-6); font-size: var(--ak-fs-body); }
32
+ .ak-btn--xl { min-height: 56px; padding: 0 var(--ak-space-8); font-size: var(--ak-fs-body-lg); font-weight: 700; }
33
+ .ak-btn--icon { padding: 0; width: 36px; }
34
+ .ak-btn--icon.ak-btn--sm { width: 30px; } .ak-btn--icon.ak-btn--lg { width: 44px; }
35
+ .ak-btn--icon.ak-btn--xs { width: 24px; } .ak-btn--icon.ak-btn--xl { width: 56px; }
36
+ .ak-btn--block { display: flex; width: 100%; }
37
+ .ak-btn--pill { border-radius: var(--ak-radius-pill); }
38
+ .ak-btn__icon { width: 1.1em; height: 1.1em; flex: none; }
39
+ /* 加载态:文字隐去,居中一枚 14px 圆弧转圈;颜色读按钮自己的 --_fg(文字已 transparent,不能用 currentColor)。
40
+ * 曾把游戏内的菱形涟漪(见 .ak-spinner)放进来,36px 高里施展不开,按钮退回圆环 */
41
+ .ak-btn.is-loading { color: transparent !important; pointer-events: none; }
42
+ .ak-btn.is-loading::after { content: ""; position: absolute; inset: 0; margin: auto; width: 14px; height: 14px; border: 2px solid var(--_fg); border-right-color: transparent; border-radius: 50%; animation: ak-spin .7s linear infinite; }
43
+ .ak-btn-group { display: inline-flex; }
44
+ .ak-btn-group > .ak-btn:not(:first-child) { margin-left: -1px; }
45
+ .ak-btn-group > .ak-btn.is-active { --_bg: var(--ak-accent); --_fg: var(--ak-accent-fg); --_bd: var(--ak-accent); z-index: 1; }
@@ -0,0 +1,28 @@
1
+ /*! PRTS Design · components/card.css — Card 卡片 · 依赖:tokens.css */
2
+ /* ═══ Card / Panel ═══ */
3
+ .ak-card {
4
+ background: var(--ak-bg-surface); border: 1px solid var(--ak-border); color: var(--ak-fg);
5
+ position: relative; display: flex; flex-direction: column;
6
+ transition: border-color var(--ak-dur-normal) var(--ak-ease), box-shadow var(--ak-dur-normal), transform var(--ak-dur-normal);
7
+ }
8
+ .ak-card--hover:hover { --_bd: var(--ak-accent-muted); border-color: var(--ak-accent-muted); box-shadow: var(--ak-shadow-md); transform: translateY(-2px); }
9
+ .ak-card--selected, .ak-card.is-selected { --_bd: var(--ak-accent); border-color: var(--ak-accent); box-shadow: inset 0 0 0 1px var(--ak-accent); }
10
+ .ak-card--selected::before, .ak-card.is-selected::before { content: ""; position: absolute; left: 0; top: 0; border-style: solid; border-width: 10px 10px 0 0; border-color: var(--ak-accent) transparent transparent transparent; z-index: 1; }
11
+ .ak-card--flat { border: 0; background: var(--ak-bg-surface-2); }
12
+ .ak-card--inset { background: var(--ak-bg-inset); }
13
+ .ak-card--accent-top { border-top-width: 3px; border-image: linear-gradient(var(--ak-accent) 3px, var(--_bd, var(--ak-border)) 3px) 3 1 1 1; } /* 色条与 1px 框直角拼接(tokens.css §Shape) */
14
+ .ak-card--accent-left { border-left-width: var(--ak-bar-w); border-image: linear-gradient(to right, var(--ak-accent) 4px, var(--_bd, var(--ak-border)) 4px) 1 1 1 4; }
15
+ .ak-card__header { display: flex; align-items: center; gap: var(--ak-space-3); padding: var(--ak-space-3) var(--ak-space-4); border-bottom: 1px solid var(--ak-border); }
16
+ .ak-card__title, :is(h1, h2, h3, h4, h5, h6).ak-card__title { font-weight: 700; font-size: var(--ak-fs-body); margin: 0; flex: 1; line-height: 1.3; } /* 标题写成 h2–h4(title-tag)时标签限定那条 (0,1,1),压过宿主正文的 .mw-body h3(Vector) */
17
+ .ak-card__eyebrow { font: 700 var(--ak-fs-overline)/1 var(--ak-font-label); letter-spacing: var(--ak-tracking-overline); text-transform: uppercase; color: var(--ak-fg-muted); margin-bottom: 4px; display: block; } /* 灰不青:不可点的装饰小标签,青色会读成链接 / 按钮,亮色下 #0098DC 压白底也只有 3.2:1;与 .ak-overline / .ak-stat__label / .ak-attr__label 同色 */
18
+ .ak-card__body { padding: var(--ak-space-4); flex: 1; }
19
+ .ak-card__body > :last-child { margin-bottom: 0; }
20
+ .ak-card__footer { padding: var(--ak-space-3) var(--ak-space-4); border-top: 1px solid var(--ak-border); display: flex; align-items: center; gap: var(--ak-space-3); background: var(--ak-bg-surface-2); }
21
+ .ak-card__media { display: block; width: 100%; aspect-ratio: 16/9; object-fit: cover; background: var(--ak-bg-inset); }
22
+ .ak-card--horizontal { flex-direction: row; }
23
+ .ak-card--horizontal .ak-card__media { width: 40%; aspect-ratio: auto; }
24
+ .ak-card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); gap: var(--ak-space-4); }
25
+ /* 整卡是链接(<a class="ak-card ak-not-prose">,Vue AkCard 的 href):not-prose 只把子孙 a 的下划线归零(:where(.ak-not-prose) a),
26
+ <a> 自己还带着 UA 的下划线,这里去掉;与 .ak-op-card / .ak-stage 同做法 */
27
+ a.ak-card { text-decoration: none; }
28
+ a.ak-card:is(:visited, :hover, :active) { color: var(--ak-fg); } /* 整张卡是链接时,宿主的 a:visited / a:hover (0,1,1) 压得过 .ak-card 的前景色(Vector 悬停会把没自带颜色的正文染蓝) */
@@ -0,0 +1,18 @@
1
+ /*! PRTS Design · components/cbox.css — Cbox 正文提示框(= 现网 {{Cbox2}}) · 依赖:tokens.css */
2
+ /* ═══ Cbox — 正文提示框(= 现网 {{Cbox2}}:左侧图标井 + 右侧正文) ═══
3
+ 与 .ak-message 的分工:.ak-message 是界面 / 系统反馈(横幅、可关闭、与 Toast 同族);.ak-cbox 是编辑写在正文里的提示——「另见 xx 页面」「本节内容已删除仅作存档」,现网满站都是这个模板。
4
+ 等级对应:lv0 绿(另见 / 提示)→ --tip · lv1 蓝(信息)→ 默认 · lv2 黄 / lv3 橙(注意)→ --warning(现网夜间样式也把 2 / 3 并成一档)· lv4 红 → --danger。
5
+ 图标井 = 等级色 24% 淡底 + 等级色线稿(同 .ak-tag--success 那套「淡底 + 色字」,明暗两套令牌各自成立,不分支);图标贴顶,井随正文拉高(现网同);直角、1px 边、不投影 */
6
+ .ak-cbox { --_c: var(--ak-info); --_bg: var(--ak-info-bg);
7
+ display: flex; align-items: stretch; margin: 0 0 var(--ak-space-4);
8
+ background: var(--_bg); border: 1px solid var(--ak-border); color: var(--ak-fg); font-size: var(--ak-fs-sm); line-height: 1.6; }
9
+ .ak-cbox--tip { --_c: var(--ak-success); --_bg: var(--ak-success-bg); }
10
+ .ak-cbox--warning { --_c: var(--ak-warning); --_bg: var(--ak-warning-bg); }
11
+ .ak-cbox--danger { --_c: var(--ak-danger); --_bg: var(--ak-danger-bg); }
12
+ .ak-cbox--neutral { --_c: var(--ak-fg-muted); --_bg: var(--ak-bg-surface-2); }
13
+ .ak-cbox--narrow { max-width: 640px; } /* = 模板 narrow= */
14
+ .ak-cbox__icon { flex: none; width: 40px; display: flex; justify-content: center; padding-top: 10px; background: color-mix(in srgb, var(--_c) 24%, transparent); color: var(--_c); }
15
+ .ak-cbox__icon > svg { width: 20px; height: 20px; }
16
+ .ak-cbox__body { flex: 1; min-width: 0; padding: 9px 12px; }
17
+ .ak-cbox__title { font-weight: 700; color: var(--_c); margin: 0 0 2px; }
18
+ .ak-cbox__body > :last-child { margin-bottom: 0; }
@@ -0,0 +1,9 @@
1
+ /*! PRTS Design · components/chip.css — Chip 筛选芯片 · 依赖:tokens.css */
2
+ /* Chip: 可交互(筛选) */
3
+ .ak-chip { position: relative; display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 12px; font: 500 var(--ak-fs-sm)/1 var(--ak-font-body);
4
+ color: var(--ak-fg-secondary); background: var(--ak-bg-surface); border: 1px solid var(--ak-border-strong); cursor: pointer; user-select: none;
5
+ transition: all var(--ak-dur-fast); }
6
+ .ak-chip:hover { border-color: var(--ak-fg-muted); color: var(--ak-fg); }
7
+ .ak-chip.is-active, .ak-chip[aria-pressed="true"] { background: var(--ak-accent); color: var(--ak-accent-fg); border-color: var(--ak-accent); font-weight: 600; }
8
+ /* 选中角标:绝对定位在左上角(与 .ak-tab / .ak-page-tabs / .ak-card 的选中角标一致),不占据行内宽度 */
9
+ .ak-chip.is-active::before, .ak-chip[aria-pressed="true"]::before { content: ""; position: absolute; top: 0; left: 0; border-style: solid; border-width: 5px 5px 0 0; border-color: currentColor transparent transparent; opacity: .7; pointer-events: none; }
@@ -0,0 +1,14 @@
1
+ /*! PRTS Design · components/dialog.css — Dialog / Overlay / Drawer 对话框 · 依赖:tokens.css */
2
+ /* ═══ Dialog / Modal ═══ */
3
+ .ak-dialog { border: 1px solid var(--ak-border); background: var(--ak-bg-surface); color: var(--ak-fg); padding: 0; max-width: min(92vw, 640px); width: 100%; box-shadow: var(--ak-shadow-lg); }
4
+ .ak-dialog::backdrop { background: var(--ak-bg-overlay); backdrop-filter: blur(2px); }
5
+ .ak-dialog--sm { max-width: 420px; } .ak-dialog--lg { max-width: 900px; } .ak-dialog--full { max-width: 96vw; height: 92vh; }
6
+ .ak-dialog__head { display: flex; align-items: center; gap: var(--ak-space-3); padding: var(--ak-space-3) var(--ak-space-4); border: 0 solid var(--ak-border); border-width: 0 0 1px var(--ak-bar-w); border-image: linear-gradient(to right, var(--ak-accent) 4px, var(--ak-border) 4px) 0 0 1 4; }
7
+ .ak-dialog__title, :is(h1, h2, h3, h4, h5, h6).ak-dialog__title { font-weight: 700; font-size: var(--ak-fs-body-lg); margin: 0; flex: 1; }
8
+ .ak-dialog__body { padding: var(--ak-space-4); max-height: 70vh; overflow: auto; }
9
+ .ak-dialog__foot { display: flex; justify-content: flex-end; gap: var(--ak-space-2); padding: var(--ak-space-3) var(--ak-space-4); border-top: 1px solid var(--ak-border); background: var(--ak-bg-surface-2); }
10
+ .ak-dialog[open] { animation: ak-dialog-in var(--ak-dur-normal) var(--ak-ease); }
11
+ .ak-overlay { position: fixed; inset: 0; background: var(--ak-bg-overlay); z-index: var(--ak-z-overlay); }
12
+ .ak-drawer { position: fixed; top: 0; bottom: 0; width: min(88vw, 320px); background: var(--ak-bg-surface); z-index: var(--ak-z-modal); box-shadow: var(--ak-shadow-lg); overflow-y: auto; transition: transform var(--ak-dur-normal) var(--ak-ease); }
13
+ .ak-drawer--left { left: 0; transform: translateX(-100%); } .ak-drawer--right { right: 0; transform: translateX(100%); }
14
+ .ak-drawer.is-open { transform: none; }
@@ -0,0 +1,8 @@
1
+ /*! PRTS Design · components/divider.css — Divider 分隔线 · 依赖:tokens.css */
2
+ /* ═══ Divider ═══ */
3
+ .ak-divider { border: 0; height: 1px; background: var(--ak-border); margin: var(--ak-space-6) 0; }
4
+ .ak-divider--accent { background: linear-gradient(90deg, var(--ak-accent) 0 80px, var(--ak-border) 80px); height: 2px; }
5
+ .ak-divider--stripes { height: 6px; background: repeating-linear-gradient(-45deg, var(--ak-stripe-color) 0 var(--ak-stripe-size), transparent var(--ak-stripe-size) calc(var(--ak-stripe-size)*2)); }
6
+ .ak-divider--text { display: flex; align-items: center; gap: var(--ak-space-3); height: auto; background: none; font: 700 var(--ak-fs-overline)/1 var(--ak-font-label); letter-spacing: var(--ak-tracking-overline); text-transform: uppercase; color: var(--ak-fg-muted); }
7
+ .ak-divider--text::before, .ak-divider--text::after { content: ""; flex: 1; height: 1px; background: var(--ak-border); }
8
+ .ak-divider--vertical { width: 1px; height: 1em; display: inline-block; margin: 0 var(--ak-space-2); vertical-align: middle; }
@@ -0,0 +1,30 @@
1
+ /*! PRTS Design · components/dropdown.css — Dropdown / Menu 下拉菜单 · 依赖:tokens.css */
2
+ /* ═══ Dropdown / Menu ═══ */
3
+ .ak-dropdown { position: relative; display: inline-block; }
4
+ .ak-menu { position: absolute; top: calc(100% + 4px); left: 0; min-width: 180px; z-index: var(--ak-z-dropdown);
5
+ max-width: min(92vw, 360px); max-height: min(70vh, 560px); overflow-y: auto; overscroll-behavior: contain; /* 长菜单(MW 工具箱 + Gadget 追加的项)在卡片内滚,不撑出视口 */
6
+ background: var(--ak-bg-surface); border: 1px solid var(--ak-border); box-shadow: var(--ak-shadow-lg); padding: 4px 0; margin: 0; list-style: none; }
7
+ .ak-menu--right { left: auto; right: 0; }
8
+ .ak-menu li::before { display: none !important; }
9
+ .ak-menu__item, .ak-menu a { display: flex; align-items: center; gap: var(--ak-space-2); padding: 7px 14px; font-size: var(--ak-fs-sm); color: var(--ak-fg); text-decoration: none; cursor: pointer; white-space: nowrap; border-left: 2px solid transparent; }
10
+ .ak-menu__item:hover, .ak-menu a:hover { background: var(--ak-bg-hover); border-left-color: var(--ak-accent); text-decoration: none; color: var(--ak-fg); }
11
+ .ak-menu__item.is-active { color: var(--ak-accent); border-left-color: var(--ak-accent); }
12
+ .ak-menu__item--danger { color: var(--ak-danger); }
13
+ .ak-menu__sep { height: 1px; background: var(--ak-border); margin: 4px 0; }
14
+ .ak-menu__label { padding: 6px 14px 2px; font: 700 var(--ak-fs-overline)/1 var(--ak-font-label); text-transform: uppercase; letter-spacing: var(--ak-tracking-overline); color: var(--ak-fg-subtle); }
15
+ /* 分组菜单:.ak-menu(此时是 div)里若干 nav.ak-menu__group > .ak-menu__label + ul——MW 门户(#p-cactions / #p-tb …)原样塞进卡片时用;组之间一条分隔线 */
16
+ .ak-menu__group > ul { margin: 0; padding: 0; list-style: none; }
17
+ .ak-menu__group + .ak-menu__group { border-top: 1px solid var(--ak-border); margin-top: 4px; padding-top: 4px; }
18
+ /* 卡片抬头(用户菜单的用户名):粗体一行 + 底线;图标上青 */
19
+ .ak-menu__head { display: flex; align-items: center; gap: 10px; padding: 10px 14px 8px; font-weight: 700; font-size: var(--ak-fs-sm); border-bottom: 1px solid var(--ak-border); margin-bottom: 4px; }
20
+ .ak-menu__head .ak-icon { width: 20px; height: 20px; flex: none; color: var(--ak-accent); }
21
+ .ak-dropdown:not(.is-open) > .ak-menu { display: none; }
22
+ .ak-dropdown > details > summary { list-style: none; cursor: pointer; }
23
+ .ak-dropdown > details > summary::-webkit-details-marker { display: none; }
24
+ .ak-dropdown > details[open] > .ak-menu { display: block; }
25
+ /* Vue 版 AkDropdown(APG 菜单按钮):方向键移到的项 = 悬停外观,焦点环收进项内;禁用项灰字、不响应悬停 */
26
+ .ak-menu__item:focus-visible { background: var(--ak-bg-hover); border-left-color: var(--ak-accent); outline-offset: -2px; }
27
+ .ak-menu__item[aria-disabled="true"] { color: var(--ak-fg-disabled); cursor: not-allowed; }
28
+ .ak-menu__item[aria-disabled="true"]:hover { background: none; border-left-color: transparent; color: var(--ak-fg-disabled); }
29
+ /* 危险链接项:.ak-menu a 的 color(0,1,1)压过了 .ak-menu__item--danger(0,1,0),<a class="ak-menu__item--danger"> 一直不红——补一条(悬停同普通项回到前景色) */
30
+ .ak-menu a.ak-menu__item--danger:not(:hover) { color: var(--ak-danger); }
@@ -0,0 +1,5 @@
1
+ /*! PRTS Design · components/empty.css — Empty 空状态 · 依赖:tokens.css */
2
+ .ak-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: var(--ak-space-12) var(--ak-space-4); color: var(--ak-fg-muted); border: 1px dashed var(--ak-border-strong); background: var(--ak-bg-surface-2); gap: var(--ak-space-2); }
3
+ .ak-empty__icon { width: 48px; height: 48px; opacity: .5; }
4
+ .ak-empty__title { margin: 0; font-weight: 700; color: var(--ak-fg-secondary); font-size: var(--ak-fs-body); }
5
+ .ak-empty__code { font-family: var(--ak-font-display); font-size: var(--ak-fs-display-xl); font-weight: 800; letter-spacing: var(--ak-tracking-display); color: var(--ak-border-strong); line-height: 1; }
@@ -0,0 +1,9 @@
1
+ /*! PRTS Design · components/fab.css — FAB 回到顶部 · 依赖:tokens.css */
2
+ /* ═══ Back-to-top / floating action ═══ */
3
+ .ak-fab { position: fixed; right: var(--ak-space-5); bottom: var(--ak-space-5); width: 44px; height: 44px; padding: 0; display: grid; place-items: center; background: var(--ak-bg-inverse); color: var(--ak-fg-inverse); border: 0; cursor: pointer; z-index: var(--ak-z-sticky); box-shadow: var(--ak-shadow-md); opacity: 0; transform: translateY(8px); transition: all var(--ak-dur-normal) var(--ak-ease); }
4
+ .ak-fab:not(.is-visible) { visibility: hidden; } /* 隐藏时不只是透明:点不到、Tab 不到、读屏也跳过(visibility 在淡出结束时才切,动画不受影响) */
5
+ .ak-fab.is-visible { opacity: 1; transform: none; }
6
+ .ak-fab:hover { background: var(--ak-accent); color: var(--ak-accent-fg); }
7
+ /* 贴最近的定位祖先右下(Vue 版 AkBackTop position="absolute":页面里某个滚动区域自己的回到顶部)。
8
+ * 它不是整页那枚,不随 chrome/responsive.css 在 < 1400 收起(那条只为把整页的回到顶部让给目录浮层);打印照样隐藏 */
9
+ .ak-fab.ak-fab--absolute { position: absolute; display: grid; }
@@ -0,0 +1,66 @@
1
+ /*! PRTS Design · components/form.css — Form controls 表单(field / input / select / check / switch / slider / search / kbd / number) · 依赖:tokens.css */
2
+ /* ═══ Form controls (design-system versions) ═══ */
3
+ .ak-field { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--ak-space-4); }
4
+ .ak-label { font-weight: 600; font-size: var(--ak-fs-sm); }
5
+ .ak-label .req { color: var(--ak-danger); }
6
+ .ak-help { font-size: var(--ak-fs-xs); color: var(--ak-fg-muted); }
7
+ .ak-help--error { color: var(--ak-danger); }
8
+ .ak-input, .ak-select, .ak-textarea { box-sizing: border-box; font: inherit; font-size: var(--ak-fs-sm); color: var(--ak-fg); background: var(--ak-bg-surface); border: 1px solid var(--ak-border-strong); border-radius: var(--ak-radius-sm); padding: 0 10px; min-height: 36px; width: 100%; transition: border-color var(--ak-dur-fast), box-shadow var(--ak-dur-fast); } /* border-box:MW 没有全局 box-sizing 重置,width:100% + padding 会在窄屏撑破容器 */
9
+ .ak-textarea { padding: 8px 10px; min-height: 90px; line-height: 1.5; resize: vertical; }
10
+ .ak-input:focus, .ak-select:focus, .ak-textarea:focus { outline: 0; border-color: var(--ak-accent); box-shadow: var(--ak-shadow-accent); }
11
+ /* 状态与裸控件同一套(base/forms.css / 文档站 /content/forms)。裸控件那边是零特指度,这里要显式再写一遍,否则 .ak-input 的底色会把它们盖掉 */
12
+ .ak-input[readonly], .ak-textarea[readonly] { background: var(--ak-bg-inset); }
13
+ .ak-input:disabled, .ak-select:disabled, .ak-textarea:disabled { background: var(--ak-bg-surface-3); color: var(--ak-fg-disabled); -webkit-text-fill-color: var(--ak-fg-disabled); opacity: 1; border-color: var(--ak-border); cursor: not-allowed; }
14
+ .ak-input.is-invalid, .ak-field.is-invalid .ak-input, :is(.ak-input, .ak-select, .ak-textarea):where(:user-invalid, [aria-invalid="true"]) { border-color: var(--ak-danger); }
15
+ .ak-input.is-invalid:focus, .ak-field.is-invalid .ak-input:focus, :is(.ak-input, .ak-select, .ak-textarea):where(:user-invalid, [aria-invalid="true"]):focus { box-shadow: 0 0 0 3px var(--ak-danger-bg); }
16
+ .ak-input.is-valid { border-color: var(--ak-success); }
17
+ .ak-input--sm { min-height: 30px; font-size: var(--ak-fs-xs); } .ak-input--lg { min-height: 44px; font-size: var(--ak-fs-body); }
18
+ .ak-input-group { display: flex; align-items: stretch; }
19
+ .ak-input-group > .ak-input { flex: 1; min-width: 0; }
20
+ .ak-input-group > .ak-input:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; margin-left: -1px; }
21
+ .ak-input-group > .ak-input:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; }
22
+ .ak-input-group__addon { display: inline-flex; align-items: center; padding: 0 10px; background: var(--ak-bg-surface-2); border: 1px solid var(--ak-border-strong); color: var(--ak-fg-muted); font-size: var(--ak-fs-sm); }
23
+ .ak-select { appearance: none; -webkit-appearance: none; padding-right: 30px; background-image: var(--ak-select-arrow); background-position: calc(100% - 15px) 50%, calc(100% - 10px) 50%; background-size: 5px 5px; background-repeat: no-repeat; } /* 与裸 <select> 同一枚 ▾(tokens.css --ak-select-arrow) */
24
+ /* 勾选 / 单选:外观统一由 base/forms.css 的裸控件规则给(18px 直角勾选框 / 圆形单选 / 主色实底),.ak-check 只负责「控件 + 文字」的排布 */
25
+ .ak-check { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: var(--ak-fs-sm); }
26
+ .ak-check > input { flex: none; }
27
+ .ak-check--sm > input { width: 16px; height: 16px; }
28
+ .ak-switch { --_w: 40px; --_h: 22px; position: relative; display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: var(--ak-fs-sm); }
29
+ .ak-switch > input { appearance: none; -webkit-appearance: none; width: var(--_w); height: var(--_h); background: var(--ak-gray-500); border: 0; border-radius: 0; margin: 0; position: relative; display: inline-block; cursor: pointer; transition: background var(--ak-dur-fast); }
30
+ .ak-switch > input::before { content: ""; position: absolute; top: 3px; left: 3px; width: calc(var(--_h) - 6px); height: calc(var(--_h) - 6px); border: 0; border-radius: 0; background: #fff; transition: transform var(--ak-dur-fast) var(--ak-ease); }
31
+ .ak-switch > input:checked { background: var(--ak-blue-600); } /* 游戏内 toggle_on #0075A9 */
32
+ .ak-switch > input:checked::before { transform: translateX(calc(var(--_w) - var(--_h))); background: #fff; }
33
+ .ak-slider { appearance: none; width: 100%; height: 4px; background: var(--ak-bg-surface-3); outline: 0; }
34
+ .ak-slider::-webkit-slider-thumb { appearance: none; width: 16px; height: 16px; background: var(--ak-accent); border: 2px solid var(--ak-bg-surface); box-shadow: 0 0 0 1px var(--ak-accent); cursor: pointer; }
35
+ .ak-slider::-moz-range-thumb { width: 16px; height: 16px; background: var(--ak-accent); border: 2px solid var(--ak-bg-surface); cursor: pointer; border-radius: 0; }
36
+ .ak-search { position: relative; }
37
+ .ak-search > .ak-input, .ak-search > input { padding-left: 34px; }
38
+ .ak-search__icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--ak-fg-muted); pointer-events: none; }
39
+ /* 键帽:快捷键提示(面板页脚 / 触发器右侧 / 行内动作)。直角、1px 边、底边略重 */
40
+ .ak-kbd, .ak-search__kbd { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 5px; box-sizing: border-box; font: 600 10px/1 var(--ak-font-mono); color: var(--ak-fg-subtle); background: var(--ak-bg-surface); border: 1px solid var(--ak-border); box-shadow: inset 0 -1px 0 var(--ak-border); vertical-align: middle; white-space: nowrap; }
41
+ .ak-search__kbd { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); }
42
+ .ak-number { display: inline-flex; border: 1px solid var(--ak-border-strong); }
43
+ .ak-number > button { all: unset; width: 32px; text-align: center; cursor: pointer; background: var(--ak-bg-surface-2); font-family: inherit; font-weight: 700; }
44
+ .ak-number > button:hover { background: var(--ak-bg-hover); }
45
+ .ak-number > input { width: 56px; border: 0; border-left: 1px solid var(--ak-border); border-right: 1px solid var(--ak-border); text-align: center; font-family: inherit; font-variant-numeric: tabular-nums; background: var(--ak-bg-surface); color: var(--ak-fg); }
46
+ /* ─── 以下是 Vue 实现(packages/vue/src/components/)用到、原先缺的钩子;模板 / Lua 照样可用 ─── */
47
+ /* 下拉的尺寸档:同 .ak-input--sm / --lg(30 / 44) */
48
+ .ak-select--sm { min-height: 30px; font-size: var(--ak-fs-xs); } .ak-select--lg { min-height: 44px; font-size: var(--ak-fs-body); }
49
+ /* 校验通过:多行输入 / 下拉与 .ak-input.is-valid 同一道绿边 */
50
+ .ak-textarea.is-valid, .ak-select.is-valid { border-color: var(--ak-success); }
51
+ /* 滑杆:上面 .ak-slider 的 outline:0 盖掉了全局 :focus-visible 描边,这里补回(文档站 /content/forms · /foundations/accessibility#焦点);禁用半透明 */
52
+ .ak-slider:focus-visible { outline: 2px solid var(--ak-focus); outline-offset: 4px; }
53
+ .ak-slider:disabled { opacity: .45; cursor: not-allowed; }
54
+ /* 字段是纵向 flex:定宽 / 内容宽的控件别被拉满一行(步进器、开关、单个勾选、单选按钮组 —— .ak-btn-group 是 button.css 的,单独写一条) */
55
+ .ak-field > :is(.ak-number, .ak-switch, .ak-check), .ak-field > .ak-btn-group { align-self: flex-start; }
56
+ /* 一组勾选 / 单选:横排换行(--vertical 竖排);组本身不画框,组名由 .ak-field 的标签(aria-labelledby)或 aria-label 给 */
57
+ .ak-check-group { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ak-space-2) var(--ak-space-4); }
58
+ .ak-check-group--vertical { flex-direction: column; align-items: flex-start; }
59
+ /* 禁用:文字降到禁用色;开关轨道半透明(.ak-switch > input 的底色压过了裸控件的禁用规则) */
60
+ .ak-check.is-disabled, .ak-switch.is-disabled { color: var(--ak-fg-disabled); cursor: not-allowed; }
61
+ .ak-switch > input:disabled { opacity: .45; cursor: not-allowed; }
62
+ /* 小一号开关 32 × 18(标题栏旁、表头里;= 首页「演示:特别开放周」那枚) */
63
+ .ak-switch--sm { --_w: 32px; --_h: 18px; font-size: var(--ak-fs-xs); }
64
+ /* 步进器:到上下限的按钮、整个禁用(.ak-number > * 的底色 / 字色压过了裸控件的禁用规则) */
65
+ .ak-number > button:disabled { color: var(--ak-fg-disabled); background: var(--ak-bg-surface-2); cursor: not-allowed; }
66
+ .ak-number > input:disabled { background: var(--ak-bg-surface-3); color: var(--ak-fg-disabled); -webkit-text-fill-color: var(--ak-fg-disabled); cursor: not-allowed; }