style.css 76 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087
  1. :root {
  2. /* ---------- 颜色(暗色主题,默认) ---------- */
  3. --bg: #06070f; /* 主背景:与窗口 BackgroundColour 一致 */
  4. --bg-soft: #0c0e1a; /* 次级背景 */
  5. --ink: #e9ecf5; /* 主文字:浅色 */
  6. --muted: #8b93a7; /* 次要文字:灰蓝 */
  7. --accent: #ff4d4d; /* 主题红 */
  8. --accent-2: #ff2d72; /* 主题粉,用于渐变 */
  9. --grad: linear-gradient(135deg, #ff5a4d 0%, #ff2d72 100%);
  10. --glass: rgba(255, 255, 255, 0.045); /* 玻璃底 */
  11. --glass-strong: rgba(255, 255, 255, 0.075);
  12. --glass-border: rgba(255, 255, 255, 0.09);
  13. --chrome-bg: rgba(1, 2, 6, 0.55); /* 标签栏 / 页脚的毛玻璃底 */
  14. --tab-bg: rgba(4, 6, 14, 0.92); /* 标签栏底色:近实深色,与内容区明显区分 */
  15. --tab-border: rgba(255, 255, 255, 0.10); /* 标签栏与内容区分隔线 */
  16. --scroll-thumb: rgba(255, 255, 255, 0.09);
  17. --close-fg: rgba(255, 255, 255, 0.55); /* 右上角关闭按钮颜色 */
  18. --title-grad: linear-gradient(120deg, #ffffff 18%, #ffb4c1 100%); /* 面板标题渐变 */
  19. --up: #ff5a5a; /* 上涨色(红涨) */
  20. --down: #3ddc84; /* 下跌色(绿跌) */
  21. --radius: 12px;
  22. --font-delta: 0px; /* 全局字号偏移(px),设置中 +- 调整,默认 0(基准字号已含 +2) */
  23. --read-bg: rgba(255, 224, 138, 0.12); /* 朗读中新闻行的背景(暗色主题) */
  24. --read-border: rgba(255, 224, 138, 0.55);/* 朗读中新闻行的边框(暗色主题) */
  25. --read-ink: #ffe08a; /* 朗读中新闻标题文字(暗色主题:金色) */
  26. --tooltip-bg: rgba(28, 32, 48, 0.97); /* 悬浮提示背景(暗色主题:近实深色) */
  27. /* ---------- 间距(黄金比 φ ≈ 1.618) ---------- */
  28. --s-1: 0.618rem;
  29. --s-2: 1rem;
  30. --s-3: 1.618rem;
  31. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
  32. "Apple Color Emoji", "Segoe UI Emoji";
  33. color-scheme: dark;
  34. -webkit-font-smoothing: antialiased;
  35. -moz-osx-font-smoothing: grayscale;
  36. -webkit-text-size-adjust: 100%;
  37. }
  38. /* 亮色主题:只覆盖颜色变量,其余布局与组件样式完全复用 */
  39. :root[data-theme="light"] {
  40. --bg: #f4f6fb;
  41. --bg-soft: #ffffff;
  42. --ink: #1a1f2b;
  43. --muted: #5d6678;
  44. --glass: rgba(255, 255, 255, 0.78);
  45. --glass-strong: rgba(255, 255, 255, 0.96);
  46. --glass-border: rgba(20, 26, 40, 0.10);
  47. --chrome-bg: rgba(255, 255, 255, 0.74);
  48. --tab-bg: rgba(245, 247, 252, 0.95); /* 亮色标签栏:近实浅色 */
  49. --tab-border: rgba(20, 26, 40, 0.12);
  50. --scroll-thumb: rgba(20, 26, 40, 0.18);
  51. --close-fg: rgba(20, 26, 40, 0.60); /* 亮色主题下关闭按钮用深色 */
  52. --title-grad: linear-gradient(120deg, #1a1f2b 22%, #d93a4e 100%);
  53. --up: #d92b2b;
  54. --down: #15803d;
  55. --read-bg: rgba(217, 138, 30, 0.14); /* 朗读中新闻行的背景(亮色主题:淡琥珀) */
  56. --read-border: rgba(180, 110, 10, 0.55); /* 朗读中新闻行的边框(亮色主题) */
  57. --read-ink: #8a5a00; /* 朗读中新闻标题文字(亮色主题:深琥珀,浅底清晰) */
  58. --tooltip-bg: rgba(255, 255, 255, 0.98); /* 悬浮提示背景(亮色主题:近实浅色) */
  59. color-scheme: light;
  60. }
  61. * { box-sizing: border-box; }
  62. /* ============================== 页面骨架 ============================== */
  63. html {
  64. background: var(--bg); /* 深色底色 */
  65. overflow: hidden; /* 防止页面级滚动接管,滚动统一交给面板内部 */
  66. }
  67. html, body {
  68. margin: 0;
  69. }
  70. body {
  71. height: 100vh;
  72. height: 100dvh;
  73. min-height: 0;
  74. display: flex;
  75. flex-direction: column; /* 标签容器 + 页脚纵向排列 */
  76. padding-top: env(safe-area-inset-top);
  77. padding-bottom: env(safe-area-inset-bottom);
  78. overflow: hidden; /* 页面本身不滚动,内容区内部滚动 */
  79. color: var(--ink);
  80. font-size: calc(16px + var(--font-delta));
  81. -webkit-user-select: none;
  82. user-select: none;
  83. --wails-draggable: no-drag; /* 默认不可拖动:只有标签栏(模拟标题栏)可拖动 */
  84. }
  85. /* 背景氛围:左上红光 + 右上粉光,向下渐隐(亮色主题下改为柔和淡色) */
  86. body::before {
  87. content: "";
  88. position: fixed;
  89. inset: 0;
  90. z-index: -1;
  91. pointer-events: none;
  92. background:
  93. radial-gradient(52% 44% at 10% 0%, rgba(255, 77, 77, 0.16), transparent 70%),
  94. radial-gradient(46% 42% at 92% 6%, rgba(255, 45, 114, 0.13), transparent 72%),
  95. linear-gradient(180deg, #0a0c17 0%, var(--bg) 64%);
  96. }
  97. /* 亮色主题的环境光:更淡,避免刺眼 */
  98. :root[data-theme="light"] body::before {
  99. background:
  100. radial-gradient(52% 44% at 10% 0%, rgba(255, 77, 77, 0.10), transparent 70%),
  101. radial-gradient(46% 42% at 92% 6%, rgba(255, 45, 114, 0.08), transparent 72%),
  102. linear-gradient(180deg, #ffffff 0%, var(--bg) 68%);
  103. }
  104. /* ============================== 标签页容器 ============================== */
  105. .tab-container {
  106. display: flex;
  107. flex-direction: column;
  108. flex: 1; /* 填满 body 剩余空间 */
  109. min-height: 0; /* 允许 flex 子项正确收缩 */
  110. }
  111. /* 标签栏:胶囊式标签 + 毛玻璃;整行兼作窗口标题栏(可拖动) */
  112. .tab-buttons {
  113. display: flex;
  114. align-items: center;
  115. gap: 0; /* 间距改由 tab-btn margin 控制,便于区分选中/未选中 */
  116. height: 46px;
  117. padding: 0 10px;
  118. flex-shrink: 0; /* 标签栏不被内容挤扁 */
  119. background: var(--tab-bg); /* 标签栏专用底色,与内容区明显区分 */
  120. backdrop-filter: blur(14px) saturate(140%);
  121. -webkit-backdrop-filter: blur(14px) saturate(140%);
  122. border-bottom: 1px solid var(--tab-border);
  123. box-shadow: 0 1px 0 rgba(0, 0, 0, 0.35); /* 加深分隔,增强与内容区的边界感 */
  124. --wails-draggable: drag; /* 标签行可拖动窗口,模拟原标题栏 */
  125. overflow-x: auto; /* Tab 过多时横向滚动 */
  126. scrollbar-width: none; /* 隐藏滚动条(Firefox) */
  127. }
  128. .tab-buttons::-webkit-scrollbar {
  129. display: none; /* 隐藏滚动条(WebKit) */
  130. }
  131. .tab-btn {
  132. display: inline-flex;
  133. align-items: center;
  134. gap: 6px;
  135. height: 30px;
  136. padding: 0 14px;
  137. margin: 0 1px; /* 未选中:相邻间距 2px(原 4px 收紧 2px) */
  138. border: 1px solid transparent;
  139. border-radius: 8px;
  140. background: transparent;
  141. color: var(--muted); /* 未激活:灰蓝 */
  142. font-size: calc(15px + var(--font-delta));
  143. font-weight: 500;
  144. letter-spacing: 0.02em;
  145. cursor: pointer;
  146. transition: color 0.18s ease, background 0.18s ease, box-shadow 0.18s ease,
  147. transform 0.18s ease, border-color 0.18s ease;
  148. --wails-draggable: no-drag; /* 按钮自身不可拖动,确保可点击 */
  149. flex-shrink: 0; /* Tab 不被压缩,超出才滚动 */
  150. }
  151. .tab-btn:hover {
  152. color: var(--ink); /* 悬停:浅色文字 */
  153. background: var(--glass-strong); /* 悬停:明显玻璃底 */
  154. border-color: var(--glass-border); /* 悬停:描边提示 */
  155. transform: translateY(-1px); /* 悬停:轻微上浮 */
  156. box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
  157. }
  158. .tab-btn.active {
  159. color: #fff; /* 激活:白字 + 渐变底 */
  160. background: var(--grad);
  161. border-color: rgba(255, 255, 255, 0.18);
  162. margin: 0 3px; /* 选中:与邻居间距 4px(3+1),保持原样 */
  163. font-weight: 600;
  164. box-shadow: 0 4px 14px rgba(255, 61, 90, 0.32), inset 0 1px 0 rgba(255, 255, 255, 0.18);
  165. transform: none; /* 选中项不浮起,避免跳动 */
  166. }
  167. /* 把关闭按钮推到最右端,同时这段空白可拖动窗口 */
  168. .win-spacer {
  169. flex: 1;
  170. --wails-draggable: drag;
  171. }
  172. /* 右上角窗口关闭按钮(无边框窗口的自定义标题栏按钮) */
  173. .win-close {
  174. width: 30px;
  175. height: 30px;
  176. margin-left: 10px;
  177. border: none;
  178. border-radius: 8px;
  179. background: transparent;
  180. color: var(--close-fg); /* 跟随界面风格变化 */
  181. font-size: calc(19px + var(--font-delta));
  182. line-height: 1;
  183. cursor: pointer;
  184. transition: background 0.15s ease, color 0.15s ease;
  185. --wails-draggable: no-drag; /* 按钮自身不可拖动 */
  186. }
  187. .win-close:hover {
  188. background: #e81123; /* Windows 风格:悬停红底 */
  189. color: #fff;
  190. }
  191. /* ============================== 内容区 ============================== */
  192. .tab-content {
  193. flex: 1;
  194. min-height: 0;
  195. display: flex;
  196. flex-direction: column; /* 面板垂直排列:flex:1 限制高度,内容超高时面板内部滚动 */
  197. overflow: hidden;
  198. color: var(--ink);
  199. }
  200. /* 细滚动条:半透明,悬停加亮 */
  201. .tab-panel::-webkit-scrollbar {
  202. width: 10px;
  203. }
  204. .tab-panel::-webkit-scrollbar-thumb {
  205. border: 3px solid transparent;
  206. border-radius: 8px;
  207. background: var(--scroll-thumb);
  208. background-clip: padding-box;
  209. }
  210. .tab-panel::-webkit-scrollbar-thumb:hover {
  211. background: rgba(255, 255, 255, 0.2);
  212. background-clip: padding-box;
  213. }
  214. /* 面板:默认隐藏,active 才显示并淡入;自身负责内边距与滚动 */
  215. .tab-panel {
  216. display: none;
  217. flex: 1;
  218. min-height: 0;
  219. min-width: 0;
  220. overflow-y: auto;
  221. scrollbar-gutter: stable; /* 预留滚动条位置,设置页内容超高时始终可滚动 */
  222. padding: 26px 30px 30px;
  223. }
  224. .tab-panel.active {
  225. display: block;
  226. animation: tabFadeIn 0.28s ease both;
  227. }
  228. /* 内嵌网页面板(笔记):去掉内边距,让 iframe 铺满整个内容区 */
  229. .panel-embed.active {
  230. display: flex;
  231. padding: 0;
  232. overflow: hidden;
  233. }
  234. .panel-embed iframe {
  235. flex: 1;
  236. width: 100%;
  237. height: 100%;
  238. border: 0;
  239. background: #fff; /* iframe 未加载完成时显示白底 */
  240. }
  241. /* 自定义 Tab 面板:纵向布局,顶部常驻工具条 + 下方 iframe / 编辑器 */
  242. .panel-custom.active {
  243. display: flex; /* 覆盖 .tab-panel 的 display:block,使 flex 子项(编辑器/预览)能占满剩余高度 */
  244. flex-direction: column;
  245. }
  246. .custom-tab-bar {
  247. display: flex;
  248. align-items: center;
  249. justify-content: flex-end;
  250. flex-shrink: 0;
  251. gap: 8px;
  252. padding: 6px 10px;
  253. border-bottom: 1px solid var(--glass-border);
  254. background: var(--glass);
  255. }
  256. .custom-tab-bar .btn-ghost {
  257. font-size: calc(14px + var(--font-delta));
  258. }
  259. /* 文件类自定义 Tab 工具条状态提示(左对齐,编辑模式下也可见) */
  260. .custom-file-status {
  261. margin-right: auto;
  262. font-size: calc(12.5px + var(--font-delta));
  263. color: var(--ink-dim);
  264. white-space: nowrap;
  265. overflow: hidden;
  266. text-overflow: ellipsis;
  267. max-width: 55%;
  268. }
  269. .custom-file-status.is-ok {
  270. color: #3ddc84;
  271. }
  272. .custom-file-status.is-err {
  273. color: #ff5a5a;
  274. }
  275. /* 文件类自定义 Tab:占满剩余高度,Markdown 内容可滚动 */
  276. .panel-custom-file {
  277. overflow: hidden; /* 内容区自行滚动 */
  278. }
  279. .panel-custom-file.active {
  280. flex-direction: column;
  281. }
  282. .custom-file-editor {
  283. flex: 1;
  284. min-height: 0;
  285. padding: 14px 16px;
  286. border: 1px solid var(--glass-border);
  287. border-radius: var(--radius);
  288. background: var(--glass);
  289. color: var(--ink);
  290. font-size: calc(15.5px + var(--font-delta));
  291. font-family: "Consolas", "Courier New", monospace;
  292. line-height: 1.7;
  293. resize: none; /* 尺寸由布局控制 */
  294. outline: none;
  295. -webkit-user-select: text;
  296. user-select: text;
  297. }
  298. .custom-file-editor:focus {
  299. border-color: rgba(255, 77, 77, 0.55);
  300. }
  301. .custom-file-mode {
  302. display: inline-flex;
  303. padding: 2px;
  304. border: 1px solid var(--glass-border);
  305. border-radius: 8px;
  306. background: var(--glass);
  307. }
  308. .custom-file-mode-btn {
  309. padding: 3px 14px;
  310. border: none;
  311. border-radius: 6px;
  312. background: transparent;
  313. color: var(--muted);
  314. font-size: calc(13.5px + var(--font-delta));
  315. line-height: 1.4;
  316. cursor: pointer;
  317. transition: background 0.15s ease, color 0.15s ease;
  318. }
  319. .custom-file-mode-btn:hover {
  320. color: var(--ink);
  321. }
  322. .custom-file-mode-btn.is-active {
  323. background: var(--accent);
  324. color: #fff;
  325. }
  326. .custom-file-md {
  327. flex: 1;
  328. min-height: 0;
  329. overflow-y: auto;
  330. padding: 16px 20px;
  331. -webkit-user-select: text;
  332. user-select: text;
  333. }
  334. .custom-file-error {
  335. color: #ff5a5a;
  336. padding: 8px 0;
  337. }
  338. .custom-file-ok {
  339. color: #3ddc84;
  340. padding: 8px 0;
  341. word-break: break-all;
  342. }
  343. @keyframes tabFadeIn {
  344. from { opacity: 0; transform: translateY(8px); }
  345. to { opacity: 1; transform: translateY(0); }
  346. }
  347. /* 面板标题:渐变文字 */
  348. .tab-panel h2 {
  349. margin: 0 0 6px;
  350. font-size: calc(23px + var(--font-delta));
  351. font-weight: 650;
  352. letter-spacing: -0.01em;
  353. background: var(--title-grad);
  354. -webkit-background-clip: text;
  355. background-clip: text;
  356. color: transparent;
  357. }
  358. /* 面板说明文字 */
  359. .panel-desc {
  360. margin: 0 0 22px;
  361. max-width: 100%;
  362. color: var(--muted);
  363. font-size: calc(15.5px + var(--font-delta));
  364. line-height: 1.7;
  365. }
  366. /* ---------- 卡片 ---------- */
  367. .card-grid {
  368. display: grid;
  369. grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  370. gap: 14px;
  371. }
  372. .card {
  373. padding: 16px 18px;
  374. border: 1px solid var(--glass-border);
  375. border-radius: var(--radius);
  376. background: var(--glass);
  377. backdrop-filter: blur(6px); /* 毛玻璃质感加强 */
  378. -webkit-backdrop-filter: blur(6px);
  379. transition: transform 0.2s ease, border-color 0.2s ease, background 0.2s ease;
  380. }
  381. .card:hover {
  382. transform: translateY(-2px); /* 悬停轻微抬升 */
  383. border-color: rgba(255, 77, 77, 0.35);
  384. background: var(--glass-strong);
  385. }
  386. .card-title {
  387. display: flex;
  388. align-items: center;
  389. gap: 8px;
  390. margin-bottom: 7px;
  391. color: var(--ink);
  392. font-size: calc(15.5px + var(--font-delta));
  393. font-weight: 600;
  394. }
  395. .card p {
  396. margin: 0;
  397. color: var(--muted);
  398. font-size: calc(14.5px + var(--font-delta));
  399. line-height: 1.65;
  400. }
  401. /* 小圆点指示器 */
  402. .dot {
  403. width: 7px;
  404. height: 7px;
  405. border-radius: 50%;
  406. flex-shrink: 0;
  407. background: var(--accent);
  408. box-shadow: 0 0 8px var(--accent);
  409. }
  410. /* ---------- 空状态(控制 / 服务 / 股市占位) ---------- */
  411. .empty-state {
  412. display: flex;
  413. flex-direction: column;
  414. align-items: center;
  415. justify-content: center;
  416. gap: 8px;
  417. min-height: 220px;
  418. padding: 32px 20px;
  419. border: 1px dashed var(--glass-border);
  420. border-radius: var(--radius);
  421. background: var(--glass);
  422. text-align: center;
  423. }
  424. .empty-mark {
  425. font-size: calc(32px + var(--font-delta));
  426. line-height: 1;
  427. color: var(--accent);
  428. opacity: 0.75;
  429. }
  430. .empty-title {
  431. color: var(--ink);
  432. font-size: calc(16px + var(--font-delta));
  433. font-weight: 600;
  434. }
  435. .empty-text {
  436. color: var(--muted);
  437. font-size: calc(14.5px + var(--font-delta));
  438. }
  439. /* ---------- 设置项 ---------- */
  440. .setting-list {
  441. display: flex;
  442. flex-direction: column;
  443. gap: 14px;
  444. }
  445. /* 设置分组卡片:每组设置项一个带边框的容器,明显区分各页设置 */
  446. .setting-group {
  447. display: flex;
  448. flex-direction: column;
  449. gap: 8px;
  450. padding: 12px 12px 14px;
  451. border: 1px solid var(--glass-border);
  452. border-radius: calc(var(--radius) + 2px);
  453. background: var(--glass);
  454. }
  455. /* 设置分组标题:每组设置项前显示所属 Tab 名称;可点击展开/收起(默认为收缩) */
  456. .setting-group-title {
  457. display: flex;
  458. align-items: center;
  459. gap: 8px;
  460. width: 100%;
  461. margin: 2px 0 6px;
  462. padding: 6px 8px;
  463. border: none;
  464. border-radius: 6px;
  465. background: transparent;
  466. color: var(--accent);
  467. font-size: calc(14.5px + var(--font-delta));
  468. font-weight: 700;
  469. letter-spacing: 0.5px;
  470. text-align: left;
  471. cursor: pointer;
  472. user-select: none;
  473. }
  474. .setting-group-title:hover {
  475. background: rgba(255, 255, 255, 0.06);
  476. }
  477. /* 标题前箭头:收缩时朝右,展开时朝下 */
  478. .setting-group-arrow {
  479. display: inline-flex;
  480. align-items: center;
  481. justify-content: center;
  482. width: 16px;
  483. height: 16px;
  484. font-size: 12px;
  485. color: var(--muted);
  486. transition: transform 0.18s ease;
  487. }
  488. .setting-group:not(.is-collapsed) .setting-group-arrow {
  489. transform: rotate(90deg);
  490. }
  491. /* 组名 */
  492. .setting-group-label {
  493. flex: 1;
  494. }
  495. /* 设置项数量徽标 */
  496. .setting-group-count {
  497. padding: 2px 8px;
  498. border-radius: 10px;
  499. background: rgba(255, 255, 255, 0.07);
  500. color: var(--muted);
  501. font-size: calc(12px + var(--font-delta));
  502. font-weight: 500;
  503. letter-spacing: 0;
  504. }
  505. /* 收缩状态:隐藏设置项 */
  506. .setting-group.is-collapsed .setting-group-rows {
  507. display: none;
  508. }
  509. /* 展开状态:设置项容器以 flex 排列 */
  510. .setting-group-rows {
  511. display: flex;
  512. flex-direction: column;
  513. gap: 8px;
  514. }
  515. .setting-group-title:first-child {
  516. margin-top: 0;
  517. }
  518. .setting-row {
  519. display: flex;
  520. align-items: center;
  521. justify-content: space-between;
  522. gap: 18px;
  523. padding: 16px 18px;
  524. border: 1px solid rgba(255, 255, 255, 0.055);
  525. border-radius: var(--radius);
  526. background: rgba(255, 255, 255, 0.02); /* 组卡片内的行:更浅背景,弱化边框,形成内嵌层级 */
  527. }
  528. /* 亮色主题下组卡片内的行用淡色底 */
  529. :root[data-theme="light"] .setting-row {
  530. border-color: rgba(20, 26, 40, 0.07);
  531. background: rgba(255, 255, 255, 0.55);
  532. }
  533. .setting-title {
  534. margin-bottom: 4px;
  535. color: var(--ink);
  536. font-size: calc(15.5px + var(--font-delta));
  537. font-weight: 600;
  538. }
  539. .setting-hint {
  540. color: var(--muted);
  541. font-size: calc(14px + var(--font-delta));
  542. line-height: 1.5;
  543. }
  544. /* 分段控件:暗色 / 亮色 */
  545. .segmented {
  546. display: inline-flex;
  547. padding: 3px;
  548. border: 1px solid var(--glass-border);
  549. border-radius: 9px;
  550. background: rgba(127, 127, 127, 0.12); /* 中性底,明暗主题都适用 */
  551. flex-shrink: 0;
  552. }
  553. .seg-btn {
  554. min-width: 62px;
  555. height: 28px;
  556. padding: 0 14px;
  557. border: none;
  558. border-radius: 7px;
  559. background: transparent;
  560. color: var(--muted);
  561. font-size: calc(14.5px + var(--font-delta));
  562. cursor: pointer;
  563. transition: color 0.18s ease, background 0.18s ease, box-shadow 0.18s ease;
  564. }
  565. .seg-btn.active {
  566. color: #fff;
  567. background: var(--grad);
  568. font-weight: 600;
  569. box-shadow: 0 2px 8px rgba(255, 61, 90, 0.28);
  570. }
  571. /* 步进器:界面字号 +- 调整 */
  572. .stepper {
  573. display: inline-flex;
  574. align-items: center;
  575. gap: 8px;
  576. flex-shrink: 0;
  577. }
  578. .step-btn {
  579. width: 30px;
  580. height: 30px;
  581. border: 1px solid var(--glass-border);
  582. border-radius: 8px;
  583. background: var(--glass);
  584. color: var(--ink);
  585. font-size: calc(18px + var(--font-delta));
  586. line-height: 1;
  587. cursor: pointer;
  588. transition: background 0.18s ease, border-color 0.18s ease;
  589. }
  590. .step-btn:hover {
  591. background: var(--glass-strong);
  592. border-color: rgba(255, 77, 77, 0.35);
  593. }
  594. .step-btn:disabled {
  595. opacity: 0.4;
  596. cursor: not-allowed;
  597. }
  598. .step-value {
  599. min-width: 22px;
  600. text-align: center;
  601. color: var(--ink);
  602. font-size: calc(15.5px + var(--font-delta));
  603. font-weight: 600;
  604. font-variant-numeric: tabular-nums;
  605. }
  606. /* 开关:checkbox 隐藏,用轨道 + 滑块绘制 */
  607. .switch {
  608. position: relative;
  609. display: inline-flex;
  610. flex-shrink: 0;
  611. width: 44px;
  612. height: 24px;
  613. cursor: pointer;
  614. }
  615. .switch input {
  616. position: absolute;
  617. inset: 0;
  618. margin: 0;
  619. opacity: 0;
  620. cursor: pointer;
  621. }
  622. .switch-track {
  623. display: block; /* span 需转为块级才能生效宽高 */
  624. width: 100%;
  625. height: 100%;
  626. border-radius: 999px;
  627. background: rgba(127, 127, 127, 0.35);
  628. transition: background 0.2s ease;
  629. }
  630. .switch-track::after {
  631. content: "";
  632. position: absolute;
  633. top: 3px;
  634. left: 3px;
  635. width: 18px;
  636. height: 18px;
  637. border-radius: 50%;
  638. background: #fff;
  639. box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
  640. transition: transform 0.2s ease;
  641. }
  642. .switch input:checked + .switch-track {
  643. background: var(--grad);
  644. }
  645. .switch input:checked + .switch-track::after {
  646. transform: translateX(20px); /* 开启时滑块滑到右侧 */
  647. }
  648. .switch input:focus-visible + .switch-track {
  649. outline: 2px solid var(--accent);
  650. outline-offset: 2px;
  651. }
  652. /* 文本输入框(地址、代码、热键) */
  653. .input {
  654. width: 260px;
  655. height: 32px;
  656. padding: 0 10px;
  657. border: 1px solid var(--glass-border);
  658. border-radius: 8px;
  659. background: rgba(127, 127, 127, 0.10);
  660. color: var(--ink);
  661. font-size: calc(14.5px + var(--font-delta));
  662. font-family: inherit;
  663. outline: none;
  664. flex-shrink: 0;
  665. -webkit-user-select: text; /* 输入框允许选择文本 */
  666. user-select: text;
  667. transition: border-color 0.18s ease, background 0.18s ease;
  668. }
  669. .input::placeholder {
  670. color: var(--muted);
  671. opacity: 0.7;
  672. }
  673. .input:focus {
  674. border-color: rgba(255, 77, 77, 0.55);
  675. background: rgba(127, 127, 127, 0.16);
  676. }
  677. .hotkey-input {
  678. width: 190px;
  679. text-align: center;
  680. letter-spacing: 0.04em;
  681. cursor: pointer;
  682. }
  683. /* 保存栏 */
  684. .save-bar {
  685. display: flex;
  686. align-items: center;
  687. gap: 12px;
  688. margin-top: 18px;
  689. }
  690. .btn-primary {
  691. height: 34px;
  692. padding: 0 20px;
  693. border: none;
  694. border-radius: 9px;
  695. background: var(--grad);
  696. color: #fff;
  697. font-size: calc(15px + var(--font-delta));
  698. font-weight: 600;
  699. cursor: pointer;
  700. box-shadow: 0 4px 14px rgba(255, 61, 90, 0.28);
  701. transition: transform 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease;
  702. }
  703. .btn-primary:hover {
  704. transform: translateY(-1px);
  705. box-shadow: 0 6px 18px rgba(255, 61, 90, 0.38);
  706. }
  707. .btn-primary:disabled {
  708. opacity: 0.6;
  709. cursor: default;
  710. transform: none;
  711. }
  712. /* 乒乓按钮「停止」状态:红色危险色 */
  713. .btn-danger {
  714. height: 34px;
  715. padding: 0 20px;
  716. border: 1px solid rgba(255, 90, 90, 0.5);
  717. border-radius: 9px;
  718. background: rgba(255, 77, 77, 0.12);
  719. color: #ff6a6a;
  720. font-size: calc(15px + var(--font-delta));
  721. font-weight: 600;
  722. cursor: pointer;
  723. transition: transform 0.15s ease, background 0.15s ease, opacity 0.15s ease;
  724. }
  725. .btn-danger:hover {
  726. background: rgba(255, 77, 77, 0.22);
  727. transform: translateY(-1px);
  728. }
  729. .btn-danger:disabled {
  730. opacity: 0.6;
  731. cursor: default;
  732. transform: none;
  733. }
  734. .btn-ghost {
  735. height: 30px;
  736. padding: 0 14px;
  737. border: 1px solid var(--glass-border);
  738. border-radius: 8px;
  739. background: var(--glass);
  740. color: var(--ink);
  741. font-size: calc(14.5px + var(--font-delta));
  742. cursor: pointer;
  743. flex-shrink: 0;
  744. transition: background 0.18s ease, border-color 0.18s ease;
  745. }
  746. .btn-ghost:hover {
  747. background: var(--glass-strong);
  748. border-color: rgba(255, 77, 77, 0.35);
  749. }
  750. /* 保存状态提示 */
  751. .save-status {
  752. color: var(--muted);
  753. font-size: calc(14px + var(--font-delta));
  754. }
  755. .save-status.is-ok {
  756. color: var(--down); /* 成功:绿色 */
  757. }
  758. .save-status.is-error {
  759. color: var(--up); /* 失败:红色 */
  760. }
  761. /* 面板标题行:标题在左,操作按钮在右 */
  762. .panel-head {
  763. display: flex;
  764. align-items: flex-start;
  765. justify-content: space-between;
  766. gap: 16px;
  767. margin-bottom: 18px;
  768. }
  769. .panel-head .panel-desc {
  770. margin-bottom: 0;
  771. }
  772. /* 面板头部右侧操作组:状态徽标 + 刷新按钮,水平排列 */
  773. .panel-head-actions {
  774. display: flex;
  775. align-items: center;
  776. gap: 10px;
  777. flex-shrink: 0;
  778. }
  779. /* Github 最后一次成功刷新时间徽标 */
  780. .github-refresh-time {
  781. color: var(--muted);
  782. font-size: 14px;
  783. white-space: nowrap;
  784. }
  785. /* 交易 / 休市 状态徽标:圆点 + 文字 */
  786. .market-status {
  787. display: inline-flex;
  788. align-items: center;
  789. gap: 6px;
  790. padding: 5px 12px;
  791. border: 1px solid var(--glass-border);
  792. border-radius: 999px;
  793. background: var(--glass);
  794. color: var(--muted);
  795. font-size: calc(14px + var(--font-delta));
  796. font-weight: 500;
  797. white-space: nowrap;
  798. }
  799. .market-status .dot {
  800. width: 8px;
  801. height: 8px;
  802. border-radius: 50%;
  803. background: var(--muted); /* 未知 / 加载中:灰 */
  804. flex-shrink: 0;
  805. }
  806. .market-status.is-open .dot {
  807. background: var(--up); /* 交易中:红(主题色) */
  808. box-shadow: 0 0 6px rgba(255, 90, 90, 0.6);
  809. animation: marketPulse 1.6s ease-in-out infinite;
  810. }
  811. .market-status.is-closed .dot {
  812. background: var(--down); /* 休市:绿 */
  813. }
  814. @keyframes marketPulse {
  815. 0%, 100% { opacity: 1; }
  816. 50% { opacity: 0.45; }
  817. }
  818. /* ---------- 股市列表 ---------- */
  819. .stock-list {
  820. display: flex;
  821. flex-direction: column;
  822. gap: 8px;
  823. }
  824. .stock-row {
  825. display: grid;
  826. grid-template-columns: minmax(140px, 1.4fr) 1fr 1.2fr auto;
  827. align-items: center;
  828. gap: 14px;
  829. padding: 13px 16px;
  830. border: 1px solid var(--glass-border);
  831. border-radius: 10px;
  832. background: var(--glass);
  833. cursor: pointer; /* 点击行打开分时 / 日K 弹窗 */
  834. transition: background 0.18s ease, border-color 0.18s ease;
  835. }
  836. .stock-row:hover {
  837. background: var(--glass-strong);
  838. border-color: rgba(255, 77, 77, 0.3);
  839. }
  840. .stock-main {
  841. display: flex;
  842. flex-direction: column;
  843. gap: 3px;
  844. min-width: 0;
  845. }
  846. .stock-name {
  847. color: var(--ink);
  848. font-size: calc(15.5px + var(--font-delta));
  849. font-weight: 600;
  850. overflow: hidden;
  851. text-overflow: ellipsis;
  852. white-space: nowrap;
  853. }
  854. /* 股票名称 = 股吧链接:下划线提示可点击,悬停高亮 */
  855. .stock-name.stock-guba {
  856. color: inherit;
  857. text-decoration: none;
  858. border-bottom: 1px dashed rgba(255, 255, 255, 0.22);
  859. transition: color 0.15s ease, border-color 0.15s ease;
  860. }
  861. .stock-name.stock-guba:hover {
  862. color: #ff5a5a;
  863. border-bottom-color: #ff5a5a;
  864. }
  865. .stock-code {
  866. color: var(--muted);
  867. font-size: calc(13.5px + var(--font-delta));
  868. letter-spacing: 0.04em;
  869. }
  870. .stock-price {
  871. font-size: calc(19px + var(--font-delta));
  872. font-weight: 650;
  873. font-variant-numeric: tabular-nums; /* 数字等宽,刷新时不抖动 */
  874. }
  875. .stock-change {
  876. display: flex;
  877. flex-direction: column;
  878. gap: 2px;
  879. font-size: calc(14.5px + var(--font-delta));
  880. font-variant-numeric: tabular-nums;
  881. }
  882. .stock-amount {
  883. color: var(--muted);
  884. font-size: calc(14px + var(--font-delta));
  885. font-variant-numeric: tabular-nums;
  886. justify-self: end;
  887. white-space: nowrap;
  888. }
  889. .stock-price.up, .stock-change.up {
  890. color: var(--up); /* 红涨 */
  891. }
  892. .stock-price.down, .stock-change.down {
  893. color: var(--down); /* 绿跌 */
  894. }
  895. /* ---------- 待办提醒弹窗(置顶) ---------- */
  896. .remind-modal {
  897. position: fixed;
  898. inset: 0;
  899. z-index: 200; /* 高于股票图表弹窗,确保置顶 */
  900. display: flex;
  901. align-items: center;
  902. justify-content: center;
  903. pointer-events: auto;
  904. }
  905. .remind-modal[hidden] {
  906. display: none;
  907. }
  908. /* 遮罩:压暗背景 */
  909. .remind-mask {
  910. position: absolute;
  911. inset: 0;
  912. background: rgba(0, 0, 0, 0.5);
  913. backdrop-filter: blur(3px);
  914. -webkit-backdrop-filter: blur(3px);
  915. }
  916. /* 提醒对话框:居中卡片 */
  917. .remind-dialog {
  918. position: relative;
  919. display: flex;
  920. flex-direction: column;
  921. align-items: center;
  922. gap: 10px;
  923. width: min(360px, 88vw);
  924. padding: 24px 26px;
  925. border: 1px solid rgba(255, 77, 77, 0.35);
  926. border-radius: 16px;
  927. background: var(--bg-soft);
  928. box-shadow: 0 18px 60px rgba(0, 0, 0, 0.5), 0 0 24px rgba(255, 77, 77, 0.15);
  929. animation: remindIn 0.25s ease both;
  930. }
  931. @keyframes remindIn {
  932. from { opacity: 0; transform: translateY(12px) scale(0.96); }
  933. to { opacity: 1; transform: translateY(0) scale(1); }
  934. }
  935. /* 提醒图标:铃铛脉冲 */
  936. .remind-icon {
  937. font-size: 44px;
  938. line-height: 1;
  939. animation: remindPulse 1.2s ease-in-out infinite;
  940. }
  941. @keyframes remindPulse {
  942. 0%, 100% { transform: scale(1); }
  943. 50% { transform: scale(1.12); }
  944. }
  945. .remind-title {
  946. color: var(--accent);
  947. font-size: calc(19px + var(--font-delta));
  948. font-weight: 700;
  949. letter-spacing: 0.04em;
  950. }
  951. /* 任务文本:可选中复制 */
  952. .remind-text {
  953. max-width: 100%;
  954. max-height: 160px;
  955. overflow-y: auto;
  956. color: var(--ink);
  957. font-size: calc(17px + var(--font-delta));
  958. font-weight: 550;
  959. text-align: center;
  960. word-break: break-word;
  961. user-select: text;
  962. }
  963. .remind-time {
  964. color: var(--muted);
  965. font-size: calc(14.5px + var(--font-delta));
  966. }
  967. .remind-actions {
  968. margin-top: 6px;
  969. }
  970. /* ---------- 股票图表弹窗 ---------- */
  971. .chart-modal {
  972. position: fixed;
  973. inset: 0;
  974. z-index: 100;
  975. display: flex;
  976. align-items: center;
  977. justify-content: center;
  978. }
  979. .chart-modal[hidden] {
  980. display: none;
  981. }
  982. /* 遮罩:压暗背景并虚化 */
  983. .chart-mask {
  984. position: absolute;
  985. inset: 0;
  986. background: rgba(0, 0, 0, 0.45);
  987. backdrop-filter: blur(3px);
  988. -webkit-backdrop-filter: blur(3px);
  989. }
  990. .chart-dialog {
  991. position: relative;
  992. display: flex;
  993. flex-direction: column;
  994. gap: 10px;
  995. width: min(860px, 92vw);
  996. height: min(520px, 78vh);
  997. padding: 16px 18px;
  998. border: 1px solid var(--glass-border);
  999. border-radius: 14px;
  1000. background: var(--bg-soft);
  1001. box-shadow: 0 18px 60px rgba(0, 0, 0, 0.45);
  1002. animation: chartIn 0.2s ease both;
  1003. }
  1004. @keyframes chartIn {
  1005. from { opacity: 0; transform: translateY(10px) scale(0.98); }
  1006. to { opacity: 1; transform: translateY(0) scale(1); }
  1007. }
  1008. .chart-head {
  1009. display: flex;
  1010. align-items: center;
  1011. gap: 14px;
  1012. }
  1013. .chart-title-wrap {
  1014. flex: 1;
  1015. min-width: 0;
  1016. }
  1017. .chart-title {
  1018. color: var(--ink);
  1019. font-size: calc(17px + var(--font-delta));
  1020. font-weight: 650;
  1021. overflow: hidden;
  1022. text-overflow: ellipsis;
  1023. white-space: nowrap;
  1024. }
  1025. .chart-sub {
  1026. margin-top: 2px;
  1027. color: var(--muted);
  1028. font-size: calc(14px + var(--font-delta));
  1029. font-variant-numeric: tabular-nums;
  1030. }
  1031. /* 弹窗右上角关闭按钮,颜色同样跟随主题 */
  1032. .chart-close {
  1033. width: 28px;
  1034. height: 28px;
  1035. border: none;
  1036. border-radius: 7px;
  1037. background: transparent;
  1038. color: var(--close-fg);
  1039. font-size: calc(18px + var(--font-delta));
  1040. line-height: 1;
  1041. cursor: pointer;
  1042. flex-shrink: 0;
  1043. transition: background 0.15s ease, color 0.15s ease;
  1044. }
  1045. .chart-close:hover {
  1046. background: #e81123;
  1047. color: #fff;
  1048. }
  1049. #chart-canvas {
  1050. flex: 1;
  1051. min-height: 0;
  1052. width: 100%;
  1053. }
  1054. .chart-legend {
  1055. display: flex;
  1056. align-items: center;
  1057. gap: 14px;
  1058. min-height: 16px;
  1059. color: var(--muted);
  1060. font-size: calc(13.5px + var(--font-delta));
  1061. }
  1062. .chart-legend .lg {
  1063. display: inline-flex;
  1064. align-items: center;
  1065. gap: 5px;
  1066. }
  1067. /* 图例前的色条 */
  1068. .chart-legend .lg i {
  1069. width: 14px;
  1070. height: 2px;
  1071. border-radius: 1px;
  1072. background: currentColor;
  1073. }
  1074. /* ============================== 页脚 ============================== */
  1075. .footer {
  1076. display: grid;
  1077. grid-template-columns: auto 1fr auto auto; /* 版本 | 说明/古诗区(伸缩) | 时钟 | 文档 */
  1078. align-items: center;
  1079. gap: 14px;
  1080. flex-shrink: 0;
  1081. padding: 9px 14px;
  1082. border-top: 1px solid var(--glass-border);
  1083. background: var(--chrome-bg); /* 半透明底,跟随主题 */
  1084. backdrop-filter: blur(10px);
  1085. -webkit-backdrop-filter: blur(10px);
  1086. color: var(--muted);
  1087. font-size: calc(14px + var(--font-delta));
  1088. --wails-draggable: drag; /* footer 区域允许拖动窗口 */
  1089. }
  1090. /* footer 说明 / 古诗滚动区:版本后面,时钟之前 */
  1091. .footer-desc {
  1092. display: flex;
  1093. align-items: center;
  1094. justify-self: stretch;
  1095. min-width: 0;
  1096. overflow: hidden;
  1097. }
  1098. /* 滚动文字(古诗或 Tab 说明),超出宽度时水平循环滚动 */
  1099. .footer-marquee {
  1100. flex: 1;
  1101. min-width: 0;
  1102. overflow: hidden;
  1103. white-space: nowrap;
  1104. text-overflow: ellipsis;
  1105. color: var(--muted);
  1106. opacity: 0.85;
  1107. cursor: pointer;
  1108. --wails-draggable: no-drag;
  1109. }
  1110. /* 内层文字 span:单份静态显示;超宽时由 JS 复制一份并整体平移 -50%,实现无缝循环 */
  1111. .footer-marquee-inner {
  1112. display: inline-block;
  1113. white-space: nowrap;
  1114. padding-right: 0;
  1115. }
  1116. .footer-marquee:hover {
  1117. opacity: 1;
  1118. color: var(--ink);
  1119. }
  1120. /* 滚动动画:由 JS 检测溢出后添加 .scrolling 类;时长由 --poem-speed(秒/轮)控制,默认 18s */
  1121. .footer-marquee.scrolling {
  1122. text-overflow: clip;
  1123. }
  1124. .footer-marquee.scrolling .footer-marquee-inner {
  1125. animation: footerMarquee var(--poem-speed, 18s) linear infinite;
  1126. }
  1127. @keyframes footerMarquee {
  1128. 0% { transform: translateX(0); }
  1129. 100% { transform: translateX(-50%); }
  1130. }
  1131. /* 朗读按钮:古诗显示时可见 */
  1132. .poem-read {
  1133. flex-shrink: 0;
  1134. margin-left: 8px;
  1135. border: none;
  1136. background: transparent;
  1137. color: var(--muted);
  1138. font-size: calc(15px + var(--font-delta));
  1139. cursor: pointer;
  1140. transition: color 0.2s ease, transform 0.15s ease;
  1141. --wails-draggable: no-drag;
  1142. }
  1143. .poem-read:hover {
  1144. color: var(--accent);
  1145. transform: scale(1.12);
  1146. }
  1147. .poem-read.is-active {
  1148. color: var(--accent); /* 朗读中:主题红 */
  1149. }
  1150. .poem-read[hidden] {
  1151. display: none;
  1152. }
  1153. .footer-version {
  1154. justify-self: start;
  1155. display: inline-flex;
  1156. align-items: center;
  1157. gap: 7px;
  1158. white-space: nowrap;
  1159. }
  1160. .footer-time {
  1161. justify-self: center;
  1162. display: inline-flex;
  1163. align-items: center;
  1164. gap: 7px;
  1165. white-space: nowrap; /* 农历+公历+节日较长,禁止换行 */
  1166. font-variant-numeric: tabular-nums; /* 时钟数字等宽,避免跳动 */
  1167. color: var(--muted);
  1168. }
  1169. .footer-docs {
  1170. justify-self: end;
  1171. display: inline-flex;
  1172. align-items: center;
  1173. gap: 5px;
  1174. color: var(--muted);
  1175. text-decoration: none;
  1176. white-space: nowrap;
  1177. cursor: pointer;
  1178. transition: color 0.2s ease;
  1179. --wails-draggable: no-drag;
  1180. }
  1181. .footer-docs:hover {
  1182. color: var(--accent); /* 悬停变主题红 */
  1183. }
  1184. /* ---------- 常用网址卡片 ---------- */
  1185. .link-card {
  1186. display: block;
  1187. color: inherit;
  1188. text-decoration: none;
  1189. cursor: pointer;
  1190. }
  1191. .link-card:hover .card-title {
  1192. color: var(--accent);
  1193. }
  1194. /* ---------- 新闻列表 ---------- */
  1195. .news-list {
  1196. display: flex;
  1197. flex-direction: column;
  1198. gap: 6px;
  1199. }
  1200. .news-row {
  1201. display: flex;
  1202. align-items: baseline;
  1203. gap: 10px;
  1204. padding: 10px 14px;
  1205. border: 1px solid var(--glass-border);
  1206. border-radius: 10px;
  1207. background: var(--glass);
  1208. color: var(--ink);
  1209. text-decoration: none;
  1210. transition: background 0.18s ease, border-color 0.18s ease;
  1211. }
  1212. .news-row:hover {
  1213. background: var(--glass-strong);
  1214. border-color: rgba(255, 77, 77, 0.3);
  1215. }
  1216. /* 命中关键词的新闻:左侧红条标记 */
  1217. .news-row.matched {
  1218. border-left: 3px solid var(--accent);
  1219. }
  1220. /* 已查看过的新闻:标题灰显 */
  1221. .news-row.viewed .news-title {
  1222. color: var(--muted);
  1223. }
  1224. .news-row.viewed .news-src {
  1225. opacity: 0.6;
  1226. }
  1227. /* 当前正在朗读的新闻行:高亮(颜色随主题变化,避免亮色下看不清) */
  1228. .news-row.reading {
  1229. background: var(--read-bg);
  1230. border-color: var(--read-border);
  1231. }
  1232. .news-row.reading .news-title {
  1233. color: var(--read-ink);
  1234. }
  1235. .news-src {
  1236. flex-shrink: 0;
  1237. padding: 1px 8px;
  1238. border-radius: 6px;
  1239. background: rgba(127, 127, 127, 0.16);
  1240. color: var(--muted);
  1241. font-size: calc(13px + var(--font-delta));
  1242. }
  1243. .news-title {
  1244. min-width: 0;
  1245. font-size: calc(15.5px + var(--font-delta));
  1246. line-height: 1.5;
  1247. }
  1248. /* 新闻分组标题:关注关键词组 / 其他组 */
  1249. .news-group-label {
  1250. display: flex;
  1251. align-items: center;
  1252. gap: 8px;
  1253. margin: 4px 2px 2px;
  1254. color: var(--muted);
  1255. font-size: calc(14px + var(--font-delta));
  1256. font-weight: 600;
  1257. letter-spacing: 0.04em;
  1258. }
  1259. .news-group-label .news-group-dot {
  1260. width: 8px;
  1261. height: 8px;
  1262. border-radius: 50%;
  1263. background: var(--accent);
  1264. box-shadow: 0 0 8px rgba(255, 77, 77, 0.5);
  1265. }
  1266. /* 其他组:圆点改为灰蓝色,弱化提示 */
  1267. .news-group-other .news-group-dot {
  1268. background: var(--muted);
  1269. box-shadow: none;
  1270. }
  1271. /* 两组之间的小区格分隔线 */
  1272. .news-divider {
  1273. display: flex;
  1274. align-items: center;
  1275. gap: 10px;
  1276. margin: 12px 0 8px;
  1277. color: var(--muted);
  1278. font-size: calc(13px + var(--font-delta));
  1279. }
  1280. .news-divider::before,
  1281. .news-divider::after {
  1282. content: '';
  1283. flex: 1;
  1284. height: 1px;
  1285. background: var(--glass-border);
  1286. }
  1287. /* B站动态区块的提示文字(如 cookie 未配置 / 已过期) */
  1288. .news-bili-hint {
  1289. margin: 2px 2px 10px;
  1290. padding: 8px 12px;
  1291. border-radius: 8px;
  1292. background: var(--glass-bg);
  1293. border: 1px solid var(--glass-border);
  1294. color: var(--muted);
  1295. font-size: calc(14px + var(--font-delta));
  1296. line-height: 1.5;
  1297. }
  1298. /* ---------- Github 仓库卡片 ---------- */
  1299. .repo-list {
  1300. display: flex;
  1301. flex-direction: column;
  1302. gap: 12px;
  1303. }
  1304. /* ---------- GitHub 热门仓库(Trending)区块 ---------- */
  1305. .trending-block {
  1306. margin-top: 24px; /* 位于关注仓库之下,用上间距分隔 */
  1307. }
  1308. .trending-head {
  1309. display: flex;
  1310. align-items: center;
  1311. justify-content: space-between;
  1312. margin-bottom: 12px;
  1313. }
  1314. .trending-head .github-refresh-time {
  1315. margin-left: auto; /* 徽标紧跟刷新按钮靠右,不占据中间 */
  1316. }
  1317. .trending-title {
  1318. margin: 0;
  1319. font-size: calc(17px + var(--font-delta));
  1320. font-weight: 650;
  1321. }
  1322. .trending-title .trending-sub {
  1323. margin-left: 6px;
  1324. color: var(--muted);
  1325. font-size: calc(13.5px + var(--font-delta));
  1326. font-weight: 400;
  1327. }
  1328. .trending-list {
  1329. display: flex;
  1330. flex-direction: column;
  1331. gap: 8px;
  1332. }
  1333. .trending-card {
  1334. display: block;
  1335. padding: 12px 14px;
  1336. border: 1px solid var(--glass-border);
  1337. border-radius: 10px;
  1338. background: var(--glass);
  1339. color: var(--ink);
  1340. text-decoration: none;
  1341. transition: background 0.18s ease, border-color 0.18s ease;
  1342. }
  1343. .trending-card:hover {
  1344. background: var(--glass-strong);
  1345. border-color: rgba(255, 77, 77, 0.3);
  1346. }
  1347. .trending-card-head {
  1348. display: flex;
  1349. align-items: center;
  1350. gap: 8px;
  1351. flex-wrap: wrap;
  1352. }
  1353. .trending-repo {
  1354. font-size: calc(15.5px + var(--font-delta));
  1355. font-weight: 650;
  1356. }
  1357. .trending-lang {
  1358. padding: 1px 8px;
  1359. border-radius: 6px;
  1360. background: rgba(127, 127, 127, 0.16);
  1361. color: var(--muted);
  1362. font-size: calc(13px + var(--font-delta));
  1363. }
  1364. .trending-desc {
  1365. margin-top: 6px;
  1366. color: var(--muted);
  1367. font-size: calc(14.5px + var(--font-delta));
  1368. line-height: 1.5;
  1369. }
  1370. .trending-meta {
  1371. display: flex;
  1372. align-items: center;
  1373. gap: 12px;
  1374. margin-top: 8px;
  1375. flex-wrap: wrap;
  1376. }
  1377. .trending-stat {
  1378. color: var(--muted);
  1379. font-size: calc(13.5px + var(--font-delta));
  1380. }
  1381. .trending-stat.trending-today {
  1382. color: var(--up); /* 今日新增星数用上涨色突出 */
  1383. font-weight: 600;
  1384. }
  1385. .repo-card {
  1386. padding: 14px 16px;
  1387. border: 1px solid var(--glass-border);
  1388. border-radius: var(--radius);
  1389. background: var(--glass);
  1390. }
  1391. .repo-head {
  1392. display: flex;
  1393. align-items: baseline;
  1394. gap: 10px;
  1395. margin-bottom: 8px;
  1396. flex-wrap: wrap;
  1397. }
  1398. .repo-name {
  1399. color: var(--ink);
  1400. font-size: calc(16px + var(--font-delta));
  1401. font-weight: 650;
  1402. text-decoration: none;
  1403. }
  1404. .repo-name:hover {
  1405. color: var(--accent);
  1406. }
  1407. .repo-desc {
  1408. color: var(--muted);
  1409. font-size: calc(14px + var(--font-delta));
  1410. }
  1411. /* Latest 之后的版本(Pre-release 等):仅列出展示,不参与更新比较 */
  1412. .repo-newer {
  1413. display: flex;
  1414. flex-wrap: wrap;
  1415. gap: 6px;
  1416. margin-top: 2px;
  1417. }
  1418. .repo-newer-item {
  1419. padding: 1px 8px;
  1420. border-radius: 999px;
  1421. font-size: calc(13px + var(--font-delta));
  1422. color: var(--muted);
  1423. border: 1px solid var(--glass-border);
  1424. background: var(--glass-strong);
  1425. text-decoration: none;
  1426. white-space: nowrap;
  1427. }
  1428. .repo-newer-item:hover {
  1429. color: var(--ink);
  1430. border-color: var(--accent);
  1431. }
  1432. .repo-newer-item.is-pre {
  1433. color: #e8b45a; /* 预发布:琥珀色 */
  1434. border-color: rgba(232, 180, 90, 0.35);
  1435. }
  1436. .repo-newer-item.is-draft {
  1437. color: #9aa4b8; /* 草稿:灰蓝 */
  1438. opacity: 0.8;
  1439. }
  1440. /* 版本徽标:最新版本 / 有更新 / 本地版本 */
  1441. .ver-badge {
  1442. display: inline-flex;
  1443. align-items: center;
  1444. gap: 4px;
  1445. padding: 2px 9px;
  1446. border-radius: 999px;
  1447. font-size: calc(13.5px + var(--font-delta));
  1448. font-weight: 600;
  1449. white-space: nowrap;
  1450. text-decoration: none;
  1451. line-height: 1.5;
  1452. }
  1453. .ver-ok {
  1454. color: var(--down);
  1455. border: 1px solid rgba(61, 220, 132, 0.35);
  1456. background: rgba(61, 220, 132, 0.10);
  1457. }
  1458. .ver-update {
  1459. color: #fff;
  1460. border: 1px solid rgba(255, 77, 77, 0.55);
  1461. background: var(--grad);
  1462. box-shadow: 0 2px 8px rgba(255, 61, 90, 0.3);
  1463. cursor: pointer;
  1464. transition: filter 0.15s ease;
  1465. }
  1466. .ver-update:hover {
  1467. filter: brightness(1.1);
  1468. }
  1469. .ver-muted {
  1470. color: var(--muted);
  1471. border: 1px solid var(--glass-border);
  1472. background: var(--glass);
  1473. }
  1474. .ver-local {
  1475. margin-left: 4px;
  1476. color: var(--muted);
  1477. font-size: calc(13px + var(--font-delta));
  1478. text-decoration: underline dotted;
  1479. text-underline-offset: 2px;
  1480. cursor: pointer;
  1481. transition: color 0.15s ease;
  1482. }
  1483. .ver-local:hover {
  1484. color: var(--accent);
  1485. }
  1486. /* ver-ok / ver-muted 作为可点击链接时给出提示 */
  1487. a.ver-ok,
  1488. a.ver-muted {
  1489. cursor: pointer;
  1490. transition: filter 0.15s ease;
  1491. }
  1492. a.ver-ok:hover {
  1493. filter: brightness(1.1);
  1494. }
  1495. a.ver-muted:hover {
  1496. color: var(--ink);
  1497. border-color: var(--accent);
  1498. }
  1499. /* 检视按钮:有可用更新时出现,点击标记已检查 */
  1500. .repo-check-btn {
  1501. padding: 2px 10px;
  1502. font-size: calc(13.5px + var(--font-delta));
  1503. line-height: 1.5;
  1504. white-space: nowrap;
  1505. border-radius: 999px;
  1506. }
  1507. .repo-check-btn:disabled {
  1508. opacity: 0.6;
  1509. cursor: default;
  1510. }
  1511. .repo-error {
  1512. color: var(--up);
  1513. font-size: calc(14.5px + var(--font-delta));
  1514. }
  1515. .commit-row {
  1516. display: flex;
  1517. align-items: baseline;
  1518. justify-content: space-between;
  1519. gap: 12px;
  1520. padding: 7px 10px;
  1521. border-radius: 8px;
  1522. color: var(--ink);
  1523. text-decoration: none;
  1524. transition: background 0.15s ease;
  1525. }
  1526. .commit-row:hover {
  1527. background: var(--glass-strong);
  1528. }
  1529. .commit-title {
  1530. min-width: 0;
  1531. overflow: hidden;
  1532. text-overflow: ellipsis;
  1533. white-space: nowrap;
  1534. font-size: calc(14.5px + var(--font-delta));
  1535. }
  1536. .commit-time {
  1537. flex-shrink: 0;
  1538. color: var(--muted);
  1539. font-size: calc(13.5px + var(--font-delta));
  1540. font-variant-numeric: tabular-nums;
  1541. }
  1542. /* ntfy 聊天室乒乓按钮:监听中突出显示 */
  1543. #chat-toggle.is-active {
  1544. background: var(--accent);
  1545. color: #fff;
  1546. border-color: var(--accent);
  1547. }
  1548. /* 工具页古诗词朗读按钮:朗读中突出显示 */
  1549. #poem-tool-read.is-active {
  1550. background: var(--accent);
  1551. color: #fff;
  1552. border-color: var(--accent);
  1553. }
  1554. /* Markdown 渲染通用样式(文件类自定义 Tab / Web 服务等) */
  1555. .markdown-body {
  1556. font-size: calc(15px + var(--font-delta));
  1557. line-height: 1.75;
  1558. color: var(--ink);
  1559. word-break: break-word;
  1560. }
  1561. .markdown-body > :first-child { margin-top: 0; }
  1562. .markdown-body > :last-child { margin-bottom: 0; }
  1563. .markdown-body h1, .markdown-body h2, .markdown-body h3,
  1564. .markdown-body h4, .markdown-body h5, .markdown-body h6 {
  1565. margin: 1.1em 0 0.5em;
  1566. font-weight: 700;
  1567. line-height: 1.3;
  1568. }
  1569. .markdown-body h1 { font-size: calc(22px + var(--font-delta)); }
  1570. .markdown-body h2 { font-size: calc(19px + var(--font-delta)); }
  1571. .markdown-body h3 { font-size: calc(17px + var(--font-delta)); }
  1572. .markdown-body h4 { font-size: calc(15.5px + var(--font-delta)); }
  1573. .markdown-body p { margin: 0.7em 0; }
  1574. .markdown-body ul, .markdown-body ol { margin: 0.7em 0; padding-left: 1.6em; }
  1575. .markdown-body li { margin: 0.25em 0; }
  1576. .markdown-body a { color: var(--accent); text-decoration: underline; }
  1577. .markdown-body blockquote {
  1578. margin: 0.8em 0;
  1579. padding: 2px 12px;
  1580. border-left: 3px solid var(--accent);
  1581. color: var(--muted);
  1582. background: var(--glass-strong);
  1583. }
  1584. .markdown-body code {
  1585. padding: 1px 5px;
  1586. border-radius: 4px;
  1587. background: var(--glass-strong);
  1588. font-family: "Consolas", "Courier New", monospace;
  1589. font-size: 0.92em;
  1590. }
  1591. .markdown-body pre {
  1592. margin: 0.8em 0;
  1593. padding: 10px 12px;
  1594. border-radius: var(--radius);
  1595. background: var(--glass-strong);
  1596. overflow-x: auto;
  1597. }
  1598. .markdown-body pre code { padding: 0; background: transparent; }
  1599. .markdown-body table {
  1600. margin: 0.8em 0;
  1601. border-collapse: collapse;
  1602. width: 100%;
  1603. }
  1604. .markdown-body th, .markdown-body td {
  1605. padding: 6px 10px;
  1606. border: 1px solid var(--glass-border);
  1607. text-align: left;
  1608. }
  1609. .markdown-body th { background: var(--glass-strong); font-weight: 600; }
  1610. .markdown-body hr {
  1611. margin: 1.2em 0;
  1612. border: none;
  1613. border-top: 1px solid var(--glass-border);
  1614. }
  1615. .markdown-body img { max-width: 100%; border-radius: 6px; }
  1616. .markdown-body del { opacity: 0.7; }
  1617. /* ---------- 待办页 ---------- */
  1618. .panel-todo {
  1619. display: none; /* 未激活时隐藏 */
  1620. }
  1621. .panel-todo.active {
  1622. display: flex; /* 激活时纵向布局:列表撑满 */
  1623. flex-direction: column;
  1624. gap: 10px;
  1625. }
  1626. .todo-list {
  1627. flex: 1;
  1628. overflow-y: auto;
  1629. display: flex;
  1630. flex-direction: column;
  1631. gap: 6px;
  1632. padding: 2px;
  1633. }
  1634. .todo-row {
  1635. display: flex;
  1636. align-items: center;
  1637. gap: 10px;
  1638. padding: 8px 12px;
  1639. border: 1px solid var(--glass-border);
  1640. border-radius: var(--radius);
  1641. background: var(--glass);
  1642. }
  1643. .todo-check {
  1644. width: 16px;
  1645. height: 16px;
  1646. flex-shrink: 0;
  1647. cursor: pointer;
  1648. accent-color: var(--accent, #ff4d4d);
  1649. }
  1650. .todo-input {
  1651. flex: 1;
  1652. min-width: 0;
  1653. padding: 6px 8px;
  1654. border: 1px solid transparent;
  1655. border-radius: calc(var(--radius) - 2px);
  1656. background: transparent;
  1657. color: var(--ink);
  1658. font-size: calc(15.5px + var(--font-delta));
  1659. outline: none;
  1660. transition: border-color 0.15s;
  1661. }
  1662. .todo-input:focus {
  1663. border-color: rgba(255, 77, 77, 0.55);
  1664. }
  1665. /* 已完成任务:文字划线变淡 */
  1666. .todo-input.todo-done {
  1667. text-decoration: line-through;
  1668. color: var(--muted);
  1669. }
  1670. .todo-del {
  1671. flex-shrink: 0;
  1672. }
  1673. /* 待办提醒时间选择器 */
  1674. .todo-remind {
  1675. flex-shrink: 0;
  1676. width: 168px;
  1677. padding: 5px 8px;
  1678. border: 1px solid var(--glass-border);
  1679. border-radius: calc(var(--radius) - 2px);
  1680. background: var(--glass-strong);
  1681. color: var(--ink);
  1682. font-size: calc(14.5px + var(--font-delta));
  1683. color-scheme: dark;
  1684. outline: none;
  1685. cursor: pointer;
  1686. transition: border-color 0.15s;
  1687. }
  1688. .todo-remind:hover {
  1689. border-color: rgba(255, 77, 77, 0.45);
  1690. }
  1691. .todo-remind:focus {
  1692. border-color: var(--accent);
  1693. }
  1694. :root[data-theme="light"] .todo-remind {
  1695. color-scheme: light;
  1696. }
  1697. /* 清除提醒时间按钮 */
  1698. .todo-remind-clear {
  1699. flex-shrink: 0;
  1700. padding: 0 6px;
  1701. font-size: calc(16px + var(--font-delta));
  1702. }
  1703. .todo-remind-clear:disabled {
  1704. opacity: 0.3;
  1705. cursor: default;
  1706. }
  1707. .todo-actions {
  1708. display: flex;
  1709. justify-content: flex-start;
  1710. }
  1711. .todo-status {
  1712. min-height: 16px;
  1713. color: var(--muted);
  1714. font-size: calc(14px + var(--font-delta));
  1715. }
  1716. /* 待办文件路径说明(面板标题下方) */
  1717. .todo-path-desc {
  1718. margin-top: 2px;
  1719. color: var(--muted);
  1720. font-size: calc(13.5px + var(--font-delta));
  1721. }
  1722. /* ---------- 记录页 ---------- */
  1723. .panel-record {
  1724. display: none; /* 未激活时隐藏 */
  1725. }
  1726. .panel-record.active {
  1727. display: flex; /* 激活时纵向布局 */
  1728. flex-direction: column;
  1729. gap: 10px;
  1730. }
  1731. /* 记录文件路径说明(面板标题下方) */
  1732. .record-path-desc {
  1733. margin-top: 2px;
  1734. color: var(--muted);
  1735. font-size: calc(13.5px + var(--font-delta));
  1736. }
  1737. /* 筛选工具栏:姓名 / 名称下拉 + 匹配条数 */
  1738. .record-toolbar {
  1739. display: flex;
  1740. align-items: center;
  1741. gap: 14px;
  1742. flex-wrap: wrap;
  1743. padding: 10px 12px;
  1744. border: 1px solid var(--glass-border);
  1745. border-radius: var(--radius);
  1746. background: var(--glass);
  1747. }
  1748. .record-label {
  1749. display: flex;
  1750. align-items: center;
  1751. gap: 8px;
  1752. font-size: calc(14.5px + var(--font-delta));
  1753. color: var(--muted);
  1754. }
  1755. .record-select {
  1756. min-width: 150px;
  1757. padding: 6px 8px;
  1758. border: 1px solid var(--glass-border);
  1759. border-radius: calc(var(--radius) - 2px);
  1760. background: var(--glass-strong);
  1761. color: var(--ink);
  1762. font-size: calc(14.5px + var(--font-delta));
  1763. outline: none;
  1764. cursor: pointer;
  1765. transition: border-color 0.15s;
  1766. }
  1767. .record-select:hover {
  1768. border-color: rgba(255, 77, 77, 0.45);
  1769. }
  1770. .record-select:focus {
  1771. border-color: var(--accent);
  1772. }
  1773. .record-date {
  1774. min-width: 140px;
  1775. padding: 6px 8px;
  1776. border: 1px solid var(--glass-border);
  1777. border-radius: calc(var(--radius) - 2px);
  1778. background: var(--glass-strong);
  1779. color: var(--ink);
  1780. font-size: calc(14.5px + var(--font-delta));
  1781. outline: none;
  1782. cursor: pointer;
  1783. transition: border-color 0.15s;
  1784. }
  1785. .record-date:hover {
  1786. border-color: rgba(255, 77, 77, 0.45);
  1787. }
  1788. .record-date:focus {
  1789. border-color: var(--accent);
  1790. }
  1791. .record-count {
  1792. margin-left: auto;
  1793. color: var(--muted);
  1794. font-size: calc(14px + var(--font-delta));
  1795. }
  1796. /* 柱状图容器:固定高度,canvas 撑满,空提示居中 */
  1797. .record-chart-wrap {
  1798. position: relative;
  1799. height: 240px;
  1800. border: 1px solid var(--glass-border);
  1801. border-radius: var(--radius);
  1802. background: var(--glass);
  1803. overflow: hidden;
  1804. }
  1805. .record-chart {
  1806. display: none; /* 有数据时显示 */
  1807. width: 100%;
  1808. height: 100%;
  1809. }
  1810. .record-chart-empty {
  1811. position: absolute;
  1812. inset: 0;
  1813. display: flex;
  1814. align-items: center;
  1815. justify-content: center;
  1816. color: var(--muted);
  1817. font-size: calc(15px + var(--font-delta));
  1818. }
  1819. /* 柱状图鼠标悬停提示 */
  1820. .record-chart-tooltip {
  1821. position: absolute;
  1822. z-index: 5;
  1823. pointer-events: none; /* 不阻挡鼠标,避免闪烁 */
  1824. max-width: 240px;
  1825. padding: 6px 10px;
  1826. border-radius: 8px;
  1827. border: 1px solid var(--glass-border, rgba(127,127,127,0.3));
  1828. background: var(--tooltip-bg, rgba(28,32,48,0.97));
  1829. color: var(--ink, #e9ecf5);
  1830. font-size: calc(12px + var(--font-delta));
  1831. line-height: 1.5;
  1832. box-shadow: 0 4px 14px rgba(0,0,0,0.35);
  1833. white-space: nowrap;
  1834. }
  1835. .record-chart-tooltip .tip-name {
  1836. font-weight: 600;
  1837. }
  1838. .record-chart-tooltip div + div {
  1839. margin-top: 2px;
  1840. }
  1841. /* 记录列表:每行「姓名|名称|值|删除」 */
  1842. .record-list {
  1843. flex: 1;
  1844. min-height: 120px; /* 保证列表区有最小可用高度,避免被固定元素挤压成一行 */
  1845. overflow-y: auto;
  1846. overflow-x: hidden;
  1847. display: flex;
  1848. flex-direction: column;
  1849. gap: 6px;
  1850. padding: 2px;
  1851. }
  1852. .record-row {
  1853. display: flex;
  1854. align-items: center;
  1855. gap: 10px;
  1856. min-width: 0;
  1857. padding: 8px 12px;
  1858. border: 1px solid var(--glass-border);
  1859. border-radius: var(--radius);
  1860. background: var(--glass);
  1861. }
  1862. .record-input {
  1863. padding: 6px 8px;
  1864. border: 1px solid transparent;
  1865. border-radius: calc(var(--radius) - 2px);
  1866. background: transparent;
  1867. color: var(--ink);
  1868. font-size: calc(15px + var(--font-delta));
  1869. outline: none;
  1870. transition: border-color 0.15s;
  1871. }
  1872. .record-input:focus {
  1873. border-color: rgba(255, 77, 77, 0.55);
  1874. }
  1875. .record-name {
  1876. width: 150px;
  1877. flex: 0 1 150px;
  1878. min-width: 60px;
  1879. }
  1880. .record-item {
  1881. width: 200px;
  1882. flex: 0 1 200px;
  1883. min-width: 70px;
  1884. }
  1885. .record-value {
  1886. width: 110px;
  1887. flex: 0 1 110px;
  1888. min-width: 60px;
  1889. }
  1890. .record-remark {
  1891. width: 180px;
  1892. flex: 0 1 180px;
  1893. min-width: 60px;
  1894. color: var(--muted);
  1895. font-size: calc(13.5px + var(--font-delta));
  1896. }
  1897. .record-time {
  1898. width: 170px;
  1899. flex: 0 1 170px;
  1900. min-width: 90px;
  1901. color: var(--muted);
  1902. font-size: calc(13.5px + var(--font-delta));
  1903. }
  1904. .record-del {
  1905. flex-shrink: 0;
  1906. margin-left: auto;
  1907. }
  1908. /* 自定义自动补全下拉:挂到 body,绝对定位于输入框下方 */
  1909. .record-ac {
  1910. position: fixed;
  1911. z-index: 9999;
  1912. max-height: 220px;
  1913. overflow-y: auto;
  1914. background: var(--glass-strong);
  1915. border: 1px solid var(--glass-border);
  1916. border-radius: var(--radius);
  1917. box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  1918. padding: 4px;
  1919. }
  1920. .record-ac-item {
  1921. padding: 7px 10px;
  1922. border-radius: calc(var(--radius) - 4px);
  1923. cursor: pointer;
  1924. font-size: calc(14.5px + var(--font-delta));
  1925. color: var(--ink);
  1926. }
  1927. .record-ac-item:hover {
  1928. background: rgba(255, 77, 77, 0.16);
  1929. }
  1930. /* 添加按钮区 */
  1931. .record-actions {
  1932. display: flex;
  1933. justify-content: flex-start;
  1934. }
  1935. .record-status {
  1936. min-height: 16px;
  1937. color: var(--muted);
  1938. font-size: calc(14px + var(--font-delta));
  1939. }
  1940. /* ---------- 主机页 ---------- */
  1941. .host-cards {
  1942. display: grid;
  1943. grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  1944. gap: 12px;
  1945. margin-bottom: 18px;
  1946. }
  1947. .host-cards .card p {
  1948. font-variant-numeric: tabular-nums;
  1949. word-break: break-all;
  1950. }
  1951. /* 卡片标题行内嵌操作按钮(如 API 服务右上角的「停止/启动」) */
  1952. .card-title-row {
  1953. display: flex;
  1954. align-items: center;
  1955. justify-content: space-between;
  1956. gap: 10px;
  1957. margin-bottom: 6px;
  1958. }
  1959. .card-title-row .btn-ghost {
  1960. font-size: calc(12px + var(--font-delta));
  1961. padding: 4px 10px;
  1962. }
  1963. /* 服务运行中:按钮高亮(「停止服务」态) */
  1964. #api-toggle.is-active {
  1965. color: var(--brand-text, #2d7d46);
  1966. border-color: currentColor;
  1967. }
  1968. /* 文件上传卡片 */
  1969. .upload-box {
  1970. display: flex;
  1971. flex-direction: column;
  1972. gap: 10px;
  1973. }
  1974. .upload-box input[type="password"] {
  1975. width: 100%;
  1976. padding: 8px 10px;
  1977. border-radius: 8px;
  1978. border: 1px solid var(--border, rgba(127,127,127,0.25));
  1979. background: var(--input-bg, rgba(127,127,127,0.08));
  1980. color: var(--text, #e9ecf5);
  1981. font-size: calc(13px + var(--font-delta));
  1982. }
  1983. .upload-row {
  1984. display: flex;
  1985. gap: 8px;
  1986. align-items: center;
  1987. }
  1988. .upload-input {
  1989. flex: 1;
  1990. min-width: 0;
  1991. font-size: calc(12px + var(--font-delta));
  1992. color: var(--muted, #8b93a7);
  1993. }
  1994. .upload-progress {
  1995. height: 6px;
  1996. border-radius: 4px;
  1997. background: rgba(127,127,127,0.15);
  1998. overflow: hidden;
  1999. }
  2000. .upload-bar {
  2001. height: 100%;
  2002. width: 0%;
  2003. border-radius: 4px;
  2004. background: var(--brand, #4f8cff);
  2005. transition: width .15s ease;
  2006. }
  2007. .upload-result {
  2008. display: flex;
  2009. gap: 12px;
  2010. align-items: center;
  2011. padding-top: 6px;
  2012. }
  2013. .upload-qr {
  2014. width: 96px;
  2015. height: 96px;
  2016. border-radius: 8px;
  2017. padding: 6px;
  2018. background: #fff;
  2019. flex-shrink: 0;
  2020. }
  2021. .upload-qr img {
  2022. width: 100%;
  2023. height: 100%;
  2024. object-fit: contain;
  2025. display: block;
  2026. }
  2027. .upload-meta {
  2028. min-width: 0;
  2029. display: flex;
  2030. flex-direction: column;
  2031. gap: 4px;
  2032. }
  2033. .upload-name {
  2034. font-size: calc(13px + var(--font-delta));
  2035. color: var(--text, #e9ecf5);
  2036. word-break: break-all;
  2037. }
  2038. .upload-link {
  2039. font-size: calc(12px + var(--font-delta));
  2040. color: var(--brand-text, #4f8cff);
  2041. text-decoration: none;
  2042. word-break: break-all;
  2043. }
  2044. .upload-link:hover {
  2045. text-decoration: underline;
  2046. }
  2047. /* 客户端上传页地址文字 */
  2048. .client-upload-url {
  2049. margin-top: 10px;
  2050. font-size: calc(12px + var(--font-delta));
  2051. color: var(--muted, #8b93a7);
  2052. word-break: break-all;
  2053. text-align: center;
  2054. }
  2055. .section-title {
  2056. margin: 0 0 10px;
  2057. color: var(--ink);
  2058. font-size: calc(16px + var(--font-delta));
  2059. font-weight: 650;
  2060. }
  2061. /* 标题行内嵌操作按钮(如 Gin 日志右侧的「清空日志」) */
  2062. .section-title-row {
  2063. display: flex;
  2064. align-items: center;
  2065. justify-content: space-between;
  2066. gap: 10px;
  2067. }
  2068. .section-title-row .btn-ghost {
  2069. font-size: calc(12px + var(--font-delta));
  2070. padding: 4px 10px;
  2071. }
  2072. /* 截屏预览区 */
  2073. .screenshot-box {
  2074. margin-bottom: 18px;
  2075. padding: 12px;
  2076. border: 1px solid var(--glass-border);
  2077. border-radius: var(--radius);
  2078. background: var(--glass);
  2079. }
  2080. .screenshot-head {
  2081. display: flex;
  2082. align-items: center;
  2083. justify-content: space-between;
  2084. margin-bottom: 10px;
  2085. }
  2086. .screenshot-head .card-title {
  2087. margin-bottom: 0;
  2088. }
  2089. .screenshot-hint {
  2090. color: var(--muted);
  2091. font-size: calc(13.5px + var(--font-delta));
  2092. font-variant-numeric: tabular-nums;
  2093. }
  2094. .screenshot-box img {
  2095. display: block;
  2096. max-width: 100%;
  2097. max-height: 320px;
  2098. margin: 0 auto;
  2099. border-radius: 8px;
  2100. border: 1px solid var(--glass-border);
  2101. object-fit: contain;
  2102. background: rgba(0, 0, 0, 0.3);
  2103. }
  2104. /* ---------- 工具页:Web 服务 ---------- */
  2105. .tool-card {
  2106. margin-bottom: 14px;
  2107. padding: 16px;
  2108. border: 1px solid var(--glass-border);
  2109. border-radius: var(--radius);
  2110. background: var(--glass);
  2111. /* 功能卡片间的区隔:上边缘用更明显分隔 */
  2112. position: relative;
  2113. }
  2114. .tool-card + .tool-card {
  2115. border-top: 1px solid var(--glass-border);
  2116. }
  2117. .tool-card-head {
  2118. display: flex;
  2119. align-items: center;
  2120. justify-content: space-between;
  2121. margin-bottom: 8px;
  2122. cursor: pointer;
  2123. user-select: none;
  2124. border-radius: 8px;
  2125. }
  2126. .tool-card-head:focus-visible {
  2127. outline: 2px solid var(--accent);
  2128. outline-offset: 2px;
  2129. }
  2130. .tool-card-head:hover .tool-arrow {
  2131. color: var(--accent);
  2132. }
  2133. .tool-card-title {
  2134. display: inline-flex;
  2135. align-items: center;
  2136. gap: 8px;
  2137. color: var(--ink);
  2138. font-size: calc(17px + var(--font-delta));
  2139. font-weight: 650;
  2140. }
  2141. /* 折叠箭头:▸ 展开态旋转为 ▾ */
  2142. .tool-arrow {
  2143. display: inline-block;
  2144. font-size: 12px;
  2145. line-height: 1;
  2146. color: var(--muted);
  2147. transition: transform 0.2s ease, color 0.15s ease;
  2148. }
  2149. .tool-card:not(.is-collapsed) .tool-arrow {
  2150. transform: rotate(90deg);
  2151. }
  2152. /* 折叠时隐藏功能主体 */
  2153. .tool-card-body {
  2154. overflow: hidden;
  2155. }
  2156. .tool-card.is-collapsed .tool-card-body {
  2157. display: none;
  2158. }
  2159. /* 折叠时收起头部下边距 */
  2160. .tool-card.is-collapsed .tool-card-head {
  2161. margin-bottom: 0;
  2162. }
  2163. .tool-card-title .dot {
  2164. width: 8px;
  2165. height: 8px;
  2166. border-radius: 50%;
  2167. background: var(--accent);
  2168. }
  2169. .tool-status {
  2170. color: var(--muted);
  2171. font-size: calc(14px + var(--font-delta));
  2172. white-space: nowrap;
  2173. }
  2174. .tool-status.is-on {
  2175. color: #3ddc84;
  2176. }
  2177. .tool-status .tool-url {
  2178. color: #3ddc84;
  2179. text-decoration: underline;
  2180. text-underline-offset: 2px;
  2181. margin-left: 4px;
  2182. }
  2183. .tool-status .tool-url:hover {
  2184. color: #6ff0a8;
  2185. }
  2186. /* 工具排序按钮:标题右侧的上移/下移,悬停才显示,避免视觉干扰 */
  2187. .tool-order-btns {
  2188. display: inline-flex;
  2189. gap: 4px;
  2190. margin-left: 10px;
  2191. opacity: 0;
  2192. transition: opacity 0.15s ease;
  2193. }
  2194. .tool-card-head:hover .tool-order-btns {
  2195. opacity: 1;
  2196. }
  2197. .tool-order-btn {
  2198. display: inline-flex;
  2199. align-items: center;
  2200. justify-content: center;
  2201. width: 22px;
  2202. height: 22px;
  2203. padding: 0;
  2204. border: 1px solid var(--glass-border);
  2205. border-radius: 6px;
  2206. background: var(--glass-strong);
  2207. color: var(--muted);
  2208. font-size: 12px;
  2209. line-height: 1;
  2210. cursor: pointer;
  2211. user-select: none;
  2212. }
  2213. .tool-order-btn:hover {
  2214. color: var(--accent);
  2215. border-color: var(--accent);
  2216. }
  2217. .tool-order-btn:disabled {
  2218. opacity: 0.3;
  2219. cursor: default;
  2220. }
  2221. .tool-order-btn:disabled:hover {
  2222. color: var(--muted);
  2223. border-color: var(--glass-border);
  2224. }
  2225. .tool-order-btn:focus-visible {
  2226. outline: 2px solid var(--accent);
  2227. outline-offset: 1px;
  2228. }
  2229. .tool-desc {
  2230. margin: 0 0 12px;
  2231. color: var(--muted);
  2232. font-size: calc(14.5px + var(--font-delta));
  2233. }
  2234. .tool-desc code {
  2235. padding: 1px 5px;
  2236. border-radius: 4px;
  2237. background: var(--glass-strong);
  2238. color: var(--ink);
  2239. font-family: Consolas, "Courier New", monospace;
  2240. }
  2241. .tool-row {
  2242. display: flex;
  2243. align-items: center;
  2244. gap: 10px;
  2245. margin-bottom: 12px;
  2246. }
  2247. .tool-row.tool-actions {
  2248. margin-bottom: 0;
  2249. }
  2250. .tool-dir {
  2251. flex: 1;
  2252. min-width: 0;
  2253. }
  2254. .tool-hint {
  2255. color: var(--muted);
  2256. font-size: calc(13.5px + var(--font-delta));
  2257. }
  2258. /* 颜色选择器:色块 + 标签,用于 LED 点阵颜色等 */
  2259. .color-field {
  2260. display: inline-flex;
  2261. align-items: center;
  2262. gap: 6px;
  2263. font-size: calc(13.5px + var(--font-delta));
  2264. color: var(--text);
  2265. cursor: pointer;
  2266. background: var(--glass);
  2267. border: 1px solid var(--glass-border);
  2268. border-radius: var(--radius-sm);
  2269. padding: 5px 10px 5px 6px;
  2270. }
  2271. .color-field input[type="color"] {
  2272. width: 26px;
  2273. height: 26px;
  2274. padding: 0;
  2275. border: none;
  2276. border-radius: 6px;
  2277. background: transparent;
  2278. cursor: pointer;
  2279. }
  2280. .color-field input[type="color"]::-webkit-color-swatch-wrapper {
  2281. padding: 0;
  2282. }
  2283. .color-field input[type="color"]::-webkit-color-swatch {
  2284. border: none;
  2285. border-radius: 6px;
  2286. }
  2287. /* 速度输入框:数字 + 标签,用于 LED 滚动速度等 */
  2288. .speed-field {
  2289. display: inline-flex;
  2290. align-items: center;
  2291. gap: 6px;
  2292. font-size: calc(13.5px + var(--font-delta));
  2293. color: var(--text);
  2294. background: var(--glass);
  2295. border: 1px solid var(--glass-border);
  2296. border-radius: var(--radius-sm);
  2297. padding: 5px 10px 5px 8px;
  2298. }
  2299. .speed-field input[type="number"] {
  2300. width: 60px;
  2301. padding: 3px 6px;
  2302. font-size: calc(13px + var(--font-delta));
  2303. color: var(--text);
  2304. background: var(--panel);
  2305. border: 1px solid var(--glass-border);
  2306. border-radius: 6px;
  2307. outline: none;
  2308. }
  2309. .speed-field input[type="number"]:focus {
  2310. border-color: var(--accent);
  2311. }
  2312. .websvc-preview {
  2313. margin-top: 14px;
  2314. height: 320px;
  2315. border: 1px solid var(--glass-border);
  2316. border-radius: var(--radius);
  2317. overflow: hidden;
  2318. background: rgba(0, 0, 0, 0.25);
  2319. }
  2320. .websvc-preview iframe {
  2321. width: 100%;
  2322. height: 100%;
  2323. border: none;
  2324. }
  2325. /* LocalSend 文件互传 */
  2326. .localsend-config {
  2327. margin: 12px 0 4px;
  2328. padding: 10px 12px;
  2329. border: 1px solid var(--glass-border);
  2330. border-radius: var(--radius-sm);
  2331. background: var(--glass);
  2332. }
  2333. .localsend-config .tool-row {
  2334. margin-bottom: 10px;
  2335. }
  2336. .localsend-config .tool-row:last-child {
  2337. margin-bottom: 0;
  2338. }
  2339. .tool-label {
  2340. min-width: 64px;
  2341. font-size: calc(13.5px + var(--font-delta));
  2342. color: var(--muted);
  2343. }
  2344. .localsend-config .input {
  2345. flex: 1;
  2346. min-width: 0;
  2347. }
  2348. .radio-field {
  2349. display: inline-flex;
  2350. align-items: center;
  2351. gap: 5px;
  2352. font-size: calc(13.5px + var(--font-delta));
  2353. color: var(--text);
  2354. cursor: pointer;
  2355. }
  2356. .radio-field input[type="radio"] {
  2357. accent-color: var(--accent);
  2358. cursor: pointer;
  2359. }
  2360. .localsend-devices {
  2361. margin-top: 14px;
  2362. }
  2363. .localsend-device-list {
  2364. list-style: none;
  2365. margin: 8px 0 0;
  2366. padding: 0;
  2367. display: flex;
  2368. flex-direction: column;
  2369. gap: 6px;
  2370. }
  2371. .localsend-device-list li {
  2372. display: flex;
  2373. align-items: center;
  2374. justify-content: space-between;
  2375. gap: 10px;
  2376. padding: 8px 10px;
  2377. border: 1px solid var(--glass-border);
  2378. border-radius: var(--radius-sm);
  2379. background: var(--glass);
  2380. font-size: calc(13.5px + var(--font-delta));
  2381. }
  2382. .localsend-device-list .ls-dev-name {
  2383. color: var(--ink);
  2384. font-weight: 500;
  2385. }
  2386. .localsend-device-list .ls-dev-meta {
  2387. color: var(--muted);
  2388. font-size: calc(12.5px + var(--font-delta));
  2389. }
  2390. .localsend-device-list .ls-dev-online {
  2391. color: #3ddc84;
  2392. font-size: calc(12px + var(--font-delta));
  2393. }
  2394. .localsend-empty {
  2395. color: var(--muted);
  2396. font-size: calc(13px + var(--font-delta));
  2397. padding: 6px 2px;
  2398. }
  2399. /* LocalSend 文件接收确认弹窗 */
  2400. .ls-offer-mask {
  2401. position: fixed;
  2402. inset: 0;
  2403. z-index: 3000;
  2404. display: flex;
  2405. align-items: center;
  2406. justify-content: center;
  2407. background: rgba(0, 0, 0, 0.55);
  2408. backdrop-filter: blur(4px);
  2409. }
  2410. /* 必须显式覆盖:display:flex 会覆盖 HTML hidden 属性的 display:none,
  2411. 否则弹窗常驻显示且点击接受/拒绝后无法隐藏 */
  2412. .ls-offer-mask[hidden] {
  2413. display: none;
  2414. }
  2415. .ls-offer-dialog {
  2416. width: min(440px, 90vw);
  2417. max-height: 80vh;
  2418. overflow: auto;
  2419. padding: 22px 24px;
  2420. border: 1px solid var(--glass-border);
  2421. border-radius: var(--radius);
  2422. background: var(--panel);
  2423. box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
  2424. }
  2425. .ls-offer-title {
  2426. font-size: calc(16px + var(--font-delta));
  2427. font-weight: 600;
  2428. color: var(--ink);
  2429. margin-bottom: 8px;
  2430. }
  2431. .ls-offer-sender {
  2432. font-size: calc(13.5px + var(--font-delta));
  2433. color: var(--muted);
  2434. margin-bottom: 12px;
  2435. }
  2436. .ls-offer-files {
  2437. list-style: none;
  2438. margin: 0 0 16px;
  2439. padding: 0;
  2440. display: flex;
  2441. flex-direction: column;
  2442. gap: 6px;
  2443. }
  2444. .ls-offer-files li {
  2445. display: flex;
  2446. align-items: center;
  2447. justify-content: space-between;
  2448. gap: 10px;
  2449. padding: 8px 10px;
  2450. border: 1px solid var(--glass-border);
  2451. border-radius: var(--radius-sm);
  2452. background: var(--glass);
  2453. font-size: calc(13.5px + var(--font-delta));
  2454. }
  2455. .ls-offer-files .ls-file-name {
  2456. color: var(--ink);
  2457. overflow: hidden;
  2458. text-overflow: ellipsis;
  2459. white-space: nowrap;
  2460. }
  2461. .ls-offer-files .ls-file-size {
  2462. color: var(--muted);
  2463. font-size: calc(12.5px + var(--font-delta));
  2464. white-space: nowrap;
  2465. }
  2466. .ls-offer-actions {
  2467. display: flex;
  2468. justify-content: flex-end;
  2469. gap: 10px;
  2470. }
  2471. /* 翻译工具:输入框 + 结果区 */
  2472. .tr-input {
  2473. width: 100%;
  2474. resize: vertical;
  2475. min-height: 72px;
  2476. font-family: inherit;
  2477. }
  2478. .tr-input:focus {
  2479. outline: none;
  2480. border-color: var(--accent);
  2481. box-shadow: 0 0 0 3px rgba(255, 77, 77, 0.14);
  2482. }
  2483. .tr-result {
  2484. margin-top: 12px;
  2485. padding: 12px 14px;
  2486. border: 1px solid var(--glass-border);
  2487. border-radius: var(--radius);
  2488. background: var(--glass-strong);
  2489. color: var(--ink);
  2490. font-size: calc(16px + var(--font-delta));
  2491. line-height: 1.7;
  2492. white-space: pre-wrap;
  2493. word-break: break-word;
  2494. user-select: text;
  2495. }
  2496. /* MD5 / SHA256 哈希结果:等宽字体 + 可复制 */
  2497. .hash-result {
  2498. margin-top: 12px;
  2499. padding: 12px 14px;
  2500. border: 1px solid var(--glass-border);
  2501. border-radius: var(--radius);
  2502. background: var(--glass-strong);
  2503. color: var(--accent);
  2504. font-family: Consolas, "Courier New", monospace;
  2505. font-size: calc(13px + var(--font-delta));
  2506. line-height: 1.6;
  2507. word-break: break-all;
  2508. user-select: text;
  2509. cursor: text;
  2510. }
  2511. /* 二维码工具:图片展示区 + 下载按钮 */
  2512. .qr-box {
  2513. margin-top: 12px;
  2514. display: flex;
  2515. flex-direction: column;
  2516. align-items: center;
  2517. gap: 10px;
  2518. padding: 14px;
  2519. border: 1px solid var(--glass-border);
  2520. border-radius: var(--radius);
  2521. background: var(--glass-strong);
  2522. }
  2523. .qr-box img {
  2524. width: 240px;
  2525. height: 240px;
  2526. border-radius: 8px;
  2527. background: #fff; /* 二维码白底,确保扫描清晰 */
  2528. padding: 8px;
  2529. cursor: pointer;
  2530. }
  2531. /* ntfy 聊天室:消息列表容器 + 单条消息 */
  2532. .chat-box {
  2533. margin-top: 12px;
  2534. border: 1px solid var(--glass-border);
  2535. border-radius: var(--radius);
  2536. background: var(--glass-strong);
  2537. overflow: hidden;
  2538. }
  2539. .chat-list {
  2540. max-height: 320px;
  2541. overflow-y: auto;
  2542. padding: 12px 10px;
  2543. display: flex;
  2544. flex-direction: column;
  2545. gap: 10px;
  2546. }
  2547. /* QQ 风格:一条消息(头像 + 主体),他人靠左、自己(.mine)靠右 */
  2548. .chat-msg {
  2549. display: flex;
  2550. align-items: flex-start;
  2551. gap: 8px;
  2552. max-width: 100%;
  2553. }
  2554. .chat-msg.mine {
  2555. flex-direction: row-reverse; /* 自己的消息头像在右 */
  2556. }
  2557. .chat-avatar {
  2558. flex: 0 0 auto;
  2559. width: 34px;
  2560. height: 34px;
  2561. border-radius: 50%;
  2562. background: linear-gradient(135deg, #4f8cff, #7b5cff);
  2563. color: #fff;
  2564. font-weight: 700;
  2565. font-size: calc(14px + var(--font-delta));
  2566. display: flex;
  2567. align-items: center;
  2568. justify-content: center;
  2569. user-select: none;
  2570. }
  2571. .chat-msg.mine .chat-avatar {
  2572. background: linear-gradient(135deg, #23c88a, #0fa5c8); /* 自己的头像用绿色系 */
  2573. }
  2574. .chat-msg-main {
  2575. display: flex;
  2576. flex-direction: column;
  2577. align-items: flex-start;
  2578. max-width: 72%;
  2579. }
  2580. .chat-msg.mine .chat-msg-main {
  2581. align-items: flex-end; /* 自己的内容靠右对齐 */
  2582. }
  2583. .chat-msg-head {
  2584. display: flex;
  2585. align-items: baseline;
  2586. gap: 8px;
  2587. margin-bottom: 3px;
  2588. padding: 0 2px;
  2589. }
  2590. .chat-msg-title {
  2591. font-weight: 600;
  2592. font-size: calc(12px + var(--font-delta));
  2593. color: var(--muted);
  2594. }
  2595. .chat-msg-time {
  2596. font-size: calc(10px + var(--font-delta));
  2597. color: var(--muted);
  2598. opacity: 0.8;
  2599. white-space: nowrap;
  2600. }
  2601. /* 气泡本体:他人灰底、自己主题色底 */
  2602. .chat-bubble {
  2603. padding: 8px 12px;
  2604. border-radius: 10px;
  2605. background: rgba(0, 0, 0, 0.12);
  2606. border: 1px solid var(--glass-border);
  2607. color: var(--text);
  2608. font-size: calc(13px + var(--font-delta));
  2609. line-height: 1.55;
  2610. white-space: pre-wrap;
  2611. word-break: break-word;
  2612. -webkit-user-select: text;
  2613. user-select: text;
  2614. border-top-left-radius: 2px; /* 靠近头像一角收尖,QQ 风格 */
  2615. }
  2616. .chat-msg.mine .chat-bubble {
  2617. background: var(--brand, #2d7d46);
  2618. border-color: transparent;
  2619. color: var(--brand-on, #fff);
  2620. border-top-right-radius: 2px;
  2621. border-top-left-radius: 10px;
  2622. }
  2623. /* 消息输入行 */
  2624. .chat-input-row {
  2625. display: flex;
  2626. gap: 8px;
  2627. padding: 8px 10px;
  2628. border-top: 1px solid var(--glass-border);
  2629. }
  2630. .chat-input-row .input {
  2631. flex: 1;
  2632. }
  2633. /* 工具页「古诗词」卡片 */
  2634. .poem-tool {
  2635. margin-top: 12px;
  2636. padding: 14px 16px;
  2637. border-radius: var(--radius);
  2638. background: var(--glass-strong);
  2639. border: 1px solid var(--glass-border);
  2640. text-align: center;
  2641. }
  2642. .poem-tool-title {
  2643. font-size: calc(16px + var(--font-delta));
  2644. font-weight: 700;
  2645. color: var(--poem-color, #c98a3a);
  2646. margin-bottom: 4px;
  2647. }
  2648. .poem-tool-author {
  2649. font-size: calc(12px + var(--font-delta));
  2650. color: var(--muted);
  2651. margin-bottom: 10px;
  2652. }
  2653. .poem-tool-content p {
  2654. margin: 2px 0;
  2655. font-size: calc(14px + var(--font-delta));
  2656. color: var(--text);
  2657. line-height: 1.7;
  2658. -webkit-user-select: text;
  2659. user-select: text;
  2660. }
  2661. /* 日志视图:等宽字体,固定高度内部滚动 */
  2662. .log-view {
  2663. margin: 0;
  2664. padding: 12px 14px;
  2665. height: 300px;
  2666. overflow-y: auto;
  2667. border: 1px solid var(--glass-border);
  2668. border-radius: var(--radius);
  2669. background: rgba(0, 0, 0, 0.25);
  2670. color: var(--muted);
  2671. font-size: calc(13.5px + var(--font-delta));
  2672. font-family: "Consolas", "Courier New", monospace;
  2673. line-height: 1.65;
  2674. white-space: pre-wrap;
  2675. word-break: break-all;
  2676. -webkit-user-select: text;
  2677. user-select: text;
  2678. }
  2679. :root[data-theme="light"] .log-view {
  2680. background: rgba(20, 26, 40, 0.06);
  2681. }
  2682. /* ---------- 设置页新增控件 ---------- */
  2683. /* 纵向排列的设置行(文本域类) */
  2684. .setting-row-col {
  2685. flex-direction: column;
  2686. align-items: stretch;
  2687. }
  2688. .textarea {
  2689. width: 100%;
  2690. height: auto;
  2691. padding: 10px 12px;
  2692. line-height: 1.6;
  2693. resize: vertical;
  2694. font-family: inherit;
  2695. }
  2696. /* 滚动条配置控件组:开关 + 字号 + 颜色 + 速度 */
  2697. .ticker-controls {
  2698. display: flex;
  2699. align-items: center;
  2700. gap: 10px;
  2701. flex-shrink: 0;
  2702. flex-wrap: wrap;
  2703. justify-content: flex-end;
  2704. }
  2705. .input-num {
  2706. width: 72px;
  2707. text-align: center;
  2708. }
  2709. /* 颜色选择器:与输入框同高的小色块 */
  2710. .input-color {
  2711. width: 40px;
  2712. height: 32px;
  2713. padding: 2px;
  2714. border: 1px solid var(--glass-border);
  2715. border-radius: 8px;
  2716. background: rgba(127, 127, 127, 0.10);
  2717. cursor: pointer;
  2718. }
  2719. /* 数字输入 + 单位:一行内右对齐(刷新间隔等) */
  2720. .num-group {
  2721. display: inline-flex;
  2722. align-items: center;
  2723. gap: 6px;
  2724. flex-shrink: 0;
  2725. }
  2726. .num-group .input-num {
  2727. width: 84px;
  2728. }
  2729. .num-unit {
  2730. color: var(--muted);
  2731. font-size: calc(14px + var(--font-delta));
  2732. white-space: nowrap;
  2733. }
  2734. /* 指定浏览器路径:输入框 + 选择/清除按钮 */
  2735. .browser-path-group {
  2736. display: flex;
  2737. align-items: center;
  2738. gap: 6px;
  2739. min-width: 0;
  2740. }
  2741. .browser-path-group .input {
  2742. flex: 1;
  2743. min-width: 120px;
  2744. }
  2745. /* 迷你勾选框(滚动条「透明」等):小号文字 + 原生 checkbox */
  2746. .mini-label {
  2747. display: inline-flex;
  2748. align-items: center;
  2749. gap: 4px;
  2750. color: var(--muted);
  2751. font-size: calc(14px + var(--font-delta));
  2752. cursor: pointer;
  2753. white-space: nowrap;
  2754. }
  2755. .mini-label input[type="checkbox"] {
  2756. width: 14px;
  2757. height: 14px;
  2758. margin: 0;
  2759. accent-color: var(--accent);
  2760. cursor: pointer;
  2761. }
  2762. /* ---------- 主机:提供的功能列表 ---------- */
  2763. .api-list {
  2764. margin: 0 0 20px;
  2765. padding: 4px 0 4px 0;
  2766. list-style: none;
  2767. display: grid;
  2768. grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  2769. gap: 8px 14px;
  2770. }
  2771. .api-list li {
  2772. display: flex;
  2773. align-items: baseline;
  2774. gap: 8px;
  2775. padding: 8px 10px;
  2776. border: 1px solid var(--glass-border);
  2777. border-radius: 8px;
  2778. background: var(--glass);
  2779. color: var(--muted);
  2780. font-size: calc(14px + var(--font-delta));
  2781. line-height: 1.5;
  2782. }
  2783. .api-list code {
  2784. flex-shrink: 0;
  2785. padding: 1px 6px;
  2786. border-radius: 5px;
  2787. background: rgba(127, 127, 127, 0.14);
  2788. color: var(--ink);
  2789. font-family: "Consolas", "Courier New", monospace;
  2790. font-size: calc(13px + var(--font-delta));
  2791. white-space: nowrap;
  2792. }
  2793. /* ---------- 刷新按钮加载动画(Github 等) ---------- */
  2794. .btn-ghost.loading {
  2795. position: relative;
  2796. padding-left: 32px; /* 为转圈图标让位 */
  2797. color: var(--muted);
  2798. pointer-events: none; /* 加载中不可再次点击 */
  2799. }
  2800. .btn-ghost.loading::before {
  2801. content: "";
  2802. position: absolute;
  2803. left: 10px;
  2804. top: 50%;
  2805. width: 14px;
  2806. height: 14px;
  2807. margin-top: -7px;
  2808. border: 2px solid var(--muted);
  2809. border-top-color: transparent; /* 顶部透明形成弧形缺口 */
  2810. border-radius: 50%;
  2811. animation: spin 0.8s linear infinite;
  2812. }
  2813. @keyframes spin {
  2814. to { transform: rotate(360deg); }
  2815. }
  2816. /* ============================== 移动端 ============================== */
  2817. @media (max-width: 640px) {
  2818. .tab-panel {
  2819. padding: 18px 16px 20px;
  2820. }
  2821. /* 标签栏:窄屏横向滚动,容纳全部 tab(基础样式已统一定义,此处只收紧内边距) */
  2822. .tab-btn {
  2823. padding: 0 12px;
  2824. }
  2825. .setting-row {
  2826. flex-direction: column; /* 窄屏设置项纵向排列 */
  2827. align-items: flex-start;
  2828. }
  2829. .input {
  2830. width: 100%; /* 窄屏输入框铺满 */
  2831. }
  2832. .hotkey-input {
  2833. width: 100%; /* 窄屏热键输入框同样铺满 */
  2834. }
  2835. .ticker-controls {
  2836. justify-content: flex-start; /* 窄屏滚动条控件靠左换行 */
  2837. }
  2838. .num-group .input-num {
  2839. width: 72px; /* 窄屏数字输入收窄 */
  2840. }
  2841. .api-list {
  2842. grid-template-columns: 1fr; /* 窄屏功能列表单列 */
  2843. }
  2844. .stock-row {
  2845. grid-template-columns: 1fr auto; /* 窄屏精简为两列 */
  2846. row-gap: 4px;
  2847. }
  2848. .stock-change {
  2849. align-items: flex-end;
  2850. }
  2851. .stock-amount {
  2852. justify-self: start; /* 窄屏成交额换行靠左 */
  2853. }
  2854. .news-row {
  2855. flex-wrap: wrap; /* 窄屏来源标签与标题可换行 */
  2856. }
  2857. .commit-time {
  2858. display: none; /* 窄屏隐藏提交时间,优先标题 */
  2859. }
  2860. /* 图表弹窗窄屏近全屏 */
  2861. .chart-dialog {
  2862. width: 96vw;
  2863. height: 84vh;
  2864. padding: 12px;
  2865. }
  2866. .chart-head {
  2867. flex-wrap: wrap;
  2868. gap: 8px;
  2869. }
  2870. .host-cards {
  2871. grid-template-columns: 1fr; /* 窄屏主机卡片单列 */
  2872. }
  2873. .log-view {
  2874. height: 220px;
  2875. font-size: calc(12.5px + var(--font-delta));
  2876. }
  2877. .tab-panel h2 {
  2878. font-size: calc(20px + var(--font-delta));
  2879. }
  2880. .card-grid {
  2881. grid-template-columns: 1fr; /* 窄屏单列 */
  2882. gap: 10px;
  2883. }
  2884. .footer {
  2885. font-size: calc(13px + var(--font-delta));
  2886. gap: 4px;
  2887. }
  2888. /* 面板头部:窄屏标题与按钮同排可换行 */
  2889. .panel-head {
  2890. flex-wrap: wrap;
  2891. gap: 10px;
  2892. }
  2893. /* 分组标题与设置行:窄屏收紧间距 */
  2894. .setting-group {
  2895. padding: 10px 10px 12px; /* 窄屏收紧分组卡片内边距 */
  2896. }
  2897. .setting-group-title {
  2898. margin: 0 4px 4px;
  2899. }
  2900. /* 新闻 / 股票列表:窄屏让出高度,避免底部被遮挡 */
  2901. .news-list, .repo-list, .stock-list {
  2902. max-height: calc(100dvh - 170px);
  2903. }
  2904. /* 步进器与分段控件:窄屏不挤压 */
  2905. .stepper, .segmented {
  2906. width: 100%;
  2907. justify-content: flex-end;
  2908. }
  2909. .segmented .seg-btn {
  2910. flex: 1;
  2911. }
  2912. }