/* * Surfaces and text shades come from three seeds and a contrast, per mode, which the * settings pane edits (prefs.svelte.ts sets them on ): --seed-bg is the * ground, --seed-fg the ink, --seed-accent the accent, --contrast 0 to 1. * Surfaces and secondary text are mixed from them, so any three colours make * a whole theme. Semantic colours and the speaker colour can be overridden. * The fallbacks here are the defaults, madoromi's spring * (https://madoromi.moonwit.ch/), for the first paint. */ /* * Every layer one component stacks against another, back to front. A window * is a stacking context of its own, so the z-indexes inside it (its header, * composer, menus) only order its own parts and never reach these. The board * is one too, so its layers never meet the app's. */ :root { /* on the board */ --z-window: 0; --z-tethers: 1; --z-floats: 2; --z-window-menu: 3; --z-board-controls: 4; /* over the board */ --z-peek: 20; --z-zen: 40; --z-pane: 50; --z-docking: 60; --z-palette: 100; } :root { color-scheme: light; --seed-bg: #f6eff8; --seed-fg: #584a5c; --seed-accent: #6928bd; --contrast: 0.45; /* how far each step goes: half as far at no contrast, half again at full */ --k: calc(0.5 + var(--contrast)); --bg: var(--seed-bg); --rail: color-mix(in oklab, var(--seed-bg), var(--seed-fg) calc(3% * var(--k))); --surface: color-mix(in oklab, var(--seed-bg), #fff 78%); --title-bar: color-mix(in oklab, var(--surface), var(--seed-fg) calc(2% * var(--k))); --well: color-mix(in oklab, var(--surface), var(--seed-fg) calc(8% * var(--k))); --field: color-mix(in oklab, var(--surface), var(--seed-fg) calc(11% * var(--k))); --bubble: color-mix(in oklab, var(--field), var(--seed-accent) 7%); --text: var(--seed-fg); --muted: color-mix(in oklab, var(--seed-fg), var(--surface) calc(28% - 20% * var(--contrast))); --faint: color-mix(in oklab, var(--seed-fg), var(--surface) calc(45% - 20% * var(--contrast))); --hover: color-mix(in oklab, var(--seed-fg) calc(5% * var(--k)), transparent); --selected: color-mix(in oklab, var(--seed-fg) calc(8% * var(--k)), transparent); --accent: var(--seed-accent); --focus-ring: color-mix(in oklab, var(--seed-accent) 45%, transparent); /* Who is speaking, as in the terminal: albedo in the accent, you opposite it. */ --agent: var(--seed-accent); --brand-from: var(--seed-accent); --brand-to: oklch(from var(--seed-accent) l c calc(h + 40)); --you: oklch(from var(--seed-accent) 0.5 0.09 calc(h - 130)); /* madoromi's young leaves (wakaba) and crimson (beni) */ --added: #5e8933; --danger: #ce2700; --scrim: color-mix(in oklab, var(--seed-bg) 60%, transparent); --dots: color-mix(in oklab, var(--seed-fg) calc(36% * var(--k)), transparent); /* The sidebar's stripes: the step the phone's stripes take from its ground, taken from the rail's. */ --rail-stripe: color-mix(in oklab, var(--rail), var(--shade) calc(3.2% * var(--k))); /* A sidebar row for a session open on the board. */ --open-tint: color-mix(in oklab, var(--rail), var(--accent) 12%); --minimap-window: var(--field); --minimap-mask: color-mix(in oklab, var(--seed-bg) 65%, transparent); --shade: color-mix(in oklab, var(--seed-fg) 70%, #000); --shadow: 0 1px 2px color-mix(in oklab, var(--shade) 7%, transparent), 0 10px 28px -8px color-mix(in oklab, var(--shade) 16%, transparent); --shadow-raised: 0 2px 4px color-mix(in oklab, var(--shade) 8%, transparent), 0 22px 48px -12px color-mix(in oklab, var(--shade) 26%, transparent); --shadow-lg: 0 4px 12px color-mix(in oklab, var(--shade) 9%, transparent), 0 32px 72px -16px color-mix(in oklab, var(--shade) 34%, transparent); /* A section's ground: sunk below the board, a tray its windows sit in, and a step toward `--section-lift` for each section round it (`--depth`). */ --section-base: 9%; --section-lift: #000; --section-step: 5%; --section-sunk: inset 0 1px 3px color-mix(in oklab, var(--shade) 14%, transparent); /* Text size, as ratios of the 13px base: every font size reads through one. The canvas follows the chrome unless the settings give it its own size. */ --ui-scale: 1; --canvas-scale: var(--ui-scale); --sans: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif; --mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; /* Faces read softest in a rounded Japanese face where there is one. */ --face: 'Hiragino Maru Gothic ProN', 'Hiragino Sans', 'Yu Gothic UI', system-ui, sans-serif; } /* In the dark, windows lift toward the ink and chrome sinks below the ground. */ :root[data-theme='dark'] { color-scheme: dark; --seed-bg: #241c26; --seed-fg: #e1d1e7; --seed-accent: #ddb3ff; --contrast: 0.5; --rail: color-mix(in oklab, var(--seed-bg), #000 calc(20% * var(--k))); --surface: color-mix(in oklab, var(--seed-bg), var(--seed-fg) calc(5% * var(--k))); --title-bar: color-mix(in oklab, var(--surface), var(--seed-fg) calc(2.5% * var(--k))); --well: color-mix(in oklab, var(--surface), #000 calc(16% * var(--k))); --field: color-mix(in oklab, var(--surface), var(--seed-fg) calc(7% * var(--k))); --bubble: color-mix(in oklab, var(--field), var(--seed-accent) 9%); --muted: color-mix(in oklab, var(--seed-fg), var(--surface) calc(42% - 20% * var(--contrast))); --faint: color-mix(in oklab, var(--seed-fg), var(--surface) calc(60% - 20% * var(--contrast))); --you: oklch(from var(--seed-accent) 0.82 0.08 calc(h - 130)); --added: #c1dd4a; --danger: #ff8b79; --dots: color-mix(in oklab, var(--seed-fg) calc(26% * var(--k)), transparent); --shade: #000; --shadow: 0 1px 2px rgb(0 0 0 / 0.4), 0 12px 32px -8px rgb(0 0 0 / 0.6); --shadow-raised: 0 2px 4px rgb(0 0 0 / 0.45), 0 24px 56px -12px rgb(0 0 0 / 0.75); --shadow-lg: 0 4px 12px rgb(0 0 0 / 0.5), 0 32px 80px -16px rgb(0 0 0 / 0.8); /* Near black every step darker looks the same, so in the dark a section in a section lifts. */ --section-base: 38%; --section-lift: var(--text); --section-step: 10%; --section-sunk: inset 0 1px 3px rgb(0 0 0 / 0.45); --rail-stripe: color-mix(in oklab, var(--rail), var(--shade) calc(19% * var(--k))); --open-tint: color-mix(in oklab, var(--rail), var(--accent) 18%); } * { box-sizing: border-box; } html, body, #app { height: 100%; margin: 0; } /* A sideways two-finger swipe pans the canvas; without this the browser reads the same gesture as back/forward. */ html, body { overscroll-behavior: none; } body { overflow: hidden; color: var(--text); font-family: var(--sans); font-size: calc(13px * var(--ui-scale)); line-height: 1.45; background: var(--bg); -webkit-font-smoothing: antialiased; } kbd { display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 5px; color: var(--muted); font-family: var(--sans); font-size: calc(11px * var(--ui-scale)); background: var(--hover); border-radius: 5px; } button:focus-visible, input:focus-visible, [role='tab']:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 1px; } /* A kaomoji: albedo's face for a turn, still or animated. */ .kaomoji { font-family: var(--face); letter-spacing: -0.03em; white-space: pre; } /* The wordmark, swept from mauve to pink as in the terminal's header. */ .brand-ink { color: var(--brand-from); background: linear-gradient(90deg, var(--brand-from), var(--brand-to)); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; } /* Svelte Flow takes the app's colours. */ .svelte-flow { --xy-background-color: var(--bg); } .svelte-flow__node:focus-visible { outline: none; } .svelte-flow__node.dragging .window { box-shadow: var(--shadow-lg); } /* A window and the views it opened are tied by a faint line. */ .svelte-flow .tether-end { width: 1px; height: 1px; min-width: 0; min-height: 0; background: transparent; border: 0; pointer-events: none; } .svelte-flow .tether path { stroke: color-mix(in oklab, var(--accent) 40%, transparent); stroke-width: 1.5; stroke-dasharray: 4 6; } /* Window edges and corners resize but draw nothing until hovered. */ .svelte-flow .window-edge { border-color: transparent; border-width: 4px; } .svelte-flow .window-corner { width: 14px; height: 14px; background: transparent; border: 0; } /* A drag on an edge, a corner or a title bar is always the canvas's, never a scroll. */ .svelte-flow .svelte-flow__resize-control, .svelte-flow .window-handle, .svelte-flow .note-handle { touch-action: none; } /* A finger needs far more to aim at than a pointer: the edges and corners reach well past the window, still drawing nothing. */ @media (pointer: coarse) { .svelte-flow .window-edge { border-width: 14px; } .svelte-flow .window-corner { width: 40px; height: 40px; } } /* Above the view controls in the same corner. */ .svelte-flow__minimap { margin: 14px 14px 60px; overflow: hidden; border-radius: 12px; box-shadow: var(--shadow); } /* A section's frame, in the tiles (tiles/TileView.svelte) or a group on a canvas (nodes/SlotNode.svelte): a tray sunk below the board, and one step on for each section round it. */ .tray { background: color-mix(in oklab, color-mix(in oklab, var(--bg), #000 var(--section-base)), var(--section-lift) calc(var(--depth, 0) * var(--section-step))); border-radius: 16px; box-shadow: var(--section-sunk); } /* A section in a section is edged too: its step alone is slight. */ .tray.nested { box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--text) 14%, transparent), var(--section-sunk); } /* The selected or picked pane (tiles/WindowSlot.svelte, tiles/TileView.svelte, nodes/SlotNode.svelte): its title or header in the accent and a faint ring, or a 2px outline when picked. */ .window-slot.selected > .window-host header h2, .tray.selected > .section-head { color: var(--accent); } .window-slot.selected:not(.picked)::after, .tray.selected:not(.picked)::after { position: absolute; inset: 0; border: 1px solid color-mix(in oklab, var(--accent) 35%, transparent); border-radius: inherit; content: ''; pointer-events: none; } .canvas-tile.nested.selected:not(.picked) { box-shadow: 0 0 0 1px color-mix(in oklab, var(--accent) 35%, transparent); } [data-theme='dark'] .window-slot.selected:not(.picked)::after, [data-theme='dark'] .tray.selected:not(.picked)::after { border-color: color-mix(in oklab, var(--accent) 55%, transparent); } [data-theme='dark'] .canvas-tile.nested.selected:not(.picked) { box-shadow: 0 0 0 1px color-mix(in oklab, var(--accent) 55%, transparent); } .window-slot.picked::after { position: absolute; inset: 0; border: 2px solid var(--accent); border-radius: inherit; content: ''; pointer-events: none; } .tray.picked, .canvas-tile.picked { box-shadow: 0 0 0 2px var(--accent); }