feat: add Cosmic theme + motion system

This commit is contained in:
Avi 2026-08-31 00:35:30 -05:00
commit 76deca6a7f
4 changed files with 327 additions and 4 deletions

View file

@ -1,4 +1,4 @@
export type Theme = 'light' | 'dark' | 'glass' | 'neon' | 'impeccable' | 'impeccable-dark';
export type Theme = 'light' | 'dark' | 'glass' | 'neon' | 'impeccable' | 'impeccable-dark' | 'cosmic';
/** Lifecycle of the NIP-46 remote signer. */
export type SignerPhase = 'stopped' | 'connecting' | 'connected';

View file

@ -108,6 +108,7 @@ export function SettingsScreen() {
<option value="neon">Neon</option>
<option value="impeccable">Impeccable — Light</option>
<option value="impeccable-dark">Impeccable — Dark</option>
<option value="cosmic">Cosmic — Stardust</option>
</select>
<div
aria-hidden="true"
@ -179,12 +180,14 @@ export function SettingsScreen() {
? 'Aurora — frosted glass, cyan'
: settings.theme === 'dark'
? 'Dark — deep ink'
: 'Light — warm paper'}
: settings.theme === 'cosmic'
? 'Cosmic — deep space, golden stardust'
: 'Light — warm paper'}
</span>
</div>
<p className="hint">
“Light” and “Dark” follow your manual selection. “Aurora”, “Neon”, “Impeccable” and
“Impeccable Dark” are aesthetic themes with distinctive color palettes.
"Light" and "Dark" follow your manual selection. "Aurora", "Neon", "Impeccable",
"Impeccable Dark", and "Cosmic" are aesthetic themes with distinctive color palettes.
</p>
</div>
</div>

View file

