matterviz 0.3.5 → 0.3.7

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 (229) hide show
  1. package/dist/MillerIndexInput.svelte +5 -5
  2. package/dist/api/optimade.js +3 -3
  3. package/dist/brillouin/BrillouinZone.svelte +5 -2
  4. package/dist/brillouin/BrillouinZone.svelte.d.ts +1 -1
  5. package/dist/brillouin/BrillouinZoneExportPane.svelte +1 -3
  6. package/dist/brillouin/BrillouinZoneInfoPane.svelte +1 -1
  7. package/dist/brillouin/BrillouinZoneScene.svelte +5 -5
  8. package/dist/brillouin/compute.js +21 -21
  9. package/dist/brillouin/index.d.ts +1 -1
  10. package/dist/brillouin/index.js +0 -1
  11. package/dist/brillouin/types.d.ts +8 -13
  12. package/dist/chempot-diagram/ChemPotDiagram.svelte +3 -3
  13. package/dist/chempot-diagram/ChemPotDiagram2D.svelte +3 -4
  14. package/dist/chempot-diagram/ChemPotDiagram3D.svelte +33 -34
  15. package/dist/chempot-diagram/compute.js +1 -7
  16. package/dist/chempot-diagram/temperature.d.ts +1 -1
  17. package/dist/chempot-diagram/temperature.js +1 -3
  18. package/dist/chempot-diagram/types.d.ts +4 -9
  19. package/dist/colors/index.js +5 -5
  20. package/dist/composition/Composition.svelte +2 -1
  21. package/dist/composition/Formula.svelte +7 -4
  22. package/dist/composition/FormulaFilter.svelte +1 -3
  23. package/dist/composition/format.js +4 -4
  24. package/dist/composition/parse.d.ts +2 -1
  25. package/dist/composition/parse.js +61 -46
  26. package/dist/convex-hull/ConvexHull2D.svelte +62 -51
  27. package/dist/convex-hull/ConvexHull3D.svelte +101 -90
  28. package/dist/convex-hull/ConvexHull4D.svelte +70 -58
  29. package/dist/convex-hull/ConvexHullControls.svelte +24 -35
  30. package/dist/convex-hull/ConvexHullInfoPane.svelte +8 -5
  31. package/dist/convex-hull/ConvexHullInfoPane.svelte.d.ts +2 -0
  32. package/dist/convex-hull/ConvexHullStats.svelte +9 -2
  33. package/dist/convex-hull/ConvexHullStats.svelte.d.ts +2 -0
  34. package/dist/convex-hull/GasPressureControls.svelte +7 -7
  35. package/dist/convex-hull/StructurePopup.svelte +65 -30
  36. package/dist/convex-hull/StructurePopup.svelte.d.ts +6 -6
  37. package/dist/convex-hull/TemperatureSlider.svelte +8 -5
  38. package/dist/convex-hull/barycentric-coords.d.ts +2 -2
  39. package/dist/convex-hull/barycentric-coords.js +2 -2
  40. package/dist/convex-hull/gas-thermodynamics.js +2 -4
  41. package/dist/convex-hull/helpers.d.ts +13 -2
  42. package/dist/convex-hull/helpers.js +37 -16
  43. package/dist/convex-hull/index.d.ts +1 -0
  44. package/dist/convex-hull/index.js +1 -0
  45. package/dist/convex-hull/thermodynamics.d.ts +2 -1
  46. package/dist/convex-hull/thermodynamics.js +7 -7
  47. package/dist/convex-hull/types.d.ts +15 -15
  48. package/dist/effects.svelte.d.ts +12 -0
  49. package/dist/effects.svelte.js +37 -0
  50. package/dist/element/BohrAtom.svelte +4 -4
  51. package/dist/element/data.json.gz.d.ts +3 -1
  52. package/dist/element/index.d.ts +1 -1
  53. package/dist/element/index.js +0 -1
  54. package/dist/fermi-surface/FermiSurface.svelte +4 -4
  55. package/dist/fermi-surface/FermiSurface.svelte.d.ts +1 -1
  56. package/dist/fermi-surface/FermiSurfaceControls.svelte +15 -19
  57. package/dist/fermi-surface/FermiSurfaceControls.svelte.d.ts +1 -1
  58. package/dist/fermi-surface/FermiSurfaceScene.svelte +8 -6
  59. package/dist/fermi-surface/compute.js +2 -2
  60. package/dist/fermi-surface/export.js +13 -26
  61. package/dist/fermi-surface/parse.js +8 -12
  62. package/dist/fermi-surface/types.d.ts +2 -5
  63. package/dist/heatmap-matrix/HeatmapMatrix.svelte +21 -3
  64. package/dist/heatmap-matrix/index.js +6 -6
  65. package/dist/io/decompress.d.ts +2 -1
  66. package/dist/io/decompress.js +1 -1
  67. package/dist/io/export.js +1 -1
  68. package/dist/io/index.d.ts +1 -1
  69. package/dist/io/index.js +0 -1
  70. package/dist/io/url-drop.js +7 -1
  71. package/dist/isosurface/IsosurfaceControls.svelte +11 -25
  72. package/dist/isosurface/slice.js +1 -1
  73. package/dist/isosurface/types.js +12 -12
  74. package/dist/labels.d.ts +1 -1
  75. package/dist/labels.js +14 -11
  76. package/dist/layout/InfoTag.svelte +6 -4
  77. package/dist/layout/PropertyFilter.svelte +4 -2
  78. package/dist/layout/json-tree/JsonTree.svelte +22 -14
  79. package/dist/layout/json-tree/JsonValue.svelte +2 -2
  80. package/dist/layout/json-tree/types.d.ts +3 -2
  81. package/dist/layout/json-tree/types.js +0 -1
  82. package/dist/layout/json-tree/utils.d.ts +4 -4
  83. package/dist/layout/json-tree/utils.js +12 -20
  84. package/dist/marching-cubes.js +13 -15
  85. package/dist/math.d.ts +11 -1
  86. package/dist/math.js +15 -6
  87. package/dist/overlays/DragControlTab.svelte +98 -0
  88. package/dist/overlays/DragControlTab.svelte.d.ts +8 -0
  89. package/dist/overlays/DraggablePane.svelte +7 -84
  90. package/dist/overlays/index.d.ts +1 -0
  91. package/dist/overlays/index.js +1 -0
  92. package/dist/periodic-table/PeriodicTable.svelte +11 -11
  93. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte +4 -2
  94. package/dist/phase-diagram/IsobaricBinaryPhaseDiagram.svelte.d.ts +1 -1
  95. package/dist/phase-diagram/PhaseDiagramControls.svelte +4 -9
  96. package/dist/phase-diagram/PhaseDiagramControls.svelte.d.ts +1 -1
  97. package/dist/phase-diagram/PhaseDiagramExportPane.svelte +2 -10
  98. package/dist/phase-diagram/PhaseDiagramTooltip.svelte +2 -3
  99. package/dist/phase-diagram/TdbInfoPanel.svelte +3 -3
  100. package/dist/phase-diagram/build-diagram.js +11 -18
  101. package/dist/phase-diagram/diagram-input.d.ts +5 -9
  102. package/dist/phase-diagram/index.d.ts +2 -2
  103. package/dist/phase-diagram/index.js +0 -2
  104. package/dist/phase-diagram/parse.d.ts +2 -2
  105. package/dist/phase-diagram/parse.js +6 -10
  106. package/dist/phase-diagram/svg-to-diagram.js +15 -15
  107. package/dist/phase-diagram/types.d.ts +5 -11
  108. package/dist/phase-diagram/utils.d.ts +2 -2
  109. package/dist/phase-diagram/utils.js +9 -11
  110. package/dist/plot/BarPlot.svelte +162 -314
  111. package/dist/plot/BarPlot.svelte.d.ts +5 -4
  112. package/dist/plot/BarPlotControls.svelte.d.ts +1 -1
  113. package/dist/plot/BinnedScatterPlot.svelte +1114 -0
  114. package/dist/plot/BinnedScatterPlot.svelte.d.ts +66 -0
  115. package/dist/plot/ColorBar.svelte +19 -17
  116. package/dist/plot/ColorBar.svelte.d.ts +1 -1
  117. package/dist/plot/FillArea.svelte +2 -4
  118. package/dist/plot/FillArea.svelte.d.ts +1 -1
  119. package/dist/plot/Histogram.svelte +167 -281
  120. package/dist/plot/Histogram.svelte.d.ts +1 -1
  121. package/dist/plot/HistogramControls.svelte.d.ts +1 -1
  122. package/dist/plot/InteractiveAxisLabel.svelte +5 -3
  123. package/dist/plot/InteractiveAxisLabel.svelte.d.ts +1 -1
  124. package/dist/plot/PlotAxis.svelte +169 -0
  125. package/dist/plot/PlotAxis.svelte.d.ts +24 -0
  126. package/dist/plot/PlotControls.svelte.d.ts +1 -1
  127. package/dist/plot/ReferenceLine3D.svelte +53 -51
  128. package/dist/plot/ReferencePlane.svelte +39 -42
  129. package/dist/plot/ScatterPlot.svelte +300 -367
  130. package/dist/plot/ScatterPlot.svelte.d.ts +8 -5
  131. package/dist/plot/ScatterPlot3D.svelte +33 -6
  132. package/dist/plot/ScatterPlot3D.svelte.d.ts +3 -2
  133. package/dist/plot/ScatterPlot3DControls.svelte +9 -9
  134. package/dist/plot/ScatterPlotControls.svelte +3 -4
  135. package/dist/plot/ScatterPoint.svelte +18 -27
  136. package/dist/plot/ScatterPoint.svelte.d.ts +4 -3
  137. package/dist/plot/Surface3D.svelte +4 -7
  138. package/dist/plot/ZeroLines.svelte +2 -1
  139. package/dist/plot/ZeroLines.svelte.d.ts +2 -1
  140. package/dist/plot/ZoomRect.svelte +2 -2
  141. package/dist/plot/ZoomRect.svelte.d.ts +3 -3
  142. package/dist/plot/adaptive-density.d.ts +69 -0
  143. package/dist/plot/adaptive-density.js +191 -0
  144. package/dist/plot/auto-place.d.ts +43 -0
  145. package/dist/plot/auto-place.js +122 -0
  146. package/dist/plot/axis-utils.js +3 -5
  147. package/dist/plot/binned-scatter-types.d.ts +59 -0
  148. package/dist/plot/binned-scatter-types.js +1 -0
  149. package/dist/plot/data-cleaning.js +1 -1
  150. package/dist/plot/data-transform.js +1 -1
  151. package/dist/plot/fill-utils.d.ts +4 -9
  152. package/dist/plot/fill-utils.js +29 -44
  153. package/dist/plot/index.d.ts +4 -0
  154. package/dist/plot/index.js +2 -0
  155. package/dist/plot/interactions.d.ts +4 -4
  156. package/dist/plot/interactions.js +4 -3
  157. package/dist/plot/layout.d.ts +20 -2
  158. package/dist/plot/layout.js +59 -16
  159. package/dist/plot/reference-line.d.ts +1 -1
  160. package/dist/plot/reference-line.js +9 -11
  161. package/dist/plot/scales.d.ts +1 -1
  162. package/dist/plot/scales.js +20 -23
  163. package/dist/plot/types.d.ts +30 -58
  164. package/dist/plot/types.js +2 -6
  165. package/dist/plot/utils/label-placement.d.ts +24 -3
  166. package/dist/plot/utils/label-placement.js +82 -12
  167. package/dist/plot/utils/series-visibility.d.ts +8 -2
  168. package/dist/plot/utils/series-visibility.js +23 -5
  169. package/dist/rdf/RdfPlot.svelte +5 -5
  170. package/dist/rdf/calc-rdf.js +3 -3
  171. package/dist/sanitize.d.ts +2 -0
  172. package/dist/sanitize.js +2 -0
  173. package/dist/spectral/Bands.svelte +1 -1
  174. package/dist/spectral/BandsAndDos.svelte +22 -16
  175. package/dist/spectral/BrillouinBandsDos.svelte +20 -16
  176. package/dist/spectral/Dos.svelte +1 -1
  177. package/dist/spectral/helpers.d.ts +4 -2
  178. package/dist/spectral/helpers.js +44 -35
  179. package/dist/spectral/index.d.ts +1 -1
  180. package/dist/spectral/index.js +0 -1
  181. package/dist/structure/AtomLegend.svelte +23 -6
  182. package/dist/structure/AtomLegend.svelte.d.ts +1 -0
  183. package/dist/structure/CanvasTooltip.svelte +9 -9
  184. package/dist/structure/CanvasTooltip.svelte.d.ts +1 -1
  185. package/dist/structure/CellSelect.svelte +14 -16
  186. package/dist/structure/Structure.svelte +317 -68
  187. package/dist/structure/Structure.svelte.d.ts +4 -2
  188. package/dist/structure/StructureControls.svelte +20 -45
  189. package/dist/structure/StructureExportPane.svelte +2 -1
  190. package/dist/structure/StructureInfoPane.svelte +10 -8
  191. package/dist/structure/StructureScene.svelte +527 -177
  192. package/dist/structure/StructureScene.svelte.d.ts +5 -2
  193. package/dist/structure/atom-properties.js +4 -4
  194. package/dist/structure/bond-order-perception.js +115 -98
  195. package/dist/structure/bonding.d.ts +27 -1
  196. package/dist/structure/bonding.js +187 -16
  197. package/dist/structure/export.js +1 -1
  198. package/dist/structure/index.d.ts +3 -2
  199. package/dist/structure/index.js +0 -2
  200. package/dist/structure/parse.js +88 -59
  201. package/dist/symmetry/WyckoffTable.svelte +7 -0
  202. package/dist/symmetry/index.js +13 -14
  203. package/dist/table/HeatmapTable.svelte +45 -66
  204. package/dist/table/HeatmapTable.svelte.d.ts +1 -1
  205. package/dist/table/ToggleMenu.svelte +19 -10
  206. package/dist/theme/themes.mjs +12 -0
  207. package/dist/tooltip/index.d.ts +1 -1
  208. package/dist/tooltip/index.js +0 -1
  209. package/dist/trajectory/Trajectory.svelte +43 -15
  210. package/dist/trajectory/TrajectoryInfoPane.svelte +2 -2
  211. package/dist/trajectory/extract.js +1 -1
  212. package/dist/trajectory/frame-reader.js +4 -4
  213. package/dist/trajectory/helpers.d.ts +5 -4
  214. package/dist/trajectory/helpers.js +9 -17
  215. package/dist/trajectory/index.d.ts +2 -2
  216. package/dist/trajectory/index.js +2 -2
  217. package/dist/trajectory/parse/ase.js +4 -4
  218. package/dist/trajectory/parse/hdf5.js +1 -1
  219. package/dist/trajectory/parse/index.js +2 -3
  220. package/dist/trajectory/parse/lammps.js +1 -1
  221. package/dist/trajectory/parse/vasp.js +1 -1
  222. package/dist/trajectory/plotting.d.ts +1 -1
  223. package/dist/trajectory/plotting.js +38 -38
  224. package/dist/trajectory/types.d.ts +1 -1
  225. package/dist/utils.d.ts +1 -0
  226. package/dist/utils.js +9 -0
  227. package/dist/xrd/calc-xrd.js +3 -4
  228. package/dist/xrd/parse.js +1 -1
  229. package/package.json +42 -22
