/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ :root { --player-bg-color: #000; --player-control-icon-fill: #fff; --player-control-item-half-width: clamp(calc(16px / 2), calc(10vmax / 2), calc(32px / 2)); --player-control-item-height: clamp(16px, 10vmax, 32px); --close-btn-fill-color: #000; --controls-bottom-distance: 15px; --controls-bottom-upper-height: 30px; --scrubber-vertical-margin: 7px; --resize-margin: 5px; background-color: var(--player-bg-color); overflow: hidden; } button::-moz-focus-inner { border: 0; } body { margin: 0; } body:fullscreen { -moz-window-dragging: no-drag; } .player-holder { display: flex; flex-direction: column; height: 100vh; overflow: hidden; } .seethrough-mode { background: transparent; .player-holder { will-change: opacity, filter; transition: opacity 160ms linear, filter 160ms linear; body:hover:not(:fullscreen) & { opacity: 0.35; filter: blur(8px); } } } browser { flex: 1; } #controls { height: calc(100% - 2 * var(--resize-margin)); left: 0; position: absolute; top: 0; width: calc(100% - 2 * var(--resize-margin)); margin: var(--resize-margin); -moz-window-dragging: drag; } #controls button { appearance: none; border: 0; z-index: 1; } #controls button:focus-visible, #controls input:focus-visible, .switch > input:focus-visible + .slider { outline: 3px solid #0060DF; box-shadow: 1px 2px 5px #000; } /* Styling for background gradient. * Opacity changes are handled separately under .control-item. */ #controls-bottom-gradient { background: linear-gradient(0deg, #000000 -13.24%, rgba(0, 0, 0, 0) 90.44%); position: absolute; height: calc(var(--controls-bottom-distance) + 2 * var(--resize-margin) + var(--player-control-item-height) + var(--controls-bottom-upper-height) + var(--scrubber-vertical-margin)); bottom: 0; width: 100vw; margin: 0 calc(-1 * var(--resize-margin)) calc(-1 * var(--resize-margin)) calc(-1 * var(--resize-margin)); pointer-events: none; -moz-window-dragging: drag; } #controls-bottom { position: absolute; bottom: var(--controls-bottom-distance); width: 100%; } .controls-bottom-lower { display: grid; grid-template-columns: repeat(3, 1fr); margin: 0 24px; } .start-controls { display: grid; justify-self: start; } .center-controls { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-areas: "seekbackward playpause seekforward"; justify-self: center; gap: 8px; } .end-controls { display: grid; grid-template-columns: 1fr 2fr 1fr 1fr; grid-template-areas: "audio audio-scrubber closedcaption fullscreen"; justify-self: end; gap: 8px; } .control-item { -moz-window-dragging: no-drag; transition: opacity 160ms linear, fill-opacity 160ms linear; opacity: 0; cursor: pointer; } .control-button { background-color: transparent; border-radius: 4px; /** * Make the button dimensions a square proportional to one * dimension of the window - in this case, the width dimension, * since we suspect most videos are wider than they are tall. */ height: var(--player-control-item-height); width: 10vmax; max-width: 32px; min-width: 16px; -moz-context-properties: fill, fill-opacity; fill: var(--player-control-icon-fill); background-position: center; background-size: 60%; background-repeat: no-repeat; } .control-button:hover:enabled { background-color: rgba(255, 255, 255, .25); } #controls:is([keying], [showing]) .control-button:disabled, /* Only change opacity on hover events for non-fullscreen mode. * Fullscreen mode uses the `showing` attribute instead. */ body:not(:fullscreen) #controls:hover .control-button:disabled { /* Set `fill-opacity` to the desired opacity in addition to full `opacity` * to allow having the button's tooltip in full opacity even if the button is disabled. */ fill-opacity: 0.4; opacity: 1 !important; } .control-item:focus-visible::after, .control-item:hover::after { content: attr(tooltip); display: inline-block; width: max-content; position: relative; padding: .4em .5em; background: #000000; color: #ffffff; border-radius: 4px; pointer-events: none; } /* Since #controls is set to LTR, button tooltips would normally appear * as LTR also for RTL locales. To fix this, set the .control-item's ::after * to RTL based on the root directionality. * Because of that, don't set logical properties for the next set of rules. */ :root:dir(rtl) .control-item::after { direction: rtl; } /* Set the tooltip position for different playback controls */ .tooltip-under-controls:focus-visible::after, .tooltip-under-controls:hover::after { bottom: -3em; } #close:focus-visible::after, #close:hover::after, #unpip[mac="true"]:focus-visible::after, #unpip[mac="true"]:hover::after { float: right; transform: translateX(1em); } #unpip:focus-visible::after, #unpip:hover::after, #close[mac="true"]:focus-visible::after, #close[mac="true"]:hover::after { float: left; transform: translateX(-1em); } .tooltip-over-controls:focus-visible::after, .tooltip-over-controls:hover::after { bottom: 3em; } .inline-end-tooltip:focus-visible::after, .inline-end-tooltip:hover::after { float: right; right: -1em; } .inline-start-tooltip:focus-visible::after, .inline-start-tooltip:hover::after { float: left; left: -1em; } .center-tooltip:focus-visible::after, .center-tooltip:hover::after { right: 0.8em; translate: calc(-50% + var(--player-control-item-half-width)); } /* Since the unpip button icon is reversed for RTL locales, * re-position the tooltip so that the tooltip remains in the original placement */ :root:dir(rtl) #unpip:focus-visible::after, :root:dir(rtl) #unpip:hover::after { float: right; } :root:dir(rtl) #unpip[mac="true"]:focus-visible::after, :root:dir(rtl) #unpip[mac="true"]:hover::after { float: left; } /* Since the unpip icon is reversed for RTL locales, * flip its tooltip back */ :root:dir(rtl) #unpip:focus-visible::after, :root:dir(rtl) #unpip:hover::after { scale: -1 1; } /* Set opacity for buttons and scrubber when controls are visible on the pip window and are not hovered over. * For fullscreen mode, only apply opacity if there is a showing attribute. */ body:not(:fullscreen) #controls:hover .control-item:not(:hover), body:fullscreen #controls[showing]:hover .control-item:not(:hover), #controls[donthide] .control-item { opacity: 0.8; } #controls[keying] .control-item, #controls[showing] .control-item, .control-item:hover { opacity: 1; } /* Background gradient is the only control item with a fixed opacity value. */ #controls[keying] #controls-bottom-gradient, #controls[showing] #controls-bottom-gradient, #controls-bottom-gradient:hover { opacity: 0.8; } /* For readability, timestamp should maintain full opacity when visible */ body:not(:fullscreen) #controls:hover #timestamp, body:fullscreen #controls[showing]:hover { opacity: 1; } #close, #unpip { background-color: rgba(255, 255, 255, .8); position: absolute; fill: var(--close-btn-fill-color); } #close:is(:hover, :focus-visible), #unpip:is(:hover, :focus-visible) { background-color: rgba(255, 255, 255, .9); } #close { background-image: url("chrome://global/skin/icons/close.svg"); right: 10px; top: 10px; } #close[mac="true"] { right: auto; left: 10px; } #unpip { background-image: url("chrome://global/skin/media/picture-in-picture-closed.svg"); left: 10px; top: 10px; } #unpip[mac="true"] { right: 10px; left: auto; } #playpause { grid-area: playpause; } #audio { grid-area: audio; } #audio-scrubber { grid-area: audio-scrubber; align-self: center; width: 64px; background-color: transparent; padding: 6px 2px; margin: 0; &::-moz-range-thumb { border-radius: 8px; background-color: #FFFFFF; width: 8px; height: 8px; padding: 0; } &::-moz-range-track { background-color: #969696; } &::-moz-range-progress { background-color: #FFFFFF; } &, &::-moz-range-track, &::-moz-range-progress { height: 2px; border-radius: 10px; } } #fullscreen { grid-area: fullscreen; } #controls.playing #playpause { background-image: url("chrome://global/skin/media/pause-fill.svg"); } #controls:not(.playing) #playpause { background-image: url("chrome://global/skin/media/play-fill.svg"); } #controls.muted #audio { background-image: url("chrome://global/skin/media/audio-muted.svg"); } #controls:not(.muted) #audio { background-image: url("chrome://global/skin/media/audio.svg"); } body:fullscreen #fullscreen { background-image: url("chrome://global/skin/media/picture-in-picture-exit-fullscreen-button.svg"); background-size: auto; } body:not(:fullscreen) #fullscreen { background-image: url("chrome://global/skin/media/picture-in-picture-enter-fullscreen-button.svg"); background-size: auto; } #seekBackward { background-image: url("chrome://global/skin/media/picture-in-picture-seekBackward-button.svg"); background-size: auto; grid-area: seekbackward; } #seekForward { background-image: url("chrome://global/skin/media/picture-in-picture-seekForward-button.svg"); background-size: auto; grid-area: seekforward; } :root:dir(rtl) #unpip { transform: scaleX(-1); } #closed-caption { background-image: url("chrome://global/skin/media/closed-caption-settings-button.svg"); color: white; grid-area: closedcaption; } .box { -moz-window-dragging: no-drag; background-color: #2B2A33; text-align: start; font-size: 1em; width: 186px; padding: 0 8px; margin: 0; border-radius: 8px; } :root:dir(rtl) .box { direction: rtl; } .a11y-only { visibility: hidden; position: absolute; } .hide { display: none; } .bold { font-weight: 590; } .box > input[type="radio"] { background-color: red; fill: currentColor; } .box label:not(.switch) { color: white; font-family: sans-serif; } #subtitles-toggle-label { width: fit-content; padding: 8px; } .panel { position: absolute; bottom: 40px; user-select: none; right: 24px; } .panel-fieldset { border: none; margin-top: 8px; padding-inline-start: 0; } .panel-legend { font-family: sans-serif; color: white; margin-top: 8px; padding-inline-start: 0; } .arrow { border: 10px solid transparent; border-top-color: #2B2A33; width: 0; height: 0; inset-inline-start: 136px; position: relative; } .grey-line { width: 100%; height: 1px; background: #8F8F9D; } .font-size-selection { margin-inline-start: 8px; padding-inline-start: 8px; } .font-size-selection-radio { display: flex; width: fit-content; cursor: pointer; padding-block: 8px; } .font-size-selection-radio label { cursor: pointer; } .font-size-selection-radio > input[type="radio"] { appearance: none; width: 16px; height: 16px; border: 1px solid #8f8f9d; border-radius: 50%; margin: 0; margin-inline-end: 6px; } .font-size-selection-radio > input[type="radio"]:checked { border: 4px solid #00ddff; } .subtitle-grid { display: grid; grid-template-rows: auto; grid-template-columns: auto 46px; padding: 8px; } .switch { position: relative; display: inline-block; width: 32px; height: 16px; grid-column: 2; margin: 8px; cursor: pointer; } .switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; inset: 0; transition: transform 250ms; border-radius: 13px; background-color: #55545f; } .slider::before { position: absolute; content: ''; height: 12px; width: 12px; inset-inline-start: 2px; bottom: 2px; background-color: #2B2A33; transition: transform 250ms; border-radius: 50%; } input:checked + .slider { background-color: #00ddff; } input:checked + .slider::before { transform: translateX(16px); } :root:dir(rtl) input:checked + .slider::before { transform: translateX(-16px); } .font-size-overlay { opacity: 0.4; pointer-events: none; } .controls-bottom-upper { width: calc(100% - 38px); height: var(--controls-bottom-upper-height); margin: 0 19px; display: grid; } .scrubber-no-drag { -moz-window-dragging: no-drag; height: 16px; margin: var(--scrubber-vertical-margin) 0; display: grid; justify-items: center; align-items: center; width: 100%; } #scrubber { width: 100%; background-color: transparent; padding: 6px 2px; &::-moz-range-thumb { border-radius: 14px; background-color: #BFBFC9; width: 8px; height: 8px; border: 3px solid #FFFFFF; padding: 0; } &::-moz-range-track { background-color: #969696; } &::-moz-range-progress { background-color: #FFFFFF; } &, &::-moz-range-track, &::-moz-range-progress { height: 4px; border-radius: 10px; } } #timestamp { align-self: center; color: #FFFFFF; cursor: default; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Ubuntu", "Helvetica Neue", sans-serif; font-size: 0.9em; user-select: none; width: 16ch; grid-area: timestamp; } #timestamp::after { background: unset; content: unset; } @media (width <= 630px) { #audio-scrubber { display: none; } .end-controls { grid-template-columns: repeat(3, 1fr); grid-template-areas: "audio closedcaption fullscreen"; } } @media (width <= 475px) { #closed-caption { display: none; } .end-controls { grid-template-columns: repeat(2, 1fr); grid-template-areas: "audio fullscreen"; } } @media (height <= 325px) and (width > 630px) { #closed-caption { display: none; } .end-controls { grid-template-columns: 1fr 2fr 1fr; grid-template-areas: "audio audio-scrubber fullscreen"; } } @media (height <= 325px) and (width <= 630px) { #closed-caption, #audio-scrubber { display: none; } .end-controls { grid-template-columns: repeat(2, 1fr); grid-template-areas: "audio fullscreen"; } } @media (width <= 440px) { #timestamp { display: none; } } @media (width <= 350px) { #fullscreen { display: none; } .end-controls { grid-template-columns: repeat(1, 1fr); grid-template-areas: "audio"; } } @media (height <= 200px) { .scrubber-no-drag { display: none; } } @media (width <= 300px) { .scrubber-no-drag, #seekForward, #seekBackward, .start-controls { display: none; } .controls-bottom-lower { grid-template-columns: repeat(2, 1fr); } .center-controls { grid-template-columns: repeat(1, 1fr); grid-template-areas: "playpause"; } .end-controls { justify-self: center; } }