base.css 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /* ==========================================================================
  2. 基础排版 & 布局骨架(v3)
  3. - 光场 .ambient:四团色光 + 左上斜下的天光,极缓漂移(尊重 reduced-motion)
  4. - 噪点 .grain:细颗粒,让玻璃像材质而不是纯渐变
  5. - 侧栏/顶栏:整片玻璃(L3),与内容区背景形成"浮在上面的玻璃层"
  6. ========================================================================== */
  7. *,*::before,*::after{box-sizing:border-box}
  8. html,body{margin:0;padding:0}
  9. html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
  10. body{
  11. font-family:var(--font);
  12. font-size:14px;line-height:1.55;color:var(--ink);
  13. background:var(--bg);
  14. -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  15. text-rendering:optimizeLegibility;
  16. min-height:100vh;overflow-x:hidden;
  17. }
  18. h1,h2,h3,h4,h5,p,ul,ol,dl,dd,figure{margin:0}
  19. ul,ol{padding:0;list-style:none}
  20. a{color:var(--accent-ink);text-decoration:none}
  21. a:hover{text-decoration:underline;text-underline-offset:3px}
  22. button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}
  23. input,select{font:inherit;color:inherit}
  24. img{max-width:100%}
  25. :focus-visible{outline:2px solid var(--accent-line);outline-offset:2px;border-radius:8px}
  26. ::selection{background:rgba(29,92,240,.16)}
  27. /* 数字:等宽数字保证列对齐;小单位用自己的字号层级 */
  28. .num{font-family:var(--font-num);font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}
  29. .ta-r{text-align:right}
  30. /* ---------- 光场(装饰层,永不承载内容) ---------- */
  31. .ambient{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
  32. .ambient::before{
  33. /* 从左上斜下的天光:这是"光源"本身 */
  34. content:"";position:absolute;inset:0;
  35. background:
  36. radial-gradient(120% 90% at 8% -10%, rgba(255,255,255,.95) 0%, rgba(255,255,255,.35) 32%, rgba(255,255,255,0) 62%);
  37. }
  38. .ambient i{position:absolute;display:block;border-radius:50%;filter:blur(70px);opacity:.85;will-change:transform}
  39. .ambient .b1{width:62vw;height:52vw;left:-16vw;top:-18vw;background:radial-gradient(circle at 40% 40%,rgba(122,167,255,.55),rgba(122,167,255,0) 68%);animation:drift1 46s ease-in-out infinite alternate}
  40. .ambient .b2{width:48vw;height:44vw;right:-12vw;top:-14vw;background:radial-gradient(circle at 50% 50%,rgba(227,211,255,.75),rgba(227,211,255,0) 66%);animation:drift2 58s ease-in-out infinite alternate}
  41. .ambient .b3{width:52vw;height:46vw;left:-8vw;bottom:-26vw;background:radial-gradient(circle at 50% 50%,rgba(159,240,212,.55),rgba(159,240,212,0) 66%);animation:drift3 52s ease-in-out infinite alternate}
  42. .ambient .b4{width:46vw;height:40vw;right:-10vw;bottom:-22vw;background:radial-gradient(circle at 50% 50%,rgba(255,225,194,.7),rgba(255,225,194,0) 66%);animation:drift4 64s ease-in-out infinite alternate}
  43. @keyframes drift1{to{transform:translate3d(6vw,4vw,0) scale(1.08)}}
  44. @keyframes drift2{to{transform:translate3d(-5vw,6vw,0) scale(.94)}}
  45. @keyframes drift3{to{transform:translate3d(7vw,-4vw,0) scale(1.06)}}
  46. @keyframes drift4{to{transform:translate3d(-6vw,-5vw,0) scale(.95)}}
  47. /* 噪点:用 SVG 湍流生成,极淡叠加 */
  48. .grain{
  49. position:fixed;inset:0;z-index:0;pointer-events:none;opacity:.22;mix-blend-mode:soft-light;
  50. background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='100%' height='100%' filter='url(%23n)' opacity='.55'/></svg>");
  51. }
  52. /* ---------- 应用骨架 ---------- */
  53. .app{position:relative;z-index:1;display:grid;grid-template-columns:var(--sidebar) minmax(0,1fr);min-height:100vh}
  54. /* 侧栏:整片玻璃(L3)。边缘发丝边用伪元素画成渐变,上亮下暗 */
  55. .side{
  56. position:sticky;top:0;height:100vh;display:flex;flex-direction:column;
  57. padding:22px 14px 16px;
  58. background:linear-gradient(180deg,rgba(255,255,255,.58),rgba(255,255,255,.40));
  59. -webkit-backdrop-filter:var(--blur-3);backdrop-filter:var(--blur-3);
  60. border-right:1px solid rgba(255,255,255,.55);
  61. box-shadow:var(--light-top),var(--lift-1);
  62. }
  63. .brand{display:flex;align-items:center;gap:11px;padding:2px 10px 20px}
  64. .brand .mark{
  65. width:28px;height:28px;border-radius:9px;flex:none;position:relative;
  66. background:linear-gradient(150deg,rgba(255,255,255,.95),rgba(255,255,255,.45) 55%,rgba(160,185,255,.55));
  67. border:1px solid rgba(255,255,255,.85);
  68. box-shadow:var(--light-top),0 6px 14px -8px rgba(32,48,90,.35),inset 0 -6px 10px -6px rgba(122,167,255,.55);
  69. display:grid;place-items:center;font-size:12.5px;font-weight:700;color:var(--ink);
  70. }
  71. .brand .name{font-size:14.5px;font-weight:600;letter-spacing:.1px;line-height:1.25}
  72. .brand .sub{font-size:11px;color:var(--ink-3);margin-top:1px}
  73. .nav{display:flex;flex-direction:column;gap:2px}
  74. .nav-group{font-size:11px;color:var(--ink-4);padding:16px 12px 6px;letter-spacing:.6px}
  75. .nav a{
  76. display:flex;align-items:center;gap:9px;position:relative;
  77. padding:8px 12px;border-radius:11px;
  78. color:var(--ink-2);font-size:13.5px;text-decoration:none;
  79. border:1px solid transparent;
  80. transition:background .16s ease,color .16s ease,border-color .16s ease;
  81. }
  82. .nav a svg{width:15px;height:15px;opacity:.55;flex:none;margin-left:-2px}
  83. .nav a:hover{background:rgba(255,255,255,.42);color:var(--ink);text-decoration:none}
  84. .nav a:hover svg{opacity:.85}
  85. .nav a.on svg{opacity:1;color:var(--accent)}
  86. .nav a.on{
  87. background:linear-gradient(150deg,rgba(255,255,255,.92),rgba(255,255,255,.62));
  88. color:var(--ink);
  89. border-color:rgba(255,255,255,.95);
  90. box-shadow:var(--light-top),0 6px 16px -12px rgba(32,48,90,.4);
  91. }
  92. .nav a.on::before{content:"";position:absolute;left:-1px;top:9px;bottom:9px;width:2px;border-radius:2px;background:var(--accent);box-shadow:var(--accent-glow)}
  93. .nav a .cnt{margin-left:auto;font-size:11.5px;color:var(--ink-4);font-variant-numeric:tabular-nums}
  94. .nav a.on .cnt{color:var(--ink-3)}
  95. .side .foot{margin-top:auto;padding:12px 12px 0;border-top:1px solid var(--rule);font-size:11px;color:var(--ink-3);display:flex;align-items:center;gap:7px}
  96. .dot{width:6px;height:6px;border-radius:50%;background:var(--ink-4);flex:none}
  97. .dot.live{background:var(--ok);box-shadow:0 0 0 3px rgba(20,122,85,.14)}
  98. .dot.syncing{background:var(--warn);animation:pulse 1.2s ease-in-out infinite}
  99. .dot.err{background:var(--risk)}
  100. @keyframes pulse{50%{opacity:.35}}
  101. /* 主区 */
  102. .main{min-width:0;display:flex;flex-direction:column}
  103. /* 顶栏:同一片玻璃;滚动时内容从下面透过去 */
  104. .topbar{
  105. position:sticky;top:0;z-index:20;
  106. display:flex;align-items:center;gap:16px;
  107. min-height:var(--topbar);padding:0 clamp(20px,3vw,40px);
  108. background:linear-gradient(180deg,rgba(255,255,255,.62),rgba(255,255,255,.44));
  109. -webkit-backdrop-filter:var(--blur-3);backdrop-filter:var(--blur-3);
  110. border-bottom:1px solid rgba(255,255,255,.6);
  111. box-shadow:var(--light-top),0 10px 30px -24px rgba(32,48,90,.35);
  112. }
  113. .crumb{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--ink-3);min-width:0}
  114. .crumb a{color:var(--ink-3)}
  115. .crumb .sep{color:var(--ink-4)}
  116. .crumb .now{color:var(--ink);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:42ch}
  117. .topbar .tools{margin-left:auto;display:flex;align-items:center;gap:10px}
  118. /* 搜索 */
  119. .search{position:relative;display:flex;align-items:center}
  120. .search svg{position:absolute;left:11px;width:15px;height:15px;color:var(--ink-3);pointer-events:none}
  121. .search input{
  122. width:260px;height:36px;padding:0 34px 0 34px;border-radius:11px;
  123. border:1px solid rgba(255,255,255,.75);background:rgba(255,255,255,.42);
  124. box-shadow:var(--light-top),inset 0 1px 2px rgba(32,48,90,.05);
  125. font-size:13px;outline:none;transition:background .2s,border-color .2s,box-shadow .2s;
  126. }
  127. .search input::placeholder{color:var(--ink-3)}
  128. .search input:focus{background:rgba(255,255,255,.86);border-color:rgba(255,255,255,.98);box-shadow:var(--light-top),0 0 0 3px var(--accent-wash),0 1px 2px rgba(32,48,90,.05)}
  129. .search .clear{position:absolute;right:6px;width:22px;height:22px;border-radius:7px;display:grid;place-items:center;color:var(--ink-3)}
  130. .search .clear:hover{background:rgba(24,34,56,.07)}
  131. /* 内容区 */
  132. .view{padding:clamp(22px,3vw,40px) clamp(20px,3vw,40px) 80px;max-width:1560px;width:100%;margin:0 auto}
  133. .view-head{display:flex;align-items:flex-end;gap:16px;flex-wrap:wrap;margin-bottom:26px}
  134. .view-head h1{font-size:24px;font-weight:600;letter-spacing:-.3px;line-height:1.25}
  135. .view-head .lede{font-size:13px;color:var(--ink-3);margin-top:5px;max-width:68ch;line-height:1.65}
  136. .view-head .aside{margin-left:auto;display:flex;gap:8px;align-items:center}
  137. /* 区块标题 */
  138. .sec{display:flex;align-items:baseline;gap:10px;margin:34px 0 12px}
  139. .sec:first-child{margin-top:0}
  140. .sec h2{font-size:15px;font-weight:600;letter-spacing:.1px}
  141. .sec .hint{font-size:12px;color:var(--ink-3)}
  142. .sec .more{margin-left:auto;font-size:12.5px}
  143. /* ---------- 玻璃基元 ----------
  144. * .glass 是最小的玻璃面板:半透明白 + 背景模糊 + 发丝边 + 顶部内高光 + 极浅影。
  145. * 发丝边用双层背景实现:第一层画在 border-box 上做 1px 渐变边(上亮下暗),
  146. * 第二层是面板本体(稍微内缩),形成"边缘折光"的感觉。 */
  147. .glass{
  148. position:relative;
  149. background:
  150. var(--edge) border-box;
  151. border:1px solid transparent;
  152. border-radius:var(--r-lg);
  153. -webkit-backdrop-filter:var(--blur-2);backdrop-filter:var(--blur-2);
  154. box-shadow:var(--light-top),var(--lift-1);
  155. }
  156. /* 用 ::before 叠加一层半透明本体,避免 border-box 渐变把整块染色 */
  157. .glass::before{
  158. content:"";position:absolute;inset:-1px;border-radius:inherit;pointer-events:none;
  159. background:var(--glass-2);
  160. z-index:-1;
  161. }
  162. .glass > *{position:relative}
  163. .panel{
  164. position:relative;border-radius:var(--r-lg);overflow:hidden;
  165. background:var(--glass-1);
  166. -webkit-backdrop-filter:var(--blur-1);backdrop-filter:var(--blur-1);
  167. border:1px solid rgba(255,255,255,.6);
  168. box-shadow:var(--light-top),var(--lift-1);
  169. }
  170. .panel::after{
  171. /* 上亮下暗的边缘:顶部一条细高光,底部一条极淡暗边 */
  172. content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  173. background:linear-gradient(180deg,rgba(255,255,255,.28),rgba(255,255,255,0) 18%,rgba(255,255,255,0) 82%,rgba(255,255,255,.12));
  174. box-shadow:inset 0 -1px 0 rgba(32,48,90,.05);
  175. }
  176. .panel-pad{padding:20px 22px}
  177. .panel-head{display:flex;align-items:center;gap:10px;padding:14px 22px;border-bottom:1px solid var(--rule)}
  178. .panel-head h3{font-size:13.5px;font-weight:600}
  179. .panel-head .hint{margin-left:auto;font-size:12px;color:var(--ink-3)}
  180. /* 通用文字 */
  181. .muted{color:var(--ink-3)}
  182. .dim{color:var(--ink-2)}
  183. .tiny{font-size:12px}
  184. .mono-num{font-family:var(--font-num);font-variant-numeric:tabular-nums}
  185. /* 移动端菜单按钮 */
  186. .menu-btn{display:none;width:36px;height:36px;border-radius:11px;border:1px solid rgba(255,255,255,.8);background:rgba(255,255,255,.45);box-shadow:var(--light-top);place-items:center}
  187. .menu-btn svg{width:18px;height:18px}
  188. .scrim{display:none}
  189. /* ---------- 降级:不支持 backdrop-filter 时,玻璃退回"高亮度磨砂纸" ---------- */
  190. @supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  191. .panel{background:rgba(255,255,255,.80)}
  192. .side,.topbar{background:rgba(255,255,255,.86)}
  193. .ambient{opacity:.6}
  194. }
  195. /* 台账定位:?focus=<id> 时高亮那一行,并在结果区上方给出"你在找这条"的说明 */
  196. .focus-note{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 12px;padding:10px 14px;border-radius:12px;background:var(--accent-wash);box-shadow:inset 0 0 0 1px rgba(29,92,240,.16);font-size:12.5px;color:var(--ink-2)}
  197. .focus-note b{color:var(--accent-ink)}
  198. .tbl tbody tr.focus-on td{animation:focusRow 2.4s ease-out}
  199. @keyframes focusRow{0%,40%{background:rgba(29,92,240,.13)}100%{background:transparent}}