@@ -1,4 +1,6 @@
1
1
  export declare function sanitize_html(html: unknown): string;
2
+ export declare const compact_formula: (formula: string) => string;
2
3
  export declare const sanitize_formula: (formula: string, use_subscripts?: boolean) => string;
4
+ export declare const sanitize_compact_formula: (formula: string, use_subscripts?: boolean) => string;
3
5
  export declare const sanitize_svg: (html: string) => string;
4
6
  export declare const sanitize_icon_svg: (html: string) => string;
package/dist/sanitize.js CHANGED
@@ -91,8 +91,10 @@ export function sanitize_html(html) {
91
91
  ] });
92
92
  return dp.sanitize(safe, { ALLOWED_TAGS: SAFE_TAGS, ALLOWED_ATTR: SAFE_ATTRS });
93
93
  }
94
+ export const compact_formula = (formula) => formula.replaceAll(/\s+/g, ``);
94
95
  // Sanitize a chemical formula with optional subscript formatting
95
96
  export const sanitize_formula = (formula, use_subscripts = true) => sanitize_html(format_formula_html(formula, use_subscripts));
97
+ export const sanitize_compact_formula = (formula, use_subscripts = true) => sanitize_formula(compact_formula(formula), use_subscripts);
96
98
  const SVG_TEXT_TAGS = [`tspan`, `title`];
