@ryanhelsing/ry-ui
Version:
Framework-agnostic, Light DOM web components. CSS is the source of truth.
1,838 lines (1,547 loc) • 198 kB
CSS
/**
* ry-ui Design Tokens
*
* CORE KNOBS → DERIVED TOKENS → COMPONENTS
*
* Themes only need to set the ~18 core knobs at the top.
* Everything else derives automatically via color-mix() and calc().
* Override any derived token for fine-tuning.
*/
/* ═══════════════════════════════════════════════════════════════
@property — typed custom properties for animation & type safety
Note: color tokens are NOT registered here because @property
prevents light-dark() from re-resolving on dynamic color-scheme
changes in Firefox. Colors use unregistered custom properties.
═══════════════════════════════════════════════════════════════ */
@property --ry-duration-fast { syntax: "<time>"; inherits: true; initial-value: 100ms; }
@property --ry-duration-normal { syntax: "<time>"; inherits: true; initial-value: 200ms; }
@property --ry-duration-slow { syntax: "<time>"; inherits: true; initial-value: 300ms; }
@property --ry-space-1 { syntax: "<length>"; inherits: true; initial-value: 0.25rem; }
@property --ry-space-2 { syntax: "<length>"; inherits: true; initial-value: 0.5rem; }
@property --ry-space-3 { syntax: "<length>"; inherits: true; initial-value: 0.75rem; }
@property --ry-space-4 { syntax: "<length>"; inherits: true; initial-value: 1rem; }
@property --ry-space-6 { syntax: "<length>"; inherits: true; initial-value: 1.5rem; }
@property --ry-space-8 { syntax: "<length>"; inherits: true; initial-value: 2rem; }
@layer ry-tokens, ry-structure, ry-theme;
@layer ry-tokens {
:root {
color-scheme: light dark;
/* ═══════════════════════════════════════════════════════════════
CORE KNOBS — set these to define a theme
═══════════════════════════════════════════════════════════════ */
/* Palette: 3 roles */
--ry-color-primary: light-dark(oklch(0.623 0.188 259.8), oklch(0.714 0.143 254.6));
--ry-color-secondary: light-dark(oklch(0.554 0.041 257.4), oklch(0.711 0.035 256.8));
--ry-color-accent: light-dark(oklch(0.627 0.213 303.9), oklch(0.714 0.183 303.9));
/* Surface */
--ry-color-bg: light-dark(oklch(1 0 0), oklch(0.208 0.04 265.8));
--ry-color-text: light-dark(oklch(0.279 0.037 260), oklch(0.968 0.007 248.1));
/* Semantic (overrideable, but defaults are universal) */
--ry-color-success: oklch(0.723 0.192 149.6);
--ry-color-warning: oklch(0.769 0.165 70.1);
--ry-color-danger: oklch(0.637 0.208 25.3);
--ry-color-info: oklch(0.715 0.126 215.2);
/* Type: 2 fonts */
--ry-font-primary: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
--ry-font-secondary: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
/* Shape */
--ry-radius-base: 0.375rem;
--ry-border-width: 1px;
--ry-outline-width: 0px;
/* Depth */
--ry-shadow-color: light-dark(oklch(0 0 0 / 0.1), oklch(0 0 0 / 0.4));
--ry-shadow-strength: 1;
--ry-shadow-spread: 1;
/* Surface treatment */
--ry-panel-opacity: 1;
--ry-panel-blur: 0px;
/* Motion */
--ry-animation-style: smooth; /* none | smooth | bouncy */
--ry-duration-scale: 1;
/* Density */
--ry-space-scale: 1;
/* ═══════════════════════════════════════════════════════════════
DERIVED: COLORS — auto-generated from core palette
═══════════════════════════════════════════════════════════════ */
/* Hover/active states via color-mix */
--ry-color-primary-hover: color-mix(in oklch, var(--ry-color-primary) 80%, var(--ry-color-text));
--ry-color-primary-active: color-mix(in oklch, var(--ry-color-primary) 65%, var(--ry-color-text));
--ry-color-secondary-hover: color-mix(in oklch, var(--ry-color-secondary) 80%, var(--ry-color-text));
--ry-color-secondary-active: color-mix(in oklch, var(--ry-color-secondary) 65%, var(--ry-color-text));
--ry-color-accent-hover: color-mix(in oklch, var(--ry-color-accent) 80%, var(--ry-color-text));
--ry-color-accent-active: color-mix(in oklch, var(--ry-color-accent) 65%, var(--ry-color-text));
--ry-color-danger-hover: color-mix(in oklch, var(--ry-color-danger) 80%, var(--ry-color-text));
/* Text variants */
--ry-color-text-muted: color-mix(in oklch, var(--ry-color-text) 55%, var(--ry-color-bg));
--ry-color-text-inverse: var(--ry-color-bg);
/* Background variants */
--ry-color-bg-subtle: color-mix(in oklch, var(--ry-color-bg) 96%, var(--ry-color-text));
--ry-color-bg-muted: color-mix(in oklch, var(--ry-color-bg) 92%, var(--ry-color-text));
/* Border variants */
--ry-color-border: color-mix(in oklch, var(--ry-color-bg) 82%, var(--ry-color-text));
--ry-color-border-strong: color-mix(in oklch, var(--ry-color-bg) 70%, var(--ry-color-text));
/* Overlay */
--ry-color-overlay: color-mix(in oklch, var(--ry-color-text) 50%, transparent);
--ry-color-hover-overlay: color-mix(in oklch, var(--ry-color-text) 4%, transparent);
/* Semantic backgrounds & text — derived from base semantic colors */
--ry-color-info-bg: color-mix(in srgb, var(--ry-color-info) 12%, var(--ry-color-bg));
--ry-color-info-text: color-mix(in oklch, var(--ry-color-info) 70%, var(--ry-color-text));
--ry-color-success-bg: color-mix(in srgb, var(--ry-color-success) 12%, var(--ry-color-bg));
--ry-color-success-text: color-mix(in oklch, var(--ry-color-success) 70%, var(--ry-color-text));
--ry-color-warning-bg: color-mix(in srgb, var(--ry-color-warning) 12%, var(--ry-color-bg));
--ry-color-warning-text: color-mix(in oklch, var(--ry-color-warning) 70%, var(--ry-color-text));
--ry-color-danger-bg: color-mix(in srgb, var(--ry-color-danger) 12%, var(--ry-color-bg));
--ry-color-danger-text: color-mix(in oklch, var(--ry-color-danger) 70%, var(--ry-color-text));
/* ═══════════════════════════════════════════════════════════════
DERIVED: CODE SYNTAX — from palette, auto-adapts to any theme
═══════════════════════════════════════════════════════════════ */
--ry-code-bg: var(--ry-color-bg-subtle);
--ry-code-header-bg: var(--ry-color-bg-muted);
--ry-code-text-color: var(--ry-color-text);
--ry-code-title-color: var(--ry-color-text-muted);
--ry-code-icon-color: var(--ry-color-text-muted);
--ry-code-icon-hover-bg: var(--ry-color-bg-muted);
--ry-code-icon-hover-color: var(--ry-color-text);
--ry-code-line-number-color: var(--ry-color-secondary);
--ry-code-line-border-color: var(--ry-color-border);
--ry-code-color-preview-border: var(--ry-color-border);
--ry-code-keyword: var(--ry-color-danger);
--ry-code-property: var(--ry-color-primary);
--ry-code-value: var(--ry-color-accent);
--ry-code-string: var(--ry-color-success);
--ry-code-number: var(--ry-color-warning);
--ry-code-comment: var(--ry-color-text-muted);
--ry-code-selector: var(--ry-color-info);
--ry-code-punctuation: var(--ry-color-text-muted);
--ry-code-tag: var(--ry-color-info);
--ry-code-attribute: var(--ry-color-primary);
/* ═══════════════════════════════════════════════════════════════
DERIVED: TYPOGRAPHY — from core font knobs
═══════════════════════════════════════════════════════════════ */
--ry-font-sans: var(--ry-font-primary);
--ry-font-mono: var(--ry-font-secondary);
/* Font sizes */
--ry-text-xs: 0.75rem;
--ry-text-sm: 0.875rem;
--ry-text-base: 1rem;
--ry-text-lg: 1.125rem;
--ry-text-xl: 1.25rem;
--ry-text-2xl: 1.5rem;
--ry-text-3xl: 1.875rem;
--ry-text-4xl: 2.25rem;
/* Font weights */
--ry-font-normal: 400;
--ry-font-medium: 500;
--ry-font-semibold: 600;
--ry-font-bold: 700;
/* Line heights */
--ry-leading-tight: 1.25;
--ry-leading-normal: 1.5;
--ry-leading-relaxed: 1.75;
/* ═══════════════════════════════════════════════════════════════
DERIVED: SPACING — scaled from base
═══════════════════════════════════════════════════════════════ */
--ry-space-0: 0;
--ry-space-1: calc(0.25rem * var(--ry-space-scale));
--ry-space-2: calc(0.5rem * var(--ry-space-scale));
--ry-space-3: calc(0.75rem * var(--ry-space-scale));
--ry-space-4: calc(1rem * var(--ry-space-scale));
--ry-space-5: calc(1.25rem * var(--ry-space-scale));
--ry-space-6: calc(1.5rem * var(--ry-space-scale));
--ry-space-8: calc(2rem * var(--ry-space-scale));
--ry-space-10: calc(2.5rem * var(--ry-space-scale));
--ry-space-12: calc(3rem * var(--ry-space-scale));
--ry-space-16: calc(4rem * var(--ry-space-scale));
--ry-space-20: calc(5rem * var(--ry-space-scale));
/* ═══════════════════════════════════════════════════════════════
DERIVED: BORDERS & RADIUS — scaled from base
═══════════════════════════════════════════════════════════════ */
--ry-radius-none: 0;
--ry-radius-sm: calc(var(--ry-radius-base) * 0.66);
--ry-radius-md: var(--ry-radius-base);
--ry-radius-lg: calc(var(--ry-radius-base) * 1.33);
--ry-radius-xl: calc(var(--ry-radius-base) * 2);
--ry-radius-2xl: calc(var(--ry-radius-base) * 2.66);
--ry-radius-full: 9999px;
/* ═══════════════════════════════════════════════════════════════
DERIVED: SHADOWS — scaled from strength + spread knobs
═══════════════════════════════════════════════════════════════ */
--ry-shadow-color-sm: color-mix(in oklch, var(--ry-shadow-color) calc(50% * var(--ry-shadow-strength)), transparent);
--ry-shadow-sm:
0
calc(1px * var(--ry-shadow-spread))
calc(2px * var(--ry-shadow-spread))
0
var(--ry-shadow-color-sm);
--ry-shadow-md:
0
calc(4px * var(--ry-shadow-spread))
calc(6px * var(--ry-shadow-spread))
calc(-1px * var(--ry-shadow-spread))
var(--ry-shadow-color),
0
calc(2px * var(--ry-shadow-spread))
calc(4px * var(--ry-shadow-spread))
calc(-2px * var(--ry-shadow-spread))
var(--ry-shadow-color);
--ry-shadow-lg:
0
calc(10px * var(--ry-shadow-spread))
calc(15px * var(--ry-shadow-spread))
calc(-3px * var(--ry-shadow-spread))
var(--ry-shadow-color),
0
calc(4px * var(--ry-shadow-spread))
calc(6px * var(--ry-shadow-spread))
calc(-4px * var(--ry-shadow-spread))
var(--ry-shadow-color);
--ry-shadow-xl:
0
calc(20px * var(--ry-shadow-spread))
calc(25px * var(--ry-shadow-spread))
calc(-5px * var(--ry-shadow-spread))
var(--ry-shadow-color),
0
calc(8px * var(--ry-shadow-spread))
calc(10px * var(--ry-shadow-spread))
calc(-6px * var(--ry-shadow-spread))
var(--ry-shadow-color);
/* ═══════════════════════════════════════════════════════════════
DERIVED: TRANSITIONS — scaled from duration-scale + animation style
═══════════════════════════════════════════════════════════════ */
--ry-duration-fast: calc(100ms * var(--ry-duration-scale));
--ry-duration-normal: calc(200ms * var(--ry-duration-scale));
--ry-duration-slow: calc(300ms * var(--ry-duration-scale));
--ry-ease: cubic-bezier(0.4, 0, 0.2, 1);
--ry-ease-in: cubic-bezier(0.4, 0, 1, 1);
--ry-ease-out: cubic-bezier(0, 0, 0.2, 1);
--ry-ease-out-back: cubic-bezier(0.34, 1.85, 0.64, 1);
--ry-ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1);
--ry-ease-in-out-expo: cubic-bezier(1, 0, 0, 1);
/* ═══════════════════════════════════════════════════════════════
Z-INDEX (not themeable — structural)
═══════════════════════════════════════════════════════════════ */
--ry-z-dropdown: 1000;
--ry-z-sticky: 1020;
--ry-z-fixed: 1030;
--ry-z-modal-backdrop: 1040;
--ry-z-modal: 1050;
--ry-z-popover: 1060;
--ry-z-tooltip: 1070;
--ry-z-toast: 1080;
/* ═══════════════════════════════════════════════════════════════
DERIVED: FOCUS — from primary
═══════════════════════════════════════════════════════════════ */
--ry-focus-ring: 0 0 0 3px color-mix(in oklch, var(--ry-color-primary) 50%, transparent);
}
/* Force light or dark mode */
[data-ry-theme="light"] { color-scheme: light; }
[data-ry-theme="dark"] { color-scheme: dark; }
} /* @layer ry-tokens */
/**
* ry-ui Structure CSS
*
* Pure layout and behavioral styles using data-ry-target selectors.
* No colors, shadows, or decorative properties.
* Works with any theme or no theme at all.
*
* Users can bring their own styling (e.g., Tailwind) - classes are optional.
* JS queries use [data-ry-target], structure CSS uses [data-ry-target],
* only theme CSS requires .ry-* classes.
*/
@layer ry-structure {
/* Enable native height: auto animation for all components */
:root {
interpolate-size: allow-keywords;
}
/* ═══════════════════════════════════════════════════════════════
SCROLL LOCK (for modals, drawers)
═══════════════════════════════════════════════════════════════ */
body {
margin: 0;
min-height: 100dvh;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
body[data-ry-scroll-lock] {
overflow: hidden;
padding-right: var(--ry-scrollbar-width, 0);
}
/* ═══════════════════════════════════════════════════════════════
PREFLIGHT RESET (opt-in via data-ry-reset on body/html)
Faithful equivalent of Tailwind Preflight.
═══════════════════════════════════════════════════════════════ */
/* Universal — :where() gives zero specificity so component styles always win */
:where([data-ry-reset]) *,
:where([data-ry-reset]) *::before,
:where([data-ry-reset]) *::after,
:where([data-ry-reset]) *::backdrop {
box-sizing: border-box;
margin: 0;
padding: 0;
border: 0 solid;
}
/* Root */
:where([data-ry-reset]) {
line-height: 1.5;
-webkit-text-size-adjust: 100%;
tab-size: 4;
-webkit-tap-highlight-color: transparent;
}
/* Typography */
:where([data-ry-reset]) :where(h1, h2, h3, h4, h5, h6) {
font-size: inherit;
font-weight: inherit;
}
:where([data-ry-reset]) :where(a) {
color: inherit;
text-decoration: inherit;
}
:where([data-ry-reset]) :where(b, strong) {
font-weight: bolder;
}
:where([data-ry-reset]) :where(code, kbd, samp, pre) {
font-size: 1em;
}
:where([data-ry-reset]) :where(small) {
font-size: 80%;
}
:where([data-ry-reset]) :where(sub, sup) {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
:where([data-ry-reset]) :where(sub) { bottom: -0.25em; }
:where([data-ry-reset]) :where(sup) { top: -0.5em; }
/* Lists */
:where([data-ry-reset]) :where(ol, ul, menu) {
list-style: none;
}
/* Table */
:where([data-ry-reset]) :where(table) {
text-indent: 0;
border-color: inherit;
border-collapse: collapse;
}
/* HR */
:where([data-ry-reset]) :where(hr) {
height: 0;
color: inherit;
border-top-width: 1px;
}
/* Media */
:where([data-ry-reset]) :where(img, svg, video, canvas, audio, iframe, embed, object) {
display: block;
vertical-align: middle;
}
:where([data-ry-reset]) :where(img, video) {
max-width: 100%;
height: auto;
}
/* Form controls */
:where([data-ry-reset]) :where(button, input, select, optgroup, textarea) {
font: inherit;
font-feature-settings: inherit;
font-variation-settings: inherit;
letter-spacing: inherit;
color: inherit;
border-radius: 0;
background-color: transparent;
}
:where([data-ry-reset]) ::placeholder {
opacity: 1;
}
@supports (color: color-mix(in oklab, currentcolor 50%, transparent)) {
:where([data-ry-reset]) ::placeholder {
color: color-mix(in oklab, currentcolor 50%, transparent);
}
}
:where([data-ry-reset]) :where(textarea) {
resize: vertical;
}
:where([data-ry-reset]) :where(button, input:where([type='button'], [type='reset'], [type='submit'])) {
appearance: button;
}
:where([data-ry-reset]) ::-webkit-search-decoration {
-webkit-appearance: none;
}
:where([data-ry-reset]) ::-webkit-inner-spin-button,
:where([data-ry-reset]) ::-webkit-outer-spin-button {
height: auto;
}
/* Misc */
:where([data-ry-reset]) :where(summary) {
display: list-item;
}
:where([data-ry-reset]) :where([hidden]:not([hidden='until-found'])) {
display: none !important;
}
/* ═══════════════════════════════════════════════════════════════
TRANSFORM WRAPPER (FOUC prevention)
═══════════════════════════════════════════════════════════════ */
ry,
ry-search-item,
ry-search-group {
display: none;
}
/* ═══════════════════════════════════════════════════════════════
BOX SIZING RESET
═══════════════════════════════════════════════════════════════ */
:where([data-ry-target],
ry-page, ry-header, ry-main, ry-footer, ry-section, ry-aside,
ry-grid, ry-stack, ry-cluster, ry-split, ry-center,
ry-card, ry-accordion, ry-modal, ry-tabs, ry-dropdown,
ry-button, ry-badge, ry-alert, ry-field, ry-nav, ry-logo, ry-actions,
ry-accordion-item, ry-tab, ry-menu, ry-menu-item, ry-divider,
ry-theme-toggle, ry-select, ry-switch, ry-tooltip, ry-drawer, ry-toast,
ry-toggle-button, ry-knob, ry-slider, ry-number-select, ry-color-picker, ry-color-input,
ry-gradient-picker, ry-tree, ry-tree-item,
ry-tag, ry-tag-input, ry-hero, ry-stat, ry-feature, ry-feature-grid,
ry-pricing, ry-pricing-card, ry-carousel, ry-combobox, ry-heading,
ry-logo-bar) {
box-sizing: border-box;
}
:where([data-ry-target],
ry-page, ry-header, ry-main, ry-footer, ry-section,
ry-card, ry-accordion, ry-modal, ry-tabs, ry-dropdown) * {
box-sizing: inherit;
}
/* ═══════════════════════════════════════════════════════════════
CUSTOM ELEMENT DISPLAY DEFAULTS
═══════════════════════════════════════════════════════════════ */
/* Block elements */
:is(ry-page, ry-header, ry-main, ry-footer, ry-section, ry-aside,
ry-card, ry-accordion, ry-accordion-item, ry-tabs, ry-tab, ry-alert, ry-field,
ry-tag-input, ry-carousel) {
display: block;
}
/* Flex containers */
:is(ry-grid, ry-stack, ry-cluster, ry-split, ry-center, ry-nav, ry-actions) {
display: flex;
}
/* Inline elements */
:is(ry-badge, ry-logo, ry-tag) {
display: inline-flex;
}
/* Contents (wrapper doesn't affect layout) */
:is(ry-modal, ry-drawer) {
display: contents;
}
/* Button-like elements */
:is(ry-button, ry-menu-item) {
display: inline-flex;
}
/* Balanced text wrapping for headings in overlay/display components */
:is(ry-modal [data-ry-target="header"] h3,
ry-card h3,
ry-hero h1,
ry-pricing-card h3,
ry-heading [data-ry-target="title"]) {
text-wrap: balance;
}
/* ═══════════════════════════════════════════════════════════════
PAGE LAYOUT
═══════════════════════════════════════════════════════════════ */
ry-page {
display: flex;
flex-direction: column;
min-height: 100vh;
min-height: 100dvh;
container-type: inline-size;
scrollbar-gutter: stable;
overflow-x: clip;
}
/* ═══════════════════════════════════════════════════════════════
HEADER
═══════════════════════════════════════════════════════════════ */
ry-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--ry-space-4, 1rem);
padding: var(--ry-space-4, 1rem) var(--ry-space-6, 1.5rem);
}
ry-header[sticky] {
position: sticky;
top: 0;
z-index: var(--ry-z-sticky, 1020);
}
/* ═══════════════════════════════════════════════════════════════
MAIN
═══════════════════════════════════════════════════════════════ */
ry-main {
flex: 1;
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: var(--ry-space-8, 2rem) var(--ry-space-6, 1.5rem);
container-type: inline-size;
scrollbar-gutter: stable;
}
/* ═══════════════════════════════════════════════════════════════
FOOTER
═══════════════════════════════════════════════════════════════ */
ry-footer {
padding: var(--ry-space-6, 1.5rem);
text-align: center;
}
/* Full footer with columns */
ry-footer[layout="columns"] {
text-align: start;
padding: var(--ry-space-12, 3rem) var(--ry-space-6, 1.5rem);
}
ry-footer[layout="columns"] > [data-ry-target="columns"],
ry-footer[layout="columns"] > .ry-footer__columns {
display: grid;
grid-template-columns: 1.5fr repeat(auto-fit, minmax(8rem, 1fr));
gap: var(--ry-space-8, 2rem);
padding-block-end: var(--ry-space-8, 2rem);
}
ry-footer[layout="columns"] > [data-ry-target="columns"] nav,
ry-footer[layout="columns"] > .ry-footer__columns nav {
display: flex;
flex-direction: column;
gap: var(--ry-space-2, 0.5rem);
}
ry-footer[layout="columns"] > [data-ry-target="columns"] nav strong,
ry-footer[layout="columns"] > .ry-footer__columns nav strong {
margin-block-end: var(--ry-space-2, 0.5rem);
}
ry-footer[layout="columns"] > [data-ry-target="bottom"],
ry-footer[layout="columns"] > .ry-footer__bottom {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: var(--ry-space-4, 1rem);
padding-block-start: var(--ry-space-6, 1.5rem);
border-top: 1px solid currentColor;
opacity: 0.5;
}
@media (max-width: 768px) {
ry-footer[layout="columns"] > [data-ry-target="columns"],
ry-footer[layout="columns"] > .ry-footer__columns {
grid-template-columns: 1fr 1fr;
}
}
/* ═══════════════════════════════════════════════════════════════
SECTION
═══════════════════════════════════════════════════════════════ */
ry-section {
margin-block-end: var(--ry-space-12, 3rem);
container-type: inline-size;
}
ry-section:last-child {
margin-block-end: 0;
}
ry-section[narrow] {
max-inline-size: 48rem;
margin-inline: auto;
}
/* Full-width breakout — bg goes edge-to-edge, content stays centered */
ry-section[full],
ry-section[inverted],
ry-footer,
ry-logo-bar {
width: 100vw;
margin-inline-start: calc(50% - 50vw);
padding-inline: max(var(--ry-space-6, 1.5rem), calc(50vw - 50%));
}
ry-section[inverted] {
padding-block: var(--ry-space-12, 3rem);
}
ry-section[pad-bottom="lg"] {
padding-bottom: var(--ry-space-20, 5rem);
}
/* ═══════════════════════════════════════════════════════════════
LOGO BAR
═══════════════════════════════════════════════════════════════ */
ry-logo-bar {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
gap: var(--ry-space-8, 2rem);
padding-block: var(--ry-space-8, 2rem);
text-align: center;
}
ry-logo-bar > p {
width: 100%;
margin: 0;
}
ry-logo-bar > :not(p) {
display: inline-flex;
align-items: center;
}
/* Scroll layout — horizontal scroll, no wrap */
ry-logo-bar[layout="scroll"] {
flex-wrap: nowrap;
overflow-x: auto;
overflow-y: hidden;
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
}
ry-logo-bar[layout="scroll"]::-webkit-scrollbar {
display: none;
}
ry-logo-bar[layout="scroll"] > :not(p) {
flex-shrink: 0;
}
/* Marquee layout — infinite auto-scroll */
ry-logo-bar[layout="marquee"] {
flex-wrap: nowrap;
overflow: hidden;
}
ry-logo-bar[layout="marquee"] [data-ry-target="track"] {
display: flex;
align-items: center;
gap: var(--ry-space-8, 2rem);
width: max-content;
animation: ry-marquee var(--ry-logo-bar-speed, 30s) linear infinite;
}
ry-logo-bar[layout="marquee"] [data-ry-target="track"] > * {
display: inline-flex;
align-items: center;
flex-shrink: 0;
}
ry-logo-bar[layout="marquee"]:hover [data-ry-target="track"] {
animation-play-state: paused;
}
@keyframes ry-marquee {
from { transform: translateX(0); }
to { transform: translateX(-25%); }
}
/* Size variants */
ry-logo-bar[size="sm"] {
padding: var(--ry-space-4, 1rem) var(--ry-space-4, 1rem);
gap: var(--ry-space-4, 1rem);
}
ry-logo-bar[size="lg"] {
padding: var(--ry-space-12, 3rem) var(--ry-space-6, 1.5rem);
gap: var(--ry-space-6, 1.5rem);
}
/* Logo items */
ry-logo-bar img {
height: var(--ry-logo-bar-height, 2rem);
width: auto;
object-fit: contain;
}
ry-logo-bar span {
white-space: nowrap;
}
/* ═══════════════════════════════════════════════════════════════
GRID
═══════════════════════════════════════════════════════════════ */
ry-grid {
display: grid;
gap: var(--ry-space-4, 1rem);
}
ry-grid[cols="1"] { grid-template-columns: 1fr; }
ry-grid[cols="2"] { grid-template-columns: repeat(2, 1fr); }
ry-grid[cols="3"] { grid-template-columns: repeat(3, 1fr); }
ry-grid[cols="4"] { grid-template-columns: repeat(4, 1fr); }
ry-grid[cols="5"] { grid-template-columns: repeat(5, 1fr); }
ry-grid[cols="6"] { grid-template-columns: repeat(6, 1fr); }
/* Auto-fit mode: fluid columns based on min-width */
ry-grid[cols="auto-fit"] {
grid-template-columns: repeat(auto-fit, minmax(var(--ry-grid-min, 280px), 1fr));
}
ry-grid[cols="auto-fill"] {
grid-template-columns: repeat(auto-fill, minmax(var(--ry-grid-min, 280px), 1fr));
}
ry-grid[overlap] {
position: relative;
z-index: 1;
margin-top: calc(-1 * var(--ry-space-12, 3rem));
padding-inline: var(--ry-space-6, 1.5rem);
}
/* Default responsive behavior */
@container (max-width: 640px) {
:is(ry-grid[cols="2"], ry-grid[cols="3"], ry-grid[cols="4"],
ry-grid[cols="5"], ry-grid[cols="6"]) {
grid-template-columns: 1fr;
}
}
@container (min-width: 641px) and (max-width: 1024px) {
:is(ry-grid[cols="3"], ry-grid[cols="4"],
ry-grid[cols="5"], ry-grid[cols="6"]) {
grid-template-columns: repeat(2, 1fr);
}
}
/* Per-breakpoint column overrides: cols-sm, cols-md, cols-lg */
@container (max-width: 640px) {
ry-grid[cols-sm="1"] { grid-template-columns: 1fr; }
ry-grid[cols-sm="2"] { grid-template-columns: repeat(2, 1fr); }
ry-grid[cols-sm="3"] { grid-template-columns: repeat(3, 1fr); }
}
@container (min-width: 641px) and (max-width: 1024px) {
ry-grid[cols-md="1"] { grid-template-columns: 1fr; }
ry-grid[cols-md="2"] { grid-template-columns: repeat(2, 1fr); }
ry-grid[cols-md="3"] { grid-template-columns: repeat(3, 1fr); }
ry-grid[cols-md="4"] { grid-template-columns: repeat(4, 1fr); }
}
@container (min-width: 1025px) {
ry-grid[cols-lg="2"] { grid-template-columns: repeat(2, 1fr); }
ry-grid[cols-lg="3"] { grid-template-columns: repeat(3, 1fr); }
ry-grid[cols-lg="4"] { grid-template-columns: repeat(4, 1fr); }
ry-grid[cols-lg="5"] { grid-template-columns: repeat(5, 1fr); }
ry-grid[cols-lg="6"] { grid-template-columns: repeat(6, 1fr); }
}
/* ═══════════════════════════════════════════════════════════════
STACK (vertical)
═══════════════════════════════════════════════════════════════ */
ry-stack {
display: flex;
flex-direction: column;
gap: var(--ry-space-4, 1rem);
}
ry-stack[gap="sm"] { gap: var(--ry-space-2, 0.5rem); }
ry-stack[gap="md"] { gap: var(--ry-space-4, 1rem); }
ry-stack[gap="lg"] { gap: var(--ry-space-6, 1.5rem); }
ry-stack[gap="xl"] { gap: var(--ry-space-8, 2rem); }
/* ═══════════════════════════════════════════════════════════════
CLUSTER (horizontal, wraps)
═══════════════════════════════════════════════════════════════ */
ry-cluster {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--ry-space-3, 0.75rem);
}
ry-cluster[gap="sm"] { gap: var(--ry-space-2, 0.5rem); }
ry-cluster[gap="md"] { gap: var(--ry-space-3, 0.75rem); }
ry-cluster[gap="lg"] { gap: var(--ry-space-4, 1rem); }
/* ═══════════════════════════════════════════════════════════════
SPLIT (two columns)
═══════════════════════════════════════════════════════════════ */
ry-split {
display: flex;
gap: var(--ry-space-6, 1.5rem);
}
ry-split > :first-child {
flex: 1;
}
ry-split > :last-child {
flex-shrink: 0;
width: var(--ry-split-width, 300px);
min-width: var(--ry-split-min-width, 0);
}
/* Resize handle */
ry-split [data-ry-target="handle"] {
flex-shrink: 0;
width: 8px;
margin-inline: -4px;
cursor: col-resize;
position: relative;
z-index: 1;
touch-action: none;
}
/* Larger hit area via pseudo-element */
ry-split [data-ry-target="handle"]::before {
content: '';
position: absolute;
inset-block: 0;
inset-inline: -4px;
}
/* Visible drag indicator */
ry-split [data-ry-target="handle"]::after {
content: '';
position: absolute;
inset-block-start: 50%;
inset-inline-start: 50%;
width: 4px;
height: 32px;
transform: translate(-50%, -50%);
border-radius: 2px;
opacity: 0;
transition: opacity var(--ry-duration-fast, 100ms);
}
ry-split [data-ry-target="handle"]:hover::after,
ry-split[data-ry-resizing] [data-ry-target="handle"]::after {
opacity: 1;
}
@container (max-width: 768px) {
ry-split {
flex-direction: column;
}
ry-split > :last-child {
width: 100%;
}
ry-split [data-ry-target="handle"] {
display: none;
}
}
/* ═══════════════════════════════════════════════════════════════
CENTER
═══════════════════════════════════════════════════════════════ */
ry-center {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
}
/* ═══════════════════════════════════════════════════════════════
NAV
═══════════════════════════════════════════════════════════════ */
ry-nav {
display: flex;
align-items: center;
gap: var(--ry-space-1, 0.25rem);
}
ry-nav a {
text-decoration: none;
padding: var(--ry-space-2, 0.5rem) var(--ry-space-3, 0.75rem);
white-space: nowrap;
}
/* ═══════════════════════════════════════════════════════════════
LOGO
═══════════════════════════════════════════════════════════════ */
ry-logo {
display: inline-flex;
align-items: center;
}
/* ═══════════════════════════════════════════════════════════════
ACTIONS
═══════════════════════════════════════════════════════════════ */
ry-actions {
display: flex;
align-items: center;
gap: var(--ry-space-2, 0.5rem);
margin-inline-start: auto;
}
/* ═══════════════════════════════════════════════════════════════
DIVIDER
═══════════════════════════════════════════════════════════════ */
ry-divider {
display: block;
height: 1px;
margin-block: var(--ry-space-4, 1rem);
margin-inline: 0;
}
ry-divider[vertical] {
width: 1px;
height: auto;
align-self: stretch;
margin-block: 0;
margin-inline: var(--ry-space-4, 1rem);
}
/* ═══════════════════════════════════════════════════════════════
BUTTONS
═══════════════════════════════════════════════════════════════ */
ry-button {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--ry-space-2, 0.5rem);
padding: var(--ry-space-2, 0.5rem) var(--ry-space-4, 1rem);
white-space: nowrap;
cursor: pointer;
user-select: none;
}
ry-button[disabled] {
cursor: not-allowed;
pointer-events: none;
}
/* Button sizes */
ry-button[size="sm"] {
padding: var(--ry-space-1, 0.25rem) var(--ry-space-3, 0.75rem);
}
ry-button[size="lg"] {
padding: var(--ry-space-3, 0.75rem) var(--ry-space-6, 1.5rem);
}
/* Icon-only button */
ry-button[icon]:empty {
padding: var(--ry-space-2, 0.5rem);
}
ry-button[icon][size="sm"]:empty {
padding: var(--ry-space-1, 0.25rem);
}
/* Link variant — inline text link style */
ry-button[variant="link"] {
background: none;
border: none;
padding: 0;
display: inline;
cursor: pointer;
}
/* ═══════════════════════════════════════════════════════════════
TOGGLE BUTTON
═══════════════════════════════════════════════════════════════ */
ry-toggle-button {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--ry-space-2, 0.5rem);
padding: var(--ry-space-2, 0.5rem) var(--ry-space-4, 1rem);
white-space: nowrap;
cursor: pointer;
user-select: none;
}
ry-toggle-button[disabled] {
cursor: not-allowed;
pointer-events: none;
}
/* Toggle button sizes */
ry-toggle-button[size="sm"] {
padding: var(--ry-space-1, 0.25rem) var(--ry-space-3, 0.75rem);
}
ry-toggle-button[size="lg"] {
padding: var(--ry-space-3, 0.75rem) var(--ry-space-6, 1.5rem);
}
/* Icon-only toggle button */
ry-toggle-button[icon]:empty {
padding: var(--ry-space-2, 0.5rem);
}
ry-toggle-button[icon][size="sm"]:empty {
padding: var(--ry-space-1, 0.25rem);
}
ry-toggle-button[icon][size="lg"]:empty {
padding: var(--ry-space-3, 0.75rem);
}
/* Block toggle button (card-style, full width) */
ry-toggle-button[block] {
display: block;
width: 100%;
text-align: start;
padding: var(--ry-space-4, 1rem);
}
/* ═══════════════════════════════════════════════════════════════
KNOB
═══════════════════════════════════════════════════════════════ */
ry-knob {
display: inline-flex;
flex-direction: column;
align-items: center;
gap: var(--ry-space-1, 0.25rem);
user-select: none;
outline: none;
}
ry-knob[disabled] {
pointer-events: none;
}
ry-knob [data-ry-target="ring"] {
--knob-size: 64px;
--knob-rotation: -135deg;
--knob-percent: 0;
position: relative;
width: var(--knob-size);
height: var(--knob-size);
cursor: grab;
}
ry-knob [data-ry-target="ring"].ry-knob__ring--dragging {
cursor: grabbing;
}
ry-knob [data-ry-target="cap"] {
position: absolute;
inset: 0;
transform: rotate(var(--knob-rotation));
}
ry-knob [data-ry-target="indicator"] {
position: absolute;
width: 3px;
height: 10px;
top: 6px;
left: 50%;
margin-left: -1.5px;
}
ry-knob [data-ry-target="display"] {
display: block;
min-width: 3em;
text-align: center;
}
ry-knob [data-ry-target="label"] {
display: block;
text-align: center;
}
/* Sizes */
ry-knob[size="sm"] [data-ry-target="ring"] { --knob-size: 48px; }
ry-knob[size="lg"] [data-ry-target="ring"] { --knob-size: 80px; }
/* ═══════════════════════════════════════════════════════════════
NUMBER SELECT
═══════════════════════════════════════════════════════════════ */
ry-number-select {
display: inline-flex;
align-items: center;
gap: 0;
user-select: none;
touch-action: none;
}
ry-number-select[disabled] {
pointer-events: none;
}
ry-number-select :is([data-ry-target="decrement"], [data-ry-target="increment"]) {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 36px;
padding: 0;
flex-shrink: 0;
cursor: pointer;
}
ry-number-select :is([data-ry-target="decrement"], [data-ry-target="increment"]) svg {
width: 16px;
height: 16px;
}
ry-number-select [data-ry-target="display"] {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 48px;
height: 36px;
padding: 0 var(--ry-space-2, 0.5rem);
position: relative;
cursor: ew-resize;
outline: none;
}
:is(ry-number-select[drag="y"],
ry-number-select[arrows="stacked"]:not([drag]),
ry-number-select[arrows="stacked-end"]:not([drag]),
ry-number-select[arrows="stacked-start"]:not([drag])) [data-ry-target="display"] {
cursor: ns-resize;
}
ry-number-select[drag="none"] [data-ry-target="display"] {
cursor: default;
}
ry-number-select[data-dragging] {
cursor: ew-resize;
}
:is(ry-number-select[drag="y"],
ry-number-select[arrows="stacked"]:not([drag]),
ry-number-select[arrows="stacked-end"]:not([drag]),
ry-number-select[arrows="stacked-start"]:not([drag]))[data-dragging] {
cursor: ns-resize;
}
ry-number-select [data-ry-target="value"] {
display: inline-block;
min-width: 2em;
text-align: center;
transition: transform 60ms ease-out;
}
ry-number-select :is([data-ry-target="prefix"], [data-ry-target="suffix"]) {
flex-shrink: 0;
pointer-events: none;
}
ry-number-select [data-ry-target="input"] {
display: none;
position: absolute;
inset: 0;
width: 100%;
height: 100%;
text-align: center;
padding: 0 var(--ry-space-1, 0.25rem);
outline: none;
}
ry-number-select [data-ry-target="label"] {
display: block;
text-align: center;
margin-inline-end: var(--ry-space-2, 0.5rem);
order: -1;
}
/* Stacked layout (buttons above/below) */
ry-number-select[arrows="stacked"] {
flex-direction: column;
align-items: stretch;
}
ry-number-select[arrows="stacked"] :is([data-ry-target="decrement"], [data-ry-target="increment"]) {
width: auto;
height: 24px;
}
ry-number-select[arrows="stacked"] :is([data-ry-target="decrement"], [data-ry-target="increment"]) svg {
width: 14px;
height: 14px;
}
/* Stacked-end / stacked-start (buttons grouped beside display) */
ry-number-select [data-ry-target="btn-group"] {
display: flex;
flex-direction: column;
flex-shrink: 0;
}
:is(ry-number-select[arrows="stacked-end"], ry-number-select[arrows="stacked-start"]) :is([data-ry-target="decrement"], [data-ry-target="increment"]) {
width: 28px;
height: 18px;
}
:is(ry-number-select[arrows="stacked-end"], ry-number-select[arrows="stacked-start"]) :is([data-ry-target="decrement"], [data-ry-target="increment"]) svg {
width: 12px;
height: 12px;
}
/* Sizes */
ry-number-select[size="xs"] :is([data-ry-target="decrement"], [data-ry-target="increment"]) { width: 20px; height: 22px; }
ry-number-select[size="xs"] [data-ry-target="display"] { min-width: 28px; height: 22px; padding: 0 var(--ry-space-1, 0.25rem); }
ry-number-select[size="xs"] :is([data-ry-target="decrement"], [data-ry-target="increment"]) svg { width: 12px; height: 12px; }
ry-number-select[size="sm"] :is([data-ry-target="decrement"], [data-ry-target="increment"]) { width: 24px; height: 28px; }
ry-number-select[size="sm"] [data-ry-target="display"] { min-width: 36px; height: 28px; }
ry-number-select[size="lg"] :is([data-ry-target="decrement"], [data-ry-target="increment"]) { width: 40px; height: 44px; }
ry-number-select[size="lg"] [data-ry-target="display"] { min-width: 60px; height: 44px; }
/* ═══════════════════════════════════════════════════════════════
SLIDER
═══════════════════════════════════════════════════════════════ */
ry-slider {
display: block;
position: relative;
padding: var(--ry-space-4, 1rem) 0;
touch-action: none;
user-select: none;
}
ry-slider[disabled] {
pointer-events: none;
}
ry-slider [data-ry-target="track"] {
position: relative;
height: var(--ry-slider-track, 14px);
cursor: pointer;
}
ry-slider [data-ry-target="fill"] {
position: absolute;
height: 100%;
}
ry-slider [data-ry-target^="thumb"] {
position: absolute;
width: var(--ry-slider-thumb, 32px);
height: var(--ry-slider-thumb, 32px);
top: 50%;
transform: translate(-50%, -50%);
cursor: grab;
}
ry-slider [data-ry-target^="thumb"]:active {
cursor: grabbing;
}
ry-slider [data-ry-target="labels"] {
display: flex;
justify-content: space-between;
margin-block-start: var(--ry-space-2, 0.5rem);
pointer-events: none;
}
ry-slider [data-ry-target^="tooltip"] {
position: absolute;
bottom: calc(100% + 8px);
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
opacity: 0;
visibility: hidden;
transition: opacity var(--ry-duration-fast, 100ms) var(--ry-ease, ease),
visibility var(--ry-duration-fast, 100ms) var(--ry-ease, ease);
transition-behavior: allow-discrete;
pointer-events: none;
}
:is(ry-slider [data-ry-target^="thumb"]:hover,
ry-slider [data-ry-target^="thumb"]:focus,
ry-slider[data-dragging]) [data-ry-target^="tooltip"] {
opacity: 1;
visibility: visible;
}
@starting-style {
:is(ry-slider [data-ry-target^="thumb"]:hover,
ry-slider [data-ry-target^="thumb"]:focus,
ry-slider[data-dragging]) [data-ry-target^="tooltip"] {
opacity: 0;
}
}
/* Vertical */
ry-slider[vertical] {
display: inline-flex;
width: auto;
height: 200px;
padding: 0 var(--ry-space-4, 1rem);
}
ry-slider[vertical] [data-ry-target="track"] {
width: var(--ry-slider-track, 14px);
height: 100%;
}
ry-slider[vertical] [data-ry-target="fill"] {
width: 100%;
height: auto;
bottom: 0;
left: 0;
}
ry-slider[vertical] [data-ry-target^="thumb"] {
left: 50%;
top: auto;
transform: translate(-50%, 50%);
}
ry-slider[vertical] [data-ry-target="labels"] {
flex-direction: column-reverse;
justify-content: space-between;
height: 100%;
margin-block-start: 0;
margin-inline-start: var(--ry-space-2, 0.5rem);
}
/* Sizes */
ry-slider[size="sm"] { --ry-slider-track: 10px; --ry-slider-thumb: 24px; }
ry-slider[size="lg"] { --ry-slider-track: 18px; --ry-slider-thumb: 40px; }
/* ═══════════════════════════════════════════════════════════════
CARDS
═══════════════════════════════════════════════════════════════ */
ry-card {
display: block;
padding: var(--ry-space-6, 1.5rem);
container-type: inline-size;
}
:is(a, [interactive]):is(ry-card) {
cursor: pointer;
transition: transform var(--ry-duration-normal, 200ms) var(--ry-ease, ease);
}
:is(a, [interactive]):is(ry-card):hover {
transform: translateY(-1px);
}
:is(a, [interactive]):is(ry-card):active {
transform: translateY(0);
}
ry-card h3 {
margin: 0 0 var(--ry-space-2, 0.5rem) 0;
}
ry-card p {
margin: 0 0 var(--ry-space-4, 1rem) 0;
}
ry-card p:last-child {
margin-bottom: 0;
}
ry-card > img:first-child {
display: block;
width: 100%;
margin-bottom: var(--ry-space-4, 1rem);
}
/* ═══════════════════════════════════════════════════════════════
BADGES
═══════════════════════════════════════════════════════════════ */
ry-badge {
display: inline-flex;
align-items: center;
padding: var(--ry-space-1, 0.25rem) var(--ry-space-2, 0.5rem);
line-height: 1;
}
/* ═══════════════════════════════════════════════════════════════
ALERTS
═══════════════════════════════════════════════════════════════ */
ry-alert {
display: flex;
gap: var(--ry-space-3, 0.75rem);
padding: var(--ry-space-4, 1rem);
}
.ry-alert__title {
margin: 0 0 var(--ry-space-1, 0.25rem) 0;
}
ry-alert p,
ry-alert [data-ry-target="content"] {
margin: 0;
}
/* ═══════════════════════════════════════════════════════════════
FORM ELEMENTS
═══════════════════════════════════════════════════════════════ */
ry-field :is(input, textarea, select) {
display: block;
width: 100%;
padding: var(--ry-space-2, 0.5rem) var(--ry-space-3, 0.75rem);
}
ry-field :is(input, textarea):disabled {
cursor: not-allowed;
}
ry-field :is(label, [data-ry-target="label"]) {
display: block;
margin-block-end: var(--ry-space-2, 0.5rem);
}
ry-field {
display: block;
margin-block-end: var(--ry-space-4, 1rem);
}
ry-field [data-ry-target="error"]:empty,
ry-field [data-ry-target="hint"]:empty {
display: none;
}
ry-field [data-ry-target="error"]:not(:empty) ~ [data-ry-target="hint"] {
display: none;
}
ry-field :is([data-ry-target="error"], [data-ry-target="hint"]) {
margin-block-start: var(--ry-space-1, 0.25rem);
}
/* ═══════════════════════════════════════════════════════════════
ACCORDION
═══════════════════════════════════════════════════════════════ */
ry-accordion {
overflow: hidden;
}
ry-accordion [data-ry-target="trigger"] {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: var(--ry-space-4, 1rem) var(--ry-space-6, 1.5rem);
text-align: start;
border: none;
cursor: pointer;
}
ry-accordion [data-ry-target="icon"] {
flex-shrink: 0;
transition: transform var(--ry-duration-normal, 200ms) var(--ry-ease, ease);
}
ry-accordion [data-ry-target="item"][data-ry-state="open"] [data-ry-target="icon"] {
transform: rotate(180deg);
}
ry-accordion [data-ry-target="panel"] {
overflow: hidden;
}
ry-accordion [data-ry-target="item"][data-ry-state="closed"] [data-ry-target="panel"] {
display: none;
}
ry-accordion [data-ry-target="panel"] > * {
padding: var(--ry-space-4, 1rem) var(--ry-space-6, 1.5rem);
}
/* ═══════════════════════════════════════════════════════════════
TABS
═══════════════════════════════════════════════════════════════ */
ry-tabs {
display: block;
}
ry-tabs [data-ry-target="list"] {
display: flex;
gap: var(--ry-space-1, 0.25rem);
margin-block-end: var(--ry-space-4, 1rem);
}
ry-tabs [data-ry-target="trigger"] {
padding: var(--ry-space-2, 0.5rem) var(--ry-space-4, 1rem);
border: none;
border-block-end: 2px solid transparent;
margin-block-end: -1px;
cursor: pointer;
}
ry-tabs [data-ry-target="panel"],
ry-tab {
display: none;
}
:is(ry-tabs [data-ry-target="panel"][data-ry-state="active"],
ry-tab[active],
ry-tab[data-ry-state="active"]) {
display: block;
}
ry-tabs:not(:defined) ry-tab:first-of-type {
display: block;
}
/* ═══════════════════════════════════════════════════════════════
MODAL
═══════════════════════════════════════════════════════════════ */
ry-modal {
display: contents;
}
ry-modal [data-ry-target="backdrop"] {
position: fixed;
inset: 0;
z-index: var(--ry-z-modal-backdrop, 1040);
opacity: 0;
visibility: hidden;
transition: opacity var(--ry-duration-normal, 200ms) var(--ry-ease, ease),
visibility var(--ry-duration-normal, 200ms) var(--ry-ease, ease);
transition-behavior: allow-discrete;
}
ry-modal[data-ry-state="open"] [data-ry-target="backdrop"] {
opacity: 1;
visibility: visible;
}
@starting-style {
ry-modal[data-ry-state="open"] [data-ry-target="backdrop"] {
opacity: 0;
}
}
ry-modal [data-ry-target="dialog"] {
position: fixed;
top: 50%;
left: 50%;
z-index: var(--ry-z-modal, 1050);
width: 100%;
max-width: 32rem;
max-height: calc(100vh - var(--ry-space-8, 2rem));
overflow: auto;
overscroll-behavior: contain;
opacity: 0;
visibility: hidden;
transform: translate(-50%, -50%) scale(0.95);
transition: opacity var(--ry-duration-normal, 200ms) var(--ry-ease, ease),
visibility var(--ry-duration-normal, 200ms) var(--ry-ease, ease),
transform var(--ry-duration-normal, 200ms) var(--ry-ease, ease);
transition-behavior: allow-discrete;
}
ry-modal[data-ry-state="open"] [data-ry-target="dialog"] {
opacity: 1;
visibility: visible;
transform: translate(-50%, -50%) scale(1);
}
@starting-style {
ry-modal[data-ry-state="open"] [data-ry-target="dialog"] {
opacity: 0;
transform: translate(-50%, -50%) scale(0.95);
}
}
ry-modal [data-ry-target="header"] {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--ry-space-4, 1rem) var(--ry-space-6, 1.5rem);
}
ry-modal [data-ry-target="header"] h3 {
margin: 0;
}
ry-modal [data-ry-target="close"] {
display: flex;
align-items: center;
justify-content: center;
width: 2rem;
height: 2rem;
padding: 0;
border: none;
cursor: pointer;
}
ry-modal [data-ry-target="body"] {
padding: var(--ry-space-6, 1.5rem);
}
ry-modal [data-ry-target="footer"] {
display: flex;
justify-content: flex-end;
gap: var(--ry-space-3, 0.75rem);
padding: var(--ry-space-4, 1rem) var(--ry-space-6, 1.5rem);
}
/* ═══════════════════════════════════════════════════════════════
DROPDOWN
═══════════════════════════════════════════════════════════════ */
ry-dropdown {
position: relative;
display: inline-block;
}
ry-dropdown :is([data-ry-target="menu"], ry-menu) {
position: absolute;
top: 100%;
left: 0;
z-index: var(--ry-z-dropdown, 1000);
min-width: 12rem;
margin-block-start: var(--ry-space-1, 0.25rem);
padding: var(--ry-space-1, 0.25rem);
opacity: 0;
visibility: hidden;
transform: translateY(-0.5rem);
transition: opacity var(--ry-duration-fast, 100ms) var(--ry-ease, ease),
visibility var(--ry-duration-fast, 100ms) var(--ry-ease, ease),
transform var(--ry-duration-fast, 100ms) var(--ry-ease, ease);
transition-behavior: allow-discrete;
}
ry-dropdown[data-ry-state="open"] :is([data-ry-target="menu"], ry-menu) {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
@starting-style {
ry-dropdown[data-ry-state="open"] :is([data-ry-target="menu"], ry-menu) {
opacity: 0;
transform: translateY(-0.5rem);
}
}
ry-dropdown[data-ry-position="top"] :is([data-ry-target="menu"], ry-menu) {
top: auto;
bottom: 100%;
margin-block-start: 0;
margin-block-end: var(--ry-space-1, 0.25rem);
transform: translateY(0.5rem);
}
ry-dropdown[data-ry-position="top"][data-ry-state="open"] :is([data-ry-target="menu"], ry-menu) {
transform: translateY(0);
}
ry-menu-item {
display: block;
width: 100%;
padding: var(--ry-space-2, 0.5rem) var(--ry-space-3, 0.75rem);
text-align: start;
text-decoration: none;
border: none;
cursor: pointer;
}
/* ═══════════════════════════════════════════════════════════════
SWITCH
═══════════════════════════════════════════════════════════════ */
ry-switch {
display: inline-flex;
align-items: center;
gap: var(--ry-space-3, 0.75rem);
cursor: pointer;
user-select: none;
}
ry-switch[disabled] {
cursor: not-allowed;
}
ry-switch [data-ry-target="track"] {
position: relative;
display: inline-flex;
width: 2.75rem;
height: 1.5rem;
flex-shrink: 0;
}
ry-switch [data-ry-target="thumb"] {
position: absolute;
top: 2px;
left: 2px;
width: 1.125rem;
height: 1.125rem;
transition: transform var(--ry-duration-fast, 100ms) var(--ry-ease, ease);
}
ry-switch[checked] [data-ry-target="thumb"] {
transform: translateX(1.25rem);
}
ry-switch [data-ry-target="input"] {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
ry-switch:focus-visible {
outline: none;
}
/* ═══════════════════════════════════════════════════════════════
TOOLTIP
═══════════════════════════════════════════════════════════════ */
ry-tooltip {
position: relative;
display: inline-block;
}
ry-tooltip [data-ry-target="content"] {
position: absolute;
z-index: var(--ry-z-tooltip, 1070);
padding: var(--ry-space-2, 0.5rem) var(--ry-space-3, 0.75rem);
white-space: nowrap;
opacity: 0;
visibility: hidden;
pointer-events: none;
transition: opacity var(--ry-duration-fast, 100ms) var(--ry-ease, ease),
visibility var(--ry-duration-fast, 100ms) var(--ry-ease, ease);
transition-behavior: allow-discrete;
}
ry-tooltip[data-ry-state="open"] [data-ry-target="content"] {
opacity: 1;
visibility: visible;
}
@starting-style {
ry-tooltip[data-ry-state="open"] [data-ry-target="content"] {
opacity: 0;
}
}
/* Tooltip positioning - CSS handles all layout, no JS needed */
ry-tooltip[data-ry-position="top"] [data-ry-target="content"] {
bottom: 100%;
left: 50%;
transform: translateX(-50%);
margin-bottom: var(--ry-space-2, 0.5rem);
}
ry-tooltip[data-ry-position="bottom"] [data-ry-target="content"] {
top: 100%;
left: 50%;
transform: translateX(-50%);
margin-top: var(--ry-space-2, 0.5rem);
}
ry-tooltip[data-ry-position="left"] [data-ry-target="content"] {
right: 100%;
top: 50%;
transform: translateY(-50%);
margin-r