Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 138 additions & 0 deletions static/css/base/reset-and-typography.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/* #region Reset And Base */
/* ── Reset & Base ── */

* { box-sizing: border-box; }
html, body { overflow-x: hidden; height: 100%; margin: 0; overscroll-behavior: none; }

body {
background-color: var(--bg);
color: var(--fg);
/* Animate the dock push BOTH ways. Keeping the transition on the base body
(not on .right/left-dock-active) means removing the class on undock also
animates padding back to 0 — otherwise the chat snapped back instantly. */
transition: padding-left 160ms cubic-bezier(0.22, 0.61, 0.36, 1),
padding-right 160ms cubic-bezier(0.22, 0.61, 0.36, 1);
font-family: var(--font-family, 'Fira Code', monospace);
display: flex;
height: 100%;
height: 100dvh; /* dynamic viewport height — adapts when mobile keyboard opens */
overflow: hidden;
}

/* Self-hosted Fira Code font */
@font-face { font-family: 'Fira Code'; font-weight: 300; font-style: normal; font-display: swap; src: url('/static/fonts/FiraCode-Light.woff2') format('woff2'); }
@font-face { font-family: 'Fira Code'; font-weight: 400; font-style: normal; font-display: swap; src: url('/static/fonts/FiraCode-Regular.woff2') format('woff2'); }
@font-face { font-family: 'Fira Code'; font-weight: 600; font-style: normal; font-display: swap; src: url('/static/fonts/FiraCode-SemiBold.woff2') format('woff2'); }

/* Self-hosted OpenDyslexic — dyslexia-friendly accessibility font option (SIL OFL 1.1) */
@font-face { font-family: 'OpenDyslexic'; font-weight: 400; font-style: normal; font-display: swap; src: url('/static/fonts/OpenDyslexic-Regular.woff2') format('woff2'); }
@font-face { font-family: 'OpenDyslexic'; font-weight: 700; font-style: normal; font-display: swap; src: url('/static/fonts/OpenDyslexic-Bold.woff2') format('woff2'); }

/* Code block baseline */
pre, code, .hljs {
font-size: 0.95em;
line-height: 1.5;
}

/* Scrollbar styling */
@supports selector(::-webkit-scrollbar) {
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: var(--panel);
}
::-webkit-scrollbar-thumb {
background-color: var(--red);
border-radius: 4px;
border: 2px solid var(--panel);
}
::-webkit-scrollbar-thumb:hover {
background-color: color-mix(in srgb, var(--red) 80%, white);
}
}

html {
scrollbar-color: var(--red) var(--panel);
scrollbar-width: thin;
}

/* Utility */
.red-text { color: var(--red); }
/* #endregion Reset And Base */

/* #region Density Overrides */
/* ── Density Overrides ── */

:root.density-compact { font-size: 13px; }
:root.density-compact .msg { padding: 6px 10px; margin-bottom: 4px; }
:root.density-compact .list-item { padding: 4px 8px; }
:root.density-compact .sidebar .section { padding: 0; }
:root.density-spacious { font-size: 16px; }
:root.density-spacious .msg { padding: 14px 18px; margin-bottom: 12px; }
:root.density-spacious .list-item { padding: 8px 12px; }
:root.density-spacious .sidebar .section { padding: 0; }

/* ── UI text-size scale (accessibility) ──
Density only changes the root font-size, which can't move the many
hard-coded px sizes. `zoom` scales the whole UI uniformly (px text
included) while keeping layout intact, unlike `transform: scale`. */
:root.ui-scale-125 { zoom: 1.25; }
/* `zoom` makes the 100dvh shell render taller than the real viewport, which
pushes the bottom-pinned sidebar account/settings row below the fold (and
body's overflow:hidden then clips it). Shrink the shell by the same factor
so it fits the viewport exactly. */
:root.ui-scale-125 body { height: calc(100dvh / 1.25); }
/* Modals/panels under the 1.25x scale: zoom renders a centred, viewport-sized
panel ~1.25x taller, pushing its draggable header + close button off-screen
(a catch-22 — you can't reach the control to turn the size back down). Divide
each max-height by the same factor to keep the original on-screen footprint.
Desktop only — the mobile `!important` full-sheet rules win on small screens
and stay top-anchored, so their headers are already visible. */
:root.ui-scale-125 .modal-content { max-height: calc(85dvh / 1.25); }
:root.ui-scale-125 .cal-modal-content { max-height: calc(88dvh / 1.25); }
:root.ui-scale-125 .settings-modal-content { max-height: calc(85dvh / 1.25); }
:root.ui-scale-125 #theme-popup { max-height: min(calc(85dvh / 1.25), 480px); }
/* Cookbook is the one modal that set its height inline (94vh), which beat the
.modal-content compensation above and overflowed the viewport at 1.25x
(header + close button pushed off-screen). Own its height here so the same
zoom compensation applies. */
#cookbook-modal .modal-content { height: 94vh; max-height: 94vh; }
:root.ui-scale-125 #cookbook-modal .modal-content { height: calc(94dvh / 1.25); max-height: calc(94dvh / 1.25); }
/* PDF export modal also set its height inline (86vh) at v1.0; that inline cap
beat the .modal-content compensation above and shifted ~1vh at Default when
removed. Own its height here so Default is byte-for-byte 86vh and the same
1.25x compensation applies. */
.pdf-export-overlay .modal-content { max-height: 86vh; }
:root.ui-scale-125 .pdf-export-overlay .modal-content { max-height: calc(86dvh / 1.25); }
/* #endregion Density Overrides */