97
99
  // oxfmt-ignore
98
100
  const SVG_TEXT_ATTRS = [`dx`, `dy`, `x`, `y`, `fill`, `font-size`, `font-weight`, `baseline-shift`];
@@ -883,7 +883,7 @@
883
883
  {/each}
884
884
 
885
885
  <!-- Symmetry point vertical lines (filter NaN from scale) -->
886
- {#each Object.keys(x_axis_ticks).map(Number).map((x) => x_scale_fn(x)).filter(
886
+ {#each Object.keys(x_axis_ticks).map(Number).map((tick) => x_scale_fn(tick)).filter(
887
887
  Number.isFinite,
888
888
  ) as
889
889
  scaled_x
@@ -7,6 +7,7 @@
7
7
  import Bands from './Bands.svelte'
8
8
  import Dos from './Dos.svelte'
9
9
  import {
10
+ axis_with_range,
10
11
  compute_frequency_range,
11
12
  detect_zoom_change,
12
13
  extract_efermi,
@@ -40,10 +41,26 @@
40
41
  )
41
42
  let fermi_level = $derived(extract_efermi(band_structs) ?? extract_efermi(doses))
42
43
 
43
- // Synced zoom state (null = use auto-computed range)
44
+ const bands_default_axis = (range = shared_frequency_range): AxisConfig =>
45
+ shared_y_axis ? axis_with_range(bands_props.y_axis, range) : { ...bands_props.y_axis }
46
+ const dos_default_axis = (range = shared_frequency_range): AxisConfig =>
47
+ shared_y_axis ? axis_with_range(dos_props.y_axis, range, ``) : {
48
+ label: ``,
49
+ ...dos_props.y_axis,
50
+ }
51
+
44
52
  let synced_zoom_range = $state<Vec2 | null>(null)
45
- let bands_y_axis = $state<AxisConfig>({})
46
- let dos_y_axis = $state<AxisConfig>({ label: `` })
53
+ let bands_y_axis = $state<AxisConfig>(bands_default_axis())
54
+ let dos_y_axis = $state<AxisConfig>(dos_default_axis())
55
+ let prev_sources: unknown[] | undefined
56
+ $effect(() => {
57
+ const sources = [band_structs, doses, shared_y_axis, bands_props.y_axis, dos_props.y_axis]
58
+ if (prev_sources?.every((source, idx) => source === sources[idx])) return
59
+ prev_sources = sources
60
+ synced_zoom_range = null
61
+ bands_y_axis = bands_default_axis()
62
+ dos_y_axis = dos_default_axis()
63
+ })
47
64
 
48
65
  // Detect zoom changes and sync between components (runs first to capture child updates)
49
66
  $effect(() => {
@@ -67,12 +84,7 @@
67
84
  return
68
85
  }
69
86
  // Only include range if it's valid (don't override child's auto-range with undefined)
70
- bands_y_axis = shared_y_axis
71
- ? {
72
- ...bands_props.y_axis,
73
- ...(is_valid_range(base_range) && { range: base_range }),
74
- }
75
- : { ...bands_props.y_axis }
87
+ bands_y_axis = bands_default_axis(base_range)
76
88
  })
