Files
sendou.ink/app/styles/vars.css
2026-09-27 09:59:54 +03:00

405 lines
16 KiB
CSS

@layer reset, base, elements, components, features, utilities;
/* ⚠️ Read styles.md before editing colors in this file */
/*
Tokens settable by custom themes and their defaults. Not to be consumed directly, only as a base
for other vars. Values are generated with ThemePalette.ts, do not edit by hand.
A subtree can force a color scheme with [data-theme="dark"|"light"] and opt out of an active
custom theme with [data-default-theme] (e.g. image export previews)
*/
html,
[data-default-theme] {
--_base-l: 0.17;
--_base-h: 268;
--_base-c-0: 0;
--_base-c-1: 0.02356547860966049;
--_base-c-2: 0.031;
--_base-c-3: 0.06999999999999999;
--_base-c-4: 0.0645;
--_base-c-5: 0.068;
--_base-c-6: 0.0645;
--_base-c-7: 0.0335;
--_acc-c: 0.24;
--_acc-h: 253;
--_acc-l-0: 0.26;
--_acc-l-1: 0.52;
--_acc-l-2: 0.83;
--_acc-l-3: 0.88;
--_acc-l-4: 0.485;
--_acc-l-5: 0.32;
--_acc-l-6: 0.485;
--_acc-c-0: 0.08016408718561431;
--_acc-c-1: 0.1603381743712286;
--_acc-c-2: 0.0816;
--_acc-c-3: 0.06;
--_acc-c-4: 0.14954550878854975;
--_acc-c-5: 0.09866579961306376;
--_acc-c-6: 0.14954550878854975;
--_acc-h-0: 253;
--_acc-h-1: 253;
--_acc-h-2: 253;
--_acc-h-3: 253;
--_acc-h-4: 253;
--_acc-h-5: 253;
--_acc-h-6: 253;
--_acc-fill-dark-text: 0;
--_second-l-0: 0.26;
--_second-l-1: 0.52;
--_second-l-2: 0.83;
--_second-l-3: 0.88;
--_second-l-4: 0.485;
--_second-l-5: 0.32;
--_second-c-0: 0.055379201356259726;
--_second-c-1: 0.11075840271251945;
--_second-c-2: 0.0816;
--_second-c-3: 0.06;
--_second-c-4: 0.10330351022225373;
--_second-c-5: 0.06815901705385813;
--_second-h-0: 73;
--_second-h-1: 73;
--_second-h-2: 73;
--_second-h-3: 73;
--_second-h-4: 73;
--_second-h-5: 73;
--_second-l-6: 0.8007;
--_second-c-6: 0.1704874227120647;
--_second-h-6: 73;
--_second-fill-dark-text: 1;
--_radius-box: 3;
--_radius-field: 2;
--_radius-selector: 2;
--_border-width: 2;
/* not overridable by custom themes to prevent accessibility issues and layout shifts */
--_size-field: 1;
--_size-selector: 1;
--_size-spacing: 1;
}
/*
'low' and 'high' do not indicate lightness: dark goes light to dark, light goes dark to light.
--color-base-x is rarely consumed directly, it is the base for vars like --color-text and --color-bg.
Accent and secondary colors come in four kinds of token:
- --color-bg-x: surfaces (tinted chips, highlighted rows...)
- --color-fg-x: foreground on surfaces: text, icons, borders, outlines and indicators (dots,
bars, checkboxes...). Readable on any --color-bg-x surface
- --color-fill-x: fills that carry content (buttons, badges...)
- --color-fg-on-x: foreground on a --color-fill-x fill. In light mode a yellow accent e.g. gets a
bright fill with dark text while --color-fg-accent stays dark enough to read
--color-accent-x and --color-second-x are the building blocks behind these and not meant to be
consumed directly.
Info, success, warning, error: --color-x-high for text, --color-x-low for backgrounds,
--color-x for borders and icons.
The checkbox icons are masks colored by the checkbox. The select and date/time icons are background
images with a hardcoded color per mode, since those elements render no pseudo-element to mask and
SVGs cannot use currentColor inside data URLs.
Custom theme lightness, chroma and hue values are generated by ThemePalette.ts which guarantees
their contrast. Any changes here NEED to be reflected in ThemePalette.ts as well
*/
html.dark,
html.dark [data-custom-theme],
[data-theme="dark"] {
--color-base-0: oklch(100% var(--_base-c-0) var(--_base-h));
--color-base-1: oklch(95% var(--_base-c-1) var(--_base-h));
--color-base-2: oklch(90% var(--_base-c-2) var(--_base-h));
--color-base-3: oklch(64% var(--_base-c-3) var(--_base-h));
--color-base-4: oklch(46% var(--_base-c-4) var(--_base-h));
--color-base-5: oklch(
calc(var(--_base-l) + 0.15) var(--_base-c-5) var(--_base-h)
);
--color-base-6: oklch(
calc(var(--_base-l) + 0.08) var(--_base-c-6) var(--_base-h)
);
--color-base-7: oklch(var(--_base-l) var(--_base-c-7) var(--_base-h));
--color-accent-low: oklch(var(--_acc-l-0) var(--_acc-c-0) var(--_acc-h-0));
--color-accent: oklch(var(--_acc-l-1) var(--_acc-c-1) var(--_acc-h-1));
--color-accent-high: oklch(var(--_acc-l-2) var(--_acc-c-2) var(--_acc-h-2));
--color-second-low: oklch(
var(--_second-l-0) var(--_second-c-0) var(--_second-h-0)
);
--color-second: oklch(
var(--_second-l-1) var(--_second-c-1) var(--_second-h-1)
);
--color-second-high: oklch(
var(--_second-l-2) var(--_second-c-2) var(--_second-h-2)
);
--color-fill-accent: var(--color-accent-high);
--color-fill-second: var(--color-second-high);
--color-fg-accent: var(--color-accent-high);
--color-fg-second: var(--color-second-high);
--color-fg-on-accent: var(--color-base-7);
--color-fg-on-second: var(--color-base-7);
--color-info-low: oklch(26% 0.09 275);
--color-info: oklch(52% 0.27 275);
--color-info-high: oklch(83% 0.08 275);
--color-success-low: oklch(35% 0.08 135);
--color-success: oklch(85% 0.22 135);
--color-success-high: oklch(91% 0.12 135);
--color-warning-low: oklch(38% 0.05 85);
--color-warning: oklch(82% 0.14 85);
--color-warning-high: oklch(94% 0.05 85);
--color-error-low: oklch(31% 0.07 10);
--color-error: oklch(65% 0.25 10);
--color-error-high: oklch(87% 0.07 10);
--color-chart-alpha: oklch(64% 0.16 10);
--color-chart-bravo: oklch(60% 0.17 275);
--color-chart-splatted: oklch(66% 0.03 var(--_base-h));
--color-chart-special: oklch(80% 0.14 84);
--color-chart-kill: oklch(78% 0.19 150);
/* inlined instead of var() because data URIs can't read custom properties: keep in sync with --color-text-high */
--field-icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(122, 139, 183)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
--field-icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(122, 139, 183)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
--field-icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(122, 139, 183)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
}
html.light,
html.light [data-custom-theme],
[data-theme="light"] {
--color-base-0: oklch(17% var(--_base-c-7) var(--_base-h));
--color-base-1: oklch(25% var(--_base-c-6) var(--_base-h));
--color-base-2: oklch(32% var(--_base-c-5) var(--_base-h));
--color-base-3: oklch(46% var(--_base-c-4) var(--_base-h));
--color-base-4: oklch(64% var(--_base-c-3) var(--_base-h));
--color-base-5: oklch(90% var(--_base-c-2) var(--_base-h));
--color-base-6: oklch(95% var(--_base-c-1) var(--_base-h));
--color-base-7: oklch(100% var(--_base-c-0) var(--_base-h));
--color-accent-low: oklch(var(--_acc-l-3) var(--_acc-c-3) var(--_acc-h-3));
--color-accent: oklch(var(--_acc-l-4) var(--_acc-c-4) var(--_acc-h-4));
--color-accent-high: oklch(var(--_acc-l-5) var(--_acc-c-5) var(--_acc-h-5));
--color-second-low: oklch(
var(--_second-l-3) var(--_second-c-3) var(--_second-h-3)
);
--color-second: oklch(
var(--_second-l-4) var(--_second-c-4) var(--_second-h-4)
);
--color-second-high: oklch(
var(--_second-l-5) var(--_second-c-5) var(--_second-h-5)
);
--color-fill-accent: oklch(var(--_acc-l-6) var(--_acc-c-6) var(--_acc-h-6));
--color-fill-second: oklch(
var(--_second-l-6) var(--_second-c-6) var(--_second-h-6)
);
--color-fg-accent: var(--color-accent);
--color-fg-second: var(--color-second);
--color-fg-on-accent: oklch(
calc(1 - 0.83 * var(--_acc-fill-dark-text))
calc(var(--_base-c-7) * var(--_acc-fill-dark-text)) var(--_base-h)
);
--color-fg-on-second: oklch(
calc(1 - 0.83 * var(--_second-fill-dark-text))
calc(var(--_base-c-7) * var(--_second-fill-dark-text)) var(--_base-h)
);
--color-info-low: oklch(87.897% 0.0555 279.573);
--color-info: oklch(53.03% 0.24331 270.147);
--color-info-high: oklch(31.865% 0.1766 267.138);
--color-success-low: oklch(95.604% 0.06419 135.506);
--color-success: oklch(79.407% 0.25035 139.5);
--color-success-high: oklch(44.893% 0.13293 138.416);
--color-warning-low: oklch(94.216% 0.05193 85.101);
--color-warning: oklch(82.426% 0.15029 82.564);
--color-warning-high: oklch(46.236% 0.09033 79.825);
--color-error-low: oklch(89.949% 0.04928 355.498);
--color-error: oklch(65.223% 0.22164 5.216);
--color-error-high: oklch(41.268% 0.15511 8.446);
--color-chart-alpha: oklch(52% 0.18 10);
--color-chart-bravo: oklch(47% 0.19 275);
--color-chart-splatted: oklch(50% 0.03 var(--_base-h));
--color-chart-special: oklch(67% 0.14 72);
--color-chart-kill: oklch(55% 0.17 150);
/* inlined instead of var() because data URIs can't read custom properties: keep in sync with --color-text-high */
--field-icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(72, 87, 124)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
--field-icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(72, 87, 124)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
--field-icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(72, 87, 124)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
}
/* the vars you mainly want to use */
html,
[data-custom-theme],
[data-theme] {
--color-text: var(--color-base-0);
--color-text-high: var(--color-base-3);
--color-text-inverse: var(--color-base-7);
--color-text-on-light: oklch(17% var(--_base-c-7) var(--_base-h));
--color-text-on-dark: oklch(100% var(--_base-c-0) var(--_base-h));
--color-bg: var(--color-base-7);
--color-bg-high: var(--color-base-6);
--color-bg-higher: var(--color-base-5);
--color-bg-nav: color-mix(
in oklch,
var(--color-bg) 75%,
var(--color-bg-high) 25%
);
--color-bg-ability: oklch(11.736% 0.00867 215.976);
--color-bg-badge: oklch(0% 0 0);
--color-bg-accent: var(--color-accent-low);
--color-bg-second: var(--color-second-low);
/* masks, so the color is set by the checkbox */
--field-icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
--field-icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");
--color-border: var(--color-base-5);
--color-border-high: var(--color-base-4);
--border-width: calc(var(--_border-width) * 1px);
--border-style: var(--border-width) solid var(--color-border);
--border-style-high: var(--border-width) solid var(--color-border-high);
--border-style-accent: var(--border-width) solid var(--color-fg-accent);
--focus-ring: 2px solid var(--color-fg-accent);
--focus-ring-error: 2px solid var(--color-error);
--font-xl: 1.5rem;
--font-lg: 1.2rem;
--font-md: 1rem;
--font-sm: 0.9rem;
--font-xs: 0.8rem;
--font-2xs: 0.7rem;
--font-3xs: 0.6rem;
--weight-extra: 700;
--weight-bold: 600;
--weight-semi: 500;
--weight-body: 400;
--line-height: 1.5;
/* spacing */
--s-0-5: calc(var(--_size-spacing) * 0.5 * 0.25rem);
--s-1: calc(var(--_size-spacing) * 1 * 0.25rem);
--s-1-5: calc(var(--_size-spacing) * 1.5 * 0.25rem);
--s-2: calc(var(--_size-spacing) * 2 * 0.25rem);
--s-2-5: calc(var(--_size-spacing) * 2.5 * 0.25rem);
--s-3: calc(var(--_size-spacing) * 3 * 0.25rem);
--s-4: calc(var(--_size-spacing) * 4 * 0.25rem);
--s-5: calc(var(--_size-spacing) * 5 * 0.25rem);
--s-6: calc(var(--_size-spacing) * 6 * 0.25rem);
--s-8: calc(var(--_size-spacing) * 8 * 0.25rem);
--s-10: calc(var(--_size-spacing) * 10 * 0.25rem);
--s-12: calc(var(--_size-spacing) * 12 * 0.25rem);
--s-16: calc(var(--_size-spacing) * 16 * 0.25rem);
--s-24: calc(var(--_size-spacing) * 24 * 0.25rem);
--s-32: calc(var(--_size-spacing) * 32 * 0.25rem);
/*
layout dimensions; --layout-sticky-top is for position: sticky elements sticking relative
to the document scroll, for a smooth transition between sticking and un-sticking
*/
--layout-nav-height: 55px;
--layout-sidenav-width: 250px;
--layout-fuse-bottom-height: 90px;
--layout-main-padding: var(--s-3);
--layout-sticky-top: calc(
var(--layout-nav-height) +
var(--layout-main-padding) +
env(safe-area-inset-top)
);
--popover-boundary-top: var(--layout-nav-height);
--popover-boundary-bottom: 0px;
--modal-margin-block: 5rem;
--floating-gap: var(--s-2);
--floating-viewport-padding: 12px;
/*
Boxes contain other elements (cards, containers, modals). Fields are interactive elements
(buttons, inputs, selects) or any interactable/content child of a box. Selectors are small
elements complementary to fields (checkboxes, toggles, badges, tags, pills).
*/
--field-size-xs: calc(var(--_size-field) * 6 * 0.25rem);
--field-size-sm: calc(var(--_size-field) * 8 * 0.25rem);
--field-size: calc(var(--_size-field) * 10 * 0.25rem);
--field-size-lg: calc(var(--_size-field) * 12 * 0.25rem);
--field-size-icon: 18px;
--field-padding: 0.6rem;
--selector-size-xs: calc(var(--_size-selector) * 4 * 0.25rem);
--selector-size-sm: calc(var(--_size-selector) * 5 * 0.25rem);
--selector-size: calc(var(--_size-selector) * 6 * 0.25rem);
--selector-size-lg: calc(var(--_size-selector) * 7 * 0.25rem);
--radius-box: calc(var(--_radius-box) * 4px);
--radius-field: calc(var(--_radius-field) * 4px);
--radius-selector: calc(var(--_radius-selector) * 4px);
--radius-full: 99999px;
--radius-avatar: var(--radius-full);
--label-margin: var(--s-1);
}
/* registered so scripts read them as resolved lengths even when they are a calc() */
@property --popover-boundary-top {
syntax: "<length>";
inherits: true;
initial-value: 0px;
}
@property --popover-boundary-bottom {
syntax: "<length>";
inherits: true;
initial-value: 0px;
}
@property --floating-gap {
syntax: "<length>";
inherits: true;
initial-value: 0px;
}
@property --floating-viewport-padding {
syntax: "<length>";
inherits: true;
initial-value: 0px;
}
@media screen and (display-mode: standalone) {
html {
--popover-boundary-top: calc(
var(--layout-nav-height) +
env(safe-area-inset-top)
);
}
}
@media (width < 600px) {
html {
--modal-margin-block: calc(
var(--s-4) +
max(env(safe-area-inset-top, 0px), env(safe-area-inset-bottom, 0px))
);
--popover-boundary-bottom: calc(
var(--layout-nav-height) +
env(safe-area-inset-bottom, 0px)
);
}
}