import { css } from 'lit'; /** * Shared host styles every component pulls in. Sets default font, color, * container query support, and the entry fade-in. */ export const baseStyles = css` :host { display: block; container-type: inline-size; font-family: var( --roxy-font-sans, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif ); color: var(--roxy-fg, #0a0a0a); background: transparent; font-size: var(--roxy-text-base, 1rem); line-height: var(--roxy-leading-normal, 1.5); animation: roxy-fade-in var(--roxy-motion-duration, 200ms) var(--roxy-motion-easing, cubic-bezier(0.4, 0, 0.2, 1)) both; } /** * Opt out of the component's own card surface. When the embedder already * wraps the component in their own card, set the \`bare\` attribute to drop * the painted background + shadow so there is no nested card chrome. The * inner border stays a hairline; override --roxy-border to remove it too. */ :host([bare]) { --roxy-surface: transparent; --roxy-shadow-sm: none; --roxy-shadow-md: none; } *, *::before, *::after { box-sizing: border-box; } @keyframes roxy-fade-in { from { opacity: 0; transform: translateY(2px); } to { opacity: 1; transform: translateY(0); } } @media (prefers-reduced-motion: reduce) { :host { animation: none; } } .roxy-skeleton { background: linear-gradient( 90deg, var(--roxy-border, #e4e4e7) 0%, color-mix(in srgb, var(--roxy-border, #e4e4e7) 60%, transparent) 50%, var(--roxy-border, #e4e4e7) 100% ); background-size: 200% 100%; animation: roxy-shimmer 1.4s ease-in-out infinite; border-radius: var(--roxy-radius-md, 8px); } @keyframes roxy-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } @media (prefers-reduced-motion: reduce) { .roxy-skeleton { animation: none; } } .roxy-empty { padding: var(--roxy-space-lg, 1.5rem); color: var(--roxy-muted, #71717a); text-align: center; font-size: var(--roxy-text-sm, 0.875rem); } .roxy-error { display: grid; gap: var(--roxy-space-sm, 0.5rem); justify-items: start; padding: var(--roxy-space-lg, 1.5rem); background: var(--roxy-surface, #fff); border: 1px solid var(--roxy-danger, #dc2626); border-radius: var(--roxy-radius-md, 8px); color: var(--roxy-danger-fg, #991b1b); font-size: var(--roxy-text-sm, 0.875rem); } /* Opt-in component backdrop. A component that paints content directly (table, * grid, prose) adds this to its root so it sits on an owned, theme-aware * surface rather than inheriting the page background, which may not match the * resolved token theme and would render text on a same-tone background. */ .roxy-surface { background: var(--roxy-surface, #fff); color: var(--roxy-fg, #0a0a0a); } :host(:focus-within) .roxy-card { outline: 2px solid var(--roxy-ring, rgba(245, 158, 11, 0.4)); outline-offset: 2px; } /* Force the text-style variant on every Unicode glyph in the component. * macOS and iOS substitute coloured emoji glyphs for the planetary and * gender Unicode code points (Mars, Venus, Mercury, etc.) when the * system colour-emoji font wins font selection. The text-style variant * keeps glyphs monochrome so they inherit the surrounding fill colour * and match the brand palette consistently across platforms. * * font-variant-emoji is part of CSS Fonts 4 (Safari 17+, Chrome 134+, * Firefox 139+). On older browsers the rule is silently ignored. */ :host { font-variant-emoji: text; } `;