Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Web Video Optimizer

<picture>
<source media="(prefers-color-scheme: light)" srcset="docs/assets/brand/wordmark-light.svg">
<img src="docs/assets/brand/wordmark-dark.svg" alt="Web Video Optimizer" width="420">
<source media="(prefers-color-scheme: light)" srcset="apps/web/public/brand/WVO-logo-transparent.png">
<img src="apps/web/public/brand/WVO-logo-white-transparent.png" alt="Web Video Optimizer" width="360">
</picture>

[![CI](https://github.com/Artsen/web-video-optimizer/actions/workflows/ci.yml/badge.svg)](https://github.com/Artsen/web-video-optimizer/actions/workflows/ci.yml)
Expand Down
2 changes: 1 addition & 1 deletion apps/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" type="image/png" href="/brand/WVO-favicon.png" />
<title>Local Web Video Optimizer</title>
</head>
<body>
Expand Down
Binary file added apps/web/public/brand/WVO-favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/web/public/brand/WVO-logo-transparent.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 0 additions & 13 deletions apps/web/public/favicon.svg

This file was deleted.

2 changes: 1 addition & 1 deletion apps/web/src/app/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ describe("App behavior", () => {
renderApp(api);

expect(await screen.findByRole("heading", { name: "Ready for a source video" })).toBeInTheDocument();
const warning = screen.getByRole("status");
const warning = await screen.findByRole("status");
expect(warning).toHaveTextContent("Storage status");
expect(warning).not.toHaveTextContent("D:\\private");

Expand Down
5 changes: 0 additions & 5 deletions apps/web/src/assets/brand/mark-monochrome.svg

This file was deleted.

14 changes: 0 additions & 14 deletions apps/web/src/assets/brand/mark.svg

This file was deleted.

16 changes: 0 additions & 16 deletions apps/web/src/assets/brand/wordmark-dark.svg

This file was deleted.

16 changes: 0 additions & 16 deletions apps/web/src/assets/brand/wordmark-light.svg

This file was deleted.

20 changes: 14 additions & 6 deletions apps/web/src/components/ui/AppMark.test.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
import { render, screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import { AppMark } from "./AppMark";
import { AppMark, WVO_LOGO_TRANSPARENT_PATH, WVO_LOGO_WHITE_TRANSPARENT_PATH } from "./AppMark";

describe("AppMark", () => {
it("renders the compression-frame brand mark as decorative SVG geometry", () => {
it("renders the approved WVO monogram variants as decorative images", () => {
render(
<div>
<AppMark />
<AppMark size="small" />
<span>Web Video Optimizer</span>
</div>
);

const mark = document.querySelector(".app-mark");
expect(mark).toHaveAttribute("aria-hidden", "true");
expect(mark).toHaveClass("small");
expect(screen.getByText("Web Video Optimizer")).toBeVisible();
expect(document.querySelector(".app-mark-frame")).toBeInTheDocument();
expect(document.querySelectorAll(".app-mark-band")).toHaveLength(3);
expect(document.querySelector(".app-mark-play")).toBeInTheDocument();

const images = document.querySelectorAll<HTMLImageElement>(".app-mark-image");
expect(images).toHaveLength(2);
expect(images[0]).toHaveAttribute("src", WVO_LOGO_TRANSPARENT_PATH);
expect(images[1]).toHaveAttribute("src", WVO_LOGO_WHITE_TRANSPARENT_PATH);
expect(images[0]).toHaveAttribute("alt", "");
expect(images[1]).toHaveAttribute("alt", "");
expect(images[0]).toHaveAttribute("draggable", "false");
expect(images[1]).toHaveAttribute("draggable", "false");
expect(mark?.querySelector("svg")).not.toBeInTheDocument();
});
});
29 changes: 11 additions & 18 deletions apps/web/src/components/ui/AppMark.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
export const WVO_LOGO_TRANSPARENT_PATH = "/brand/WVO-logo-transparent.png";
export const WVO_LOGO_WHITE_TRANSPARENT_PATH = "/brand/WVO-logo-white-transparent.png";

export function AppMark({ size = "default" }: { size?: "default" | "small" }) {
return (
<span className={`app-mark ${size === "small" ? "small" : ""}`} aria-hidden="true">
<svg className="app-mark-icon" viewBox="0 0 64 64" focusable="false" aria-hidden="true">
<defs>
<linearGradient id="app-mark-spectral" x1="10" x2="54" y1="14" y2="50" gradientUnits="userSpaceOnUse">
<stop offset="0" stopColor="#5f6fe5" />
<stop offset="0.54" stopColor="#765bc8" />
<stop offset="1" stopColor="#e66a3a" />
</linearGradient>
</defs>
<path
className="app-mark-frame"
d="M10 16.5C10 13.46 12.46 11 15.5 11h33C51.54 11 54 13.46 54 16.5v31C54 50.54 51.54 53 48.5 53h-33C12.46 53 10 50.54 10 47.5v-31Z"
/>
<path className="app-mark-band band-wide" d="M18 22h20v6H18z" />
<path className="app-mark-band band-mid" d="M18 32h15v6H18z" />
<path className="app-mark-band band-small" d="M18 42h10v5H18z" />
<path className="app-mark-play" d="M39 27.2v19.6l12-9.8-12-9.8Z" />
</svg>
<span className={`app-mark ${size === "small" ? "small" : "default"}`} aria-hidden="true">
<img className="app-mark-image app-mark-image-dark" src={WVO_LOGO_TRANSPARENT_PATH} alt="" draggable={false} />
<img
className="app-mark-image app-mark-image-white"
src={WVO_LOGO_WHITE_TRANSPARENT_PATH}
alt=""
draggable={false}
/>
</span>
);
}
1 change: 1 addition & 0 deletions apps/web/src/components/ui/design-primitives.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ describe("design primitives", () => {
const { container } = render(<AppMark />);

expect(container.querySelector(".app-mark")).toHaveAttribute("aria-hidden", "true");
expect(container.querySelector(".app-mark")).toHaveClass("default");
});

it("renders status badges with semantic text and tone classes", () => {
Expand Down
48 changes: 17 additions & 31 deletions apps/web/src/styles/components.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
.app-mark,
.brand-mark,
.upload-icon,
.preset-icon {
Expand All @@ -12,40 +11,31 @@
}

.app-mark {
width: 40px;
height: 40px;
display: block;
width: 86px;
height: auto;
flex: 0 0 auto;
padding: 3px;
overflow: hidden;
background:
linear-gradient(var(--color-surface-recessed), var(--color-surface-recessed)) padding-box,
var(--gradient-brand-spectral) border-box;
border-color: transparent;
line-height: 0;
}

.app-mark.small {
width: 32px;
height: 32px;
padding: 2px;
width: 58px;
}

.app-mark-icon {
display: block;
.app-mark-image {
display: none;
width: 100%;
height: 100%;
}

.app-mark-frame {
fill: url("#app-mark-spectral");
height: auto;
object-fit: contain;
user-select: none;
}

.app-mark-band {
fill: #ffffff;
fill-opacity: 0.92;
:root:not([data-theme="light"]) .app-mark-image-white {
display: block;
}

.app-mark-play {
fill: var(--color-ember-text);
:root[data-theme="light"] .app-mark-image-dark {
display: block;
}

.upload-icon {
Expand Down Expand Up @@ -1199,8 +1189,7 @@ progress::-moz-progress-bar {
}

.source-topbar .app-mark {
width: 34px;
height: 34px;
width: 76px;
}

.source-topbar h1 {
Expand Down Expand Up @@ -2663,18 +2652,15 @@ progress::-moz-progress-bar {
}

@media (forced-colors: active) {
.app-mark,
.upload-icon {
forced-color-adjust: auto;
color: CanvasText;
background: Canvas;
border-color: ButtonBorder;
}

.app-mark-frame,
.app-mark-band,
.app-mark-play {
fill: currentColor;
.app-mark-image {
forced-color-adjust: auto;
}

.dropzone.dropzone-empty::before,
Expand Down
4 changes: 1 addition & 3 deletions apps/web/src/styles/layout.css
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,7 @@
}

.topbar .app-mark {
width: 34px;
height: 34px;
border-radius: var(--radius-card);
width: 86px;
}

.topbar h1 {
Expand Down
14 changes: 0 additions & 14 deletions docs/assets/brand/mark.svg

This file was deleted.

16 changes: 0 additions & 16 deletions docs/assets/brand/wordmark-dark.svg

This file was deleted.

16 changes: 0 additions & 16 deletions docs/assets/brand/wordmark-light.svg

This file was deleted.

2 changes: 1 addition & 1 deletion docs/assets/screenshots/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ Review captures are full-page unless the Playwright screenshot suite names them

The current curated set balances dark workflow coverage, one light-theme result, Compare theatre, Custom Export density, and mobile bottom chrome. Add an empty-state screenshot only when it materially improves the README.

Current curated set: 6 WebP files, 260,638 bytes total.
Current curated set: 6 WebP files, 333,348 bytes total.
Binary file modified docs/assets/screenshots/compare-wipe-dark.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/custom-export-dark.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/mobile-results-dark.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/prepare-dark.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/results-dark.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/screenshots/results-light.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 7 additions & 9 deletions docs/brand-system.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,21 @@ The intended balance is roughly 80% slate structure, 15% tonal elevation and bor

## Logo

The mark is a compression-frame symbol: an outer video frame, three narrowing source bands, and a terminal output/play shape. It should suggest media reduction and website-ready delivery without resembling a generic clapperboard or AI sparkle.
The approved mark is a fused WVO monogram. The W and V share overlapping geometry, while the O acts as the terminal output form. The chromatic cyan and ember edge separation is part of the artwork and should remain intact.

Canonical app assets live in `apps/web/src/assets/brand/`. Documentation copies live in `docs/assets/brand/` so GitHub can render README imagery.
Canonical app and documentation assets live in `apps/web/public/brand/` so the Vite app, favicon, README, and packaged static paths use the same source files.

Logo variants:

- `mark.svg`: spectral icon mark.
- `mark-monochrome.svg`: one-color app mark.
- `wordmark-dark.svg`: horizontal logo for dark backgrounds.
- `wordmark-light.svg`: horizontal logo for light backgrounds.
- `apps/web/public/favicon.svg`: favicon-compatible mark.
- `WVO-logo-transparent.png`: dark letterform variant for light surfaces.
- `WVO-logo-white-transparent.png`: white letterform variant for dark surfaces.
- `WVO-favicon.png`: favicon derived from the approved monogram for small browser chrome.

When the mark sits next to visible "Web Video Optimizer" text, it should be `aria-hidden` to avoid duplicate announcements. Use text alternatives for standalone documentation imagery.

Clear space should be at least one quarter of the mark width on all sides. Minimum practical sizes are 16px for the favicon mark, 20px for navigation chrome, 32px for prominent UI placement, and 180px wide for the wordmark.
Clear space should be at least one quarter of the visible monogram width on all sides. Minimum practical rendered widths are about 48px for mobile chrome, 54px for sidebar chrome, 72px for workspace headers, and 180px for documentation or marketing placement.

Do not rotate, stretch, recolor outside the approved palette, add glow effects, place on low-contrast imagery, replace the compression bands, or use the spectral gradient as ordinary text fill.
Do not rotate, stretch, recolor, recreate with text, add containers by default, remove or exaggerate the cyan/ember edges, place on busy media, or use the logo's chromatic treatment as ordinary interface decoration. The logo's cyan and ember edges do not redefine the product palette; the interface remains slate, iris, and ember.

## Palette

Expand Down
Loading