@aiquants/resize-panels 1.7.3 → 1.8.1
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/LICENSE +21 -0
- package/README.md +21 -2
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/styles/resize-panels.css +1 -1
- package/dist/styles/resize-panels.standalone.css +3 -0
- package/package.json +7 -4
- package/src/GlobalDebugOverlay.tsx +284 -0
- package/src/Panel.tsx +635 -0
- package/src/PanelDebugInfo.tsx +148 -0
- package/src/PanelGroup.tsx +260 -0
- package/src/PanelResizeHandle.tsx +718 -0
- package/src/context.ts +25 -0
- package/src/debugOverlayStore.ts +351 -0
- package/src/hooks.ts +968 -0
- package/src/index.ts +62 -0
- package/src/reducer.ts +1234 -0
- package/src/roundHalfToEven.ts +40 -0
- package/src/styles/components.entry.css +10 -0
- package/src/styles/resize-panels.css +1 -0
- package/src/styles/standalone.entry.css +12 -0
- package/src/types.ts +288 -0
- package/src/utils/simple-logger.ts +186 -0
- package/src/utils.ts +279 -0
- package/dist/resize-panels.css +0 -1
package/src/utils.ts
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Utility functions for custom resizable panels
|
|
3
|
+
* カスタムリサイズ可能パネルのためのユーティリティ関数
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { roundHalfToEven } from "./roundHalfToEven"
|
|
7
|
+
import { type ContainerAxisMeasurement, type FlexibleSize, PANEL_COLLAPSE_THRESHOLD_MAX, PANEL_COLLAPSE_THRESHOLD_RATIO, PANEL_MIN_SNAP_THRESHOLD, PANEL_SNAP_THRESHOLD, type PanelDirection, type PanelLayoutData, type SizeConfig, type SizeUnit } from "./types"
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Number of significant fractional digits to preserve when rounding percentage-based sizes.
|
|
11
|
+
* パーセンテージサイズの丸めで保持する有効小数桁数。
|
|
12
|
+
*/
|
|
13
|
+
export const PERCENTAGE_DIGITS = 6
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Convert a pixel measurement to a percentage of the container using banker’s rounding.
|
|
17
|
+
* ピクセル寸法をバンカーズラウンディングでコンテナ比率のパーセンテージへ変換する。
|
|
18
|
+
*/
|
|
19
|
+
export const toRoundedPercentage = (size: number, base: number): number => {
|
|
20
|
+
if (base <= 0) {
|
|
21
|
+
return 0
|
|
22
|
+
}
|
|
23
|
+
const percentage = roundHalfToEven((size / base) * 100, PERCENTAGE_DIGITS)
|
|
24
|
+
return percentage
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Translate a percentage-based size back into pixels relative to the container.
|
|
29
|
+
* パーセンテージ指定のサイズをコンテナ基準のピクセル値へ変換する。
|
|
30
|
+
*/
|
|
31
|
+
export const percentageToPixels = (percentage: number | undefined, base: number): number => {
|
|
32
|
+
if (!percentage || base <= 0) {
|
|
33
|
+
return 0
|
|
34
|
+
}
|
|
35
|
+
return (percentage / 100) * base
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Normalize a flexible size into a size configuration object.
|
|
40
|
+
* 柔軟なサイズ指定をサイズ設定オブジェクトへ正規化する。
|
|
41
|
+
*/
|
|
42
|
+
export const normalizeSizeConfig = (size: FlexibleSize | undefined, defaultUnit: SizeUnit = "percentage"): SizeConfig | undefined => {
|
|
43
|
+
if (size === undefined) return undefined
|
|
44
|
+
if (typeof size === "number") {
|
|
45
|
+
return { value: size, unit: defaultUnit }
|
|
46
|
+
}
|
|
47
|
+
return size
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Convert flexible size constraints into pixel values based on container size.
|
|
52
|
+
* 柔軟サイズ制約をコンテナサイズ基準のピクセル値へ変換する。
|
|
53
|
+
*/
|
|
54
|
+
export const getConstraintInPixels = (size: FlexibleSize | undefined, defaultValue: number, containerSize: number): number => {
|
|
55
|
+
if (!size) return defaultValue
|
|
56
|
+
if (typeof size === "number") {
|
|
57
|
+
return (size / 100) * containerSize
|
|
58
|
+
}
|
|
59
|
+
if (size.unit === "pixels") {
|
|
60
|
+
return size.value
|
|
61
|
+
}
|
|
62
|
+
return (size.value / 100) * containerSize
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Clamp a numeric value between the provided bounds.
|
|
67
|
+
* 数値を指定した範囲に収めるためのクリッピング処理。
|
|
68
|
+
*/
|
|
69
|
+
export const clamp = (value: number, min: number, max: number): number => {
|
|
70
|
+
return Math.min(Math.max(value, min), max)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Derive a snap-to-zero threshold from the container axis length using shared heuristics.
|
|
75
|
+
* 共通ヒューリスティクスに基づきコンテナ軸長からゼロスナップ閾値を算出する。
|
|
76
|
+
*/
|
|
77
|
+
export const calculateSnapThreshold = (axisSize: number): number => {
|
|
78
|
+
if (!Number.isFinite(axisSize) || axisSize <= 0) {
|
|
79
|
+
return PANEL_MIN_SNAP_THRESHOLD
|
|
80
|
+
}
|
|
81
|
+
const thresholdFromRatio = axisSize * PANEL_COLLAPSE_THRESHOLD_RATIO
|
|
82
|
+
const cappedThreshold = Math.min(PANEL_SNAP_THRESHOLD, PANEL_COLLAPSE_THRESHOLD_MAX, thresholdFromRatio)
|
|
83
|
+
return Math.max(PANEL_MIN_SNAP_THRESHOLD, cappedThreshold)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Adjust pixel-based panels in priority order to absorb remaining space.
|
|
88
|
+
* 残余スペースを吸収するためにピクセル基準パネルを優先度順に調整する。
|
|
89
|
+
*/
|
|
90
|
+
type AdjustPixelOptions = {
|
|
91
|
+
enforceAutoMinSize?: boolean
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export const adjustPixelPanelsByPriority = (panels: PanelLayoutData[], sizeDiff: number, containerSize: number, options: AdjustPixelOptions = {}): number => {
|
|
95
|
+
if (Math.abs(sizeDiff) <= 0) {
|
|
96
|
+
return sizeDiff
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const enforceAutoMinSize = options.enforceAutoMinSize ?? false
|
|
100
|
+
|
|
101
|
+
// ピクセル指定パネルを抽出してインデックスを保持
|
|
102
|
+
const pixelPanels = panels.map((panel, index) => ({ panel, index })).filter(({ panel }) => !panel.collapsed && (panel.sizeUnit === "pixels" || panel.originalPixelSize !== undefined))
|
|
103
|
+
|
|
104
|
+
if (pixelPanels.length === 0) {
|
|
105
|
+
return sizeDiff
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 優先度順にソート (優先度が同じ場合はインデックス順)
|
|
109
|
+
const isGrowing = sizeDiff > 0
|
|
110
|
+
const sortedPanels = [...pixelPanels].sort((a, b) => {
|
|
111
|
+
const priorityA = a.panel.pixelAdjustPriority ?? a.index + 1
|
|
112
|
+
const priorityB = b.panel.pixelAdjustPriority ?? b.index + 1
|
|
113
|
+
if (priorityA === priorityB) {
|
|
114
|
+
return isGrowing ? b.index - a.index : a.index - b.index
|
|
115
|
+
}
|
|
116
|
+
return isGrowing ? priorityB - priorityA : priorityA - priorityB
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
let remaining = sizeDiff
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Execute a single adjustment pass for pixel panels.
|
|
123
|
+
* ピクセルパネル調整処理
|
|
124
|
+
*/
|
|
125
|
+
const adjustPass = (respectPreferred: boolean) => {
|
|
126
|
+
for (const { index } of sortedPanels) {
|
|
127
|
+
if (Math.abs(remaining) <= 0) {
|
|
128
|
+
break
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const panel = panels[index]
|
|
132
|
+
if (!panel || panel.collapsed) {
|
|
133
|
+
continue
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// パネルの最小・最大サイズをピクセル値へ変換
|
|
137
|
+
// bare number は他の全経路 (getConstraintInPixels) と同じくパーセンテージとして解釈する
|
|
138
|
+
const minSizeFromConstraint = getConstraintInPixels(panel.minSize, 0, containerSize)
|
|
139
|
+
const maxSize = getConstraintInPixels(panel.maxSize, containerSize, containerSize)
|
|
140
|
+
const autoMinSize = enforceAutoMinSize ? getConstraintInPixels(panel.autoMinSize, 0, containerSize) : 0
|
|
141
|
+
const minSize = Math.max(minSizeFromConstraint, autoMinSize)
|
|
142
|
+
const preferredPixel = panel.preferredPixelSize !== undefined ? clamp(panel.preferredPixelSize, minSize, maxSize) : panel.size
|
|
143
|
+
|
|
144
|
+
const panelIsCollapsible = panel.collapseFromStart || panel.collapseFromEnd
|
|
145
|
+
if (remaining > 0) {
|
|
146
|
+
// パネルサイズがゼロかどうかを判定
|
|
147
|
+
const isZero = Math.abs(panel.size) <= 0 && (panel.percentageSize ?? 0) <= 0
|
|
148
|
+
// ゼロのパネルはスキップ
|
|
149
|
+
if (isZero) {
|
|
150
|
+
continue
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const targetSize = Math.max(panel.size, preferredPixel)
|
|
154
|
+
const effectiveMax = respectPreferred ? Math.min(maxSize, targetSize) : maxSize
|
|
155
|
+
const expansionCapacity = Math.max(0, effectiveMax - panel.size)
|
|
156
|
+
if (expansionCapacity <= 0) {
|
|
157
|
+
continue
|
|
158
|
+
}
|
|
159
|
+
const applied = Math.min(expansionCapacity, remaining)
|
|
160
|
+
if (applied <= 0) {
|
|
161
|
+
continue
|
|
162
|
+
}
|
|
163
|
+
const nextSize = panel.size + applied
|
|
164
|
+
const nextPercentage = toRoundedPercentage(nextSize, containerSize)
|
|
165
|
+
const nextSizeBeforeCollapse = panelIsCollapsible ? nextSize : panel.sizeBeforeCollapse
|
|
166
|
+
const nextMeasuredPixelBeforeCollapse = panelIsCollapsible ? (panel.measuredPixelSizeBeforeCollapse ?? panel.measuredPixelSize ?? nextSize) : panel.measuredPixelSizeBeforeCollapse
|
|
167
|
+
panels[index] = {
|
|
168
|
+
...panel,
|
|
169
|
+
size: nextSize,
|
|
170
|
+
percentageSize: nextPercentage,
|
|
171
|
+
sizeBeforeCollapse: nextSizeBeforeCollapse,
|
|
172
|
+
measuredPixelSizeBeforeCollapse: nextMeasuredPixelBeforeCollapse,
|
|
173
|
+
measuredPixelSize: undefined,
|
|
174
|
+
measuredPercentageSize: undefined,
|
|
175
|
+
}
|
|
176
|
+
remaining -= applied
|
|
177
|
+
} else {
|
|
178
|
+
const shrinkFloor = respectPreferred ? preferredPixel : minSize
|
|
179
|
+
const reductionCapacity = Math.max(0, panel.size - shrinkFloor)
|
|
180
|
+
if (reductionCapacity <= 0) {
|
|
181
|
+
continue
|
|
182
|
+
}
|
|
183
|
+
const applied = Math.min(reductionCapacity, Math.abs(remaining))
|
|
184
|
+
if (applied <= 0) {
|
|
185
|
+
continue
|
|
186
|
+
}
|
|
187
|
+
const nextSize = panel.size - applied
|
|
188
|
+
const nextPercentage = toRoundedPercentage(nextSize, containerSize)
|
|
189
|
+
const nextSizeBeforeCollapse = panelIsCollapsible ? nextSize : panel.sizeBeforeCollapse
|
|
190
|
+
const nextMeasuredPixelBeforeCollapse = panelIsCollapsible ? (panel.measuredPixelSizeBeforeCollapse ?? panel.measuredPixelSize ?? nextSize) : panel.measuredPixelSizeBeforeCollapse
|
|
191
|
+
panels[index] = {
|
|
192
|
+
...panel,
|
|
193
|
+
size: nextSize,
|
|
194
|
+
percentageSize: nextPercentage,
|
|
195
|
+
sizeBeforeCollapse: nextSizeBeforeCollapse,
|
|
196
|
+
measuredPixelSizeBeforeCollapse: nextMeasuredPixelBeforeCollapse,
|
|
197
|
+
measuredPixelSize: undefined,
|
|
198
|
+
measuredPercentageSize: undefined,
|
|
199
|
+
}
|
|
200
|
+
remaining += applied
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
adjustPass(true)
|
|
206
|
+
|
|
207
|
+
if ((isGrowing && remaining > 0) || (!isGrowing && remaining < 0)) {
|
|
208
|
+
adjustPass(false)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return remaining
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Parse a CSS pixel string and return the numeric portion.
|
|
216
|
+
* CSS ピクセル表現から数値を抽出する処理。
|
|
217
|
+
*/
|
|
218
|
+
const parsePixelValue = (value: string | null): number => {
|
|
219
|
+
if (!value) {
|
|
220
|
+
return 0
|
|
221
|
+
}
|
|
222
|
+
const parsed = parseFloat(value)
|
|
223
|
+
return Number.isFinite(parsed) ? parsed : 0
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Measure container size in a given direction, returning inner (borderless) and outer dimensions.
|
|
228
|
+
* 指定方向で枠線控除後と控除前の両方の寸法を測定して返す。
|
|
229
|
+
*/
|
|
230
|
+
export const getContainerSize = (element: HTMLElement, direction: PanelDirection): ContainerAxisMeasurement => {
|
|
231
|
+
const rect = element.getBoundingClientRect()
|
|
232
|
+
const styles = typeof window !== "undefined" ? window.getComputedStyle(element) : null
|
|
233
|
+
const horizontalBorder = styles ? parsePixelValue(styles.borderLeftWidth) + parsePixelValue(styles.borderRightWidth) : 0
|
|
234
|
+
const verticalBorder = styles ? parsePixelValue(styles.borderTopWidth) + parsePixelValue(styles.borderBottomWidth) : 0
|
|
235
|
+
if (direction === "horizontal") {
|
|
236
|
+
const rectWidth = rect.width > 0 ? rect.width : element.offsetWidth
|
|
237
|
+
const innerWidth = rect.width > 0 ? Math.max(0, rect.width - horizontalBorder) : element.clientWidth
|
|
238
|
+
const outerWidthFallback = element.offsetWidth > 0 ? element.offsetWidth : element.clientWidth + horizontalBorder
|
|
239
|
+
// 枠線の厚みを控除した実効幅と控除前の幅をそれぞれ算出
|
|
240
|
+
return {
|
|
241
|
+
inner: innerWidth > 0 ? innerWidth : Math.max(0, element.clientWidth),
|
|
242
|
+
outer: rectWidth > 0 ? rectWidth : Math.max(0, outerWidthFallback),
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const rectHeight = rect.height > 0 ? rect.height : element.offsetHeight
|
|
246
|
+
const innerHeight = rect.height > 0 ? Math.max(0, rect.height - verticalBorder) : element.clientHeight
|
|
247
|
+
const outerHeightFallback = element.offsetHeight > 0 ? element.offsetHeight : element.clientHeight + verticalBorder
|
|
248
|
+
// 枠線控除後の高さと控除前の高さを併せて返却
|
|
249
|
+
return {
|
|
250
|
+
inner: innerHeight > 0 ? innerHeight : Math.max(0, element.clientHeight),
|
|
251
|
+
outer: rectHeight > 0 ? rectHeight : Math.max(0, outerHeightFallback),
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Persist panel layout sizes to local storage.
|
|
257
|
+
* パネルレイアウトのサイズをローカルストレージへ保存する。
|
|
258
|
+
*/
|
|
259
|
+
export const saveLayout = (id: string, sizes: number[]): void => {
|
|
260
|
+
try {
|
|
261
|
+
localStorage.setItem(`panel-layout-${id}`, JSON.stringify(sizes))
|
|
262
|
+
} catch (error) {
|
|
263
|
+
console.warn("Failed to save panel layout:", error)
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Restore panel layout sizes from local storage.
|
|
269
|
+
* パネルレイアウトのサイズをローカルストレージから復元する。
|
|
270
|
+
*/
|
|
271
|
+
export const loadLayout = (id: string): number[] | null => {
|
|
272
|
+
try {
|
|
273
|
+
const saved = localStorage.getItem(`panel-layout-${id}`)
|
|
274
|
+
return saved ? JSON.parse(saved) : null
|
|
275
|
+
} catch (error) {
|
|
276
|
+
console.warn("Failed to load panel layout:", error)
|
|
277
|
+
return null
|
|
278
|
+
}
|
|
279
|
+
}
|
package/dist/resize-panels.css
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-orange-100:oklch(95.4% .038 75.164);--color-yellow-50:oklch(98.7% .026 102.212);--color-yellow-100:oklch(97.3% .071 103.193);--color-lime-100:oklch(96.7% .067 122.328);--color-green-50:oklch(98.2% .018 155.826);--color-green-100:oklch(96.2% .044 156.743);--color-green-200:oklch(92.5% .084 155.995);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-blue-50:oklch(97% .014 254.604);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-blue-900:oklch(37.9% .146 265.522);--color-indigo-50:oklch(96.2% .018 272.314);--color-indigo-500:oklch(58.5% .233 277.117);--color-indigo-700:oklch(45.7% .24 277.023);--color-indigo-800:oklch(39.8% .195 277.366);--color-purple-50:oklch(97.7% .014 308.299);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-semibold:600;--leading-relaxed:1.625;--radius-lg:.5rem;--blur-sm:8px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components.components;@layer utilities{.pointer-events-auto{pointer-events:auto}.collapse{visibility:collapse}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.bottom-1{bottom:calc(var(--spacing) * 1)}.bottom-2{bottom:calc(var(--spacing) * 2)}.bottom-3{bottom:calc(var(--spacing) * 3)}.bottom-4{bottom:calc(var(--spacing) * 4)}.bottom-5{bottom:calc(var(--spacing) * 5)}.bottom-6{bottom:calc(var(--spacing) * 6)}.z-20{z-index:20}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.h-3\/4{height:75%}.h-8{height:calc(var(--spacing) * 8)}.h-12{height:calc(var(--spacing) * 12)}.h-96{height:calc(var(--spacing) * 96)}.h-\[2px\]{height:2px}.h-\[6px\]{height:6px}.h-full{height:100%}.h-screen{height:100vh}.min-h-0{min-height:calc(var(--spacing) * 0)}.w-16{width:calc(var(--spacing) * 16)}.w-20{width:calc(var(--spacing) * 20)}.w-\[2px\]{width:2px}.w-\[6px\]{width:6px}.w-full{width:100%}.min-w-0{min-width:calc(var(--spacing) * 0)}.flex-1{flex:1}.flex-shrink,.shrink{flex-shrink:1}.flex-grow,.grow{flex-grow:1}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-col-resize{cursor:col-resize}.cursor-not-allowed{cursor:not-allowed}.cursor-row-resize{cursor:row-resize}.resize{resize:both}.flex-col{flex-direction:column}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-hidden{overflow-x:hidden}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.border{border-style:var(--tw-border-style);border-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-none{--tw-border-style:none;border-style:none}.border-blue-200{border-color:var(--color-blue-200)}.border-blue-400{border-color:var(--color-blue-400)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.border-green-200{border-color:var(--color-green-200)}.border-indigo-500{border-color:var(--color-indigo-500)}.border-red-200{border-color:var(--color-red-200)}.border-slate-300{border-color:var(--color-slate-300)}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-200\/80{background-color:#bedbffcc}@supports (color:color-mix(in lab,red,red)){.bg-blue-200\/80{background-color:color-mix(in oklab,var(--color-blue-200) 80%,transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-emerald-500{background-color:var(--color-emerald-500)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-green-50{background-color:var(--color-green-50)}.bg-green-100{background-color:var(--color-green-100)}.bg-indigo-50{background-color:var(--color-indigo-50)}.bg-lime-100{background-color:var(--color-lime-100)}.bg-orange-100{background-color:var(--color-orange-100)}.bg-purple-50{background-color:var(--color-purple-50)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-100{background-color:var(--color-red-100)}.bg-slate-50{background-color:var(--color-slate-50)}.bg-slate-100{background-color:var(--color-slate-100)}.bg-slate-100\/70{background-color:#f1f5f9b3}@supports (color:color-mix(in lab,red,red)){.bg-slate-100\/70{background-color:color-mix(in oklab,var(--color-slate-100) 70%,transparent)}}.bg-slate-600{background-color:var(--color-slate-600)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\/70{background-color:#ffffffb3}@supports (color:color-mix(in lab,red,red)){.bg-white\/70{background-color:color-mix(in oklab,var(--color-white) 70%,transparent)}}.bg-yellow-50{background-color:var(--color-yellow-50)}.bg-yellow-100{background-color:var(--color-yellow-100)}.p-1{padding:calc(var(--spacing) * 1)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-\[2px\]{padding-inline:2px}.py-1{padding-block:calc(var(--spacing) * 1)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-\[2px\]{padding-block:2px}.text-center{text-align:center}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-blue-700{color:var(--color-blue-700)}.text-blue-800{color:var(--color-blue-800)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-green-700{color:var(--color-green-700)}.text-green-800{color:var(--color-green-800)}.text-indigo-700{color:var(--color-indigo-700)}.text-indigo-800{color:var(--color-indigo-800)}.text-red-700{color:var(--color-red-700)}.text-red-800{color:var(--color-red-800)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-slate-700{color:var(--color-slate-700)}.text-slate-900{color:var(--color-slate-900)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.opacity-50{opacity:.5}.shadow-\[0_0_0_1px_rgba\(191\,219\,254\,0\.65\)\,0_1px_4px_rgba\(59\,130\,246\,0\.45\)\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,#bfdbfea6), 0 1px 4px var(--tw-shadow-color,#3b82f673);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_0_1px_rgba\(255\,255\,255\,0\.9\)\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,#ffffffe6);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\[0_0_0_1px_rgba\(255\,255\,255\,0\.85\)\,0_1px_3px_rgba\(15\,23\,42\,0\.18\)\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,#ffffffd9), 0 1px 3px var(--tw-shadow-color,#0f172a2e);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-blue-300{--tw-ring-color:var(--color-blue-300)}.ring-white\/80{--tw-ring-color:#fffc}@supports (color:color-mix(in lab,red,red)){.ring-white\/80{--tw-ring-color:color-mix(in oklab, var(--color-white) 80%, transparent)}}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.select-none{-webkit-user-select:none;user-select:none}.ring-inset{--tw-ring-inset:inset}@media(hover:hover){.group-hover\:bg-slate-700:is(:where(.group):hover *){background-color:var(--color-slate-700)}.hover\:bg-blue-50:hover{background-color:var(--color-blue-50)}.hover\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\:bg-emerald-600:hover{background-color:var(--color-emerald-600)}.hover\:bg-gray-200\/70:hover{background-color:#e5e7ebb3}@supports (color:color-mix(in lab,red,red)){.hover\:bg-gray-200\/70:hover{background-color:color-mix(in oklab,var(--color-gray-200) 70%,transparent)}}}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.active\:bg-blue-300\/60:active{background-color:#90c5ff99}@supports (color:color-mix(in lab,red,red)){.active\:bg-blue-300\/60:active{background-color:color-mix(in oklab,var(--color-blue-300) 60%,transparent)}}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-blue-300:disabled{background-color:var(--color-blue-300)}.disabled\:bg-emerald-300:disabled{background-color:var(--color-emerald-300)}@media(min-width:48rem){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(prefers-color-scheme:dark){.dark\:border-slate-600{border-color:var(--color-slate-600)}.dark\:bg-blue-300{background-color:var(--color-blue-300)}.dark\:bg-blue-800\/60{background-color:#193cb899}@supports (color:color-mix(in lab,red,red)){.dark\:bg-blue-800\/60{background-color:color-mix(in oklab,var(--color-blue-800) 60%,transparent)}}.dark\:bg-blue-900\/70{background-color:#1c398eb3}@supports (color:color-mix(in lab,red,red)){.dark\:bg-blue-900\/70{background-color:color-mix(in oklab,var(--color-blue-900) 70%,transparent)}}.dark\:bg-slate-200{background-color:var(--color-slate-200)}.dark\:bg-slate-800\/50{background-color:#1d293d80}@supports (color:color-mix(in lab,red,red)){.dark\:bg-slate-800\/50{background-color:color-mix(in oklab,var(--color-slate-800) 50%,transparent)}}.dark\:bg-slate-800\/95{background-color:#1d293df2}@supports (color:color-mix(in lab,red,red)){.dark\:bg-slate-800\/95{background-color:color-mix(in oklab,var(--color-slate-800) 95%,transparent)}}.dark\:text-slate-200{color:var(--color-slate-200)}.dark\:text-slate-400{color:var(--color-slate-400)}.dark\:shadow-\[0_0_0_1px_rgba\(15\,23\,42\,0\.55\)\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,#0f172a8c);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark\:shadow-\[0_0_0_1px_rgba\(147\,197\,253\,0\.5\)\,0_1px_4px_rgba\(59\,130\,246\,0\.55\)\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,#93c5fd80), 0 1px 4px var(--tw-shadow-color,#3b82f68c);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark\:shadow-\[0_0_0_1px_rgba\(148\,163\,184\,0\.45\)\,0_1px_3px_rgba\(2\,6\,23\,0\.55\)\]{--tw-shadow:0 0 0 1px var(--tw-shadow-color,#94a3b873), 0 1px 3px var(--tw-shadow-color,#0206178c);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.dark\:ring-blue-400{--tw-ring-color:var(--color-blue-400)}.dark\:ring-slate-500\/60{--tw-ring-color:#62748e99}@supports (color:color-mix(in lab,red,red)){.dark\:ring-slate-500\/60{--tw-ring-color:color-mix(in oklab, var(--color-slate-500) 60%, transparent)}}@media(hover:hover){.dark\:group-hover\:bg-slate-100:is(:where(.group):hover *){background-color:var(--color-slate-100)}.dark\:hover\:bg-gray-700\/70:hover{background-color:#364153b3}@supports (color:color-mix(in lab,red,red)){.dark\:hover\:bg-gray-700\/70:hover{background-color:color-mix(in oklab,var(--color-gray-700) 70%,transparent)}}}.dark\:active\:bg-blue-700\/60:active{background-color:#1447e699}@supports (color:color-mix(in lab,red,red)){.dark\:active\:bg-blue-700\/60:active{background-color:color-mix(in oklab,var(--color-blue-700) 60%,transparent)}}}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}
|