77
89
 
78
90
  // Propagate synced range to DOS y-axis (untrack current to avoid overwriting child zoom)
@@ -85,13 +97,7 @@
85
97
  return
86
98
  }
87
99
  // Only include range if it's valid (don't override child's auto-range with undefined)
88
- dos_y_axis = shared_y_axis
89
- ? {
90
- label: ``,
91
- ...dos_props.y_axis,
92
- ...(is_valid_range(base_range) && { range: base_range }),
93
- }
94
- : { label: ``, ...dos_props.y_axis }
100
+ dos_y_axis = dos_default_axis(base_range)
95
101
  })
96
102
 
97
103
  let hovered_frequency = $state<number | null>(null)
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { BrillouinZone, reciprocal_lattice } from '../brillouin'
3
3
  import type { Vec2, Vec3 } from '../math'
4
- import type { InternalPoint } from '../plot'
4
+ import type { InternalPoint, ScatterHandlerEvent } from '../plot'
5
5
  import type { AxisConfig } from '../plot/types'
6
6
  import type { Crystal } from '../structure'
7
7
  import type { ComponentProps, Snippet } from 'svelte'
@@ -101,10 +101,23 @@
101
101
  : `phone`,
102
102
  )
103
103
 
104
- // Synced zoom state (null = use auto-computed range)
104
+ const bands_default_axis = (range = shared_frequency_range): AxisConfig =>
105
+ helpers.axis_with_range(bands_props.y_axis, range)
106
+ const dos_default_axis = (range = shared_frequency_range): AxisConfig =>
107
+ is_desktop ? helpers.axis_with_range(dos_props.y_axis, range, ``) : { ...dos_props.y_axis }
108
+
105
109
  let synced_zoom_range = $state<Vec2 | null>(null)
106
- let bands_y_axis = $state<AxisConfig>({})
107
- let dos_y_axis = $state<AxisConfig>({})
110
+ let bands_y_axis = $state<AxisConfig>(bands_default_axis())
111
+ let dos_y_axis = $state<AxisConfig>(dos_default_axis())
112
+ let prev_sources: unknown[] | undefined
113
+ $effect(() => {
114
+ const sources = [band_structs, doses, is_desktop, bands_props.y_axis, dos_props.y_axis]
115
+ if (prev_sources?.every((source, idx) => source === sources[idx])) return
116
+ prev_sources = sources
117
+ synced_zoom_range = null
118
+ bands_y_axis = bands_default_axis()
119
+ dos_y_axis = dos_default_axis()
120
+ })
108
121
 
109
122
  // Detect zoom changes and sync between components (runs first to capture child updates)
110
123
  $effect(() => {
@@ -130,10 +143,7 @@
130
143
  !helpers.ranges_equal(current_range, base_range)
131
144
  ) return
132
145
  // Only include range if it's valid (don't override child's auto-range with undefined)
133
- bands_y_axis = {
134
- ...bands_props.y_axis,
135
- ...(helpers.is_valid_range(base_range) && { range: base_range }),
136
- }
146
+ bands_y_axis = bands_default_axis(base_range)
137
147
  })
138
148
 
139
149
  // Propagate synced range to DOS y-axis (untrack current to avoid overwriting child zoom)
@@ -147,13 +157,7 @@
147
157
  !helpers.ranges_equal(current_range, base_range)
148
158
  ) return
149
159
  // Only include range if it's valid (don't override child's auto-range with undefined)
150
- dos_y_axis = is_desktop
151
- ? {
152
- label: ``,
153
- ...dos_props.y_axis,
154
- ...(helpers.is_valid_range(base_range) && { range: base_range }),
155
- }
156
- : { ...dos_props.y_axis }
160
+ dos_y_axis = dos_default_axis(base_range)
157
161
  })
158
162
 
159
163
  let hovered_frequency = $state<number | null>(null)
@@ -174,7 +178,7 @@
174
178
  bind:y_axis={bands_y_axis}
175
179
  bind:x_positions={bands_x_positions}
176
180
  reference_frequency={hovered_frequency}
