Skip to content

fix: admin-app built assets and correctness bugs - #28

Merged
jackgranatowski merged 3 commits into
mainfrom
claude/wp-plugin-svelte-configurator-7b3fld
Jun 14, 2026
Merged

fix: admin-app built assets and correctness bugs#28
jackgranatowski merged 3 commits into
mainfrom
claude/wp-plugin-svelte-configurator-7b3fld

Conversation

@jackgranatowski

@jackgranatowski jackgranatowski commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

$(cat <<'EOF'

Summary

Follow-up to #27 — the new panel was not showing because built assets were missing, plus three runtime bugs found during local verification.

  • Built assets committedassets/admin-app/app.{js,css} now tracked in git; class-token-page.php checks file_exists() on this path and falls back to the old Bricks panel when it is absent, which is why the old UI was still showing
  • Synced configurator sourcesadmin-app/src/{components,lib,data,styles} committed so CI can build without needing a GitHub API token
  • package-lock.json added so npm ci works in CI
  • ManualCssTab.svelte — removed the parseCSS as parseCssOverrides alias; use the correct exported name directly
  • SettingsTab.sveltehtml_font_size options were pixel values (14–18); PHP REST endpoint only accepts '' / '100' / '62.5' — saves were silently failing validation
  • vite.config.js — added define: { __SLASHED_VERSION__ } as a runtime expression reading window.slashedApp?.versions?.framework; without this the framework version pill in the Header was always blank
  • class-rest-controller.php — added GET /framework/versions and POST /framework/version endpoints backed by Slashed_Framework_Updater; without these VersionTab always showed "Could not load versions"

Test plan

  • Admin panel loads the new configurator UI (not the old Bricks panel)
  • Header shows correct framework version pill (e.g. "v0.5.23")
  • VersionTab lists available releases and "Switch" triggers a download
  • SettingsTab → CSS bundle and font size save correctly; toggling Manual CSS mode persists
  • ManualCssTab → paste @layer slashed.overrides { :root { --sf-color-brand: oklch(0.6 0.2 220) } } → "Validate & Save" → override stored

https://claude.ai/code/session_017Q5NUFKipcefaCeWSfwQib
EOF
)


Generated by Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new admin app for design token configuration with an intuitive interface
    • Added brand color editing with automatic light/dark pair generation
    • Implemented WCAG contrast checker and accessible palette generator
    • Added modular scale generators for typography and spacing
    • Enabled export and import of design token overrides as CSS
    • Added light/dark theme preview with viewport presets
    • Introduced undo/redo functionality for all edits
    • Added search and filtering across design tokens
    • Implemented one-click style presets (borders, shadows)
    • Added user theme saving and management
  • Chores

    • Updated CI workflow to support new admin app
    • Updated build configuration and source maps handling

claude added 2 commits June 14, 2026 07:42
…assets