/* #region Background Patterns */
/* ── Background Patterns ── */

:root { --bg-effect-intensity: 1; }

/* Canvas-based effects — single source of truth for intensity */
#synapse-canvas, #rain-canvas, #constellations-canvas,
#perlin-flow-canvas, #petals-canvas, #sparkles-canvas,
#embers-canvas {
opacity: var(--bg-effect-intensity, 1);
}

body.bg-pattern-dots {
background-image: radial-gradient(color-mix(in srgb, var(--bg-effect-color, var(--fg)) calc(5% * var(--bg-effect-intensity, 1)), transparent) 1px, transparent 1px);
background-size: 20px 20px; background-attachment: fixed;
}
body.bg-pattern-synapse {
/* CSS grid as base, canvas pulses overlay */
background-image: linear-gradient(color-mix(in srgb, var(--bg-effect-color, var(--fg)) calc(3.5% * var(--bg-effect-intensity, 1)), transparent) 1px, transparent 1px),
linear-gradient(90deg, color-mix(in srgb, var(--bg-effect-color, var(--fg)) calc(3.5% * var(--bg-effect-intensity, 1)), transparent) 1px, transparent 1px);
background-size: 24px 24px; background-attachment: fixed;
}
body.bg-pattern-perlin-flow,
body.bg-pattern-petals,
body.bg-pattern-sparkles {
/* canvas-only backgrounds */
}
/* #endregion Background Patterns */
89 changes: 89 additions & 0 deletions static/css/base/tokens.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/* #region Theme Tokens */
/* ── Variables ──
*
* Theme-public variables (override via theme.js or custom themes):
* Core: --bg, --fg, --panel, --border, --red
* Syntax: --hl-keyword, --hl-string, --hl-comment, --hl-function,
* --hl-number, --hl-builtin, --hl-variable, --hl-params,
* --hl-bg, --hl-fg
* Accents: --accent-primary, --accent-error (set by theme.js)
* Semantic: --color-error, --color-success, --color-warning, --color-danger,
* --color-accent, --color-muted, --color-muted-alt
*/

:root {
/* Core palette */
--bg: #282c34;
--fg: #9cdef2;
--panel: #111;
--border: #355a66;
--red: #e06c75;
/* Were `var(--green)` / `var(--warn)` — self-referential, so they
resolved to invalid and every site fell back to its own literal
(or, for sites with no fallback, painted as transparent/inherit).
Anchor them to real hex so the token layer actually works. */
--green: #50fa7b;
--warn: #f0ad4e;

/* Syntax highlighting */
--hl-bg: #1e2228;
--hl-fg: #9cdef2;
--hl-keyword: #c678dd;
--hl-string: #e5c07b;
--hl-comment: #828997;
--hl-function: #61afef;
--hl-number: #d19a66;
--hl-builtin: #56b6c2;
--hl-variable: #abb2bf;
--hl-params: #a8c0d4;

/* Semantic colors */
--color-error: #ff4444;
--color-error-light: #ff6666;
--color-success: #4caf50;
--color-warning: #f0ad4e;
--color-danger: #c0392b;
--color-recording: #ff3b30;
--color-recording-hover: #d63031;
--color-muted: #888;
--color-muted-alt: #6b7280;
--color-accent: #00aaff;
--color-agent-active: #00ff00;
--color-brand-blue: #3b82f6;
--color-blind-orange: #ff9800;
--color-save-green: var(--color-success);
--color-link-hover: #66c7ff;
--color-subheader: #6b8a94;
--select-bg: var(--bg);
--select-fg: var(--fg);
--select-option-bg: color-mix(in srgb, var(--panel) 74%, var(--bg));
--select-option-fg: var(--fg);
--select-option-active-bg: color-mix(in srgb, var(--accent, var(--red)) 24%, var(--panel));
/* Warm accent — used by the Goals/Today UI in Notes. Lives as a token so
themes can override without touching the goal CSS. */
--accent-warm: #d19a66;

}

:root.light {
--bg: #f5f5f5;
--fg: #2b2b2b;
--panel: #fff;
--border: #bbb;
--hl-bg: #f9f9f9;
--hl-fg: #2b2b2b;
--hl-keyword: #7928a1;
--hl-string: #986801;
--hl-comment: #6a737d;
--hl-function: #005cc5;
--hl-number: #986801;
--hl-builtin: #0070a0;
--hl-variable: #383a42;
--hl-params: #4a4f5c;
--select-bg: #eaeaea;
--select-fg: var(--fg);
--select-option-bg: var(--panel);
--select-option-fg: var(--fg);
--select-option-active-bg: color-mix(in srgb, var(--red) 16%, var(--panel));
}
/* #endregion Theme Tokens */
3 changes: 3 additions & 0 deletions static/css/components/forms-and-buttons.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/* forms-and-buttons.css
Intentionally minimal while legacy duplicated rules are consolidated into
utilities/helpers-and-overrides.css to avoid double-definition drift. */
Loading