/* ============================================================ dash.js Controlbar – Standalone CSS ============================================================ Include this stylesheet alongside ControlBar.js. Requires Bootstrap Icons CSS for icon display. Theming: override --cb-accent and --cb-danger on the .cb-controlbar selector (or any ancestor) to customise highlight and live-indicator colours. ============================================================ */ /* ---- Default theme variables ---- */ .cb-controlbar { --cb-accent: #5b8def; --cb-danger: #e74c3c; } .cb-skip-btn { min-width: 2.5rem; font-size: 0.8rem; font-weight: 700; } /* ---- Utility: hidden element (replaces Bootstrap d-none) ---- */ .cb-hidden-element { display: none !important; } /* ---- Control Bar container ---- */ .cb-controlbar { position: absolute; bottom: 0; left: 0; right: 0; background: linear-gradient(transparent, rgba(0, 0, 0, 0.85)); padding: 2rem 1rem 0.5rem 1rem; z-index: 10; transition: opacity 0.3s ease, visibility 0.3s ease; display: flex; flex-direction: column; gap: 0.35rem; } .cb-controlbar.cb-hidden { opacity: 0; visibility: hidden; pointer-events: none; } .cb-controlbar.cb-disabled { pointer-events: none; opacity: 0.3; } /* ---- Seekbar ---- */ .cb-seekbar-row { display: flex; align-items: center; gap: 0.5rem; position: relative; } .cb-seekbar { flex: 1; height: 4px; background: rgba(255, 255, 255, 0.2); border-radius: 2px; position: relative; cursor: pointer; transition: height 0.1s; } .cb-seekbar:hover { height: 6px; } .cb-seekbar-buffer { position: absolute; top: 0; left: 0; height: 100%; background: rgba(255, 255, 255, 0.3); border-radius: 2px; pointer-events: none; } .cb-seekbar-played { position: absolute; top: 0; left: 0; height: 100%; background: var(--cb-accent); border-radius: 2px; pointer-events: none; } .cb-seekbar-played::after { content: ''; position: absolute; right: -6px; top: 50%; transform: translateY(-50%); width: 12px; height: 12px; background: var(--cb-accent); border-radius: 50%; opacity: 0; transition: opacity 0.1s; } .cb-seekbar:hover .cb-seekbar-played::after { opacity: 1; } /* ---- Control buttons row ---- */ .cb-controls-row { display: flex; align-items: center; gap: 0.5rem; } .cb-btn { background: none; border: none; color: #fff; font-size: 1.1rem; cursor: pointer; padding: 0.25rem; opacity: 0.85; transition: opacity 0.15s; display: flex; align-items: center; justify-content: center; } .cb-btn:hover { opacity: 1; } .cb-time { font-size: 0.8rem; color: #fff; font-variant-numeric: tabular-nums; white-space: nowrap; user-select: none; } .cb-time-separator { opacity: 0.4; } .cb-spacer { flex: 1; } /* ---- Volume ---- */ .cb-volume-group { display: flex; align-items: center; gap: 0.25rem; } .cb-volume-slider { width: 80px; height: 4px; -webkit-appearance: none; appearance: none; background: rgba(255, 255, 255, 0.3); border-radius: 2px; outline: none; cursor: pointer; } .cb-volume-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; background: #fff; border-radius: 50%; cursor: pointer; } .cb-volume-slider::-moz-range-thumb { width: 12px; height: 12px; background: #fff; border-radius: 50%; cursor: pointer; border: none; } /* ---- Playback rate controls ---- */ .cb-rate-group { display: flex; align-items: center; gap: 0.15rem; margin: 0 0.25rem; } .cb-rate-display { color: #e0e0e0; font-size: 0.75rem; min-width: 2.5rem; text-align: center; cursor: pointer; user-select: none; line-height: 1; } .cb-rate-display:hover { color: #ffffff; } .cb-btn-sm { font-size: 0.7rem; padding: 0.1rem 0.3rem; } /* ---- Live indicator ---- */ .cb-live-indicator { cursor: pointer; color: #8a8aa0; } .cb-live-indicator.cb-at-live-edge { color: var(--cb-danger); } .cb-live-indicator .bi-circle-fill { font-size: 0.5rem; vertical-align: middle; } /* ---- Thumbnail preview ---- */ .cb-thumbnail-container { position: absolute; bottom: 100%; pointer-events: none; z-index: 20; text-align: center; } .cb-thumbnail-elem { border: 2px solid #fff; border-radius: 4px; overflow: hidden; transform-origin: center bottom; } .cb-thumbnail-time { font-size: 0.7rem; color: #fff; background: rgba(0, 0, 0, 0.7); padding: 1px 6px; border-radius: 3px; margin-top: 4px; display: inline-block; } /* ---- Menu anchors and menus ---- */ .cb-menu-anchor { position: relative; } /* Menus — always dark (overlays video) */ .cb-menu { position: absolute; bottom: 100%; right: 0; background: rgba(20, 20, 40, 0.95); border: 1px solid #2d2d50; border-radius: 6px; min-width: 180px; max-height: min(400px, 60vh); overflow-y: auto; padding: 0.25rem 0; margin-bottom: 0.5rem; backdrop-filter: blur(10px); z-index: 30; } /* Scrollbar styling for menus */ .cb-menu::-webkit-scrollbar { width: 6px; } .cb-menu::-webkit-scrollbar-track { background: transparent; } .cb-menu::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.2); border-radius: 3px; } .cb-menu::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.35); } /* Firefox scrollbar */ .cb-menu { scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, 0.2) transparent; } .cb-menu-title { padding: 0.35rem 0.75rem; font-size: 0.7rem; font-weight: 600; color: rgba(255, 255, 255, 0.5); text-transform: uppercase; letter-spacing: 0.03em; } .cb-menu-item { padding: 0.35rem 0.75rem; font-size: 0.8rem; cursor: pointer; color: #e0e0e0; transition: background 0.1s; } .cb-menu-item:hover { background: rgba(255, 255, 255, 0.1); } .cb-menu-item-selected { color: var(--cb-accent); font-weight: 600; } .cb-menu-item-selected::before { content: '✓ '; } /* ---- Fullscreen wrapper helper ---- */ .cb-fullscreen { /* Applied to the wrapper element when entering fullscreen */ }