@jjlmoya/utils-science 1.40.0 → 1.42.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.
- package/package.json +1 -1
- package/scripts/crystal-lattice-catalog-translations.mjs +459 -0
- package/scripts/sync-crystal-lattice-i18n.mjs +50 -0
- package/src/tool/crystal-lattice-structure-finder/component.astro +120 -39
- package/src/tool/crystal-lattice-structure-finder/crystal-lattice-structure-finder.css +204 -56
- package/src/tool/crystal-lattice-structure-finder/data.ts +107 -133
- package/src/tool/crystal-lattice-structure-finder/i18n/de.ts +39 -0
- package/src/tool/crystal-lattice-structure-finder/i18n/en.ts +45 -6
- package/src/tool/crystal-lattice-structure-finder/i18n/es.ts +39 -0
- package/src/tool/crystal-lattice-structure-finder/i18n/fr.ts +39 -0
- package/src/tool/crystal-lattice-structure-finder/i18n/id.ts +39 -0
- package/src/tool/crystal-lattice-structure-finder/i18n/it.ts +39 -0
- package/src/tool/crystal-lattice-structure-finder/i18n/ja.ts +39 -0
- package/src/tool/crystal-lattice-structure-finder/i18n/ko.ts +39 -0
- package/src/tool/crystal-lattice-structure-finder/i18n/nl.ts +39 -0
- package/src/tool/crystal-lattice-structure-finder/i18n/pl.ts +39 -0
- package/src/tool/crystal-lattice-structure-finder/i18n/pt.ts +39 -0
- package/src/tool/crystal-lattice-structure-finder/i18n/ru.ts +39 -0
- package/src/tool/crystal-lattice-structure-finder/i18n/sv.ts +39 -0
- package/src/tool/crystal-lattice-structure-finder/i18n/tr.ts +39 -0
- package/src/tool/crystal-lattice-structure-finder/i18n/zh.ts +39 -0
- package/src/tool/crystal-lattice-structure-finder/logic.ts +7 -3
- package/src/tool/crystal-lattice-structure-finder/structures/README.md +26 -0
- package/src/tool/crystal-lattice-structure-finder/structures/body-centered-cubic.ts +19 -0
- package/src/tool/crystal-lattice-structure-finder/structures/cesium-chloride.ts +19 -0
- package/src/tool/crystal-lattice-structure-finder/structures/diamond-cubic.ts +23 -0
- package/src/tool/crystal-lattice-structure-finder/structures/face-centered-cubic.ts +16 -0
- package/src/tool/crystal-lattice-structure-finder/structures/hexagonal-close-packed.ts +30 -0
- package/src/tool/crystal-lattice-structure-finder/structures/index.ts +25 -0
- package/src/tool/crystal-lattice-structure-finder/structures/perovskite.ts +20 -0
- package/src/tool/crystal-lattice-structure-finder/structures/rock-salt.ts +23 -0
- package/src/tool/crystal-lattice-structure-finder/structures/rutile.ts +25 -0
- package/src/tool/crystal-lattice-structure-finder/structures/shared.ts +86 -0
- package/src/tool/crystal-lattice-structure-finder/structures/simple-cubic.ts +16 -0
- package/src/tool/crystal-lattice-structure-finder/structures/wurtzite.ts +22 -0
- package/src/tool/crystal-lattice-structure-finder/structures/zinc-blende.ts +23 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
import
|
|
2
|
+
import { LATTICE_STRUCTURES, MATERIAL_PRESETS } from './logic';
|
|
3
3
|
import './crystal-lattice-structure-finder.css';
|
|
4
4
|
|
|
5
5
|
interface Props {
|
|
@@ -8,20 +8,32 @@ interface Props {
|
|
|
8
8
|
|
|
9
9
|
const { ui } = Astro.props;
|
|
10
10
|
|
|
11
|
-
const latticeOptions
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
{
|
|
24
|
-
|
|
11
|
+
const latticeOptions = LATTICE_STRUCTURES;
|
|
12
|
+
const materialOptions = MATERIAL_PRESETS;
|
|
13
|
+
|
|
14
|
+
function pascalId(id: string): string {
|
|
15
|
+
return id.split('-').map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join('');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function uiText(key: string, fallback: string): string {
|
|
19
|
+
return ui[key] ?? fallback;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function materialName(material: { id: string; name: string }): string {
|
|
23
|
+
return uiText(`material${pascalId(material.id)}`, material.name);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function materialNote(material: { id: string; note: string }): string {
|
|
27
|
+
return uiText(`material${pascalId(material.id)}Note`, material.note);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function latticeName(lattice: { id: string; name: string }): string {
|
|
31
|
+
return uiText(`lattice${pascalId(lattice.id)}`, lattice.name);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function latticeShortName(lattice: { id: string; shortName: string }): string {
|
|
35
|
+
return uiText(`short${pascalId(lattice.id)}`, lattice.shortName);
|
|
36
|
+
}
|
|
25
37
|
---
|
|
26
38
|
|
|
27
39
|
<div class="lattice-lab" id="lattice-lab">
|
|
@@ -66,28 +78,50 @@ const materialOptions: Array<{ id: string; uiKey: string; noteKey: string }> = [
|
|
|
66
78
|
<p>{ui.density}</p>
|
|
67
79
|
</div>
|
|
68
80
|
|
|
69
|
-
<
|
|
81
|
+
<div class="lattice-field lattice-field-select">
|
|
70
82
|
<span>{ui.material}</span>
|
|
71
|
-
<select id="lattice-material">
|
|
72
|
-
{materialOptions.map((
|
|
73
|
-
<option value={
|
|
83
|
+
<select class="lattice-native-select" id="lattice-material" tabindex="-1" aria-hidden="true">
|
|
84
|
+
{materialOptions.map((material) => (
|
|
85
|
+
<option value={material.id} data-note={materialNote(material)}>{materialName(material)}</option>
|
|
74
86
|
))}
|
|
75
87
|
</select>
|
|
76
|
-
|
|
88
|
+
<button class="lattice-select-button" id="lattice-material-button" type="button" aria-haspopup="listbox" aria-expanded="false">
|
|
89
|
+
<span>Copper</span>
|
|
90
|
+
<i aria-hidden="true"></i>
|
|
91
|
+
</button>
|
|
92
|
+
<div class="lattice-select-menu" id="lattice-material-menu" role="listbox" aria-label={ui.material}>
|
|
93
|
+
{materialOptions.map((material) => (
|
|
94
|
+
<button type="button" role="option" data-select-target="lattice-material" data-value={material.id}>
|
|
95
|
+
{materialName(material)}
|
|
96
|
+
</button>
|
|
97
|
+
))}
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
77
100
|
|
|
78
101
|
<div class="lattice-note">
|
|
79
102
|
<span id="lattice-formula">Cu</span>
|
|
80
103
|
<p id="lattice-material-note">{ui.materialNote}</p>
|
|
81
104
|
</div>
|
|
82
105
|
|
|
83
|
-
<
|
|
106
|
+
<div class="lattice-field lattice-field-select">
|
|
84
107
|
<span>{ui.lattice}</span>
|
|
85
|
-
<select id="lattice-structure">
|
|
86
|
-
{latticeOptions.map((
|
|
87
|
-
<option value={
|
|
108
|
+
<select class="lattice-native-select" id="lattice-structure" tabindex="-1" aria-hidden="true">
|
|
109
|
+
{latticeOptions.map((lattice) => (
|
|
110
|
+
<option value={lattice.id} data-short={latticeShortName(lattice)}>{latticeName(lattice)}</option>
|
|
88
111
|
))}
|
|
89
112
|
</select>
|
|
90
|
-
|
|
113
|
+
<button class="lattice-select-button" id="lattice-structure-button" type="button" aria-haspopup="listbox" aria-expanded="false">
|
|
114
|
+
<span>Face-centered cubic</span>
|
|
115
|
+
<i aria-hidden="true"></i>
|
|
116
|
+
</button>
|
|
117
|
+
<div class="lattice-select-menu" id="lattice-structure-menu" role="listbox" aria-label={ui.lattice}>
|
|
118
|
+
{latticeOptions.map((lattice) => (
|
|
119
|
+
<button type="button" role="option" data-select-target="lattice-structure" data-value={lattice.id}>
|
|
120
|
+
{latticeName(lattice)}
|
|
121
|
+
</button>
|
|
122
|
+
))}
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
91
125
|
|
|
92
126
|
<div class="lattice-slider-grid">
|
|
93
127
|
<label class="lattice-field" for="lattice-rotation">
|
|
@@ -105,20 +139,20 @@ const materialOptions: Array<{ id: string; uiKey: string; noteKey: string }> = [
|
|
|
105
139
|
|
|
106
140
|
<div class="lattice-input-grid">
|
|
107
141
|
<label class="lattice-number" for="lattice-a">
|
|
108
|
-
<span>{ui.latticeA}
|
|
142
|
+
<span>{ui.latticeA}</span>
|
|
109
143
|
<input id="lattice-a" type="text" inputmode="decimal" pattern="[0-9.]*" value="3.615" />
|
|
144
|
+
<em>Å</em>
|
|
110
145
|
</label>
|
|
111
146
|
<label class="lattice-number" for="lattice-c-ratio">
|
|
112
147
|
<span>{ui.cRatio}</span>
|
|
113
148
|
<input id="lattice-c-ratio" type="text" inputmode="decimal" pattern="[0-9.]*" value="1" />
|
|
114
149
|
</label>
|
|
115
150
|
<label class="lattice-number" for="lattice-mass">
|
|
116
|
-
<span>{ui.molarMass}
|
|
151
|
+
<span>{ui.molarMass}</span>
|
|
117
152
|
<input id="lattice-mass" type="text" inputmode="decimal" pattern="[0-9.]*" value="63.546" />
|
|
153
|
+
<em>g/mol</em>
|
|
118
154
|
</label>
|
|
119
155
|
</div>
|
|
120
|
-
|
|
121
|
-
<button class="lattice-reset" id="lattice-reset" type="button">{ui.resetView}</button>
|
|
122
156
|
</section>
|
|
123
157
|
|
|
124
158
|
<section class="lattice-results" aria-label="Crystal lattice results">
|
|
@@ -176,7 +210,8 @@ const materialOptions: Array<{ id: string; uiKey: string; noteKey: string }> = [
|
|
|
176
210
|
const massInput = document.getElementById('lattice-mass') as HTMLInputElement | null;
|
|
177
211
|
const gridLayer = document.getElementById('lattice-grid');
|
|
178
212
|
const atomLayer = document.getElementById('lattice-atoms');
|
|
179
|
-
const
|
|
213
|
+
const customSelectButtons = document.querySelectorAll<HTMLButtonElement>('.lattice-select-button');
|
|
214
|
+
const customSelectOptions = document.querySelectorAll<HTMLButtonElement>('[data-select-target]');
|
|
180
215
|
|
|
181
216
|
const labels = {
|
|
182
217
|
formula: document.getElementById('lattice-formula'),
|
|
@@ -204,6 +239,26 @@ const materialOptions: Array<{ id: string; uiKey: string; noteKey: string }> = [
|
|
|
204
239
|
return getMaterial(materialSelect?.value ?? MATERIAL_PRESETS[0].id);
|
|
205
240
|
}
|
|
206
241
|
|
|
242
|
+
function closeSelectMenus() {
|
|
243
|
+
customSelectButtons.forEach((button) => {
|
|
244
|
+
button.setAttribute('aria-expanded', 'false');
|
|
245
|
+
button.closest('.lattice-field-select')?.classList.remove('lattice-select-open');
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function syncCustomSelect(select: HTMLSelectElement | null) {
|
|
250
|
+
if (!select) return;
|
|
251
|
+
|
|
252
|
+
const button = document.getElementById(`${select.id}-button`);
|
|
253
|
+
const label = button?.querySelector('span');
|
|
254
|
+
const selected = select.options[select.selectedIndex];
|
|
255
|
+
if (label && selected) label.textContent = selected.textContent ?? '';
|
|
256
|
+
|
|
257
|
+
document.querySelectorAll<HTMLButtonElement>(`[data-select-target="${select.id}"]`).forEach((option) => {
|
|
258
|
+
option.setAttribute('aria-selected', `${option.dataset.value === select.value}`);
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
207
262
|
function decimalValue(input: HTMLInputElement | null, fallback: number): number {
|
|
208
263
|
if (!input) return fallback;
|
|
209
264
|
|
|
@@ -268,7 +323,7 @@ const materialOptions: Array<{ id: string; uiKey: string; noteKey: string }> = [
|
|
|
268
323
|
const lattice = getLattice(structureSelect.value as LatticeId);
|
|
269
324
|
const rotation = Number(rotationInput.value);
|
|
270
325
|
const zoom = Number(zoomInput.value);
|
|
271
|
-
const isHex = lattice.
|
|
326
|
+
const isHex = lattice.cellGeometry === 'hexagonal';
|
|
272
327
|
const projected = lattice.vertices.map((vertex) => projectPoint(vertex, rotation, zoom / 100, isHex));
|
|
273
328
|
|
|
274
329
|
clearLayer(gridLayer);
|
|
@@ -328,13 +383,13 @@ const materialOptions: Array<{ id: string; uiKey: string; noteKey: string }> = [
|
|
|
328
383
|
labels.volume!.textContent = `${formatNumber(result.cellVolumeCm3 * 1e24, 3)} ų`;
|
|
329
384
|
labels.cellMass!.textContent = `${result.cellMassG.toExponential(3)} g`;
|
|
330
385
|
labels.radius!.textContent = `${formatNumber(radius, 3)} Å`;
|
|
331
|
-
resetButton?.classList.toggle('lattice-reset-active', rotationInput!.value !== '38' || zoomInput!.value !== '100');
|
|
332
386
|
}
|
|
333
387
|
|
|
334
388
|
function loadMaterial(materialId: string) {
|
|
335
389
|
const material = getMaterial(materialId);
|
|
336
390
|
const lattice = getLattice(material.latticeId);
|
|
337
391
|
|
|
392
|
+
syncCustomSelect(materialSelect);
|
|
338
393
|
populateInputs(material, lattice);
|
|
339
394
|
labels.formula!.textContent = material.formula;
|
|
340
395
|
const selectedMaterial = materialSelect?.options[materialSelect.selectedIndex ?? -1];
|
|
@@ -347,20 +402,46 @@ const materialOptions: Array<{ id: string; uiKey: string; noteKey: string }> = [
|
|
|
347
402
|
if (aInput) aInput.value = `${material.latticeA}`;
|
|
348
403
|
if (cRatioInput) cRatioInput.value = `${material.cToA ?? lattice.cToA ?? 1}`;
|
|
349
404
|
if (massInput) massInput.value = `${material.atomicMass}`;
|
|
405
|
+
syncCustomSelect(structureSelect);
|
|
350
406
|
}
|
|
351
407
|
|
|
408
|
+
customSelectButtons.forEach((button) => {
|
|
409
|
+
button.addEventListener('click', () => {
|
|
410
|
+
const isOpen = button.getAttribute('aria-expanded') === 'true';
|
|
411
|
+
closeSelectMenus();
|
|
412
|
+
button.setAttribute('aria-expanded', `${!isOpen}`);
|
|
413
|
+
button.closest('.lattice-field-select')?.classList.toggle('lattice-select-open', !isOpen);
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
customSelectOptions.forEach((option) => {
|
|
418
|
+
option.addEventListener('click', () => {
|
|
419
|
+
const select = document.getElementById(option.dataset.selectTarget ?? '') as HTMLSelectElement | null;
|
|
420
|
+
if (!select || !option.dataset.value) return;
|
|
421
|
+
|
|
422
|
+
select.value = option.dataset.value;
|
|
423
|
+
syncCustomSelect(select);
|
|
424
|
+
select.dispatchEvent(new Event('change', { bubbles: true }));
|
|
425
|
+
closeSelectMenus();
|
|
426
|
+
});
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
document.addEventListener('click', (event) => {
|
|
430
|
+
if (event.target instanceof Element && event.target.closest('.lattice-field-select')) return;
|
|
431
|
+
closeSelectMenus();
|
|
432
|
+
});
|
|
433
|
+
|
|
352
434
|
materialSelect?.addEventListener('change', () => loadMaterial(materialSelect.value));
|
|
353
|
-
structureSelect?.addEventListener('change',
|
|
435
|
+
structureSelect?.addEventListener('change', () => {
|
|
436
|
+
syncCustomSelect(structureSelect);
|
|
437
|
+
updateResults();
|
|
438
|
+
});
|
|
354
439
|
rotationInput?.addEventListener('input', updateResults);
|
|
355
440
|
zoomInput?.addEventListener('input', updateResults);
|
|
356
441
|
aInput?.addEventListener('input', updateResults);
|
|
357
442
|
cRatioInput?.addEventListener('input', updateResults);
|
|
358
443
|
massInput?.addEventListener('input', updateResults);
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
if (zoomInput) zoomInput.value = '100';
|
|
362
|
-
updateResults();
|
|
363
|
-
});
|
|
364
|
-
|
|
444
|
+
syncCustomSelect(materialSelect);
|
|
445
|
+
syncCustomSelect(structureSelect);
|
|
365
446
|
loadMaterial(materialSelect?.value ?? MATERIAL_PRESETS[0].id);
|
|
366
447
|
</script>
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
--lattice-button-text: #fff;
|
|
18
18
|
--lattice-structure-label: #187c78;
|
|
19
19
|
--lattice-main-value: #9f4f23;
|
|
20
|
-
--lattice-
|
|
20
|
+
--lattice-divider: rgba(19, 40, 44, 0.12);
|
|
21
|
+
--lattice-menu-bg: rgba(247, 252, 249, 0.88);
|
|
21
22
|
|
|
22
23
|
display: grid;
|
|
23
24
|
grid-template-columns: minmax(0, 1.15fr) minmax(280px, 0.85fr);
|
|
@@ -51,7 +52,8 @@ html.theme-dark .lattice-lab {
|
|
|
51
52
|
--lattice-button-text: #071314;
|
|
52
53
|
--lattice-structure-label: #91d8c8;
|
|
53
54
|
--lattice-main-value: #f6d37a;
|
|
54
|
-
--lattice-
|
|
55
|
+
--lattice-divider: rgba(255, 255, 255, 0.08);
|
|
56
|
+
--lattice-menu-bg: rgba(10, 22, 27, 0.86);
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
.lattice-viewer {
|
|
@@ -123,7 +125,8 @@ html.theme-dark .lattice-lab {
|
|
|
123
125
|
|
|
124
126
|
.lattice-summary strong {
|
|
125
127
|
color: var(--lattice-main-value);
|
|
126
|
-
font-size:
|
|
128
|
+
font-size: 1.85rem;
|
|
129
|
+
font-variant-numeric: tabular-nums;
|
|
127
130
|
line-height: 1;
|
|
128
131
|
}
|
|
129
132
|
|
|
@@ -140,6 +143,8 @@ html.theme-dark .lattice-lab {
|
|
|
140
143
|
display: flex;
|
|
141
144
|
flex-wrap: wrap;
|
|
142
145
|
gap: 0.55rem;
|
|
146
|
+
align-self: start;
|
|
147
|
+
padding-inline: 0.15rem;
|
|
143
148
|
}
|
|
144
149
|
|
|
145
150
|
.lattice-legend span {
|
|
@@ -190,17 +195,37 @@ html.theme-dark .lattice-lab {
|
|
|
190
195
|
min-width: 0;
|
|
191
196
|
}
|
|
192
197
|
|
|
198
|
+
.lattice-field-select {
|
|
199
|
+
position: relative;
|
|
200
|
+
}
|
|
201
|
+
|
|
193
202
|
.lattice-number {
|
|
194
203
|
position: relative;
|
|
204
|
+
gap: 0.2rem;
|
|
205
|
+
padding: 0.15rem 1rem 0.2rem;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.lattice-number + .lattice-number {
|
|
209
|
+
border-left: 1px solid var(--lattice-divider);
|
|
195
210
|
}
|
|
196
211
|
|
|
197
212
|
.lattice-number > span {
|
|
213
|
+
position: static;
|
|
214
|
+
font-size: 0.64rem;
|
|
215
|
+
pointer-events: none;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.lattice-number em {
|
|
198
219
|
position: absolute;
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
font-size: 0.
|
|
220
|
+
right: 1rem;
|
|
221
|
+
bottom: 0.5rem;
|
|
222
|
+
color: var(--lattice-muted);
|
|
223
|
+
font-size: 0.9rem;
|
|
224
|
+
font-style: normal;
|
|
225
|
+
line-height: 1;
|
|
226
|
+
opacity: 0.3;
|
|
203
227
|
pointer-events: none;
|
|
228
|
+
white-space: nowrap;
|
|
204
229
|
}
|
|
205
230
|
|
|
206
231
|
.lattice-field > span,
|
|
@@ -214,50 +239,121 @@ html.theme-dark .lattice-lab {
|
|
|
214
239
|
text-transform: uppercase;
|
|
215
240
|
}
|
|
216
241
|
|
|
217
|
-
.lattice-
|
|
242
|
+
.lattice-native-select {
|
|
243
|
+
position: absolute;
|
|
244
|
+
width: 1px;
|
|
245
|
+
height: 1px;
|
|
246
|
+
overflow: hidden;
|
|
247
|
+
opacity: 0;
|
|
248
|
+
pointer-events: none;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.lattice-select-button,
|
|
218
252
|
.lattice-number input {
|
|
219
253
|
width: 100%;
|
|
220
254
|
min-height: 2.65rem;
|
|
221
|
-
border:
|
|
222
|
-
border-radius:
|
|
223
|
-
background:
|
|
255
|
+
border: 0;
|
|
256
|
+
border-radius: 0;
|
|
257
|
+
background: transparent;
|
|
224
258
|
color: var(--lattice-text);
|
|
225
259
|
font-size: inherit;
|
|
226
260
|
font-weight: inherit;
|
|
227
261
|
}
|
|
228
262
|
|
|
229
|
-
.lattice-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
263
|
+
.lattice-select-button {
|
|
264
|
+
display: flex;
|
|
265
|
+
align-items: center;
|
|
266
|
+
justify-content: space-between;
|
|
267
|
+
min-height: 2.9rem;
|
|
268
|
+
padding: 0 0.15rem 0.35rem;
|
|
269
|
+
border-bottom: 1px solid var(--lattice-divider);
|
|
270
|
+
text-align: left;
|
|
271
|
+
cursor: pointer;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.lattice-select-button span {
|
|
275
|
+
overflow: hidden;
|
|
276
|
+
text-overflow: ellipsis;
|
|
277
|
+
white-space: nowrap;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.lattice-select-button i {
|
|
281
|
+
width: 0.48rem;
|
|
282
|
+
height: 0.48rem;
|
|
283
|
+
margin-left: 0.8rem;
|
|
284
|
+
border-right: 1.5px solid currentcolor;
|
|
285
|
+
border-bottom: 1.5px solid currentcolor;
|
|
286
|
+
opacity: 0.55;
|
|
287
|
+
transform: rotate(45deg) translateY(-0.12rem);
|
|
288
|
+
transition: transform 160ms ease;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.lattice-select-open .lattice-select-button i {
|
|
292
|
+
transform: rotate(225deg) translate(-0.08rem, -0.08rem);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.lattice-select-menu {
|
|
296
|
+
position: absolute;
|
|
297
|
+
z-index: 5;
|
|
298
|
+
top: calc(100% + 0.45rem);
|
|
299
|
+
right: 0;
|
|
300
|
+
left: 0;
|
|
301
|
+
display: none;
|
|
302
|
+
overflow: hidden;
|
|
303
|
+
border: 1px solid var(--lattice-border);
|
|
304
|
+
border-radius: 8px;
|
|
305
|
+
background: var(--lattice-menu-bg);
|
|
306
|
+
box-shadow: 0 22px 50px rgba(0, 0, 0, 0.18);
|
|
307
|
+
backdrop-filter: blur(12px);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.lattice-select-open .lattice-select-menu {
|
|
311
|
+
display: grid;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.lattice-select-menu button {
|
|
315
|
+
min-height: 2.45rem;
|
|
316
|
+
padding: 0 0.8rem;
|
|
317
|
+
border: 0;
|
|
318
|
+
border-bottom: 1px solid var(--lattice-divider);
|
|
319
|
+
background: transparent;
|
|
320
|
+
color: var(--lattice-text);
|
|
321
|
+
text-align: left;
|
|
322
|
+
cursor: pointer;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.lattice-select-menu button:last-child {
|
|
326
|
+
border-bottom: 0;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.lattice-select-menu button:hover,
|
|
330
|
+
.lattice-select-menu button[aria-selected="true"] {
|
|
331
|
+
background: color-mix(in srgb, var(--lattice-button-bg) 12%, transparent);
|
|
242
332
|
}
|
|
243
333
|
|
|
244
334
|
.lattice-number input {
|
|
245
|
-
min-height:
|
|
246
|
-
padding:
|
|
247
|
-
font-size: 1.
|
|
335
|
+
min-height: 2.35rem;
|
|
336
|
+
padding: 0 2.55rem 0 0;
|
|
337
|
+
font-size: 1.15rem;
|
|
248
338
|
font-variant-numeric: tabular-nums;
|
|
249
339
|
}
|
|
250
340
|
|
|
251
|
-
.lattice-
|
|
252
|
-
|
|
341
|
+
.lattice-number input:focus,
|
|
342
|
+
.lattice-select-button:focus {
|
|
343
|
+
outline: 0;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.lattice-number:focus-within,
|
|
347
|
+
.lattice-field-select:focus-within {
|
|
348
|
+
color: var(--lattice-text);
|
|
253
349
|
}
|
|
254
350
|
|
|
255
351
|
.lattice-note {
|
|
256
352
|
display: grid;
|
|
257
353
|
grid-template-columns: auto 1fr;
|
|
258
|
-
gap: 0.
|
|
354
|
+
gap: 0.85rem;
|
|
259
355
|
align-items: center;
|
|
260
|
-
padding: 0.
|
|
356
|
+
padding: 0.85rem 1rem;
|
|
261
357
|
border: 1px solid var(--lattice-border);
|
|
262
358
|
border-radius: 8px;
|
|
263
359
|
background: var(--lattice-panel);
|
|
@@ -276,6 +372,7 @@ html.theme-dark .lattice-lab {
|
|
|
276
372
|
|
|
277
373
|
.lattice-note p {
|
|
278
374
|
margin: 0;
|
|
375
|
+
padding-right: 0.3rem;
|
|
279
376
|
color: var(--lattice-text);
|
|
280
377
|
font-size: 0.95rem;
|
|
281
378
|
line-height: 1.35;
|
|
@@ -284,76 +381,111 @@ html.theme-dark .lattice-lab {
|
|
|
284
381
|
.lattice-slider-grid,
|
|
285
382
|
.lattice-input-grid {
|
|
286
383
|
display: grid;
|
|
287
|
-
gap: 0.
|
|
384
|
+
gap: 0.9rem;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.lattice-slider-grid .lattice-field {
|
|
388
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
389
|
+
align-items: center;
|
|
390
|
+
gap: 0.35rem 0.75rem;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.lattice-slider-grid .lattice-field input {
|
|
394
|
+
grid-column: 1 / -1;
|
|
288
395
|
}
|
|
289
396
|
|
|
290
397
|
.lattice-input-grid {
|
|
291
398
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
399
|
+
padding-block: 0.25rem;
|
|
292
400
|
}
|
|
293
401
|
|
|
294
402
|
.lattice-field output {
|
|
403
|
+
align-self: start;
|
|
295
404
|
justify-self: end;
|
|
296
|
-
margin-top: -1.55rem;
|
|
297
405
|
color: var(--lattice-text);
|
|
406
|
+
font-size: 0.86rem;
|
|
298
407
|
font-weight: 800;
|
|
408
|
+
font-variant-numeric: tabular-nums;
|
|
409
|
+
text-align: right;
|
|
299
410
|
}
|
|
300
411
|
|
|
301
412
|
.lattice-field input[type="range"] {
|
|
413
|
+
appearance: none;
|
|
302
414
|
width: 100%;
|
|
303
|
-
|
|
415
|
+
height: 1rem;
|
|
416
|
+
background: transparent;
|
|
304
417
|
}
|
|
305
418
|
|
|
306
|
-
.lattice-
|
|
307
|
-
|
|
308
|
-
border:
|
|
309
|
-
|
|
310
|
-
background: var(--lattice-reset-bg);
|
|
311
|
-
color: var(--lattice-muted);
|
|
312
|
-
font-size: inherit;
|
|
313
|
-
font-weight: inherit;
|
|
314
|
-
cursor: pointer;
|
|
315
|
-
transition: background-color 160ms ease, border-color 160ms ease, color 160ms ease;
|
|
419
|
+
.lattice-field input[type="range"]::-webkit-slider-runnable-track {
|
|
420
|
+
height: 2px;
|
|
421
|
+
border-radius: 999px;
|
|
422
|
+
background: var(--lattice-divider);
|
|
316
423
|
}
|
|
317
424
|
|
|
318
|
-
.lattice-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
425
|
+
.lattice-field input[type="range"]::-webkit-slider-thumb {
|
|
426
|
+
appearance: none;
|
|
427
|
+
width: 0.86rem;
|
|
428
|
+
height: 0.86rem;
|
|
429
|
+
margin-top: -0.39rem;
|
|
430
|
+
border: 0;
|
|
431
|
+
border-radius: 50%;
|
|
432
|
+
background: var(--lattice-button-bg);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
.lattice-field input[type="range"]::-moz-range-track {
|
|
436
|
+
height: 2px;
|
|
437
|
+
border-radius: 999px;
|
|
438
|
+
background: var(--lattice-divider);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.lattice-field input[type="range"]::-moz-range-thumb {
|
|
442
|
+
width: 0.86rem;
|
|
443
|
+
height: 0.86rem;
|
|
444
|
+
border: 0;
|
|
445
|
+
border-radius: 50%;
|
|
446
|
+
background: var(--lattice-button-bg);
|
|
323
447
|
}
|
|
324
448
|
|
|
325
449
|
.lattice-results {
|
|
326
450
|
grid-column: 1 / -1;
|
|
327
451
|
display: grid;
|
|
328
452
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
329
|
-
gap:
|
|
453
|
+
gap: 2.5rem;
|
|
330
454
|
padding: 0.35rem 0.25rem 0;
|
|
331
455
|
}
|
|
332
456
|
|
|
333
457
|
.lattice-result-group {
|
|
334
458
|
display: grid;
|
|
335
|
-
|
|
459
|
+
grid-template-columns: 1fr;
|
|
460
|
+
gap: 0.52rem;
|
|
336
461
|
min-width: 0;
|
|
337
462
|
}
|
|
338
463
|
|
|
339
464
|
.lattice-result-group h2 {
|
|
340
|
-
margin: 0 0 0.
|
|
465
|
+
margin: 0 0 0.35rem;
|
|
341
466
|
}
|
|
342
467
|
|
|
343
468
|
.lattice-metric-row {
|
|
344
469
|
display: grid;
|
|
345
|
-
grid-template-columns: minmax(0, 1fr)
|
|
346
|
-
gap:
|
|
470
|
+
grid-template-columns: minmax(7.75rem, 8.75rem) minmax(0, 1fr);
|
|
471
|
+
gap: 0.9rem;
|
|
347
472
|
align-items: baseline;
|
|
473
|
+
min-width: 0;
|
|
348
474
|
}
|
|
349
475
|
|
|
350
476
|
.lattice-metric-row strong {
|
|
351
477
|
overflow-wrap: anywhere;
|
|
352
478
|
color: var(--lattice-text);
|
|
353
|
-
font-size: 1.
|
|
479
|
+
font-size: 1.25rem;
|
|
354
480
|
font-variant-numeric: tabular-nums;
|
|
355
481
|
line-height: 1.15;
|
|
356
|
-
text-align:
|
|
482
|
+
text-align: left;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.lattice-metric-row span {
|
|
486
|
+
max-width: 8.75rem;
|
|
487
|
+
font-size: 0.68rem;
|
|
488
|
+
line-height: 1.2;
|
|
357
489
|
}
|
|
358
490
|
|
|
359
491
|
@media (max-width: 900px) {
|
|
@@ -364,6 +496,10 @@ html.theme-dark .lattice-lab {
|
|
|
364
496
|
.lattice-results {
|
|
365
497
|
grid-template-columns: 1fr;
|
|
366
498
|
}
|
|
499
|
+
|
|
500
|
+
.lattice-result-group {
|
|
501
|
+
grid-template-columns: 1fr;
|
|
502
|
+
}
|
|
367
503
|
}
|
|
368
504
|
|
|
369
505
|
@media (max-width: 560px) {
|
|
@@ -381,6 +517,18 @@ html.theme-dark .lattice-lab {
|
|
|
381
517
|
grid-template-columns: 1fr;
|
|
382
518
|
}
|
|
383
519
|
|
|
520
|
+
.lattice-number + .lattice-number {
|
|
521
|
+
border-left: 0;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.lattice-number {
|
|
525
|
+
padding-inline: 0;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.lattice-metric-row {
|
|
529
|
+
grid-template-columns: minmax(6.8rem, 7.5rem) minmax(0, 1fr);
|
|
530
|
+
}
|
|
531
|
+
|
|
384
532
|
.lattice-note {
|
|
385
533
|
grid-template-columns: 1fr;
|
|
386
534
|
}
|