- Synced 36 configurator components/libs into admin-app/src/ via sync-core.mjs
- Fixed ManualCssTab.svelte: import parseCSS (not parseCssOverrides) from css.js
- Added package-lock.json for admin-app
- Built assets: assets/admin-app/app.{js,css} (692 kB JS, 77 kB CSS)
- Added assets/admin-app/*.map to .gitignore
- CI: build-admin-app job now also builds and audits the new admin-app

https://claude.ai/code/session_017Q5NUFKipcefaCeWSfwQib
ManualCssTab.svelte: use parseCSS directly, not an alias
SettingsTab.svelte: html_font_size options were pixel values; PHP
  only accepts '', '100', '62.5' — fix options and default
vite.config.js: define __SLASHED_VERSION__ as runtime expression
  reading window.slashedApp.versions.framework so the Header pill
  shows the active framework CSS version from PHP hydration
class-rest-controller.php: add GET /framework/versions and
  POST /framework/version endpoints backed by Slashed_Framework_Updater
  so VersionTab can list and switch framework CSS releases

https://claude.ai/code/session_017Q5NUFKipcefaCeWSfwQib
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jackgranatowski, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 42 minutes and 30 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c43bc908-d0e0-4984-8307-7bb721843b83

📥 Commits

Reviewing files that changed from the base of the PR and between 2b964b1 and 946b7c5.

📒 Files selected for processing (1)
  • .stylelintrc.json
📝 Walkthrough

Walkthrough

Adds a complete new Svelte-based design-token configurator admin app under SLASHED-for-WP/admin-app, including all utility libraries (color math, WCAG, history, CSS generation, scale, domain taxonomy), UI components, app-level styles, and Vite build config. Also adds two PHP REST endpoints for listing and switching framework versions. CI and .gitignore are updated to support the new app.

Changes

New SLASHED Admin App

Layer / File(s) Summary
Token catalogue model and domain taxonomy
SLASHED-for-WP/admin-app/src/lib/model.js, SLASHED-for-WP/admin-app/src/lib/domains.js, SLASHED-for-WP/admin-app/src/lib/uiState.js
model.js shapes the generated JSON index into token collections, lookup maps, and classification helpers. domains.js defines domain taxonomy, quick-knob metadata, and the domainOf classifier. uiState.js adds localStorage sanitization for persisted UI fields.
Pure utility libraries
SLASHED-for-WP/admin-app/src/lib/css.js, SLASHED-for-WP/admin-app/src/lib/color.js, SLASHED-for-WP/admin-app/src/lib/contrast.js, SLASHED-for-WP/admin-app/src/lib/lightdark.js, SLASHED-for-WP/admin-app/src/lib/scale.js, SLASHED-for-WP/admin-app/src/lib/length.js, SLASHED-for-WP/admin-app/src/lib/fonts.js, SLASHED-for-WP/admin-app/src/lib/clipboard.js, SLASHED-for-WP/admin-app/src/lib/historyOps.js
Adds framework-agnostic utility modules: CSS override generation/parsing, WCAG math and OKLCH/HSL/gamut color utilities, light-dark() CSS resolver, modular-scale math, CSS length parsing, system font stack detection, clipboard helper, and an override store history/drag-commit engine.
Preview declarations and color probe host
SLASHED-for-WP/admin-app/src/lib/preview.js, SLASHED-for-WP/admin-app/src/lib/probeHost.js
buildPreviewDeclarations emits scoped CSS variable declarations for a given theme. probeHost.js manages a hidden singleton DOM element that resolves authored CSS color expressions to computed rgb(...) values via the cascade.
Domain-scoped data modules
SLASHED-for-WP/admin-app/src/lib/basics.js, SLASHED-for-WP/admin-app/src/lib/brandColors.js, SLASHED-for-WP/admin-app/src/lib/stylePresets.js, SLASHED-for-WP/admin-app/src/lib/fluidEngine.js, SLASHED-for-WP/admin-app/src/lib/themes.js
Adds curated basic-mode token controls, brand color OKLCH parse/auto-dark utilities, border/shadow one-click presets, fluid scale engine patch builders, and built-in/saved theme management with localStorage persistence.
App shell: global styles and Vite config
SLASHED-for-WP/admin-app/src/styles/app.css, SLASHED-for-WP/admin-app/vite.config.js, SLASHED-for-WP/assets/admin-app/app.css
Adds the full configurator chrome design system (dark/light tokens, cfg-* UI primitives) and injects __SLASHED_VERSION__ at build time via the Vite define option.
Atomic/leaf UI components
SLASHED-for-WP/admin-app/src/components/ContrastBadge.svelte, SLASHED-for-WP/admin-app/src/components/OklchPicker.svelte, SLASHED-for-WP/admin-app/src/components/TokenEditor.svelte, SLASHED-for-WP/admin-app/src/components/TokenGroup.svelte, SLASHED-for-WP/admin-app/src/components/TokenRow.svelte
ContrastBadge renders an inline WCAG pill via probe-based color resolution. OklchPicker is a floating OKLCH/OKLab color picker with EyeDropper integration. TokenEditor handles font/color/number/length controls. TokenGroup is a collapsible group wrapper. TokenRow renders a complete token row with badges, editor, and reset.
Domain-level UI components
SLASHED-for-WP/admin-app/src/components/ScaleGenerator.svelte, SLASHED-for-WP/admin-app/src/components/QuickKnobs.svelte, SLASHED-for-WP/admin-app/src/components/BrandColorRow.svelte, SLASHED-for-WP/admin-app/src/components/StylePresetRow.svelte, SLASHED-for-WP/admin-app/src/components/Cheatsheet.svelte
Adds mid-level domain components: fluid modular scale ramp UI, drag-commit slider knob panel, light/dark OKLCH brand color editor, one-click style preset row, and searchable paginated token reference table.
Tool panels
SLASHED-for-WP/admin-app/src/components/WcagPanel.svelte, SLASHED-for-WP/admin-app/src/components/ThemeGallery.svelte, SLASHED-for-WP/admin-app/src/components/OutputPanel.svelte, SLASHED-for-WP/admin-app/src/components/Preview.svelte
WcagPanel provides a contrast checker, text matrix, and accessible palette generator. ThemeGallery renders built-in and user-saved themes. OutputPanel is the CSS export/import/diff drawer. Preview is the live design-token preview overlay.
App frame components
SLASHED-for-WP/admin-app/src/components/Header.svelte, SLASHED-for-WP/admin-app/src/components/Sidebar.svelte, SLASHED-for-WP/admin-app/src/components/DomainPanel.svelte, SLASHED-for-WP/admin-app/src/components/Home.svelte
Header is the global toolbar. Sidebar is the domain left-rail. DomainPanel is the per-domain panel branching across basic/advanced modes with curated surfaces, grouped catalogue, and power knobs. Home is the Basic-mode landing screen.
Minor component updates
SLASHED-for-WP/admin-app/src/components/ManualCssTab.svelte, SLASHED-for-WP/admin-app/src/components/SettingsTab.svelte
ManualCssTab switches from parseCssOverrides to the new parseCSS. SettingsTab defaults html_font_size to empty and replaces pixel-based options with percentage presets.
CI and .gitignore
.github/workflows/ci.yml, .gitignore
CI adds install/build/audit steps for the new admin app with GITHUB_TOKEN. .gitignore excludes admin app source maps.

Framework Version REST API

Layer / File(s) Summary
Framework version REST endpoints
SLASHED-for-WP/includes/class-rest-controller.php
Registers GET /slashed/v1/framework/versions and POST /slashed/v1/framework/version routes and implements handlers that list release tags from the metadata URL and switch the active version via Slashed_Framework_Updater::download_files().

Sequence Diagram(s)

sequenceDiagram
  participant User
  rect rgba(70, 130, 180, 0.5)
    note right of User: Token override flow
    User->>TokenRow: edit token value
    TokenRow->>TokenEditor: render control (color/length/font/number)
    TokenEditor->>historyOps: dragSet(s, name, value)
    historyOps->>overrides: mutate in place
    TokenEditor->>historyOps: endDrag(s)
    historyOps->>overrides: checkpoint + persist
  end
  rect rgba(144, 100, 180, 0.5)
    note right of User: Live preview and contrast
    TokenRow->>ContrastBadge: value
    ContrastBadge->>probeHost: measureBackground(value)
    probeHost->>buildPreviewDeclarations: overrides + theme
    probeHost-->>ContrastBadge: rgb(...) string
    ContrastBadge->>contrastInfo: contrastInfo(rgb)
    contrastInfo-->>TokenRow: { ratio, level }
  end
  rect rgba(60, 160, 100, 0.5)
    note right of User: CSS export
    User->>OutputPanel: copy/download
    OutputPanel->>generateCSS: overrides, opts
    generateCSS-->>User: CSS text
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • codeslash-dev/SLASHED-Plugins#27: The ManualCssTab.svelte change switching to parseCSS/replaceOverrides directly builds on the parsing and persistence behavior introduced in that PR.
  • codeslash-dev/SLASHED-Plugins#25: This PR adds the shared color.js, scale.js, and fonts.js utility modules, overlapping with the earlier extraction of shared WCAG/scale/font logic introduced in that PR.
  • codeslash-dev/SLASHED-Plugins#24: The new css.js with sanitizeValue() and generateCSS() layer-vs-:root framing directly parallels the Bricks export.js changes from that PR introducing the same framing toggle.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/wp-plugin-svelte-configurator-7b3fld

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (4)
SLASHED-for-WP/includes/class-rest-controller.php (1)

521-559: ⚡ Quick win

Consider caching the version list with a transient.

Every call to this endpoint triggers an external HTTP request to jsDelivr. If the admin panel is opened frequently or by multiple admins, this adds latency and unnecessary load. Framework releases are infrequent, so a short-lived cache (e.g., 1 hour) would improve responsiveness without sacrificing freshness.

♻️ Suggested implementation with transient caching
 public function list_framework_versions() {
+	$cached = get_transient( 'slashed_framework_versions' );
+	if ( false !== $cached ) {
+		return rest_ensure_response( $cached );
+	}
+
 	$response = wp_remote_get(
 		Slashed_Framework_Updater::METADATA_URL,
 		array(
 			'timeout'    => 10,
 			'user-agent' => 'SLASHED/' . SLASHED_VERSION . '; WordPress/' . get_bloginfo( 'version' ),
 		)
 	);

 	if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
 		return new WP_Error(
 			'fetch_failed',
 			__( 'Could not fetch version list. Try again later.', 'slashed' ),
 			array( 'status' => 502 )
 		);
 	}

 	$body = json_decode( wp_remote_retrieve_body( $response ), true );

 	if ( ! is_array( $body ) || empty( $body['versions'] ) ) {
 		return new WP_Error(
 			'no_versions',
 			__( 'No versions found.', 'slashed' ),
 			array( 'status' => 502 )
 		);
 	}

 	$versions = array();
 	foreach ( $body['versions'] as $entry ) {
 		$ver = isset( $entry['version'] ) ? (string) $entry['version'] : '';
 		if ( $ver && preg_match( '/^v?\d+\.\d+\.\d/', $ver ) ) {
 			$versions[] = array(
 				'tag'  => 'v' . ltrim( $ver, 'v' ),
 				'date' => isset( $entry['date'] ) ? (string) $entry['date'] : '',
 			);
 		}
 	}

-	return rest_ensure_response( array_slice( $versions, 0, 20 ) );
+	$result = array_slice( $versions, 0, 20 );
+	set_transient( 'slashed_framework_versions', $result, HOUR_IN_SECONDS );
+
+	return rest_ensure_response( $result );
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SLASHED-for-WP/includes/class-rest-controller.php` around lines 521 - 559,
The list_framework_versions method currently makes an external HTTP request on
every call, causing unnecessary latency and load. Implement transient caching to
store the fetched version list for a short duration (such as 1 hour). At the
start of the method, check if a cached version list exists using get_transient
with an appropriate key; if it exists, return the cached data immediately. If
the transient is empty, proceed with the existing HTTP request logic to fetch
the version list from Slashed_Framework_Updater::METADATA_URL. After
successfully retrieving and validating the versions array, store the result
using set_transient before returning, so subsequent calls within the cache
duration will use the stored data instead of making new external requests.
SLASHED-for-WP/admin-app/src/components/Header.svelte (1)

20-20: ⚡ Quick win

Use the already-imported overrideCount instead of recalculating.

Line 17 imports overrideCount from the store, but line 20 derives modCount using Object.keys(overrides).length, which duplicates the same calculation.

♻️ Simplify by using the imported value
- const modCount = $derived(Object.keys(overrides).length);
+ const modCount = $derived(overrideCount);

Or simply use overrideCount directly in the template if no additional derivation is needed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SLASHED-for-WP/admin-app/src/components/Header.svelte` at line 20, The
modCount derivation on line 20 is duplicating the calculation that is already
provided by the overrideCount variable imported from the store on line 17.
Remove the derivation of modCount using Object.keys(overrides).length and
instead use the already-imported overrideCount directly in your template or
reassign modCount to equal overrideCount to eliminate the redundant calculation.
SLASHED-for-WP/admin-app/src/components/DomainPanel.svelte (1)

117-120: 💤 Low value

Minor optimization: check length before building patch.

The current code builds the patch object even when there are no modified tokens, then checks the length.

♻️ Optimize by early return
  function resetDomain() {
+   if (!modifiedHere.length) return;
    const patch = Object.fromEntries(modifiedHere.map((t) => [t.name, null]));
-   if (modifiedHere.length) patchOverrides(patch);
+   patchOverrides(patch);
  }

This avoids creating an empty patch object when there's nothing to reset.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SLASHED-for-WP/admin-app/src/components/DomainPanel.svelte` around lines 117
- 120, The resetDomain function currently builds the patch object before
checking if modifiedHere has any items, which unnecessarily creates an empty
object when there are no modifications. Move the length check to the beginning
of the function so that the patch object is only constructed when
modifiedHere.length is truthy, avoiding unnecessary object creation and the
mapping operation when there is nothing to reset.
SLASHED-for-WP/admin-app/src/components/Sidebar.svelte (1)

88-88: 💤 Low value

Consider showing platform-appropriate keyboard shortcuts.

The hint shows ⌘Z for undo, which is Mac-specific. Windows/Linux users expect Ctrl+Z. Consider using a platform detection or generic hint like "Undo/Redo" without the specific key combination, or show both.

This is a minor UX enhancement. The current implementation is acceptable but could be more inclusive.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SLASHED-for-WP/admin-app/src/components/Sidebar.svelte` at line 88, The
keyboard shortcut hint in the Sidebar.svelte component currently displays a
hardcoded Mac-specific keyboard shortcut (⌘Z) that is not appropriate for
Windows/Linux users. Modify the hint section by implementing platform detection
to conditionally display the correct undo shortcut: show ⌘Z for Mac users and
Ctrl+Z for Windows/Linux users. You can detect the platform using JavaScript at
runtime (such as checking navigator.platform or user agent) and conditionally
render the appropriate kbd element with the cfg-kbd class, or alternatively
simplify the hint to show a generic label like "Undo" without platform-specific
key combinations if platform detection is not feasible.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@SLASHED-for-WP/admin-app/src/lib/contrast.js`:
- Around line 42-44: Update the gamma decode threshold in the toLinear function
from 0.04045 to 0.03928 to match the WCAG 2.1 specification used in the
gammaToLinear function. This ensures consistent relative luminance calculations
across both modules and maintains WCAG 2.1 compliance. The sRGB spec value of
0.04045 must be replaced with the correct WCAG 2.1 threshold of 0.03928 in the
conditional expression.

In `@SLASHED-for-WP/admin-app/src/styles/app.css`:
- Line 106: The text-rendering property value optimizeLegibility uses mixed case
but should be lowercase per stylelint standards. Change the value to
optimizelegibility to comply with CSS keyword formatting rules. This is a simple
case conversion of the property value in the text-rendering declaration.
- Line 60: The CSS custom property `--cfg-surface` is using the full hex color
notation `#ffffff` which should be shortened to `#fff` for consistency with
Stylelint requirements. Replace the value of the `--cfg-surface` variable with
the shorthand hex notation.
- Line 37: The CSS custom property --cfg-sans contains a font name "Roboto" that
must be lowercase to comply with stylelint rules for CSS keyword values. Change
"Roboto" to "roboto" in the font-family declaration to resolve the stylelint
validation error.
- Line 278: The `clip` property used in the `.cfg-sr-only` class is deprecated
and should be replaced with the modern `clip-path` property. In the app.css file
where `clip: rect(0, 0, 0, 0);` appears in the `.cfg-sr-only` screen-reader
helper class, replace this line with `clip-path: inset(50%);` to achieve the
same visual effect of hiding content from the viewport while keeping it
accessible to screen readers.
- Line 28: Replace all instances of the legacy `rgba()` color function notation
with modern `rgb()` syntax in the CSS file. For each `rgba()` call (such as the
one at the css variable `--cfg-accent-soft`), convert it to use the modern
`rgb()` function where the red, green, and blue values are space-separated and
the alpha channel is appended after a forward slash. For example, `rgba(79, 140,
255, 0.16)` should become `rgb(79 140 255 / 0.16)`. Apply this conversion
consistently to all color variables and declarations throughout the file that
currently use `rgba()` notation.

In `@SLASHED-for-WP/admin-app/vite.config.js`:
- Around line 16-20: The __SLASHED_VERSION__ definition in the define
configuration currently includes outer quotes and parentheses, which causes Vite
to inject it as a string literal rather than a runtime expression. Remove the
outer quotes and parentheses from the __SLASHED_VERSION__ value so that Vite
injects the expression window.slashedApp?.versions?.framework ?? "" directly
into the compiled code, allowing it to evaluate at runtime to display the actual
framework version.

In `@SLASHED-for-WP/assets/admin-app/app.css`:
- Around line 1-2: The compiled CSS file contains stylelint violations
originating from source CSS in src/styles/app.css and component-scoped styles in
.svelte files. Rather than manually fixing the compiled output, apply stylelint
fixes to the source files that generate this CSS: update src/styles/app.css to
address base design system issues and fix individual .svelte component files to
remove vendor prefix violations, deprecated CSS properties like clip, and
kebab-case violations in custom properties. Alternatively, if the compiled
output should not be linted, add assets/admin-app/app.css to .stylelintignore to
exclude generated files from linting.

---

Nitpick comments:
In `@SLASHED-for-WP/admin-app/src/components/DomainPanel.svelte`:
- Around line 117-120: The resetDomain function currently builds the patch
object before checking if modifiedHere has any items, which unnecessarily
creates an empty object when there are no modifications. Move the length check
to the beginning of the function so that the patch object is only constructed
when modifiedHere.length is truthy, avoiding unnecessary object creation and the
mapping operation when there is nothing to reset.

In `@SLASHED-for-WP/admin-app/src/components/Header.svelte`:
- Line 20: The modCount derivation on line 20 is duplicating the calculation
that is already provided by the overrideCount variable imported from the store
on line 17. Remove the derivation of modCount using
Object.keys(overrides).length and instead use the already-imported overrideCount
directly in your template or reassign modCount to equal overrideCount to
eliminate the redundant calculation.

In `@SLASHED-for-WP/admin-app/src/components/Sidebar.svelte`:
- Line 88: The keyboard shortcut hint in the Sidebar.svelte component currently
displays a hardcoded Mac-specific keyboard shortcut (⌘Z) that is not appropriate
for Windows/Linux users. Modify the hint section by implementing platform
detection to conditionally display the correct undo shortcut: show ⌘Z for Mac
users and Ctrl+Z for Windows/Linux users. You can detect the platform using
JavaScript at runtime (such as checking navigator.platform or user agent) and
conditionally render the appropriate kbd element with the cfg-kbd class, or
alternatively simplify the hint to show a generic label like "Undo" without
platform-specific key combinations if platform detection is not feasible.

In `@SLASHED-for-WP/includes/class-rest-controller.php`:
- Around line 521-559: The list_framework_versions method currently makes an
external HTTP request on every call, causing unnecessary latency and load.
Implement transient caching to store the fetched version list for a short
duration (such as 1 hour). At the start of the method, check if a cached version
list exists using get_transient with an appropriate key; if it exists, return
the cached data immediately. If the transient is empty, proceed with the
existing HTTP request logic to fetch the version list from
Slashed_Framework_Updater::METADATA_URL. After successfully retrieving and
validating the versions array, store the result using set_transient before
returning, so subsequent calls within the cache duration will use the stored
data instead of making new external requests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f1aa2d70-2898-4840-9354-81f94206a961

📥 Commits

Reviewing files that changed from the base of the PR and between 590988d and 2b964b1.

⛔ Files ignored due to path filters (1)
  • SLASHED-for-WP/admin-app/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (47)
  • .github/workflows/ci.yml
  • .gitignore
  • SLASHED-for-WP/admin-app/src/components/BrandColorRow.svelte
  • SLASHED-for-WP/admin-app/src/components/Cheatsheet.svelte
  • SLASHED-for-WP/admin-app/src/components/ContrastBadge.svelte
  • SLASHED-for-WP/admin-app/src/components/DomainPanel.svelte
  • SLASHED-for-WP/admin-app/src/components/Header.svelte
  • SLASHED-for-WP/admin-app/src/components/Home.svelte
  • SLASHED-for-WP/admin-app/src/components/ManualCssTab.svelte
  • SLASHED-for-WP/admin-app/src/components/OklchPicker.svelte
  • SLASHED-for-WP/admin-app/src/components/OutputPanel.svelte
  • SLASHED-for-WP/admin-app/src/components/Preview.svelte
  • SLASHED-for-WP/admin-app/src/components/QuickKnobs.svelte
  • SLASHED-for-WP/admin-app/src/components/ScaleGenerator.svelte
  • SLASHED-for-WP/admin-app/src/components/SettingsTab.svelte
  • SLASHED-for-WP/admin-app/src/components/Sidebar.svelte
  • SLASHED-for-WP/admin-app/src/components/StylePresetRow.svelte
  • SLASHED-for-WP/admin-app/src/components/ThemeGallery.svelte
  • SLASHED-for-WP/admin-app/src/components/TokenEditor.svelte
  • SLASHED-for-WP/admin-app/src/components/TokenGroup.svelte
  • SLASHED-for-WP/admin-app/src/components/TokenRow.svelte
  • SLASHED-for-WP/admin-app/src/components/WcagPanel.svelte
  • SLASHED-for-WP/admin-app/src/data/api-index.generated.json
  • SLASHED-for-WP/admin-app/src/lib/basics.js
  • SLASHED-for-WP/admin-app/src/lib/brandColors.js
  • SLASHED-for-WP/admin-app/src/lib/clipboard.js
  • SLASHED-for-WP/admin-app/src/lib/color.js
  • SLASHED-for-WP/admin-app/src/lib/contrast.js
  • SLASHED-for-WP/admin-app/src/lib/css.js
  • SLASHED-for-WP/admin-app/src/lib/domains.js
  • SLASHED-for-WP/admin-app/src/lib/fluidEngine.js
  • SLASHED-for-WP/admin-app/src/lib/fonts.js
  • SLASHED-for-WP/admin-app/src/lib/historyOps.js
  • SLASHED-for-WP/admin-app/src/lib/length.js
  • SLASHED-for-WP/admin-app/src/lib/lightdark.js
  • SLASHED-for-WP/admin-app/src/lib/model.js
  • SLASHED-for-WP/admin-app/src/lib/preview.js
  • SLASHED-for-WP/admin-app/src/lib/probeHost.js
  • SLASHED-for-WP/admin-app/src/lib/scale.js
  • SLASHED-for-WP/admin-app/src/lib/stylePresets.js
  • SLASHED-for-WP/admin-app/src/lib/themes.js
  • SLASHED-for-WP/admin-app/src/lib/uiState.js
  • SLASHED-for-WP/admin-app/src/styles/app.css
  • SLASHED-for-WP/admin-app/vite.config.js
  • SLASHED-for-WP/assets/admin-app/app.css
  • SLASHED-for-WP/assets/admin-app/app.js
  • SLASHED-for-WP/includes/class-rest-controller.php

Comment on lines +42 to +44
function gammaToLinear(c) {
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Gamma decode threshold inconsistency between contrast.js and color.js.

contrast.js uses threshold 0.03928 (WCAG 2.1 spec), but color.js line 25 uses 0.04045 (sRGB spec). This inconsistency causes the two modules to compute different contrast ratios for identical color pairs, breaking WCAG compliance guarantees.

According to the WCAG 2.1 specification, the correct threshold for relative luminance calculations is 0.03928. Since color.js claims WCAG 2.1 compliance (line 15 comment), its toLinear function should use 0.03928, not 0.04045.

🔧 Proposed fix for color.js

Update color.js line 25 to use the WCAG 2.1 threshold:

 export function toLinear(c) {
   c /= 255;
-  return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
+  return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SLASHED-for-WP/admin-app/src/lib/contrast.js` around lines 42 - 44, Update
the gamma decode threshold in the toLinear function from 0.04045 to 0.03928 to
match the WCAG 2.1 specification used in the gammaToLinear function. This
ensures consistent relative luminance calculations across both modules and
maintains WCAG 2.1 compliance. The sRGB spec value of 0.04045 must be replaced
with the correct WCAG 2.1 threshold of 0.03928 in the conditional expression.


--cfg-accent: #75a7ff;
--cfg-accent-strong: #4f8cff;
--cfg-accent-soft: rgba(79, 140, 255, 0.16);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix color function notation to use modern rgb() syntax.

Stylelint expects modern color-function notation using rgb() instead of rgba(). The alpha channel is now part of rgb().

📐 Proposed fix
-  --cfg-accent-soft: rgba(79, 140, 255, 0.16);
+  --cfg-accent-soft: rgb(79 140 255 / 0.16);

Apply the same pattern to all other rgba() instances in this file (lines 29, 32, 47-48, 73-74, 84-85, etc.).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
--cfg-accent-soft: rgba(79, 140, 255, 0.16);
--cfg-accent-soft: rgb(79 140 255 / 0.16);
🧰 Tools
🪛 GitHub Actions: CI / 1_Lint, test, version & drift checks.txt

[error] 28-28: stylelint rule color-function-alias-notation: Expected "rgba" to be "rgb".


[error] 28-28: stylelint rule color-function-notation: Expected modern color-function notation.

🪛 GitHub Actions: CI / Lint, test, version & drift checks

[error] 28-28: stylelint (color-function-alias-notation & color-function-notation): Expected "rgba" to be "rgb" and modern color-function notation (at 28:22). Multiple occurrences reported.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SLASHED-for-WP/admin-app/src/styles/app.css` at line 28, Replace all
instances of the legacy `rgba()` color function notation with modern `rgb()`
syntax in the CSS file. For each `rgba()` call (such as the one at the css
variable `--cfg-accent-soft`), convert it to use the modern `rgb()` function
where the red, green, and blue values are space-separated and the alpha channel
is appended after a forward slash. For example, `rgba(79, 140, 255, 0.16)`
should become `rgb(79 140 255 / 0.16)`. Apply this conversion consistently to
all color variables and declarations throughout the file that currently use
`rgba()` notation.

--cfg-warn: #ffd556;

--cfg-mono: ui-monospace, "SFMono-Regular", "JetBrains Mono", "Menlo", monospace;
--cfg-sans: system-ui, -apple-system, "Inter", "Segoe UI", Roboto, sans-serif;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use lowercase for font-family keyword values.

Stylelint requires lowercase for CSS keyword values. Change "Roboto" to "roboto" or remove quotes if it's a keyword (though here it's a font name, so lowercase is still preferred).

📐 Proposed fix
-  --cfg-sans: system-ui, -apple-system, "Inter", "Segoe UI", Roboto, sans-serif;
+  --cfg-sans: system-ui, -apple-system, "Inter", "Segoe UI", roboto, sans-serif;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
--cfg-sans: system-ui, -apple-system, "Inter", "Segoe UI", Roboto, sans-serif;
--cfg-sans: system-ui, -apple-system, "Inter", "Segoe UI", roboto, sans-serif;
🧰 Tools
🪛 GitHub Actions: CI / 1_Lint, test, version & drift checks.txt

[error] 37-37: stylelint rule value-keyword-case: Expected "Roboto" to be "roboto".

🪛 GitHub Actions: CI / Lint, test, version & drift checks

[error] 37-37: stylelint (value-keyword-case): Expected "Roboto" to be "roboto" (at 37:62).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SLASHED-for-WP/admin-app/src/styles/app.css` at line 37, The CSS custom
property --cfg-sans contains a font name "Roboto" that must be lowercase to
comply with stylelint rules for CSS keyword values. Change "Roboto" to "roboto"
in the font-family declaration to resolve the stylelint validation error.

[data-ui-theme="light"] {
--cfg-bg: #f4f6fb;
--cfg-bg-2: #edf0f8;
--cfg-surface: #ffffff;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use shorthand hex notation.

Stylelint expects #fff instead of #ffffff for brevity.

📐 Proposed fix
-  --cfg-surface: `#ffffff`;
+  --cfg-surface: `#fff`;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
--cfg-surface: #ffffff;
--cfg-surface: `#fff`;
🧰 Tools
🪛 GitHub Actions: CI / 1_Lint, test, version & drift checks.txt

[error] 60-60: stylelint rule color-hex-length: Expected "#ffffff" to be "#fff".

🪛 GitHub Actions: CI / Lint, test, version & drift checks

[error] 60-60: stylelint (color-hex-length): Expected "#ffffff" to be "#fff" (at 60:18).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SLASHED-for-WP/admin-app/src/styles/app.css` at line 60, The CSS custom
property `--cfg-surface` is using the full hex color notation `#ffffff` which
should be shortened to `#fff` for consistency with Stylelint requirements.
Replace the value of the `--cfg-surface` variable with the shorthand hex
notation.

font-size: 14px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use lowercase for CSS keyword values.

The text-rendering value should be lowercase per stylelint.

📐 Proposed fix
-  text-rendering: optimizeLegibility;
+  text-rendering: optimizelegibility;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
text-rendering: optimizeLegibility;
text-rendering: optimizelegibility;
🧰 Tools
🪛 GitHub Actions: CI / 1_Lint, test, version & drift checks.txt

[error] 106-106: stylelint rule value-keyword-case: Expected "optimizeLegibility" to be "optimizelegibility".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SLASHED-for-WP/admin-app/src/styles/app.css` at line 106, The text-rendering
property value optimizeLegibility uses mixed case but should be lowercase per
stylelint standards. Change the value to optimizelegibility to comply with CSS
keyword formatting rules. This is a simple case conversion of the property value
in the text-rendering declaration.

padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Replace deprecated clip property with clip-path.

The clip property is deprecated. Use clip-path: inset(50%) for the same effect in the .cfg-sr-only screen-reader helper.

📐 Proposed fix
-  clip: rect(0, 0, 0, 0);
+  clip-path: inset(50%);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
clip: rect(0, 0, 0, 0);
clip-path: inset(50%);
🧰 Tools
🪛 GitHub Actions: CI / 1_Lint, test, version & drift checks.txt

[error] 278-278: stylelint rule property-no-deprecated: Deprecated property "clip".

🪛 GitHub Actions: CI / Lint, test, version & drift checks

[error] 278-278: stylelint (property-no-deprecated): Deprecated property "clip" (at 278:3).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SLASHED-for-WP/admin-app/src/styles/app.css` at line 278, The `clip` property
used in the `.cfg-sr-only` class is deprecated and should be replaced with the
modern `clip-path` property. In the app.css file where `clip: rect(0, 0, 0, 0);`
appears in the `.cfg-sr-only` screen-reader helper class, replace this line with
`clip-path: inset(50%);` to achieve the same visual effect of hiding content
from the viewport while keeping it accessible to screen readers.

Comment on lines +16 to +20
define: {
// Replaced at build time: reads the framework CSS version from PHP hydration.
// model.js uses `typeof __SLASHED_VERSION__ !== 'undefined'` to pick this up.
__SLASHED_VERSION__: '(window.slashedApp?.versions?.framework ?? "")',
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix __SLASHED_VERSION__ definition to inject runtime expression correctly.

The current value includes outer quotes and parentheses, which will cause Vite to replace __SLASHED_VERSION__ with the string literal '(window.slashedApp?.versions?.framework ?? "")' instead of the runtime expression window.slashedApp?.versions?.framework ?? "".

This means the framework version pill will display the literal string instead of evaluating the expression to get the actual version.

🔧 Proposed fix
   define: {
     // Replaced at build time: reads the framework CSS version from PHP hydration.
     // model.js uses `typeof __SLASHED_VERSION__ !== 'undefined'` to pick this up.
-    __SLASHED_VERSION__: '(window.slashedApp?.versions?.framework ?? "")',
+    __SLASHED_VERSION__: 'window.slashedApp?.versions?.framework ?? ""',
   },

Remove the outer quotes and parentheses. Vite's define will inject this as a raw expression in the compiled code.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SLASHED-for-WP/admin-app/vite.config.js` around lines 16 - 20, The
__SLASHED_VERSION__ definition in the define configuration currently includes
outer quotes and parentheses, which causes Vite to inject it as a string literal
rather than a runtime expression. Remove the outer quotes and parentheses from
the __SLASHED_VERSION__ value so that Vite injects the expression
window.slashedApp?.versions?.framework ?? "" directly into the compiled code,
allowing it to evaluate at runtime to display the actual framework version.

Comment on lines +1 to +2
.hdr.svelte-oiwvqb{background:linear-gradient(to bottom, #ffffff05, transparent), var(--cfg-surface);border-bottom:1px solid var(--cfg-border);grid-area:header;grid-template-columns:minmax(280px,1fr) minmax(220px,480px) auto;align-items:center;gap:18px;padding:12px 18px;display:grid}.hdr__brand.svelte-oiwvqb{flex-wrap:wrap;align-items:center;gap:12px;min-width:0;display:flex}.hdr__mark.svelte-oiwvqb{font-family:var(--cfg-mono);color:var(--cfg-accent);border:1px solid var(--cfg-border-strong);border-radius:var(--cfg-radius);background:linear-gradient(135deg,#4f8cff2e,#7850dc2e);flex-shrink:0;place-items:center;width:42px;height:42px;font-size:26px;font-weight:800;display:grid}.hdr__title-wrap.svelte-oiwvqb{min-width:0}.hdr__title.svelte-oiwvqb{letter-spacing:.005em;margin:0;font-size:16px;font-weight:600}.hdr__sub.svelte-oiwvqb{color:var(--cfg-text-muted);margin:1px 0 0;font-size:11.5px}.hdr__pills.svelte-oiwvqb{flex-wrap:wrap;gap:6px;display:inline-flex}.hdr__pill.svelte-oiwvqb{font-family:var(--cfg-mono);color:var(--cfg-accent);background:#4f8cff1a;border:1px solid #75a7ff66;border-radius:999px;padding:2px 9px;font-size:10.5px;font-weight:600;line-height:1.6}.hdr__pill--muted.svelte-oiwvqb{color:var(--cfg-text-muted);border-color:var(--cfg-border-strong);background:var(--cfg-surface-2)}.hdr__pill--mod.svelte-oiwvqb{color:var(--cfg-warn);background:#ffd5561f;border-color:#ffd55666}.hdr__pill--btn.svelte-oiwvqb{cursor:pointer;transition:background .12s,border-color .12s}.hdr__pill--btn.svelte-oiwvqb:hover{background:#ffd55638;border-color:#ffd556b3}.hdr__search.svelte-oiwvqb{align-items:center;display:flex;position:relative}.hdr__search-icon.svelte-oiwvqb{color:var(--cfg-text-faint);pointer-events:none;font-size:14px;position:absolute;left:10px}.hdr__search-input.svelte-oiwvqb{width:100%;padding-left:28px;padding-right:30px}.hdr__search-kbd.svelte-oiwvqb{pointer-events:none;position:absolute;right:8px}.hdr__controls.svelte-oiwvqb{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;display:flex}.hdr__history.svelte-oiwvqb{gap:2px;display:inline-flex}.hdr__pane.svelte-oiwvqb{border-color:var(--cfg-border-strong);color:var(--cfg-text-muted)}.hdr__theme-toggle.svelte-oiwvqb{margin-right:4px}@media (max-width:1100px){.hdr.svelte-oiwvqb{grid-template-columns:minmax(0,1fr) minmax(180px,320px) auto}.hdr__sub.svelte-oiwvqb{display:none}}@media (max-width:760px){.hdr.svelte-oiwvqb{grid-template-rows:auto auto;grid-template-columns:minmax(0,1fr);gap:10px}.hdr__brand.svelte-oiwvqb{order:1}.hdr__search.svelte-oiwvqb{order:3;grid-column:1}.hdr__controls.svelte-oiwvqb{order:2;justify-content:flex-end}.hdr__sub.svelte-oiwvqb{display:none}.hdr__title.svelte-oiwvqb{font-size:15px}}@media (max-width:600px){.hdr.svelte-oiwvqb{gap:8px;padding:10px 12px}.hdr__pill--muted.svelte-oiwvqb,.hdr__pane--side.svelte-oiwvqb{display:none}.hdr__controls.svelte-oiwvqb{scrollbar-width:none;flex-wrap:nowrap;justify-content:flex-start;gap:6px;overflow-x:auto}.hdr__controls.svelte-oiwvqb::-webkit-scrollbar{display:none}}.sidebar.svelte-p4t2mh{background:var(--cfg-sidebar,#1a1a1a);border-right:1px solid var(--cfg-border,#333);flex-direction:column;grid-area:side;width:100%;min-width:0;display:flex;overflow:hidden}.sidebar__toggle.svelte-p4t2mh{border:none;border-bottom:1px solid var(--cfg-border,#333);height:36px;color:var(--cfg-text-muted,#888);cursor:pointer;background:0 0;flex-shrink:0;justify-content:center;align-items:center;width:100%;padding:0;font-size:10px;transition:color .1s,background .1s;display:flex}.sidebar__toggle.svelte-p4t2mh:hover{color:var(--cfg-text,#eee);background:var(--cfg-hover,#ffffff0d)}.sidebar__nav.svelte-p4t2mh{scrollbar-width:thin;flex:1;padding:4px 0;overflow:hidden auto}.sidebar__item.svelte-p4t2mh{box-sizing:border-box;width:calc(100% - 8px);height:36px;color:var(--cfg-text-muted,#888);cursor:pointer;text-align:left;white-space:nowrap;background:0 0;border:none;border-radius:4px;align-items:center;gap:8px;margin:1px 4px;padding:0 8px;font-family:inherit;font-size:12px;transition:color .1s,background .1s;display:flex;overflow:hidden}.sidebar__item.svelte-p4t2mh:hover{color:var(--cfg-text,#eee);background:var(--cfg-hover,#ffffff0f)}.sidebar__item--active.svelte-p4t2mh{color:var(--cfg-accent,#60a5fa);background:var(--cfg-active,#60a5fa1a)}.sidebar__item--tool.svelte-p4t2mh{font-style:italic}.sidebar__icon.svelte-p4t2mh{text-align:center;flex-shrink:0;width:20px;font-size:14px;line-height:1}.sidebar__label.svelte-p4t2mh{text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.sidebar__divider.svelte-p4t2mh{background:var(--cfg-border,#333);height:1px;margin:6px 8px}.sidebar__count.svelte-p4t2mh{background:var(--cfg-accent,#60a5fa);color:#000;text-align:center;border-radius:10px;min-width:16px;margin:0 auto 8px;padding:1px 5px;font-size:10px;font-weight:600}.sidebar--collapsed.svelte-p4t2mh .sidebar__item:where(.svelte-p4t2mh){justify-content:center;padding:0}.oklch.svelte-fqycfb{z-index:9999;background:var(--cfg-surface-2);border:1px solid var(--cfg-border-strong);border-radius:var(--cfg-radius);width:304px;box-shadow:var(--cfg-shadow-pop);flex-direction:column;gap:8px;padding:12px;display:flex;position:fixed}.oklch__preview.svelte-fqycfb{border-radius:var(--cfg-radius-s);border:1px solid var(--cfg-border);background-image:linear-gradient(var(--pc,transparent), var(--pc,transparent)), conic-gradient(#444 25%, #2a2a2a 0 50%, #444 0 75%, #2a2a2a 0);background-size:cover,12px 12px;height:44px}.oklch__top.svelte-fqycfb{align-items:center;gap:8px;display:flex}.oklch__modes.svelte-fqycfb{flex:1}.oklch__icon-btn.svelte-fqycfb{background:var(--cfg-bg);border:1px solid var(--cfg-border-strong);border-radius:var(--cfg-radius-s);width:32px;height:28px;color:var(--cfg-text-muted);font-size:16px;line-height:1}.oklch__icon-btn.svelte-fqycfb:hover{color:var(--cfg-text);border-color:var(--cfg-border-focus)}.oklch__row.svelte-fqycfb{grid-template-columns:14px 1fr 60px;align-items:center;gap:8px;display:grid}.oklch__ch.svelte-fqycfb{font-family:var(--cfg-mono);color:var(--cfg-text-faint);text-align:center;font-size:11px}.oklch__slider.svelte-fqycfb{appearance:none;background:var(--trk,#555);cursor:pointer;border:1px solid #00000026;border-radius:6px;outline:none;height:12px}.oklch__slider.svelte-fqycfb::-webkit-slider-thumb{-webkit-appearance:none;cursor:pointer;background:#fff;border:2px solid #00000040;border-radius:50%;width:18px;height:18px;box-shadow:0 1px 4px #0006}.oklch__slider.svelte-fqycfb::-moz-range-thumb{cursor:pointer;background:#fff;border:2px solid #00000040;border-radius:50%;width:18px;height:18px;box-shadow:0 1px 4px #0006}.oklch__num.svelte-fqycfb{font-family:var(--cfg-mono);background:var(--cfg-bg);border:1px solid var(--cfg-border);border-radius:var(--cfg-radius-s);color:var(--cfg-text);text-align:right;width:100%;padding:3px 5px;font-size:11px}.oklch__num.svelte-fqycfb:focus{outline:2px solid var(--cfg-accent);outline-offset:-1px}.oklch__hex.svelte-fqycfb{align-items:center;gap:8px;margin-top:2px;display:flex}.oklch__hex-label.svelte-fqycfb{font-family:var(--cfg-mono);color:var(--cfg-text-faint);width:36px;font-size:11px}.oklch__hex-input.svelte-fqycfb{font-family:var(--cfg-mono);background:var(--cfg-bg);border:1px solid var(--cfg-border);border-radius:var(--cfg-radius-s);color:var(--cfg-text);text-transform:uppercase;flex:1;padding:5px 8px;font-size:12px}.oklch__hex-input.svelte-fqycfb:focus{outline:2px solid var(--cfg-accent);outline-offset:-1px;border-color:var(--cfg-accent)}.oklch__out.svelte-fqycfb{font-family:var(--cfg-mono);color:var(--cfg-text-faint);word-break:break-all;background:var(--cfg-bg);border-radius:var(--cfg-radius-s);border:1px solid var(--cfg-border);padding:6px 8px;font-size:11px;line-height:1.4}.editor.svelte-xs7uts{flex:1;align-items:center;gap:8px;min-width:0;display:flex}.editor.svelte-xs7uts .cfg-input{flex:1;min-width:0}.editor--font.svelte-xs7uts{align-items:stretch}.font.svelte-xs7uts{flex-direction:column;gap:6px;width:100%;display:flex}.font__top.svelte-xs7uts{align-items:center;gap:8px;display:flex}.font__seg.svelte-xs7uts{flex-shrink:0}.font__select.svelte-xs7uts{flex:1;min-width:0}.font__preview.svelte-xs7uts{color:var(--cfg-text);white-space:nowrap;text-overflow:ellipsis;border-top:1px dashed var(--cfg-border);padding-top:4px;font-size:14px;overflow:hidden}.editor__swatch.svelte-xs7uts{border-radius:var(--cfg-radius-s);border:1px solid var(--cfg-border-strong);cursor:pointer;background-image:linear-gradient(var(--probe,transparent), var(--probe,transparent)), conic-gradient(#444 25%, #2a2a2a 0 50%, #444 0 75%, #2a2a2a 0);background-size:cover,12px 12px;flex-shrink:0;width:30px;height:30px;padding:0;transition:box-shadow .1s,border-color .1s}.editor__swatch.svelte-xs7uts:hover{box-shadow:0 0 0 2px var(--cfg-accent)}.editor__unit.svelte-xs7uts{color:var(--cfg-text-faint);font-family:var(--cfg-mono);text-align:left;min-width:24px;font-size:12px}.len__slider.svelte-xs7uts{appearance:none;background:linear-gradient(to right, var(--cfg-accent-strong) 0, var(--cfg-accent-strong) var(--p,0%), var(--cfg-surface-3) var(--p,0%), var(--cfg-surface-3) 100%);cursor:pointer;border:none;border-radius:3px;outline:none;flex:90px;min-width:60px;height:6px;margin:0}.len__slider.svelte-xs7uts:focus-visible{box-shadow:0 0 0 3px var(--cfg-accent-soft)}.len__slider.svelte-xs7uts:disabled{opacity:.45;cursor:not-allowed}.len__slider.svelte-xs7uts::-webkit-slider-thumb{-webkit-appearance:none;border:2px solid var(--cfg-accent-strong);cursor:pointer;background:#fff;border-radius:50%;width:14px;height:14px;box-shadow:0 1px 4px #00000080}.len__slider.svelte-xs7uts::-moz-range-thumb{border:2px solid var(--cfg-accent-strong);cursor:pointer;background:#fff;border-radius:50%;width:14px;height:14px;box-shadow:0 1px 4px #00000080}.len__num.svelte-xs7uts{text-align:right;flex:0 0 70px}.len__raw.svelte-xs7uts{text-transform:uppercase;letter-spacing:.05em;flex-shrink:0;font-size:10.5px}@media (max-width:600px){.len__num.svelte-xs7uts{flex:0 0 58px}}.cb.svelte-112lbn9{font-family:var(--cfg-mono);letter-spacing:.02em;border:1px solid var(--cfg-border-strong);color:var(--cfg-text-muted);background:var(--cfg-surface-2);white-space:nowrap;border-radius:999px;align-items:center;padding:1px 6px;font-size:9.5px;font-weight:700;line-height:1.5;display:inline-flex}.cb--aaa.svelte-112lbn9{color:#87e8a4;background:#288a412e;border-color:#87e8a466}.cb--aa.svelte-112lbn9{color:#6dd9c8;background:#2882822e;border-color:#6dd9c866}.cb--aaL.svelte-112lbn9{color:#ffd79a;background:#b8821e2e;border-color:#ffd79a66}.cb--fail.svelte-112lbn9{color:#ff8c8c;background:#b432322e;border-color:#ff8c8c66}.row.svelte-12pzrt1{border-bottom:1px solid var(--cfg-border);grid-template-columns:minmax(0,1fr) minmax(340px,460px);align-items:center;gap:16px;padding:12px 16px;transition:background .15s;display:grid}.row.svelte-12pzrt1:hover{background:#ffffff05}.row.svelte-12pzrt1:last-child{border-bottom:none}.row--modified.svelte-12pzrt1{box-shadow:inset 3px 0 0 var(--cfg-accent-strong);background:linear-gradient(90deg,#4f8cff14,#0000 60%)}.row--modified.svelte-12pzrt1:hover{background:linear-gradient(90deg,#4f8cff1f,#0000 60%)}.row__info.svelte-12pzrt1{min-width:0}.row__name-line.svelte-12pzrt1{flex-wrap:wrap;align-items:center;gap:7px;display:flex}.row__name.svelte-12pzrt1{border-radius:var(--cfg-radius-s);color:var(--cfg-text);cursor:pointer;text-align:left;background:0 0;border:1px solid #0000;align-items:center;gap:6px;min-width:0;max-width:100%;padding:1px 6px;transition:background .12s,border-color .12s,color .12s;display:inline-flex}.row__name.svelte-12pzrt1 code:where(.svelte-12pzrt1){font-family:var(--cfg-mono);word-break:break-all;font-size:12.5px}.row__copy.svelte-12pzrt1{color:var(--cfg-text-faint);opacity:0;font-size:11px;transition:opacity .15s,color .15s}.row__name.svelte-12pzrt1:hover{background:var(--cfg-surface-2);border-color:var(--cfg-border)}.row__name.svelte-12pzrt1:hover .row__copy:where(.svelte-12pzrt1){opacity:1}.row__name.svelte-12pzrt1:focus-visible{outline:2px solid var(--cfg-accent);outline-offset:1px}.row__drives.svelte-12pzrt1{text-transform:uppercase;letter-spacing:.06em;color:var(--cfg-accent);background:var(--cfg-accent-soft);white-space:nowrap;border-radius:999px;padding:1px 7px;font-size:9.5px;font-weight:700;line-height:1.6}.row__alias.svelte-12pzrt1{font-family:var(--cfg-mono);color:var(--cfg-text-faint);font-size:11px}.row__opt.svelte-12pzrt1{text-transform:uppercase;letter-spacing:.05em;color:var(--cfg-text-faint);border:1px solid var(--cfg-border);border-radius:999px;padding:0 6px;font-size:9.5px;font-weight:600}.row__desc.svelte-12pzrt1{color:var(--cfg-text-muted);max-width:60ch;margin:4px 0 0;font-size:12px;line-height:1.5}.row__desc--faint.svelte-12pzrt1{color:var(--cfg-text-faint)}.row__label.svelte-12pzrt1{color:var(--cfg-text);font-size:13.5px;font-weight:600}.row__info-btn.svelte-12pzrt1{width:18px;height:18px;color:var(--cfg-text-faint);cursor:pointer;background:0 0;border:0;border-radius:999px;place-items:center;padding:0;font-size:12px;line-height:1;transition:color .12s;display:inline-grid}.row__info-btn.svelte-12pzrt1:hover,.row__info-btn--on.svelte-12pzrt1{color:var(--cfg-accent)}.row__raw.svelte-12pzrt1{background:var(--cfg-bg-2);border:1px solid var(--cfg-border);border-radius:var(--cfg-radius-s);margin-top:6px;padding:8px 10px}.row__raw-line.svelte-12pzrt1{flex-wrap:wrap;align-items:center;gap:7px;display:flex}.row__default.svelte-12pzrt1{color:var(--cfg-text-faint);margin:4px 0 0;font-size:11px}.row__default.svelte-12pzrt1 code:where(.svelte-12pzrt1){font-family:var(--cfg-mono);color:var(--cfg-text-muted);word-break:break-all;font-size:11px}.row__control.svelte-12pzrt1{align-items:center;gap:8px;min-width:0;display:flex}.row__reset.svelte-12pzrt1{flex-shrink:0;font-size:14px;line-height:1}.row--consume.svelte-12pzrt1{opacity:.7}.row--consume.svelte-12pzrt1:hover{background:0 0}.row__readonly.svelte-12pzrt1{background:var(--cfg-bg-2);border:1px dashed var(--cfg-border);border-radius:var(--cfg-radius-s);flex:1;align-items:center;min-width:0;padding:7px 10px;display:flex;overflow:hidden}.row__readonly-val.svelte-12pzrt1{font-family:var(--cfg-mono);color:var(--cfg-text-faint);white-space:nowrap;text-overflow:ellipsis;font-size:11.5px;overflow:hidden}@media (max-width:720px){.row.svelte-12pzrt1{grid-template-columns:1fr;gap:8px}}@media (max-width:600px){.row.svelte-12pzrt1{padding:10px 12px}.row__opt.svelte-12pzrt1,.row__alias.svelte-12pzrt1{display:none}.row__desc.svelte-12pzrt1{font-size:11.5px}}.group.svelte-1fgpw6o{overflow:clip}.group--mod.svelte-1fgpw6o{box-shadow:var(--cfg-shadow-card), 0 0 0 1px #4f8cff2e}.group__head.svelte-1fgpw6o{text-align:left;background:var(--cfg-surface-2);width:100%;color:var(--cfg-text);border:none;grid-template-columns:14px minmax(0,1fr) auto auto;align-items:center;gap:10px;padding:11px 14px;font-size:13px;transition:background .12s;display:grid}.group__head.svelte-1fgpw6o:hover{background:var(--cfg-surface-3)}.group__caret.svelte-1fgpw6o{color:var(--cfg-text-faint);text-align:center;font-size:9px;transition:transform .12s}.group__caret--open.svelte-1fgpw6o{transform:rotate(90deg)}.group__labels.svelte-1fgpw6o{flex-wrap:wrap;align-items:baseline;gap:8px;min-width:0;display:flex}.group__cat.svelte-1fgpw6o{color:var(--cfg-text-faint);text-transform:uppercase;letter-spacing:.06em;font-size:10px}.group__name.svelte-1fgpw6o{font-weight:600}.group__mod.svelte-1fgpw6o{font-family:var(--cfg-mono);color:#fff;background:var(--cfg-accent-strong);border-radius:999px;padding:1px 7px;font-size:10.5px;font-weight:700;line-height:1.5}.group__count.svelte-1fgpw6o{font-family:var(--cfg-mono);color:var(--cfg-text-faint);font-size:11px}.group__desc.svelte-1fgpw6o{color:var(--cfg-text-muted);border-bottom:1px solid var(--cfg-border);background:var(--cfg-bg-2);margin:0;padding:8px 14px 10px;font-size:12.5px}.bcr.svelte-1vc5u8w{border-bottom:1px solid var(--cfg-border);grid-template-columns:80px 1fr 18px 1fr;align-items:center;gap:8px;padding:8px 16px;transition:background .15s;display:grid}.bcr.svelte-1vc5u8w:hover{background:#ffffff05}.bcr.svelte-1vc5u8w:last-child{border-bottom:none}.bcr--light-mod.svelte-1vc5u8w,.bcr--dark-mod.svelte-1vc5u8w{box-shadow:inset 3px 0 0 var(--cfg-accent-strong);background:linear-gradient(90deg,#4f8cff0f,#0000 60%)}.bcr__label.svelte-1vc5u8w{color:var(--cfg-text-muted);white-space:nowrap;font-size:12px;font-weight:600}.bcr__side.svelte-1vc5u8w{align-items:center;gap:6px;min-width:0;display:flex}.bcr__swatch.svelte-1vc5u8w{border-radius:var(--cfg-radius-s);border:1px solid var(--cfg-border-strong);cursor:pointer;background-image:linear-gradient(var(--probe,transparent), var(--probe,transparent)), conic-gradient(#444 25%, #2a2a2a 0 50%, #444 0 75%, #2a2a2a 0);background-size:cover,10px 10px;flex-shrink:0;width:28px;height:28px;padding:0;transition:box-shadow .1s}.bcr__swatch.svelte-1vc5u8w:hover{box-shadow:0 0 0 2px var(--cfg-accent)}.bcr__swatch.svelte-1vc5u8w:focus-visible{outline:2px solid var(--cfg-accent);outline-offset:1px}.bcr__input.svelte-1vc5u8w{flex:1;min-width:0;font-size:11.5px}.bcr__reset.svelte-1vc5u8w{flex-shrink:0;font-size:13px;line-height:1}.bcr__arrow.svelte-1vc5u8w{color:var(--cfg-text-faint);text-align:center;font-size:11px}.bcr__auto.svelte-1vc5u8w{text-transform:uppercase;letter-spacing:.07em;color:var(--cfg-text-faint);border:1px solid var(--cfg-border);white-space:nowrap;cursor:default;border-radius:999px;padding:1px 7px;font-size:9.5px;font-weight:700;line-height:1.6}@media (max-width:720px){.bcr.svelte-1vc5u8w{grid-template-columns:60px 1fr 14px 1fr;gap:6px;padding:8px 12px}}@media (max-width:500px){.bcr.svelte-1vc5u8w{grid-template-columns:1fr;gap:4px}.bcr__label.svelte-1vc5u8w{font-size:11px}.bcr__arrow.svelte-1vc5u8w{display:none}}.card.svelte-1y8fkhh{background:var(--cfg-surface);border:1px solid var(--cfg-border);border-radius:var(--cfg-radius);padding:16px}.seg.svelte-1y8fkhh{border:1px solid var(--cfg-border-strong);border-radius:var(--cfg-radius-s);margin-bottom:16px;display:inline-flex;overflow:hidden}.seg__btn.svelte-1y8fkhh{background:var(--cfg-surface-2);color:var(--cfg-text-muted);border:none;padding:6px 16px;font-size:13px}.seg__btn--on.svelte-1y8fkhh{background:var(--cfg-accent-strong);color:#fff}.controls.svelte-1y8fkhh{flex-wrap:wrap;gap:14px;margin-bottom:16px;display:flex}.ctl.svelte-1y8fkhh{color:var(--cfg-text-muted);flex-direction:column;gap:5px;font-size:12px;display:flex}.ctl__in.svelte-1y8fkhh{align-items:center;gap:5px;display:flex}.ctl__in.svelte-1y8fkhh i:where(.svelte-1y8fkhh){color:var(--cfg-text-faint);font-size:11px;font-style:normal}.ctl.svelte-1y8fkhh input:where(.svelte-1y8fkhh){background:var(--cfg-bg);width:84px;color:var(--cfg-text);border:1px solid var(--cfg-border-strong);border-radius:var(--cfg-radius-s);padding:6px 8px}.ctl.svelte-1y8fkhh select:where(.svelte-1y8fkhh){background:var(--cfg-bg);color:var(--cfg-text);border:1px solid var(--cfg-border-strong);border-radius:var(--cfg-radius-s);padding:6px 8px;font-size:12px}.preview.svelte-1y8fkhh{border-top:1px solid var(--cfg-border);flex-direction:column;gap:4px;margin-bottom:16px;padding-top:12px;display:flex}.preview__row.svelte-1y8fkhh{grid-template-columns:16ch 1fr minmax(0,32ch);align-items:center;gap:12px;display:grid}.preview__row--missing.svelte-1y8fkhh{opacity:.4}.preview__token.svelte-1y8fkhh{font-family:var(--cfg-mono);color:var(--cfg-text-muted);font-size:11.5px}.preview__sample.svelte-1y8fkhh{color:var(--cfg-text);align-items:center;max-block-size:3rem;line-height:1;display:flex;overflow:hidden}.preview__bar.svelte-1y8fkhh{background:var(--cfg-accent-strong);border-radius:3px;block-size:12px;max-inline-size:100%}.preview__clamp.svelte-1y8fkhh{font-family:var(--cfg-mono);color:var(--cfg-text-faint);text-overflow:ellipsis;white-space:nowrap;font-size:11px;overflow:hidden}@media (max-width:600px){.preview__row.svelte-1y8fkhh{grid-template-columns:minmax(0,15ch) minmax(0,1fr);gap:8px}.preview__sample.svelte-1y8fkhh{display:none}.preview__clamp.svelte-1y8fkhh{white-space:normal;overflow-wrap:break-word;text-overflow:clip}}.scales__actions.svelte-1y8fkhh{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.scales__note.svelte-1y8fkhh{color:var(--cfg-text-faint);font-size:12px}.scales__hint.svelte-1y8fkhh{color:var(--cfg-text-muted);margin:0 0 12px;font-size:12px;line-height:1.5}.ctl.svelte-1y8fkhh select:where(.svelte-1y8fkhh):disabled{opacity:.55;cursor:not-allowed}.knobs.svelte-xuco48{overflow:clip}.knobs__head.svelte-xuco48{border-bottom:1px solid var(--cfg-border);background:linear-gradient(to right, #4f8cff0f, transparent 70%), var(--cfg-surface-2);justify-content:space-between;align-items:center;gap:12px;padding:12px 16px;display:flex}.knobs__title-wrap.svelte-xuco48{flex-wrap:wrap;align-items:baseline;gap:10px;display:flex}.knobs__title.svelte-xuco48{text-transform:uppercase;letter-spacing:.06em;color:var(--cfg-text);font-size:12.5px;font-weight:700}.knobs__blurb.svelte-xuco48{color:var(--cfg-text-muted);font-size:12px}.knobs__list.svelte-xuco48{flex-direction:column;display:flex}.knob.svelte-xuco48{border-bottom:1px solid var(--cfg-border);grid-template-columns:minmax(160px,220px) minmax(0,1fr) minmax(110px,150px) auto;align-items:center;gap:12px;padding:10px 16px;transition:background .12s;display:grid}.knob.svelte-xuco48:last-child{border-bottom:none}.knob.svelte-xuco48:hover{background:#ffffff05}.knob--mod.svelte-xuco48{box-shadow:inset 3px 0 0 var(--cfg-accent-strong);background:linear-gradient(90deg,#4f8cff14,#0000 60%)}.knob--mod.svelte-xuco48:hover{background:linear-gradient(90deg,#4f8cff1f,#0000 60%)}.knob__label.svelte-xuco48{flex-wrap:wrap;align-items:center;gap:8px;min-width:0;display:flex}.knob__name.svelte-xuco48{font-family:var(--cfg-mono);color:var(--cfg-text);text-overflow:ellipsis;white-space:nowrap;font-size:12px;overflow:hidden}.knob__drives.svelte-xuco48{text-transform:uppercase;letter-spacing:.06em;color:var(--cfg-accent);background:var(--cfg-accent-soft);white-space:nowrap;border-radius:999px;padding:1px 7px;font-size:9.5px;font-weight:700;line-height:1.6}.knob__help.svelte-xuco48{background:var(--cfg-surface-3);border:1px solid var(--cfg-border);width:16px;height:16px;color:var(--cfg-text-muted);cursor:help;border-radius:50%;place-items:center;font-size:10px;font-weight:700;display:inline-grid}.knob__slider.svelte-xuco48{appearance:none;background:linear-gradient(to right, var(--cfg-accent-strong), var(--cfg-accent-strong)) 0/var(--p,50%) no-repeat, var(--cfg-surface-3);cursor:pointer;border:none;border-radius:3px;outline:none;width:100%;height:6px}.knob__slider.svelte-xuco48:focus-visible{box-shadow:0 0 0 3px var(--cfg-accent-soft)}.knob__slider.svelte-xuco48::-webkit-slider-thumb{-webkit-appearance:none;border:2px solid var(--cfg-accent-strong);cursor:pointer;background:#fff;border-radius:50%;width:16px;height:16px;box-shadow:0 1px 4px #00000080}.knob__slider.svelte-xuco48::-moz-range-thumb{border:2px solid var(--cfg-accent-strong);cursor:pointer;background:#fff;border-radius:50%;width:16px;height:16px;box-shadow:0 1px 4px #00000080}.knob__numeric.svelte-xuco48{align-items:center;gap:6px;display:flex}.knob__num.svelte-xuco48{text-align:right;width:100%}.knob__unit.svelte-xuco48{font-family:var(--cfg-mono);color:var(--cfg-text-faint);min-width:18px;font-size:11px}.knob__meta.svelte-xuco48{align-items:center;gap:8px;display:flex}.knob__default.svelte-xuco48{color:var(--cfg-text-faint);font-size:11px}.knob__default.svelte-xuco48 code:where(.svelte-xuco48){font-family:var(--cfg-mono);color:var(--cfg-text-muted)}.knob__reset.svelte-xuco48{font-size:14px;line-height:1}@media (max-width:900px){.knob.svelte-xuco48{grid-template-columns:1fr;gap:6px;padding:12px 16px}.knob__label.svelte-xuco48{order:1}.knob__slider.svelte-xuco48{order:2}.knob__numeric.svelte-xuco48{order:3}.knob__meta.svelte-xuco48{order:4;justify-content:space-between}}.presets.svelte-1vwjmdy{padding:12px 16px}.presets__head.svelte-1vwjmdy{flex-wrap:wrap;align-items:baseline;gap:12px;margin-bottom:10px;display:flex}.presets__title.svelte-1vwjmdy{text-transform:uppercase;letter-spacing:.06em;color:var(--cfg-text);font-size:12.5px;font-weight:700}.presets__hint.svelte-1vwjmdy{color:var(--cfg-text-faint);font-size:11.5px}.presets__row.svelte-1vwjmdy{flex-wrap:wrap;gap:8px;display:flex}.presets__btn.svelte-1vwjmdy{color:var(--cfg-text-muted);background:var(--cfg-surface-2);border:1px solid var(--cfg-border-strong);border-radius:var(--cfg-radius-s);cursor:pointer;padding:7px 16px;font-size:12.5px;transition:background .12s,color .12s,border-color .12s}.presets__btn.svelte-1vwjmdy:hover{color:var(--cfg-text);border-color:var(--cfg-accent-strong)}.presets__btn--on.svelte-1vwjmdy{background:var(--cfg-accent-strong);border-color:var(--cfg-accent-strong);color:#fff;font-weight:600}.panel.svelte-74kf9u{flex-direction:column;height:100%;min-height:0;display:flex;overflow:hidden}.panel__head.svelte-74kf9u{border-bottom:1px solid var(--cfg-border);background:var(--cfg-surface);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;padding:14px 20px 12px;display:flex}.panel__title-wrap.svelte-74kf9u{flex:auto;align-items:center;gap:10px;min-width:0;display:flex}.panel__icon.svelte-74kf9u{border-radius:var(--cfg-radius);border:1px solid var(--cfg-border-strong);background:linear-gradient(135deg,#4f8cff2e,#7850dc2e);flex-shrink:0;place-items:center;width:32px;height:32px;font-size:16px;display:inline-grid}.panel__title.svelte-74kf9u{margin:0;font-size:16px;font-weight:600}.panel__blurb.svelte-74kf9u{color:var(--cfg-text-muted);max-width:70ch;margin:2px 0 0;font-size:12px}.panel__actions.svelte-74kf9u{flex-wrap:wrap;flex-shrink:0;align-items:center;gap:10px;display:flex}.panel__usage-seg.svelte-74kf9u .cfg-seg__btn{padding:4px 10px;font-size:11.5px}.panel__check.svelte-74kf9u{color:var(--cfg-text-muted);cursor:pointer;white-space:nowrap;align-items:center;gap:6px;font-size:12px;display:flex}.panel__check.svelte-74kf9u input:where(.svelte-74kf9u){accent-color:var(--cfg-accent-strong)}.panel__body.svelte-74kf9u{flex-direction:column;gap:16px;min-height:0;padding:16px 20px 80px;display:flex;overflow-y:auto}.panel__card.svelte-74kf9u{overflow:clip}.panel__card-head.svelte-74kf9u{border-bottom:1px solid var(--cfg-border);background:var(--cfg-surface-2);flex-wrap:wrap;align-items:baseline;gap:12px;padding:12px 16px;display:flex}.panel__card-title.svelte-74kf9u{text-transform:uppercase;letter-spacing:.06em;color:var(--cfg-text);font-size:12.5px;font-weight:700}.panel__card-count.svelte-74kf9u{font-family:var(--cfg-mono);color:var(--cfg-text-faint);font-size:11px}.panel__card-hint.svelte-74kf9u{text-align:right;color:var(--cfg-text-faint);flex:auto;font-size:11.5px}.panel__intro.svelte-74kf9u{color:var(--cfg-text-muted);background:var(--cfg-surface);border:1px solid var(--cfg-border);border-left:3px solid var(--cfg-accent-strong);border-radius:var(--cfg-radius-s);margin:0;padding:10px 14px;font-size:13px;line-height:1.55}.panel__more.svelte-74kf9u{color:var(--cfg-text-muted);background:var(--cfg-surface-2);border:1px dashed var(--cfg-border-strong);border-radius:var(--cfg-radius-s);cursor:pointer;align-self:center;padding:8px 16px;font-size:12.5px;transition:color .12s,border-color .12s}.panel__more.svelte-74kf9u:hover{color:var(--cfg-text);border-color:var(--cfg-accent-strong)}.power.svelte-74kf9u{border-radius:var(--cfg-radius);background:#f0ad4e0f;border:1px solid #f0ad4e73;overflow:clip}.power__summary.svelte-74kf9u{cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;gap:10px;padding:12px 16px;list-style:none;display:flex}.power__summary.svelte-74kf9u::-webkit-details-marker{display:none}.power__summary.svelte-74kf9u:hover{background:#f0ad4e1a}.power__bolt.svelte-74kf9u{font-size:14px}.power__title.svelte-74kf9u{text-transform:uppercase;letter-spacing:.06em;font-size:12.5px;font-weight:700}.power__chip.svelte-74kf9u{font-family:var(--cfg-mono);color:#f0ad4e;border:1px solid #f0ad4e73;border-radius:999px;padding:1px 8px;font-size:10.5px}.power__intro.svelte-74kf9u{color:var(--cfg-text-muted);margin:0;padding:0 16px 10px;font-size:12.5px;line-height:1.55}.power.svelte-74kf9u>.knobs{border:0;border-top:1px solid #f0ad4e40;border-radius:0}.panel__empty.svelte-74kf9u,.panel__hint.svelte-74kf9u{color:var(--cfg-text-faint);text-align:center;padding:20px 4px;font-size:13.5px}.panel__empty.svelte-74kf9u code:where(.svelte-74kf9u){color:var(--cfg-text);background:var(--cfg-bg-2);border:1px solid var(--cfg-border);border-radius:4px;padding:1px 6px}.panel__docs.svelte-74kf9u{text-align:center;margin:4px 0 0;font-size:12px}.panel__docs.svelte-74kf9u a:where(.svelte-74kf9u){color:var(--cfg-text-faint);text-decoration:none;transition:color .12s}.panel__docs.svelte-74kf9u a:where(.svelte-74kf9u):hover{color:var(--cfg-accent);text-decoration:underline}@media (max-width:600px){.panel__body.svelte-74kf9u{gap:12px;padding:12px 10px 60px}.panel__head.svelte-74kf9u{gap:8px;padding:10px 12px 8px}.panel__title.svelte-74kf9u{font-size:14px}.panel__blurb.svelte-74kf9u{display:none}.panel__actions.svelte-74kf9u{flex-basis:100%;gap:8px}.panel__usage-seg.svelte-74kf9u .cfg-seg__btn{padding:4px 8px;font-size:10.5px}}.out.svelte-q0ve31{background:var(--cfg-surface);border-top:1px solid var(--cfg-border);flex-direction:column;grid-area:output;max-height:50vh;transition:max-height .18s;display:flex;box-shadow:0 -4px 16px #0003}.out--closed.svelte-q0ve31{max-height:44px}@media (max-width:600px){.out.svelte-q0ve31:not(.out--closed){max-height:35vh}}.out__head.svelte-q0ve31{flex-wrap:wrap;flex-shrink:0;justify-content:space-between;align-items:center;gap:12px;padding:6px 16px;display:flex}.out__toggle.svelte-q0ve31{color:var(--cfg-text);font:inherit;border-radius:var(--cfg-radius-s);background:0 0;border:none;align-items:center;gap:10px;padding:6px 4px;transition:background .12s;display:inline-flex}.out__toggle.svelte-q0ve31:hover{background:var(--cfg-surface-2)}.out__caret.svelte-q0ve31{color:var(--cfg-text-faint);font-size:9px;transition:transform .12s}.out__caret--open.svelte-q0ve31{transform:rotate(90deg)}.out__count.svelte-q0ve31{color:var(--cfg-text-faint);font-size:11.5px;font-family:var(--cfg-mono)}.out__actions.svelte-q0ve31{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.out__fmt.svelte-q0ve31{align-items:center;gap:8px;margin-right:4px;display:flex}.out__fmt-label.svelte-q0ve31{color:var(--cfg-text-faint);cursor:help;font-size:11px}.out__import.svelte-q0ve31{flex-shrink:0;align-items:flex-end;gap:8px;padding:8px 16px 10px;display:flex}.out__import.svelte-q0ve31 .cfg-textarea:where(.svelte-q0ve31){font-family:var(--cfg-mono);resize:vertical;flex:1;font-size:12px}.out__msg.svelte-q0ve31{color:var(--cfg-text-muted);margin:0;padding:0 16px 8px;font-size:12px}.out__msg--warn.svelte-q0ve31{color:var(--cfg-warn)}.out__code.svelte-q0ve31{background:var(--cfg-bg);border-top:1px solid var(--cfg-border);min-height:0;font-family:var(--cfg-mono);color:#c9d4e3;white-space:pre;tab-size:2;flex:1;margin:0;padding:12px 16px;font-size:12.5px;line-height:1.6;overflow:auto}.out__code.svelte-q0ve31 .hl-c{color:#6a7283;font-style:italic}.out__code.svelte-q0ve31 .hl-k{color:#c792ea}.out__code.svelte-q0ve31 .hl-p{color:#82aaff}.out__code.svelte-q0ve31 .hl-v{color:#c3e88d}.out__foot.svelte-q0ve31{color:var(--cfg-text-faint);border-top:1px solid var(--cfg-border);flex-shrink:0;padding:6px 16px;font-size:11px}.out__foot.svelte-q0ve31 code:where(.svelte-q0ve31){color:var(--cfg-text-muted)}.out__view.svelte-q0ve31{margin-right:4px}.out__empty.svelte-q0ve31{color:var(--cfg-text-faint);text-align:center;border-top:1px solid var(--cfg-border);flex:1;margin:0;padding:24px 16px;font-size:13px}.diff.svelte-q0ve31{background:var(--cfg-bg);border-top:1px solid var(--cfg-border);min-height:0;font-family:var(--cfg-mono);flex:1;margin:0;font-size:12px;line-height:1.55;overflow:auto}.diff__head.svelte-q0ve31,.diff__row.svelte-q0ve31{grid-template-columns:minmax(220px,1.2fr) minmax(0,1fr) minmax(0,1fr);align-items:start;gap:16px;padding:6px 16px;display:grid}.diff__head.svelte-q0ve31{background:var(--cfg-surface-2);border-bottom:1px solid var(--cfg-border);color:var(--cfg-text-muted);text-transform:uppercase;letter-spacing:.06em;z-index:1;padding-block:8px;font-size:10.5px;font-weight:700;position:sticky;top:0}.diff__row.svelte-q0ve31{border-bottom:1px solid var(--cfg-border)}.diff__row.svelte-q0ve31:hover{background:#ffffff06}.diff__row.svelte-q0ve31 code:where(.svelte-q0ve31){font:inherit;color:inherit}.diff__name.svelte-q0ve31{color:var(--cfg-text);word-break:break-all}.diff__before.svelte-q0ve31{color:var(--cfg-text-faint);word-break:break-all;-webkit-text-decoration:line-through #ff717673;text-decoration:line-through #ff717673}.diff__after.svelte-q0ve31{color:#c3e88d;word-break:break-all}.preview.svelte-1x4flvo{background:var(--cfg-surface);border-left:1px solid var(--cfg-border);flex-direction:column;grid-area:preview;min-width:0;height:100%;min-height:0;display:flex;overflow:hidden}.preview__bar.svelte-1x4flvo{border-bottom:1px solid var(--cfg-border);flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;padding:10px 16px;display:flex}.preview__viewports.svelte-1x4flvo{flex-shrink:0}.preview__vp-btn.svelte-1x4flvo{padding-inline:9px;font-size:11.5px}.preview__viewport.svelte-1x4flvo{background:var(--cfg-bg-2);flex:1;min-height:0;padding:0;overflow:auto}.preview__stage.svelte-1x4flvo{background:var(--sf-color-bg,#fff);color:var(--sf-color-text,#111);min-height:100%;transition:max-inline-size .15s}.preview__stage--rm.svelte-1x4flvo,.preview__stage--rm.svelte-1x4flvo :where(.svelte-1x4flvo),.preview__stage--rm.svelte-1x4flvo :where(.svelte-1x4flvo):before,.preview__stage--rm.svelte-1x4flvo :where(.svelte-1x4flvo):after{transition-duration:0s!important;transition-delay:0s!important;animation-duration:0s!important;animation-delay:0s!important}.preview__title.svelte-1x4flvo{align-items:center;gap:8px;display:inline-flex}.preview__dot.svelte-1x4flvo{background:var(--cfg-ok);border-radius:50%;width:8px;height:8px;box-shadow:0 0 0 3px #5ad27a2e}.preview__hint.svelte-1x4flvo{color:var(--cfg-text-faint);text-transform:capitalize;font-size:11px}.preview__modes.svelte-1x4flvo .cfg-seg__btn{padding:4px 9px;font-size:12px}.preview__close.svelte-1x4flvo{width:26px;height:26px;color:var(--cfg-text-muted);background:var(--cfg-surface-2);border:1px solid var(--cfg-border-strong);border-radius:var(--cfg-radius-s);cursor:pointer;flex-shrink:0;margin-left:auto;padding:0;font-size:13px;line-height:1;display:none}.preview__close.svelte-1x4flvo:hover{color:var(--cfg-text);border-color:var(--cfg-accent-strong)}@media (max-width:1100px){.preview__close.svelte-1x4flvo{place-items:center;min-width:44px;min-height:44px;display:inline-grid}.preview__hint.svelte-1x4flvo{display:none}.preview__bar.svelte-1x4flvo{flex-wrap:wrap;gap:8px}}@media (max-width:430px){.preview__vp-text.svelte-1x4flvo{display:none}.preview__vp-btn.svelte-1x4flvo{padding-inline:7px}}.pv.svelte-1x4flvo{font-family:var(--sf-font-body,system-ui, sans-serif);gap:var(--sf-space-l,24px);flex-direction:column;padding:clamp(16px,3vw,32px);display:flex}.pv__block.svelte-1x4flvo{flex-direction:column;gap:8px;margin:0;display:flex}.pv__eyebrow.svelte-1x4flvo{letter-spacing:.08em;text-transform:uppercase;color:var(--sf-color-text--muted,#888);margin:0;font-size:10px;font-weight:700}.pv__h.svelte-1x4flvo{font-family:var(--sf-font-heading,inherit);font-size:var(--sf-text-2xl,2rem);line-height:var(--sf-leading-tight,1.15);color:var(--sf-color-heading,inherit);margin:0}.pv__p.svelte-1x4flvo{font-size:var(--sf-text-m,1rem);max-width:60ch;color:var(--sf-color-text--secondary,inherit);margin:0}.pv__muted.svelte-1x4flvo{font-size:var(--sf-text-s,.85rem);color:var(--sf-color-text--muted,inherit);margin:0}.pv__display.svelte-1x4flvo{font-family:var(--sf-font-display,var(--sf-font-heading,inherit));font-weight:var(--sf-font-weight-display,800);color:var(--sf-color-heading,inherit);overflow-wrap:anywhere;max-width:100%;margin:0;line-height:1.05}.pv__display--l.svelte-1x4flvo{font-size:var(--sf-text-display-l,3rem);line-height:var(--sf-display-l-line-height,1.05)}.pv__display--m.svelte-1x4flvo{font-size:var(--sf-text-display-m,2.4rem);line-height:var(--sf-display-m-line-height,1.1)}.pv__display--s.svelte-1x4flvo{font-size:var(--sf-text-display-s,1.9rem);line-height:var(--sf-display-s-line-height,1.15)}.pv__scale.svelte-1x4flvo{flex-direction:column;gap:6px;display:flex}.pv__scale-row.svelte-1x4flvo{align-items:baseline;gap:10px;display:flex}.pv__scale-sample.svelte-1x4flvo{font-family:var(--sf-font-heading,inherit);color:var(--sf-color-text,inherit);min-width:2.2em;line-height:1.1}.pv__scale-row.svelte-1x4flvo code:where(.svelte-1x4flvo){font-family:var(--sf-font-mono,monospace);color:var(--sf-color-text--muted,inherit);font-size:11px}.pv__a.svelte-1x4flvo{color:var(--sf-color-link,#4f8cff)}.pv__code.svelte-1x4flvo{font-family:var(--sf-font-mono,monospace);background:var(--sf-color-inset,#7f7f7f26);border-radius:var(--sf-radius-s,4px);color:var(--sf-color-code,inherit);padding:.1em .4em}.pv__surfaces.svelte-1x4flvo{gap:var(--sf-space-s,8px);grid-template-columns:repeat(4,1fr);display:grid}.pv__surface.svelte-1x4flvo{border:1px solid var(--sf-color-border,#7f7f7f4d);border-radius:var(--sf-radius-s,4px);min-height:54px;box-shadow:var(--sf-shadow-s,0 1px 3px #0000001a);color:var(--sf-color-text--secondary,inherit);align-items:flex-end;padding:6px 8px;font-size:11px;font-weight:600;display:flex}.pv__btns.svelte-1x4flvo{gap:var(--sf-space-s,8px);flex-wrap:wrap;display:flex}.pv__btn.svelte-1x4flvo{border-radius:var(--sf-radius-m,8px);font-weight:600;font-size:var(--sf-text-s,.9rem);cursor:default;border:1px solid #0000;padding:.5em 1.1em;transition:filter .12s}.pv__btn.svelte-1x4flvo:hover{filter:brightness(1.05)}.pv__btn--primary.svelte-1x4flvo{background:var(--sf-color-primary,#4f8cff);color:var(--sf-color-text--on-primary,#fff)}.pv__btn--secondary.svelte-1x4flvo{background:var(--sf-color-secondary,#6b7280);color:var(--sf-color-text--on-secondary,#fff)}.pv__btn--action.svelte-1x4flvo{background:var(--sf-color-action,#0891b2);color:var(--sf-color-text--on-action,#fff)}.pv__btn--outline.svelte-1x4flvo{border-color:var(--sf-color-primary,currentColor);color:var(--sf-color-primary,inherit);background:0 0}.pv__btn--ghost.svelte-1x4flvo{border-color:var(--sf-color-border,currentColor);color:inherit;background:0 0}.pv__btn--sm.svelte-1x4flvo{font-size:var(--sf-text-xs,.8rem);padding:.35em .9em}.pv__btn--push.svelte-1x4flvo{margin-inline-start:auto}.pv__swatches.svelte-1x4flvo{grid-template-columns:repeat(auto-fit,minmax(80px,1fr));gap:6px;display:grid}.pv__sw.svelte-1x4flvo{aspect-ratio:3/2;border-radius:var(--sf-radius-m,8px);border:1px solid var(--sf-color-border,#7f7f7f4d);text-transform:capitalize;align-items:flex-end;padding:6px 8px;font-size:12px;display:flex}.pv__alerts.svelte-1x4flvo{flex-direction:column;gap:6px;display:flex}.pv__alert.svelte-1x4flvo{border-radius:var(--sf-radius-s,4px);font-size:var(--sf-text-s,.85rem);color:var(--sf-color-text,inherit);border-inline-start:3px solid;align-items:center;gap:10px;padding:8px 10px;display:flex}.pv__alert-text.svelte-1x4flvo{color:var(--sf-color-text,inherit)}.pv__badge.svelte-1x4flvo{border-radius:var(--sf-radius-full,999px);text-transform:capitalize;white-space:nowrap;align-items:center;padding:2px 8px;font-size:10px;font-weight:700;display:inline-flex}.pv__badge--push.svelte-1x4flvo{margin-inline-start:auto}.pv__card.svelte-1x4flvo{background:var(--sf-color-surface,#7f7f7f0f);border:1px solid var(--sf-color-border,#7f7f7f4d);border-radius:var(--sf-radius-m,8px);box-shadow:var(--sf-shadow-m,0 2px 8px #0000001f);overflow:hidden}.pv__card-accent.svelte-1x4flvo{background:var(--sf-color-primary,#4f8cff);height:4px}.pv__card-body.svelte-1x4flvo{padding:var(--sf-space-m,16px);flex-direction:column;gap:10px;display:flex}.pv__card-top.svelte-1x4flvo{align-items:center;gap:10px;display:flex}.pv__avatar.svelte-1x4flvo{border-radius:var(--sf-radius-full,50%);flex-shrink:0;justify-content:center;align-items:center;width:36px;height:36px;font-weight:700;display:flex}.pv__card-title.svelte-1x4flvo{font-family:var(--sf-font-heading,inherit);font-size:var(--sf-text-m,1rem);color:var(--sf-color-heading,inherit);margin:0;font-weight:600;line-height:1.3}.pv__card-sub.svelte-1x4flvo{font-size:var(--sf-text-xs,.8rem);color:var(--sf-color-text--muted,inherit);margin:0;line-height:1.3}.pv__card-text.svelte-1x4flvo{font-size:var(--sf-text-s,.9rem);color:var(--sf-color-text--secondary,inherit);margin:0}.pv__card-footer.svelte-1x4flvo{border-top:1px solid var(--sf-color-border,#7f7f7f33);flex-wrap:wrap;align-items:center;gap:6px;padding-top:8px;display:flex}.pv__field.svelte-1x4flvo{flex-direction:column;gap:5px;max-width:320px;display:flex}.pv__field-label.svelte-1x4flvo{font-size:var(--sf-text-xs,.8rem);color:var(--sf-color-text--secondary,inherit);font-weight:600}.pv__field-input.svelte-1x4flvo{font-size:var(--sf-text-s,.9rem);border-radius:var(--sf-radius-s,4px);border:1px solid var(--sf-color-border,#7f7f7f66);background:var(--sf-color-bg,#fff);color:var(--sf-color-text,inherit);padding:7px 10px}.pv__space.svelte-1x4flvo{flex-direction:column;gap:4px;display:flex}.pv__space-row.svelte-1x4flvo{align-items:center;gap:10px;font-size:12px;display:flex;overflow:hidden}.pv__space-row.svelte-1x4flvo code:where(.svelte-1x4flvo){font-family:var(--sf-font-mono,monospace);min-width:13ch;color:var(--sf-color-text--muted,inherit);flex-shrink:0}.pv__space-bar.svelte-1x4flvo{background:var(--sf-color-action,#4f8cff);border-radius:3px;flex-shrink:1;block-size:12px;max-inline-size:100%}.pv__radii.svelte-1x4flvo{flex-wrap:wrap;gap:12px;display:flex}.pv__radii-item.svelte-1x4flvo{font-family:var(--sf-font-mono,monospace);color:var(--sf-color-text--muted,inherit);flex-direction:column;align-items:center;gap:4px;font-size:11px;display:flex}.pv__radii-box.svelte-1x4flvo{background:var(--sf-color-primary,#4f8cff);width:56px;height:56px;display:block}.pv__shadows.svelte-1x4flvo{grid-template-columns:repeat(auto-fit,minmax(80px,1fr));gap:14px;padding:8px 6px;display:grid}.pv__shadow-item.svelte-1x4flvo{aspect-ratio:1;background:var(--sf-color-surface,#fff);border-radius:var(--sf-radius-m,8px);color:var(--sf-color-text--muted,inherit);font-family:var(--sf-font-mono,monospace);place-items:center;font-size:11px;display:grid}.pv__gradients.svelte-1x4flvo{grid-template-columns:repeat(auto-fit,minmax(80px,1fr));gap:6px;display:grid}.pv__grad.svelte-1x4flvo{aspect-ratio:2;border-radius:var(--sf-radius-m,8px);border:1px solid var(--sf-color-border,#7f7f7f4d);align-items:flex-end;padding:6px 8px;display:flex}.pv__grad-label.svelte-1x4flvo{text-transform:capitalize;color:#fff;text-shadow:0 1px 3px #00000080;font-size:12px;font-weight:600}.pv__btn--focused.svelte-1x4flvo{outline:var(--sf-focus-ring-width,2px) solid var(--sf-focus-ring-color,var(--sf-color-primary,#4f8cff));outline-offset:var(--sf-focus-ring-offset,2px)}.pv__tabs.svelte-1x4flvo{border-bottom:1px solid var(--sf-color-border,#7f7f7f4d);flex-wrap:wrap;display:flex}.pv__tab.svelte-1x4flvo{border:none;font-size:var(--sf-text-s,.875rem);color:var(--sf-color-text--muted,#888);cursor:default;background:0 0;border-bottom:2px solid #0000;margin-bottom:-1px;padding:7px 14px;font-weight:500}.pv__tab--active.svelte-1x4flvo{color:var(--sf-color-primary,#4f8cff);border-bottom-color:var(--sf-color-primary,#4f8cff);font-weight:600}.pv__breadcrumb.svelte-1x4flvo{font-size:var(--sf-text-s,.875rem);flex-wrap:wrap;align-items:center;gap:4px;display:flex}.pv__crumb.svelte-1x4flvo{text-decoration:none}.pv__crumb[aria-current=page].svelte-1x4flvo{color:var(--sf-color-text,inherit);font-weight:500}.pv__crumb-sep.svelte-1x4flvo{color:var(--sf-color-text--muted,#888)}.pv__form-row.svelte-1x4flvo{grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;display:grid}.pv__field-label--valid.svelte-1x4flvo{color:var(--sf-color-success,#16a34a)}.pv__field-label--error.svelte-1x4flvo{color:var(--sf-color-error,#dc2626)}.pv__field-label--disabled.svelte-1x4flvo{color:var(--sf-color-text--muted,#888)}.pv__field-input--valid.svelte-1x4flvo{border-color:var(--sf-color-success,#16a34a);background:var(--sf-color-success-subtle,#16a34a14)}.pv__field-input--error.svelte-1x4flvo{border-color:var(--sf-color-error,#dc2626);background:var(--sf-color-error-subtle,#dc262614)}.pv__field-input--disabled.svelte-1x4flvo{opacity:.5;cursor:not-allowed;background:var(--sf-color-inset,#7f7f7f1a)}.pv__field-hint.svelte-1x4flvo{font-size:var(--sf-text-xs,.75rem);margin-top:-2px}.pv__field-hint--valid.svelte-1x4flvo{color:var(--sf-color-success,#16a34a)}.pv__field-hint--error.svelte-1x4flvo{color:var(--sf-color-error,#dc2626)}.pv__motion-demos.svelte-1x4flvo{gap:var(--sf-space-l,24px);flex-wrap:wrap;padding:4px 0;display:flex}.pv__motion-cell.svelte-1x4flvo{flex-direction:column;align-items:center;gap:8px;display:flex}.pv__anim-label.svelte-1x4flvo{font-family:var(--sf-font-mono,monospace);color:var(--sf-color-text--muted,#888);white-space:nowrap;font-size:10px}.pv__anim.svelte-1x4flvo{border-radius:var(--sf-radius-full,999px);width:28px;height:28px;display:block}@keyframes svelte-1x4flvo-pv-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.8)}}@keyframes svelte-1x4flvo-pv-spin{to{transform:rotate(360deg)}}@keyframes svelte-1x4flvo-pv-bounce{0%,to{transform:translateY(0)}50%{transform:translateY(-10px)}}@keyframes svelte-1x4flvo-pv-slide{0%{opacity:.25;transform:translate(-10px)}50%{opacity:1;transform:translate(0)}to{opacity:.25;transform:translate(10px)}}@keyframes svelte-1x4flvo-pv-sweep{0%{transform-origin:0;transform:scaleX(0)}50%{transform-origin:0;transform:scaleX(1)}51%{transform-origin:100%;transform:scaleX(1)}to{transform-origin:100%;transform:scaleX(0)}}.pv__anim--pulse.svelte-1x4flvo{animation:svelte-1x4flvo-pv-pulse var(--sf-duration-slow,.9s) var(--sf-ease-in-out,ease-in-out) infinite}.pv__anim--spin.svelte-1x4flvo{border-radius:var(--sf-radius-full,999px);animation:svelte-1x4flvo-pv-spin var(--sf-duration-slow,.7s) linear infinite;border:3px solid}.pv__anim--bounce.svelte-1x4flvo{border-radius:var(--sf-radius-m,8px);animation:svelte-1x4flvo-pv-bounce var(--sf-duration-slow,.7s) var(--sf-ease-in-out,ease-in-out) infinite}.pv__anim--slide.svelte-1x4flvo{border-radius:var(--sf-radius-m,8px);animation:svelte-1x4flvo-pv-slide calc(var(--sf-duration-slow,.7s) * 1.5) var(--sf-ease-in-out,ease-in-out) infinite}.pv__durations.svelte-1x4flvo{flex-direction:column;gap:5px;margin-top:4px;display:flex}.pv__dur-row.svelte-1x4flvo{align-items:center;gap:10px;display:flex;overflow:hidden}.pv__dur-label.svelte-1x4flvo{font-family:var(--sf-font-mono,monospace);color:var(--sf-color-text--muted,#888);flex-shrink:0;min-width:16ch;font-size:11px}.pv__dur-track.svelte-1x4flvo{background:var(--sf-color-inset,#7f7f7f1f);border-radius:var(--sf-radius-full,999px);flex:1;height:10px;position:relative;overflow:hidden}.pv__dur-bar.svelte-1x4flvo{background:var(--sf-color-primary,#4f8cff);border-radius:inherit;height:100%;animation:svelte-1x4flvo-pv-sweep var(--sf-duration-normal,.25s) linear infinite;display:block}.wcag-probe.svelte-1qru490{visibility:hidden;pointer-events:none;width:0;height:0;position:absolute;overflow:hidden}.wcag.svelte-1qru490{flex-direction:column;gap:16px;padding:18px;display:flex;overflow-y:auto}.wcag__title.svelte-1qru490{margin:0;font-size:18px}.wcag__lead.svelte-1qru490{color:var(--cfg-text-muted);max-width:70ch;margin:4px 0 0;font-size:13px}.card.svelte-1qru490{background:var(--cfg-surface);border:1px solid var(--cfg-border);border-radius:var(--cfg-radius);padding:16px}.card__h.svelte-1qru490{margin:0 0 4px;font-size:14px}.card__lead.svelte-1qru490{color:var(--cfg-text-muted);max-width:70ch;margin:0 0 12px;font-size:13px}.checker.svelte-1qru490{grid-template-columns:1fr auto;align-items:stretch;gap:16px;display:grid}.checker__controls.svelte-1qru490{align-items:flex-end;gap:10px;display:flex}.checker__field.svelte-1qru490{flex-direction:column;flex:1;gap:5px;min-width:0;display:flex}.checker__field.svelte-1qru490 span:where(.svelte-1qru490){color:var(--cfg-text-muted);font-size:12px}.checker__field.svelte-1qru490 select:where(.svelte-1qru490){background:var(--cfg-bg);width:100%;color:var(--cfg-text);border:1px solid var(--cfg-border-strong);border-radius:var(--cfg-radius-s);font-family:var(--cfg-mono);padding:7px 9px;font-size:12px}.checker__swap.svelte-1qru490{align-self:flex-end;padding:6px 9px;font-size:16px}.checker__result.svelte-1qru490{border:1px solid var(--cfg-border-strong);border-radius:var(--cfg-radius);flex-direction:column;justify-content:center;align-items:center;gap:8px;min-width:190px;padding:16px;display:flex}.checker__sample.svelte-1qru490{font-size:44px;font-weight:700;line-height:1}.checker__ratio.svelte-1qru490{color:#111;border-radius:var(--cfg-radius-s);background:#ffffffd9;padding:2px 10px;font-size:20px;font-weight:700}.checker__badges.svelte-1qru490{flex-direction:column;gap:4px;width:100%;display:flex}.badge-row.svelte-1qru490{border-radius:var(--cfg-radius-s);color:#333;background:#ffffffd9;justify-content:space-between;gap:10px;padding:3px 9px;font-size:11px;display:flex}.checker__empty.svelte-1qru490{color:var(--cfg-text-muted);text-align:center;font-size:13px}.badge.svelte-1qru490{white-space:nowrap;border-radius:3px;padding:1px 7px;font-size:11px;font-weight:700}.badge--aaa.svelte-1qru490{color:#fff;background:#2b8a3e}.badge--aa.svelte-1qru490{color:#fff;background:#1971c2}.badge--aa-large.svelte-1qru490{color:#1a1a1a;background:#e8a317}.badge--fail.svelte-1qru490{color:#fff;background:#c92a2a}.badge--neutral.svelte-1qru490{background:var(--cfg-surface-2);color:var(--cfg-text-muted);border:1px solid var(--cfg-border-strong)}.matrix-wrap.svelte-1qru490{overflow-x:auto}.matrix.svelte-1qru490{border-collapse:collapse;font-size:12px}.matrix.svelte-1qru490 th:where(.svelte-1qru490){color:var(--cfg-text-muted);padding:6px;font-weight:500}.matrix.svelte-1qru490 thead:where(.svelte-1qru490) th:where(.svelte-1qru490){text-align:center}.matrix__sw.svelte-1qru490{border:1px solid var(--cfg-border-strong);border-radius:4px;width:22px;height:22px;margin:0 auto 3px;display:block}.matrix__lbl.svelte-1qru490{font-size:10px;font-family:var(--cfg-mono)}.matrix__row-h.svelte-1qru490{text-align:right;font-family:var(--cfg-mono);white-space:nowrap;padding-right:10px;font-size:11px}.matrix__cell.svelte-1qru490{text-align:center;color:#1a1a1a;border:1px solid var(--cfg-border);cursor:pointer;width:58px;height:40px;font-size:11px;font-weight:700}.matrix__cell--AAA.svelte-1qru490{background:#b6f0c4}.matrix__cell--AA.svelte-1qru490{background:#b8dcf7}.matrix__cell--AA-large.svelte-1qru490{background:#fbe7a8}.matrix__cell--fail.svelte-1qru490{background:#f5c2c2}.matrix__cell--na.svelte-1qru490{background:var(--cfg-surface-2);color:var(--cfg-text-faint);cursor:default}.matrix__cell--active.svelte-1qru490{outline:2px solid var(--cfg-text);outline-offset:-2px}.matrix__cell.svelte-1qru490:hover:not(.matrix__cell--na){filter:brightness(.95)}.legend.svelte-1qru490{color:var(--cfg-text-muted);flex-wrap:wrap;gap:16px;margin-top:10px;font-size:12px;display:flex}.legend.svelte-1qru490 span:where(.svelte-1qru490){align-items:center;gap:6px;display:flex}.dot.svelte-1qru490{border-radius:3px;width:12px;height:12px;display:inline-block}.dot--aaa.svelte-1qru490{background:#b6f0c4}.dot--aa.svelte-1qru490{background:#b8dcf7}.dot--aa-large.svelte-1qru490{background:#fbe7a8}.dot--fail.svelte-1qru490{background:#f5c2c2}.usage.svelte-1qru490{grid-template-columns:repeat(auto-fill,minmax(130px,1fr));gap:8px;display:grid}.usage__chip.svelte-1qru490{border-radius:var(--cfg-radius-s);border:1px solid var(--cfg-border);align-items:center;gap:8px;min-height:52px;padding:12px;display:flex}.usage__aa.svelte-1qru490{font-size:20px;font-weight:700;line-height:1}.usage__role.svelte-1qru490{text-transform:capitalize;opacity:.92;flex:1;font-size:12px}.opt__actions.svelte-1qru490{flex-wrap:wrap;align-items:center;gap:12px;display:flex}.opt__msg.svelte-1qru490{color:var(--cfg-ok);font-size:13px;font-weight:500}.opt__locks.svelte-1qru490{flex-wrap:wrap;gap:8px;margin:0 0 14px;display:flex}.opt__lock.svelte-1qru490{background:var(--cfg-bg);border:1px solid var(--cfg-border-strong);border-radius:var(--cfg-radius-s);color:var(--cfg-text-muted);text-transform:capitalize;cursor:pointer;align-items:center;gap:7px;padding:6px 10px;font-size:12px;transition:border-color .12s,color .12s,background .12s;display:inline-flex}.opt__lock.svelte-1qru490:hover{color:var(--cfg-text)}.opt__lock--on.svelte-1qru490{border-color:var(--cfg-accent-strong);color:var(--cfg-text);background:var(--cfg-surface-2);font-weight:600}.opt__lock-ico.svelte-1qru490{font-size:13px;line-height:1}.opt__lock-sw.svelte-1qru490{border:1px solid var(--cfg-border-strong);border-radius:4px;width:16px;height:16px}.opt__locked-tag.svelte-1qru490{font-size:11px}.opt__results.svelte-1qru490{border:1px solid var(--cfg-border);border-radius:var(--cfg-radius);margin-top:14px;overflow:hidden}.opt__row.svelte-1qru490{border-bottom:1px solid var(--cfg-border);align-items:center;gap:12px;padding:10px 14px;display:flex}.opt__row.svelte-1qru490:last-child{border-bottom:none}.opt__row--warn.svelte-1qru490{opacity:.75}.opt__sw.svelte-1qru490{border-radius:var(--cfg-radius-s);border:1px solid var(--cfg-border-strong);flex-shrink:0;width:30px;height:30px}.opt__role.svelte-1qru490{text-transform:capitalize;min-width:70px;font-weight:600}.opt__val.svelte-1qru490{font-family:var(--cfg-mono);background:var(--cfg-bg);color:var(--cfg-text-muted);text-overflow:ellipsis;white-space:nowrap;border-radius:3px;flex:1;padding:2px 6px;font-size:11px;overflow:hidden}.opt__val--locked.svelte-1qru490{color:var(--cfg-text-faint);font-style:italic}.opt__none.svelte-1qru490{color:var(--cfg-text-faint);font-size:12px}.opt__apply.svelte-1qru490{background:var(--cfg-surface-2);gap:8px;padding:12px 14px;display:flex}.themes.svelte-1qe946z{flex-direction:column;height:100%;min-height:0;display:flex;overflow:hidden}.themes__head.svelte-1qe946z{border-bottom:1px solid var(--cfg-border);background:var(--cfg-surface);padding:18px 20px 14px}.themes__title-wrap.svelte-1qe946z{align-items:flex-start;gap:12px;display:flex}.themes__icon.svelte-1qe946z{border-radius:var(--cfg-radius);border:1px solid var(--cfg-border-strong);background:linear-gradient(135deg,#4f8cff2e,#7850dc2e);place-items:center;width:36px;height:36px;font-size:18px;display:inline-grid}.themes__title.svelte-1qe946z{margin:0;font-size:18px;font-weight:600}.themes__blurb.svelte-1qe946z{color:var(--cfg-text-muted);max-width:70ch;margin:3px 0 0;font-size:13px}.themes__body.svelte-1qe946z{flex-direction:column;gap:22px;padding:16px 20px 80px;display:flex;overflow-y:auto}.themes__group.svelte-1qe946z{text-transform:uppercase;letter-spacing:.06em;color:var(--cfg-text);margin:0 0 10px;font-size:12.5px;font-weight:700}.themes__grid.svelte-1qe946z{grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px;display:grid}.theme.svelte-1qe946z{flex-direction:column;gap:8px;padding:14px;display:flex}.theme__head.svelte-1qe946z{align-items:center;gap:8px;display:flex}.theme__icon.svelte-1qe946z{font-size:18px}.theme__name.svelte-1qe946z{flex:1;margin:0;font-size:14px;font-weight:600}.theme__size.svelte-1qe946z{font-family:var(--cfg-mono);color:var(--cfg-accent);background:var(--cfg-accent-soft);border-radius:999px;padding:1px 8px;font-size:10.5px;font-weight:700}.theme__size--zero.svelte-1qe946z{color:var(--cfg-text-faint);background:var(--cfg-surface-2)}.theme__blurb.svelte-1qe946z{color:var(--cfg-text-muted);flex:1;margin:0;font-size:12.5px;line-height:1.5}.theme__apply.svelte-1qe946z{align-self:stretch;margin-top:4px}.theme__actions.svelte-1qe946z{gap:8px;margin-top:4px;display:flex}.theme__actions.svelte-1qe946z .cfg-btn:where(.svelte-1qe946z){flex:1}.themes__save.svelte-1qe946z{flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:12px;display:flex}.themes__save-name.svelte-1qe946z{flex:1;min-width:180px}.themes__save-meta.svelte-1qe946z{color:var(--cfg-text-faint);font-size:11.5px}.themes__msg.svelte-1qe946z{color:var(--cfg-text-muted);margin:0 0 12px;font-size:12.5px}.themes__msg--err.svelte-1qe946z{color:var(--cfg-warn)}.themes__msg.svelte-1qe946z code:where(.svelte-1qe946z){color:var(--cfg-text)}.themes__empty.svelte-1qe946z{text-align:center;color:var(--cfg-text-faint);border:1px dashed var(--cfg-border);border-radius:var(--cfg-radius);margin:0;padding:20px;font-size:13px}.cs.svelte-zu66pa{flex-direction:column;height:100%;min-height:0;display:flex;overflow:hidden}.cs__toolbar.svelte-zu66pa{border-bottom:1px solid var(--cfg-border);background:var(--cfg-surface);flex-wrap:wrap;align-items:center;gap:10px;padding:12px 16px;display:flex}.cs__search.svelte-zu66pa{flex:240px;min-width:180px}.cs__filters.svelte-zu66pa{flex-wrap:wrap;gap:8px;display:flex}.cs__select.svelte-zu66pa{padding:4px 8px;font-size:12px}.cs__count.svelte-zu66pa{color:var(--cfg-text-faint);font-size:11.5px;font-family:var(--cfg-mono);white-space:nowrap;margin-left:auto}.cs__table-wrap.svelte-zu66pa{flex:1;min-height:0;overflow:auto}.cs__table.svelte-zu66pa{border-collapse:collapse;width:100%;font-size:12px}.cs__th.svelte-zu66pa{background:var(--cfg-surface-2);border-bottom:1px solid var(--cfg-border-strong);text-align:left;text-transform:uppercase;letter-spacing:.06em;color:var(--cfg-text-muted);white-space:nowrap;z-index:1;padding:8px 10px;font-size:10.5px;font-weight:700;position:sticky;top:0}.cs__row.svelte-zu66pa{border-bottom:1px solid var(--cfg-border);transition:background .1s}.cs__row.svelte-zu66pa:hover{background:#ffffff06}.cs__td.svelte-zu66pa{vertical-align:top;padding:7px 10px}.cs__th--name.svelte-zu66pa,.cs__td--name.svelte-zu66pa{width:280px;min-width:200px}.cs__th--role.svelte-zu66pa,.cs__td--role.svelte-zu66pa{white-space:nowrap;width:110px}.cs__th--tier.svelte-zu66pa,.cs__td--tier.svelte-zu66pa{white-space:nowrap;width:90px}.cs__th--ns.svelte-zu66pa,.cs__td--ns.svelte-zu66pa{width:90px}.cs__th--val.svelte-zu66pa,.cs__td--val.svelte-zu66pa{width:220px;max-width:300px}.cs__th--desc.svelte-zu66pa,.cs__td--desc.svelte-zu66pa{min-width:200px}.cs__copy-btn.svelte-zu66pa{border-radius:var(--cfg-radius-s);color:var(--cfg-text);cursor:pointer;font-size:inherit;text-align:left;background:0 0;border:1px solid #0000;align-items:center;gap:4px;max-width:100%;padding:1px 4px;transition:background .1s,border-color .1s;display:inline-flex}.cs__copy-btn.svelte-zu66pa:hover{background:var(--cfg-surface-2);border-color:var(--cfg-border)}.cs__copy-btn.svelte-zu66pa:focus-visible{outline:2px solid var(--cfg-accent);outline-offset:1px}.cs__name.svelte-zu66pa{font-family:var(--cfg-mono);word-break:break-all;font-size:11.5px}.cs__copy-icon.svelte-zu66pa{color:var(--cfg-text-faint);opacity:0;flex-shrink:0;font-size:10px}.cs__copy-btn.svelte-zu66pa:hover .cs__copy-icon:where(.svelte-zu66pa){opacity:1}.cs__alias.svelte-zu66pa{color:var(--cfg-text-faint);font-size:10.5px;font-family:var(--cfg-mono);margin-top:2px;display:block}.cs__val.svelte-zu66pa{font-family:var(--cfg-mono);color:var(--cfg-text-muted);-webkit-line-clamp:2;line-clamp:2;word-break:break-all;-webkit-box-orient:vertical;font-size:11px;display:-webkit-box;overflow:hidden}.cs__ns.svelte-zu66pa{font-family:var(--cfg-mono);color:var(--cfg-text-muted);font-size:11px}.cs__note.svelte-zu66pa{color:var(--cfg-text);font-size:11.5px;line-height:1.5}.cs__desc.svelte-zu66pa{color:var(--cfg-text-faint);font-size:11.5px;line-height:1.5}.cs__group.svelte-zu66pa{color:var(--cfg-text-faint);vertical-align:middle;opacity:.6;margin-left:4px;font-size:10px;display:inline-block}.cs-badge.svelte-zu66pa{text-transform:uppercase;letter-spacing:.05em;white-space:nowrap;border-radius:999px;padding:1px 7px;font-size:9.5px;font-weight:700;line-height:1.6;display:inline-block}.cs-badge--public.svelte-zu66pa{color:#6fbf7e;background:#6fbf7e1f}.cs-badge--advanced.svelte-zu66pa{color:#f0a050;background:#f0a0501f}.cs-badge--internal.svelte-zu66pa{color:var(--cfg-text-faint);background:var(--cfg-surface-2)}.cs-badge--knob.svelte-zu66pa{color:var(--cfg-accent);background:var(--cfg-accent-soft)}.cs-badge--consumption.svelte-zu66pa{color:var(--cfg-text-faint);background:var(--cfg-surface-3)}.cs-badge--opt.svelte-zu66pa{color:var(--cfg-text-faint);border:1px solid var(--cfg-border);padding:0 5px}.cs__empty.svelte-zu66pa{text-align:center;color:var(--cfg-text-faint);padding:40px 24px;font-size:13px}.cs__pager.svelte-zu66pa{border-top:1px solid var(--cfg-border);background:var(--cfg-surface);flex-shrink:0;justify-content:center;align-items:center;gap:6px;padding:10px 16px;display:flex}.cs__pager-info.svelte-zu66pa{color:var(--cfg-text-muted);font-size:12px;font-family:var(--cfg-mono);text-align:center;min-width:120px}.cs__pager-range.svelte-zu66pa{color:var(--cfg-text-faint);font-size:11px}@media (max-width:900px){.cs__th--val.svelte-zu66pa,.cs__td--val.svelte-zu66pa,.cs__th--desc.svelte-zu66pa,.cs__td--desc.svelte-zu66pa{display:none}}@media (max-width:600px){.cs__th--ns.svelte-zu66pa,.cs__td--ns.svelte-zu66pa{display:none}.cs__toolbar.svelte-zu66pa{gap:8px}.cs__filters.svelte-zu66pa{flex-direction:column;width:100%}.cs__select.svelte-zu66pa{width:100%}}.home.svelte-1ary22t{flex-direction:column;gap:20px;height:100%;padding:28px 24px 80px;display:flex;overflow-y:auto}.home__head.svelte-1ary22t{max-width:72ch}.home__title.svelte-1ary22t{margin:0 0 6px;font-size:20px;font-weight:700}.home__lead.svelte-1ary22t{color:var(--cfg-text-muted);margin:0;font-size:13.5px;line-height:1.6}.home__export.svelte-1ary22t{color:#fff;background:var(--cfg-accent-strong);border-radius:var(--cfg-radius-s);cursor:pointer;border:0;margin-top:14px;padding:8px 16px;font-size:12.5px;font-weight:600}.home__export.svelte-1ary22t:hover{filter:brightness(1.1)}.home__list.svelte-1ary22t{flex-direction:column;gap:10px;max-width:760px;margin:0;padding:0;list-style:none;display:flex}.home__row.svelte-1ary22t{text-align:left;background:var(--cfg-surface);border:1px solid var(--cfg-border);border-radius:var(--cfg-radius);cursor:pointer;grid-template-columns:44px minmax(0,1fr) auto;align-items:center;gap:14px;width:100%;padding:14px 16px;transition:border-color .12s,background .12s,transform .12s;display:grid}.home__row.svelte-1ary22t:hover{background:var(--cfg-surface-2);border-color:var(--cfg-accent-strong);transform:translate(2px)}.home__icon.svelte-1ary22t{border-radius:var(--cfg-radius);border:1px solid var(--cfg-border-strong);background:linear-gradient(135deg,#4f8cff29,#7850dc29);place-items:center;width:44px;height:44px;font-size:20px;display:inline-grid}.home__body.svelte-1ary22t{flex-direction:column;gap:3px;min-width:0;display:flex}.home__name.svelte-1ary22t{color:var(--cfg-text);font-size:14.5px;font-weight:650}.home__blurb.svelte-1ary22t{color:var(--cfg-text-muted);-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;font-size:12px;line-height:1.5;display:-webkit-box;overflow:hidden}.home__count.svelte-1ary22t{font-family:var(--cfg-mono);color:var(--cfg-text-faint);white-space:nowrap;font-size:11px}.home__count--mod.svelte-1ary22t{color:#fff;background:var(--cfg-accent-strong);border-radius:999px;padding:2px 9px;font-weight:700}.home__count--start.svelte-1ary22t{color:var(--cfg-accent-strong);font-weight:700}@media (max-width:600px){.home.svelte-1ary22t{padding:16px 12px 60px}.home__row.svelte-1ary22t{grid-template-columns:36px minmax(0,1fr) auto;gap:10px;padding:12px}.home__icon.svelte-1ary22t{width:36px;height:36px;font-size:16px}}.version-tab.svelte-cxst8t{flex-direction:column;gap:1rem;max-width:640px;padding:1.5rem;display:flex}.version-tab__header.svelte-cxst8t{flex-wrap:wrap;align-items:baseline;gap:1rem;display:flex}.version-tab__header.svelte-cxst8t h2:where(.svelte-cxst8t){color:var(--cfg-text,#111);margin:0;font-size:1rem;font-weight:600}.version-tab__current.svelte-cxst8t{color:var(--cfg-text-muted,#666);font-size:.85rem}.version-tab__loading.svelte-cxst8t,.version-tab__empty.svelte-cxst8t{color:var(--cfg-text-muted,#666);font-size:.875rem}.version-tab__error.svelte-cxst8t{color:#bd001b;color:lab(39.7145% 70.0599 49.6254);margin:0;font-size:.875rem}.version-tab__success.svelte-cxst8t{color:#00791d;color:lab(44.0674% -50.9499 46.2923);margin:0;font-size:.875rem}.version-tab__list.svelte-cxst8t{flex-direction:column;gap:.5rem;margin:0;padding:0;list-style:none;display:flex}.version-tab__item.svelte-cxst8t{border:1px solid var(--cfg-border,#ddd);background:var(--cfg-surface,#fafafa);border-radius:8px;justify-content:space-between;align-items:center;gap:1rem;padding:.75rem 1rem;display:flex}.version-tab__item.is-active.svelte-cxst8t{border-color:var(--cfg-accent,#0083e3);background:color-mix(in oklch, var(--cfg-accent,#0083e3) 8%, white)}@supports (color:lab(0% 0 0)){.version-tab__item.is-active.svelte-cxst8t{border-color:var(--cfg-accent,lab(52.5446% -2.04957 -60.1708));background:color-mix(in oklch, var(--cfg-accent,lab(52.5446% -2.04957 -60.1708)) 8%, white)}}.version-tab__info.svelte-cxst8t{flex-direction:column;gap:.2rem;display:flex}.version-tag.svelte-cxst8t{color:var(--cfg-text,#111);font-family:ui-monospace,monospace;font-size:.875rem;font-weight:600}.version-date.svelte-cxst8t{color:var(--cfg-text-muted,#666);font-size:.75rem}.version-notes.svelte-cxst8t{color:var(--cfg-text-muted,#666);font-size:.75rem;font-style:italic}.btn.svelte-cxst8t{cursor:pointer;white-space:nowrap;border:1px solid #0000;border-radius:6px;flex-shrink:0;padding:.375rem .875rem;font-size:.8125rem;font-weight:500;transition:background .15s}.btn.svelte-cxst8t:disabled{cursor:not-allowed;opacity:.65}.btn--active.svelte-cxst8t{background:var(--cfg-accent,#0083e3);color:#fff;border-color:var(--cfg-accent,#0083e3)}@supports (color:lab(0% 0 0)){.btn--active.svelte-cxst8t{background:var(--cfg-accent,lab(52.5446% -2.04957 -60.1708));border-color:var(--cfg-accent,lab(52.5446% -2.04957 -60.1708))}}.btn--switch.svelte-cxst8t{color:var(--cfg-text,#111);border-color:var(--cfg-border,#ddd);background:0 0}.btn--switch.svelte-cxst8t:not(:disabled):hover{background:var(--cfg-hover,#f0f0f0)}.version-tab__footer.svelte-cxst8t{border-top:1px solid var(--cfg-border,#eee);margin-top:.5rem;padding-top:1rem}.version-tab__footer.svelte-cxst8t p:where(.svelte-cxst8t){color:var(--cfg-text-muted,#666);margin:0;font-size:.8125rem}.settings-tab.svelte-1102y3w{max-width:600px;padding:1.5rem}.settings-tab__title.svelte-1102y3w{color:var(--cfg-text,#111);margin:0 0 1.5rem;font-size:1rem;font-weight:600}.settings-form.svelte-1102y3w{flex-direction:column;gap:1.5rem;display:flex}.field-group.svelte-1102y3w{border:none;flex-direction:column;gap:.5rem;margin:0;padding:0;display:flex}.field-group__label.svelte-1102y3w{color:var(--cfg-text,#111);font-size:.875rem;font-weight:600}.field-group__hint.svelte-1102y3w,.field__hint.svelte-1102y3w{color:var(--cfg-text-muted,#666);margin:0;font-size:.8125rem}.radio-list.svelte-1102y3w{flex-direction:column;gap:.375rem;display:flex}.radio-item.svelte-1102y3w{cursor:pointer;border:1px solid var(--cfg-border,#ddd);background:var(--cfg-surface,#fafafa);border-radius:6px;grid-template-rows:auto auto;grid-template-columns:auto 1fr;align-items:start;column-gap:.5rem;padding:.5rem .75rem;display:grid}.radio-item.svelte-1102y3w:has(input:where(.svelte-1102y3w):checked){border-color:var(--cfg-accent,#0083e3);background:color-mix(in oklch, var(--cfg-accent,#0083e3) 6%, white)}@supports (color:lab(0% 0 0)){.radio-item.svelte-1102y3w:has(input:where(.svelte-1102y3w):checked){border-color:var(--cfg-accent,lab(52.5446% -2.04957 -60.1708));background:color-mix(in oklch, var(--cfg-accent,lab(52.5446% -2.04957 -60.1708)) 6%, white)}}.radio-item.svelte-1102y3w input[type=radio]:where(.svelte-1102y3w){grid-row:1/3;margin-top:.2rem}.radio-item__label.svelte-1102y3w{color:var(--cfg-text,#111);font-size:.875rem;font-weight:500}.radio-item__hint.svelte-1102y3w{color:var(--cfg-text-muted,#666);font-size:.75rem}.field.svelte-1102y3w{flex-direction:column;gap:.375rem;display:flex}.field__label.svelte-1102y3w{color:var(--cfg-text,#111);font-size:.875rem;font-weight:600}.field__select.svelte-1102y3w,.field__input.svelte-1102y3w{border:1px solid var(--cfg-border,#ddd);background:var(--cfg-surface,#fafafa);color:var(--cfg-text,#111);border-radius:6px;max-width:320px;padding:.4375rem .625rem;font-size:.875rem}.field__select.svelte-1102y3w:focus,.field__input.svelte-1102y3w:focus{border-color:var(--cfg-accent,#0083e3);box-shadow:0 0 0 2px color-mix(in oklch, var(--cfg-accent,#0083e3) 20%, transparent);outline:none}@supports (color:lab(0% 0 0)){.field__select.svelte-1102y3w:focus,.field__input.svelte-1102y3w:focus{border-color:var(--cfg-accent,lab(52.5446% -2.04957 -60.1708));box-shadow:0 0 0 2px color-mix(in oklch, var(--cfg-accent,lab(52.5446% -2.04957 -60.1708)) 20%, transparent)}}.field--toggle.svelte-1102y3w{gap:.25rem}.toggle.svelte-1102y3w{cursor:pointer;align-items:center;gap:.625rem;display:flex}.toggle.svelte-1102y3w input[type=checkbox]:where(.svelte-1102y3w){clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.toggle__track.svelte-1102y3w{background:var(--cfg-border,#ccc);border-radius:999px;flex-shrink:0;width:2.25rem;height:1.25rem;transition:background .2s;position:relative}.toggle__track.svelte-1102y3w:after{content:"";background:#fff;border-radius:50%;width:1rem;height:1rem;transition:transform .2s;position:absolute;top:.125rem;left:.125rem;box-shadow:0 1px 3px #0003}.toggle.svelte-1102y3w input:where(.svelte-1102y3w):checked~.toggle__track:where(.svelte-1102y3w){background:var(--cfg-accent,#0083e3)}@supports (color:lab(0% 0 0)){.toggle.svelte-1102y3w input:where(.svelte-1102y3w):checked~.toggle__track:where(.svelte-1102y3w){background:var(--cfg-accent,lab(52.5446% -2.04957 -60.1708))}}.toggle.svelte-1102y3w input:where(.svelte-1102y3w):checked~.toggle__track:where(.svelte-1102y3w):after{transform:translate(1rem)}.toggle__label.svelte-1102y3w{color:var(--cfg-text,#111);font-size:.875rem;font-weight:500}.settings-form__actions.svelte-1102y3w{flex-wrap:wrap;align-items:center;gap:.75rem;display:flex}.btn.svelte-1102y3w{cursor:pointer;border:1px solid #0000;border-radius:6px;padding:.5rem 1.25rem;font-size:.875rem;font-weight:500;transition:background .15s,opacity .15s}.btn.svelte-1102y3w:disabled{opacity:.5;cursor:not-allowed}.btn--primary.svelte-1102y3w{background:var(--cfg-accent,#0083e3);color:#fff}@supports (color:lab(0% 0 0)){.btn--primary.svelte-1102y3w{background:var(--cfg-accent,lab(52.5446% -2.04957 -60.1708))}}.btn--primary.svelte-1102y3w:not(:disabled):hover{background:color-mix(in oklch, var(--cfg-accent,#0083e3) 85%, black)}@supports (color:lab(0% 0 0)){.btn--primary.svelte-1102y3w:not(:disabled):hover{background:color-mix(in oklch, var(--cfg-accent,lab(52.5446% -2.04957 -60.1708)) 85%, black)}}.error-msg.svelte-1102y3w{color:#bd001b;color:lab(39.7145% 70.0599 49.6254);font-size:.85rem}.manual-css.svelte-1jjlbc4{box-sizing:border-box;flex-direction:column;gap:1rem;height:100%;padding:1.5rem;display:flex}.manual-css__header.svelte-1jjlbc4{align-items:center;gap:.75rem;display:flex}.manual-css__header.svelte-1jjlbc4 h2:where(.svelte-1jjlbc4){color:var(--cfg-text,#111);margin:0;font-size:1rem;font-weight:600}.badge.svelte-1jjlbc4{background:var(--cfg-accent,#0083e3);color:#fff;border-radius:999px;padding:.125rem .5rem;font-size:.75rem}@supports (color:lab(0% 0 0)){.badge.svelte-1jjlbc4{background:var(--cfg-accent,lab(52.5446% -2.04957 -60.1708))}}.manual-css__hint.svelte-1jjlbc4{color:var(--cfg-text-muted,#666);margin:0;font-size:.85rem}.manual-css__hint.svelte-1jjlbc4 a:where(.svelte-1jjlbc4){color:var(--cfg-accent,#0083e3)}@supports (color:lab(0% 0 0)){.manual-css__hint.svelte-1jjlbc4 a:where(.svelte-1jjlbc4){color:var(--cfg-accent,lab(52.5446% -2.04957 -60.1708))}}.manual-css__editor.svelte-1jjlbc4{flex:1;min-height:0}.manual-css__textarea.svelte-1jjlbc4{border:1px solid var(--cfg-border,#ddd);background:var(--cfg-surface,#fafafa);width:100%;height:100%;min-height:280px;color:var(--cfg-text,#111);resize:vertical;box-sizing:border-box;border-radius:6px;padding:.75rem;font-family:ui-monospace,Cascadia Code,Fira Code,monospace;font-size:.8125rem;line-height:1.6}.manual-css__textarea.svelte-1jjlbc4:focus{border-color:var(--cfg-accent,#0083e3);box-shadow:0 0 0 2px color-mix(in oklch, var(--cfg-accent,#0083e3) 20%, transparent);outline:none}@supports (color:lab(0% 0 0)){.manual-css__textarea.svelte-1jjlbc4:focus{border-color:var(--cfg-accent,lab(52.5446% -2.04957 -60.1708));box-shadow:0 0 0 2px color-mix(in oklch, var(--cfg-accent,lab(52.5446% -2.04957 -60.1708)) 20%, transparent)}}.manual-css__preview-count.svelte-1jjlbc4{color:var(--cfg-text-muted,#666);margin:0;font-size:.8125rem}.manual-css__actions.svelte-1jjlbc4{flex-wrap:wrap;gap:.5rem;display:flex}.btn.svelte-1jjlbc4{cursor:pointer;border:1px solid #0000;border-radius:6px;padding:.5rem 1.25rem;font-size:.875rem;font-weight:500;transition:background .15s,opacity .15s}.btn.svelte-1jjlbc4:disabled{opacity:.5;cursor:not-allowed}.btn--primary.svelte-1jjlbc4{background:var(--cfg-accent,#0083e3);color:#fff}@supports (color:lab(0% 0 0)){.btn--primary.svelte-1jjlbc4{background:var(--cfg-accent,lab(52.5446% -2.04957 -60.1708))}}.btn--primary.svelte-1jjlbc4:not(:disabled):hover{background:color-mix(in oklch, var(--cfg-accent,#0083e3) 85%, black)}@supports (color:lab(0% 0 0)){.btn--primary.svelte-1jjlbc4:not(:disabled):hover{background:color-mix(in oklch, var(--cfg-accent,lab(52.5446% -2.04957 -60.1708)) 85%, black)}}.btn--ghost.svelte-1jjlbc4{color:var(--cfg-text,#111);border-color:var(--cfg-border,#ddd);background:0 0}.btn--ghost.svelte-1jjlbc4:not(:disabled):hover{background:var(--cfg-hover,#f0f0f0)}.manual-css__error.svelte-1jjlbc4{color:#bd001b;color:lab(39.7145% 70.0599 49.6254);margin:0;font-size:.85rem}.shell.svelte-1n46o8q{--shell-sw:240px;--shell-pw:440px;--shell-rs:6px;grid-template-columns:var(--shell-sw) var(--shell-rs) minmax(0, 1fr) var(--shell-rs) var(--shell-pw);grid-template-rows:auto minmax(0,1fr) auto;grid-template-areas:"header header header header header""side rs1 main rs2 preview""output output output output output";height:100vh;display:grid}.shell--no-preview.svelte-1n46o8q{grid-template-columns:var(--shell-sw) var(--shell-rs) minmax(0, 1fr);grid-template-areas:"header header header""side rs1 main""output output output"}.shell--no-sidebar.svelte-1n46o8q{grid-template-columns:60px minmax(0, 1fr) var(--shell-rs) var(--shell-pw);grid-template-areas:"header header header header""side main rs2 preview""output output output output"}.shell--no-sidebar.shell--no-preview.svelte-1n46o8q{grid-template-columns:60px minmax(0,1fr);grid-template-areas:"header header""side main""output output"}.shell--dragging.svelte-1n46o8q,.shell--dragging.svelte-1n46o8q :where(.svelte-1n46o8q){-webkit-user-select:none;user-select:none;cursor:col-resize!important}.main.svelte-1n46o8q{background:var(--cfg-bg);flex-direction:column;grid-area:main;min-width:0;min-height:0;display:flex;overflow:hidden}.resizer.svelte-1n46o8q{cursor:col-resize;z-index:20;touch-action:none;background:0 0;transition:background .1s;position:relative}.resizer--sidebar.svelte-1n46o8q{grid-area:rs1}.resizer--preview.svelte-1n46o8q{grid-area:rs2}.resizer.svelte-1n46o8q:after{content:"";background:var(--cfg-border);pointer-events:none;width:1px;transition:background .1s,width .15s;position:absolute;top:0;bottom:0;left:50%;transform:translate(-50%)}.resizer.svelte-1n46o8q:hover:after,.shell--dragging.svelte-1n46o8q .resizer:where(.svelte-1n46o8q):after{background:var(--cfg-accent-strong);width:3px}.scrim.svelte-1n46o8q{z-index:49;cursor:pointer;background:#00000073;border:0;padding:0;display:none;position:fixed;inset:0}@media (max-width:1100px){.shell.svelte-1n46o8q,.shell--no-preview.svelte-1n46o8q,.shell--no-sidebar.svelte-1n46o8q,.shell--no-sidebar.shell--no-preview.svelte-1n46o8q{grid-template-columns:60px minmax(0,1fr);grid-template-areas:"header header""side main""output output"}.resizer.svelte-1n46o8q{display:none}.main.svelte-1n46o8q{border-left:1px solid var(--cfg-border)}.scrim.svelte-1n46o8q{display:block}.shell.svelte-1n46o8q section.preview{z-index:50;border-left:1px solid var(--cfg-border-strong);width:min(440px,94vw);position:fixed;inset:0 0 0 auto;box-shadow:-16px 0 48px #00000080}}@media (max-width:600px){.shell.svelte-1n46o8q,.shell--no-preview.svelte-1n46o8q,.shell--no-sidebar.svelte-1n46o8q,.shell--no-sidebar.shell--no-preview.svelte-1n46o8q{grid-template-columns:44px minmax(0,1fr)}}
/*$vite$:1*/ No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Exclude compiled CSS from stylelint or apply fixes to source files.

