:host { // Theme-aware tokens — map to app design tokens --epg-panel-bg: var(--app-widget-bg); --epg-shadow: var(--app-widget-shadow); --epg-text-primary: var(--app-heading-color); --epg-text-secondary: var(--app-body-color); --epg-text-tertiary: var(--app-muted-color); --epg-accent: var(--app-selection-color); --epg-accent-glow: color-mix( in srgb, var(--app-selection-color) 40%, transparent ); --epg-item-hover: var(--app-hover-overlay); --epg-separator: var(--app-separator); // Status colors — semantic, not theme-dependent --epg-success: #22c55e; --epg-error: #ef4444; --epg-queued: #a78bfa; } .epg-progress-panel { position: fixed; bottom: 20px; left: 76px; width: 300px; max-width: calc(100vw - 96px); background: var(--epg-panel-bg); border-radius: 12px; border: 1px solid var(--epg-separator); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08), 0 8px 24px rgba(0, 0, 0, 0.18), 0 16px 48px rgba(0, 0, 0, 0.12); z-index: 900; overflow: hidden; animation: slideInFromLeft 0.3s cubic-bezier(0.16, 1, 0.3, 1); } @keyframes slideInFromLeft { from { opacity: 0; transform: translateX(-16px) scale(0.97); } to { opacity: 1; transform: translateX(0) scale(1); } } .panel-header { display: flex; align-items: center; justify-content: space-between; padding: 8px 8px 8px 12px; border-bottom: 1px solid var(--epg-separator); .header-title { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 0.78rem; letter-spacing: 0.04em; color: var(--epg-text-primary); text-transform: uppercase; mat-icon { font-size: 18px; width: 18px; height: 18px; color: var(--epg-accent); } .minimized-summary { font-size: 0.78rem; font-weight: 500; text-transform: none; letter-spacing: normal; color: var(--epg-text-secondary); } } .header-actions { display: flex; align-items: center; gap: 0; } .minimize-btn, .dismiss-all-btn { width: 28px; height: 28px; padding: 0; line-height: 28px; border-radius: 8px; color: var(--epg-text-tertiary); mat-icon { font-size: 18px; width: 18px; height: 18px; } } } .epg-progress-panel--minimized { width: auto; min-width: 180px; max-width: 300px; .panel-header { border-bottom: none; } } .imports-list { max-height: 320px; overflow-y: auto; padding: 4px 0; scrollbar-width: thin; } .import-item { padding: 6px 10px; transition: background 0.15s ease; position: relative; &:not(:last-child) { border-bottom: 1px solid var(--epg-separator); } &:hover { background: var(--epg-item-hover); } .item-header { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; mat-icon { font-size: 16px; width: 16px; height: 16px; flex-shrink: 0; } .item-url { flex: 1; font-size: 0.78rem; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--epg-text-secondary); } .dismiss-btn, .retry-btn { width: 24px; height: 24px; padding: 0; line-height: 24px; border-radius: 6px; opacity: 0; transition: opacity 0.15s ease, color 0.15s ease; color: var(--epg-text-tertiary); mat-icon { font-size: 16px; width: 16px; height: 16px; } } // Retry is a deliberate action — keep it discoverable, not hover-only, // and use the accent color so it reads as primary. .retry-btn { opacity: 1; color: var(--epg-accent); &:hover { color: color-mix( in srgb, var(--epg-accent) 80%, var(--epg-text-primary) ); } } } &:hover .dismiss-btn { opacity: 1; } &.status-loading .item-header mat-icon { color: var(--epg-accent); } &.status-complete .item-header mat-icon { color: var(--epg-success); } &.status-error .item-header mat-icon { color: var(--epg-error); } } .spinning { animation: spin 1.2s linear infinite; } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } .item-stats { display: flex; align-items: center; gap: 6px; padding-left: 24px; min-height: 20px; .stat-badge { display: inline-flex; align-items: center; gap: 3px; font-size: 0.7rem; font-weight: 500; color: var(--epg-text-tertiary); mat-icon { font-size: 12px; width: 12px; height: 12px; } } .error-text { font-size: 0.72rem; color: var(--epg-error); } } .queue-section { margin: 2px 0 0; padding: 6px 10px 8px; border-top: 1px solid var(--epg-separator); // When queue is the only content (no active imports above), // the panel-header border-bottom already provides separation — // suppress this border to avoid a visible double rule. &:first-child { margin-top: 0; border-top: none; } } .queue-header { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; font-size: 0.72rem; font-weight: 600; color: var(--epg-text-tertiary); text-transform: uppercase; letter-spacing: 0.04em; mat-icon { font-size: 14px; width: 14px; height: 14px; color: var(--epg-queued); } } .queue-list { display: flex; flex-direction: column; gap: 2px; } .queue-item { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border-radius: 6px; color: var(--epg-text-tertiary); .queue-position { width: 16px; text-align: center; font-size: 0.68rem; font-weight: 700; color: var(--epg-queued); } .queue-url { flex: 1; font-size: 0.72rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .dismiss-btn { width: 22px; height: 22px; padding: 0; line-height: 22px; color: var(--epg-text-tertiary); mat-icon { font-size: 14px; width: 14px; height: 14px; } } } @media (max-width: 700px) { .epg-progress-panel { left: 76px; right: 12px; bottom: 12px; width: auto; max-width: none; } } @media (max-width: 640px) { .epg-progress-panel { left: 12px; } }