/* stylelint-disable */ @import "tailwindcss"; @config "../tailwind.config.js"; /* stylelint-enable */ @layer utilities { .line-clamp-3 { display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; } .scrollbar-hide { -ms-overflow-style: none; scrollbar-width: none; } .scrollbar-hide::-webkit-scrollbar { display: none; } .scrollbar-auto { scrollbar-width: thin; scrollbar-color: transparent transparent; overflow: auto; } .scrollbar-auto::-webkit-scrollbar { width: 8px; height: 8px; } .scrollbar-auto::-webkit-scrollbar-track { background: transparent; margin: 4px 0; } .scrollbar-auto::-webkit-scrollbar-thumb { background: transparent; border-radius: 4px; border: 2px solid transparent; background-clip: padding-box; min-height: 40px; } .scrollbar-auto:hover::-webkit-scrollbar-thumb, .scrollbar-auto.scrolling::-webkit-scrollbar-thumb, .scrollbar-auto:focus-within::-webkit-scrollbar-thumb { background: hsl(var(--foreground) / 0.25); } .scrollbar-auto::-webkit-scrollbar-thumb:hover { background: hsl(var(--foreground) / 0.4) !important; border: 1px solid transparent; } .scrollbar-auto.scrolling::-webkit-scrollbar-thumb { transition: background 0.3s ease; } /* Scrollbar layout is constant: the gutter is always reserved and only the thumb's color toggles on scroll. Toggling scrollbar-width/overflow instead changed the content width mid-scroll and jittered text and borders (#309). */ .scrollbar-on-scroll { scrollbar-width: thin; scrollbar-color: transparent transparent; } .scrollbar-on-scroll::-webkit-scrollbar { width: 8px; height: 8px; } .scrollbar-on-scroll::-webkit-scrollbar-track { background: transparent; } .scrollbar-on-scroll::-webkit-scrollbar-thumb { background: transparent; border-radius: 4px; border: 2px solid transparent; background-clip: padding-box; } .scrollbar-on-scroll.scrolling { scrollbar-color: hsl(var(--foreground) / 0.25) transparent; } .scrollbar-on-scroll.scrolling::-webkit-scrollbar-thumb { background: hsl(var(--foreground) / 0.25); } .scrollbar-on-scroll.scrolling::-webkit-scrollbar-thumb:hover { background: hsl(var(--foreground) / 0.4); } .touch-manipulation { touch-action: manipulation; } } /* User-selected reduced motion applies independently of the OS preference. */ html[data-animation='reduced'] *, html[data-animation='reduced'] *::before, html[data-animation='reduced'] *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } .hd-drag { -webkit-app-region: drag; -webkit-user-select: none; user-select: none; } .hd-btns { -webkit-app-region: no-drag; } @media (max-width: 1023px) { .hd-drag { -webkit-app-region: no-drag; } } .repository-list-syncing .repository-card, .repository-list-syncing .repository-card * { animation: none !important; transition: none !important; } .repository-card { scroll-margin: 20px; } .repository-card[data-selection-mode="true"] { scroll-margin: 0; } .category-scrollbar { scrollbar-width: thin; scrollbar-color: transparent transparent; } .category-scrollbar.is-scrolling { scrollbar-color: hsl(var(--muted-foreground) / 0.8) transparent; } .category-scrollbar::-webkit-scrollbar { width: 6px; } .category-scrollbar::-webkit-scrollbar-track { background: transparent; border-radius: 3px; } .category-scrollbar::-webkit-scrollbar-thumb { background: transparent; border-radius: 3px; transition: background 0.2s ease; } .category-scrollbar.is-scrolling::-webkit-scrollbar-thumb { background: hsl(var(--muted-foreground) / 0.8); } .readme-scrollbar { scrollbar-width: thin; scrollbar-color: hsl(var(--muted-foreground) / 0.4) transparent; } .readme-scrollbar::-webkit-scrollbar { width: 6px; } .readme-scrollbar::-webkit-scrollbar-track { background: transparent; border-radius: 3px; } .readme-scrollbar::-webkit-scrollbar-thumb { background: hsl(var(--muted-foreground) / 0.4); border-radius: 3px; transition: background 0.2s ease; } .readme-scrollbar::-webkit-scrollbar-thumb:hover { background: hsl(var(--muted-foreground) / 0.7); } .readme-scrollbar::-webkit-scrollbar-thumb:active { background: hsl(var(--muted-foreground) / 0.9); } /* ========== highlight.js Dark Mode Scope Isolation ========== */ .dark .hljs { color: #c9d1d9; background: transparent !important; } .dark .hljs-doctag, .dark .hljs-keyword, .dark .hljs-meta .hljs-keyword, .dark .hljs-template-tag, .dark .hljs-template-variable, .dark .hljs-type, .dark .hljs-variable.language_ { color: #ff7b72; } .dark .hljs-title, .dark .hljs-title.class_, .dark .hljs-title.class_.inherited__, .dark .hljs-title.function_ { color: #d2a8ff; } .dark .hljs-attr, .dark .hljs-attribute, .dark .hljs-literal, .dark .hljs-meta, .dark .hljs-number, .dark .hljs-operator, .dark .hljs-selector-attr, .dark .hljs-selector-class, .dark .hljs-selector-id, .dark .hljs-variable { color: #79c0ff; } .dark .hljs-meta .hljs-string, .dark .hljs-regexp, .dark .hljs-string { color: #a5d6ff; } .dark .hljs-built_in, .dark .hljs-symbol { color: #ffa657; } .dark .hljs-code, .dark .hljs-comment, .dark .hljs-formula { color: #8b949e; } .dark .hljs-name, .dark .hljs-quote, .dark .hljs-selector-pseudo, .dark .hljs-selector-tag { color: #7ee787; } .dark .hljs-subst { color: #c9d1d9; } .dark .hljs-section { color: #1f6feb; font-weight: 700; } .dark .hljs-bullet { color: #f2cc60; } .dark .hljs-addition { color: #aff5b4; background-color: #033a16; } .dark .hljs-deletion { color: #ffdcd7; background-color: #67060c; } .dark .hljs-params { color: #c9d1d9; } .dark .hljs-property { color: #79c0ff; } .dark .hljs-punctuation { color: #c9d1d9; } .dark .hljs-tag { color: #7ee787; } .dark .hljs-title { color: #d2a8ff; } /* ========== Base Code Block Reset ========== */ .hljs { background: transparent !important; padding: 0 !important; } @layer components { .linear-bg-base { @apply bg-background text-foreground; } .linear-bg-panel { @apply bg-card text-card-foreground; } .btn-ghost { @apply border border-transparent bg-transparent text-muted-foreground rounded-md px-3 py-1.5 transition-colors duration-200; } .btn-ghost:hover { @apply bg-accent text-accent-foreground; } .btn-ghost:focus { @apply outline-none ring-2 ring-ring ring-offset-2 ring-offset-background; } .btn-subtle { @apply bg-muted text-muted-foreground rounded-md px-[6px] py-0 transition-colors duration-200; } .btn-subtle:hover { @apply bg-accent text-accent-foreground; } .btn-primary { @apply border border-transparent bg-primary text-primary-foreground px-4 py-2 rounded-md transition-colors duration-200; } .btn-primary:hover { @apply bg-primary/90; } .btn-icon { @apply bg-background text-foreground border border-border rounded-full p-2 flex items-center justify-center transition-colors duration-200; } .btn-icon:hover { @apply bg-accent text-accent-foreground; } .pill { @apply bg-transparent text-muted-foreground px-[10px] py-0 rounded-full border border-border text-[12px] font-medium flex items-center gap-1; } .pill-success { @apply bg-success text-success-foreground rounded-full text-xs font-medium; } .badge-subtle { @apply bg-muted text-muted-foreground px-2 py-0 rounded-sm border border-border text-xs font-medium; } .input-base { @apply bg-background text-foreground border border-input rounded-md px-[14px] py-[12px] focus:outline-none focus:border-ring focus:ring-2 focus:ring-ring/20 transition-all duration-200; } .input-search { @apply bg-transparent text-foreground focus:outline-none placeholder:text-muted-foreground; } .linear-card { @apply bg-card text-card-foreground border border-border rounded-lg shadow-sm hover:bg-accent/30 transition-colors duration-200; } .linear-panel { @apply bg-card text-card-foreground border border-border rounded-lg shadow-md; } } option { @apply bg-background dark:bg-card text-foreground; } /* ========== Text Area & Input Styles ========== */ /* Selection and focus glow are token-driven; see --ui-selection/--ui-accent-ring. */ /* Smooth scrolling for text areas */ textarea { scroll-behavior: smooth; -webkit-overflow-scrolling: touch; } /* Enhanced scrollbar styling for WebKit browsers */ textarea::-webkit-scrollbar { width: 8px; height: 8px; } textarea::-webkit-scrollbar-track { background: transparent; border-radius: 4px; margin: 4px 0; } textarea::-webkit-scrollbar-thumb { background: hsl(var(--muted-foreground) / 0.4); border-radius: 4px; border: 2px solid transparent; background-clip: padding-box; transition: background-color 0.2s ease; } textarea::-webkit-scrollbar-thumb:hover { background: hsl(var(--muted-foreground) / 0.6); } /* Textarea resize handle styling */ textarea::-webkit-resizer { background-image: url("data:image/svg+xml,%3Csvg width='10' height='10' viewBox='0 0 10 10' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M9 1L1 9M9 5L5 9M9 9L9 9' stroke='%239CA3AF' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right bottom; cursor: se-resize; } .dark textarea::-webkit-resizer { background-image: url("data:image/svg+xml,%3Csvg width='10' height='10' viewBox='0 0 10 10' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M9 1L1 9M9 5L5 9M9 9L9 9' stroke='%234B5563' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E"); } /* Enhanced placeholder styling (token-driven) */ ::placeholder { color: var(--ui-placeholder); opacity: 1; } /* Responsive text sizing for better readability */ @media (max-width: 768px) { textarea, input[type="text"] { font-size: 16px; /* Prevent iOS zoom */ } } /* Print-friendly styles */ @media print { textarea, input { border: 1px solid #000; box-shadow: none; } } /* ---- 窗口级原生滚动条(仅作用于 document 滚动容器,不影响各组件 opt-in 滚动条类) ---- */ /* 固定窗口滚动槽并裁掉页面级横向溢出,避免 portal 下拉打开时 viewport 横向晃动。 */ html { overflow-x: hidden; overflow-y: scroll; scrollbar-gutter: stable; } /* Radix Select/Dialog uses react-remove-scroll and otherwise adds a body margin to compensate for a scrollbar that html already reserves permanently. */ html body[data-scroll-locked] { margin-right: 0 !important; /* react-remove-scroll sets overflow:hidden, which turns body into a scroll container and re-anchors position:sticky headers to the document top (off-screen on long pages). overflow:clip blocks scrolling without creating a scroll container, so sticky keeps anchoring to the viewport. */ overflow: clip !important; } /* body's overflow never propagates to the viewport (html owns overflow), so the root scroller must be locked directly or the page behind a modal overlay keeps scrolling (scrollbar drag + wheel). hidden — not clip — keeps the viewport a scroll container, so the scroll offset, the sticky header's anchor and the scrollbar-gutter: stable reservation all survive the lock. */ html:has(body[data-scroll-locked]) { overflow: hidden !important; } /* 窗口滚动条颜色由 --ui-line-strong 等 token 统一驱动(见文件底部 Linear 段落)。 */ /* ========== Linear Design System: application shell, surfaces and interaction states ========== */ :root { color-scheme: light; /* Canvas sits one step off-white so white cards/popovers float on it — the Linear-style surface layering that makes the shell feel native. */ --background: 210 40% 98%; --foreground: 222.2 84% 4.9%; --card: 0 0% 100%; --card-foreground: 222.2 84% 4.9%; --popover: 0 0% 100%; --popover-foreground: 222.2 84% 4.9%; --primary: 222.2 47.4% 11.2%; --primary-foreground: 210 40% 98%; --secondary: 210 40% 96.1%; --secondary-foreground: 222.2 47.4% 11.2%; --muted: 210 40% 96.1%; --muted-foreground: 215.4 16.3% 46.9%; --accent: 210 40% 92%; --accent-foreground: 222.2 47.4% 11.2%; /* red-600: white text on the old red-500 measured 3.76:1 — below the 4.5 text target. Dark mode keeps its deep red, which passes with white. */ --destructive: 0 72% 51%; --destructive-foreground: 210 40% 98%; --border: 214.3 31.8% 91.4%; --border-strong: 214.3 25% 80%; --input: 214.3 31.8% 91.4%; --ring: 222.2 84% 4.9%; --radius: 0.5rem; /* Status fills use a dark foreground in every mode. The legacy white foreground fails the 4.5:1 WCAG text target on these palettes. */ --success: 142 76% 36%; --success-foreground: 222.2 47.4% 11.2%; --warning: 34.7 94.6% 43.7%; --warning-foreground: 222.2 47.4% 11.2%; /* Scrim tokens for modal backdrops and the image lightbox — conventional dark overlays in both modes. Not part of the tweakcn palette, so theme presets cannot desaturate the scrim, but overridable here if desired. */ --overlay: 0 0% 0%; --overlay-foreground: 0 0% 100%; /* Typography stacks (theme presets may swap families). Inter leads the latin stack for the premium SaaS voice; CJK falls through to the OS face. */ --font-sans: 'Geist Variable', ui-sans-serif, system-ui, -apple-system, blinkmacsystemfont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; --font-serif: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif; --font-mono: 'Geist Mono Variable', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace; /* Elevation recipes consumed by the Tailwind boxShadow tokens. */ --shadow-color: 0 0% 0%; --shadow-opacity: 0.1; --app-shadow-subtle: 0 1px 2px rgba(0, 0, 0, 0.035); --app-shadow-elevated: 0 12px 32px rgba(0, 0, 0, 0.12); --app-shadow-dialog: 0 20px 48px rgba(0, 0, 0, 0.18), 0 2px 8px rgba(0, 0, 0, 0.08); /* Compatibility aliases for existing application-shell utilities. */ --ui-canvas: hsl(var(--background)); --ui-panel: hsl(var(--card)); --ui-panel-muted: hsl(var(--muted)); --ui-panel-hover: hsl(var(--accent)); --ui-text: hsl(var(--foreground)); --ui-text-muted: hsl(var(--muted-foreground)); --ui-text-faint: hsl(var(--muted-foreground) / 0.75); --ui-text-caption: hsl(var(--foreground)); --ui-line: hsl(var(--border)); --ui-line-subtle: hsl(var(--border) / 0.7); --ui-line-strong: hsl(var(--border-strong)); --ui-accent: hsl(var(--primary)); --ui-accent-hover: hsl(var(--primary) / 0.9); --ui-accent-soft: hsl(var(--accent)); --ui-accent-ring: hsl(var(--ring)); /* Text-selection and search-hit fills. Accent/palettes cannot be trusted here (zen-inspired light accent ≈ card made ::selection invisible, issue #348), so each theme ships derived fills with guaranteed surface contrast; values below mirror DEFAULT_*_COLORS in constants/themePresets.ts. */ --selection: 222.2 47.4% 55.5%; --selection-foreground: 222.2 84% 4.9%; --search-highlight: 222.2 28.4% 72.8%; --ui-selection: hsl(var(--selection)); --ui-selection-foreground: hsl(var(--selection-foreground)); --ui-search-highlight: hsl(var(--search-highlight)); --ui-search-highlight-foreground: hsl(var(--foreground)); /* Placeholder text must stay above 4.5:1 on the canvas (WCAG 1.4.3), so it uses the full muted-foreground token instead of an alpha wash. */ --ui-placeholder: hsl(var(--muted-foreground)); --ui-success: hsl(var(--success)); --ui-warning: hsl(var(--warning)); --ui-danger: hsl(var(--destructive)); --ui-shadow-card: 0 1px 2px rgb(0 0 0 / 0.04), 0 4px 12px rgb(0 0 0 / 0.03); --ui-shadow-float: 0 10px 24px rgb(0 0 0 / 0.08), 0 2px 6px rgb(0 0 0 / 0.04); --ui-radius-xs: calc(var(--radius) - 4px); --ui-radius-sm: calc(var(--radius) - 2px); --ui-radius-md: var(--radius); --ui-radius-lg: calc(var(--radius) + 4px); /* Application workspace layout tokens (see UI redesign plan §6.4). Layout/motion constants only — colors and fonts stay theme-driven. */ --app-shell-max-width: 90rem; --app-header-height: 3.5rem; --app-header-offset: calc(var(--app-header-height) + var(--app-border-width)); --app-gutter-inline: clamp(1rem, 3vw, 2rem); --app-content-padding-block: 1.5rem; --app-route-stack-gap: 1rem; --app-sidebar-width: 14.875rem; --app-sidebar-gap: 1.5rem; --app-sidebar-offset: 1rem; --app-section-gap: 1.5rem; --app-control-height-sm: 2rem; --app-control-height-md: 2.25rem; --app-border-width: 1px; --app-motion-fast: 120ms; --app-motion-base: 180ms; --app-z-header: 50; --app-z-sidebar: 10; --app-z-popover: 9999; --app-gist-help-popover-shift: -0.5rem; /* Desktop workspace visual tokens. Every surface derives from the active theme palette, so presets and light/dark mode remain authoritative. */ --app-canvas-surface: hsl(var(--background)); --app-canvas-wash: color-mix(in srgb, hsl(var(--background)) 88%, hsl(var(--card)) 12%); --app-canvas-image: linear-gradient(180deg, var(--app-canvas-wash), var(--app-canvas-surface)); --app-canvas-size: 100% 100%; --app-main-padding-block: 1.75rem; --app-workspace-gap: 1.125rem; --app-header-gap: 1rem; --app-header-action-gap: 0.5rem; --app-nav-tracking: -0.006em; --app-header-surface: color-mix(in srgb, hsl(var(--background)) 90%, hsl(var(--card)) 10%); --app-header-border: transparent; --app-header-shadow: none; --app-nav-surface: color-mix(in srgb, hsl(var(--muted)) 46%, transparent); --app-nav-border: color-mix(in srgb, hsl(var(--border)) 72%, transparent); --app-nav-padding: 0.1875rem; --app-nav-item-height: 2.125rem; --app-nav-item-padding-inline: 0.6875rem; --app-nav-font-size: 0.84375rem; --app-nav-font-weight: 520; --app-nav-active-font-weight: 560; --app-nav-icon-size: 0.9375rem; --app-nav-icon-stroke: 1.8; --app-nav-active-surface: color-mix(in srgb, hsl(var(--foreground)) 6%, transparent); --app-nav-active-border: transparent; --app-nav-active-shadow: none; --app-brand-mark-size: 2rem; --app-brand-mark-radius: calc(var(--radius) - 2px); --app-brand-mark-shadow: 0 1px 3px color-mix(in srgb, hsl(var(--shadow-color)) 16%, transparent); --app-brand-title-size: 0.8125rem; --app-brand-title-weight: 620; --app-brand-title-tracking: -0.014em; --app-brand-title-line-height: 1.25; --app-brand-subtitle-size: 0.65625rem; --app-brand-subtitle-color: hsl(var(--muted-foreground)); --app-brand-subtitle-line-height: 1.35; --app-header-user-name-size: 0.75rem; --app-header-user-name-weight: 550; --app-icon-size: 1rem; --app-sidebar-surface: color-mix(in srgb, hsl(var(--background)) 72%, hsl(var(--card)) 28%); --app-sidebar-border: transparent; --app-sidebar-padding: 0; --app-sidebar-padding-collapsed: 0.5rem; --app-sidebar-head-min-height: 3.25rem; --app-sidebar-head-gap: 0.5rem; --app-sidebar-head-padding-block-start: 0.5625rem; --app-sidebar-head-padding-block-end: 0.4375rem; --app-sidebar-head-padding-inline-start: 1rem; --app-sidebar-head-padding-inline-end: 0.75rem; --app-sidebar-body-padding-block-start: 0.25rem; --app-sidebar-body-padding-block-end: 0.75rem; --app-sidebar-body-padding-inline: 0.5rem; --app-sidebar-section-padding-block: 0.75rem; --app-sidebar-section-padding-inline: 0.5rem; --app-sidebar-section-gap: 0.25rem; --app-sidebar-heading-size: 0.8125rem; --app-sidebar-heading-weight: 580; --app-sidebar-heading-tracking: -0.012em; --app-sidebar-heading-color: color-mix(in srgb, hsl(var(--foreground)) 66%, hsl(var(--muted-foreground)) 34%); --app-sidebar-muted-color: color-mix(in srgb, hsl(var(--foreground)) 28%, hsl(var(--muted-foreground)) 72%); --app-sidebar-title-gap: 0.125rem; --app-sidebar-line-height: 1.2; --app-sidebar-eyebrow-size: 0.59375rem; --app-sidebar-eyebrow-weight: 560; --app-sidebar-eyebrow-tracking: 0.075em; --app-sidebar-label-size: 0.625rem; --app-sidebar-label-weight: 560; --app-sidebar-label-tracking: 0.025em; --app-sidebar-caption-size: 0.6875rem; --app-sidebar-tab-height: 2.25rem; --app-sidebar-item-height: 2.125rem; --app-sidebar-item-gap: 0.625rem; --app-sidebar-item-padding-inline: 0.625rem; --app-sidebar-item-font-size: 0.8125rem; --app-sidebar-item-font-weight: 480; --app-sidebar-item-color: color-mix(in srgb, hsl(var(--foreground)) 58%, hsl(var(--muted-foreground)) 42%); --app-sidebar-active-item-font-weight: 540; --app-sidebar-active-item-color: color-mix(in srgb, hsl(var(--foreground)) 82%, hsl(var(--muted-foreground)) 18%); --app-sidebar-active-surface: color-mix(in srgb, hsl(var(--foreground)) 6.5%, transparent); --app-sidebar-active-border: transparent; --app-sidebar-active-shadow: none; --app-sidebar-item-tracking: -0.002em; --app-sidebar-list-gap: 0.125rem; --app-side-label-margin-inline: 0.5rem; --app-side-label-padding-block-start: 0.75rem; --app-side-label-padding-block-end: 0.25rem; --app-sidebar-tab-padding-inline: 0.5rem; --app-sidebar-count-size: 0.625rem; --app-sidebar-count-color: color-mix(in srgb, hsl(var(--foreground)) 45%, hsl(var(--muted-foreground)) 55%); --app-sidebar-count-min-width: 1.375rem; --app-sidebar-count-padding-block: 0.0625rem; --app-sidebar-count-padding-inline: 0.3125rem; --app-sidebar-count-radius: 999px; --app-sidebar-section-gap: 0.375rem; --app-sidebar-control-gap: 0.375rem; --app-sidebar-control-row-min-height: 2rem; --app-sidebar-control-row-padding-inline: 0.5rem; --app-sidebar-control-row-font-size: 0.6875rem; --app-sidebar-more-height: 1.75rem; --app-sidebar-more-font-size: 0.625rem; --app-sidebar-inline-status-font-size: 0.625rem; --app-sidebar-empty-padding-block: 0.5rem; --app-sidebar-empty-padding-inline: 0.5rem; --app-sidebar-empty-font-size: 0.6875rem; --app-sidebar-empty-line-height: 1.45; --app-sidebar-foot-border: color-mix(in srgb, hsl(var(--border)) 62%, transparent); --app-sidebar-foot-padding-block: 0.625rem; --app-sidebar-foot-padding-inline: 0.75rem; --app-sidebar-foot-gap: 0.25rem; --app-sidebar-foot-status-size: 0.625rem; --app-sidebar-foot-meta-size: 0.59375rem; --app-sidebar-status-dot-size: 0.375rem; --app-sidebar-rail-gap: 0.5rem; --app-sidebar-rail-padding-block: 0.25rem; --app-sidebar-rail-divider-color: color-mix(in srgb, hsl(var(--border)) 70%, transparent); --app-sidebar-category-emoji-size: 1rem; --app-sidebar-category-emoji-line-height: 1; --app-sidebar-icon-stroke: 1.8; --app-sidebar-toggle-size: 2rem; --app-sidebar-toggle-icon-size: 1rem; --app-sidebar-toggle-icon-stroke: 1.8; --app-sidebar-toggle-radius: var(--ui-radius-sm); --app-scope-label-size: 0.625rem; --app-scope-label-color: var(--app-sidebar-muted-color); --app-scope-trigger-height: 2rem; --app-scope-trigger-padding-inline: 0.5rem; --app-scope-trigger-gap: 0.375rem; --app-scope-trigger-font-size: 0.6875rem; --app-scope-trigger-max-width: 14rem; --app-collection-row-min-height: 2rem; --app-collection-row-gap: 0.25rem; --app-collection-row-padding-inline: 0.5rem; --app-category-strip-gap: 0.5rem; --app-category-strip-padding-block-end: 0.25rem; --app-category-pill-min-width: 8.75rem; --app-page-heading-margin-block-end: 1.25rem; --app-page-title-size: 1.625rem; --app-page-title-weight: 600; --app-page-title-tracking: -0.022em; --app-workspace-header-gap: 2rem; --app-workspace-header-border: transparent; --app-workspace-header-padding-block-end: 0; --app-workspace-header-margin-block-end: 1.25rem; --app-workspace-breadcrumb-size: 0.625rem; --app-workspace-breadcrumb-weight: 600; --app-workspace-breadcrumb-tracking: 0.08em; --app-workspace-breadcrumb-gap: 0.375rem; --app-workspace-breadcrumb-margin-block-end: 0.4375rem; --app-workspace-title-size: 1.75rem; --app-workspace-title-weight: 600; --app-workspace-title-tracking: -0.025em; --app-workspace-title-line-height: 1.15; --app-workspace-title-row-gap: 0.625rem; --app-workspace-description-max-width: 64rem; --app-workspace-description-margin-block-start: 0.4375rem; --app-workspace-description-color: hsl(var(--muted-foreground)); --app-workspace-description-size: 0.8125rem; --app-workspace-description-line-height: 1.55; --app-workspace-meta-gap: 0.375rem; --app-workspace-meta-size: 0.6875rem; --app-workspace-meta-height: 1.625rem; --app-workspace-meta-padding-inline: 0.5625rem; --app-workspace-meta-border: color-mix(in srgb, hsl(var(--border)) 62%, transparent); --app-workspace-meta-surface: color-mix(in srgb, hsl(var(--card)) 76%, transparent); --app-workspace-actions-gap: 0.5rem; --app-workspace-header-note-size: 0.6875rem; --app-workspace-header-note-color: hsl(var(--muted-foreground)); --app-hover-surface: color-mix(in srgb, hsl(var(--foreground)) 4%, transparent); --app-count-surface: color-mix(in srgb, hsl(var(--foreground)) 7%, transparent); --app-count-active-surface: color-mix(in srgb, hsl(var(--primary)) 15%, transparent); --app-toolbar-surface: hsl(var(--card)); --app-toolbar-border: color-mix(in srgb, hsl(var(--border)) 58%, transparent); --app-toolbar-shadow: 0 1px 2px color-mix(in srgb, hsl(var(--shadow-color)) 3%, transparent); --app-toolbar-padding: 1rem; --app-panel-surface: hsl(var(--card)); --app-panel-border: color-mix(in srgb, hsl(var(--border)) 62%, transparent); --app-panel-shadow: 0 1px 2px color-mix(in srgb, hsl(var(--shadow-color)) 3%, transparent); --app-panel-hover-border: color-mix(in srgb, hsl(var(--border-strong)) 58%, hsl(var(--border))); --app-panel-hover-shadow: 0 1px 2px color-mix(in srgb, hsl(var(--shadow-color)) 4%, transparent), 0 10px 24px color-mix(in srgb, hsl(var(--shadow-color)) 5%, transparent); --app-active-surface: color-mix(in srgb, hsl(var(--primary)) 8%, hsl(var(--card)) 92%); --app-active-border: color-mix(in srgb, hsl(var(--primary)) 24%, hsl(var(--border)) 76%); --app-active-text: hsl(var(--primary-emphasis, var(--primary))); --app-active-shadow: inset 2px 0 0 hsl(var(--primary)); --app-workspace-surface: hsl(var(--card)); --app-workspace-min-height: calc(100dvh - var(--app-header-offset)); --app-settings-section-surface: transparent; --app-settings-section-border: transparent; --app-settings-section-radius: 0; --app-settings-section-shadow: none; --app-fork-list-gap: 0; --app-fork-list-item-surface: transparent; --app-fork-list-item-hover-surface: var(--app-hover-surface); --app-fork-list-item-border: color-mix(in srgb, hsl(var(--border)) 56%, transparent); --app-fork-list-item-radius: 0; --app-fork-list-item-shadow: none; --app-radius-shell: calc(var(--radius) + 2px); --app-radius-control: calc(var(--radius) - 2px); --app-motion-surface: background-color var(--app-motion-fast) ease, border-color var(--app-motion-fast) ease, color var(--app-motion-fast) ease, box-shadow var(--app-motion-base) ease; } html.dark { color-scheme: dark; --background: 222.2 84% 4.9%; --foreground: 210 40% 98%; --card: 222.2 47.4% 11.2%; --card-foreground: 210 40% 98%; --popover: 222.2 47.4% 11.2%; --popover-foreground: 210 40% 98%; --primary: 210 40% 98%; --primary-foreground: 222.2 47.4% 11.2%; --secondary: 217.2 32.6% 17.5%; --secondary-foreground: 210 40% 98%; --muted: 217.2 32.6% 17.5%; --muted-foreground: 215 20.2% 65.1%; --accent: 217.2 32.6% 21%; --accent-foreground: 210 40% 98%; --destructive: 0 62.8% 30.6%; --destructive-foreground: 210 40% 98%; --border: 217.2 32.6% 17.5%; --border-strong: 217.2 32.6% 28%; --input: 217.2 32.6% 17.5%; --ring: 212.7 26.8% 83.9%; --success: 141 69% 58%; --warning: 43 96% 56%; /* Status fills use a dark foreground in both modes: white falls below the WCAG text contrast target on the saturated success/warning palettes. */ --success-foreground: 222.2 47.4% 11.2%; --warning-foreground: 222.2 47.4% 11.2%; /* Selection and search-hit fills re-derive per mode for the same guaranteed-contrast reasons as the light block above. */ --selection: 210 40% 40%; --selection-foreground: 210 40% 98%; --search-highlight: 210 24% 29.6%; --ui-selection: hsl(var(--selection)); --ui-selection-foreground: hsl(var(--selection-foreground)); --ui-search-highlight: hsl(var(--search-highlight)); --ui-search-highlight-foreground: hsl(var(--foreground)); --ui-placeholder: hsl(var(--muted-foreground)); --ui-canvas: hsl(var(--background)); --ui-panel: hsl(var(--card)); --ui-panel-muted: hsl(var(--muted)); --ui-panel-hover: hsl(var(--accent)); --ui-text: hsl(var(--foreground)); --ui-text-muted: hsl(var(--muted-foreground)); --ui-text-faint: hsl(var(--muted-foreground) / 0.75); --ui-line: hsl(var(--border)); --ui-line-subtle: hsl(var(--border) / 0.7); --ui-line-strong: hsl(var(--border-strong)); --ui-accent: hsl(var(--primary)); --ui-accent-hover: hsl(var(--primary) / 0.9); --ui-accent-soft: hsl(var(--accent)); --ui-accent-ring: hsl(var(--ring)); --ui-success: hsl(var(--success)); --ui-warning: hsl(var(--warning)); --ui-danger: hsl(var(--destructive)); --ui-shadow-card: 0 1px 2px rgb(0 0 0 / 0.3); --ui-shadow-float: 0 18px 36px rgb(0 0 0 / 0.35), 0 2px 8px rgb(0 0 0 / 0.2); } html, body, #root { min-height: 100%; } @layer base { * { @apply border-border; } } body { @apply bg-background text-foreground font-sans; font-feature-settings: normal; letter-spacing: normal; /* Root-level smoothing: on macOS text otherwise renders heavier than the design intends. Set once here, never per component. */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } button, a, input, select, textarea { -webkit-tap-highlight-color: transparent; } button:focus-visible, a:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible, [role="button"]:focus-visible { outline: 2px solid hsl(var(--ring)); outline-offset: 2px; } /* Use one quiet, intentional treatment for application containers. */ .ui-shell { background: hsl(var(--background)); color: hsl(var(--foreground)); } .ui-panel { background: hsl(var(--card)); color: hsl(var(--card-foreground)); border: 1px solid hsl(var(--border)); border-radius: var(--ui-radius-md); box-shadow: var(--ui-shadow-card); } .ui-toolbar { background: hsl(var(--card)); color: hsl(var(--card-foreground)); border: 1px solid hsl(var(--border)); border-radius: var(--ui-radius-sm); box-shadow: var(--ui-shadow-card); } .ui-card { background: hsl(var(--card)); color: hsl(var(--card-foreground)); border: 1px solid hsl(var(--border)); border-radius: var(--ui-radius-md); background-clip: padding-box; box-shadow: var(--ui-shadow-card); transition: border-color 150ms ease, box-shadow 150ms ease; } /* Recessed content lives inside cards without introducing a new visual system. It uses the theme canvas and the smaller native radius to retain hierarchy. */ .ui-inset-surface { background: hsl(var(--background)); color: hsl(var(--foreground)); border: 1px solid hsl(var(--border)); border-radius: var(--ui-radius-sm); background-clip: padding-box; box-shadow: inset 0 1px 0 hsl(var(--foreground) / 0.03); } /* Application workspace shell (UI redesign plan §6). Layout only: document stays the single scroll root and sidebars must not clip portal popovers. */ .app-main { width: 100%; max-width: var(--app-shell-max-width); margin-inline: auto; padding: var(--app-main-padding-block) var(--app-gutter-inline); } .app-header-inner { max-width: var(--app-shell-max-width); margin-inline: auto; padding-inline: var(--app-gutter-inline); } .route-workspace { display: flex; flex-direction: column; gap: var(--app-route-stack-gap); } @media (min-width: 1024px) { .app-main { padding: 0; } .route-workspace { flex-direction: row; align-items: flex-start; gap: 0; } .workspace-content { padding: var(--app-content-padding-block) var(--app-gutter-inline); } } .workspace-content { flex: 1 1 0%; min-width: 0; } .settings-mobile-tabs { margin-inline: calc(-1 * var(--app-gutter-inline)); } .context-sidebar { background: hsl(var(--card)); color: hsl(var(--card-foreground)); z-index: var(--app-z-sidebar); } @media (min-width: 1024px) { .context-sidebar { display: flex; flex-direction: column; position: sticky; top: var(--app-header-offset); max-height: none; overflow: visible; } /* Settings 的 14–15 个 Tab 超出小视口高度;保持 document 唯一滚动根,让标签随文档滚动。 */ .context-sidebar[data-context-sidebar='settings'] { position: static; max-height: none; overflow: visible; } } .context-sidebar-section { display: flex; flex-direction: column; padding: var(--app-sidebar-section-padding-block) var(--app-sidebar-section-padding-inline); border-bottom: var(--app-border-width) solid var(--app-sidebar-border); } .context-sidebar-group { display: flex; flex-direction: column; gap: var(--app-sidebar-section-gap); } .context-sidebar-head { display: flex; min-height: var(--app-sidebar-head-min-height); align-items: center; justify-content: space-between; gap: var(--app-sidebar-head-gap); padding: var(--app-sidebar-head-padding-block-start) var(--app-sidebar-head-padding-inline-end) var(--app-sidebar-head-padding-block-end) var(--app-sidebar-head-padding-inline-start); } .context-sidebar-title { margin: 0; color: hsl(var(--foreground)); font-size: var(--app-sidebar-heading-size); font-weight: var(--app-sidebar-heading-weight); letter-spacing: var(--app-sidebar-heading-tracking); } .context-sidebar-body { display: flex; flex-direction: column; padding: var(--app-sidebar-body-padding-block-start) var(--app-sidebar-body-padding-inline) var(--app-sidebar-body-padding-block-end); } .app-collection-row { display: flex; min-height: var(--app-collection-row-min-height); align-items: center; justify-content: space-between; gap: var(--app-collection-row-gap); padding-inline: var(--app-collection-row-padding-inline); } .app-page-heading { display: flex; align-items: center; justify-content: space-between; gap: var(--app-sidebar-head-gap); margin-block-end: var(--app-page-heading-margin-block-end); } .app-page-title { margin: 0; color: hsl(var(--foreground)); font-size: var(--app-page-title-size); font-weight: var(--app-page-title-weight); letter-spacing: var(--app-page-title-tracking); } .app-workspace-page-header { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--app-workspace-header-gap); margin-block-end: var(--app-workspace-header-margin-block-end); padding-block-end: var(--app-workspace-header-padding-block-end); border-bottom: var(--app-border-width) solid var(--app-workspace-header-border); } .app-workspace-page-header-copy { min-width: 0; } .app-workspace-breadcrumb { display: flex; align-items: center; gap: var(--app-workspace-breadcrumb-gap); margin-block-end: var(--app-workspace-breadcrumb-margin-block-end); color: var(--app-sidebar-muted-color); font-size: var(--app-workspace-breadcrumb-size); font-weight: var(--app-workspace-breadcrumb-weight); letter-spacing: var(--app-workspace-breadcrumb-tracking); text-transform: uppercase; } .app-workspace-title-row { display: flex; min-width: 0; flex-wrap: wrap; align-items: center; gap: var(--app-workspace-title-row-gap); } .app-workspace-title { margin: 0; color: hsl(var(--foreground)); font-size: var(--app-workspace-title-size); font-weight: var(--app-workspace-title-weight); letter-spacing: var(--app-workspace-title-tracking); line-height: var(--app-workspace-title-line-height); } .app-workspace-description { max-width: var(--app-workspace-description-max-width); margin: var(--app-workspace-description-margin-block-start) 0 0; color: var(--app-workspace-description-color); font-size: var(--app-workspace-description-size); line-height: var(--app-workspace-description-line-height); } .app-workspace-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--app-workspace-meta-gap); } .app-workspace-meta-pill { display: inline-flex; min-height: var(--app-workspace-meta-height); align-items: center; padding-inline: var(--app-workspace-meta-padding-inline); border: var(--app-border-width) solid var(--app-workspace-meta-border); border-radius: var(--app-sidebar-count-radius); background: var(--app-workspace-meta-surface); color: hsl(var(--muted-foreground)); font-size: var(--app-workspace-meta-size); font-variant-numeric: tabular-nums; } .app-workspace-page-actions { display: flex; flex: none; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--app-workspace-actions-gap); } .app-workspace-header-note { color: var(--app-workspace-header-note-color); font-size: var(--app-workspace-header-note-size); white-space: nowrap; } .workspace-toolbar { display: flex; flex-direction: column; gap: var(--app-sidebar-gap); } /* Interactive card surfaces share the same quiet elevation in every view. Selected and expanded cards retain their own ring/shadow treatment while still receiving the shared hover border. */ .ui-card:hover { border-color: hsl(var(--ring) / 0.5); } .ui-card:not(.linear-card-selected):not(.is-expanded):not(.ring-1):hover { box-shadow: var(--ui-shadow-float); } .ui-divider { border-color: var(--ui-line) !important; } .ui-field { color: hsl(var(--foreground)); background: hsl(var(--background)); border: 1px solid hsl(var(--input)); border-radius: var(--ui-radius-sm); box-shadow: none; } .ui-field::placeholder { color: var(--ui-text-muted); } .ui-field:hover { border-color: hsl(var(--ring)); } .ui-field:focus { background: hsl(var(--background)); border-color: hsl(var(--ring)); box-shadow: 0 0 0 3px hsl(var(--ring) / 0.2); } .ui-button { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; color: hsl(var(--foreground)); background: hsl(var(--background)); border: 1px solid hsl(var(--input)); border-radius: var(--ui-radius-sm); transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease; } .ui-button:hover { color: hsl(var(--accent-foreground)); background: hsl(var(--accent)); border-color: hsl(var(--input)); } .ui-button-primary { color: hsl(var(--primary-foreground)); background: hsl(var(--primary)); border: 1px solid transparent; border-radius: var(--ui-radius-sm); transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease; } .ui-button-primary:hover { background: hsl(var(--primary) / 0.9); border-color: transparent; } .ui-button:active, .ui-button-primary:active { transform: scale(0.96); } .ui-icon-button { color: hsl(var(--muted-foreground)); background: transparent; border: 1px solid transparent; border-radius: var(--ui-radius-sm); transition: background-color 150ms ease, color 150ms ease, border-color 150ms ease; } .ui-icon-button:hover { color: hsl(var(--accent-foreground)); background: hsl(var(--accent)); border-color: transparent; } .ui-chip { color: hsl(var(--muted-foreground)); background: hsl(var(--muted)); border: 1px solid hsl(var(--border)); border-radius: var(--ui-radius-sm); } .ui-chip-active { color: hsl(var(--primary-emphasis, var(--primary))); background: hsl(var(--primary) / 0.1); border-color: hsl(var(--primary) / 0.35); } /* `--primary` remains the user's solid fill; text uses the contrast-safe derivative. */ .text-primary { color: hsl(var(--primary-emphasis, var(--primary))); } /* Component-level class consolidation for existing Tailwind primitives. */ .dark .linear-bg-base { background-color: var(--ui-canvas); } .dark .linear-bg-panel { background-color: var(--ui-panel); } textarea:focus, input:focus, select:focus { outline: 2px solid hsl(var(--ring)); outline-offset: 2px; } ::selection { color: var(--ui-selection-foreground); background: var(--ui-selection); } .search-result-highlight { color: var(--ui-search-highlight-foreground); background: var(--ui-search-highlight); border-radius: 0.25rem; box-decoration-break: clone; -webkit-box-decoration-break: clone; } /* Narrow, low-contrast scrolling aligned with the rest of the application chrome. */ html { scrollbar-width: thin; scrollbar-color: var(--ui-line-strong) transparent; } html::-webkit-scrollbar { width: 10px; height: 10px; } html::-webkit-scrollbar-thumb { background: var(--ui-line-strong); border: 3px solid transparent; border-radius: 999px; background-clip: padding-box; } html::-webkit-scrollbar-thumb:hover { background: var(--ui-text-faint); border: 3px solid transparent; background-clip: padding-box; } /* Application chrome: low-noise framing, clear active state, no decorative gradients. */ .linear-header { background: hsl(var(--background) / 0.95); border-bottom: 1px solid hsl(var(--border)); backdrop-filter: blur(12px) saturate(1.4); -webkit-backdrop-filter: blur(12px) saturate(1.4); } .linear-header-inner { position: relative; height: var(--app-header-height); } .linear-header-inner::after { display: none; } .linear-nav-item { color: var(--ui-text-muted); background: transparent; border: 1px solid transparent; border-radius: var(--ui-radius-sm); transition: color 150ms ease, background-color 150ms ease, border-color 150ms ease; } .linear-nav-item:hover { color: hsl(var(--accent-foreground)); background: hsl(var(--accent)); } .linear-nav-item.is-active { color: hsl(var(--accent-foreground)); background: hsl(var(--accent)); border-color: hsl(var(--border)); box-shadow: none; } .linear-icon-button { color: var(--ui-text-muted); background: transparent; border: 1px solid transparent; border-radius: var(--ui-radius-sm); transition: color 150ms ease, background-color 150ms ease, border-color 150ms ease; } .linear-icon-button:hover { color: hsl(var(--accent-foreground)); background: hsl(var(--accent)); border-color: transparent; } .linear-sidebar { background: hsl(var(--card)); color: hsl(var(--card-foreground)); border: 1px solid hsl(var(--border)); border-radius: var(--ui-radius-md); box-shadow: var(--ui-shadow-card); } .linear-sidebar button:focus-visible { position: relative; z-index: 1; } .linear-sidebar .category-scrollbar::-webkit-scrollbar-thumb { background: var(--ui-line-strong); } .linear-sidebar .category-scrollbar::-webkit-scrollbar-thumb:hover { background: var(--ui-text-faint); } /* Dense search controls retain a clear state without stacking heavy surfaces. */ .linear-filter-toggle, .linear-filter-chip { color: hsl(var(--muted-foreground)); background: hsl(var(--muted)); border: 1px solid hsl(var(--border)); border-radius: var(--ui-radius-sm); transition: color 150ms ease, background-color 150ms ease, border-color 150ms ease; } .linear-filter-toggle:hover, .linear-filter-chip:hover { color: hsl(var(--accent-foreground)); background: hsl(var(--accent)); border-color: hsl(var(--ring) / 0.5); } /* Active filter state uses the app-wide selected-item language (primary tint) instead of solid accent, which is vivid in several theme presets. */ .linear-filter-toggle.is-active, .linear-filter-chip.is-active { color: hsl(var(--primary-emphasis, var(--primary))); background: hsl(var(--primary) / 0.1); border-color: hsl(var(--primary) / 0.35); } .linear-filter-toggle .filter-badge { color: hsl(var(--primary-foreground)); background: var(--ui-accent); } .ui-menu { background: hsl(var(--popover)); color: hsl(var(--popover-foreground)); border: 1px solid hsl(var(--border)); border-radius: var(--ui-radius-sm); box-shadow: var(--ui-shadow-float); } .ui-menu-item { color: hsl(var(--muted-foreground)); transition: color 150ms ease, background-color 150ms ease; } .ui-menu-item:hover { color: hsl(var(--accent-foreground)); background: hsl(var(--accent)); } /* Repository surfaces: an active item receives an accent line, not a heavy fill. Keeping the card surface intact avoids inheriting an incompatible text color from a theme's accent token while the ring remains visually unambiguous. */ .linear-card-selected { background: hsl(var(--card)); border-color: hsl(var(--ring) / 0.65); box-shadow: 0 0 0 1px hsl(var(--ring) / 0.28), var(--ui-shadow-card); } .linear-card-tag { color: hsl(var(--muted-foreground)); background: hsl(var(--muted)); border: 1px solid hsl(var(--border)); border-radius: var(--ui-radius-sm); } .linear-platform-icon { color: hsl(var(--muted-foreground)); background: hsl(var(--muted)); border: 1px solid hsl(var(--border)); border-radius: var(--ui-radius-sm); } /* Release 资产行的方形平台徽章:容器为 muted 底,用 card 底 + 边框做出层次 */ .asset-platform-badge { display: inline-flex; align-items: center; justify-content: center; width: 1.125rem; height: 1.125rem; color: hsl(var(--muted-foreground)); background: hsl(var(--card)); border: 1px solid hsl(var(--border)); border-radius: 0.25rem; } .repository-card .status, .repository-card [class~="text-green-600"] { color: var(--ui-success); } /* 展开态使用柔和浅色表面:资产列表容器比卡片更浅(light 下接近白色) */ .release-card.is-expanded { background: hsl(var(--muted)); border-color: hsl(var(--ring) / 0.5); box-shadow: 0 0 0 1px hsl(var(--ring) / 0.2); } html.dark .release-card.is-expanded { background-image: linear-gradient(hsl(var(--foreground) / 0.16), hsl(var(--foreground) / 0.16)); background-color: hsl(var(--card)); } /* 折叠容器:延迟切换 visibility,既保住 grid-rows 折叠/展开动画, 又让折叠内容离开 Tab 焦点序与无障碍树(与 hidden 属性的可达性效果一致) */ .collapse-hidden { visibility: hidden; transition: visibility 0s linear 300ms; } .linear-release-action { color: hsl(var(--muted-foreground)); background: hsl(var(--muted)); border: 1px solid hsl(var(--border)); border-radius: var(--ui-radius-sm); transition: color 150ms ease, background-color 150ms ease, border-color 150ms ease; } .linear-release-action:hover { color: hsl(var(--accent-foreground)); background: hsl(var(--accent)); border-color: hsl(var(--ring) / 0.5); } .ui-empty-state { color: hsl(var(--muted-foreground)); background: hsl(var(--card)); border: var(--app-border-width) solid var(--app-panel-border); border-radius: var(--ui-radius-md); } /* Floating layers use one elevated surface across settings, forms and details. */ .linear-modal-backdrop { background: hsl(var(--overlay) / 0.5); backdrop-filter: blur(2px); } .linear-modal { background: hsl(var(--card)); color: hsl(var(--card-foreground)); border: 1px solid hsl(var(--border)); border-radius: var(--ui-radius-md); box-shadow: var(--ui-shadow-float); } .linear-settings-nav-item { color: var(--ui-text-muted); background: transparent; border: 1px solid transparent; border-radius: var(--ui-radius-sm); transition: color 150ms ease, background-color 150ms ease, border-color 150ms ease; } .linear-settings-nav-item:hover { color: hsl(var(--foreground)); background: var(--app-hover-surface); } .linear-settings-nav-item.is-active { color: var(--app-active-text); background: var(--app-active-surface); border-color: var(--app-active-border); box-shadow: var(--app-active-shadow); } /* Desktop workspace visual layer. Layout stays unchanged; these rules turn the existing shell classes into one quiet, native-feeling application chrome. */ .ui-shell { background-color: var(--app-canvas-surface); background-image: var(--app-canvas-image); background-size: var(--app-canvas-size); } .app-main { padding: var(--app-main-padding-block) var(--app-gutter-inline); } .route-workspace { gap: var(--app-route-stack-gap); } .linear-header { background: var(--app-header-surface); border-bottom-color: var(--app-header-border); box-shadow: var(--app-header-shadow); } .linear-header-inner { gap: var(--app-header-gap); } .app-brand-title { color: hsl(var(--foreground)); font-size: var(--app-brand-title-size); font-weight: var(--app-brand-title-weight); letter-spacing: var(--app-brand-title-tracking); line-height: var(--app-brand-title-line-height); } .app-brand-subtitle { color: var(--app-brand-subtitle-color); font-size: var(--app-brand-subtitle-size); line-height: var(--app-brand-subtitle-line-height); } .app-header-user-name { color: hsl(var(--foreground)); font-size: var(--app-header-user-name-size); font-weight: var(--app-header-user-name-weight); } .app-brand-mark { width: var(--app-brand-mark-size); height: var(--app-brand-mark-size); border-radius: var(--app-brand-mark-radius); box-shadow: var(--app-brand-mark-shadow); } .app-header-nav { padding: 0; background: transparent; border: 0; border-radius: 0; } .app-header-nav button { height: var(--app-nav-item-height); padding-inline: var(--app-nav-item-padding-inline); border-radius: var(--app-radius-control); color: hsl(var(--muted-foreground)); font-size: var(--app-nav-font-size); font-weight: var(--app-nav-font-weight); letter-spacing: var(--app-nav-tracking); transition: var(--app-motion-surface); } .app-header-nav button:hover { background: var(--app-hover-surface); color: hsl(var(--foreground)); } .app-header-nav button[aria-pressed='true'] { background: var(--app-nav-active-surface); border-color: var(--app-nav-active-border); color: hsl(var(--foreground)); box-shadow: var(--app-nav-active-shadow); font-weight: var(--app-nav-active-font-weight); } .app-header-nav button[aria-pressed='true'] svg { color: hsl(var(--foreground)); } .app-header-nav svg { width: var(--app-nav-icon-size); height: var(--app-nav-icon-size); stroke-width: var(--app-nav-icon-stroke); } .app-header-actions { gap: var(--app-header-action-gap); } .context-sidebar, .linear-sidebar { /* Fallback for browsers without color-mix support. */ background: hsl(var(--card)); border: 0; border-radius: 0; box-shadow: none; font-synthesis: none; } .workspace-content { background: var(--app-workspace-surface); } @media (min-width: 1024px) { .app-main { padding: 0; } .route-workspace { gap: 0; } .workspace-content { min-height: var(--app-workspace-min-height); padding: var(--app-content-padding-block) var(--app-gutter-inline); } .route-workspace > [data-context-sidebar] { min-height: calc(100dvh - var(--app-header-offset)); margin-block-start: 0; } .context-sidebar, .linear-sidebar { border-right: 0; } } @supports (background: color-mix(in srgb, red 50%, blue)) { :root { --ui-text-caption: color-mix( in srgb, hsl(var(--foreground)) 50%, hsl(var(--muted-foreground)) ); } .context-sidebar, .linear-sidebar { background: var(--app-sidebar-surface); } @media (min-width: 1024px) { .context-sidebar, .linear-sidebar { border-right-color: var(--app-sidebar-border); } } } .context-sidebar-title { font-size: var(--app-sidebar-heading-size); font-weight: var(--app-sidebar-heading-weight); letter-spacing: var(--app-sidebar-heading-tracking); } .context-sidebar [role='tab'] { min-height: var(--app-sidebar-tab-height); padding: var(--app-sidebar-count-padding-block) var(--app-sidebar-tab-padding-inline); border-radius: var(--app-radius-control); color: hsl(var(--muted-foreground)); transition: var(--app-motion-surface); } .context-sidebar [role='tab']:hover { background: var(--app-hover-surface); color: hsl(var(--foreground)); } .context-sidebar [role='tab'][aria-selected='true'] { background: var(--app-sidebar-active-surface); border-color: var(--app-sidebar-active-border); color: var(--app-sidebar-active-item-color); box-shadow: var(--app-sidebar-active-shadow); font-weight: var(--app-sidebar-active-item-font-weight); } .context-sidebar [role='tab'][aria-selected='true'] .app-side-count { background: var(--app-count-active-surface); color: var(--app-sidebar-active-item-color); } .context-sidebar [role='tab'] svg, .linear-sidebar [role='tab'] svg { width: var(--app-icon-size); height: var(--app-icon-size); } .linear-sidebar { min-height: calc(100dvh - var(--app-header-offset)); padding: var(--app-sidebar-padding); } .linear-sidebar.is-collapsed { padding: var(--app-sidebar-padding-collapsed); } .linear-sidebar button[aria-pressed='true'] { background: var(--app-sidebar-active-surface); border-color: var(--app-sidebar-active-border); color: var(--app-sidebar-active-item-color); box-shadow: var(--app-sidebar-active-shadow); font-weight: var(--app-sidebar-active-item-font-weight); } .linear-sidebar button[aria-pressed='false']:hover { background: var(--app-hover-surface); color: hsl(var(--foreground)); } .ui-toolbar { padding: var(--app-toolbar-padding); background: var(--app-toolbar-surface); border-color: var(--app-toolbar-border); border-radius: var(--app-radius-shell); box-shadow: var(--app-toolbar-shadow); } .ui-panel { background: var(--app-panel-surface); border-color: var(--app-panel-border); border-radius: var(--app-radius-shell); box-shadow: var(--app-panel-shadow); } .ui-card { background: var(--app-panel-surface); border-color: var(--app-panel-border); border-radius: var(--app-radius-shell); box-shadow: var(--app-panel-shadow); transition: var(--app-motion-surface); } .ui-card:not(.linear-card-selected):hover { border-color: var(--app-panel-hover-border); box-shadow: var(--app-panel-hover-shadow); } /* Auth is part of the application, not a marketing landing page. */ .linear-login-shell { position: relative; overflow: hidden; background: var(--ui-canvas); } .linear-login-shell::before { display: none; } .linear-login-shell > * { position: relative; } .linear-login-toggle, .linear-login-theme, .linear-login-card, .linear-login-mark { background: var(--ui-panel); border: 1px solid var(--ui-line); box-shadow: var(--ui-shadow-card); } .linear-login-toggle { border-radius: var(--ui-radius-sm); } .linear-login-theme { box-shadow: var(--ui-shadow-card); } .linear-login-language { color: var(--ui-text-muted); background: transparent; border: 0; transition: color 150ms ease, background-color 150ms ease; } .linear-login-language:hover { color: hsl(var(--accent-foreground)); background: hsl(var(--accent)); } .linear-login-language.is-active { color: hsl(var(--primary-foreground)); background: hsl(var(--primary)); } .linear-login-mark { border-radius: var(--ui-radius-md); box-shadow: 0 12px 28px color-mix(in srgb, var(--ui-accent) 14%, transparent); } .linear-login-card { border-radius: var(--ui-radius-lg); box-shadow: var(--ui-shadow-float); } .linear-login-help { background: var(--ui-panel-muted); border: 1px solid var(--ui-line-subtle); border-radius: var(--ui-radius-md); } /* ========== prefers-reduced-motion: collapse all non-essential motion ========== Movement, loops and slides become instant; color/opacity feedback survives via the state cues themselves. Spinning loaders are re-enabled below: their rotation is functional progress feedback (a frozen spinner reads as a hang), and it stays confined to a tiny icon area. */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } .animate-spin { animation-duration: 1.2s !important; animation-iteration-count: infinite !important; } } /* Option-1 prototype sidebar language: mono uppercase eyebrow + compact semibold heading + quiet group labels + right-aligned tabular count badges. Pure visual layer; components keep their existing layout and handlers. */ .app-side-eyebrow { color: var(--app-sidebar-muted-color); font-family: var(--font-mono); font-size: var(--app-sidebar-eyebrow-size); font-weight: var(--app-sidebar-eyebrow-weight); letter-spacing: var(--app-sidebar-eyebrow-tracking); text-transform: uppercase; } .app-side-title { margin-block-start: var(--app-sidebar-title-gap); color: var(--app-sidebar-heading-color); font-size: var(--app-sidebar-heading-size); font-weight: var(--app-sidebar-heading-weight); letter-spacing: var(--app-sidebar-heading-tracking); line-height: var(--app-sidebar-line-height); } .app-section-label { color: var(--app-sidebar-muted-color); font-size: var(--app-sidebar-label-size); font-weight: var(--app-sidebar-label-weight); letter-spacing: var(--app-sidebar-label-tracking); } .app-side-group-label { margin-inline: var(--app-side-label-margin-inline); padding-block: var(--app-side-label-padding-block-start) var(--app-side-label-padding-block-end); } .app-side-count { color: var(--app-sidebar-count-color); background: var(--app-count-surface); font-family: var(--font-mono); font-size: var(--app-sidebar-count-size); font-variant-numeric: tabular-nums; min-width: var(--app-sidebar-count-min-width); padding: var(--app-sidebar-count-padding-block) var(--app-sidebar-count-padding-inline); border-radius: var(--app-sidebar-count-radius); text-align: center; } .app-side-item { position: relative; display: flex; width: 100%; min-height: var(--app-sidebar-item-height); align-items: center; gap: var(--app-sidebar-item-gap); padding-inline: var(--app-sidebar-item-padding-inline); border: 1px solid transparent; border-radius: var(--ui-radius-sm); color: var(--app-sidebar-item-color); font-size: var(--app-sidebar-item-font-size); font-weight: var(--app-sidebar-item-font-weight); letter-spacing: var(--app-sidebar-item-tracking); transition: var(--app-motion-surface), opacity var(--app-motion-base) ease, transform var(--app-motion-base) ease; } .app-side-item[aria-pressed='false']:hover { background: var(--app-hover-surface); color: hsl(var(--foreground)); } .app-side-item:hover svg, .app-side-item[aria-pressed='true'] svg { color: currentColor; } .app-side-item[aria-pressed='true'] { background: var(--app-sidebar-active-surface); border-color: var(--app-sidebar-active-border); color: var(--app-sidebar-active-item-color); box-shadow: var(--app-sidebar-active-shadow); font-weight: var(--app-sidebar-active-item-font-weight); } .app-side-item[aria-pressed='true'] .app-side-count, .linear-settings-nav-item.is-active .app-side-count { background: var(--app-count-active-surface); color: var(--app-sidebar-active-item-color); } .app-side-item svg { width: var(--app-icon-size); height: var(--app-icon-size); stroke-width: var(--app-sidebar-icon-stroke); } .app-sidebar-toggle { width: var(--app-sidebar-toggle-size); height: var(--app-sidebar-toggle-size); flex: none; padding: 0; border-radius: var(--app-sidebar-toggle-radius); } .app-sidebar-toggle-icon { width: var(--app-sidebar-toggle-icon-size); height: var(--app-sidebar-toggle-icon-size); stroke-width: var(--app-sidebar-toggle-icon-stroke); } .app-workspace-content .ui-toolbar { padding: 0; border-color: transparent; border-radius: 0; background: transparent; box-shadow: none; } .app-settings-content-panel { padding: 0; border: 0; border-radius: 0; background: transparent; box-shadow: none; } .app-settings-content-panel :is(.bg-card.rounded-xl.border) { border-color: var(--app-settings-section-border); border-radius: var(--app-settings-section-radius); background: var(--app-settings-section-surface); box-shadow: var(--app-settings-section-shadow); } .app-fork-list { display: flex; flex-direction: column; gap: var(--app-fork-list-gap); } .app-fork-list > .ui-card { border: 0; border-bottom: var(--app-border-width) solid var(--app-fork-list-item-border); border-radius: var(--app-fork-list-item-radius); background: var(--app-fork-list-item-surface); box-shadow: var(--app-fork-list-item-shadow); } .app-fork-list > .ui-card:hover { background: var(--app-fork-list-item-hover-surface); } .app-fork-list > .ui-card:last-child { border-bottom: 0; } .app-side-list { display: flex; flex-direction: column; gap: var(--app-sidebar-list-gap); } .app-side-section { display: flex; flex-direction: column; gap: var(--app-sidebar-section-gap); padding-block: var(--app-sidebar-section-padding-block); } .app-side-item-label { display: inline-flex; min-width: 0; align-items: center; gap: var(--app-sidebar-item-gap); line-height: var(--app-sidebar-line-height); } .app-category-emoji { display: inline-grid; width: var(--app-icon-size); height: var(--app-icon-size); flex: none; place-items: center; font-size: var(--app-sidebar-category-emoji-size); line-height: var(--app-sidebar-category-emoji-line-height); } .app-side-icon-rail { display: flex; flex-direction: column; align-items: center; gap: var(--app-sidebar-rail-gap); padding-block: var(--app-sidebar-rail-padding-block); } .app-side-rail-divider { width: 100%; height: var(--app-border-width); background: var(--app-sidebar-rail-divider-color); } .context-sidebar-foot { display: flex; flex-direction: column; gap: var(--app-sidebar-foot-gap); margin-block-start: auto; padding: var(--app-sidebar-foot-padding-block) var(--app-sidebar-foot-padding-inline); border-top: var(--app-border-width) solid var(--app-sidebar-foot-border); } .app-side-foot-status { display: flex; align-items: center; gap: var(--app-sidebar-control-gap); color: var(--app-sidebar-muted-color); font-size: var(--app-sidebar-foot-status-size); } .app-status-dot { width: var(--app-sidebar-status-dot-size); height: var(--app-sidebar-status-dot-size); flex: none; border-radius: var(--app-sidebar-count-radius); background: var(--ui-success); } .app-side-foot-meta { display: flex; align-items: center; justify-content: space-between; gap: var(--app-sidebar-control-gap); color: var(--app-sidebar-muted-color); font-size: var(--app-sidebar-foot-meta-size); font-variant-numeric: tabular-nums; } .app-route-scope { display: flex; align-items: center; gap: var(--app-scope-trigger-gap); } .app-route-scope-label { color: var(--app-scope-label-color); font-size: var(--app-scope-label-size); } .app-route-scope-trigger { width: auto; max-width: var(--app-scope-trigger-max-width); height: var(--app-scope-trigger-height); min-height: var(--app-scope-trigger-height); min-width: 0; gap: var(--app-scope-trigger-gap); padding-inline: var(--app-scope-trigger-padding-inline); border-color: var(--app-toolbar-border); background: var(--app-toolbar-surface); color: var(--app-sidebar-item-color); box-shadow: none; font-size: var(--app-scope-trigger-font-size); font-weight: var(--app-sidebar-item-font-weight); } .app-route-scope-trigger:hover { background: var(--app-hover-surface); color: hsl(var(--foreground)); } .app-route-scope-trigger svg { width: var(--app-icon-size); height: var(--app-icon-size); } .app-side-more { display: flex; width: 100%; min-height: var(--app-sidebar-more-height); align-items: center; justify-content: center; border: 0; border-radius: var(--ui-radius-sm); background: transparent; color: var(--app-sidebar-muted-color); font-size: var(--app-sidebar-more-font-size); font-weight: var(--app-sidebar-item-font-weight); } .app-side-more:hover { background: var(--app-hover-surface); color: hsl(var(--foreground)); } .app-side-control-row { display: flex; min-height: var(--app-sidebar-control-row-min-height); align-items: center; justify-content: space-between; gap: var(--app-sidebar-control-gap); padding-inline: var(--app-sidebar-control-row-padding-inline); color: var(--ui-text-muted); font-size: var(--app-sidebar-control-row-font-size); } .app-side-inline-status { display: flex; align-items: center; gap: var(--app-sidebar-control-gap); color: var(--app-sidebar-muted-color); font-size: var(--app-sidebar-inline-status-font-size); } .app-side-empty { margin: 0; padding: var(--app-sidebar-empty-padding-block) var(--app-sidebar-empty-padding-inline); color: var(--app-sidebar-muted-color); font-size: var(--app-sidebar-empty-font-size); line-height: var(--app-sidebar-empty-line-height); } .app-category-strip { display: flex; gap: var(--app-category-strip-gap); overflow-x: auto; padding-block-end: var(--app-category-strip-padding-block-end); } .app-category-pill { min-width: var(--app-category-pill-min-width); } .gist-access-help-popover { z-index: var(--app-z-popover); transform: translateX(var(--app-gist-help-popover-shift)); }