The pipeline failures in this compiled CSS come from two sources:

  1. Source CSS issues (Lines 28, 37, 60, 106, 278 in src/styles/app.css) — already flagged in the source file review
  2. Component-scoped styles in .svelte files that use vendor prefixes (-webkit-appearance, -webkit-user-select, -webkit-text-decoration), deprecated clip, kebab-case violations in custom properties, etc.

Since this is generated/compiled output, fixes should be applied to:

  • Source files: src/styles/app.css for the base design system
  • Component styles: Individual .svelte files for component-specific rules

Alternatively, add assets/admin-app/app.css to your .stylelintignore to skip linting generated files.

🧰 Tools
🪛 GitHub Actions: CI / Lint, test, version & drift checks

[error] 1-1: stylelint (media-feature-range-notation): Expected "context" media feature range notation (e.g., column 2248). Multiple occurrences reported.


[error] 1-1: stylelint (property-no-vendor-prefix): Vendor-prefixed property "-webkit-appearance" (e.g., column 6334). Multiple occurrences reported.


[error] 1-1: stylelint (property-no-vendor-prefix): Vendor-prefixed property "-webkit-user-select" (e.g., column 27650).


[error] 1-1: stylelint (property-no-vendor-prefix): Vendor-prefixed property "-webkit-text-decoration" (e.g., column 32833).


