| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- /*
- * 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;
- }
- }
|