177
- on_point_hover={(event) => {
181
+ on_point_hover={(event: ScatterHandlerEvent | null) => {
178
182
  hovered_band_point = event?.point ?? null
179
183
  bands_props.on_point_hover?.(event)
180
184
  }}
@@ -239,7 +239,7 @@
239
239
 
240
240
  // For mirror mode, negate the densities
241
241
  if (effective_spin_mode === `mirror`) {
242
- densities_down = densities_down.map((d) => -d)
242
+ densities_down = densities_down.map((density) => -density)
243
243
  }
244
244
 
245
245
  // For stacked plots with overlay mode, use separate spin-down cumulative
@@ -1,8 +1,10 @@
1
- import { type Matrix3x3, type Vec2, type Vec3 } from '../math';
1
+ import type { Matrix3x3, Vec2, Vec3 } from '../math';
2
+ import type { AxisConfig } from '../plot/types';
2
3
  import type * as types from './types';
3
4
  import type { RibbonConfig } from './types';
4
5
  export declare const is_valid_range: (range: unknown) => range is Vec2;
5
6
  export declare const ranges_equal: (a: Vec2 | undefined | null, b: Vec2 | undefined | null, tol?: number) => boolean;
7
+ export declare const axis_with_range: (axis: AxisConfig | undefined, range: Vec2 | undefined, label?: string) => AxisConfig;
6
8
  export declare function detect_zoom_change(bands_range: unknown, dos_range: unknown, shared_range: Vec2, current_synced: Vec2 | null, dos_enabled?: boolean): Vec2 | null | undefined;
7
9
  export declare const IMAGINARY_MODE_NOISE_THRESHOLD = 0.005;
8
10
  export declare function pretty_sym_point(symbol: string): string;
@@ -89,7 +91,7 @@ export declare const DEFAULT_SIGMA = 0;
89
91
  export declare const DEFAULT_NORMALIZE: types.NormalizationMode;
90
92
  export declare const DEFAULT_UNITS: types.FrequencyUnit;
91
93
  export declare function format_sigma(val: number): string;
92
- export declare function validate_sigma_range([min, max]: [number, number]): [number, number];
94
+ export declare const validate_sigma_range: ([min, max]: [number, number]) => [number, number];
93
95
  export declare function calculate_sigma_step(range: [number, number]): number;
94
96
  export interface BandPointMeta extends Record<string, unknown> {
95
97
  band_idx: number;
@@ -1,6 +1,7 @@
1
1
  // Helper utilities for band structure and DOS data processing
2
2
  import { SUBSCRIPT_MAP } from '../labels';
3
3
  import { centered_frac, euclidean_dist } from '../math';
4
+ const is_subscript_key = (key) => key in SUBSCRIPT_MAP;
4
5
  // Check if range is a valid [min, max] tuple (strict 2-element array of finite numbers)
5
6
  export const is_valid_range = (range) => Array.isArray(range) &&
6
7
  range.length === 2 &&
@@ -16,6 +17,11 @@ export const ranges_equal = (a, b, tol = 0.001) => {
16
17
  Math.abs(a[0] - b[0]) <= safe_tol &&
17
18
  Math.abs(a[1] - b[1]) <= safe_tol);
18
19
  };
20
+ export const axis_with_range = (axis, range, label) => ({
21
+ ...axis,
22
+ ...(label !== undefined && { label }),
23
+ ...(is_valid_range(range) && { range }),
24
+ });
19
25
  // Detect which plot triggered a zoom change and return the new synced range.
20
26
  // Returns null to reset to shared range, undefined for no change, or Vec2 for new zoom.
21
27
  export function detect_zoom_change(bands_range, dos_range, shared_range, current_synced, dos_enabled = true) {
@@ -72,7 +78,7 @@ export function pretty_sym_point(symbol) {
72
78
  .replace(/(\p{L})(\d+)/gu, (_, letter, num) => letter +
73
79
  num
74
80
  .split(``)
75
- .map((digit) => SUBSCRIPT_MAP[digit] ?? digit)
81
+ .map((digit) => (is_subscript_key(digit) ? SUBSCRIPT_MAP[digit] : digit))
76
82
  .join(``));
77
83
  }
78
84
  // Create segment key from start and end labels
@@ -81,7 +87,7 @@ export const get_segment_key = (start_label, end_label) => `${start_label ?? `nu
81
87
  export const get_ordered_segments = (band_struct, segments) => {
82
88
  if (!band_struct)
83
89
  return Array.from(segments);
84
- const ordered = band_struct.branches.map((br) => get_segment_key(band_struct.qpoints[br.start_index]?.label ?? undefined, band_struct.qpoints[br.end_index]?.label ?? undefined));
90
+ const ordered = band_struct.branches.map((branch) => get_segment_key(band_struct.qpoints[branch.start_index]?.label ?? undefined, band_struct.qpoints[branch.end_index]?.label ?? undefined));
85
91
  const remaining = Array.from(segments).filter((seg) => !ordered.includes(seg));
86
92
  return [...ordered, ...remaining];
87
93
  };
@@ -105,17 +111,23 @@ export function scale_segment_distances(segment_distances, x_start, x_end) {
105
111
  // primitive-typed keys (opacity, max_width, scale, color) exist at the top level.
106
112
  export function get_ribbon_config(ribbon_config, label) {
107
113
  const defaults = { opacity: 0.3, max_width: 6, scale: 1 };
114
+ const config_record = ribbon_config;
108
115
  // Check for primitive config values (not objects) to distinguish single vs per-structure config
109
- const cfg = ribbon_config;
110
- const has_primitive = [`opacity`, `max_width`, `scale`, `color`].some((key) => cfg[key] !== undefined && typeof cfg[key] !== `object`);
116
+ const has_primitive = [`opacity`, `max_width`, `scale`, `color`].some((key) => {
117
+ const value = config_record[key];
118
+ return value !== undefined && typeof value !== `object`;
119
+ });
111
120
  if (has_primitive) {
112
121
  // Single global config with primitive values - apply to all structures
113
122
  return { ...defaults, ...ribbon_config };
114
123
  }
115
124
  // Otherwise, treat as Record<string, RibbonConfig> and look up by label
116
125
  // Empty label skips lookup and uses defaults only
117
- const per_struct = ribbon_config;
118
- return { ...defaults, ...(label ? per_struct[label] : {}) };
126
+ const label_config = label ? config_record[label] : undefined;
127
+ return {
128
+ ...defaults,
129
+ ...(label_config && typeof label_config === `object` ? label_config : {}),
130
+ };
119
131
  }
120
132
  // Extract tick positions and labels for a band structure plot.
121
133
  export function get_band_xaxis_ticks(band_struct, branches = []) {
@@ -132,7 +144,7 @@ export function get_band_xaxis_ticks(band_struct, branches = []) {
132
144
  // Find which branch this point belongs to
133
145
  const branch_names = band_struct.branches
134
146
  .filter((branch) => branch.start_index <= idx && idx <= branch.end_index)
135
- .map((b) => b.name);
147
+ .map((branch) => branch.name);
136
148
  const this_branch = branch_names[0] || null;
137
149
  if (point.label !== prev_label && prev_branch !== this_branch) {
138
150
  // Branch transition - combine labels
@@ -279,10 +291,7 @@ export function clear_smearing_cache() {
279
291
  }
280
292
  // Type guards for pymatgen qpoint formats
281
293
  const is_vec3 = (val) => Array.isArray(val) && val.length >= 3 && val.slice(0, 3).every(Number.isFinite);
282
- const is_kpoint = (val) => !!val &&
283
- typeof val === `object` &&
284
- `frac_coords` in val &&
285
- is_vec3(val.frac_coords);
294
+ const is_kpoint = (val) => !!val && typeof val === `object` && `frac_coords` in val && is_vec3(val.frac_coords);
286
295
  const is_pymatgen_format = (obj) => {
287
296
  // Check for explicit pymatgen markers
288
297
  if (typeof obj[`@class`] === `string` || typeof obj[`@module`] === `string`) {
@@ -381,17 +390,19 @@ function convert_pymatgen_band_structure(pmg) {
381
390
  !raw_bands.length)
382
391
  return null;
383
392
  const qpoints = raw_qpts
384
- .map((q) => parse_qpoint(q, labels_dict))
385
- .filter((q) => q !== null);
393
+ .map((qpoint) => parse_qpoint(qpoint, labels_dict))
394
+ .filter((qpoint) => qpoint !== null);
386
395
  if (!qpoints.length)
387
396
  return null;
388
397
  // Step distances and discontinuity detection (5x median threshold)
389
398
  const steps = qpoints
390
399
  .slice(1)
391
- .map((q, idx) => euclidean_dist(qpoints[idx].frac_coords, q.frac_coords));
400
+ .map((qpoint, idx) => euclidean_dist(qpoints[idx].frac_coords, qpoint.frac_coords));
392
401
  const sorted = steps.slice().sort((a, b) => a - b);
393
402
  const threshold = (sorted[Math.floor(sorted.length / 2)] ?? 0) * 5;
394
- const disc_set = new Set(steps.map((s, idx) => (s > threshold ? idx + 1 : -1)).filter((i) => i >= 0));
403
+ const disc_set = new Set(steps
404
+ .map((step, idx) => (step > threshold ? idx + 1 : -1))
405
+ .filter((disc_idx) => disc_idx >= 0));
395
406
  // Cumulative distance (skip discontinuities)
396
407
  const distance = steps.reduce((acc, step, idx) => [...acc, disc_set.has(idx + 1) ? acc[idx] : acc[idx] + step], [0]);
397
408
  // Use pymatgen's branches if available - they correctly handle discontinuities
@@ -400,11 +411,11 @@ function convert_pymatgen_band_structure(pmg) {
400
411
  let branches = [];
401
412
  if (Array.isArray(pmg_branches) && pmg_branches.length > 0) {
402
413
  // Validate and use pymatgen branches directly
403
- branches = pmg_branches.filter((br) => typeof br.start_index === `number` &&
404
- typeof br.end_index === `number` &&
405
- br.start_index >= 0 &&
406
- br.end_index < qpoints.length &&
407
- br.start_index <= br.end_index);
414
+ branches = pmg_branches.filter((branch) => typeof branch.start_index === `number` &&
415
+ typeof branch.end_index === `number` &&
416
+ branch.start_index >= 0 &&
417
+ branch.end_index < qpoints.length &&
418
+ branch.start_index <= branch.end_index);
408
419
  }
409
420
  // Fallback: infer branches from discontinuities when none provided or all invalid
410
421
  if (branches.length === 0) {
@@ -426,7 +437,7 @@ function convert_pymatgen_band_structure(pmg) {
426
437
  name: `${start_label}-${end_label}`,
427
438
  };
428
439
  })
429
- .filter((br) => br.start_index <= br.end_index);
440
+ .filter((branch) => branch.start_index <= branch.end_index);
430
441
  }
431
442
  if (!branches.length) {
432
443
  branches.push({ start_index: 0, end_index: qpoints.length - 1, name: `path` });
@@ -482,11 +493,11 @@ export function normalize_band_structure(bs) {
482
493
  const n_qpts = qpoints.length;
483
494
  if (distance.length !== n_qpts ||
484
495
  bands.some((band) => !Array.isArray(band) || band.length !== n_qpts) ||
485
- branches.some((br) => typeof br.start_index !== `number` ||
486
- typeof br.end_index !== `number` ||
487
- br.start_index < 0 ||
488
- br.end_index >= n_qpts ||
489
- br.start_index > br.end_index))
496
+ branches.some((branch) => typeof branch.start_index !== `number` ||
497
+ typeof branch.end_index !== `number` ||
498
+ branch.start_index < 0 ||
499
+ branch.end_index >= n_qpts ||
500
+ branch.start_index > branch.end_index))
490
501
  return null;
491
502
  return band_struct;
492
503
  }
@@ -522,7 +533,7 @@ export function normalize_dos(dos, options = {}) {
522
533
  let final_frequencies = frequencies;
523
534
  if (auto_convert_units && max_freq > 100) {
524
535
  // Likely in cm⁻¹, convert to THz
525
- final_frequencies = frequencies.map((f) => f * CM_TO_THZ);
536
+ final_frequencies = frequencies.map((frequency) => frequency * CM_TO_THZ);
526
537
  console.warn(`Phonon DOS frequencies appear to be in cm⁻¹ (max: ${max_freq.toFixed(1)}). ` +
527
538
  `Converting to THz (max: ${(max_freq * CM_TO_THZ).toFixed(1)} THz).`);
528
539
  }
@@ -912,6 +923,7 @@ function parse_axis_label(label) {
912
923
  const match = /^(.+?)\s*\(([^)]+)\)$/.exec(label);
913
924
  return match ? { name: match[1], unit: match[2] } : { name: label };
914
925
  }
926
+ const format_tooltip_line = (name, value, unit) => `${name}: ${value}${unit ? ` ${unit}` : ``}`;
915
927
  // Format DOS tooltip content from axis labels and values
916
928
  export function format_dos_tooltip(x_formatted, y_formatted, label, is_horizontal, is_phonon, units, x_axis_label, y_axis_label, num_series) {
917
929
  const x_parsed = parse_axis_label(x_axis_label);
@@ -920,15 +932,14 @@ export function format_dos_tooltip(x_formatted, y_formatted, label, is_horizonta
920
932
  name: is_phonon ? `Frequency` : `Energy`,
921
933
  unit: is_phonon ? units : `eV`,
922
934
  };
923
- const format_line = (name, value, unit) => `${name}: ${value}${unit ? ` ${unit}` : ``}`;
924
935
  const lines = is_horizontal
925
936
  ? [
926
- format_line(y_parsed.name || freq_defaults.name, y_formatted, y_parsed.unit || freq_defaults.unit),
927
- format_line(x_parsed.name || `Density`, x_formatted),
937
+ format_tooltip_line(y_parsed.name || freq_defaults.name, y_formatted, y_parsed.unit || freq_defaults.unit),
938
+ format_tooltip_line(x_parsed.name || `Density`, x_formatted),
928
939
  ]
929
940
  : [
930
- format_line(y_parsed.name || `Density`, y_formatted),
931
- format_line(x_parsed.name || freq_defaults.name, x_formatted, x_parsed.unit || freq_defaults.unit),
941
+ format_tooltip_line(y_parsed.name || `Density`, y_formatted),
942
+ format_tooltip_line(x_parsed.name || freq_defaults.name, x_formatted, x_parsed.unit || freq_defaults.unit),
932
943
  ];
933
944
  return { title: num_series > 1 && label ? label : undefined, lines };
934
945
  }
@@ -962,9 +973,7 @@ export function format_sigma(val) {
962
973
  return val.toFixed(val < 1 ? 3 : 2);
963
974
  }
964
975
  // Validate sigma_range: ensures min < max, returns [0, 1] if invalid
965
- export function validate_sigma_range([min, max]) {
966
- return Number.isFinite(min) && Number.isFinite(max) && min < max ? [min, max] : [0, 1];
967
- }
976
+ export const validate_sigma_range = ([min, max]) => Number.isFinite(min) && Number.isFinite(max) && min < max ? [min, max] : [0, 1];
968
977
  // Calculate slider step: 1/100th of range, or 0.01 fallback
969
978
  export function calculate_sigma_step(range) {
970
979
  const [min, max] = validate_sigma_range(range);
@@ -3,4 +3,4 @@ export { default as BandsAndDos } from './BandsAndDos.svelte';
3
3
  export { default as BrillouinBandsDos } from './BrillouinBandsDos.svelte';
4
4
  export { default as Dos } from './Dos.svelte';
5
5
  export * from './helpers';
6
- export * from './types';
6
+ export type * from './types';
@@ -4,4 +4,3 @@ export { default as BandsAndDos } from './BandsAndDos.svelte';
4
4
  export { default as BrillouinBandsDos } from './BrillouinBandsDos.svelte';
5
5
  export { default as Dos } from './Dos.svelte';
6
6
  export * from './helpers';
7
- export * from './types';
@@ -44,6 +44,7 @@
44
44
  title = ``,
45
45
  sym_data = null,
46
46
  structure = undefined,
47
+ show_mode_toggle = true,
47
48
  children,
48
49
  ...rest
49
50
  }: Omit<HTMLAttributes<HTMLDivElement>, `children`> & {
@@ -66,6 +67,7 @@
66
67
  title?: string
67
68
  sym_data?: MoyoDataset | null
68
69
  structure?: AnyStructure | null
70
+ show_mode_toggle?: boolean
69
71
  children?: Snippet<[{ mode_menu_open: boolean; structure?: AnyStructure | null }]>
70
72
  } = $props()
71
73
 
@@ -87,13 +89,14 @@
87
89
 
88
90
  // Dropdown state
89
91
  let mode_menu_open = $state(false)
92
+ let mode_toggle_visible = $derived(show_mode_toggle || mode_menu_open)
90
93
 
91
94
  // Clear hidden property values when switching modes (since they may not be valid)
92
- let previous_mode = $state(atom_color_config.mode)
95
+ let prev_mode = $state(atom_color_config.mode)
93
96
  $effect(() => {
94
- if (atom_color_config.mode !== previous_mode) {
97
+ if (atom_color_config.mode !== prev_mode) {
95
98
  hidden_prop_vals.clear()
96
- previous_mode = atom_color_config.mode
99
+ prev_mode = atom_color_config.mode
97
100
  }
98
101
  })
99
102
 
@@ -111,7 +114,9 @@
111
114
  if (typeof val === `string` && val.includes(`|`)) { // Format Wyckoff orbit IDs
112
115
  const [wyckoff, element] = val.split(`|`, 2)
113
116
  // Count how many sites have this wyckoff+element combination
114
- const count = property_colors?.values.filter((v) => v === val).length ?? 0
117
+ const count = property_colors?.values.filter((property_value) =>
118
+ property_value === val
119
+ ).length ?? 0
115
120
  return `${element}:${count}${wyckoff}`
116
121
  }
117
122
  return String(val)
@@ -237,9 +242,12 @@
237
242
  >
238
243
  <button
239
244
  class="mode-toggle"
245
+ class:visible={mode_toggle_visible}
240
246
  onclick={() => (mode_menu_open = !mode_menu_open)}
241
247
  title="Change atom coloring mode"
242
248
  aria-expanded={mode_menu_open}
249
+ aria-hidden={mode_toggle_visible ? undefined : true}
250
+ tabindex={mode_toggle_visible ? undefined : -1}
243
251
  {@attach tooltip()}
244
252
  >
245
253
  <Icon icon={mode_menu_open ? `Collapse` : `Expand`} />
@@ -715,6 +723,7 @@
715
723
  position: relative;
716
724
  display: flex;
717
725
  align-items: center;
726
+ margin-left: calc(-0.5 * var(--struct-legend-gap, clamp(3pt, 2cqmin, 7pt)));
718
727
  }
719
728
  .mode-toggle {
720
729
  background: transparent;
@@ -724,10 +733,18 @@
724
733
  display: flex;
725
734
  align-items: center;
726
735
  font-size: 0.9em;
727
- opacity: 0.7;
736
+ opacity: 0;
737
+ pointer-events: none;
728
738
  transition: opacity 0.2s ease;
729
739
  }
730
- .mode-toggle:hover {
740
+ .mode-toggle :global(svg) {
741
+ font-size: 1.15em;
742
+ }
743
+ .mode-toggle.visible {
744
+ opacity: 0.7;
745
+ pointer-events: auto;
746
+ }
747
+ .mode-toggle.visible:hover {
731
748
  opacity: 1;
732
749
  }
733
750
  .mode-dropdown {
@@ -24,6 +24,7 @@ type $$ComponentProps = Omit<HTMLAttributes<HTMLDivElement>, `children`> & {
24
24
  title?: string;
25
25
  sym_data?: MoyoDataset | null;
26
26
  structure?: AnyStructure | null;
27
+ show_mode_toggle?: boolean;
27
28
  children?: Snippet<[{
28
29
  mode_menu_open: boolean;
29
30
  structure?: AnyStructure | null;
@@ -1,13 +1,13 @@
1
1
  <script lang="ts">
2
+ import { HTML } from '@threlte/extras'
3
+ import type { Snippet } from 'svelte'
4
+ import type { HTMLAttributes } from 'svelte/elements'
2
5
  import type { Vec3 } from '../math'
3
- import { HTML } from '@threlte/extras'
4
- import type { Snippet } from 'svelte'
5
- import type { HTMLAttributes } from 'svelte/elements'
6
6
 
7
- let { position, children, ...rest }: HTMLAttributes<HTMLDivElement> & {
8
- position: Vec3
9
- children: Snippet<[{ position: Vec3 }]>
10
- } = $props()
7
+ let { position, children, ...rest }: HTMLAttributes<HTMLDivElement> & {
8
+ position: Vec3
9
+ children: Snippet<[{ position: Vec3 }]>
10
+ } = $props()
11
11
  </script>
12
12
 
13
13
  <HTML {position} pointerEvents="none">
@@ -22,9 +22,9 @@
22
22
  box-sizing: border-box;
23
23
  text-align: var(--canvas-tooltip-text-align, left);
24
24
  border-radius: var(--canvas-tooltip-border-radius, var(--border-radius, 3pt));
25
- background: var(--canvas-tooltip-bg, var(--code-bg));
25
+ background: var(--canvas-tooltip-bg, light-dark(rgba(226, 232, 240, 0.96), rgba(15, 23, 42, 0.96)));
26
26
  padding: var(--canvas-tooltip-padding, 1pt 5pt);
27
- color: var(--canvas-tooltip-text-color);
27
+ color: var(--canvas-tooltip-text-color, light-dark(#0f172a, #f8fafc));
28
28
  font-family: var(--canvas-tooltip-font-family);
29
29
  font-size: var(--canvas-tooltip-font-size, clamp(8pt, 3cqmin, 18pt));
30
30
  line-height: var(--canvas-tooltip-line-height);
@@ -1,6 +1,6 @@
1
- import type { Vec3 } from '../math';
2
1
  import type { Snippet } from 'svelte';
3
2
  import type { HTMLAttributes } from 'svelte/elements';
3
+ import type { Vec3 } from '../math';
4
4
  type $$ComponentProps = HTMLAttributes<HTMLDivElement> & {
5
5
  position: Vec3;
6
6
  children: Snippet<[{
@@ -118,7 +118,6 @@
118
118
  class:align-left={align === `left`}
119
119
  transition:fade={{ duration: 100 }}
120
120
  >
121
- <!-- Cell type selector -->
122
121
  <div class="cell-type-row">
123
122
  {#each cell_types as type (type)}
124
123
  {@const disabled = type !== `original` && !sym_data}
@@ -140,7 +139,6 @@
140
139
  {/each}
141
140
  </div>
142
141
 
143
- <!-- Supercell presets -->
144
142
  <div class="supercell-grid">
145
143
  {#each supercell_presets as preset (preset)}
146
144
  <button
@@ -153,7 +151,6 @@
153
151
  {/each}
154
152
  </div>
155
153
 
156
- <!-- Custom input -->
157
154
  <div class="custom-input-row">
158
155
  <input
159
156
  type="text"
@@ -188,10 +185,11 @@
188
185
  );
189
186
  }
190
187
  .toggle-btn {
188
+ font: inherit;
191
189
  padding: var(--struct-legend-padding, 0 4pt);
192
190
  line-height: var(--struct-legend-line-height, 1.3);
193
191
  vertical-align: middle;
194
- color: var(--text-color);
192
+ color: inherit;
195
193
  background: var(--btn-bg, light-dark(rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.1)));
196
194
  border: 1px solid var(--border-color);
197
195
  border-radius: var(--border-radius, 3pt);
@@ -211,15 +209,22 @@
211
209
  right: 0;
212
210
  margin-top: 2px;
213
211
  background: var(--surface-bg, light-dark(rgba(255, 255, 255, 0.96), #222));
214
- padding: 6px;
212
+ padding: 4px;
215
213
  border-radius: var(--struct-border-radius, var(--border-radius, 3pt));
216
214
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
217
215
  display: flex;
218
216
  flex-direction: column;
219
217
  gap: 5px;
220
218
  z-index: 100;
219
+ font-size: var(--struct-cell-select-dropdown-font, max(10px, 1em));
221
220
  min-width: 118px;
222
221
  }
222
+ .dropdown button,
223
+ .custom-input-row input {
224
+ color: inherit;
225
+ font-family: inherit;
226
+ font-size: inherit;
227
+ }
223
228
  /* Invisible bridge to prevent menu closing when moving mouse from toggle to dropdown */
224
229
  .dropdown::before {
225
230
  content: '';
@@ -244,7 +249,6 @@
244
249
  left: 0;
245
250
  }
246
251
 
247
- /* Cell type row - compact buttons with minimal padding */
248
252
  .cell-type-row {
249
253
  display: flex;
250
254
  gap: 3px;
@@ -253,9 +257,7 @@
253
257
  }
254
258
  .cell-type-btn {
255
259
  flex: 1;
256
- padding: 2px 6px;
257
- font-size: 0.9em;
258
- color: var(--text-color);
260
+ padding: 1px 3px;
259
261
  background: var(--btn-bg, light-dark(rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.1)));
260
262
  border: 1px solid var(--border-color);
261
263
  border-radius: var(--border-radius, 3pt);
@@ -288,16 +290,14 @@
288
290
  cursor: not-allowed;
289
291
  }
290
292
 
291
- /* Supercell grid */
292
293
  .supercell-grid {
293
294
  display: grid;
294
295
  grid-template-columns: 1fr 1fr;
295
- gap: 2px;
296
+ gap: 3px;
296
297
  }
297
298
  .preset-btn {
298
- padding: 2px 4px;
299
- font-size: 0.9em;
300
- color: var(--text-color);
299
+ padding: 0 1px;
300
+ line-height: 1;
301
301
  background: var(--btn-bg, light-dark(rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.1)));
302
302
  border: 1px solid var(--border-color);
303
303
  border-radius: var(--border-radius, 3pt);
@@ -324,7 +324,6 @@
324
324
  );
325
325
  }
326
326
 
327
- /* Custom input row */
328
327
  .custom-input-row {
329
328
  display: flex;
330
329
  align-items: center;
@@ -334,7 +333,6 @@
334
333
  max-width: 60px;
335
334
  min-height: 0;
336
335
  padding: 1px 4px;
337
- font-size: 0.85em;
338
336
  }
339
337
  .custom-input-row input.invalid {
340
338
  border-color: rgba(255, 100, 100, 0.6);