mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
fix(studio): ship component styles as their own stylesheet for embedders (#4393)
* fix(studio): ship component styles as their own stylesheet for embedders Studio's component rules (timeline clips, loaders, range inputs, toasts and the rest) lived only in the app sheet, so a page that embeds Studio's components with theme.css got unstyled clips and dark-on-dark labels. They move unchanged into components.css, exported as @hyperframes/studio/components.css; studio.css keeps the app shell and imports it, so Studio's compiled CSS has the same rules. * test(studio): read moved component rules from components.css * test(studio): catch class rules nested in the app sheet's layers and media blocks
This commit is contained in:
@@ -19,6 +19,12 @@
|
||||
"types": null,
|
||||
"environments": ["browser"]
|
||||
},
|
||||
"./components.css": {
|
||||
"source": "./src/styles/components.css",
|
||||
"runtime": "./src/styles/components.css",
|
||||
"types": null,
|
||||
"environments": ["browser"]
|
||||
},
|
||||
"./styles.css": {
|
||||
"source": "./src/styles/studio.css",
|
||||
"runtime": "./dist/styles.css",
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"types": "./src/styles/tailwind-preset.ts"
|
||||
},
|
||||
"./theme.css": "./src/styles/theme.css",
|
||||
"./components.css": "./src/styles/components.css",
|
||||
"./styles.css": "./src/styles/studio.css",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
@@ -42,6 +43,7 @@
|
||||
"types": "./dist/styles/tailwind-preset.d.ts"
|
||||
},
|
||||
"./theme.css": "./src/styles/theme.css",
|
||||
"./components.css": "./src/styles/components.css",
|
||||
"./styles.css": "./dist/styles.css",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
const studioCss = readFileSync(new URL("../../styles/studio.css", import.meta.url), "utf8");
|
||||
const studioCss = readFileSync(new URL("../../styles/components.css", import.meta.url), "utf8");
|
||||
|
||||
describe("preview volume range styles", () => {
|
||||
it("uses the same compact thumb in Chromium and Firefox", () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
const studioCss = readFileSync(new URL("../../styles/studio.css", import.meta.url), "utf8");
|
||||
const studioCss = readFileSync(new URL("../../styles/components.css", import.meta.url), "utf8");
|
||||
const themeCss = readFileSync(new URL("../../styles/theme.css", import.meta.url), "utf8");
|
||||
const timelineOverlaySources = [
|
||||
"TimelineShortcutHint.tsx",
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/** Guards the split between Studio's app sheet and the component rules an embedder imports. */
|
||||
|
||||
import { readFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { compile } from "tailwindcss";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { loadStylesheet, STYLES_DIR } from "./styleSources";
|
||||
|
||||
/** Class names in a stylesheet's selectors, at any nesting depth (inside @layer or @media too). */
|
||||
function selectorClasses(css: string): string[] {
|
||||
const source = css.replace(/\/\*[\s\S]*?\*\//g, "").replace(/@(?:import|source)[^;]*;/g, "");
|
||||
return [...source.matchAll(/([^{};]+)\{/g)]
|
||||
.map((match) => match[1].trim())
|
||||
.filter((prelude) => !prelude.startsWith("@"))
|
||||
.flatMap((selector) => [...selector.matchAll(/\.(-?[_a-zA-Z][\w-]*)/g)].map((m) => m[1]));
|
||||
}
|
||||
|
||||
describe("studio component styles", () => {
|
||||
it("keeps class rules out of the app sheet, where an embedder never sees them", () => {
|
||||
const appSheet = readFileSync(path.join(STYLES_DIR, "studio.css"), "utf8");
|
||||
|
||||
expect(selectorClasses(appSheet), "move these rules to components.css").toEqual([]);
|
||||
expect(
|
||||
selectorClasses(readFileSync(path.join(STYLES_DIR, "components.css"), "utf8")),
|
||||
).toContain("timeline-clip__label");
|
||||
});
|
||||
|
||||
it("gives an embedder the timeline rules from theme.css and components.css alone", async () => {
|
||||
const entry = '@import "tailwindcss";\n@import "./theme.css";\n@import "./components.css";';
|
||||
const css = (await compile(entry, { base: STYLES_DIR, loadStylesheet })).build([]);
|
||||
|
||||
expect(css).toMatch(/^\s*\.timeline-clip__label \{/m);
|
||||
expect(css).not.toContain("#root");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,843 @@
|
||||
/* Rules for Studio's components, for any page that renders them. Reads the tokens in
|
||||
* theme.css. The app shell (body, #root, preflight) stays in studio.css. */
|
||||
|
||||
.hf-color-grading-number::-webkit-outer-spin-button,
|
||||
.hf-color-grading-number::-webkit-inner-spin-button {
|
||||
margin: 0;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.hf-color-grading-number {
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
}
|
||||
|
||||
.hf-color-grading-range {
|
||||
height: 1.5rem;
|
||||
cursor: default;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hf-color-grading-range:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.hf-color-grading-range::-webkit-slider-runnable-track {
|
||||
height: 1.25rem;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hf-color-grading-range::-webkit-slider-thumb {
|
||||
width: 0.625rem;
|
||||
height: 1rem;
|
||||
margin-top: 0.125rem;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
background: #ffffff;
|
||||
box-shadow:
|
||||
0 0 0 2px #0c0c0e,
|
||||
0 1px 4px rgba(0, 0, 0, 0.55);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.hf-color-grading-range::-moz-range-track {
|
||||
height: 1.25rem;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hf-color-grading-range::-moz-range-thumb {
|
||||
width: 0.625rem;
|
||||
height: 1rem;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
background: #ffffff;
|
||||
box-shadow:
|
||||
0 0 0 2px #0c0c0e,
|
||||
0 1px 4px rgba(0, 0, 0, 0.55);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.hf-color-grading-range:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.hf-color-grading-range:focus-visible::-webkit-slider-thumb {
|
||||
box-shadow:
|
||||
0 0 0 2px #0c0c0e,
|
||||
0 0 0 4px rgba(60, 230, 172, 0.22),
|
||||
0 1px 4px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
.hf-color-grading-range:focus-visible::-moz-range-thumb {
|
||||
box-shadow:
|
||||
0 0 0 2px #0c0c0e,
|
||||
0 0 0 4px rgba(60, 230, 172, 0.22),
|
||||
0 1px 4px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
.hf-preview-volume-range {
|
||||
height: 1.5rem;
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range:disabled {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range::-webkit-slider-runnable-track {
|
||||
height: 2px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range::-webkit-slider-thumb {
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
margin-top: -3px;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
appearance: none;
|
||||
background: #ffffff;
|
||||
box-shadow:
|
||||
0 0 0 2px #0a0a0a,
|
||||
0 1px 3px rgba(0, 0, 0, 0.5);
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range::-webkit-slider-thumb:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range::-moz-range-track,
|
||||
.hf-preview-volume-range::-moz-range-progress {
|
||||
height: 2px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range::-moz-range-thumb {
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
background: #ffffff;
|
||||
box-shadow:
|
||||
0 0 0 2px #0a0a0a,
|
||||
0 1px 3px rgba(0, 0, 0, 0.5);
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range::-moz-range-thumb:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range:focus-visible::-webkit-slider-thumb,
|
||||
.hf-preview-volume-range:focus-visible::-moz-range-thumb {
|
||||
box-shadow:
|
||||
0 0 0 2px #0a0a0a,
|
||||
0 0 0 4px rgba(60, 230, 172, 0.4),
|
||||
0 1px 3px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.timeline-clip {
|
||||
background-color: var(--clip-bg);
|
||||
border: 1px solid var(--clip-border);
|
||||
border-radius: var(--timeline-clip-radius);
|
||||
box-shadow:
|
||||
inset 0 1px 0 var(--timeline-clip-highlight),
|
||||
var(--timeline-clip-shadow);
|
||||
}
|
||||
|
||||
.timeline-transition {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
pointer-events: none;
|
||||
z-index: 30;
|
||||
}
|
||||
|
||||
.timeline-transition__zone {
|
||||
position: absolute;
|
||||
left: calc(var(--timeline-transition-zone-width) / -2);
|
||||
top: -21px;
|
||||
width: var(--timeline-transition-zone-width);
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background: var(--timeline-transition-zone);
|
||||
filter: blur(2.5px);
|
||||
opacity: 0.95;
|
||||
}
|
||||
|
||||
.timeline-transition__image {
|
||||
position: absolute;
|
||||
inset: -4px;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.timeline-transition__image--out {
|
||||
mask-image: linear-gradient(90deg, black 0%, transparent 100%);
|
||||
}
|
||||
|
||||
.timeline-transition__image--in {
|
||||
mask-image: linear-gradient(90deg, transparent 0%, black 100%);
|
||||
}
|
||||
|
||||
.timeline-transition__badge {
|
||||
position: absolute;
|
||||
left: -14px;
|
||||
top: -14px;
|
||||
display: grid;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
place-items: center;
|
||||
border: 1px solid color-mix(in srgb, var(--timeline-transition-badge-ink) 22%, transparent);
|
||||
border-radius: 999px;
|
||||
background: var(--timeline-transition-badge);
|
||||
box-shadow: 0 2px 5px var(--timeline-playhead-shadow);
|
||||
}
|
||||
|
||||
.timeline-transition__badge svg {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
}
|
||||
.timeline-transition__frame,
|
||||
.timeline-transition__frame--out,
|
||||
.timeline-transition__frame--in {
|
||||
fill: none;
|
||||
stroke: var(--timeline-transition-badge-ink);
|
||||
stroke-width: 1.5;
|
||||
}
|
||||
.timeline-transition__intersection {
|
||||
fill: var(--timeline-transition-badge-ink);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.timeline-clip::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
background: var(--clip-bg-active);
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.timeline-clip[data-active] {
|
||||
border-color: var(--clip-border-active);
|
||||
}
|
||||
|
||||
.timeline-clip[data-active]::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Audio clips read as a distinct kind — a persistent violet tint vs the teal-
|
||||
accented visual clips — so the audio zone at the bottom is visually separate
|
||||
at a glance (the timeline's kinds: visual on top, audio below). */
|
||||
.timeline-clip.is-audio {
|
||||
background-color: var(--timeline-clip-audio-bg);
|
||||
border-color: var(--timeline-clip-audio-border);
|
||||
border-radius: var(--timeline-clip-audio-radius);
|
||||
}
|
||||
|
||||
.timeline-clip.is-audio.is-hovered {
|
||||
background-color: var(--timeline-clip-audio-bg-hover);
|
||||
}
|
||||
|
||||
.timeline-clip.is-audio.is-dragging {
|
||||
box-shadow:
|
||||
inset 0 0 0 999px var(--timeline-clip-audio-bg-dragging),
|
||||
0 8px 24px var(--timeline-clip-shadow-dragging);
|
||||
}
|
||||
|
||||
/* Mute greys the pill in place. Hot path: no transition. */
|
||||
.timeline-clip.is-audio[data-clip-hidden="true"],
|
||||
.timeline-clip.is-audio[data-audio-muted="true"] {
|
||||
background-color: var(--timeline-clip-audio-muted-bg);
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.timeline-audio-link {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
top: -9px;
|
||||
left: 50%;
|
||||
width: 1px;
|
||||
height: 10px;
|
||||
background: var(--timeline-audio-link);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.timeline-clip.is-hovered {
|
||||
background-color: var(--clip-bg-hover);
|
||||
}
|
||||
|
||||
.timeline-clip[data-active].is-hovered {
|
||||
border-color: var(--clip-border-hover);
|
||||
}
|
||||
|
||||
.timeline-clip.is-selected {
|
||||
outline: 1.5px solid var(--timeline-clip-selection);
|
||||
outline-offset: -1.5px;
|
||||
}
|
||||
|
||||
.timeline-clip.is-selected::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 4;
|
||||
border-radius: inherit;
|
||||
box-shadow: inset 0 0 0 1px var(--timeline-clip-selection-highlight);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.timeline-clip[data-active].is-selected {
|
||||
outline: 1.5px solid var(--timeline-clip-selection);
|
||||
outline-offset: -1.5px;
|
||||
}
|
||||
|
||||
.timeline-clip.is-dragging {
|
||||
/* Veil is a shadow, not background-color, so drop does not fade the hover fill. */
|
||||
box-shadow:
|
||||
inset 0 0 0 999px var(--clip-bg-dragging),
|
||||
0 8px 24px var(--timeline-clip-shadow-dragging);
|
||||
}
|
||||
|
||||
.timeline-clip__label {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 6px;
|
||||
z-index: 6;
|
||||
width: fit-content;
|
||||
max-width: calc(100% - 22px);
|
||||
overflow: hidden;
|
||||
padding: 1px 5px;
|
||||
border-radius: 4px;
|
||||
background: var(--timeline-clip-chip-bg);
|
||||
color: var(--timeline-clip-chip-text);
|
||||
font-size: 10px;
|
||||
font-weight: 500;
|
||||
line-height: 16px;
|
||||
pointer-events: none;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.timeline-clip.is-audio .timeline-clip__label {
|
||||
top: 11px;
|
||||
left: 9px;
|
||||
background: var(--timeline-clip-chip-audio-bg);
|
||||
}
|
||||
|
||||
.timeline-clip__timecode {
|
||||
position: absolute;
|
||||
bottom: 6px;
|
||||
left: 12px;
|
||||
overflow: hidden;
|
||||
color: var(--timeline-tick-text);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 9px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
line-height: 1;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.timeline-clip {
|
||||
transition: background-color 120ms ease-out;
|
||||
}
|
||||
|
||||
.timeline-clip__handle-bar {
|
||||
transition: opacity 120ms ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
/* CodeMirror overrides */
|
||||
.cm-editor {
|
||||
height: 100%;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.cm-editor .cm-scroller {
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.cm-editor.cm-focused {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* HyperFrames brand loader. Shared by preview overlays that need a calm,
|
||||
* branded loading state instead of a generic spinner.
|
||||
*/
|
||||
.hf-loader {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.75rem;
|
||||
width: min(34rem, 100%);
|
||||
padding: 1.5rem;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
.hf-frame {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 12rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
background: rgba(0, 0, 0, 0.52);
|
||||
}
|
||||
|
||||
.hf-loader-mark-frame {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
overflow: visible;
|
||||
transform-origin: 50% 50%;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
.hf-loader-mark {
|
||||
display: block;
|
||||
overflow: visible;
|
||||
filter: drop-shadow(0 0 7px rgba(79, 219, 94, 0.2));
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
.hf-loader-title {
|
||||
font-family: var(--font-sans);
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0;
|
||||
color: var(--hf-heading, #f4f4f5);
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.hf-loader-detail {
|
||||
max-width: 32rem;
|
||||
min-height: 2.5rem;
|
||||
overflow: hidden;
|
||||
color: var(--hf-text-secondary, rgba(244, 244, 245, 0.68));
|
||||
font-family: var(--font-sans);
|
||||
font-size: 0.82rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.hf-loader-mono {
|
||||
width: min(36rem, 100%);
|
||||
min-height: 1.5rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: var(--hf-text-tertiary, rgba(244, 244, 245, 0.46));
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.75rem;
|
||||
letter-spacing: 0;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.hf-loader-progress {
|
||||
width: min(18rem, 72vw);
|
||||
height: 0.375rem;
|
||||
overflow: hidden;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
@keyframes hf-thumb-fade {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.hf-loader-progress__fill {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform: scaleX(0);
|
||||
transform-origin: left center;
|
||||
border-radius: inherit;
|
||||
background: linear-gradient(90deg, #06e3fa, #4fdb5e);
|
||||
transition: transform 160ms ease;
|
||||
}
|
||||
|
||||
/* Toast enter/exit (StudioToast) */
|
||||
@keyframes hf-toast-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-toast-out {
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
}
|
||||
|
||||
.hf-toast-enter {
|
||||
animation: hf-toast-in 160ms ease-out;
|
||||
}
|
||||
|
||||
.hf-toast-exit {
|
||||
animation: hf-toast-out 160ms ease-in forwards;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.hf-toast-enter,
|
||||
.hf-toast-exit {
|
||||
animation: none;
|
||||
}
|
||||
.hf-toast-exit {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Overlay/backdrop entrance — the heaviest visual changes shouldn't pop in */
|
||||
@keyframes hf-backdrop-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.hf-backdrop-in {
|
||||
animation: hf-backdrop-in 150ms ease-out;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.hf-backdrop-in {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Flat inspector group header/body entrance (FlatGroupHeader) */
|
||||
@keyframes hf-flat-group-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.hf-flat-group-enter {
|
||||
animation: hf-flat-group-in 120ms ease-out;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.hf-flat-group-enter {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Preset shelf: the hovered row, and the wave that says it is being heard.
|
||||
*
|
||||
* Hovering a preset auditions it on the running audio, which is invisible — the
|
||||
* panel looks identical whether the audition is playing or the pointer just
|
||||
* happens to be resting there. The bars are that feedback: they run only while a
|
||||
* preset is actually sounding, so they are a readout of the audio rather than a
|
||||
* hover decoration. */
|
||||
.hf-fx-preset-item {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.hf-fx-preset-item {
|
||||
transition:
|
||||
background-color 120ms ease,
|
||||
color 120ms ease;
|
||||
}
|
||||
}
|
||||
|
||||
.hf-fx-preset-item:hover,
|
||||
.hf-fx-preset-item:focus-visible {
|
||||
/* The accent at low alpha rather than a grey: the row is lit by the thing that
|
||||
is playing, and it should read as the same event as the bars. */
|
||||
background-color: rgba(60, 230, 172, 0.12);
|
||||
}
|
||||
|
||||
.hf-fx-preset-wave {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
height: 0.75rem;
|
||||
transform: translateY(-50%);
|
||||
opacity: 0;
|
||||
transition: opacity 120ms ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.hf-fx-preset-item:hover .hf-fx-preset-wave,
|
||||
.hf-fx-preset-item:focus-visible .hf-fx-preset-wave {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.hf-fx-preset-wave span {
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
border-radius: 1px;
|
||||
background: #3ce6ac;
|
||||
transform: scaleY(0.25);
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.hf-fx-preset-wave span {
|
||||
animation: hf-fx-preset-wave 900ms ease-in-out infinite;
|
||||
}
|
||||
/* Staggered so it reads as a waveform travelling rather than four bars
|
||||
pumping in unison, which reads as a loading spinner. */
|
||||
.hf-fx-preset-wave span:nth-child(2) {
|
||||
animation-delay: 150ms;
|
||||
}
|
||||
.hf-fx-preset-wave span:nth-child(3) {
|
||||
animation-delay: 300ms;
|
||||
}
|
||||
.hf-fx-preset-wave span:nth-child(4) {
|
||||
animation-delay: 450ms;
|
||||
}
|
||||
}
|
||||
|
||||
/* Still visible without motion — it is telling the author something is
|
||||
playing, and that fact does not go away because the bars hold still. */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.hf-fx-preset-wave span {
|
||||
transform: scaleY(0.7);
|
||||
}
|
||||
}
|
||||
|
||||
/* Receipt-driven WebMCP Topology Lens. Every animation is one-shot Studio
|
||||
chrome; none of these nodes enter the composition iframe or rendered output. */
|
||||
.hf-topology-contour {
|
||||
border: 1px solid rgba(60, 230, 172, 0.62);
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(6, 227, 250, 0.08),
|
||||
inset 0 0 18px rgba(60, 230, 172, 0.035);
|
||||
}
|
||||
|
||||
.hf-topology-field::before,
|
||||
.hf-topology-contour::before,
|
||||
.hf-topology-target::before {
|
||||
content: attr(data-topology-node);
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 3px;
|
||||
z-index: 2;
|
||||
padding: 1px 3px;
|
||||
border-radius: 2px;
|
||||
background: rgba(5, 15, 12, 0.86);
|
||||
color: rgb(90, 247, 193);
|
||||
font:
|
||||
600 7px/1.3 ui-monospace,
|
||||
SFMono-Regular,
|
||||
Menlo,
|
||||
Monaco,
|
||||
Consolas,
|
||||
monospace;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
.hf-topology-field {
|
||||
z-index: 0;
|
||||
border: 1px solid rgba(60, 230, 172, 0.28);
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(60, 230, 172, 0.025),
|
||||
rgba(60, 230, 172, 0.1) 68%,
|
||||
rgba(6, 227, 250, 0.06)
|
||||
);
|
||||
box-shadow: inset 0 0 28px rgba(60, 230, 172, 0.05);
|
||||
}
|
||||
|
||||
.hf-topology-target {
|
||||
border: 1px solid rgba(60, 230, 172, 0.82);
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(60, 230, 172, 0.14),
|
||||
0 0 18px rgba(6, 227, 250, 0.09);
|
||||
}
|
||||
|
||||
.hf-topology-scan {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent,
|
||||
rgba(60, 230, 172, 0.16) 55%,
|
||||
rgba(230, 255, 247, 0.9)
|
||||
);
|
||||
clip-path: polygon(0 0, 100% 0, 72% 100%, 0 100%);
|
||||
}
|
||||
|
||||
.hf-topology-seal {
|
||||
filter: drop-shadow(0 0 6px rgba(60, 230, 172, 0.36));
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.hf-topology-contour {
|
||||
animation: hf-topology-reveal 176ms cubic-bezier(0.77, 0, 0.175, 1) both;
|
||||
}
|
||||
|
||||
.hf-topology-field[data-topology-phase="acquiring"] {
|
||||
animation: hf-topology-reveal 240ms cubic-bezier(0.77, 0, 0.175, 1) both;
|
||||
}
|
||||
|
||||
.hf-topology-scan {
|
||||
animation: hf-topology-scan 224ms cubic-bezier(0.77, 0, 0.175, 1) both;
|
||||
}
|
||||
|
||||
.hf-topology-target[data-topology-phase="acquiring"] {
|
||||
animation: hf-topology-localize 224ms cubic-bezier(0.23, 1, 0.32, 1) 72ms both;
|
||||
}
|
||||
|
||||
.hf-topology-target[data-topology-phase="localizing"] {
|
||||
animation: hf-topology-localize 176ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
||||
}
|
||||
|
||||
.hf-topology-target[data-topology-phase="sealing"] {
|
||||
animation: hf-topology-localize 144ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
||||
}
|
||||
|
||||
.hf-topology-seal {
|
||||
animation: hf-topology-seal 224ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
||||
}
|
||||
|
||||
.hf-topology-seal path:first-of-type {
|
||||
animation: hf-topology-seal-left 224ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
||||
}
|
||||
|
||||
.hf-topology-seal path:nth-of-type(2) {
|
||||
animation: hf-topology-seal-right 224ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-topology-reveal {
|
||||
from {
|
||||
opacity: 0;
|
||||
clip-path: inset(0 100% 0 0);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
clip-path: inset(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-topology-scan {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
}
|
||||
16% {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translate3d(400%, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-topology-localize {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scaleX(0.76);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scaleX(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-topology-seal {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.88);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-topology-seal-left {
|
||||
from {
|
||||
transform: translate3d(-9px, 0, 0);
|
||||
}
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-topology-seal-right {
|
||||
from {
|
||||
transform: translate3d(9px, 0, 0);
|
||||
}
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.hf-topology-contour,
|
||||
.hf-topology-field,
|
||||
.hf-topology-target,
|
||||
.hf-topology-seal,
|
||||
.hf-topology-seal path {
|
||||
animation: none;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-fx-preset-wave {
|
||||
0%,
|
||||
100% {
|
||||
transform: scaleY(0.25);
|
||||
}
|
||||
50% {
|
||||
transform: scaleY(1);
|
||||
}
|
||||
}
|
||||
@@ -57,8 +57,8 @@
|
||||
"packages/studio/src/player/components/ShortcutsPanel.tsx": 7,
|
||||
"packages/studio/src/player/components/SpeedMenu.tsx": 2,
|
||||
"packages/studio/src/player/components/trackHeaderLabelRows.tsx": 6,
|
||||
"packages/studio/src/styles/components.css": 48,
|
||||
"packages/studio/src/telemetry/client.ts": 1,
|
||||
"packages/studio/src/styles/studio.css": 48,
|
||||
"packages/studio/src/webmcp/webmcpTestUtils.ts": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@import "tailwindcss" source(none);
|
||||
@import "./palette-reset.css";
|
||||
@import "./theme.css";
|
||||
@import "./components.css";
|
||||
|
||||
/* Explicit sources: Studio's own TypeScript and its shell HTML. Automatic
|
||||
* detection would walk up to the repo root and scan `data/projects`, gitignored user content. */
|
||||
@@ -33,156 +34,6 @@ body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hf-color-grading-number::-webkit-outer-spin-button,
|
||||
.hf-color-grading-number::-webkit-inner-spin-button {
|
||||
margin: 0;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.hf-color-grading-number {
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
}
|
||||
|
||||
.hf-color-grading-range {
|
||||
height: 1.5rem;
|
||||
cursor: default;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hf-color-grading-range:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.hf-color-grading-range::-webkit-slider-runnable-track {
|
||||
height: 1.25rem;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hf-color-grading-range::-webkit-slider-thumb {
|
||||
width: 0.625rem;
|
||||
height: 1rem;
|
||||
margin-top: 0.125rem;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
background: #ffffff;
|
||||
box-shadow:
|
||||
0 0 0 2px #0c0c0e,
|
||||
0 1px 4px rgba(0, 0, 0, 0.55);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.hf-color-grading-range::-moz-range-track {
|
||||
height: 1.25rem;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hf-color-grading-range::-moz-range-thumb {
|
||||
width: 0.625rem;
|
||||
height: 1rem;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
background: #ffffff;
|
||||
box-shadow:
|
||||
0 0 0 2px #0c0c0e,
|
||||
0 1px 4px rgba(0, 0, 0, 0.55);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.hf-color-grading-range:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.hf-color-grading-range:focus-visible::-webkit-slider-thumb {
|
||||
box-shadow:
|
||||
0 0 0 2px #0c0c0e,
|
||||
0 0 0 4px rgba(60, 230, 172, 0.22),
|
||||
0 1px 4px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
.hf-color-grading-range:focus-visible::-moz-range-thumb {
|
||||
box-shadow:
|
||||
0 0 0 2px #0c0c0e,
|
||||
0 0 0 4px rgba(60, 230, 172, 0.22),
|
||||
0 1px 4px rgba(0, 0, 0, 0.55);
|
||||
}
|
||||
|
||||
.hf-preview-volume-range {
|
||||
height: 1.5rem;
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range:disabled {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range::-webkit-slider-runnable-track {
|
||||
height: 2px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range::-webkit-slider-thumb {
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
margin-top: -3px;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
appearance: none;
|
||||
background: #ffffff;
|
||||
box-shadow:
|
||||
0 0 0 2px #0a0a0a,
|
||||
0 1px 3px rgba(0, 0, 0, 0.5);
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range::-webkit-slider-thumb:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range::-moz-range-track,
|
||||
.hf-preview-volume-range::-moz-range-progress {
|
||||
height: 2px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range::-moz-range-thumb {
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
border: 0;
|
||||
border-radius: 999px;
|
||||
background: #ffffff;
|
||||
box-shadow:
|
||||
0 0 0 2px #0a0a0a,
|
||||
0 1px 3px rgba(0, 0, 0, 0.5);
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range::-moz-range-thumb:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.hf-preview-volume-range:focus-visible::-webkit-slider-thumb,
|
||||
.hf-preview-volume-range:focus-visible::-moz-range-thumb {
|
||||
box-shadow:
|
||||
0 0 0 2px #0a0a0a,
|
||||
0 0 0 4px rgba(60, 230, 172, 0.4),
|
||||
0 1px 3px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
#root {
|
||||
width: 100vw;
|
||||
/*
|
||||
@@ -198,694 +49,3 @@ body {
|
||||
height: 100vh;
|
||||
height: 100dvh;
|
||||
}
|
||||
|
||||
.timeline-clip {
|
||||
background-color: var(--clip-bg);
|
||||
border: 1px solid var(--clip-border);
|
||||
border-radius: var(--timeline-clip-radius);
|
||||
box-shadow:
|
||||
inset 0 1px 0 var(--timeline-clip-highlight),
|
||||
var(--timeline-clip-shadow);
|
||||
}
|
||||
|
||||
.timeline-transition {
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
pointer-events: none;
|
||||
z-index: 30;
|
||||
}
|
||||
|
||||
.timeline-transition__zone {
|
||||
position: absolute;
|
||||
left: calc(var(--timeline-transition-zone-width) / -2);
|
||||
top: -21px;
|
||||
width: var(--timeline-transition-zone-width);
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background: var(--timeline-transition-zone);
|
||||
filter: blur(2.5px);
|
||||
opacity: 0.95;
|
||||
}
|
||||
|
||||
.timeline-transition__image {
|
||||
position: absolute;
|
||||
inset: -4px;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.timeline-transition__image--out {
|
||||
mask-image: linear-gradient(90deg, black 0%, transparent 100%);
|
||||
}
|
||||
|
||||
.timeline-transition__image--in {
|
||||
mask-image: linear-gradient(90deg, transparent 0%, black 100%);
|
||||
}
|
||||
|
||||
.timeline-transition__badge {
|
||||
position: absolute;
|
||||
left: -14px;
|
||||
top: -14px;
|
||||
display: grid;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
place-items: center;
|
||||
border: 1px solid color-mix(in srgb, var(--timeline-transition-badge-ink) 22%, transparent);
|
||||
border-radius: 999px;
|
||||
background: var(--timeline-transition-badge);
|
||||
box-shadow: 0 2px 5px var(--timeline-playhead-shadow);
|
||||
}
|
||||
|
||||
.timeline-transition__badge svg {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
}
|
||||
.timeline-transition__frame,
|
||||
.timeline-transition__frame--out,
|
||||
.timeline-transition__frame--in {
|
||||
fill: none;
|
||||
stroke: var(--timeline-transition-badge-ink);
|
||||
stroke-width: 1.5;
|
||||
}
|
||||
.timeline-transition__intersection {
|
||||
fill: var(--timeline-transition-badge-ink);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.timeline-clip::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
background: var(--clip-bg-active);
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.timeline-clip[data-active] {
|
||||
border-color: var(--clip-border-active);
|
||||
}
|
||||
|
||||
.timeline-clip[data-active]::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Audio clips read as a distinct kind — a persistent violet tint vs the teal-
|
||||
accented visual clips — so the audio zone at the bottom is visually separate
|
||||
at a glance (the timeline's kinds: visual on top, audio below). */
|
||||
.timeline-clip.is-audio {
|
||||
background-color: var(--timeline-clip-audio-bg);
|
||||
border-color: var(--timeline-clip-audio-border);
|
||||
border-radius: var(--timeline-clip-audio-radius);
|
||||
}
|
||||
|
||||
.timeline-clip.is-audio.is-hovered {
|
||||
background-color: var(--timeline-clip-audio-bg-hover);
|
||||
}
|
||||
|
||||
.timeline-clip.is-audio.is-dragging {
|
||||
box-shadow:
|
||||
inset 0 0 0 999px var(--timeline-clip-audio-bg-dragging),
|
||||
0 8px 24px var(--timeline-clip-shadow-dragging);
|
||||
}
|
||||
|
||||
/* Mute greys the pill in place. Hot path: no transition. */
|
||||
.timeline-clip.is-audio[data-clip-hidden="true"],
|
||||
.timeline-clip.is-audio[data-audio-muted="true"] {
|
||||
background-color: var(--timeline-clip-audio-muted-bg);
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.timeline-audio-link {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
top: -9px;
|
||||
left: 50%;
|
||||
width: 1px;
|
||||
height: 10px;
|
||||
background: var(--timeline-audio-link);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.timeline-clip.is-hovered {
|
||||
background-color: var(--clip-bg-hover);
|
||||
}
|
||||
|
||||
.timeline-clip[data-active].is-hovered {
|
||||
border-color: var(--clip-border-hover);
|
||||
}
|
||||
|
||||
.timeline-clip.is-selected {
|
||||
outline: 1.5px solid var(--timeline-clip-selection);
|
||||
outline-offset: -1.5px;
|
||||
}
|
||||
|
||||
.timeline-clip.is-selected::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 4;
|
||||
border-radius: inherit;
|
||||
box-shadow: inset 0 0 0 1px var(--timeline-clip-selection-highlight);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.timeline-clip[data-active].is-selected {
|
||||
outline: 1.5px solid var(--timeline-clip-selection);
|
||||
outline-offset: -1.5px;
|
||||
}
|
||||
|
||||
.timeline-clip.is-dragging {
|
||||
/* Veil is a shadow, not background-color, so drop does not fade the hover fill. */
|
||||
box-shadow:
|
||||
inset 0 0 0 999px var(--clip-bg-dragging),
|
||||
0 8px 24px var(--timeline-clip-shadow-dragging);
|
||||
}
|
||||
|
||||
.timeline-clip__label {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 6px;
|
||||
z-index: 6;
|
||||
width: fit-content;
|
||||
max-width: calc(100% - 22px);
|
||||
overflow: hidden;
|
||||
padding: 1px 5px;
|
||||
border-radius: 4px;
|
||||
background: var(--timeline-clip-chip-bg);
|
||||
color: var(--timeline-clip-chip-text);
|
||||
font-size: 10px;
|
||||
font-weight: 500;
|
||||
line-height: 16px;
|
||||
pointer-events: none;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.timeline-clip.is-audio .timeline-clip__label {
|
||||
top: 11px;
|
||||
left: 9px;
|
||||
background: var(--timeline-clip-chip-audio-bg);
|
||||
}
|
||||
|
||||
.timeline-clip__timecode {
|
||||
position: absolute;
|
||||
bottom: 6px;
|
||||
left: 12px;
|
||||
overflow: hidden;
|
||||
color: var(--timeline-tick-text);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 9px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
line-height: 1;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.timeline-clip {
|
||||
transition: background-color 120ms ease-out;
|
||||
}
|
||||
|
||||
.timeline-clip__handle-bar {
|
||||
transition: opacity 120ms ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
/* CodeMirror overrides */
|
||||
.cm-editor {
|
||||
height: 100%;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.cm-editor .cm-scroller {
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.cm-editor.cm-focused {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* HyperFrames brand loader. Shared by preview overlays that need a calm,
|
||||
* branded loading state instead of a generic spinner.
|
||||
*/
|
||||
.hf-loader {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.75rem;
|
||||
width: min(34rem, 100%);
|
||||
padding: 1.5rem;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
.hf-frame {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 12rem;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
background: rgba(0, 0, 0, 0.52);
|
||||
}
|
||||
|
||||
.hf-loader-mark-frame {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
overflow: visible;
|
||||
transform-origin: 50% 50%;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
.hf-loader-mark {
|
||||
display: block;
|
||||
overflow: visible;
|
||||
filter: drop-shadow(0 0 7px rgba(79, 219, 94, 0.2));
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
.hf-loader-title {
|
||||
font-family: var(--font-sans);
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0;
|
||||
color: var(--hf-heading, #f4f4f5);
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.hf-loader-detail {
|
||||
max-width: 32rem;
|
||||
min-height: 2.5rem;
|
||||
overflow: hidden;
|
||||
color: var(--hf-text-secondary, rgba(244, 244, 245, 0.68));
|
||||
font-family: var(--font-sans);
|
||||
font-size: 0.82rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.hf-loader-mono {
|
||||
width: min(36rem, 100%);
|
||||
min-height: 1.5rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: var(--hf-text-tertiary, rgba(244, 244, 245, 0.46));
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.75rem;
|
||||
letter-spacing: 0;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.hf-loader-progress {
|
||||
width: min(18rem, 72vw);
|
||||
height: 0.375rem;
|
||||
overflow: hidden;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
@keyframes hf-thumb-fade {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.hf-loader-progress__fill {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform: scaleX(0);
|
||||
transform-origin: left center;
|
||||
border-radius: inherit;
|
||||
background: linear-gradient(90deg, #06e3fa, #4fdb5e);
|
||||
transition: transform 160ms ease;
|
||||
}
|
||||
|
||||
/* Toast enter/exit (StudioToast) */
|
||||
@keyframes hf-toast-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-toast-out {
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translateY(8px);
|
||||
}
|
||||
}
|
||||
|
||||
.hf-toast-enter {
|
||||
animation: hf-toast-in 160ms ease-out;
|
||||
}
|
||||
|
||||
.hf-toast-exit {
|
||||
animation: hf-toast-out 160ms ease-in forwards;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.hf-toast-enter,
|
||||
.hf-toast-exit {
|
||||
animation: none;
|
||||
}
|
||||
.hf-toast-exit {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Overlay/backdrop entrance — the heaviest visual changes shouldn't pop in */
|
||||
@keyframes hf-backdrop-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.hf-backdrop-in {
|
||||
animation: hf-backdrop-in 150ms ease-out;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.hf-backdrop-in {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Flat inspector group header/body entrance (FlatGroupHeader) */
|
||||
@keyframes hf-flat-group-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.hf-flat-group-enter {
|
||||
animation: hf-flat-group-in 120ms ease-out;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.hf-flat-group-enter {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Preset shelf: the hovered row, and the wave that says it is being heard.
|
||||
*
|
||||
* Hovering a preset auditions it on the running audio, which is invisible — the
|
||||
* panel looks identical whether the audition is playing or the pointer just
|
||||
* happens to be resting there. The bars are that feedback: they run only while a
|
||||
* preset is actually sounding, so they are a readout of the audio rather than a
|
||||
* hover decoration. */
|
||||
.hf-fx-preset-item {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.hf-fx-preset-item {
|
||||
transition:
|
||||
background-color 120ms ease,
|
||||
color 120ms ease;
|
||||
}
|
||||
}
|
||||
|
||||
.hf-fx-preset-item:hover,
|
||||
.hf-fx-preset-item:focus-visible {
|
||||
/* The accent at low alpha rather than a grey: the row is lit by the thing that
|
||||
is playing, and it should read as the same event as the bars. */
|
||||
background-color: rgba(60, 230, 172, 0.12);
|
||||
}
|
||||
|
||||
.hf-fx-preset-wave {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
height: 0.75rem;
|
||||
transform: translateY(-50%);
|
||||
opacity: 0;
|
||||
transition: opacity 120ms ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.hf-fx-preset-item:hover .hf-fx-preset-wave,
|
||||
.hf-fx-preset-item:focus-visible .hf-fx-preset-wave {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.hf-fx-preset-wave span {
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
border-radius: 1px;
|
||||
background: #3ce6ac;
|
||||
transform: scaleY(0.25);
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.hf-fx-preset-wave span {
|
||||
animation: hf-fx-preset-wave 900ms ease-in-out infinite;
|
||||
}
|
||||
/* Staggered so it reads as a waveform travelling rather than four bars
|
||||
pumping in unison, which reads as a loading spinner. */
|
||||
.hf-fx-preset-wave span:nth-child(2) {
|
||||
animation-delay: 150ms;
|
||||
}
|
||||
.hf-fx-preset-wave span:nth-child(3) {
|
||||
animation-delay: 300ms;
|
||||
}
|
||||
.hf-fx-preset-wave span:nth-child(4) {
|
||||
animation-delay: 450ms;
|
||||
}
|
||||
}
|
||||
|
||||
/* Still visible without motion — it is telling the author something is
|
||||
playing, and that fact does not go away because the bars hold still. */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.hf-fx-preset-wave span {
|
||||
transform: scaleY(0.7);
|
||||
}
|
||||
}
|
||||
|
||||
/* Receipt-driven WebMCP Topology Lens. Every animation is one-shot Studio
|
||||
chrome; none of these nodes enter the composition iframe or rendered output. */
|
||||
.hf-topology-contour {
|
||||
border: 1px solid rgba(60, 230, 172, 0.62);
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(6, 227, 250, 0.08),
|
||||
inset 0 0 18px rgba(60, 230, 172, 0.035);
|
||||
}
|
||||
|
||||
.hf-topology-field::before,
|
||||
.hf-topology-contour::before,
|
||||
.hf-topology-target::before {
|
||||
content: attr(data-topology-node);
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 3px;
|
||||
z-index: 2;
|
||||
padding: 1px 3px;
|
||||
border-radius: 2px;
|
||||
background: rgba(5, 15, 12, 0.86);
|
||||
color: rgb(90, 247, 193);
|
||||
font:
|
||||
600 7px/1.3 ui-monospace,
|
||||
SFMono-Regular,
|
||||
Menlo,
|
||||
Monaco,
|
||||
Consolas,
|
||||
monospace;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: lowercase;
|
||||
}
|
||||
|
||||
.hf-topology-field {
|
||||
z-index: 0;
|
||||
border: 1px solid rgba(60, 230, 172, 0.28);
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(60, 230, 172, 0.025),
|
||||
rgba(60, 230, 172, 0.1) 68%,
|
||||
rgba(6, 227, 250, 0.06)
|
||||
);
|
||||
box-shadow: inset 0 0 28px rgba(60, 230, 172, 0.05);
|
||||
}
|
||||
|
||||
.hf-topology-target {
|
||||
border: 1px solid rgba(60, 230, 172, 0.82);
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(60, 230, 172, 0.14),
|
||||
0 0 18px rgba(6, 227, 250, 0.09);
|
||||
}
|
||||
|
||||
.hf-topology-scan {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
transparent,
|
||||
rgba(60, 230, 172, 0.16) 55%,
|
||||
rgba(230, 255, 247, 0.9)
|
||||
);
|
||||
clip-path: polygon(0 0, 100% 0, 72% 100%, 0 100%);
|
||||
}
|
||||
|
||||
.hf-topology-seal {
|
||||
filter: drop-shadow(0 0 6px rgba(60, 230, 172, 0.36));
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.hf-topology-contour {
|
||||
animation: hf-topology-reveal 176ms cubic-bezier(0.77, 0, 0.175, 1) both;
|
||||
}
|
||||
|
||||
.hf-topology-field[data-topology-phase="acquiring"] {
|
||||
animation: hf-topology-reveal 240ms cubic-bezier(0.77, 0, 0.175, 1) both;
|
||||
}
|
||||
|
||||
.hf-topology-scan {
|
||||
animation: hf-topology-scan 224ms cubic-bezier(0.77, 0, 0.175, 1) both;
|
||||
}
|
||||
|
||||
.hf-topology-target[data-topology-phase="acquiring"] {
|
||||
animation: hf-topology-localize 224ms cubic-bezier(0.23, 1, 0.32, 1) 72ms both;
|
||||
}
|
||||
|
||||
.hf-topology-target[data-topology-phase="localizing"] {
|
||||
animation: hf-topology-localize 176ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
||||
}
|
||||
|
||||
.hf-topology-target[data-topology-phase="sealing"] {
|
||||
animation: hf-topology-localize 144ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
||||
}
|
||||
|
||||
.hf-topology-seal {
|
||||
animation: hf-topology-seal 224ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
||||
}
|
||||
|
||||
.hf-topology-seal path:first-of-type {
|
||||
animation: hf-topology-seal-left 224ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
||||
}
|
||||
|
||||
.hf-topology-seal path:nth-of-type(2) {
|
||||
animation: hf-topology-seal-right 224ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-topology-reveal {
|
||||
from {
|
||||
opacity: 0;
|
||||
clip-path: inset(0 100% 0 0);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
clip-path: inset(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-topology-scan {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
}
|
||||
16% {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translate3d(400%, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-topology-localize {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scaleX(0.76);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scaleX(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-topology-seal {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.88);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-topology-seal-left {
|
||||
from {
|
||||
transform: translate3d(-9px, 0, 0);
|
||||
}
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-topology-seal-right {
|
||||
from {
|
||||
transform: translate3d(9px, 0, 0);
|
||||
}
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.hf-topology-contour,
|
||||
.hf-topology-field,
|
||||
.hf-topology-target,
|
||||
.hf-topology-seal,
|
||||
.hf-topology-seal path {
|
||||
animation: none;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hf-fx-preset-wave {
|
||||
0%,
|
||||
100% {
|
||||
transform: scaleY(0.25);
|
||||
}
|
||||
50% {
|
||||
transform: scaleY(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ describe("token gate", () => {
|
||||
});
|
||||
|
||||
it("accepts variants, static utilities and Studio's own CSS classes", async () => {
|
||||
// `timeline-clip` is a plain rule in `studio.css`, not a utility.
|
||||
// `timeline-clip` is a plain rule in `components.css`, not a utility.
|
||||
const source = `<div className="hover:bg-surface/50 text-center border-dashed timeline-clip" />`;
|
||||
|
||||
expect(await unresolved(new Map([["a.tsx", source]]))).toEqual([]);
|
||||
|
||||
+33
-33
@@ -47,8 +47,8 @@
|
||||
"role": "text",
|
||||
"minimum": 4.5,
|
||||
"sources": [
|
||||
"packages/studio/src/styles/studio.css:203",
|
||||
"packages/studio/src/styles/studio.css:286"
|
||||
"packages/studio/src/styles/components.css:155",
|
||||
"packages/studio/src/styles/components.css:238"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -62,8 +62,8 @@
|
||||
"role": "text",
|
||||
"minimum": 4.5,
|
||||
"sources": [
|
||||
"packages/studio/src/styles/studio.css:230",
|
||||
"packages/studio/src/styles/studio.css:300"
|
||||
"packages/studio/src/styles/components.css:182",
|
||||
"packages/studio/src/styles/components.css:252"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -73,8 +73,8 @@
|
||||
"role": "text",
|
||||
"minimum": 4.5,
|
||||
"sources": [
|
||||
"packages/studio/src/styles/studio.css:203",
|
||||
"packages/studio/src/styles/studio.css:305"
|
||||
"packages/studio/src/styles/components.css:155",
|
||||
"packages/studio/src/styles/components.css:257"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -84,9 +84,9 @@
|
||||
"role": "text",
|
||||
"minimum": 4.5,
|
||||
"sources": [
|
||||
"packages/studio/src/styles/studio.css:203",
|
||||
"packages/studio/src/styles/studio.css:213",
|
||||
"packages/studio/src/styles/studio.css:305"
|
||||
"packages/studio/src/styles/components.css:155",
|
||||
"packages/studio/src/styles/components.css:165",
|
||||
"packages/studio/src/styles/components.css:257"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -96,8 +96,8 @@
|
||||
"role": "graphic",
|
||||
"minimum": 3,
|
||||
"sources": [
|
||||
"packages/studio/src/styles/studio.css:203",
|
||||
"packages/studio/src/styles/studio.css:204",
|
||||
"packages/studio/src/styles/components.css:155",
|
||||
"packages/studio/src/styles/components.css:156",
|
||||
"packages/studio/src/player/components/TimelineLanes.tsx:270"
|
||||
],
|
||||
"paintBacking": ["--timeline-row-bg", "--timeline-clip-bg"]
|
||||
@@ -109,8 +109,8 @@
|
||||
"role": "graphic",
|
||||
"minimum": 3,
|
||||
"sources": [
|
||||
"packages/studio/src/styles/studio.css:203",
|
||||
"packages/studio/src/styles/studio.css:219",
|
||||
"packages/studio/src/styles/components.css:155",
|
||||
"packages/studio/src/styles/components.css:171",
|
||||
"packages/studio/src/player/components/TimelineLanes.tsx:270"
|
||||
],
|
||||
"paintBacking": ["--timeline-row-bg", "--timeline-clip-bg"]
|
||||
@@ -122,7 +122,7 @@
|
||||
"role": "graphic",
|
||||
"minimum": 3,
|
||||
"sources": [
|
||||
"packages/studio/src/styles/studio.css:251",
|
||||
"packages/studio/src/styles/components.css:203",
|
||||
"packages/studio/src/player/components/TimelineLanes.tsx:270"
|
||||
]
|
||||
},
|
||||
@@ -136,7 +136,7 @@
|
||||
"packages/studio/src/player/components/TimelineClip.tsx:160",
|
||||
"packages/studio/src/player/components/TimelineClip.tsx:161",
|
||||
"packages/studio/src/player/components/timelineTheme.ts:86",
|
||||
"packages/studio/src/styles/studio.css:203"
|
||||
"packages/studio/src/styles/components.css:155"
|
||||
],
|
||||
"opacity": 0.492
|
||||
},
|
||||
@@ -150,9 +150,9 @@
|
||||
"packages/studio/src/player/components/TimelineClip.tsx:160",
|
||||
"packages/studio/src/player/components/TimelineClip.tsx:161",
|
||||
"packages/studio/src/player/components/timelineTheme.ts:86",
|
||||
"packages/studio/src/styles/studio.css:203",
|
||||
"packages/studio/src/styles/studio.css:213",
|
||||
"packages/studio/src/styles/studio.css:223"
|
||||
"packages/studio/src/styles/components.css:155",
|
||||
"packages/studio/src/styles/components.css:165",
|
||||
"packages/studio/src/styles/components.css:175"
|
||||
],
|
||||
"opacity": 0.492
|
||||
},
|
||||
@@ -166,7 +166,7 @@
|
||||
"packages/studio/src/player/components/TimelineClip.tsx:160",
|
||||
"packages/studio/src/player/components/TimelineClip.tsx:161",
|
||||
"packages/studio/src/player/components/timelineTheme.ts:87",
|
||||
"packages/studio/src/styles/studio.css:243"
|
||||
"packages/studio/src/styles/components.css:195"
|
||||
],
|
||||
"opacity": 0.456
|
||||
},
|
||||
@@ -184,9 +184,9 @@
|
||||
"packages/studio/src/player/components/TimelineClip.tsx:160",
|
||||
"packages/studio/src/player/components/TimelineClip.tsx:161",
|
||||
"packages/studio/src/player/components/timelineTheme.ts:87",
|
||||
"packages/studio/src/styles/studio.css:243",
|
||||
"packages/studio/src/styles/studio.css:213",
|
||||
"packages/studio/src/styles/studio.css:223"
|
||||
"packages/studio/src/styles/components.css:195",
|
||||
"packages/studio/src/styles/components.css:165",
|
||||
"packages/studio/src/styles/components.css:175"
|
||||
],
|
||||
"opacity": 0.456
|
||||
},
|
||||
@@ -200,7 +200,7 @@
|
||||
"packages/studio/src/player/components/TimelineClip.tsx:160",
|
||||
"packages/studio/src/player/components/TimelineClip.tsx:161",
|
||||
"packages/studio/src/player/components/timelineTheme.ts:85",
|
||||
"packages/studio/src/styles/studio.css:261"
|
||||
"packages/studio/src/styles/components.css:213"
|
||||
],
|
||||
"opacity": 0.57
|
||||
},
|
||||
@@ -218,9 +218,9 @@
|
||||
"packages/studio/src/player/components/TimelineClip.tsx:160",
|
||||
"packages/studio/src/player/components/TimelineClip.tsx:161",
|
||||
"packages/studio/src/player/components/timelineTheme.ts:85",
|
||||
"packages/studio/src/styles/studio.css:261",
|
||||
"packages/studio/src/styles/studio.css:213",
|
||||
"packages/studio/src/styles/studio.css:223"
|
||||
"packages/studio/src/styles/components.css:213",
|
||||
"packages/studio/src/styles/components.css:165",
|
||||
"packages/studio/src/styles/components.css:175"
|
||||
],
|
||||
"opacity": 0.57
|
||||
},
|
||||
@@ -231,8 +231,8 @@
|
||||
"role": "graphic",
|
||||
"minimum": 3,
|
||||
"sources": [
|
||||
"packages/studio/src/styles/studio.css:230",
|
||||
"packages/studio/src/styles/studio.css:213",
|
||||
"packages/studio/src/styles/components.css:182",
|
||||
"packages/studio/src/styles/components.css:165",
|
||||
"packages/studio/src/player/components/AudioWaveform.tsx:139",
|
||||
"packages/studio/src/player/components/AudioWaveform.tsx:145"
|
||||
],
|
||||
@@ -250,8 +250,8 @@
|
||||
"role": "graphic",
|
||||
"minimum": 3,
|
||||
"sources": [
|
||||
"packages/studio/src/styles/studio.css:230",
|
||||
"packages/studio/src/styles/studio.css:213",
|
||||
"packages/studio/src/styles/components.css:182",
|
||||
"packages/studio/src/styles/components.css:165",
|
||||
"packages/studio/src/player/components/AudioWaveform.tsx:139",
|
||||
"packages/studio/src/player/components/AudioWaveform.tsx:145"
|
||||
],
|
||||
@@ -265,7 +265,7 @@
|
||||
"role": "graphic",
|
||||
"minimum": 3,
|
||||
"sources": [
|
||||
"packages/studio/src/styles/studio.css:246",
|
||||
"packages/studio/src/styles/components.css:198",
|
||||
"packages/studio/src/player/components/AudioWaveform.tsx:144"
|
||||
],
|
||||
"opacity": 0.64,
|
||||
@@ -352,7 +352,7 @@
|
||||
"minimum": 4.5,
|
||||
"sources": [
|
||||
"packages/studio/src/styles/theme.css",
|
||||
"packages/studio/src/styles/studio.css"
|
||||
"packages/studio/src/styles/components.css"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -363,7 +363,7 @@
|
||||
"minimum": 3,
|
||||
"sources": [
|
||||
"packages/studio/src/styles/theme.css",
|
||||
"packages/studio/src/styles/studio.css"
|
||||
"packages/studio/src/styles/components.css"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user