/* * Spry CSS theme: "modern" * ------------------------ * Contemporary premium design system — Linear/Vercel/Stripe register. * Signatures: mono micro-labels (h6/badges/table heads/hints), filled * gray input wells that bloom white on focus, flat hairline cards that * lift on hover, borderless tables with row dividers, left-accent-bar * alerts, and a sheen + soft glow primary button. * Light-only: color-scheme stays light and the user's dark preference is ignored. */ [data-theme="modern"], html:has(#spry-theme-modern:checked) { color-scheme: light; /* ---- Palette (soft tints & alert washes derive automatically) ---- */ --spry-bg: #fafafa; /* near-white page */ --spry-bg-alt: #f4f4f5; /* alternate bands, hovers */ --spry-bg-inset: #efeff2; /* wells: code blocks, disabled fills, tracks */ --spry-surface: #ffffff; /* cards, popovers, inputs on focus */ --spry-surface-hover: #fafafa; --spry-fg: #18181b; /* near-black text */ --spry-fg-muted: #52525b; /* secondary text (AA on bg) */ --spry-border: #e4e4e7; /* hairlines */ --spry-border-strong: #d4d4d8; /* hover borders, kbd, switch track */ --spry-accent: #5b5bd6; /* vivid indigo */ --spry-accent-hover: #4949c3; --spry-accent-fg: #ffffff; /* 5.4:1 on accent */ --spry-danger: #d92d20; --spry-success: #15803d; --spry-warning: #a16207; --spry-info: #0369a1; --spry-backdrop: rgb(24 24 27 / 0.35); --spry-link: var(--spry-accent); --spry-link-hover: var(--spry-accent-hover); /* Soft halo rings — solid-accent borders/underlines carry the 3:1 contrast */ --spry-focus-ring: 0 0 0 2px color-mix(in srgb, var(--spry-accent) 40%, transparent); /* ---- Typography ---- */ --spry-font: Inter, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --spry-font-heading: var(--spry-font); --spry-font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; --spry-font-size: 1rem; --spry-line-height: 1.6; --spry-heading-weight: 650; /* ---- Shape, depth, motion: 8px controls / 12px cards / 16px overlays ---- */ --spry-radius: 0.75rem; /* cards, btn-lg */ --spry-radius-sm: 0.5rem; /* buttons, inputs, alerts */ --spry-radius-lg: 1rem; /* dialogs, popovers */ --spry-radius-pill: 999px; --spry-border-width: 1px; --spry-shadow: 0 2px 4px rgb(24 24 27 / 0.04), 0 8px 24px -8px rgb(24 24 27 / 0.08); --spry-shadow-lg: 0 8px 20px -6px rgb(24 24 27 / 0.12), 0 20px 48px -12px rgb(24 24 27 / 0.16); --spry-glass: none; --spry-transition: 150ms cubic-bezier(0.25, 0.6, 0.35, 1); --spry-dialog-duration: 180ms; --spry-dialog-ease: cubic-bezier(0.2, 0.9, 0.3, 1); --spry-dialog-in: translateY(0.5rem) scale(0.98); /* ---- Controls: filled gray wells, no border until hover/focus ---- */ --spry-control-bg: #f4f4f5; --spry-control-fg: var(--spry-fg); --spry-control-border: transparent; --spry-control-radius: var(--spry-radius-sm); --spry-control-padding-x: 0.7rem; --spry-control-padding-y: 0.5rem; /* ---- Buttons ---- */ --spry-btn-bg: var(--spry-surface); --spry-btn-fg: var(--spry-fg); --spry-btn-border: var(--spry-border); --spry-btn-bg-hover: var(--spry-bg-alt); --spry-btn-bg-active: var(--spry-bg-inset); /* ---- Cards / tables / progress / popovers ---- */ --spry-card-bg: var(--spry-surface); --spry-card-border: var(--spry-border); --spry-card-padding: 1.5rem; --spry-card-shadow: none; /* flat at rest, lift on hover */ --spry-table-header-bg: transparent; /* airy headerless-column look */ --spry-table-hover: var(--spry-bg-alt); --spry-progress-bg: var(--spry-bg-inset); --spry-progress-fg: var(--spry-accent); --spry-popover-bg: var(--spry-surface); --spry-popover-border: var(--spry-border); --spry-popover-shadow: var(--spry-shadow-lg); /* ---- Structural overrides (nested, active only under this scope) ---- */ /* Barely-there dot-grid texture — the "modern dev tool" page floor */ & body { background: radial-gradient(rgb(24 24 27 / 0.04) 1px, transparent 1px) 0 0 / 24px 24px, var(--spry-bg); } /* Tight display-type tracking for the marketing-page look */ & :where(h1, h2, h3, .h1, .h2, .h3) { letter-spacing: -0.022em; } /* Signature: mono micro-labels */ & :where(h6, .h6) { font-family: var(--spry-font-mono); letter-spacing: 0.09em; } & .badge { font-family: var(--spry-font-mono); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 550; padding: 0.15em 0.7em; } & .hint { font-family: var(--spry-font-mono); font-size: 0.8em; } /* Global soft focus halo (inputs keep their own ring via the core) */ & :where(:focus-visible) { outline: 3px solid color-mix(in srgb, var(--spry-accent) 35%, transparent); outline-offset: 2px; } /* Buttons: shared motion incl. transform */ & .btn { transition: background-color var(--spry-transition), border-color var(--spry-transition), color var(--spry-transition), box-shadow var(--spry-transition), transform var(--spry-transition); } & .btn:not(.btn-ghost):not(.btn-link):hover { transform: translateY(-1px); } & .btn:not(.btn-ghost):not(.btn-link):active { transform: translateY(0); } /* Primary: hairline top sheen + accent glow that deepens on hover */ & .btn-primary { box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.2), 0 1px 2px color-mix(in srgb, var(--spry-accent) 30%, transparent); } & .btn-primary:hover { box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.22), 0 2px 4px color-mix(in srgb, var(--spry-accent) 32%, transparent), 0 8px 20px -6px color-mix(in srgb, var(--spry-accent) 45%, transparent); } & .btn-primary:active { box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.12); } /* Ghost buttons gain a hairline frame on hover */ & .btn-ghost:hover { border-color: var(--spry-border); } /* Inputs: filled wells turn white + ring on focus (ring/border via core) */ & :where(input, select, textarea) { transition: background-color var(--spry-transition), border-color var(--spry-transition), box-shadow var(--spry-transition); } & :where(input[type="text"], input[type="email"], input[type="password"], input[type="number"], input[type="search"], input[type="tel"], input[type="url"], input[type="date"], input[type="time"], input[type="datetime-local"], input[type="month"], input[type="week"], select, textarea, .input):focus:not([readonly]) { background: var(--spry-surface); } /* Cards: flat hairline at rest, soft lift on hover */ & .card { transition: transform var(--spry-transition), box-shadow var(--spry-transition), border-color var(--spry-transition); } & .card:not(.card-flat):hover { transform: translateY(-2px); border-color: var(--spry-border-strong); box-shadow: 0 4px 12px -2px rgb(24 24 27 / 0.06), 0 12px 32px -12px rgb(24 24 27 / 0.12); } & :where(.card-header, .card-footer) { background: transparent; } /* Tables: no frame, hairline row dividers, mono column heads */ & :where(table) { border: 0; } & :where(thead th) { font-family: var(--spry-font-mono); font-size: 0.72em; letter-spacing: 0.08em; border-bottom: var(--spry-border-width) solid var(--spry-border-strong); } /* Alerts: soft wash + colored inset edge instead of a full frame */ & :where(.alert) { border: 0; border-radius: var(--spry-radius-sm); box-shadow: inset 2px 0 0 var(--spry-border-strong); } & .alert-danger { box-shadow: inset 2px 0 0 var(--spry-danger); color: #b3180e; } & .alert-success { box-shadow: inset 2px 0 0 var(--spry-success); color: #0f7a34; } & .alert-warning { box-shadow: inset 2px 0 0 var(--spry-warning); color: #855600; } & .alert-info { box-shadow: inset 2px 0 0 var(--spry-info); color: #075e94; } & .nav a.active { color: #4343c5; } & .badge { color: #4343c5; } & .hero-eyebrow { color: #4343c5; } /* Dialogs: minimal titlebar (bold text + hairline), circular close */ & .dialog-titlebar { background: transparent; border-bottom: var(--spry-border-width) solid var(--spry-border); } & .dialog-title { font-size: 1rem; } & .dialog-close { border-radius: var(--spry-radius-pill); } & .dialog-footer { background: transparent; } /* Switch: slightly larger, floating white knob */ & .switch .track { width: 2.75rem; height: 1.5rem; } & .switch .track::after { top: 0.2rem; left: 0.2rem; width: 1.1rem; height: 1.1rem; box-shadow: 0 1px 3px rgb(24 24 27 / 0.3), 0 0 0 1px rgb(24 24 27 / 0.05); } & .switch input:checked + .track::after { translate: 1.25rem 0; } /* Slim progress bars */ & progress { height: 0.45rem; } /* Indeterminate: theme-explicit so it can never be shadowed */ & progress:indeterminate { /* cap = half the slim 0.45rem bar */ --spry-pulse-cap: 0.23em; background: radial-gradient(var(--spry-pulse-cap) var(--spry-pulse-cap) at var(--spry-pulse-cap) 50%, var(--spry-accent) 97%, transparent 100%) 0% 50% / 25% 100% no-repeat, radial-gradient(var(--spry-pulse-cap) var(--spry-pulse-cap) at calc(100% - var(--spry-pulse-cap)) 50%, var(--spry-accent) 97%, transparent 100%) 0% 50% / 25% 100% no-repeat, linear-gradient(90deg, transparent 0 var(--spry-pulse-cap), var(--spry-accent) var(--spry-pulse-cap) calc(100% - var(--spry-pulse-cap)), transparent calc(100% - var(--spry-pulse-cap))) 0% 50% / 25% 100% no-repeat, var(--spry-bg-inset); animation: spry-pulse 1.4s linear infinite alternate; } }