| /* ========================================================================== | |
| Heatmap Viewer - Component-Specific CSS | |
| DEPENDENCY: Requires _shared_assets/base.css to be loaded first | |
| This file extends the shared foundation with heatmap-specific styles. | |
| ========================================================================== */ | |
| /* Heatmap heat colors - using base.css colors with 60% opacity */ | |
| [data-theme="dark"] { | |
| --heat-1: rgba(90, 123, 167, 0.60); | |
| --heat-2: rgba(106, 148, 168, 0.60); | |
| --heat-3: rgba(122, 172, 172, 0.60); | |
| --heat-4: rgba(142, 196, 152, 0.60); | |
| --heat-5: rgba(168, 216, 136, 0.60); | |
| --heat-6: rgba(200, 222, 122, 0.60); | |
| --heat-7: rgba(244, 212, 93, 0.60); | |
| --heat-8: rgba(255, 122, 69, 0.60); | |
| } | |
| /* -------------------------------------------------------------------------- | |
| Layout Overrides (Heatmap-specific) | |
| -------------------------------------------------------------------------- */ | |
| .app-layout { | |
| min-height: 100vh; | |
| } | |
| /* Sticky top bar for heatmap views */ | |
| .top-bar { | |
| position: sticky; | |
| top: 0; | |
| z-index: 100; | |
| } | |
| /* -------------------------------------------------------------------------- | |
| Main Content Area | |
| -------------------------------------------------------------------------- */ | |
| .main-content { | |
| flex: 1; | |
| padding: 24px 3%; | |
| width: 100%; | |
| max-width: 100%; | |
| } | |
| /* -------------------------------------------------------------------------- | |
| Stats Summary Cards - Enhanced with Icons & Animations | |
| -------------------------------------------------------------------------- */ | |
| .stats-summary { | |
| display: grid; | |
| grid-template-columns: repeat(3, 1fr); | |
| gap: 12px; | |
| margin-bottom: 24px; | |
| } | |
| .stat-card { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| background: var(--bg-primary); | |
| border: 2px solid var(--border); | |
| border-radius: 10px; | |
| padding: 14px 16px; | |
| transition: all var(--transition-fast); | |
| animation: slideUp 0.5s ease-out backwards; | |
| animation-delay: calc(var(--i, 0) * 0.08s); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .stat-card:nth-child(1) { --i: 0; --card-color: var(--card-blue); } | |
| .stat-card:nth-child(2) { --i: 1; --card-color: var(--card-green); } | |
| .stat-card:nth-child(3) { --i: 2; --card-color: var(--card-yellow); } | |
| .stat-card:nth-child(4) { --i: 3; --card-color: var(--card-purple); } | |
| .stat-card:hover { | |
| border-color: rgba(var(--card-color), 0.6); | |
| background: linear-gradient(135deg, rgba(var(--card-color), 0.08) 0%, var(--bg-primary) 100%); | |
| transform: translateY(-2px); | |
| box-shadow: 0 4px 16px rgba(var(--card-color), 0.15); | |
| } | |
| .stat-icon { | |
| width: 40px; | |
| height: 40px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 18px; | |
| background: linear-gradient(135deg, rgba(var(--card-color), 0.15) 0%, rgba(var(--card-color), 0.05) 100%); | |
| border: 1px solid rgba(var(--card-color), 0.2); | |
| border-radius: 10px; | |
| flex-shrink: 0; | |
| transition: all var(--transition-fast); | |
| } | |
| .stat-card:hover .stat-icon { | |
| transform: scale(1.05) rotate(-2deg); | |
| background: linear-gradient(135deg, rgba(var(--card-color), 0.25) 0%, rgba(var(--card-color), 0.1) 100%); | |
| } | |
| .stat-data { | |
| flex: 1; | |
| min-width: 0; | |
| } | |
| .stat-value { | |
| font-family: var(--font-mono); | |
| font-size: 1.35em; | |
| font-weight: 800; | |
| color: rgb(var(--card-color)); | |
| display: block; | |
| line-height: 1.1; | |
| letter-spacing: -0.3px; | |
| } | |
| .stat-label { | |
| font-size: 10px; | |
| font-weight: 600; | |
| color: var(--text-muted); | |
| text-transform: uppercase; | |
| letter-spacing: 0.3px; | |
| margin-top: 2px; | |
| } | |
| /* Sparkline decoration for stats */ | |
| .stat-sparkline { | |
| position: absolute; | |
| bottom: 0; | |
| left: 0; | |
| right: 0; | |
| height: 30px; | |
| opacity: 0.1; | |
| background: linear-gradient(180deg, | |
| transparent 0%, | |
| rgba(var(--card-color), 0.3) 100% | |
| ); | |
| pointer-events: none; | |
| } | |
| /* -------------------------------------------------------------------------- | |
| Rate Cards (Error Rate, Missed Samples) with Progress Bars | |
| -------------------------------------------------------------------------- */ | |
| .rate-card { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 12px; | |
| background: var(--bg-primary); | |
| border: 2px solid var(--border); | |
| border-radius: 12px; | |
| padding: 18px 20px; | |
| transition: all var(--transition-fast); | |
| animation: slideUp 0.5s ease-out backwards; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .rate-card:nth-child(5) { animation-delay: 0.32s; --rate-color: var(--card-red); } | |
| .rate-card:nth-child(6) { animation-delay: 0.40s; --rate-color: var(--card-orange); } | |
| .rate-card:hover { | |
| border-color: rgba(var(--rate-color), 0.5); | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 20px rgba(var(--rate-color), 0.15); | |
| } | |
| .rate-header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| .rate-info { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .rate-icon { | |
| width: 36px; | |
| height: 36px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 18px; | |
| background: linear-gradient(135deg, rgba(var(--rate-color), 0.15) 0%, rgba(var(--rate-color), 0.05) 100%); | |
| border: 1px solid rgba(var(--rate-color), 0.2); | |
| border-radius: 10px; | |
| flex-shrink: 0; | |
| } | |
| .rate-label { | |
| font-size: 12px; | |
| font-weight: 600; | |
| color: var(--text-secondary); | |
| text-transform: uppercase; | |
| letter-spacing: 0.3px; | |
| } | |
| .rate-value { | |
| font-family: var(--font-mono); | |
| font-size: 1.4em; | |
| font-weight: 800; | |
| color: rgb(var(--rate-color)); | |
| } | |
| .rate-bar { | |
| height: 8px; | |
| background: var(--bg-tertiary); | |
| border-radius: 4px; | |
| overflow: hidden; | |
| position: relative; | |
| } | |
| .rate-fill { | |
| height: 100%; | |
| border-radius: 4px; | |
| transition: width 0.8s ease-out; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .rate-fill.error { | |
| background: linear-gradient(90deg, #dc3545 0%, #ff6b6b 100%); | |
| } | |
| .rate-fill.warning { | |
| background: linear-gradient(90deg, #ff9800 0%, #ffc107 100%); | |
| } | |
| .rate-fill.good { | |
| background: linear-gradient(90deg, #28a745 0%, #20c997 100%); | |
| } | |
| /* Shimmer animation on rate bars */ | |
| .rate-fill::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: -100%; | |
| width: 100%; | |
| height: 100%; | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(255, 255, 255, 0.4) 50%, | |
| transparent 100% | |
| ); | |
| animation: shimmer 2.5s ease-in-out infinite; | |
| } | |
| /* -------------------------------------------------------------------------- | |
| Section Headers | |
| -------------------------------------------------------------------------- */ | |
| .section-header { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| margin-bottom: 16px; | |
| padding-bottom: 12px; | |
| border-bottom: 2px solid var(--python-gold); | |
| } | |
| .section-title { | |
| font-size: 18px; | |
| font-weight: 700; | |
| color: var(--text-primary); | |
| margin: 0; | |
| flex: 1; | |
| } | |
| /* -------------------------------------------------------------------------- | |
| Filter Controls | |
| -------------------------------------------------------------------------- */ | |
| .filter-controls { | |
| display: flex; | |
| gap: 8px; | |
| flex-wrap: wrap; | |
| align-items: center; | |
| margin-bottom: 16px; | |
| } | |
| .control-btn { | |
| padding: 8px 16px; | |
| background: var(--bg-secondary); | |
| color: var(--text-primary); | |
| border: 1px solid var(--border); | |
| border-radius: 6px; | |
| font-size: 13px; | |
| font-weight: 500; | |
| cursor: pointer; | |
| transition: all var(--transition-fast); | |
| } | |
| .control-btn:hover { | |
| background: var(--accent); | |
| color: white; | |
| border-color: var(--accent); | |
| } | |
| /* -------------------------------------------------------------------------- | |
| Type Sections (stdlib, project, etc) | |
| -------------------------------------------------------------------------- */ | |
| .type-section { | |
| background: var(--bg-primary); | |
| border: 1px solid var(--border); | |
| border-radius: 8px; | |
| overflow: hidden; | |
| margin-bottom: 12px; | |
| } | |
| .type-header { | |
| padding: 12px 16px; | |
| background: var(--header-gradient); | |
| color: white; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| user-select: none; | |
| transition: all var(--transition-fast); | |
| font-weight: 600; | |
| } | |
| .type-header:hover { | |
| opacity: 0.95; | |
| } | |
| .type-icon { | |
| font-size: 12px; | |
| transition: transform var(--transition-fast); | |
| min-width: 12px; | |
| } | |
| .type-title { | |
| font-size: 14px; | |
| flex: 1; | |
| } | |
| .type-stats { | |
| font-size: 12px; | |
| opacity: 0.9; | |
| background: rgba(255, 255, 255, 0.15); | |
| padding: 4px 10px; | |
| border-radius: 4px; | |
| font-family: var(--font-mono); | |
| } | |
| .type-content { | |
| padding: 12px; | |
| } | |
| /* -------------------------------------------------------------------------- | |
| Folder Nodes (hierarchical structure) | |
| -------------------------------------------------------------------------- */ | |
| .folder-node { | |
| margin-bottom: 6px; | |
| } | |
| .folder-header { | |
| padding: 8px 12px; | |
| background: var(--bg-secondary); | |
| border: 1px solid var(--border); | |
| border-radius: 6px; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| user-select: none; | |
| transition: all var(--transition-fast); | |
| } | |
| .folder-header:hover { | |
| background: var(--accent-glow); | |
| border-color: var(--accent); | |
| } | |
| .folder-icon { | |
| font-size: 10px; | |
| color: var(--accent); | |
| transition: transform var(--transition-fast); | |
| min-width: 12px; | |
| } | |
| .folder-name { | |
| flex: 1; | |
| font-weight: 500; | |
| color: var(--text-primary); | |
| font-size: 13px; | |
| } | |
| .folder-stats { | |
| font-size: 11px; | |
| color: var(--text-secondary); | |
| background: var(--bg-tertiary); | |
| padding: 2px 8px; | |
| border-radius: 4px; | |
| font-family: var(--font-mono); | |
| } | |
| .folder-content { | |
| padding-left: 20px; | |
| margin-top: 6px; | |
| } | |
| /* -------------------------------------------------------------------------- | |
| File Items | |
| -------------------------------------------------------------------------- */ | |
| .files-list { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 4px; | |
| margin-top: 8px; | |
| } | |
| .file-item { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| padding: 8px 12px; | |
| background: var(--bg-primary); | |
| border: 1px solid var(--border-subtle); | |
| border-radius: 6px; | |
| transition: all var(--transition-fast); | |
| } | |
| .file-item:hover { | |
| background: var(--bg-secondary); | |
| border-color: var(--border); | |
| } | |
| .file-item .file-link { | |
| flex: 1; | |
| min-width: 0; | |
| font-size: 13px; | |
| } | |
| .file-samples { | |
| font-size: 12px; | |
| color: var(--text-secondary); | |
| font-weight: 600; | |
| white-space: nowrap; | |
| width: 130px; | |
| flex-shrink: 0; | |
| text-align: right; | |
| font-family: var(--font-mono); | |
| } | |
| .heatmap-bar-container { | |
| width: 120px; | |
| flex-shrink: 0; | |
| display: flex; | |
| align-items: center; | |
| } | |
| .heatmap-bar { | |
| flex-shrink: 0; | |
| border-radius: 2px; | |
| } | |
| /* Links */ | |
| .file-link { | |
| color: var(--accent); | |
| text-decoration: none; | |
| font-weight: 500; | |
| transition: color var(--transition-fast); | |
| } | |
| .file-link:hover { | |
| color: var(--accent-hover); | |
| text-decoration: underline; | |
| } | |
| /* -------------------------------------------------------------------------- | |
| Module Badges | |
| -------------------------------------------------------------------------- */ | |
| .module-badge { | |
| display: inline-block; | |
| padding: 3px 8px; | |
| border-radius: 4px; | |
| font-size: 11px; | |
| font-weight: 600; | |
| } | |
| .badge-stdlib { | |
| background: rgba(40, 167, 69, 0.15); | |
| color: #28a745; | |
| } | |
| .badge-site-packages { | |
| background: rgba(0, 123, 255, 0.15); | |
| color: #007bff; | |
| } | |
| .badge-project { | |
| background: rgba(255, 193, 7, 0.2); | |
| color: #d39e00; | |
| } | |
| .badge-other { | |
| background: var(--bg-tertiary); | |
| color: var(--text-secondary); | |
| } | |
| [data-theme="dark"] .badge-stdlib { | |
| background: rgba(40, 167, 69, 0.25); | |
| color: #5dd879; | |
| } | |
| [data-theme="dark"] .badge-site-packages { | |
| background: rgba(88, 166, 255, 0.25); | |
| color: #79b8ff; | |
| } | |
| [data-theme="dark"] .badge-project { | |
| background: rgba(255, 212, 59, 0.25); | |
| color: #ffd43b; | |
| } | |
| /* ========================================================================== | |
| FILE VIEW STYLES (Code Display) | |
| ========================================================================== */ | |
| .code-view { | |
| font-family: var(--font-mono); | |
| min-height: 100vh; | |
| } | |
| /* Code Header (Top Bar for file view) */ | |
| .code-header { | |
| height: var(--topbar-height); | |
| background: var(--header-gradient); | |
| display: flex; | |
| align-items: center; | |
| padding: 0 16px; | |
| gap: 16px; | |
| box-shadow: 0 2px 10px rgba(55, 118, 171, 0.25); | |
| border-bottom: 2px solid var(--python-gold); | |
| position: sticky; | |
| top: 0; | |
| z-index: 100; | |
| } | |
| .code-header-content { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| width: 94%; | |
| max-width: 100%; | |
| margin: 0 auto; | |
| } | |
| .code-header h1 { | |
| font-size: 14px; | |
| font-weight: 600; | |
| color: white; | |
| margin: 0; | |
| font-family: var(--font-mono); | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| /* File Stats Bar */ | |
| .file-stats { | |
| background: var(--bg-secondary); | |
| padding: 16px 24px; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .file-stats .stats-grid { | |
| width: 94%; | |
| max-width: 100%; | |
| margin: 0 auto; | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); | |
| gap: 12px; | |
| } | |
| .stat-item { | |
| background: var(--bg-primary); | |
| padding: 12px; | |
| border-radius: 8px; | |
| box-shadow: var(--shadow-sm); | |
| text-align: center; | |
| border: 1px solid var(--border); | |
| transition: all var(--transition-fast); | |
| } | |
| .stat-item:hover { | |
| transform: translateY(-2px); | |
| box-shadow: var(--shadow-md); | |
| border-color: var(--accent); | |
| } | |
| .stat-item .stat-value { | |
| font-size: 1.4em; | |
| font-weight: 700; | |
| color: var(--accent); | |
| } | |
| .stat-item .stat-label { | |
| color: var(--text-muted); | |
| font-size: 10px; | |
| margin-top: 2px; | |
| } | |
| /* Legend */ | |
| .legend { | |
| background: var(--bg-secondary); | |
| padding: 12px 24px; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .legend-content { | |
| width: 100%; | |
| display: flex; | |
| align-items: center; | |
| gap: 20px; | |
| flex-wrap: nowrap; | |
| } | |
| .legend-separator { | |
| width: 1px; | |
| height: 24px; | |
| background: var(--border); | |
| flex-shrink: 0; | |
| } | |
| .legend-title { | |
| font-weight: 600; | |
| color: var(--text-primary); | |
| font-size: 13px; | |
| font-family: var(--font-sans); | |
| flex-shrink: 0; | |
| } | |
| .legend-gradient { | |
| width: 150px; | |
| flex-shrink: 0; | |
| height: 20px; | |
| background: linear-gradient(90deg, | |
| var(--bg-tertiary) 0%, | |
| var(--heat-2) 25%, | |
| var(--heat-4) 50%, | |
| var(--heat-6) 75%, | |
| var(--heat-8) 100% | |
| ); | |
| border-radius: 4px; | |
| border: 1px solid var(--border); | |
| } | |
| .legend-labels { | |
| display: flex; | |
| gap: 12px; | |
| font-size: 11px; | |
| color: var(--text-muted); | |
| font-family: var(--font-sans); | |
| flex-shrink: 0; | |
| } | |
| /* Legend Controls Group - wraps toggles and bytecode button together */ | |
| .legend-controls { | |
| display: flex; | |
| align-items: center; | |
| gap: 20px; | |
| flex-shrink: 0; | |
| margin-left: auto; | |
| } | |
| /* Heatmap-Specific Toggle Overrides */ | |
| #toggle-color-mode .toggle-track.on { | |
| background: #8e44ad; | |
| border-color: #8e44ad; | |
| box-shadow: 0 0 8px rgba(142, 68, 173, 0.3); | |
| } | |
| #toggle-cold .toggle-track.on { | |
| background: #e67e22; | |
| border-color: #e67e22; | |
| box-shadow: 0 0 8px rgba(230, 126, 34, 0.3); | |
| } | |
| /* Code Container */ | |
| .code-container { | |
| width: 94%; | |
| max-width: 100%; | |
| margin: 16px auto; | |
| background: var(--bg-primary); | |
| border: 1px solid var(--border); | |
| border-radius: 8px 8px 8px 8px; | |
| box-shadow: var(--shadow-sm); | |
| /* Allow horizontal scroll for long lines, but don't clip sticky header */ | |
| } | |
| /* Code Header Row */ | |
| .code-header-row { | |
| position: sticky; | |
| top: var(--topbar-height); | |
| z-index: 50; | |
| display: flex; | |
| background: var(--bg-secondary); | |
| border-bottom: 2px solid var(--border); | |
| font-weight: 700; | |
| font-size: 11px; | |
| color: var(--text-muted); | |
| text-transform: uppercase; | |
| letter-spacing: 0.5px; | |
| border-radius: 8px 8px 0 0; | |
| } | |
| .header-line-number { | |
| flex-shrink: 0; | |
| width: 60px; | |
| padding: 8px 10px; | |
| text-align: right; | |
| border-right: 1px solid var(--border); | |
| } | |
| .header-samples-self, | |
| .header-samples-cumulative { | |
| flex-shrink: 0; | |
| width: 90px; | |
| padding: 8px 10px; | |
| text-align: right; | |
| border-right: 1px solid var(--border); | |
| } | |
| .header-samples-self { | |
| color: var(--heat-8); | |
| } | |
| .header-samples-cumulative { | |
| color: var(--accent); | |
| } | |
| .header-content { | |
| flex: 1; | |
| padding: 8px 15px; | |
| } | |
| /* Code Lines */ | |
| .code-line { | |
| position: relative; | |
| display: flex; | |
| min-height: 20px; | |
| line-height: 20px; | |
| font-size: 13px; | |
| transition: background var(--transition-fast); | |
| scroll-margin-top: calc(var(--topbar-height) + 50px); | |
| } | |
| .code-line:hover { | |
| filter: brightness(0.97); | |
| } | |
| [data-theme="dark"] .code-line:hover { | |
| filter: brightness(1.1); | |
| } | |
| .line-number { | |
| flex-shrink: 0; | |
| width: 60px; | |
| padding: 0 10px; | |
| text-align: right; | |
| color: var(--text-muted); | |
| background: var(--bg-secondary); | |
| border-right: 1px solid var(--border); | |
| user-select: none; | |
| transition: all var(--transition-fast); | |
| } | |
| .line-number:hover { | |
| background: var(--accent); | |
| color: white; | |
| cursor: pointer; | |
| } | |
| .line-samples-self, | |
| .line-samples-cumulative { | |
| flex-shrink: 0; | |
| width: 90px; | |
| padding: 0 10px; | |
| text-align: right; | |
| background: var(--bg-secondary); | |
| border-right: 1px solid var(--border); | |
| font-weight: 600; | |
| user-select: none; | |
| font-size: 12px; | |
| } | |
| .line-samples-self { | |
| color: var(--heat-8); | |
| } | |
| .line-samples-cumulative { | |
| color: var(--accent); | |
| } | |
| .line-content { | |
| flex: 1; | |
| padding: 0 15px; | |
| white-space: pre; | |
| overflow-x: auto; | |
| } | |
| /* Scrollbar Styling */ | |
| .line-content::-webkit-scrollbar { | |
| height: 6px; | |
| } | |
| .line-content::-webkit-scrollbar-thumb { | |
| background: var(--border); | |
| border-radius: 3px; | |
| } | |
| .line-content::-webkit-scrollbar-thumb:hover { | |
| background: var(--text-muted); | |
| } | |
| /* Navigation Buttons */ | |
| .line-nav-buttons { | |
| position: absolute; | |
| right: 8px; | |
| top: 50%; | |
| transform: translateY(-50%); | |
| display: flex; | |
| gap: 4px; | |
| align-items: center; | |
| } | |
| .nav-btn { | |
| padding: 2px 6px; | |
| font-size: 12px; | |
| font-weight: 500; | |
| border: 1px solid var(--accent); | |
| border-radius: 4px; | |
| background: var(--bg-primary); | |
| color: var(--accent); | |
| cursor: pointer; | |
| transition: all var(--transition-fast); | |
| user-select: none; | |
| line-height: 1; | |
| } | |
| .nav-btn:hover:not(:disabled) { | |
| background: var(--accent); | |
| color: white; | |
| transform: translateY(-1px); | |
| box-shadow: var(--shadow-sm); | |
| } | |
| .nav-btn:active:not(:disabled) { | |
| transform: translateY(0); | |
| } | |
| .nav-btn:disabled { | |
| opacity: 0.3; | |
| cursor: not-allowed; | |
| color: var(--text-muted); | |
| background: var(--bg-secondary); | |
| border-color: var(--border); | |
| } | |
| .nav-btn.caller { | |
| color: var(--nav-caller); | |
| border-color: var(--nav-caller); | |
| } | |
| .nav-btn.callee { | |
| color: var(--nav-callee); | |
| border-color: var(--nav-callee); | |
| } | |
| .nav-btn.caller:hover:not(:disabled) { | |
| background: var(--nav-caller-hover); | |
| color: white; | |
| } | |
| .nav-btn.callee:hover:not(:disabled) { | |
| background: var(--nav-callee-hover); | |
| color: white; | |
| } | |
| /* Highlighted target line */ | |
| .code-line:target { | |
| animation: highlight-line 2s ease-out; | |
| } | |
| @keyframes highlight-line { | |
| 0% { | |
| background: rgba(255, 212, 59, 0.6) !important; | |
| outline: 3px solid var(--python-gold); | |
| outline-offset: -3px; | |
| } | |
| 50% { | |
| background: rgba(255, 212, 59, 0.5) !important; | |
| outline: 3px solid var(--python-gold); | |
| outline-offset: -3px; | |
| } | |
| 100% { | |
| outline: 3px solid transparent; | |
| outline-offset: -3px; | |
| } | |
| } | |
| /* Popup menu for multiple callees */ | |
| .callee-menu { | |
| position: absolute; | |
| background: var(--bg-primary); | |
| border: 1px solid var(--border); | |
| border-radius: 8px; | |
| box-shadow: var(--shadow-lg); | |
| padding: 8px; | |
| z-index: 1000; | |
| min-width: 250px; | |
| max-width: 400px; | |
| max-height: 300px; | |
| overflow-y: auto; | |
| } | |
| .callee-menu-header { | |
| font-weight: 600; | |
| color: var(--text-primary); | |
| margin-bottom: 8px; | |
| padding-bottom: 8px; | |
| border-bottom: 1px solid var(--border); | |
| font-size: 13px; | |
| font-family: var(--font-sans); | |
| } | |
| .callee-menu-item { | |
| padding: 8px; | |
| margin: 4px 0; | |
| border-radius: 6px; | |
| cursor: pointer; | |
| transition: background var(--transition-fast); | |
| display: flex; | |
| flex-direction: column; | |
| gap: 4px; | |
| } | |
| .callee-menu-item:hover { | |
| background: var(--bg-secondary); | |
| } | |
| .callee-menu-func { | |
| font-weight: 500; | |
| color: var(--accent); | |
| font-size: 12px; | |
| } | |
| .callee-menu-file { | |
| font-size: 11px; | |
| color: var(--text-muted); | |
| } | |
| .count-badge { | |
| display: inline-block; | |
| background: var(--accent); | |
| color: white; | |
| font-size: 10px; | |
| padding: 2px 6px; | |
| border-radius: 4px; | |
| font-weight: 600; | |
| margin-left: 6px; | |
| } | |
| /* Callee menu scrollbar */ | |
| .callee-menu::-webkit-scrollbar { | |
| width: 6px; | |
| } | |
| .callee-menu::-webkit-scrollbar-track { | |
| background: var(--bg-secondary); | |
| border-radius: 3px; | |
| } | |
| .callee-menu::-webkit-scrollbar-thumb { | |
| background: var(--border); | |
| border-radius: 3px; | |
| } | |
| /* -------------------------------------------------------------------------- | |
| Scroll Minimap Marker | |
| -------------------------------------------------------------------------- */ | |
| #scroll_marker { | |
| position: fixed; | |
| z-index: 1000; | |
| right: 0; | |
| top: 0; | |
| width: 12px; | |
| height: 100%; | |
| background: var(--bg-secondary); | |
| border-left: 1px solid var(--border); | |
| pointer-events: none; | |
| } | |
| #scroll_marker .marker { | |
| position: absolute; | |
| min-height: 3px; | |
| width: 100%; | |
| pointer-events: none; | |
| } | |
| #scroll_marker .marker.cold { | |
| background: var(--heat-1); | |
| } | |
| #scroll_marker .marker.cool { | |
| background: var(--heat-2); | |
| } | |
| #scroll_marker .marker.mild { | |
| background: var(--heat-3); | |
| } | |
| #scroll_marker .marker.warm { | |
| background: var(--heat-4); | |
| } | |
| #scroll_marker .marker.hot { | |
| background: var(--heat-5); | |
| } | |
| #scroll_marker .marker.very-hot { | |
| background: var(--heat-6); | |
| } | |
| #scroll_marker .marker.intense { | |
| background: var(--heat-7); | |
| } | |
| #scroll_marker .marker.extreme { | |
| background: var(--heat-8); | |
| } | |
| /* -------------------------------------------------------------------------- | |
| Responsive (Heatmap-specific) | |
| -------------------------------------------------------------------------- */ | |
| @media (max-width: 1100px) { | |
| .stats-summary { | |
| grid-template-columns: repeat(2, 1fr); | |
| } | |
| .legend-content { | |
| flex-wrap: wrap; | |
| justify-content: center; | |
| } | |
| .legend-controls { | |
| margin-left: 0; | |
| } | |
| } | |
| @media (max-width: 900px) { | |
| .main-content { | |
| padding: 16px; | |
| } | |
| } | |
| @media (max-width: 600px) { | |
| .stats-summary { | |
| grid-template-columns: 1fr; | |
| } | |
| .file-stats .stats-grid { | |
| grid-template-columns: repeat(2, 1fr); | |
| } | |
| .legend-content { | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 12px; | |
| } | |
| .legend-gradient { | |
| width: 100%; | |
| max-width: none; | |
| } | |
| .legend-separator { | |
| width: 80%; | |
| height: 1px; | |
| } | |
| .legend-controls { | |
| flex-direction: column; | |
| gap: 12px; | |
| } | |
| .legend-controls .toggle-switch { | |
| justify-content: center; | |
| } | |
| .legend-controls .toggle-switch .toggle-label:first-child { | |
| width: 70px; | |
| text-align: right; | |
| } | |
| .legend-controls .toggle-switch .toggle-label:last-child { | |
| width: 90px; | |
| text-align: left; | |
| } | |
| /* Compact code columns on small screens */ | |
| .header-line-number, | |
| .line-number { | |
| width: 40px; | |
| } | |
| .header-samples-self, | |
| .header-samples-cumulative, | |
| .line-samples-self, | |
| .line-samples-cumulative { | |
| width: 55px; | |
| font-size: 10px; | |
| } | |
| /* Adjust padding - headers need vertical, data rows don't */ | |
| .header-line-number, | |
| .header-samples-self, | |
| .header-samples-cumulative { | |
| padding: 8px 4px; | |
| } | |
| .line-number, | |
| .line-samples-self, | |
| .line-samples-cumulative { | |
| padding: 0 4px; | |
| } | |
| .bytecode-panel { | |
| margin: 8px 10px 8px 160px; | |
| } | |
| } | |
| .bytecode-toggle { | |
| flex-shrink: 0; | |
| width: 20px; | |
| height: 20px; | |
| padding: 0; | |
| margin: 0 4px; | |
| border: none; | |
| background: transparent; | |
| color: var(--code-accent); | |
| cursor: pointer; | |
| font-size: 10px; | |
| transition: transform var(--transition-fast), color var(--transition-fast); | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .bytecode-toggle:hover { | |
| color: var(--accent); | |
| } | |
| .bytecode-spacer { | |
| flex-shrink: 0; | |
| width: 20px; | |
| height: 20px; | |
| margin: 0 4px; | |
| } | |
| .bytecode-panel { | |
| background: var(--bg-primary); | |
| border: 1px solid var(--border); | |
| border-radius: 8px; | |
| box-shadow: var(--shadow-md); | |
| font-family: var(--font-mono); | |
| font-size: 12px; | |
| color: var(--text-primary); | |
| line-height: 1.5; | |
| word-wrap: break-word; | |
| overflow-wrap: break-word; | |
| padding: 0; | |
| margin: 8px 10px 8px 250px; | |
| position: relative; | |
| z-index: 1; | |
| overflow-y: auto; | |
| max-height: 500px; | |
| flex: 1; | |
| transition: padding 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| .bytecode-panel.expanded { | |
| padding: 14px; | |
| } | |
| .bytecode-wrapper { | |
| position: relative; | |
| display: flex; | |
| overflow: visible; | |
| max-height: 0; | |
| opacity: 0; | |
| transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease-in-out; | |
| } | |
| .bytecode-wrapper.expanded { | |
| max-height: 600px; | |
| opacity: 1; | |
| transition: max-height 0.5s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.4s ease-in-out; | |
| } | |
| /* Column backdrop matching table header columns (line/self/total) */ | |
| .bytecode-columns { | |
| display: none; | |
| position: absolute; | |
| left: 0; | |
| overflow: hidden; | |
| pointer-events: none; | |
| z-index: 0; | |
| } | |
| .bytecode-wrapper.expanded .bytecode-columns { | |
| display: flex; | |
| top: 0; | |
| bottom: 0; | |
| } | |
| .bytecode-panel::-webkit-scrollbar { | |
| width: 8px; | |
| } | |
| .bytecode-panel::-webkit-scrollbar-track { | |
| background: var(--bg-secondary); | |
| border-radius: 4px; | |
| } | |
| .bytecode-panel::-webkit-scrollbar-thumb { | |
| background: var(--border); | |
| border-radius: 4px; | |
| } | |
| .bytecode-panel::-webkit-scrollbar-thumb:hover { | |
| background: var(--text-muted); | |
| } | |
| /* Specialization summary bar */ | |
| .bytecode-spec-summary { | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| padding: 8px 12px; | |
| margin-bottom: 10px; | |
| border-radius: var(--radius-sm); | |
| background: rgba(100, 100, 100, 0.1); | |
| } | |
| .bytecode-spec-summary .spec-pct { | |
| font-size: 1.4em; | |
| font-weight: 700; | |
| } | |
| .bytecode-spec-summary .spec-label { | |
| font-weight: 500; | |
| text-transform: uppercase; | |
| font-size: 0.85em; | |
| letter-spacing: 0.5px; | |
| } | |
| .bytecode-spec-summary .spec-detail { | |
| color: var(--text-secondary); | |
| font-size: 0.9em; | |
| margin-left: auto; | |
| } | |
| .bytecode-spec-summary.high { | |
| background: var(--spec-high-bg); | |
| border-left: 3px solid var(--spec-high); | |
| } | |
| .bytecode-spec-summary.high .spec-pct, | |
| .bytecode-spec-summary.high .spec-label { | |
| color: var(--spec-high-text); | |
| } | |
| .bytecode-spec-summary.medium { | |
| background: var(--spec-medium-bg); | |
| border-left: 3px solid var(--spec-medium); | |
| } | |
| .bytecode-spec-summary.medium .spec-pct, | |
| .bytecode-spec-summary.medium .spec-label { | |
| color: var(--spec-medium-text); | |
| } | |
| .bytecode-spec-summary.low { | |
| background: var(--spec-low-bg); | |
| border-left: 3px solid var(--spec-low); | |
| } | |
| .bytecode-spec-summary.low .spec-pct, | |
| .bytecode-spec-summary.low .spec-label { | |
| color: var(--spec-low-text); | |
| } | |
| .bytecode-header { | |
| display: grid; | |
| grid-template-columns: 1fr 80px 80px; | |
| gap: 12px; | |
| padding: 4px 8px; | |
| font-weight: 600; | |
| color: var(--text-secondary); | |
| border-bottom: 1px solid var(--code-border); | |
| margin-bottom: 4px; | |
| } | |
| .bytecode-expand-all { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 6px; | |
| padding: 6px 12px; | |
| background: var(--bg-secondary); | |
| border: 1px solid var(--code-border); | |
| border-radius: var(--radius-sm); | |
| color: var(--text-secondary); | |
| font-size: 12px; | |
| font-weight: 500; | |
| cursor: pointer; | |
| transition: all var(--transition-fast); | |
| flex-shrink: 0; | |
| } | |
| .bytecode-expand-all:hover, | |
| .bytecode-expand-all.expanded { | |
| background: var(--accent); | |
| color: white; | |
| border-color: var(--accent); | |
| } | |
| .bytecode-expand-all .expand-icon { | |
| font-size: 10px; | |
| transition: transform var(--transition-fast); | |
| } | |
| .bytecode-expand-all.expanded .expand-icon { | |
| transform: rotate(90deg); | |
| } | |
| /* ======================================== | |
| INSTRUCTION SPAN HIGHLIGHTING | |
| (triggered only from bytecode panel hover) | |
| ======================================== */ | |
| /* Highlight from bytecode panel hover */ | |
| .instr-span.highlight-from-bytecode { | |
| outline: 3px solid #ff6b6b !important; | |
| background-color: rgba(255, 107, 107, 0.4) !important; | |
| border-radius: 2px; | |
| } | |
| /* Bytecode instruction row */ | |
| .bytecode-instruction { | |
| display: grid; | |
| grid-template-columns: 1fr 80px 80px; | |
| gap: 12px; | |
| align-items: center; | |
| padding: 4px 8px; | |
| margin: 2px 0; | |
| border-radius: var(--radius-sm); | |
| cursor: pointer; | |
| transition: background-color var(--transition-fast); | |
| } | |
| .bytecode-instruction:hover, | |
| .bytecode-instruction.highlight { | |
| background-color: rgba(55, 118, 171, 0.15); | |
| } | |
| .bytecode-instruction[data-locations] { | |
| cursor: pointer; | |
| } | |
| .bytecode-instruction[data-locations]:hover { | |
| background-color: rgba(255, 107, 107, 0.2); | |
| } | |
| .bytecode-opname { | |
| font-weight: 600; | |
| font-family: var(--font-mono); | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| white-space: nowrap; | |
| } | |
| .bytecode-opname.specialized { | |
| color: #2e7d32; | |
| } | |
| [data-theme="dark"] .bytecode-opname.specialized { | |
| color: #81c784; | |
| } | |
| .bytecode-opname .base-op { | |
| color: var(--code-text-muted); | |
| font-weight: normal; | |
| font-size: 0.9em; | |
| margin-left: 4px; | |
| } | |
| .bytecode-samples { | |
| text-align: right; | |
| font-weight: 600; | |
| color: var(--accent); | |
| font-family: var(--font-mono); | |
| } | |
| .bytecode-samples.hot { | |
| color: #ff6b6b; | |
| } | |
| .bytecode-heatbar { | |
| width: 60px; | |
| height: 12px; | |
| background: var(--bg-secondary); | |
| border-radius: 2px; | |
| overflow: hidden; | |
| border: 1px solid var(--code-border); | |
| } | |
| .bytecode-heatbar-fill { | |
| height: 100%; | |
| background: linear-gradient(90deg, #00d4ff 0%, #ff6b00 100%); | |
| } | |
| .specialization-badge { | |
| display: inline-block; | |
| padding: 1px 6px; | |
| font-size: 0.75em; | |
| background: #e8f5e9; | |
| color: #2e7d32; | |
| border-radius: 3px; | |
| margin-left: 6px; | |
| font-weight: 600; | |
| } | |
| [data-theme="dark"] .specialization-badge { | |
| background: rgba(129, 199, 132, 0.2); | |
| color: #81c784; | |
| } | |
| .bytecode-empty { | |
| color: var(--code-text-muted); | |
| font-style: italic; | |
| padding: 8px; | |
| } | |
| .bytecode-error { | |
| color: #d32f2f; | |
| font-style: italic; | |
| padding: 8px; | |
| } | |
| /* ======================================== | |
| SPAN TOOLTIPS | |
| ======================================== */ | |
| .span-tooltip { | |
| position: absolute; | |
| z-index: 10000; | |
| background: var(--bg-primary); | |
| color: var(--text-primary); | |
| padding: 10px 14px; | |
| border-radius: var(--radius-md); | |
| border: 1px solid var(--border); | |
| font-family: var(--font-sans); | |
| font-size: 12px; | |
| box-shadow: var(--shadow-lg); | |
| pointer-events: none; | |
| min-width: 160px; | |
| max-width: 300px; | |
| } | |
| .span-tooltip::after { | |
| content: ''; | |
| position: absolute; | |
| bottom: -7px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| border-width: 7px 7px 0; | |
| border-style: solid; | |
| border-color: var(--bg-primary) transparent transparent; | |
| filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.1)); | |
| } | |
| .span-tooltip-header { | |
| font-weight: 600; | |
| margin-bottom: 8px; | |
| padding-bottom: 6px; | |
| border-bottom: 1px solid var(--border); | |
| color: var(--text-primary); | |
| } | |
| .span-tooltip-header.hot { | |
| color: #e65100; | |
| } | |
| .span-tooltip-header.warm { | |
| color: #f59e0b; | |
| } | |
| .span-tooltip-header.cold { | |
| color: var(--text-muted); | |
| } | |
| .span-tooltip-row { | |
| display: flex; | |
| justify-content: space-between; | |
| margin: 4px 0; | |
| gap: 16px; | |
| } | |
| .span-tooltip-label { | |
| color: var(--text-secondary); | |
| } | |
| .span-tooltip-value { | |
| font-weight: 600; | |
| text-align: right; | |
| color: var(--text-primary); | |
| } | |
| .span-tooltip-value.highlight { | |
| color: var(--accent); | |
| } | |
| .span-tooltip-section { | |
| font-weight: 600; | |
| color: var(--text-secondary); | |
| font-size: 11px; | |
| margin-top: 8px; | |
| margin-bottom: 4px; | |
| padding-top: 6px; | |
| border-top: 1px solid var(--border); | |
| } | |
| .span-tooltip-opcode { | |
| font-family: var(--font-mono); | |
| font-size: 11px; | |
| color: var(--text-primary); | |
| background: var(--bg-secondary); | |
| padding: 3px 8px; | |
| margin: 2px 0; | |
| border-radius: var(--radius-sm); | |
| border-left: 2px solid var(--accent); | |
| } |