@jjlmoya/utils-science 1.21.0 → 1.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +2 -1
  3. package/src/entries.ts +3 -1
  4. package/src/index.ts +1 -0
  5. package/src/tests/locale_completeness.test.ts +2 -2
  6. package/src/tests/tool_validation.test.ts +2 -2
  7. package/src/tool/lorenz-attractor/bibliography.astro +14 -0
  8. package/src/tool/lorenz-attractor/bibliography.ts +12 -0
  9. package/src/tool/lorenz-attractor/component.astro +146 -0
  10. package/src/tool/lorenz-attractor/entry.ts +27 -0
  11. package/src/tool/lorenz-attractor/i18n/de.ts +141 -0
  12. package/src/tool/lorenz-attractor/i18n/en.ts +185 -0
  13. package/src/tool/lorenz-attractor/i18n/es.ts +141 -0
  14. package/src/tool/lorenz-attractor/i18n/fr.ts +141 -0
  15. package/src/tool/lorenz-attractor/i18n/id.ts +139 -0
  16. package/src/tool/lorenz-attractor/i18n/it.ts +140 -0
  17. package/src/tool/lorenz-attractor/i18n/ja.ts +139 -0
  18. package/src/tool/lorenz-attractor/i18n/ko.ts +139 -0
  19. package/src/tool/lorenz-attractor/i18n/nl.ts +139 -0
  20. package/src/tool/lorenz-attractor/i18n/pl.ts +139 -0
  21. package/src/tool/lorenz-attractor/i18n/pt.ts +139 -0
  22. package/src/tool/lorenz-attractor/i18n/ru.ts +139 -0
  23. package/src/tool/lorenz-attractor/i18n/sv.ts +139 -0
  24. package/src/tool/lorenz-attractor/i18n/tr.ts +139 -0
  25. package/src/tool/lorenz-attractor/i18n/zh.ts +139 -0
  26. package/src/tool/lorenz-attractor/index.ts +9 -0
  27. package/src/tool/lorenz-attractor/logic/LorenzEngine.ts +32 -0
  28. package/src/tool/lorenz-attractor/lorenz-attractor.css +453 -0
  29. package/src/tool/lorenz-attractor/renderer.ts +136 -0
  30. package/src/tool/lorenz-attractor/script.ts +283 -0
  31. package/src/tool/lorenz-attractor/seo.astro +15 -0
  32. package/src/tools.ts +2 -0