[error] 1-1: stylelint (selector-pseudo-element-colon-notation): Expected double colon pseudo-element notation (e.g., column 33876 and 33942).


[error] 1-1: stylelint (custom-property-pattern): Expected custom property name "--sf-color-text--muted" / "--sf-color-text--secondary" to be kebab-case (e.g., columns 35507, 35842, 38123). Multiple occurrences reported.


[error] 1-1: stylelint (selector-attribute-quotes): Expected quotes around attribute value (e.g., "page" at column 43904; "radio" at column 68126; "checkbox" at column 69403).


[error] 1-1: stylelint (keyframe-selector-notation): Expected "to" to be "100%" (e.g., columns 45485, 45655, 45829, 46037). Multiple occurrences reported.


[error] 1-1: stylelint (font-family-name-quotes): Expected quotes around font-family names "Cascadia Code" / "Fira Code" (e.g., columns 72638 and 72652).


[error] 1-1: stylelint (property-no-deprecated): Deprecated property "clip" (e.g., column 69436).


[error] 2-2: stylelint (comment-whitespace-inside): Expected whitespace after "/*" (at 2:3).


[error] 2-2: stylelint (comment-whitespace-inside): Expected whitespace before "*/" (at 2:10).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SLASHED-for-WP/assets/admin-app/app.css` around lines 1 - 2, The compiled CSS
file contains stylelint violations originating from source CSS in
src/styles/app.css and component-scoped styles in .svelte files. Rather than
manually fixing the compiled output, apply stylelint fixes to the source files
that generate this CSS: update src/styles/app.css to address base design system
issues and fix individual .svelte component files to remove vendor prefix
violations, deprecated CSS properties like clip, and kebab-case violations in
custom properties. Alternatively, if the compiled output should not be linted,
add assets/admin-app/app.css to .stylelintignore to exclude generated files from
linting.

Source: Pipeline failures

assets/admin-app/ is a compiled build artifact.
admin-app/src/styles/ is synced verbatim from the configurator repo.
Neither is our code to lint — add them to ignoreFiles, matching the
same pattern already used for the bricks app build outputs.

https://claude.ai/code/session_017Q5NUFKipcefaCeWSfwQib
@jackgranatowski
jackgranatowski merged commit fd6282f into main Jun 14, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants