/* ══════════════════════════════════════════════════════════════════════ Melange theme — a blend, which is all the name means now. It began as a port of savq/melange-nvim and kept that scheme's idea rather than its browns: a handful of hues that only make sense mixed. Here they are a sorbet's (pink, coral, lilac, sky, mint), run together as one gradient along the header, through the site's name and between a journal's blocks, on grounds of berry at night and of blush paper by day. The rest is a print of it: film grain over the whole page, pillowy borderless cards that sit in a tinted shadow rather than inside a line, a glow under whatever is active, and one quirky grotesque for all of it. The two schemes are one print and its negative. They trade ink and paper: the night's lilac-white type is the day's page, the night's plum ground the day's type. What doesn't trade is the sorbet: the accent is the same pink in both, steeped a little deeper by day so that it holds on paper, and what is written on it is the same plum. A pill, a button, the stripe under the header are the same objects in either. Dark scheme → berry (plum grounds, lilac-white ink). Light scheme → the same on paper (lilac-white grounds, plum ink). ══════════════════════════════════════════════════════════════════════ */ /* ── Palette (light-dark: see tokens.css) ─────────────────────────── */ :root[data-style="melange"] { /* One family. fonts.css loads its weight axis alone, so it is the same cut at every size. */ --font-body: "Bricolage Grotesque Variable", system-ui, sans-serif; --font-display: var(--font-body); /* Nothing here has a sharp corner. */ --radius-xs: 5px; --radius-sm: 8px; --radius-md: 12px; --radius-lg: 16px; --radius-xl: 22px; /* Text — by day, the night's card colour. On the accent it is plum in both schemes. */ --color-text: light-dark(#2b2338, #f1e8f3); --color-text-secondary: light-dark(#564769, #c8b8d2); --color-text-muted: light-dark(#746489, #a898b6); --color-on-accent: #2a1830; /* Surfaces — sunken < bg < surface < raised: the page is the tinted ground in both schemes and a card the lighter sheet on it. By day the page is the night's type colour. */ --color-bg: light-dark(#f1e8f3, #211a2b); --color-surface: light-dark(#fbf7fc, #2b2338); --color-surface-raised: light-dark(#fffcff, #372d47); --color-surface-sunken: light-dark(#e3d6e7, #19131f); /* Borders — mostly unused: this theme separates by tint and shadow, not by line. */ --color-border: light-dark(rgb(117 98 131 / 0.34), rgb(168 152 182 / 0.36)); --color-border-subtle: light-dark( rgb(117 98 131 / 0.16), rgb(168 152 182 / 0.18) ); /* Accent — one pink, deeper on paper than at night. Hovering walks it one step along the blend, to the coral. */ --color-accent: light-dark(#e2568f, #f48fb1); --color-accent-hover: light-dark(#ea6a45, #ff9e80); --color-accent-soft: light-dark( rgb(226 86 143 / 0.12), rgb(244 143 177 / 0.14) ); --color-focus-ring: light-dark( rgb(226 86 143 / 0.4), rgb(244 143 177 / 0.42) ); /* Links — a line of text needs more ink than a pill: the pink again, steeped until it reads at any size on paper. */ --color-link: light-dark(#b62d6b, #f48fb1); --color-link-hover: light-dark(#c2452b, #ff9e80); --color-danger: light-dark(#c0303a, #ff8a80); --color-danger-bg: light-dark(#f8dde0, #4d2030); --color-danger-hover: light-dark(#c0303a, #c9404f); --color-success: light-dark(#1b7f66, #86d3b4); --color-success-bg: light-dark(#d5efe6, #1d3a33); --color-success-hover: light-dark(#17705a, #a3e0c8); --color-warning: light-dark(#b5541f, #ffb38a); /* Overlays */ --color-overlay: light-dark(rgb(54 38 63 / 0.3), rgb(15 10 20 / 0.72)); --color-header-user-bg: transparent; --color-header-user-bg-hover: light-dark( rgb(54 38 63 / 0.07), rgb(241 232 243 / 0.08) ); /* Misc */ --color-option-bg: light-dark(#eee3ef, #2b2338); --color-option-border: light-dark( rgb(117 98 131 / 0.16), rgb(168 152 182 / 0.18) ); /* The rest of the blend, beside the accent's pink: the theme's own furniture colours. By day each is steeped as far as the accent is, a sorbet still and not a flag's primary. */ --mel-coral: light-dark(#ea6a45, #ff9e80); --mel-lilac: light-dark(#8262d8, #b9a2f2); --mel-sky: light-dark(#3a8fd4, #86bdea); --mel-mint: light-dark(#27a583, #86d3b4); /* The mélange: every hue, blended once, left to right in the order of the wheel so no two neighbours mix to mud. */ --mel-spice: linear-gradient( 90deg, var(--mel-coral), var(--color-accent) 26%, var(--mel-lilac) 54%, var(--mel-sky) 78%, var(--mel-mint) ); /* Shadows are tinted with the ground and wide. Light needs more of them than dark: on paper, shadow is the only thing holding a card off the page. */ --shadow-color: light-dark(rgb(96 52 118 / 0.2), rgb(8 4 12 / 0.5)); --shadow-color-soft: light-dark(rgb(96 52 118 / 0.13), rgb(8 4 12 / 0.32)); --shadow-color-strong: light-dark(rgb(96 52 118 / 0.32), rgb(8 4 12 / 0.7)); --shadow-1: 0 2px 10px -2px var(--shadow-color-soft); --shadow-2: 0 14px 34px -10px var(--shadow-color), 0 2px 6px var(--shadow-color-soft); --shadow-3: 0 32px 70px -16px var(--shadow-color-strong), 0 3px 10px var(--shadow-color-soft); /* Grain — one fine tile for both schemes, laid differently (see body::after). Defaults are the night's; the day overrides them by selector. */ --mel-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)' opacity='0.22'/%3E%3C/svg%3E"); --mel-grain-blend: soft-light; --mel-grain-opacity: 0.55; /* Glow: the accent catches light where it's interactive. */ --mel-glow: 0 3px 16px -4px light-dark(rgb(226 86 143 / 0.5), rgb(244 143 177 / 0.38)); /* Component skins — no lines anywhere; tint and shadow do the work. */ --border-width: 1px; /* The header is a board laid over the page, lighter than it in both schemes. */ --header-bg: light-dark(#fffcff, #2b2338); --input-focus-bg: var(--color-surface-raised); --overlay-filter: blur(6px); --modal-border: transparent; --card-border: transparent; --card-border-width: 1px; --card-shadow: var(--shadow-1); --card-hover-border: transparent; --panel-ring: var(--shadow-1); --tab-border: transparent; --btn-primary-shadow: var(--mel-glow); --btn-primary-shadow-hover: 0 5px 22px -4px light-dark(rgb(226 86 143 / 0.6), rgb(244 143 177 / 0.48)); } /* ══════════════════════════════════════════════════════════════════════ Structural overrides ══════════════════════════════════════════════════════════════════════ */ /* ── The page is lit from above: the accent pools faintly at the top, the ground below is flat. ────────────────────────────────────── */ [data-style="melange"] body { background-image: radial-gradient( 120% 55% at 50% -12%, var(--color-accent-soft), transparent 70% ); background-repeat: no-repeat; background-attachment: fixed; } /* ── Film grain over everything, so no surface reads as flat pixels. Sits above the page, below modals and toasts. It is the same fine tile in both schemes, and the blend is what differs. On berry, `soft-light` grits the surface without lifting the blacks. On paper that blend does nothing, pale grey noise on a pale ground having nothing to work against, so the day multiplies it: paper tooth, which is tiny shadows, kept faint enough that the page stays the colour it is given. Neither blend nor opacity takes light-dark(), so the two are custom properties and the scheme is picked by selector below. ───────────────────────────────────────── */ [data-style="melange"] body::after { content: ""; position: fixed; inset: 0; z-index: calc(var(--z-modal) - 1); pointer-events: none; opacity: var(--mel-grain-opacity); mix-blend-mode: var(--mel-grain-blend); background-image: var(--mel-grain); } /* Auto (no forced scheme) follows the OS; the attribute forms win over it because they come later and are more specific. */ @media (prefers-color-scheme: light) { :root[data-style="melange"] { --mel-grain-blend: multiply; --mel-grain-opacity: 0.4; } } :root[data-style="melange"][data-color-scheme="light"] { --mel-grain-blend: multiply; --mel-grain-opacity: 0.4; } /* Forcing dark under a light OS would otherwise inherit the day's two from the media query above. */ :root[data-style="melange"][data-color-scheme="dark"] { --mel-grain-blend: soft-light; --mel-grain-opacity: 0.55; } @media (prefers-reduced-transparency: reduce) { [data-style="melange"] body::after { display: none; } } /* ── Header — a board over the page: no rule under it, just its own shade, a tinted shadow, and the blend laid along its bottom edge as a single stripe. ──────────────────────────────────────────── */ [data-style="melange"] .app-header { border-bottom: none; box-shadow: var(--shadow-1); z-index: var(--z-raised); } [data-style="melange"] .app-header::after { content: ""; position: absolute; inset: auto 0 0 0; height: 3px; background: var(--mel-spice); } /* Brand — the site's name is cut out of the blend itself. The fill takes the place of the text's colour, so the emoji beside it, which sits outside the name's span, keeps its own. The blend is laid twice as wide as the name and drifts under it, from its warm end to its cool one and back, so the name is never the same two colours for long. Pointed at, the name fills with the accent over the blend, as a card's title turns to it. */ [data-style="melange"] .app-header-brand { font-weight: 800; letter-spacing: -0.02em; } [data-style="melange"] .app-header-brand-name { background: var(--mel-spice) 0 0 / 200% 100%; -webkit-background-clip: text; background-clip: text; color: transparent; transition: color var(--dur-base); animation: mel-drift 7s ease-in-out infinite alternate; } [data-style="melange"] .app-header-brand:hover .app-header-brand-name { color: var(--color-accent); } @keyframes mel-drift { to { background-position: 100% 0; } } /* Held still, the name shows the whole blend. */ @media (prefers-reduced-motion: reduce) { [data-style="melange"] .app-header-brand-name { background-size: 100% 100%; animation: none; } } /* Headlines are heavy and set a little tight, as the face likes. */ [data-style="melange"] h1, [data-style="melange"] .dump-title, [data-style="melange"] .page-title, [data-style="melange"] .form-page-title { font-weight: 800; letter-spacing: -0.02em; } /* Tabs keep the shared uppercase cut, but the active one glows. */ [data-style="melange"] .feed-sort-btn.active { box-shadow: var(--mel-glow); } [data-style="melange"] .feed-sort-btn:hover:not(.active) { background: var(--color-accent-soft); } /* ── Cards sit in the light rather than inside a line; they rise a little when pointed at. ───────────────────────────────────────── */ [data-style="melange"] .dump-card, [data-style="melange"] .journal-card, [data-style="melange"] .playlist-card { transition: box-shadow var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out); } [data-style="melange"] .dump-card:hover, [data-style="melange"] .journal-card:hover, [data-style="melange"] .playlist-card:hover { box-shadow: var(--shadow-2); transform: translateY(-2px); } @media (prefers-reduced-motion: reduce) { [data-style="melange"] .dump-card:hover, [data-style="melange"] .journal-card:hover, [data-style="melange"] .playlist-card:hover { transform: none; } } /* A pointed-at headline over a photo sits on a pillow of the night ground — the dark scheme's in either scheme, since the scrim under it is dark in both — lit in the dark scheme's pink. */ [data-style="melange"] .journal-card--image .journal-card-title { --journal-title-hover-bg: rgb(33 26 43 / 0.86); --journal-title-hover-color: #f48fb1; --journal-title-hover-radius: var(--radius-sm); --journal-title-hover-shadow: 0 4px 14px -4px rgb(0 0 0 / 0.5); } /* ── A quote is a printed pull-quote: big mark, in the coral ─────── */ [data-style="melange"] .journal-card--quote { background: var(--color-surface); } [data-style="melange"] .journal-card-quotemark { color: var(--mel-coral); opacity: 0.3; } [data-style="melange"] .journal-card-quote-body { font-size: var(--text-lg); line-height: 1.35; } /* The blend runs along the header's bottom edge; between sub-blocks it returns as a softer band of the same — the page divided by its own palette rather than by a line. A rule can't carry a gradient, so this one is a filled bar and the base break's border stands down. */ [data-style="melange"] .journal-break { --journal-break-space: 2rem; --journal-break-rule: none; height: 3px; border-radius: 999px; background: var(--mel-spice); opacity: 0.6; } /* Vote tallies are the blend's lilac, apart from the accent's pink. */ [data-style="melange"] .vote-btn:not(.vote-btn--active) { color: var(--mel-lilac); } /* A dump's note is read at length: full ink, where the base dims it. */ [data-style="melange"] .dump-comment { opacity: 1; }