cc-haha/desktop/src/theme/globals.css
程序员阿江(Relakkes) 41fb22790a feat: self-host fonts to eliminate Google CDN dependency
Replace Google Fonts CDN links with locally hosted woff2 files to avoid
FOUT/FOIT on slow networks and ensure the app works in regions where
Google is blocked. Material Symbols uses font-display: block to prevent
raw icon text from flashing on load.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 22:30:18 +08:00

264 lines
8.4 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@import "tailwindcss";
@plugin "@tailwindcss/typography";
/* ─── Self-hosted fonts (no Google CDN dependency) ────────────── */
/* Inter variable weight 400-600, latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400 600;
font-display: swap;
src: url('/fonts/inter-latin.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400 600;
font-display: swap;
src: url('/fonts/inter-latin-ext.woff2') format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Manrope variable weight 400-800, latin */
@font-face {
font-family: 'Manrope';
font-style: normal;
font-weight: 400 800;
font-display: swap;
src: url('/fonts/manrope-latin.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
font-family: 'Manrope';
font-style: normal;
font-weight: 400 800;
font-display: swap;
src: url('/fonts/manrope-latin-ext.woff2') format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* JetBrains Mono weight 400, latin */
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('/fonts/jetbrains-mono-latin.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('/fonts/jetbrains-mono-latin-ext.woff2') format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Material Symbols Outlined variable weight, use block to avoid showing raw text */
@font-face {
font-family: 'Material Symbols Outlined';
font-style: normal;
font-weight: 100 700;
font-display: block;
src: url('/fonts/material-symbols-outlined.woff2') format('woff2');
}
/* Code highlighting is handled by shiki/react-shiki (inline styles + CSS line numbers) */
/* ─── Shiki code viewer ───────────────────────────────────────── */
.code-viewer-area .line {
display: inline-block;
width: 100%;
padding: 1px 12px;
}
.code-viewer-area .has-line-numbers .line {
padding-left: 0;
}
.code-viewer-area .line:hover {
background: rgba(0, 0, 0, 0.03);
}
.code-viewer-area .has-line-numbers {
--line-numbers-foreground: rgba(135, 115, 109, 0.5);
--line-numbers-width: 2.5ch;
--line-numbers-padding-left: 1ch;
--line-numbers-padding-right: 1.5ch;
--line-numbers-font-size: 11px;
}
/* ─── Tailwind Theme Override (matches prototype design system) ─── */
@theme {
--color-primary: #8F482F;
--color-primary-container: #AD5F45;
--color-primary-fixed: #FFDBD0;
--color-primary-fixed-dim: #FFB59D;
--color-on-primary: #FFFFFF;
--color-on-surface: #1B1C1A;
--color-on-surface-variant: #54433E;
--color-surface: #FAF9F5;
--color-surface-bright: #FAF9F5;
--color-surface-dim: #DBDAD6;
--color-surface-container: #EFEEEA;
--color-surface-container-low: #F4F4F0;
--color-surface-container-high: #E9E8E4;
--color-surface-container-highest: #E3E2DF;
--color-surface-container-lowest: #FFFFFF;
--color-surface-variant: #E3E2DF;
--color-background: #FAF9F5;
--color-outline: #87736D;
--color-outline-variant: #DAC1BA;
--color-secondary: #2D628F;
--color-secondary-container: #9ACBFE;
--color-tertiary: #4F6237;
--color-tertiary-container: #677B4E;
--color-error: #BA1A1A;
--color-error-container: #FFDAD6;
--color-inverse-surface: #2F312E;
--color-inverse-on-surface: #F2F1ED;
--color-inverse-primary: #FFB59D;
--color-success: #16A34A;
--color-warning: #CA8A04;
--font-headline: 'Manrope', sans-serif;
--font-body: 'Inter', sans-serif;
--font-label: 'Inter', sans-serif;
--font-mono: 'JetBrains Mono', monospace;
}
/* ─── Semantic Aliases (used by layout & infrastructure components) ── */
:root {
/* Layout dimensions */
--sidebar-width: 280px;
--titlebar-height: 40px;
--statusbar-height: 36px;
/* Surface aliases */
--color-surface-sidebar: var(--color-surface-container-low);
--color-surface-hover: var(--color-surface-container-high);
--color-surface-selected: var(--color-surface-container);
/* Border aliases */
--color-border: var(--color-outline-variant);
--color-border-focus: var(--color-primary);
--color-border-separator: var(--color-outline-variant);
/* Text aliases */
--color-text-primary: var(--color-on-surface);
--color-text-secondary: var(--color-on-surface-variant);
--color-text-tertiary: var(--color-outline);
/* Info surface (for team status bar, notifications) */
--color-surface-info: var(--color-surface-container-low);
/* Brand & accents */
--color-brand: var(--color-primary);
--color-text-accent: var(--color-secondary);
/* Shadows */
--shadow-dropdown: 0 4px 20px rgba(27, 28, 26, 0.04), 0 12px 40px rgba(27, 28, 26, 0.08);
/* Button colors */
--color-btn-primary-bg: var(--color-primary);
--color-btn-primary-fg: var(--color-on-primary);
--color-btn-primary-bg-hover: var(--color-primary-container);
--color-btn-primary-bg-active: var(--color-primary);
/* User message bubble */
--color-surface-user-msg: var(--color-surface-container);
/* Radii */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
--radius-full: 9999px;
}
/* ─── Material Symbols ─────────────────────────────────────────── */
.material-symbols-outlined {
font-family: 'Material Symbols Outlined';
font-weight: normal;
font-style: normal;
font-size: 24px;
line-height: 1;
letter-spacing: normal;
text-transform: none;
display: inline-block;
white-space: nowrap;
word-wrap: normal;
direction: ltr;
-webkit-font-feature-settings: 'liga';
-webkit-font-smoothing: antialiased;
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
vertical-align: middle;
}
/* ─── Base styles ──────────────────────────────────────────────── */
* {
box-sizing: border-box;
}
html, body, #root {
height: 100%;
margin: 0;
padding: 0;
font-family: var(--font-body);
color: var(--color-on-surface);
background-color: var(--color-background);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Tauri drag region */
[data-tauri-drag-region] {
-webkit-app-region: drag;
}
button, input, textarea, select, a, [role="button"] {
-webkit-app-region: no-drag;
}
/* Custom shadow from prototype */
.custom-shadow {
box-shadow: 0 4px 20px rgba(27, 28, 26, 0.04), 0 12px 40px rgba(27, 28, 26, 0.08);
}
/* Scrollbar */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--color-outline); border-radius: 9999px; opacity: 0.3; }
::-webkit-scrollbar-thumb:hover { opacity: 0.6; }
/* Animations */
@keyframes shimmer {
0%, 100% { opacity: 0.4; }
50% { opacity: 1; }
}
@keyframes spin {
to { transform: rotate(360deg); }
}
@keyframes pulse-dot {
0%, 100% { opacity: 1; }
50% { opacity: 0.3; }
}
.animate-shimmer { animation: shimmer 1.5s ease-in-out infinite; }
.animate-spin { animation: spin 1s linear infinite; }
.animate-pulse-dot { animation: pulse-dot 1.5s ease-in-out infinite; }
/* Progress bar */
@keyframes progress-fill {
from { width: 0%; }
}