/* 00-tokens - part of the former static/style.css. * * The stylesheet is split by area, but the split is mechanical: rules were * moved verbatim and NOT regrouped. The numeric prefix is the load order, and * that order is what preserves the cascade. A rule sits in the file its * original position fell into, so an area's rules are not all in its file and * a file is not only that area's rules. * * Do not reorder the tags in static/index.html, and do not move a rule * between files: with 1,151 redeclarations and 1,886 !important in this * cascade, either can change which declaration wins. * * static/index.html and the PRECACHE list in static/sw.js must agree on this * order. tests/test_static_stylesheet_manifest.py and * tests/test_css_computed_style_snapshot.py fail if that drifts. */ /* ============================================ */ /* Odysseus UI — Consolidated Stylesheet */ /* ============================================ */ /* ── 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; /* Device safe areas (notch, Dynamic Island, home indicator) */ --safe-top: env(safe-area-inset-top, 0px); --safe-right: env(safe-area-inset-right, 0px); --safe-bottom: env(safe-area-inset-bottom, 0px); --safe-left: env(safe-area-inset-left, 0px); /* Full-height sheets start clear of the status-bar blur; flush when there is no inset */ --sheet-top: calc(var(--safe-top) + min(var(--safe-top), 24px)); --app-height: 100dvh; } /* The on-screen keyboard covers the home indicator */ :root.keyboard-open { --safe-bottom: 0px; } /* iOS standalone web apps report dvh (and the viewport) short by the status bar height; lvh still matches the screen. Body becomes the containing block for fixed elements so overlays reach the real bottom edge as well. Containment stops body's background reaching the canvas, so html paints it instead. */ @media (display-mode: standalone) { @supports (-webkit-touch-callout: none) { :root { --app-height: 100lvh; } html { height: var(--app-height); background-color: var(--bg); } body { contain: layout; overflow: clip; } } } :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)); } /* ── 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); /* Keep the base padding transition for older layout paths that still adjust the body directly. Edge docks reserve workspace room on the flex panes below so left + right docks can coexist without skewing the whole body. */ 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: var(--app-height); padding: var(--safe-top) var(--safe-right) var(--safe-bottom) var(--safe-left); overflow: hidden; } /* iOS keeps the full height when the keyboard opens; size the shell to what is visible */ :root.keyboard-open body { height: var(--keyboard-viewport-height, var(--app-height)); } /* 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: 11px; 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); } /* ── 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; }