@import "tailwindcss"; /* ─────────────────────────────────────────────────────────────── muse design system The accent is the ARTWORK. --a-r/g/b hold the dominant colour sampled from whatever album is on screen; every tinted surface derives from them, so the page takes on the palette of the music instead of a fixed brand colour. JS writes those three numbers and nothing else. ─────────────────────────────────────────────────────────────── */ @theme inline { --color-accent: rgb(var(--a-r) var(--a-g) var(--a-b)); --color-accent-soft: rgb(var(--a-r) var(--a-g) var(--a-b) / 0.16); --color-accent-line: rgb(var(--a-r) var(--a-g) var(--a-b) / 0.4); --color-ink: var(--fg); --color-dim: var(--dim); --color-edge: var(--edge); --color-edge-hi: var(--edge-hi); --color-faint: var(--faint); --color-ok: var(--ok); --color-err: var(--err); --color-warn: var(--warn); --radius-glass: 14px; --radius-panel: 28px; --radius-control: 11px; --radius-pill: 999px; --ease-glass: cubic-bezier(0.22, 0.9, 0.28, 1); /* Apple's motion reads as weight, not duration: things overshoot slightly and settle. A single shared curve keeps unrelated components feeling like one physical system. */ --ease-spring: linear( 0, 0.006, 0.025, 0.101, 0.539, 0.721, 0.849, 0.937, 0.968, 0.991, 1 ); --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", ui-sans-serif, system-ui, "Segoe UI", Roboto, sans-serif; --font-display: -apple-system, BlinkMacSystemFont, "SF Pro Display", ui-sans-serif, system-ui, "Segoe UI", Roboto, sans-serif; --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace; /* Type scale. The defining trait of Apple's typography is that tracking tightens as size grows — display text at default tracking looks loose and amateurish, and small text at display tracking looks cramped. */ --text-display: 2.125rem; --text-display--line-height: 1.08; --text-display--letter-spacing: -0.033em; --text-display--font-weight: 700; --text-title: 1.4375rem; --text-title--line-height: 1.18; --text-title--letter-spacing: -0.024em; --text-title--font-weight: 700; --text-headline: 1.0625rem; --text-headline--line-height: 1.35; --text-headline--letter-spacing: -0.014em; --text-headline--font-weight: 600; --text-body: 0.9375rem; --text-body--line-height: 1.5; --text-body--letter-spacing: -0.008em; --text-callout: 0.8125rem; --text-callout--line-height: 1.45; --text-callout--letter-spacing: -0.003em; --text-caption: 0.6875rem; --text-caption--line-height: 1.35; --text-caption--letter-spacing: 0.005em; } :root { --a-r: 120; --a-g: 140; --a-b: 255; --bg: #08090d; --fg: #f2f4f9; --dim: #9aa3b6; --faint: rgb(255 255 255 / 0.07); --glass: rgb(255 255 255 / 0.055); --glass-hi: rgb(255 255 255 / 0.085); --edge: rgb(255 255 255 / 0.1); --edge-hi: rgb(255 255 255 / 0.17); --sheet: rgb(16 18 26 / 0.86); --header: rgb(8 9 13 / 0.62); --scrim: rgb(8 9 13 / 0.74); --scrim-2: rgb(8 9 13 / 0.4); --blur: saturate(180%) blur(24px); --shadow: 0 10px 40px rgb(0 0 0 / 0.45); /* Semantic colours are per-theme, not fixed. These are tuned to sit on the dark background; the same amber on white fails contrast outright, which is exactly the text a reviewer most needs to read. */ --ok: #3ddc84; --err: #ff6b6b; --warn: #ffc95c; /* The specular edge. A real frosted panel catches light along its top rim; without this, blur alone reads as a flat grey rectangle. This one line is most of the difference between "translucent" and "material". */ --spec: inset 0 1px 0 rgb(255 255 255 / 0.09); --spec-hi: inset 0 1px 0 rgb(255 255 255 / 0.14); /* Elevation. Two shadows each: a tight contact shadow that anchors the element, and a wide soft one for the light. One alone always looks fake. */ --e1: 0 1px 2px rgb(0 0 0 / 0.28), 0 4px 12px rgb(0 0 0 / 0.18); --e2: 0 2px 6px rgb(0 0 0 / 0.32), 0 12px 32px rgb(0 0 0 / 0.28); --e3: 0 6px 16px rgb(0 0 0 / 0.36), 0 28px 68px rgb(0 0 0 / 0.42); } @media (prefers-color-scheme: light) { :root { --bg: #f4f5f8; --fg: #0e1116; --dim: #5a6274; --faint: rgb(10 14 25 / 0.07); --glass: rgb(255 255 255 / 0.7); --glass-hi: rgb(255 255 255 / 0.88); --edge: rgb(10 14 25 / 0.09); --edge-hi: rgb(10 14 25 / 0.16); --sheet: rgb(255 255 255 / 0.95); --header: rgb(244 245 248 / 0.72); --scrim: rgb(255 255 255 / 0.78); --scrim-2: rgb(255 255 255 / 0.5); --shadow: 0 10px 34px rgb(20 30 60 / 0.13); /* On light material the specular rim is near-white and the shadows have to lose most of their weight, or every card looks like it is hovering. */ --spec: inset 0 1px 0 rgb(255 255 255 / 0.9); --spec-hi: inset 0 1px 0 rgb(255 255 255 / 1); --e1: 0 1px 2px rgb(20 30 60 / 0.07), 0 4px 12px rgb(20 30 60 / 0.06); --e2: 0 2px 6px rgb(20 30 60 / 0.08), 0 12px 32px rgb(20 30 60 / 0.09); --e3: 0 6px 16px rgb(20 30 60 / 0.1), 0 28px 68px rgb(20 30 60 / 0.14); /* Darkened to clear 4.5:1 on the light background. Same hues, so a status still reads as the same status when the theme flips. */ --ok: #0a7d43; --err: #c62828; --warn: #8a5a00; } } @layer base { * { box-sizing: border-box; } html { -webkit-text-size-adjust: 100%; } body { margin: 0; min-height: 100vh; background: var(--bg); color: var(--fg); font-family: var(--font-sans); font-size: 15px; line-height: 1.55; letter-spacing: -0.008em; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; overflow-x: hidden; } /* Headings take the display face and its tighter tracking automatically, so a component never has to remember to ask for it. */ h1, h2, h3 { font-family: var(--font-display); text-wrap: balance; } /* Ragged-right paragraphs with one orphan word are the giveaway of an interface nobody typeset. */ p { text-wrap: pretty; } button, input, select, textarea { font: inherit; letter-spacing: inherit; color: inherit; } ::selection { background: var(--color-accent-soft); } } @utility glass { background: var(--glass); border: 1px solid var(--edge); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur); box-shadow: var(--spec); } @utility glass-hi { background: var(--glass-hi); border: 1px solid var(--edge-hi); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur); box-shadow: var(--spec-hi); } @utility sheet { background: var(--sheet); border: 1px solid var(--edge-hi); backdrop-filter: var(--blur); -webkit-backdrop-filter: var(--blur); box-shadow: var(--spec-hi), var(--e3); } /* A card that lifts on hover. The translate is tiny on purpose: Apple's hover feedback is barely perceptible frame to frame and obvious in aggregate. Anything larger reads as a web page, not an interface. */ @utility lift { transition: transform 0.28s var(--ease-glass), box-shadow 0.28s var(--ease-glass), border-color 0.28s var(--ease-glass), background 0.28s var(--ease-glass); &:hover { transform: translateY(-2px); box-shadow: var(--spec-hi), var(--e2); border-color: var(--edge-hi); } &:active { transform: translateY(0) scale(0.994); transition-duration: 0.06s; } } /* Keyboard focus only — a mouse click should never draw a ring. */ @utility ring { &:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; } } /* Numbers that change in place (counts, durations, percentages) must not reflow the text around them as digits swap. */ @utility nums { font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; } @utility clamp1 { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } @utility clamp2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } /* Very light noise over the gradients — large flat blurs band visibly on 8-bit panels without it. */ @utility grain { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E"); } @utility no-scrollbar { scrollbar-width: none; &::-webkit-scrollbar { display: none; } } input[type="search"]::-webkit-search-cancel-button { display: none; } /* Keyframes live here rather than in a