@@ -0,0 +1,139 @@
1
+ const slug = 'lorenz-attractor';
2
+ const title = '洛伦兹吸引子混沌模拟器:3D蝴蝶效应';
3
+ const description = '通过这个交互式3D洛伦兹吸引子模拟探索混沌理论。可视化蝴蝶效应。';
4
+
5
+ const howTo = [
6
+ {
7
+ "name": "旋转画布",
8
+ "text": "在3D视口上点击并拖动以旋转吸引子。"
9
+ },
10
+ {
11
+ "name": "调节滑块",
12
+ "text": "修改Sigma、Rho和Beta参数以观察混沌的产生。"
13
+ },
14
+ {
15
+ "name": "观察发散",
16
+ "text": "观察两条轨迹之间的距离是如何呈指数级增长的。"
17
+ },
18
+ {
19
+ "name": "暂停与重置",
20
+ "text": "使用控制按钮暂停模拟或重置参数。"
21
+ }
22
+ ];
23
+
24
+ const faq = [
25
+ {
26
+ "question": "什么是洛伦兹吸引子?",
27
+ "answer": "洛伦兹吸引子是洛伦兹方程组的一组混沌解。"
28
+ },
29
+ {
30
+ "question": "什么是蝴蝶效应?",
31
+ "answer": "非线性系统中对初始条件的敏感依赖性,微小的初始差异会导致巨大的长期差异。"
32
+ },
33
+ {
34
+ "question": "参数代表什么?",
35
+ "answer": "Sigma代表普朗特数,Rho代表瑞利数,Beta与物理尺寸几何比相关。"
36
+ }
37
+ ];
38
+
39
+ import { bibliography } from '../bibliography';
40
+ import type { ToolLocaleContent } from '../../../types';
41
+
42
+ export const content: ToolLocaleContent = {
43
+ slug,
44
+ title,
45
+ description,
46
+ ui: {
47
+ "copied": "已复制",
48
+ "noHistory": "无历史记录",
49
+ "load": "加载",
50
+ "delete": "删除",
51
+ "title": "洛伦兹吸引子",
52
+ "subTitle": "决定论混沌",
53
+ "parameterControls": "系统参数",
54
+ "simulationSpeed": "速度 (dt)",
55
+ "initialPerturbation": "初始微扰 (dx)",
56
+ "trajectories": "轨迹",
57
+ "distance": "发散距离",
58
+ "exponentialGrowth": "指数发散",
59
+ "resetDefault": "Reset",
60
+ "clearPath": "Clear",
61
+ "play": "Resume",
62
+ "pause": "Pause",
63
+ "coords": "坐标",
64
+ "divergenceExplanation": "发散图显示了两条轨迹之间的欧几里得距离随时间的变化。"
65
+ },
66
+ seo: [
67
+ { type: 'title', text: "确定性混沌:理解洛伦兹方程", level: 2 },
68
+ { type: 'paragraph', html: "洛伦兹系统是非线性动力学和混沌理论中的里程碑式成果。1963年,气象学家兼数学家<strong>爱德华·洛伦兹</strong>从大气对流的简化模型中推导出该方程组。洛伦兹将复杂的流体动力学方程简化为三个耦合的常微分方程。他发现这些简单的确定性方程能够产生高度复杂、非周期性的混沌行为,从而彻底改变了我们对物理系统的认识。" },
69
+ { type: 'paragraph', html: "该系统由三个耦合微分方程定义,在时间维度上追踪三维相空间中的坐标:" },
70
+ {
71
+ type: 'list',
72
+ items: [
73
+ "<strong>dx/dt = &sigma; * (y - x):</strong>描述对流运动的速率。参数 &sigma;(普朗特数)表示流体粘度与导热系数之比。",
74
+ "<strong>dy/dt = x * (&rho; - z) - y:</strong>代表上升和下降对流流之间的温度差。&rho;(瑞利数)代表对流加热强度。",
75
+ "<strong>dz/dt = x * y - &beta; * z:</strong>追踪垂直温度剖面的畸变。&beta; 是对流物理单元的几何纵横比。",
76
+ ],
77
+ },
78
+ { type: 'title', text: "蝴蝶效应:对初始条件的敏感依赖", level: 3 },
79
+ { type: 'paragraph', html: "混沌系统的决定性特征是其<strong>对初始条件的敏感依赖</strong>,通俗称为<strong>蝴蝶效应</strong>。本模拟器通过运行两条轨迹(T1为青色,T2为粉色)来展示这一现象,两条轨迹的起始点仅有微小差异。起初,它们几乎沿同一路径运行;短时间后,非线性项将差异放大,两条路径完全分叉。" },
80
+ {
81
+ type: 'table',
82
+ headers: ["参数","标准值","物理含义","改变时的行为"],
83
+ rows: [
84
+ ["&sigma; (西格玛)","10.0","普朗特数","决定流体内部摩擦。值越大,速度变化对温度梯度的响应越快。"],
85
+ ["&rho; (罗)","28.0","瑞利数","&rho; = 1以下,原点是唯一的稳定点。在 &rho; = 28时,系统完全进入混沌状态。"],
86
+ ["&beta; (贝塔)","8/3 (2.667)","几何纵横比","控制对流单元的宽高比,改变轨道的尺度和旋转速度。"],
87
+ ],
88
+ },
89
+ { type: 'title', text: "相空间、奇怪吸引子与分形", level: 3 },
90
+ { type: 'paragraph', html: "在经典物理学中,轨迹最终稳定在不动点,或以极限环的形式重复。洛伦兹系统两者皆不:轨迹在三维空间中无限盘旋而从不自我交叉,形成豪斯多夫维数 约 2.06 的分形几何<strong>奇怪吸引子</strong>。" },
91
+ { type: 'title', text: "混沌理论在科学中的应用", level: 3 },
92
+ { type: 'paragraph', html: "洛伦兹吸引子的启示远不止于气象预报,已对众多现代研究领域产生深远影响:" },
93
+ {
94
+ type: 'list',
95
+ items: [
96
+ "<strong>气象学:</strong>确立了天气可预测性的根本限制,催生了集合预报方法。",
97
+ "<strong>密码学:</strong>混沌轨道确定但不可预测的特性被用于生成安全的伪随机密钥,加密敏感数据流。",
98
+ "<strong>心脏病学:</strong>用于心脏节律建模,健康心脏呈现混沌特征,而周期性节律可能预示病理状态。",
99
+ "<strong>工程学:</strong>通过分析并规避悬索桥和机械系统中的混沌共振,助力设计稳定结构。",
100
+ ],
101
+ },
102
+ ],
103
+ faq,
104
+ bibliography,
105
+ howTo,
106
+ schemas: [
107
+ {
108
+ '@context': 'https://schema.org',
109
+ '@type': 'SoftwareApplication',
110
+ name: title,
111
+ description: description,
112
+ applicationCategory: 'ScientificApplication',
113
+ operatingSystem: 'Any',
114
+ },
115
+ {
116
+ '@context': 'https://schema.org',
117
+ '@type': 'FAQPage',
118
+ mainEntity: faq.map((item) => ({
119
+ '@type': 'Question',
120
+ name: item.question,
121
+ acceptedAnswer: {
122
+ '@type': 'Answer',
123
+ text: item.answer,
124
+ },
125
+ })),
126
+ },
127
+ {
128
+ '@context': 'https://schema.org',
129
+ '@type': 'HowTo',
130
+ name: title,
131
+ step: howTo.map((step) => ({
132
+ '@type': 'HowToStep',
133
+ name: step.name,
134
+ stepValue: step.name,
135
+ text: step.text,
136
+ })),
137
+ },
138
+ ],
139
+ };
@@ -0,0 +1,9 @@
1
+ import { lorenzAttractor } from './entry';
2
+ import type { ToolDefinition } from '../../types';
3
+ export * from './entry';
4
+ export const LORENZ_ATTRACTOR_TOOL: ToolDefinition = {
5
+ entry: lorenzAttractor,
6
+ Component: () => import('./component.astro'),
7
+ SEOComponent: () => import('./seo.astro'),
8
+ BibliographyComponent: () => import('./bibliography.astro'),
9
+ };
@@ -0,0 +1,32 @@
1
+ export interface Point3D {
2
+ x: number;
3
+ y: number;
4
+ z: number;
5
+ }
6
+
7
+ export interface LorenzParams {
8
+ sigma: number;
9
+ rho: number;
10
+ beta: number;
11
+ }
12
+
13
+ export class LorenzEngine {
14
+ static nextPoint(point: Point3D, params: LorenzParams, dt: number): Point3D {
15
+ const dx = params.sigma * (point.y - point.x) * dt;
16
+ const dy = (point.x * (params.rho - point.z) - point.y) * dt;
17
+ const dz = (point.x * point.y - params.beta * point.z) * dt;
18
+
19
+ return {
20
+ x: point.x + dx,
21
+ y: point.y + dy,
22
+ z: point.z + dz,
23
+ };
24
+ }
25
+
26
+ static getDistance(p1: Point3D, p2: Point3D): number {
27
+ const dx = p1.x - p2.x;
28
+ const dy = p1.y - p2.y;
29
+ const dz = p1.z - p2.z;
30
+ return Math.sqrt(dx * dx + dy * dy + dz * dz);
31
+ }
32
+ }
@@ -0,0 +1,453 @@
1
+ :root {
2
+ --lorenz-primary: #2563eb;
3
+ --lorenz-secondary: #7c3aed;
4
+ --lorenz-accent: #c084fc;
5
+ --lorenz-t1: #00f0ff;
6
+ --lorenz-t2: #ff007f;
7
+ --lorenz-bg-card: #fff;
8
+ --lorenz-bg-canvas: transparent;
9
+ --lorenz-border: #e2e8f0;
10
+ --lorenz-text: #0f172a;
11
+ --lorenz-text-muted: #64748b;
12
+ --lorenz-slider-track: #cbd5e1;
13
+ --lorenz-shadow-color: rgba(0, 0, 0, 0.04);
14
+ --lorenz-font-mono: consolas, monaco, 'Courier New', monospace;
15
+ }
16
+
17
+ .theme-dark {
18
+ --lorenz-primary: #3b82f6;
19
+ --lorenz-secondary: #8b5cf6;
20
+ --lorenz-accent: #a78bfa;
21
+ --lorenz-t1: #00f0ff;
22
+ --lorenz-t2: #ff007f;
23
+ --lorenz-bg-card: rgba(31, 41, 55, 0.45);
24
+ --lorenz-bg-canvas: transparent;
25
+ --lorenz-border: rgba(255, 255, 255, 0.06);
26
+ --lorenz-text: #f3f4f6;
27
+ --lorenz-text-muted: #9ca3af;
28
+ --lorenz-slider-track: #4b5563;
29
+ --lorenz-shadow-color: rgba(255, 255, 255, 0.03);
30
+ }
31
+
32
+ .lorenz-app {
33
+ width: 100%;
34
+ max-width: 1200px;
35
+ margin: 0 auto;
36
+ font: 14px Outfit, Inter, sans-serif;
37
+ color: var(--lorenz-text);
38
+ box-sizing: border-box;
39
+ }
40
+
41
+ .lorenz-card {
42
+ background: var(--lorenz-bg-card);
43
+ backdrop-filter: blur(12px);
44
+ border: 1px solid var(--lorenz-border);
45
+ border-radius: 24px;
46
+ padding: 24px;
47
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.03);
48
+ }
49
+
50
+ .theme-dark .lorenz-card {
51
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.25);
52
+ }
53
+
54
+ .lorenz-grid {
55
+ display: grid;
56
+ grid-template-columns: 1fr;
57
+ gap: 24px;
58
+ }
59
+
60
+ @media (min-width: 992px) {
61
+ .lorenz-grid {
62
+ grid-template-columns: 1.5fr 1fr;
63
+ align-items: stretch;
64
+ }
65
+
66
+ .lorenz-canvas-container {
67
+ aspect-ratio: auto;
68
+ min-height: 520px;
69
+ height: 100%;
70
+ }
71
+
72
+ .lorenz-controls-section {
73
+ gap: 12px;
74
+ }
75
+
76
+ .lorenz-sliders-block {
77
+ gap: 10px;
78
+ }
79
+
80
+ .lorenz-slider-group {
81
+ gap: 2px;
82
+ }
83
+
84
+ .lorenz-slider {
85
+ height: 28px;
86
+ }
87
+
88
+ .lorenz-coords-row {
89
+ display: flex;
90
+ flex-direction: row;
91
+ gap: 32px;
92
+ justify-content: flex-start;
93
+ }
94
+
95
+ .lorenz-divergence-display {
96
+ gap: 4px;
97
+ margin-top: 8px;
98
+ margin-bottom: 8px;
99
+ }
100
+
101
+ .lorenz-chart-canvas-wrapper {
102
+ height: 60px;
103
+ }
104
+
105
+ .lorenz-stats-block {
106
+ gap: 8px;
107
+ }
108
+ }
109
+
110
+ .lorenz-canvas-container {
111
+ position: relative;
112
+ background: var(--lorenz-bg-canvas);
113
+ border-radius: 20px;
114
+ overflow: hidden;
115
+ aspect-ratio: 4 / 3;
116
+ display: flex;
117
+ justify-content: center;
118
+ align-items: center;
119
+ }
120
+
121
+ .lorenz-canvas {
122
+ width: 100%;
123
+ height: 100%;
124
+ display: block;
125
+ cursor: grab;
126
+ touch-action: none;
127
+ }
128
+
129
+ .lorenz-canvas:active {
130
+ cursor: grabbing;
131
+ }
132
+
133
+ .lorenz-controls-section {
134
+ display: flex;
135
+ flex-direction: column;
136
+ gap: 24px;
137
+ justify-content: space-between;
138
+ }
139
+
140
+ .lorenz-sliders-block {
141
+ display: flex;
142
+ flex-direction: column;
143
+ gap: 16px;
144
+ }
145
+
146
+ .lorenz-slider-group {
147
+ display: flex;
148
+ flex-direction: column;
149
+ gap: 6px;
150
+ }
151
+
152
+ .lorenz-slider-header {
153
+ display: flex;
154
+ justify-content: space-between;
155
+ font-size: 0.75rem;
156
+ font-weight: 700;
157
+ text-transform: uppercase;
158
+ letter-spacing: 0.05em;
159
+ color: var(--lorenz-text-muted);
160
+ }
161
+
162
+ .lorenz-slider-label {
163
+ font: 700 12px Outfit, Inter, sans-serif;
164
+ }
165
+
166
+ .lorenz-slider-val {
167
+ color: var(--lorenz-primary);
168
+ font: 13px consolas, monaco, monospace;
169
+ font-variant-numeric: tabular-nums;
170
+ }
171
+
172
+ .lorenz-slider {
173
+ width: 100%;
174
+ height: 44px;
175
+ background: transparent;
176
+ outline: none;
177
+ -webkit-appearance: none;
178
+ margin: 0;
179
+ cursor: pointer;
180
+ }
181
+
182
+ .lorenz-slider::-webkit-slider-runnable-track {
183
+ width: 100%;
184
+ height: 1px;
185
+ background: var(--lorenz-slider-track);
186
+ }
187
+
188
+ .lorenz-slider::-webkit-slider-thumb {
189
+ -webkit-appearance: none;
190
+ width: 2px;
191
+ height: 12px;
192
+ background: var(--lorenz-primary);
193
+ margin-top: -5.5px;
194
+ border-radius: 0;
195
+ transition: transform 0.1s ease;
196
+ }
197
+
198
+ .lorenz-slider::-moz-range-track {
199
+ width: 100%;
200
+ height: 1px;
201
+ background: var(--lorenz-slider-track);
202
+ }
203
+
204
+ .lorenz-slider::-moz-range-thumb {
205
+ width: 2px;
206
+ height: 12px;
207
+ background: var(--lorenz-primary);
208
+ border-radius: 0;
209
+ border: none;
210
+ }
211
+
212
+ .lorenz-button-row {
213
+ display: grid;
214
+ grid-template-columns: 1fr 1fr 1fr;
215
+ gap: 8px;
216
+ }
217
+
218
+ .lorenz-btn {
219
+ padding: 10px 0;
220
+ border-radius: 8px;
221
+ font-size: 0.8rem;
222
+ font-weight: 700;
223
+ text-transform: uppercase;
224
+ letter-spacing: 0.05em;
225
+ cursor: pointer;
226
+ transition: all 0.2s ease;
227
+ text-align: center;
228
+ background: transparent;
229
+ color: var(--lorenz-text-muted);
230
+ border: 1px solid var(--lorenz-border);
231
+ }
232
+
233
+ .lorenz-btn:hover {
234
+ color: var(--lorenz-text);
235
+ background: rgba(120, 120, 120, 0.08);
236
+ }
237
+
238
+ .lorenz-btn-active-state {
239
+ border-color: var(--lorenz-primary);
240
+ color: var(--lorenz-primary);
241
+ box-shadow: 0 0 10px rgba(59, 130, 246, 0.15);
242
+ }
243
+
244
+ .lorenz-btn-active-state:hover {
245
+ background: rgba(59, 130, 246, 0.08);
246
+ color: var(--lorenz-primary);
247
+ }
248
+
249
+ .lorenz-stats-block {
250
+ border-top: 1px solid var(--lorenz-border);
251
+ padding-top: 16px;
252
+ display: flex;
253
+ flex-direction: column;
254
+ gap: 16px;
255
+ }
256
+
257
+ .lorenz-coords-row {
258
+ display: grid;
259
+ grid-template-columns: 1fr 1fr;
260
+ gap: 12px;
261
+ }
262
+
263
+ .lorenz-coord-item {
264
+ font: 12px Outfit, Inter, sans-serif;
265
+ color: var(--lorenz-text-muted);
266
+ }
267
+
268
+ .lorenz-coord-val {
269
+ font: 600 14px consolas, monaco, monospace;
270
+ font-variant-numeric: tabular-nums;
271
+ }
272
+
273
+ .lorenz-divergence-display {
274
+ display: flex;
275
+ flex-direction: column;
276
+ gap: 12px;
277
+ margin-top: 24px;
278
+ margin-bottom: 24px;
279
+ }
280
+
281
+ .lorenz-divergence-title {
282
+ font: 700 12px Outfit, Inter, sans-serif;
283
+ text-transform: uppercase;
284
+ letter-spacing: 0.05em;
285
+ color: var(--lorenz-text-muted);
286
+ }
287
+
288
+ .lorenz-divergence-main {
289
+ display: flex;
290
+ align-items: baseline;
291
+ gap: 12px;
292
+ }
293
+
294
+ .lorenz-divergence-num {
295
+ font: 750 2.8rem consolas, monaco, monospace;
296
+ line-height: 1;
297
+ color: var(--lorenz-accent);
298
+ font-variant-numeric: tabular-nums;
299
+ letter-spacing: -0.05em;
300
+ }
301
+
302
+ .lorenz-divergence-delta {
303
+ font: 700 14px consolas, monaco, monospace;
304
+ color: var(--lorenz-text-muted);
305
+ font-variant-numeric: tabular-nums;
306
+ }
307
+
308
+ .lorenz-chart-block {
309
+ border-top: 1px solid var(--lorenz-border);
310
+ padding-top: 16px;
311
+ display: flex;
312
+ flex-direction: column;
313
+ gap: 8px;
314
+ }
315
+
316
+ .lorenz-chart-header {
317
+ display: flex;
318
+ align-items: center;
319
+ font: 700 12px Outfit, Inter, sans-serif;
320
+ text-transform: uppercase;
321
+ letter-spacing: 0.05em;
322
+ color: var(--lorenz-text-muted);
323
+ }
324
+
325
+ .lorenz-tooltip-container {
326
+ position: relative;
327
+ display: inline-flex;
328
+ margin-left: 6px;
329
+ cursor: help;
330
+ }
331
+
332
+ .lorenz-info-icon {
333
+ display: inline-flex;
334
+ align-items: center;
335
+ justify-content: center;
336
+ width: 14px;
337
+ height: 14px;
338
+ border-radius: 50%;
339
+ border: 1px solid var(--lorenz-text-muted);
340
+ font: bold 9px consolas, monaco, monospace;
341
+ color: var(--lorenz-text-muted);
342
+ }
343
+
344
+ .lorenz-tooltip-text {
345
+ visibility: hidden;
346
+ position: absolute;
347
+ bottom: 130%;
348
+ left: 50%;
349
+ transform: translateX(-50%);
350
+ background-color: var(--lorenz-text);
351
+ color: var(--lorenz-bg-card);
352
+ text-align: center;
353
+ padding: 8px 12px;
354
+ border-radius: 8px;
355
+ font: 12px Outfit, Inter, sans-serif;
356
+ line-height: 1.3;
357
+ width: 200px;
358
+ z-index: 10;
359
+ opacity: 0;
360
+ transition: opacity 0.2s;
361
+ pointer-events: none;
362
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
363
+ }
364
+
365
+ .lorenz-tooltip-container:hover .lorenz-tooltip-text {
366
+ visibility: visible;
367
+ opacity: 1;
368
+ }
369
+
370
+ .lorenz-chart-canvas-wrapper {
371
+ position: relative;
372
+ width: 100%;
373
+ height: 80px;
374
+ }
375
+
376
+ .lorenz-chart-canvas {
377
+ width: 100%;
378
+ height: 100%;
379
+ display: block;
380
+ }
381
+
382
+ @media (max-width: 991px) {
383
+ .lorenz-app {
384
+ height: calc(100svh - 80px);
385
+ display: flex;
386
+ flex-direction: column;
387
+ }
388
+
389
+ .lorenz-card {
390
+ flex: 1;
391
+ display: flex;
392
+ flex-direction: column;
393
+ height: 100%;
394
+ padding: 16px;
395
+ overflow: hidden;
396
+ }
397
+
398
+ .lorenz-grid {
399
+ flex: 1;
400
+ display: flex;
401
+ flex-direction: column;
402
+ height: 100%;
403
+ gap: 16px;
404
+ }
405
+
406
+ .lorenz-canvas-container {
407
+ height: 43%;
408
+ flex-shrink: 0;
409
+ aspect-ratio: auto;
410
+ }
411
+
412
+ .lorenz-controls-section {
413
+ height: 57%;
414
+ overflow-y: auto;
415
+ display: flex;
416
+ flex-direction: column;
417
+ gap: 20px;
418
+ padding-right: 4px;
419
+ }
420
+
421
+ .lorenz-slider-group {
422
+ padding-left: 24px;
423
+ padding-right: 24px;
424
+ }
425
+
426
+ .lorenz-button-row {
427
+ grid-template-columns: 2fr 1fr 1fr;
428
+ gap: 12px;
429
+ order: 4;
430
+ }
431
+
432
+ .lorenz-stats-block {
433
+ order: 1;
434
+ border-top: none;
435
+ padding-top: 0;
436
+ }
437
+
438
+ .lorenz-chart-block {
439
+ order: 2;
440
+ border-top: none;
441
+ padding-top: 0;
442
+ }
443
+
444
+ .lorenz-chart-canvas-wrapper {
445
+ height: 56px;
446
+ }
447
+
448
+ .lorenz-sliders-block {
449
+ order: 3;
450
+ border-top: 1px solid var(--lorenz-border);
451
+ padding-top: 16px;
452
+ }
453
+ }