:root { --bg-primary: #0f0f12; --bg-secondary: #18181b; --bg-tertiary: #27272a; --border-color: #3f3f46; --text-primary: #e4e4e7; --text-secondary: #a1a1aa; --text-muted: #71717a; --accent: #6366f1; --accent-hover: #818cf8; --success: #22c55e; --warning: #f59e0b; --danger: #ef4444; --card-bg: #18181b; --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3); --font-nums: 'SF Mono', SFMono-Regular, ui-monospace, Menlo, Monaco, Consolas, monospace; /* Chart colors */ --color-chart-teal: #14b8a6; --color-chart-pink: #ec4899; /* Color utility classes */ --color-chart-1: var(--accent); --color-chart-2: var(--success); --color-chart-3: var(--warning); --color-chart-4: var(--color-chart-pink); --color-chart-5: var(--color-chart-teal); --color-chart-gc: var(--warning); --color-chart-gc-full: var(--danger); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: var(--bg-primary); color: var(--text-primary); min-height: 100vh; line-height: 1.5; } .app { min-height: 100vh; display: flex; flex-direction: column; } .header { display: flex; justify-content: space-between; align-items: center; padding: 1rem 2rem; background: var(--bg-secondary); border-bottom: 1px solid var(--border-color); position: sticky; top: 0; z-index: 100; } .loading { display: flex; flex-direction: column; justify-content: center; align-items: center; min-height: 200px; gap: 1rem; color: var(--text-secondary); font-size: 1rem; } .spinner { width: 32px; height: 32px; border: 3px solid var(--border-color); border-top-color: var(--accent); border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .header-left { display: flex; align-items: baseline; gap: 0.75rem; } .header h1 { font-size: 1.25rem; font-weight: 700; color: var(--text-primary); } .subtitle { font-size: 0.875rem; color: var(--text-muted); } .nav { display: flex; gap: 0.5rem; } .nav button { padding: 0.5rem 1rem; background: transparent; border: 1px solid var(--border-color); color: var(--text-secondary); border-radius: 0.375rem; cursor: pointer; font-size: 0.875rem; transition: all 0.2s; } .nav button:hover { background: var(--bg-tertiary); color: var(--text-primary); } .nav button.active { background: var(--accent); border-color: var(--accent); color: white; } .nav button:disabled { opacity: 0.5; cursor: not-allowed; } .main { flex: 1; padding: 2rem; max-width: 1600px; margin: 0 auto; width: 100%; padding-bottom: 8rem; } .footer { position: fixed; bottom: 0; left: 0; right: 0; padding: 0.75rem 2rem; background: var(--bg-secondary); border-top: 1px solid var(--border-color); display: flex; justify-content: flex-end; z-index: 50; } .footer-link { display: flex; align-items: center; gap: 0.5rem; color: var(--text-muted); text-decoration: none; font-size: 0.8125rem; transition: color 0.2s; } .footer-link img { fill: currentColor; } .footer-link:hover { color: var(--text-primary); } /* Upload */ .upload-container { display: flex; flex-direction: column; align-items: center; gap: 2rem; padding-top: 4rem; } .upload-card { background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 1rem; padding: 3rem; text-align: center; max-width: 480px; width: 100%; } .upload-icon { font-size: 3rem; margin-bottom: 1rem; } .upload-card h2 { font-size: 1.5rem; margin-bottom: 0.5rem; } .upload-card p { color: var(--text-secondary); margin-bottom: 2rem; } .upload-mode-toggle { display: flex; gap: 0.5rem; margin-bottom: 1.5rem; } .upload-mode-toggle button { flex: 1; padding: 0.75rem; background: var(--bg-tertiary); border: 1px solid var(--border-color); color: var(--text-secondary); border-radius: 0.5rem; cursor: pointer; transition: all 0.2s; } .upload-mode-toggle button.active { background: var(--accent); border-color: var(--accent); color: white; } .file-input-label { display: inline-block; cursor: pointer; } .file-input-label input { display: none; } .file-input-label span { display: inline-block; padding: 0.875rem 2rem; background: var(--accent); color: white; border-radius: 0.5rem; font-weight: 500; transition: background 0.2s; } .file-input-label:hover span { background: var(--accent-hover); } .json-input { width: 100%; height: 200px; padding: 1rem; background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: 0.5rem; color: var(--text-primary); font-family: 'SF Mono', Monaco, monospace; font-size: 0.8125rem; resize: vertical; margin-bottom: 1rem; } .json-input:focus { outline: none; border-color: var(--accent); } .load-btn { width: 100%; padding: 0.875rem; background: var(--accent); border: none; color: white; border-radius: 0.5rem; font-weight: 500; cursor: pointer; transition: background 0.2s; } .load-btn:hover { background: var(--accent-hover); } .error { margin-top: 1rem; padding: 0.75rem; background: rgba(239, 68, 68, 0.1); border: 1px solid var(--danger); color: var(--danger); border-radius: 0.5rem; font-size: 0.875rem; } .recent-analyses { margin-top: 2rem; padding-top: 2rem; border-top: 1px solid var(--border-color); text-align: left; } .recent-analyses h3 { font-size: 0.875rem; color: var(--text-secondary); margin-bottom: 1rem; display: flex; align-items: center; gap: 0.5rem; } .snapshot-list { display: flex; flex-direction: column; gap: 0.5rem; } .snapshot-item { display: flex; justify-content: space-between; align-items: center; padding: 0.75rem 1rem; background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: 0.5rem; cursor: pointer; transition: all 0.2s; } .snapshot-item:hover { background: var(--bg-secondary); border-color: var(--accent); } .snapshot-item .snapshot-name { font-weight: 500; color: var(--text-primary); } .snapshot-item .snapshot-date { font-size: 0.75rem; color: var(--text-muted); } .quick-tips { background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 0.75rem; padding: 1.5rem; max-width: 600px; width: 100%; } .quick-tips h4 { font-size: 0.875rem; color: var(--text-secondary); margin-bottom: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; } .quick-tips ul { list-style: none; display: flex; flex-direction: column; gap: 0.5rem; } .quick-tips code { display: block; padding: 0.75rem 1rem; background: var(--bg-tertiary); border-radius: 0.375rem; font-family: 'SF Mono', Monaco, monospace; font-size: 0.8125rem; color: var(--accent); word-break: break-all; } /* Analysis */ .analysis { display: flex; flex-direction: column; gap: 1.5rem; } .analysis-header { background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 0.75rem; padding: 1.5rem; } .header-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 1rem; } .analysis-controls { display: none; } /* Floating Actions */ .floating-actions { position: fixed; bottom: 5rem; right: 2rem; display: flex; flex-direction: column; gap: 0.75rem; z-index: 100; } .action-btn { width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; border-radius: 50%; border: none; cursor: pointer; transition: all 0.2s; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); } .action-btn.save { background: var(--accent); color: white; } .action-btn.save:hover { background: var(--accent-hover); transform: scale(1.05); } .action-btn.clear { background: var(--bg-secondary); color: var(--text-secondary); border: 1px solid var(--border-color); } .action-btn.clear:hover { background: var(--bg-tertiary); color: var(--text-primary); } .analysis-controls { display: flex; gap: 1rem; justify-content: center; padding: 1.5rem; } .save-btn, .clear-btn { padding: 0.75rem 1.5rem; border-radius: 0.5rem; font-size: 0.875rem; font-weight: 500; cursor: pointer; transition: all 0.2s; } .save-btn { background: var(--accent); border: none; color: white; } .save-btn:hover { background: var(--accent-hover); } .clear-btn { background: transparent; border: 1px solid var(--border-color); color: var(--text-secondary); } .clear-btn:hover { background: var(--bg-tertiary); color: var(--text-primary); } /* Modal */ .modal-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.7); display: flex; align-items: center; justify-content: center; z-index: 1000; } .modal { background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 1rem; padding: 2rem; min-width: 360px; } .modal-large { min-width: 480px; max-width: 90vw; max-height: 80vh; display: flex; flex-direction: column; } .modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; } .modal-header h3 { margin-bottom: 0; } .close-btn { background: transparent; border: none; color: var(--text-muted); cursor: pointer; padding: 0.25rem; display: flex; align-items: center; justify-content: center; border-radius: 0.25rem; transition: all 0.2s; } .close-btn:hover { background: var(--bg-tertiary); color: var(--text-primary); } .modal h3 { margin-bottom: 1.5rem; font-size: 1.125rem; } .snapshot-name-input { width: 100%; padding: 0.875rem 1rem; background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: 0.5rem; color: var(--text-primary); font-size: 0.9375rem; margin-bottom: 1.5rem; } .snapshot-name-input:focus { outline: none; border-color: var(--accent); } .modal-actions { display: flex; gap: 0.75rem; justify-content: flex-end; margin-top: 1.5rem; } .modal-actions:only-child { margin-top: 0; } .cancel-btn, .confirm-btn { padding: 0.625rem 1.25rem; border-radius: 0.375rem; font-size: 0.875rem; font-weight: 500; cursor: pointer; transition: all 0.2s; } .danger-btn { padding: 0.625rem 1rem; border-radius: 0.375rem; font-size: 0.875rem; font-weight: 500; cursor: pointer; transition: all 0.2s; background: rgba(239, 68, 68, 0.15); border: 1px solid var(--danger); color: var(--danger); display: flex; align-items: center; gap: 0.5rem; } .danger-btn:hover { background: var(--danger); color: white; } /* Manage Snapshots Modal */ .snapshot-list-manage { flex: 1; overflow-y: auto; max-height: 400px; border: 1px solid var(--border-color); border-radius: 0.5rem; background: var(--bg-tertiary); } .snapshot-manage-item { display: flex; align-items: center; justify-content: space-between; padding: 0.75rem 1rem; border-bottom: 1px solid var(--border-color); transition: background 0.2s; } .snapshot-manage-item:last-child { border-bottom: none; } .snapshot-manage-item:hover { background: var(--bg-secondary); } .snapshot-info { flex: 1; cursor: pointer; display: flex; flex-direction: column; gap: 0.25rem; } .snapshot-name { font-weight: 500; color: var(--text-primary); } .snapshot-date { font-size: 0.75rem; color: var(--text-muted); } .empty-state { padding: 2rem; text-align: center; color: var(--text-muted); } .cancel-btn { background: transparent; border: 1px solid var(--border-color); color: var(--text-secondary); } .cancel-btn:hover { background: var(--bg-tertiary); } .confirm-btn { background: var(--accent); border: none; color: white; } .confirm-btn:hover { background: var(--accent-hover); } /* Help Link */ .help-link { color: var(--accent); font-size: 0.875rem; cursor: pointer; margin-bottom: 2rem; display: inline-block; } .help-link:hover { text-decoration: underline; } .help-panel { background: var(--bg-tertiary); border-radius: 0.5rem; padding: 1.25rem; margin-bottom: 1.5rem; text-align: left; } .help-panel h4 { font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.75rem; } .help-panel code { display: block; padding: 0.625rem 0.875rem; background: var(--bg-secondary); border-radius: 0.375rem; font-family: 'SF Mono', Monaco, monospace; font-size: 0.75rem; color: var(--accent); margin-bottom: 0.5rem; } .help-panel p { font-size: 0.8125rem; color: var(--text-secondary); margin-top: 0.75rem; } /* Snapshots List */ .snapshots-list { background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 0.75rem; padding: 1.25rem; } .snapshots-list h4 { font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 1rem; } .snapshot-item { display: flex; justify-content: space-between; align-items: center; padding: 0.625rem 0.875rem; background: var(--bg-tertiary); border-radius: 0.375rem; margin-bottom: 0.5rem; } .snapshot-item:last-child { margin-bottom: 0; } .snapshot-name { font-size: 0.875rem; color: var(--text-primary); } .delete-btn { width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; background: transparent; border: none; color: var(--text-muted); cursor: pointer; border-radius: 0.25rem; transition: all 0.2s; } .delete-btn:hover { background: rgba(239, 68, 68, 0.15); color: var(--danger); } /* Comparison Diff Highlight */ .compare-row.diff { background: rgba(99, 102, 241, 0.05); } .compare-row.diff:hover { background: rgba(99, 102, 241, 0.1); } .metrics-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 1rem; } .metrics-grid.small { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); } .metric-card { background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 0.75rem; padding: 1.25rem; position: relative; transition: border-color 0.2s; } .metric-card:hover { border-color: var(--text-muted); } .metric-card.highlight { border-color: var(--success); background: rgba(34, 197, 94, 0.05); } .metric-value { font-size: 1.5rem; font-weight: 700; color: var(--text-primary); font-family: var(--font-nums); font-variant-numeric: tabular-nums; } .metric-label { font-size: 0.75rem; color: var(--text-muted); margin-top: 0.25rem; text-transform: uppercase; letter-spacing: 0.05em; } .tooltip { position: fixed; transform: translateX(-50%); padding: 0.5rem 0.75rem; background: var(--bg-primary); border: 1px solid var(--border-color); border-radius: 0.375rem; font-size: 0.75rem; color: var(--text-secondary); white-space: normal; max-width: 280px; width: max-content; z-index: 1000; box-shadow: var(--shadow); pointer-events: none; word-wrap: break-word; } .tooltip::after { content: ''; position: absolute; border: 6px solid transparent; } .tooltip:not([data-position='top'])::after { top: 100%; left: 50%; transform: translateX(-50%); border-top-color: var(--border-color); } .tooltip[data-position='bottom'] { transform: translateX(-50%) translateY(8px); } .tooltip[data-position='bottom']::after { top: auto; bottom: 100%; border-top-color: transparent; border-bottom-color: var(--border-color); } /* Sections */ .section { background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 0.75rem; overflow: hidden; } .section-header { width: 100%; display: flex; justify-content: space-between; align-items: center; padding: 1rem 1.25rem; background: transparent; border: none; color: var(--text-primary); font-size: 0.875rem; font-weight: 600; cursor: pointer; transition: background 0.2s; } .section-header:hover { background: var(--bg-tertiary); } .section-toggle { color: var(--text-muted); flex-shrink: 0; transition: transform 0.2s; } .section.collapsed .section-toggle { transform: rotate(-90deg); } .section-content { padding: 1.25rem; border-top: 1px solid var(--border-color); } .section.collapsed .section-content { display: none; } .charts-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 1.5rem; } /* Combined Time & Thunks Widget */ .time-thunks-combined { display: flex; flex-direction: column; gap: 1.25rem; } .thunks-section { padding-top: 1rem; border-top: 1px solid var(--border-color); } /* Memory Donut Chart */ .memory-chart { display: grid; grid-template-columns: 1fr 180px; gap: 1.5rem; align-items: center; } .gc-inline { display: flex; flex-direction: column; gap: 0.25rem; margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid var(--border-color); font-size: 0.75rem; } .gc-header { font-size: 0.625rem; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.05em; } .gc-values { display: flex; align-items: center; gap: 0.5rem 1rem; flex-wrap: wrap; } .gc-label { color: var(--text-muted); font-size: 0.625rem; text-transform: uppercase; } .gc-value { color: var(--text-primary); font-family: var(--font-nums); font-variant-numeric: tabular-nums; } .chart-legend { display: flex; flex-direction: column; gap: 0.5rem; } .legend-item { display: grid; grid-template-columns: 12px 1fr auto auto; gap: 0.75rem; align-items: center; font-size: 0.8125rem; } .legend-color { width: 12px; height: 12px; border-radius: 3px; } .legend-color.chart-1 { background: var(--color-chart-1); } .legend-color.chart-2 { background: var(--color-chart-2); } .legend-color.chart-3 { background: var(--color-chart-3); } .legend-color.chart-4 { background: var(--color-chart-4); } .legend-color.chart-5 { background: var(--color-chart-5); } .legend-label { color: var(--text-secondary); } .legend-value { color: var(--text-primary); font-family: var(--font-nums); font-variant-numeric: tabular-nums; } .legend-percent { color: var(--text-muted); font-size: 0.75rem; text-align: right; min-width: 40px; } .donut-chart svg { width: 100%; max-width: 180px; display: block; } .donut-chart svg path.chart-1 { stroke: var(--color-chart-1); } .donut-chart svg path.chart-2 { stroke: var(--color-chart-2); } .donut-chart svg path.chart-3 { stroke: var(--color-chart-3); } .donut-chart svg path.chart-4 { stroke: var(--color-chart-4); } .donut-chart svg path.chart-5 { stroke: var(--color-chart-5); } .chart-center-value { font-size: 1.25rem; font-weight: 700; fill: var(--text-primary); font-family: var(--font-nums); font-variant-numeric: tabular-nums; } .chart-center-label { font-size: 0.625rem; fill: var(--text-muted); text-transform: uppercase; letter-spacing: 0.1em; } /* Time Chart */ .time-chart { display: flex; flex-direction: column; gap: 1rem; } .time-bars { display: flex; flex-direction: column; gap: 0.5rem; } .time-bar-row { display: grid; grid-template-columns: 100px 1fr 70px; gap: 1rem; align-items: center; } .time-bar-label { font-size: 0.8125rem; color: var(--text-secondary); } .time-bar-track { height: 1.25rem; background: var(--bg-tertiary); border-radius: 0.25rem; overflow: hidden; } .time-bar-fill { height: 100%; border-radius: 0.25rem; transition: width 0.3s ease; } .time-bar-fill.chart-1 { background: var(--color-chart-1); } .time-bar-fill.chart-gc { background: var(--color-chart-gc); } .time-bar-fill.chart-gc-full { background: var(--color-chart-gc-full); } .time-bar-value { font-family: var(--font-nums); font-variant-numeric: tabular-nums; font-size: 0.75rem; color: var(--text-secondary); min-width: 80px; text-align: right; } .gc-stats { display: flex; gap: 1.5rem; padding-top: 0.75rem; border-top: 1px solid var(--border-color); } .gc-stat { display: flex; flex-direction: column; gap: 0.25rem; } .gc-stat-label { font-size: 0.6875rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; } .gc-stat-value { font-size: 0.9375rem; color: var(--text-primary); font-family: var(--font-nums); font-variant-numeric: tabular-nums; } /* Operations Chart */ .operations-chart { display: flex; flex-direction: column; gap: 0.625rem; } .op-row { display: grid; grid-template-columns: 110px 1fr 80px; gap: 1rem; align-items: center; } .op-label { font-size: 0.8125rem; color: var(--text-secondary); } .op-bar-container { height: 1.5rem; background: var(--bg-tertiary); border-radius: 0.25rem; overflow: hidden; } .op-bar { height: 100%; border-radius: 0.25rem; transition: width 0.3s ease; } .op-bar.chart-1 { background: var(--color-chart-1); } .op-bar.chart-2 { background: var(--color-chart-2); } .op-bar.chart-3 { background: var(--color-chart-3); } .op-bar.chart-4 { background: var(--color-chart-4); } .op-bar.chart-5 { background: var(--color-chart-5); } .op-value { font-size: 0.8125rem; color: var(--text-primary); font-family: var(--font-nums); font-variant-numeric: tabular-nums; text-align: right; } /* Thunk Chart */ .thunk-chart { display: flex; flex-direction: column; gap: 1rem; } .thunk-bars { display: flex; flex-direction: column; gap: 0.625rem; } .thunk-row { display: grid; grid-template-columns: 70px 1fr 80px; gap: 1rem; align-items: center; } .thunk-label { font-size: 0.8125rem; color: var(--text-secondary); } .thunk-bar-container { height: 1.5rem; background: var(--bg-tertiary); border-radius: 0.25rem; overflow: hidden; } .thunk-bar { height: 100%; border-radius: 0.25rem; transition: width 0.3s ease; } .thunk-bar.created { background: var(--color-chart-1); } .thunk-bar.avoided { background: var(--color-chart-2); } .thunk-value { font-size: 0.8125rem; color: var(--text-primary); font-family: var(--font-nums); font-variant-numeric: tabular-nums; text-align: right; } .thunk-ratio { display: flex; flex-direction: column; gap: 0.5rem; padding-top: 0.75rem; border-top: 1px solid var(--border-color); } .ratio-bar { height: 0.5rem; background: var(--bg-tertiary); border-radius: 0.25rem; overflow: hidden; } .ratio-fill { height: 100%; background: linear-gradient(90deg, #6366f1, #22c55e); border-radius: 0.25rem; transition: width 0.3s ease; } .ratio-label { font-size: 0.75rem; color: var(--text-muted); } .dashboard-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 1.5rem; } /* Bar Chart */ .bar-chart { display: flex; flex-direction: column; gap: 0.75rem; } .bar-row { display: grid; grid-template-columns: 80px 1fr 80px; align-items: center; gap: 1rem; } .bar-label { font-size: 0.8125rem; color: var(--text-secondary); } .bar-container { height: 1.5rem; background: var(--bg-tertiary); border-radius: 0.25rem; overflow: hidden; } .bar-fill { height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-hover)); border-radius: 0.25rem; transition: width 0.3s ease; } .bar-value { font-size: 0.8125rem; color: var(--text-primary); font-family: var(--font-nums); font-variant-numeric: tabular-nums; text-align: right; } /* Top Lists */ .top-list { display: flex; flex-direction: column; gap: 0.5rem; } .top-item { display: grid; grid-template-columns: 32px 1fr auto auto; align-items: center; gap: 1rem; padding: 0.75rem; background: var(--bg-tertiary); border-radius: 0.5rem; } .rank { width: 24px; height: 24px; display: flex; align-items: center; justify-content: center; background: var(--bg-secondary); border-radius: 0.25rem; font-size: 0.75rem; font-weight: 600; color: var(--text-muted); } .top-item .name { font-size: 0.8125rem; color: var(--text-primary); font-family: 'SF Mono', Monaco, monospace; } .top-item .count { font-size: 0.8125rem; color: var(--text-secondary); font-family: var(--font-nums); font-variant-numeric: tabular-nums; } .top-item .location { font-size: 0.75rem; color: var(--text-muted); } /* Comparison View */ .comparison-view { display: flex; flex-direction: column; gap: 2rem; } .comparison-controls { display: flex; align-items: flex-end; gap: 1rem; } .compare-selector { flex: 1; display: flex; flex-direction: column; gap: 0.5rem; } .compare-selector label { font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; } .compare-selector select { padding: 0.75rem 1rem; background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 0.5rem; color: var(--text-primary); font-size: 0.875rem; cursor: pointer; } .compare-selector select:focus { outline: none; border-color: var(--accent); } .compare-arrow { padding: 0.75rem; color: var(--text-muted); display: flex; align-items: center; justify-content: center; } .compare-placeholder { text-align: center; padding: 4rem; color: var(--text-muted); background: var(--card-bg); border: 1px dashed var(--border-color); border-radius: 0.75rem; } .comparison-table { background: var(--card-bg); border: 1px solid var(--border-color); border-radius: 0.75rem; overflow: hidden; } .compare-header { display: grid; grid-template-columns: 1fr 140px 140px 100px; gap: 1rem; padding: 1rem 1.25rem; background: var(--bg-tertiary); font-size: 0.75rem; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; } .compare-row { display: grid; grid-template-columns: 1fr 140px 140px 100px; gap: 1rem; padding: 0.875rem 1.25rem; border-bottom: 1px solid var(--border-color); align-items: center; transition: background 0.2s; } .compare-row:last-child { border-bottom: none; } .compare-row.highlight:hover { background: var(--bg-tertiary); } .compare-row.missing { opacity: 0.6; background: var(--bg-secondary); } .compare-row.missing:hover { background: var(--bg-tertiary); } .compare-row .col-label { font-size: 0.8125rem; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .compare-row .col-value { font-size: 0.8125rem; color: var(--text-secondary); font-family: var(--font-nums); font-variant-numeric: tabular-nums; } .compare-row .col-change { text-align: right; } .change-value { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.25rem 0.5rem; border-radius: 0.25rem; font-size: 0.75rem; font-weight: 600; font-family: var(--font-nums); font-variant-numeric: tabular-nums; } .col-change.good .change-value { background: rgba(34, 197, 94, 0.15); color: var(--success); } .col-change.bad .change-value { background: rgba(239, 68, 68, 0.15); color: var(--danger); } .col-change .neutral { color: var(--text-muted); } .missing-value { color: var(--text-tertiary); font-style: italic; } .missing-indicator { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.25rem 0.5rem; border-radius: 0.25rem; font-size: 0.75rem; font-weight: 600; font-family: var(--font-nums); font-variant-numeric: tabular-nums; background: rgba(156, 163, 175, 0.15); color: var(--text-tertiary); } .comparison-summary { display: flex; gap: 1rem; } .summary-good { padding: 0.75rem 1rem; background: rgba(34, 197, 94, 0.1); border: 1px solid rgba(34, 197, 94, 0.3); border-radius: 0.5rem; color: var(--success); font-size: 0.875rem; } .summary-bad { padding: 0.75rem 1rem; background: rgba(239, 68, 68, 0.1); border: 1px solid rgba(239, 68, 68, 0.3); border-radius: 0.5rem; color: var(--danger); font-size: 0.875rem; } /* Responsive */ @media (max-width: 768px) { .header { flex-direction: column; gap: 1rem; padding: 1rem; } .main { padding: 1rem; padding-bottom: 6rem; } .floating-actions { bottom: 4rem; right: 1rem; } .dashboard-grid { grid-template-columns: 1fr; } .compare-header, .compare-row { grid-template-columns: 1fr 100px 80px; } .compare-header .col-label, .compare-row .col-label { max-width: 120px; } .bar-row { grid-template-columns: 60px 1fr 60px; } .top-item { grid-template-columns: 24px 1fr auto; } .top-item .location { display: none; } } .precision-select { padding: 0.5rem 1.5rem 0.5rem 0.75rem; background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: 0.375rem; color: var(--text-secondary); font-size: 0.875rem; cursor: pointer; appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239ca3af' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 0.5rem center; } .precision-select:hover { border-color: var(--text-muted); color: var(--text-primary); } .precision-select:focus { outline: none; border-color: var(--accent); } .settings-label { font-size: 0.875rem; font-weight: 500; color: var(--text-primary); } .precision-input { width: 120px; padding: 0.75rem 1rem; background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: 0.5rem; color: var(--text-primary); font-size: 0.9375rem; text-align: center; } .precision-input:focus { outline: none; border-color: var(--accent); } /* Hide number input spinners */ .precision-input::-webkit-outer-spin-button, .precision-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } .precision-input[type='number'] { -moz-appearance: textfield; } .settings-hint { font-size: 0.75rem; color: var(--text-muted); }