@ -348,6 +348,230 @@ html[data-theme='impeccable-dark'] .sidebar {
border-right-color: var(--border);
}
/* "Cosmic" — Stardust color scheme from https://github.com/kaymade/cosmic
Deep space backgrounds with warm golden accents.
Fonts: Source Serif 4 for body, Cormorant Garamond for headings.
Sidebar: Deep (darker background). Workspace: Deep Space (dramatic vignette). */
@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Source+Serif+4:ital,opsz,wght@0,8..60,400;0,8..60,500;0,8..60,600;0,8..60,700;1,8..60,400;1,8..60,500;1,8..60,600;1,8..60,700&display=swap');
:root[data-theme='cosmic'] {
/* Stardust dark mode colors */
--bg: #171109;
--surface: #0d0a06;
--surface-2: #21180c;
--surface-hover: #140f08;
--border: #2d2418;
--border-strong: #3d3220;
--text: #fff5dc;
--text-muted: #d5bd8d;
--primary: #efbd62;
--primary-hover: #ffdb91;
--primary-soft: rgba(239, 189, 98, 0.15);
--on-primary: #171109;
--danger: #f08e7d;
--danger-soft: rgba(240, 142, 125, 0.15);
--warning: #f08e7d;
--warning-soft: rgba(240, 142, 125, 0.15);
--success: #74d7cb;
--success-soft: rgba(116, 215, 203, 0.15);
--info: #74d7cb;
--info-soft: rgba(116, 215, 203, 0.15);
--focus: #efbd62;
--shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
--shadow-modal: 0 12px 40px rgba(0, 0, 0, 0.6);
--radius: 8px;
--radius-sm: 4px;
color-scheme: dark;
}
/* Cosmic typography - Cormorant Garamond for headings, Source Serif 4 for body */
html[data-theme='cosmic'] body {
font-family: 'Source Serif 4', 'Georgia', serif;
font-size: 15px;
line-height: 1.6;
}
html[data-theme='cosmic'] h1,
html[data-theme='cosmic'] h2,
html[data-theme='cosmic'] h3,
html[data-theme='cosmic'] h4 {
font-family: 'Cormorant Garamond', 'Georgia', serif;
font-weight: 600;
letter-spacing: 0.02em;
}
html[data-theme='cosmic'] h1 {
font-size: 28px;
color: #efbd62;
}
html[data-theme='cosmic'] h2 {
font-size: 20px;
color: #74d7cb;
}
html[data-theme='cosmic'] h3 {
font-size: 18px;
color: #f08e7d;
}
/* Cosmic sidebar - Deep background (darker) */
html[data-theme='cosmic'] .sidebar {
background: #0d0a06;
border-right-color: var(--border);
}
/* Cosmic workspace - Deep Space background with vignette effect */
html[data-theme='cosmic'] .app-shell {
background:
radial-gradient(circle at 8% 13%, rgba(255, 245, 220, 0.72) 0 1px, transparent 1.7px),
radial-gradient(circle at 27% 7%, rgba(116, 215, 203, 0.82) 0 1px, transparent 1.8px),
radial-gradient(circle at 73% 19%, rgba(255, 245, 220, 0.68) 0 1.2px, transparent 1.9px),
radial-gradient(circle at 91% 42%, rgba(240, 142, 125, 0.78) 0 1px, transparent 1.8px),
radial-gradient(circle at 61% 78%, rgba(255, 245, 220, 0.64) 0 1px, transparent 1.7px),
radial-gradient(circle at 18% 84%, rgba(239, 189, 98, 0.82) 0 1.2px, transparent 2px),
radial-gradient(circle at 12% 4%, rgba(239, 189, 98, 0.52), transparent 58rem),
radial-gradient(circle at 88% 12%, rgba(116, 215, 203, 0.42), transparent 46rem),
radial-gradient(circle at 52% 100%, rgba(240, 142, 125, 0.36), transparent 50rem),
radial-gradient(ellipse at center, transparent 34%, rgba(13, 10, 6, 0.48) 100%),
linear-gradient(145deg, #171109, #0d0a06);
}
html[data-theme='cosmic'] .main {
background: transparent;
}
/* Cosmic cards and surfaces */
html[data-theme='cosmic'] .card,
html[data-theme='cosmic'] .profile-card,
html[data-theme='cosmic'] .relay-row {
background: var(--surface);
border-color: var(--border);
box-shadow: var(--shadow);
}
html[data-theme='cosmic'] .card:hover,
html[data-theme='cosmic'] .profile-card:hover {
border-color: var(--primary);
}
/* Cosmic buttons */
html[data-theme='cosmic'] .btn-primary {
background: var(--primary);
color: var(--on-primary);
}
html[data-theme='cosmic'] .btn-primary:hover:not(:disabled) {
background: var(--primary-hover);
}
html[data-theme='cosmic'] .btn-secondary {
background: var(--surface);
border-color: var(--border-strong);
color: var(--text);
}
html[data-theme='cosmic'] .btn-ghost {
color: var(--text-muted);
}
html[data-theme='cosmic'] .btn-ghost:hover {
background: var(--surface-2);
color: var(--text);
}
/* Cosmic navigation */
html[data-theme='cosmic'] .nav-item {
color: var(--text-muted);
}
html[data-theme='cosmic'] .nav-item:hover {
background: var(--surface-2);
color: var(--text);
}
html[data-theme='cosmic'] .nav-item.is-active {
background: var(--primary-soft);
color: var(--primary);
}
/* Cosmic inputs */
html[data-theme='cosmic'] input[type='text'],
html[data-theme='cosmic'] input[type='search'],
html[data-theme='cosmic'] input[type='password'],
html[data-theme='cosmic'] select,
html[data-theme='cosmic'] textarea {
background: var(--surface);
border-color: var(--border-strong);
color: var(--text);
}
html[data-theme='cosmic'] input:focus,
html[data-theme='cosmic'] select:focus,
html[data-theme='cosmic'] textarea:focus {
border-color: var(--focus);
box-shadow: 0 0 0 2px var(--primary-soft);
}
/* Cosmic code blocks */
html[data-theme='cosmic'] code,
html[data-theme='cosmic'] .mono {
background: var(--surface-2);
border-color: var(--border);
color: var(--primary);
}
/* Cosmic badges */
html[data-theme='cosmic'] .badge {
border-radius: 4px;
font-size: 11px;
font-weight: 600;
}
html[data-theme='cosmic'] .badge-neutral {
background: var(--surface-2);
color: var(--text-muted);
border-color: var(--border);
}
html[data-theme='cosmic'] .badge-success {
background: var(--success-soft);
color: var(--success);
}
html[data-theme='cosmic'] .badge-warning {
background: var(--warning-soft);
color: var(--warning);
}
html[data-theme='cosmic'] .badge-danger {
background: var(--danger-soft);
color: var(--danger);
}
html[data-theme='cosmic'] .badge-info {
background: var(--info-soft);
color: var(--info);
}
/* Cosmic modal */
html[data-theme='cosmic'] .modal {
background: var(--surface);
border-color: var(--border);
box-shadow: var(--shadow-modal);
}
html[data-theme='cosmic'] .modal-backdrop {
background: rgba(13, 10, 6, 0.8);
}
/* Cosmic empty state */
html[data-theme='cosmic'] .empty-state {
background: var(--surface);
border-color: var(--border);
}
* {
box-sizing: border-box;
}
@ -1944,3 +2168,97 @@ select {
align-items: flex-start;
gap: 12px;
}
/* -------------------------------------------------------------------------
Motion system
Purposeful motion for feedback, state, and continuity.
------------------------------------------------------------------------- */
@keyframes modal-enter {
from {
opacity: 0;
transform: scale(0.96) translateY(8px);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
@keyframes modal-backdrop-enter {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes alert-enter {
from {
opacity: 0;
transform: translateY(-6px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes undo-enter {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.modal-backdrop {
animation: modal-backdrop-enter 200ms cubic-bezier(0.16, 1, 0.3, 1);
}
.modal {
animation: modal-enter 220ms cubic-bezier(0.16, 1, 0.3, 1);
}
.alert {
animation: alert-enter 200ms cubic-bezier(0.16, 1, 0.3, 1);
}
.undo-bar {
animation: undo-enter 250ms cubic-bezier(0.16, 1, 0.3, 1);
}
.btn:active:not(:disabled) {
transform: scale(0.97);
transition: transform 80ms ease;
}
.profile-card:active:not(.is-active) {
transform: scale(0.985);
transition: transform 100ms ease;
}
.nav-item:active {
transform: scale(0.98);
transition: transform 80ms ease;
}
@media (prefers-reduced-motion: reduce) {
.modal-backdrop,
.modal,
.alert,
.undo-bar {
animation: none;
}
.btn:active:not(:disabled),
.profile-card:active:not(.is-active),
.nav-item:active {
transform: none;
transition: none;
}
}