/** * Dealspace Theme System * * All colors are CSS custom properties. Zero hardcoded values in templates. * Switch themes by changing the class on : theme-light, theme-dark, theme-contrast * Per-project overrides use data-project attribute. */ /* ========================================================================== BASE TOKENS (shared across themes) ========================================================================== */ :root { /* Spacing */ --space-xs: 0.25rem; /* 4px */ --space-sm: 0.5rem; /* 8px */ --space-md: 1rem; /* 16px */ --space-lg: 1.5rem; /* 24px */ --space-xl: 2rem; /* 32px */ --space-2xl: 3rem; /* 48px */ /* Border radius */ --radius-sm: 0.25rem; /* 4px */ --radius-md: 0.5rem; /* 8px */ --radius-lg: 0.75rem; /* 12px */ --radius-full: 9999px; /* Typography */ --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --font-mono: "SF Mono", Consolas, "Liberation Mono", Menlo, monospace; --text-xs: 0.75rem; /* 12px */ --text-sm: 0.875rem; /* 14px */ --text-base: 1rem; /* 16px */ --text-lg: 1.125rem; /* 18px */ --text-xl: 1.25rem; /* 20px */ --text-2xl: 1.5rem; /* 24px */ --leading-tight: 1.25; --leading-normal: 1.5; --leading-relaxed: 1.75; /* Transitions */ --transition-fast: 150ms ease; --transition-normal: 250ms ease; /* Z-index scale */ --z-dropdown: 100; --z-modal: 200; --z-toast: 300; } /* ========================================================================== LIGHT THEME (default) ========================================================================== */ .theme-light, :root { /* Surfaces */ --color-bg-primary: #ffffff; --color-bg-secondary: #f9fafb; --color-bg-tertiary: #f3f4f6; --color-bg-inverse: #1f2937; --color-bg-hover: #f3f4f6; --color-bg-selected: #eff6ff; /* Text */ --color-text-primary: #111827; --color-text-secondary: #6b7280; --color-text-tertiary: #9ca3af; --color-text-inverse: #ffffff; --color-text-link: #2563eb; --color-text-link-hover: #1d4ed8; /* Borders */ --color-border-primary: #e5e7eb; --color-border-secondary: #f3f4f6; --color-border-focus: #2563eb; /* Semantic colors */ --color-accent: #2563eb; --color-accent-hover: #1d4ed8; --color-accent-light: #dbeafe; --color-success: #059669; --color-success-light: #d1fae5; --color-warning: #d97706; --color-warning-light: #fef3c7; --color-error: #dc2626; --color-error-light: #fee2e2; --color-info: #0284c7; --color-info-light: #e0f2fe; /* Priority indicators */ --color-priority-high: #dc2626; --color-priority-normal: #d97706; --color-priority-low: #9ca3af; /* Status badges */ --color-status-open: #6b7280; --color-status-open-bg: #f3f4f6; --color-status-assigned: #2563eb; --color-status-assigned-bg: #dbeafe; --color-status-answered: #d97706; --color-status-answered-bg: #fef3c7; --color-status-vetted: #7c3aed; --color-status-vetted-bg: #ede9fe; --color-status-published: #059669; --color-status-published-bg: #d1fae5; --color-status-closed: #9ca3af; --color-status-closed-bg: #f3f4f6; /* Components */ --color-header-bg: #ffffff; --color-header-text: #111827; --color-header-border: #e5e7eb; --color-card-bg: #ffffff; --color-card-border: #e5e7eb; --color-card-shadow: rgba(0, 0, 0, 0.05); --color-input-bg: #ffffff; --color-input-border: #d1d5db; --color-input-focus: #2563eb; --color-input-placeholder: #9ca3af; --color-badge-bg: #ef4444; --color-badge-text: #ffffff; /* Shadows */ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); --shadow-focus: 0 0 0 3px rgba(37, 99, 235, 0.2); } /* ========================================================================== DARK THEME ========================================================================== */ .theme-dark { /* Surfaces */ --color-bg-primary: #111827; --color-bg-secondary: #1f2937; --color-bg-tertiary: #374151; --color-bg-inverse: #f9fafb; --color-bg-hover: #374151; --color-bg-selected: #1e3a5f; /* Text */ --color-text-primary: #f9fafb; --color-text-secondary: #9ca3af; --color-text-tertiary: #6b7280; --color-text-inverse: #111827; --color-text-link: #60a5fa; --color-text-link-hover: #93c5fd; /* Borders */ --color-border-primary: #374151; --color-border-secondary: #4b5563; --color-border-focus: #60a5fa; /* Semantic colors */ --color-accent: #3b82f6; --color-accent-hover: #60a5fa; --color-accent-light: #1e3a5f; --color-success: #10b981; --color-success-light: #064e3b; --color-warning: #f59e0b; --color-warning-light: #78350f; --color-error: #ef4444; --color-error-light: #7f1d1d; --color-info: #0ea5e9; --color-info-light: #0c4a6e; /* Priority indicators */ --color-priority-high: #ef4444; --color-priority-normal: #f59e0b; --color-priority-low: #6b7280; /* Status badges */ --color-status-open: #9ca3af; --color-status-open-bg: #374151; --color-status-assigned: #60a5fa; --color-status-assigned-bg: #1e3a5f; --color-status-answered: #f59e0b; --color-status-answered-bg: #78350f; --color-status-vetted: #a78bfa; --color-status-vetted-bg: #4c1d95; --color-status-published: #10b981; --color-status-published-bg: #064e3b; --color-status-closed: #6b7280; --color-status-closed-bg: #374151; /* Components */ --color-header-bg: #1f2937; --color-header-text: #f9fafb; --color-header-border: #374151; --color-card-bg: #1f2937; --color-card-border: #374151; --color-card-shadow: rgba(0, 0, 0, 0.3); --color-input-bg: #374151; --color-input-border: #4b5563; --color-input-focus: #60a5fa; --color-input-placeholder: #6b7280; --color-badge-bg: #ef4444; --color-badge-text: #ffffff; /* Shadows */ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3); --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -1px rgba(0, 0, 0, 0.3); --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -2px rgba(0, 0, 0, 0.3); --shadow-focus: 0 0 0 3px rgba(96, 165, 250, 0.3); } /* ========================================================================== HIGH CONTRAST THEME ========================================================================== */ .theme-contrast { /* Surfaces */ --color-bg-primary: #000000; --color-bg-secondary: #1a1a1a; --color-bg-tertiary: #333333; --color-bg-inverse: #ffffff; --color-bg-hover: #333333; --color-bg-selected: #003366; /* Text */ --color-text-primary: #ffffff; --color-text-secondary: #e0e0e0; --color-text-tertiary: #b0b0b0; --color-text-inverse: #000000; --color-text-link: #66b3ff; --color-text-link-hover: #99ccff; /* Borders */ --color-border-primary: #ffffff; --color-border-secondary: #808080; --color-border-focus: #ffff00; /* Semantic colors */ --color-accent: #66b3ff; --color-accent-hover: #99ccff; --color-accent-light: #003366; --color-success: #00ff00; --color-success-light: #003300; --color-warning: #ffff00; --color-warning-light: #333300; --color-error: #ff3333; --color-error-light: #330000; --color-info: #00ffff; --color-info-light: #003333; /* Priority indicators */ --color-priority-high: #ff3333; --color-priority-normal: #ffff00; --color-priority-low: #808080; /* Status badges */ --color-status-open: #ffffff; --color-status-open-bg: #333333; --color-status-assigned: #66b3ff; --color-status-assigned-bg: #003366; --color-status-answered: #ffff00; --color-status-answered-bg: #333300; --color-status-vetted: #cc99ff; --color-status-vetted-bg: #330066; --color-status-published: #00ff00; --color-status-published-bg: #003300; --color-status-closed: #808080; --color-status-closed-bg: #1a1a1a; /* Components */ --color-header-bg: #000000; --color-header-text: #ffffff; --color-header-border: #ffffff; --color-card-bg: #1a1a1a; --color-card-border: #ffffff; --color-card-shadow: none; --color-input-bg: #1a1a1a; --color-input-border: #ffffff; --color-input-focus: #ffff00; --color-input-placeholder: #808080; --color-badge-bg: #ff3333; --color-badge-text: #ffffff; /* Shadows - disabled for clarity */ --shadow-sm: none; --shadow-md: none; --shadow-lg: none; --shadow-focus: 0 0 0 3px #ffff00; } /* High contrast specific: underline all links */ .theme-contrast a { text-decoration: underline; } .theme-contrast a:focus { outline: 3px solid var(--color-border-focus); outline-offset: 2px; } /* ========================================================================== PER-PROJECT BRAND OVERRIDES ========================================================================== */ /* Project overrides cascade on top of the selected theme */ /* Example: data-project="alpha" */ [data-project="alpha"] { --color-accent: #7c3aed; /* Purple accent */ --color-accent-hover: #6d28d9; --color-header-bg: #7c3aed; --color-header-text: #ffffff; } [data-project="beta"] { --color-accent: #059669; /* Emerald accent */ --color-accent-hover: #047857; --color-header-bg: #059669; --color-header-text: #ffffff; } /* ========================================================================== COMPONENT STYLES (using theme variables) ========================================================================== */ /* Base reset */ *, *::before, *::after { box-sizing: border-box; } body { font-family: var(--font-sans); font-size: var(--text-base); line-height: var(--leading-normal); color: var(--color-text-primary); background-color: var(--color-bg-primary); margin: 0; padding: 0; } /* Header */ .global-header { display: flex; align-items: center; gap: var(--space-lg); padding: var(--space-md) var(--space-lg); background: var(--color-header-bg); border-bottom: 1px solid var(--color-header-border); } .global-header .logo { font-size: var(--text-xl); font-weight: 700; color: var(--color-header-text); } /* Project selector */ .project-select { flex: 1; max-width: 400px; padding: var(--space-sm) var(--space-md); font-size: var(--text-sm); color: var(--color-text-primary); background: var(--color-input-bg); border: 1px solid var(--color-input-border); border-radius: var(--radius-md); cursor: pointer; } .project-select:focus { outline: none; border-color: var(--color-input-focus); box-shadow: var(--shadow-focus); } /* Workstream tabs */ .workstream-tabs { display: flex; gap: var(--space-xs); padding: 0 var(--space-lg); background: var(--color-bg-secondary); border-bottom: 1px solid var(--color-border-primary); } .workstream-tabs a { display: inline-flex; align-items: center; gap: var(--space-sm); padding: var(--space-md) var(--space-lg); font-size: var(--text-sm); font-weight: 500; color: var(--color-text-secondary); text-decoration: none; border-bottom: 2px solid transparent; transition: color var(--transition-fast), border-color var(--transition-fast); } .workstream-tabs a:hover { color: var(--color-text-primary); } .workstream-tabs a.active { color: var(--color-accent); border-bottom-color: var(--color-accent); } /* Badge */ .badge { display: inline-flex; align-items: center; justify-content: center; min-width: 1.25rem; height: 1.25rem; padding: 0 var(--space-xs); font-size: var(--text-xs); font-weight: 600; color: var(--color-badge-text); background: var(--color-badge-bg); border-radius: var(--radius-full); } .badge-muted { background: var(--color-bg-tertiary); color: var(--color-text-secondary); } /* Task card */ .task-card { display: block; padding: var(--space-md) var(--space-lg); background: var(--color-card-bg); border: 1px solid var(--color-card-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); text-decoration: none; color: inherit; transition: box-shadow var(--transition-fast), border-color var(--transition-fast); } .task-card:hover { border-color: var(--color-border-focus); box-shadow: var(--shadow-md); } .task-card-header { display: flex; align-items: flex-start; gap: var(--space-md); margin-bottom: var(--space-sm); } .task-card-priority { width: 0.625rem; height: 0.625rem; border-radius: var(--radius-full); flex-shrink: 0; margin-top: 0.375rem; } .task-card-priority.high { background: var(--color-priority-high); } .task-card-priority.normal { background: var(--color-priority-normal); } .task-card-priority.low { background: var(--color-priority-low); } .task-card-ref { font-size: var(--text-sm); font-weight: 600; color: var(--color-text-secondary); font-family: var(--font-mono); } .task-card-title { flex: 1; font-size: var(--text-base); font-weight: 600; color: var(--color-text-primary); } .task-card-due { font-size: var(--text-sm); color: var(--color-text-secondary); white-space: nowrap; } .task-card-due.overdue { color: var(--color-error); font-weight: 600; } .task-card-due.today { color: var(--color-warning); font-weight: 600; } .task-card-meta { font-size: var(--text-sm); color: var(--color-text-secondary); margin-bottom: var(--space-sm); } .task-card-preview { font-size: var(--text-sm); color: var(--color-text-tertiary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* Status badge */ .status-badge { display: inline-flex; align-items: center; padding: var(--space-xs) var(--space-sm); font-size: var(--text-xs); font-weight: 600; text-transform: uppercase; letter-spacing: 0.025em; border-radius: var(--radius-sm); } .status-badge.open { color: var(--color-status-open); background: var(--color-status-open-bg); } .status-badge.assigned { color: var(--color-status-assigned); background: var(--color-status-assigned-bg); } .status-badge.answered { color: var(--color-status-answered); background: var(--color-status-answered-bg); } .status-badge.vetted { color: var(--color-status-vetted); background: var(--color-status-vetted-bg); } .status-badge.published { color: var(--color-status-published); background: var(--color-status-published-bg); } .status-badge.closed { color: var(--color-status-closed); background: var(--color-status-closed-bg); } /* Buttons */ .btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-sm); padding: var(--space-sm) var(--space-md); font-size: var(--text-sm); font-weight: 500; text-decoration: none; border-radius: var(--radius-md); border: 1px solid transparent; cursor: pointer; transition: all var(--transition-fast); } .btn-primary { color: var(--color-text-inverse); background: var(--color-accent); border-color: var(--color-accent); } .btn-primary:hover { background: var(--color-accent-hover); border-color: var(--color-accent-hover); } .btn-secondary { color: var(--color-text-primary); background: var(--color-bg-secondary); border-color: var(--color-border-primary); } .btn-secondary:hover { background: var(--color-bg-tertiary); } .btn:focus { outline: none; box-shadow: var(--shadow-focus); } /* Form inputs */ .input, .textarea { width: 100%; padding: var(--space-sm) var(--space-md); font-size: var(--text-base); color: var(--color-text-primary); background: var(--color-input-bg); border: 1px solid var(--color-input-border); border-radius: var(--radius-md); } .input::placeholder, .textarea::placeholder { color: var(--color-input-placeholder); } .input:focus, .textarea:focus { outline: none; border-color: var(--color-input-focus); box-shadow: var(--shadow-focus); } .textarea { min-height: 100px; resize: vertical; } /* Thread messages */ .thread-message { padding: var(--space-md); background: var(--color-card-bg); border: 1px solid var(--color-card-border); border-radius: var(--radius-lg); margin-bottom: var(--space-md); } .thread-message-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-sm); } .thread-message-author { font-weight: 600; color: var(--color-text-primary); } .thread-message-time { font-size: var(--text-sm); color: var(--color-text-tertiary); } .thread-message-body { color: var(--color-text-primary); line-height: var(--leading-relaxed); } .thread-message-attachment { display: inline-flex; align-items: center; gap: var(--space-sm); margin-top: var(--space-sm); padding: var(--space-sm) var(--space-md); background: var(--color-bg-tertiary); border-radius: var(--radius-md); font-size: var(--text-sm); color: var(--color-text-link); text-decoration: none; } .thread-message-attachment:hover { color: var(--color-text-link-hover); } /* Routing chain */ .routing-chain { display: flex; align-items: center; gap: var(--space-md); padding: var(--space-md); background: var(--color-bg-secondary); border-radius: var(--radius-lg); overflow-x: auto; } .routing-step { display: flex; align-items: center; gap: var(--space-sm); white-space: nowrap; font-size: var(--text-sm); color: var(--color-text-secondary); } .routing-step.current { font-weight: 600; color: var(--color-accent); } .routing-arrow { color: var(--color-text-tertiary); } /* Empty state */ .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: var(--space-2xl); text-align: center; } .empty-state-icon { font-size: 3rem; margin-bottom: var(--space-md); } .empty-state-title { font-size: var(--text-xl); font-weight: 600; color: var(--color-text-primary); margin-bottom: var(--space-sm); } .empty-state-text { color: var(--color-text-secondary); } /* ========================================================================== UTILITY CLASSES ========================================================================== */ .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; } .container { max-width: 1200px; margin: 0 auto; padding: 0 var(--space-lg); } .flex { display: flex; } .flex-col { flex-direction: column; } .items-center { align-items: center; } .justify-between { justify-content: space-between; } .gap-sm { gap: var(--space-sm); } .gap-md { gap: var(--space-md); } .gap-lg { gap: var(--space-lg); } .mt-sm { margin-top: var(--space-sm); } .mt-md { margin-top: var(--space-md); } .mt-lg { margin-top: var(--space-lg); } .mb-sm { margin-bottom: var(--space-sm); } .mb-md { margin-bottom: var(--space-md); } .mb-lg { margin-bottom: var(--space-lg); } .text-sm { font-size: var(--text-sm); } .text-lg { font-size: var(--text-lg); } .text-muted { color: var(--color-text-secondary); } .font-semibold { font-weight: 600; }