diff --git a/web/packages/core/src/globals.d.ts b/web/packages/core/src/globals.d.ts index 1d42ddde0..00b2bd78e 100644 --- a/web/packages/core/src/globals.d.ts +++ b/web/packages/core/src/globals.d.ts @@ -3,7 +3,7 @@ interface Error { } interface SVGSVGElement { xmlns?: string; - "xmlns:xlink"?: string; + scale?: string | number; } interface SVGPathElement { fill?: string; @@ -17,10 +17,7 @@ interface SVGTextElement { interface SVGCircleElement { fill?: string; } -interface SVGUseElement { - "xlink:href"?: string; -} interface HTMLInputElement { - autoCapitalize?: string; - autoComplete?: string; + autocapitalize?: string; + autocorrect?: string; } diff --git a/web/packages/core/src/ruffle-player.tsx b/web/packages/core/src/ruffle-player.tsx index 55789e7fd..37247817d 100644 --- a/web/packages/core/src/ruffle-player.tsx +++ b/web/packages/core/src/ruffle-player.tsx @@ -1,6 +1,6 @@ import type { RuffleHandle, ZipWriter } from "../dist/ruffle_web"; import { createRuffleBuilder } from "./load-ruffle"; -import { applyStaticStyles, ruffleShadowTemplate } from "./shadow-template"; +import { ruffleShadowTemplate } from "./shadow-template"; import { lookupElement } from "./internal/register-element"; import { DEFAULT_CONFIG } from "./config"; import type { DataLoadOptions, URLLoadOptions } from "./load-options"; @@ -119,7 +119,6 @@ class Point { export class RufflePlayer extends HTMLElement { private readonly shadow: ShadowRoot; private readonly dynamicStyles: HTMLStyleElement; - private readonly staticStyles: HTMLStyleElement; private readonly container: HTMLElement; private readonly playButton: HTMLElement; private readonly unmuteOverlay: HTMLElement; @@ -231,9 +230,6 @@ export class RufflePlayer extends HTMLElement { this.dynamicStyles = this.shadow.getElementById( "dynamic-styles", ) as HTMLStyleElement; - this.staticStyles = this.shadow.getElementById( - "static-styles", - ) as HTMLStyleElement; this.container = this.shadow.getElementById("container")!; this.playButton = this.shadow.getElementById("play-button")!; this.playButton.addEventListener("click", () => this.play()); @@ -529,7 +525,6 @@ export class RufflePlayer extends HTMLElement { */ connectedCallback(): void { this.updateStyles(); - applyStaticStyles(this.staticStyles); } /** diff --git a/web/packages/core/src/shadow-template.tsx b/web/packages/core/src/shadow-template.tsx index e1c689523..1a7447ba9 100644 --- a/web/packages/core/src/shadow-template.tsx +++ b/web/packages/core/src/shadow-template.tsx @@ -1,714 +1,609 @@ import { text } from "./internal/i18n"; -/** - * Insert all rules from array in the style sheet. +/* * - * @param sheet The style sheet to which to apply the rules. - * @param rules An array of rules to be applied. - */ -function insertRules(sheet: CSSStyleSheet, rules: Array) { - for (const rule of rules) { - try { - sheet.insertRule(rule); - } catch (_err) { - // Ignore unsupported rules - } - } -} - -/** - * The default styles to apply to the shadow template. - * This function must be run after the shadow template is added to the page. - * - * @param styleElement The static style element to which to add the rules - */ -export function applyStaticStyles(styleElement: HTMLStyleElement) { - if (!styleElement.sheet) { - return; - } - - const rules = [ - `:host { - all: initial; - pointer-events: inherit; - - --ruffle-blue: #37528c; - --ruffle-orange: #ffad33; - - display: inline-block; - position: relative; - /* Default width/height; this will get overridden by user styles/attributes. */ - width: 550px; - height: 400px; - font-family: Arial, sans-serif; - letter-spacing: 0.4px; - touch-action: none; - user-select: none; - -webkit-user-select: none; - -webkit-tap-highlight-color: transparent; - }`, - - /* Ruffle's width/height CSS interferes with Safari's fullscreen CSS. */ - /* Ensure that Safari's fullscreen mode actually fills the screen. */ - `:host(:-webkit-full-screen) { - display: block; - width: 100% !important; - height: 100% !important; - }`, - - `.hidden { - display: none !important; - }`, - - /* All of these use the dimensions specified by the embed. */ - `#container, - #play-button, - #unmute-overlay, - #unmute-overlay .background, - #panic, - #splash-screen, - #message-overlay { - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - }`, - - `#container { - overflow: hidden; - }`, - - `#container canvas { - width: 100%; - height: 100%; - }`, - - `#play-button, - #unmute-overlay { - cursor: pointer; - display: none; - }`, - - `#unmute-overlay .background { - background: black; - opacity: 0.7; - }`, - - `#play-button .icon, - #unmute-overlay .icon { - position: absolute; - top: 50%; - left: 50%; - width: 50%; - height: 50%; - max-width: 384px; - max-height: 384px; - transform: translate(-50%, -50%); - opacity: 0.8; - }`, - - `#play-button:hover .icon, - #unmute-overlay:hover .icon { - opacity: 1; - }`, - - /* Includes inverted colors from play button! */ - `#panic { - font-size: 20px; - text-align: center; - background: linear-gradient(180deg, #fd3a40 0%, #fda138 100%); - color: white; - display: flex; - flex-flow: column; - justify-content: space-around; - }`, - - `#panic a { - color: var(--ruffle-blue); - font-weight: bold; - }`, - - `#panic-title { - font-size: xxx-large; - font-weight: bold; - }`, - - `#panic-body.details { - flex: 0.9; - margin: 0 10px; - }`, - - `#panic-body textarea { - width: 100%; - height: 100%; - resize: none; - }`, - - `#panic ul { - padding: 0; - display: flex; - list-style-type: none; - justify-content: space-evenly; - }`, - - `#message-overlay { - position: absolute; - background: var(--ruffle-blue); - color: var(--ruffle-orange); - opacity: 1; - z-index: 2; - display: flex; - align-items: center; - justify-content: center; - overflow: auto; - }`, - - `#message-overlay .message { - text-align: center; - max-height: 100%; - max-width: 100%; - padding: 5%; - font-size: 20px; - }`, - - `#message-overlay p { - margin: 0.5em 0; - }`, - - `#message-overlay .message div { - display: flex; - justify-content: center; - flex-wrap: wrap; - column-gap: 1em; - }`, - - `#message-overlay a, #message-overlay button { - cursor: pointer; - background: var(--ruffle-blue); - color: var(--ruffle-orange); - border: 2px solid var(--ruffle-orange); - font-weight: bold; - font-size: 1.25em; - border-radius: 0.6em; - padding: 10px; - text-decoration: none; - margin: 2% 0; - }`, - - `#message-overlay a:hover, #message-overlay button:hover { - background: #ffffff4c; - }`, - - `#continue-btn { - cursor: pointer; - background: var(--ruffle-blue); - color: var(--ruffle-orange); - border: 2px solid var(--ruffle-orange); - font-weight: bold; - font-size: 20px; - border-radius: 20px; - padding: 10px; - }`, - - `#continue-btn:hover { - background: #ffffff4c; - }`, - - `#context-menu-overlay, .modal { - width: 100%; - height: 100%; - z-index: 1; - position: absolute; - }`, - - `#context-menu { - color: rgb(var(--modal-foreground-rgb)); - background-color: var(--modal-background); - border: 1px solid gray; - box-shadow: 0px 5px 10px -5px black; - position: absolute; - font-size: 14px; - text-align: left; - list-style: none; - white-space: nowrap; - padding: 3px 0; - margin: 0; - }`, - - `#context-menu .menu-item { - padding: 5px 10px; - color: rgb(var(--modal-foreground-rgb)); - }`, - - `#context-menu .menu-item.disabled { - cursor: default; - color: rgba(var(--modal-foreground-rgb), 0.5); - }`, - - `#context-menu .menu-item:not(.disabled):hover { - background-color: rgba(var(--modal-foreground-rgb), 0.15); - }`, - - `#context-menu .menu-separator hr { - border: none; - border-bottom: 1px solid rgba(var(--modal-foreground-rgb), 0.2); - margin: 3px; - }`, - - `#splash-screen { - display: flex; - flex-direction: column; - background: var(--splash-screen-background, var(--preloader-background, var(--ruffle-blue))); - align-items: center; - justify-content: center; - }`, - - `.loadbar { - width: 100%; - max-width: 316px; - max-height: 10px; - height: 20%; - background: #253559; - }`, - - `.loadbar-inner { - width: 0px; - max-width: 100%; - height: 100%; - background: var(--ruffle-orange); - }`, - - `.logo { - display: var(--logo-display, block); - max-width: 380px; - max-height: 150px; - }`, - - `.loading-animation { - max-width: 28px; - max-height: 28px; - margin-bottom: 2%; - width: 10%; - aspect-ratio: 1; - }`, - - `.spinner { - stroke-dasharray: 180; - stroke-dashoffset: 135; - stroke: var(--ruffle-orange); - transform-origin: 50% 50%; - animation: rotate 1.5s linear infinite; - }`, - - `@keyframes rotate { - to { - transform: rotate(360deg); - } - }`, - - `#virtual-keyboard { - position: absolute; - opacity: 0; - top: -100px; - width: 1px; - height: 1px; - }`, - - `.modal { - background-color: #0008; - }`, - - `.modal-area { - position: relative; - left: 50%; - transform: translateX(-50%); - background-color: var(--modal-background); - color: rgb(var(--modal-foreground-rgb)); - width: fit-content; - padding: 8px 12px; - border-radius: 12px; - box-shadow: 0 2px 6px 0px #0008; - }`, - - `#modal-area { - width: 450px; - height: 300px; - }`, - - `.close-modal { - width: 16px; - height: 16px; - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='16px' viewBox='0 -960 960 960' width='16px' fill='black'%3E%3Cpath d='M480-392 300-212q-18 18-44 18t-44-18q-18-18-18-44t18-44l180-180-180-180q-18-18-18-44t18-44q18-18 44-18t44 18l180 180 180-180q18-18 44-18t44 18q18 18 18 44t-18 44L568-480l180 180q18 18 18 44t-18 44q-18 18-44 18t-44-18L480-392Z'/%3E%3C/svg%3E"); - cursor: pointer; - filter: var(--modal-foreground-filter); - }`, - - `.modal-button { - display: inline-block; - background-color: rgba(var(--modal-foreground-rgb), 0.2); - color: rgb(var(--modal-foreground-rgb)); - text-decoration: none; - padding: 4px 8px; - border-radius: 6px; - cursor: pointer; - }`, - - `:not(#volume-controls) > .close-modal { - position: absolute; - top: 14px; - right: 16px; - }`, - - `.general-save-options { - text-align: center; - padding-bottom: 8px; - border-bottom: 2px solid rgba(var(--modal-foreground-rgb), 0.3); - }`, - - `#local-saves { - color: inherit; - border-collapse: collapse; - overflow-y: auto; - display: block; - height: calc(100% - 45px); - min-height: 30px; - }`, - - `#local-saves td { - border-bottom: 2px solid rgba(var(--modal-foreground-rgb), 0.15); - height: 30px; - }`, - - `#local-saves td:nth-child(1) { - width: 100%; - word-break: break-all; - }`, - - `.save-option { - display: inline-block; - width: 24px; - height: 24px; - cursor: pointer; - filter: var(--modal-foreground-filter); - vertical-align: middle; - opacity: 0.4; - }`, - - `#local-saves > tr:hover .save-option { - opacity: 1; - }`, - - `#download-save { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 -960 960 960' width='24px' fill='black'%3E%3Cpath d='M480-337q-8 0-15-2.5t-13-8.5L308-492q-12-12-11.5-28t11.5-28q12-12 28.5-12.5T365-549l75 75v-286q0-17 11.5-28.5T480-800q17 0 28.5 11.5T520-760v286l75-75q12-12 28.5-11.5T652-548q11 12 11.5 28T652-492L508-348q-6 6-13 8.5t-15 2.5ZM240-160q-33 0-56.5-23.5T160-240v-80q0-17 11.5-28.5T200-360q17 0 28.5 11.5T240-320v80h480v-80q0-17 11.5-28.5T760-360q17 0 28.5 11.5T800-320v80q0 33-23.5 56.5T720-160H240Z'/%3E%3C/svg%3E"); - }`, - - `#replace-save { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 -1080 960 1200' width='24px' fill='black'%3E%3Cpath d='M440-367v127q0 17 11.5 28.5T480-200q17 0 28.5-11.5T520-240v-127l36 36q6 6 13.5 9t15 2.5q7.5-.5 14.5-3.5t13-9q11-12 11.5-28T612-388L508-492q-6-6-13-8.5t-15-2.5q-8 0-15 2.5t-13 8.5L348-388q-12 12-11.5 28t12.5 28q12 11 28 11.5t28-11.5l35-35ZM240-80q-33 0-56.5-23.5T160-160v-640q0-33 23.5-56.5T240-880h287q16 0 30.5 6t25.5 17l194 194q11 11 17 25.5t6 30.5v447q0 33-23.5 56.5T720-80H240Zm280-560q0 17 11.5 28.5T560-600h160L520-800v160Z'/%3E%3C/svg%3E"); - }`, - - `#delete-save { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 -1020 960 1080' width='24px' fill='black'%3E%3Cpath d='M280-120q-33 0-56.5-23.5T200-200v-520q-17 0-28.5-11.5T160-760q0-17 11.5-28.5T200-800h160q0-17 11.5-28.5T400-840h160q17 0 28.5 11.5T600-800h160q17 0 28.5 11.5T800-760q0 17-11.5 28.5T760-720v520q0 33-23.5 56.5T680-120H280Zm120-160q17 0 28.5-11.5T440-320v-280q0-17-11.5-28.5T400-640q-17 0-28.5 11.5T360-600v280q0 17 11.5 28.5T400-280Zm160 0q17 0 28.5-11.5T600-320v-280q0-17-11.5-28.5T560-640q-17 0-28.5 11.5T520-600v280q0 17 11.5 28.5T560-280Z'/%3E%3C/svg%3E"); - }`, - - `.replace-save { - display: none; - }`, - - `#video-modal .modal-area { - width: 95%; - height: 95%; - box-sizing: border-box; - }`, - - `#video-holder { - height: 100%; - box-sizing: border-box; - padding: 36px 4px 6px; - }`, - - `#video-holder video { - width: 100%; - height: 100%; - background-color: black; - }`, - - `#volume-controls { - display: flex; - align-items: center; - gap: 6px; - }`, - - `#mute-checkbox { - display: none; - }`, - - `label[for="mute-checkbox"] { - width: 24px; - height: 24px; - line-height: 0; - cursor: pointer; - filter: var(--modal-foreground-filter); - }`, - - `#volume-mute { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 -960 960 960' width='24px' fill='black'%3E%3Cpath d='m719.13-419.35-71.67 71.68Q634.78-335 617.13-335t-30.33-12.67q-12.67-12.68-12.67-30.33t12.67-30.33L658.48-480l-71.68-71.67q-12.67-12.68-12.67-30.33t12.67-30.33Q599.48-625 617.13-625t30.33 12.67l71.67 71.68 71.67-71.68Q803.48-625 821.13-625t30.33 12.67q12.67 12.68 12.67 30.33t-12.67 30.33L779.78-480l71.68 71.67q12.67 12.68 12.67 30.33t-12.67 30.33Q838.78-335 821.13-335t-30.33-12.67l-71.67-71.68ZM278-357.87H161.22q-17.66 0-30.33-12.67-12.67-12.68-12.67-30.33v-158.26q0-17.65 12.67-30.33 12.67-12.67 30.33-12.67H278l130.15-129.91q20.63-20.63 46.98-9.45 26.35 11.19 26.35 39.77v443.44q0 28.58-26.35 39.77-26.35 11.18-46.98-9.45L278-357.87Z'/%3E%3C/svg%3E"); - }`, - - `#volume-min { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='161 -960 960 960' width='24px' fill='black'%3E%3Cpath d='M438.65-357.87H321.87q-17.65 0-30.33-12.67-12.67-12.68-12.67-30.33v-158.26q0-17.65 12.67-30.33 12.68-12.67 30.33-12.67h116.78L568.8-732.04q20.63-20.63 46.98-9.45 26.35 11.19 26.35 39.77v443.44q0 28.58-26.35 39.77-26.35 11.18-46.98-9.45L438.65-357.87Z'/%3E%3C/svg%3E"); - }`, - - `#volume-mid { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='80 -960 960 960' width='24px' fill='black'%3E%3Cpath d='M357.98-357.87H241.2q-17.66 0-30.33-12.67-12.67-12.68-12.67-30.33v-158.26q0-17.65 12.67-30.33 12.67-12.67 30.33-12.67h116.78L487.65-731.8q20.63-20.64 47.1-9.57 26.47 11.07 26.47 39.65v443.44q0 28.58-26.47 39.65t-47.1-9.57L357.98-357.87ZM741.8-480q0 42.48-20.47 80.09-20.48 37.61-54.94 60.82-10.22 5.98-20.19.25-9.98-5.73-9.98-17.44v-248.44q0-11.71 9.98-17.32 9.97-5.61 20.19.37 34.46 23.71 54.94 61.45Q741.8-522.48 741.8-480Z'/%3E%3C/svg%3E"); - }`, - - `#volume-max { - background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='9 -960 960 960' width='24px' fill='black'%3E%3Cpath d='M754.22-480.5q0-78.52-41.88-143.9-41.88-65.38-111.91-98.62-14.47-6.74-20.47-20.96-6-14.22-.53-28.93 5.74-15.72 20.34-22.46t29.58 0q92.48 42.46 147.97 127.05 55.48 84.6 55.48 187.82t-55.48 187.82q-55.49 84.59-147.97 127.05-14.98 6.74-29.58 0-14.6-6.74-20.34-22.46-5.47-14.71.53-28.93 6-14.22 20.47-20.96 70.03-33.24 111.91-98.62 41.88-65.38 41.88-143.9ZM286.98-357.87H170.2q-17.66 0-30.33-12.67-12.67-12.68-12.67-30.33v-158.26q0-17.65 12.67-30.33 12.67-12.67 30.33-12.67h116.78L416.65-731.8q20.63-20.64 47.1-9.57 26.47 11.07 26.47 39.65v443.44q0 28.58-26.47 39.65t-47.1-9.57L286.98-357.87ZM670.8-480q0 42.48-20.47 80.09-20.48 37.61-54.94 60.82-10.22 5.98-20.19.25-9.98-5.73-9.98-17.44v-248.44q0-11.71 9.98-17.32 9.97-5.61 20.19.37 34.46 23.71 54.94 61.45Q670.8-522.48 670.8-480Z'/%3E%3C/svg%3E"); - }`, - - `#volume-slider-text { - width: 4.8ch; - text-align: center; - user-select: none; - }`, - - `#hardware-acceleration-modal .modal-area { - text-align: center; - padding: 16px 48px; - width: 95%; - box-sizing: border-box; - }`, - - `#acceleration-text { - display: block; - margin-bottom: 8px; - }`, - - `#clipboard-modal h2 { - margin-top: 4px; - margin-right: 36px; - }`, - - `#clipboard-modal p:last-child { - margin-bottom: 2px; - }`, - - /* Handle preferred color scheme. */ - `@media (prefers-color-scheme: light) { - :host { - --modal-background: #fafafa; - --modal-foreground-rgb: 0, 0, 0; - --modal-foreground-filter: none; - } - }`, - - `@media (prefers-color-scheme: dark) { - :host { - --modal-background: #282828; - --modal-foreground-rgb: 221, 221, 221; - --modal-foreground-filter: invert(90%); - } - }`, - ]; - insertRules(styleElement.sheet, rules); -} - -/** - * Create and return a new HTML Element with the given arguments. - * - * @param tag The HTML tag name of the new element. - * @param id The id of the new element. - * @param className The class name of the new element. - * @param attributes A hash of attributes for the new element. - * @param ns The namespace of the new element. - * - * @returns The newly created Element - */ -function createElement( - tag: string, - id?: string, - className?: string, - attributes?: Record, - ns?: string, -): Element { - const element = ns - ? document.createElementNS(ns, tag) - : document.createElement(tag); - if (id) { - element.id = id; - } - if (className && ns) { - element.classList.add(className); - } else if (className) { - element.className = className; - } - if (attributes) { - for (const [key, attr] of Object.entries(attributes)) { - element.setAttribute(key, attr); - } - } - return element; -} - -/** - * - * @param parentElement The node to which to append a child element. - * @param childElement The node to be appended to the parent element. - */ -function appendElement(parentElement: Node, childElement: Node) { - parentElement.appendChild(childElement); -} - -/** * The shadow template which is used to fill the actual Ruffle player element * on the page. * */ -export const ruffleShadowTemplate = document.createElement("template"); -const staticStyles = createElement("style", "static-styles"); -const dynamicStyles = createElement("style", "dynamic-styles"); +const css = ` + :host { + all: initial; + pointer-events: inherit; + + --ruffle-blue: #37528c; + --ruffle-orange: #ffad33; + + display: inline-block; + position: relative; + /* Default width/height; this will get overridden by user styles/attributes. */ + width: 550px; + height: 400px; + font-family: Arial, sans-serif; + letter-spacing: 0.4px; + touch-action: none; + user-select: none; + -webkit-user-select: none; + -webkit-tap-highlight-color: transparent; + } + + /* Ruffle's width/height CSS interferes with Safari's fullscreen CSS. */ + /* Ensure that Safari's fullscreen mode actually fills the screen. */ + :host(:-webkit-full-screen) { + display: block; + width: 100% !important; + height: 100% !important; + } + + .hidden { + display: none !important; + } + + /* All of these use the dimensions specified by the embed. */ + #container, + #play-button, + #unmute-overlay, + #unmute-overlay .background, + #panic, + #splash-screen, + #message-overlay { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + } + + #container { + overflow: hidden; + } + + #container canvas { + width: 100%; + height: 100%; + } + + #play-button, + #unmute-overlay { + cursor: pointer; + display: none; + } + + #unmute-overlay .background { + background: black; + opacity: 0.7; + } + + #play-button .icon, + #unmute-overlay .icon { + position: absolute; + top: 50%; + left: 50%; + width: 50%; + height: 50%; + max-width: 384px; + max-height: 384px; + transform: translate(-50%, -50%); + opacity: 0.8; + } + + #play-button:hover .icon, + #unmute-overlay:hover .icon { + opacity: 1; + } + + /* Includes inverted colors from play button! */ + #panic { + font-size: 20px; + text-align: center; + background: linear-gradient(180deg, #fd3a40 0%, #fda138 100%); + color: white; + display: flex; + flex-flow: column; + justify-content: space-around; + } + + #panic a { + color: var(--ruffle-blue); + font-weight: bold; + } + + #panic-title { + font-size: xxx-large; + font-weight: bold; + } + + #panic-body.details { + flex: 0.9; + margin: 0 10px; + } + + #panic-body textarea { + width: 100%; + height: 100%; + resize: none; + } + + #panic ul { + padding: 0; + display: flex; + list-style-type: none; + justify-content: space-evenly; + } + + #message-overlay { + position: absolute; + background: var(--ruffle-blue); + color: var(--ruffle-orange); + opacity: 1; + z-index: 2; + display: flex; + align-items: center; + justify-content: center; + overflow: auto; + } + + #message-overlay .message { + text-align: center; + max-height: 100%; + max-width: 100%; + padding: 5%; + font-size: 20px; + } + + #message-overlay p { + margin: 0.5em 0; + } + + #message-overlay .message div { + display: flex; + justify-content: center; + flex-wrap: wrap; + column-gap: 1em; + } + + #message-overlay a, #message-overlay button { + cursor: pointer; + background: var(--ruffle-blue); + color: var(--ruffle-orange); + border: 2px solid var(--ruffle-orange); + font-weight: bold; + font-size: 1.25em; + border-radius: 0.6em; + padding: 10px; + text-decoration: none; + margin: 2% 0; + } + + #message-overlay a:hover, #message-overlay button:hover { + background: #ffffff4c; + } + + #continue-btn { + cursor: pointer; + background: var(--ruffle-blue); + color: var(--ruffle-orange); + border: 2px solid var(--ruffle-orange); + font-weight: bold; + font-size: 20px; + border-radius: 20px; + padding: 10px; + } + + #continue-btn:hover { + background: #ffffff4c; + } + + #context-menu-overlay, .modal { + width: 100%; + height: 100%; + z-index: 1; + position: absolute; + } + + #context-menu { + color: rgb(var(--modal-foreground-rgb)); + background-color: var(--modal-background); + border: 1px solid gray; + box-shadow: 0px 5px 10px -5px black; + position: absolute; + font-size: 14px; + text-align: left; + list-style: none; + white-space: nowrap; + padding: 3px 0; + margin: 0; + } + + #context-menu .menu-item { + padding: 5px 10px; + color: rgb(var(--modal-foreground-rgb)); + } + + #context-menu .menu-item.disabled { + cursor: default; + color: rgba(var(--modal-foreground-rgb), 0.5); + } + + #context-menu .menu-item:not(.disabled):hover { + background-color: rgba(var(--modal-foreground-rgb), 0.15); + } + + #context-menu .menu-separator hr { + border: none; + border-bottom: 1px solid rgba(var(--modal-foreground-rgb), 0.2); + margin: 3px; + } + + #splash-screen { + display: flex; + flex-direction: column; + background: var(--splash-screen-background, var(--preloader-background, var(--ruffle-blue))); + align-items: center; + justify-content: center; + } + + .loadbar { + width: 100%; + max-width: 316px; + max-height: 10px; + height: 20%; + background: #253559; + } + + .loadbar-inner { + width: 0px; + max-width: 100%; + height: 100%; + background: var(--ruffle-orange); + } + + .logo { + display: var(--logo-display, block); + max-width: 380px; + max-height: 150px; + } + + .loading-animation { + max-width: 28px; + max-height: 28px; + margin-bottom: 2%; + width: 10%; + aspect-ratio: 1; + } + + .spinner { + stroke-dasharray: 180; + stroke-dashoffset: 135; + stroke: var(--ruffle-orange); + transform-origin: 50% 50%; + animation: rotate 1.5s linear infinite; + } + + @keyframes rotate { + to { + transform: rotate(360deg); + } + } + + #virtual-keyboard { + position: absolute; + opacity: 0; + top: -100px; + width: 1px; + height: 1px; + } + + .modal { + background-color: #0008; + } + + .modal-area { + position: relative; + left: 50%; + transform: translateX(-50%); + background-color: var(--modal-background); + color: rgb(var(--modal-foreground-rgb)); + width: fit-content; + padding: 8px 12px; + border-radius: 12px; + box-shadow: 0 2px 6px 0px #0008; + } + + #modal-area { + width: 450px; + height: 300px; + } + + .close-modal { + width: 16px; + height: 16px; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='16px' viewBox='0 -960 960 960' width='16px' fill='black'%3E%3Cpath d='M480-392 300-212q-18 18-44 18t-44-18q-18-18-18-44t18-44l180-180-180-180q-18-18-18-44t18-44q18-18 44-18t44 18l180 180 180-180q18-18 44-18t44 18q18 18 18 44t-18 44L568-480l180 180q18 18 18 44t-18 44q-18 18-44 18t-44-18L480-392Z'/%3E%3C/svg%3E"); + cursor: pointer; + filter: var(--modal-foreground-filter); + } + + .modal-button { + display: inline-block; + background-color: rgba(var(--modal-foreground-rgb), 0.2); + color: rgb(var(--modal-foreground-rgb)); + text-decoration: none; + padding: 4px 8px; + border-radius: 6px; + cursor: pointer; + } + + :not(#volume-controls) > .close-modal { + position: absolute; + top: 14px; + right: 16px; + } + + .general-save-options { + text-align: center; + padding-bottom: 8px; + border-bottom: 2px solid rgba(var(--modal-foreground-rgb), 0.3); + } + + #local-saves { + color: inherit; + border-collapse: collapse; + overflow-y: auto; + display: block; + height: calc(100% - 45px); + min-height: 30px; + } + + #local-saves td { + border-bottom: 2px solid rgba(var(--modal-foreground-rgb), 0.15); + height: 30px; + } + + #local-saves td:nth-child(1) { + width: 100%; + word-break: break-all; + } + + .save-option { + display: inline-block; + width: 24px; + height: 24px; + cursor: pointer; + filter: var(--modal-foreground-filter); + vertical-align: middle; + opacity: 0.4; + } + + #local-saves > tr:hover .save-option { + opacity: 1; + } + + #download-save { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 -960 960 960' width='24px' fill='black'%3E%3Cpath d='M480-337q-8 0-15-2.5t-13-8.5L308-492q-12-12-11.5-28t11.5-28q12-12 28.5-12.5T365-549l75 75v-286q0-17 11.5-28.5T480-800q17 0 28.5 11.5T520-760v286l75-75q12-12 28.5-11.5T652-548q11 12 11.5 28T652-492L508-348q-6 6-13 8.5t-15 2.5ZM240-160q-33 0-56.5-23.5T160-240v-80q0-17 11.5-28.5T200-360q17 0 28.5 11.5T240-320v80h480v-80q0-17 11.5-28.5T760-360q17 0 28.5 11.5T800-320v80q0 33-23.5 56.5T720-160H240Z'/%3E%3C/svg%3E"); + } + + #replace-save { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 -1080 960 1200' width='24px' fill='black'%3E%3Cpath d='M440-367v127q0 17 11.5 28.5T480-200q17 0 28.5-11.5T520-240v-127l36 36q6 6 13.5 9t15 2.5q7.5-.5 14.5-3.5t13-9q11-12 11.5-28T612-388L508-492q-6-6-13-8.5t-15-2.5q-8 0-15 2.5t-13 8.5L348-388q-12 12-11.5 28t12.5 28q12 11 28 11.5t28-11.5l35-35ZM240-80q-33 0-56.5-23.5T160-160v-640q0-33 23.5-56.5T240-880h287q16 0 30.5 6t25.5 17l194 194q11 11 17 25.5t6 30.5v447q0 33-23.5 56.5T720-80H240Zm280-560q0 17 11.5 28.5T560-600h160L520-800v160Z'/%3E%3C/svg%3E"); + } + + #delete-save { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 -1020 960 1080' width='24px' fill='black'%3E%3Cpath d='M280-120q-33 0-56.5-23.5T200-200v-520q-17 0-28.5-11.5T160-760q0-17 11.5-28.5T200-800h160q0-17 11.5-28.5T400-840h160q17 0 28.5 11.5T600-800h160q17 0 28.5 11.5T800-760q0 17-11.5 28.5T760-720v520q0 33-23.5 56.5T680-120H280Zm120-160q17 0 28.5-11.5T440-320v-280q0-17-11.5-28.5T400-640q-17 0-28.5 11.5T360-600v280q0 17 11.5 28.5T400-280Zm160 0q17 0 28.5-11.5T600-320v-280q0-17-11.5-28.5T560-640q-17 0-28.5 11.5T520-600v280q0 17 11.5 28.5T560-280Z'/%3E%3C/svg%3E"); + } + + .replace-save { + display: none; + } + + #video-modal .modal-area { + width: 95%; + height: 95%; + box-sizing: border-box; + } + + #video-holder { + height: 100%; + box-sizing: border-box; + padding: 36px 4px 6px; + } + + #video-holder video { + width: 100%; + height: 100%; + background-color: black; + } + + #volume-controls { + display: flex; + align-items: center; + gap: 6px; + } + + #mute-checkbox { + display: none; + } + + label[for="mute-checkbox"] { + width: 24px; + height: 24px; + line-height: 0; + cursor: pointer; + filter: var(--modal-foreground-filter); + } + + #volume-mute { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='0 -960 960 960' width='24px' fill='black'%3E%3Cpath d='m719.13-419.35-71.67 71.68Q634.78-335 617.13-335t-30.33-12.67q-12.67-12.68-12.67-30.33t12.67-30.33L658.48-480l-71.68-71.67q-12.67-12.68-12.67-30.33t12.67-30.33Q599.48-625 617.13-625t30.33 12.67l71.67 71.68 71.67-71.68Q803.48-625 821.13-625t30.33 12.67q12.67 12.68 12.67 30.33t-12.67 30.33L779.78-480l71.68 71.67q12.67 12.68 12.67 30.33t-12.67 30.33Q838.78-335 821.13-335t-30.33-12.67l-71.67-71.68ZM278-357.87H161.22q-17.66 0-30.33-12.67-12.67-12.68-12.67-30.33v-158.26q0-17.65 12.67-30.33 12.67-12.67 30.33-12.67H278l130.15-129.91q20.63-20.63 46.98-9.45 26.35 11.19 26.35 39.77v443.44q0 28.58-26.35 39.77-26.35 11.18-46.98-9.45L278-357.87Z'/%3E%3C/svg%3E"); + } + + #volume-min { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='161 -960 960 960' width='24px' fill='black'%3E%3Cpath d='M438.65-357.87H321.87q-17.65 0-30.33-12.67-12.67-12.68-12.67-30.33v-158.26q0-17.65 12.67-30.33 12.68-12.67 30.33-12.67h116.78L568.8-732.04q20.63-20.63 46.98-9.45 26.35 11.19 26.35 39.77v443.44q0 28.58-26.35 39.77-26.35 11.18-46.98-9.45L438.65-357.87Z'/%3E%3C/svg%3E"); + } + + #volume-mid { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='80 -960 960 960' width='24px' fill='black'%3E%3Cpath d='M357.98-357.87H241.2q-17.66 0-30.33-12.67-12.67-12.68-12.67-30.33v-158.26q0-17.65 12.67-30.33 12.67-12.67 30.33-12.67h116.78L487.65-731.8q20.63-20.64 47.1-9.57 26.47 11.07 26.47 39.65v443.44q0 28.58-26.47 39.65t-47.1-9.57L357.98-357.87ZM741.8-480q0 42.48-20.47 80.09-20.48 37.61-54.94 60.82-10.22 5.98-20.19.25-9.98-5.73-9.98-17.44v-248.44q0-11.71 9.98-17.32 9.97-5.61 20.19.37 34.46 23.71 54.94 61.45Q741.8-522.48 741.8-480Z'/%3E%3C/svg%3E"); + } + + #volume-max { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24px' viewBox='9 -960 960 960' width='24px' fill='black'%3E%3Cpath d='M754.22-480.5q0-78.52-41.88-143.9-41.88-65.38-111.91-98.62-14.47-6.74-20.47-20.96-6-14.22-.53-28.93 5.74-15.72 20.34-22.46t29.58 0q92.48 42.46 147.97 127.05 55.48 84.6 55.48 187.82t-55.48 187.82q-55.49 84.59-147.97 127.05-14.98 6.74-29.58 0-14.6-6.74-20.34-22.46-5.47-14.71.53-28.93 6-14.22 20.47-20.96 70.03-33.24 111.91-98.62 41.88-65.38 41.88-143.9ZM286.98-357.87H170.2q-17.66 0-30.33-12.67-12.67-12.68-12.67-30.33v-158.26q0-17.65 12.67-30.33 12.67-12.67 30.33-12.67h116.78L416.65-731.8q20.63-20.64 47.1-9.57 26.47 11.07 26.47 39.65v443.44q0 28.58-26.47 39.65t-47.1-9.57L286.98-357.87ZM670.8-480q0 42.48-20.47 80.09-20.48 37.61-54.94 60.82-10.22 5.98-20.19.25-9.98-5.73-9.98-17.44v-248.44q0-11.71 9.98-17.32 9.97-5.61 20.19.37 34.46 23.71 54.94 61.45Q670.8-522.48 670.8-480Z'/%3E%3C/svg%3E"); + } + + #volume-slider-text { + width: 4.8ch; + text-align: center; + user-select: none; + } + + #hardware-acceleration-modal .modal-area { + text-align: center; + padding: 16px 48px; + width: 95%; + box-sizing: border-box; + } + + #acceleration-text { + display: block; + margin-bottom: 8px; + } + + #clipboard-modal h2 { + margin-top: 4px; + margin-right: 36px; + } + + #clipboard-modal p:last-child { + margin-bottom: 2px; + } + + /* Handle preferred color scheme. */ + @media (prefers-color-scheme: light) { + :host { + --modal-background: #fafafa; + --modal-foreground-rgb: 0, 0, 0; + --modal-foreground-filter: none; + } + } + + @media (prefers-color-scheme: dark) { + :host { + --modal-background: #282828; + --modal-foreground-rgb: 221, 221, 221; + --modal-foreground-filter: invert(90%); + } + }`; const shortcutModifier = navigator.userAgent.includes("Mac OS X") ? "Command" : "Ctrl"; -const container = ( -
-
-
- - - - - - - - - - - - - -
-
-
-
-
- - - - - - Click to unmute - - -
-
- -
-); -const splashScreen = ( - -); -const saveManager = ( -