chore(openspec): archive completed changes and sync main specs

- archive rename-shared-album-to-galo, add-halo-branding
- sync specs: ui-branding (new capability)
This commit is contained in:
iu
2026-10-11 11:37:23 +03:00
parent 50dff63ece
commit b1b0b4a83e
10 changed files with 61 additions and 0 deletions
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-10-11
@@ -0,0 +1,49 @@
# Design
## Context
See proposal.md - Why. Current state that shapes the approach:
- `frontend/src/app.html:6` already points at `%sveltekit.assets%/favicon.png`, but `frontend/static/` does not exist, so the request 404s.
- The icon system (`ui-iconography`) requires self-contained inline vector icons with no external requests, and icons that inherit the theme color.
- Theme colors live as CSS custom properties on `:root` per theme (`--primary` = blue light/dark, orange neutral), defined in `frontend/src/app.css`.
- Static assets flow through `frontend/static/` -> `frontend/build/` -> `backend/static/` -> `go:embed` -> served by the static handler. No backend change is needed.
## Goals / Non-Goals
**Goals:**
- One recognizable halo mark, legible down to 16px, used consistently as UI emblem and favicon.
- Theme-awareness in both the UI emblem and the browser/touch icon.
- Zero external requests for any brand asset.
**Non-Goals:**
- Changing the wordmark, typography, or theme palette.
- Open Graph / social preview images, PWA manifest icons, or app-store assets.
- Any backend or API change.
## Decisions
### D1. Concept: pure halo (variant A)
A sun disc with a separated outer ring. Alternatives: rays/glow (rejected - detail collapses at 16px) and an aperture hybrid (rejected - two meanings compete at small sizes). Geometry keeps a clear gap between disc and ring so the halo reads as a halo.
### D2. Two-tone color with monochrome fallback
In the UI, the disc uses `--primary` and the ring uses `--primary` at reduced opacity; a single-color `currentColor` fallback keeps the mark usable where the two-tone treatment does not apply. Alternative: strictly monochrome (rejected - loses the "sun inside a halo" reading).
### D3. Inline SVG for UI, static files for favicon
The UI emblem is an inline SVG component so it inherits `currentColor`/theme and satisfies the no-external-requests rule, mirroring the existing icon approach. The favicon cannot use CSS custom properties, so it is a standalone asset that carries its own theme rules.
### D4. Favicon formats
Ship `favicon.svg` with an embedded `prefers-color-scheme` rule (dark and light variants), plus `favicon.png` and `apple-touch-icon.png` fallbacks. `app.html` references the SVG and keeps a PNG fallback. Alternative: `.ico` only (rejected - no theme awareness).
### D5. Placement
Emblem in the `AppShell` header, the public/login layout, and the share-page header, always next to the "Galo" wordmark, where it is decorative (hidden from assistive tech).
### D6. Asset pipeline
Files live in `frontend/static/`; the existing `make frontend` copy step carries them into `backend/static/` for embedding, so the backend serves them unchanged.
## Risks / Trade-offs
- [Mark illegible at 16px] -> Keep geometry minimal (thick-enough ring, clear gap) and verify a 16px render.
- [SVG favicon not supported everywhere] -> Provide the PNG fallback in `app.html`.
- [Favicon cannot use theme CSS variables] -> Embed `prefers-color-scheme` rules directly in the SVG.
- [Asset bloat] -> Keep the SVG hand-written and small; PNGs limited to the needed sizes.
@@ -0,0 +1,27 @@
# Proposal
## Why
The app references a favicon that does not exist (`frontend/src/app.html:6` points at `%sveltekit.assets%/favicon.png`, but there is no `frontend/static/`), so browsers get a 404. At the same time the product name **Galo** (= гало, the ring around the sun) has no visual mark — the brand is only text. This change gives the project a self-hosted halo emblem and a working favicon, consistent with the existing icon system that forbids external requests.
## What Changes
- Introduce a **halo emblem**: a sun disc surrounded by a separated ring (variant A — pure ring + disc, legible at 16px).
- Add an inline, theme-aware SVG emblem component used in the UI (header, login/public layout, share header); the sun disc uses `--primary`, the ring uses `--primary` at reduced opacity with a monochrome `currentColor` fallback.
- Add static brand assets under `frontend/static/`: `favicon.svg` (theme-aware via `prefers-color-scheme`), `favicon.png` fallback, and `apple-touch-icon.png`.
- Update `frontend/src/app.html` to reference `favicon.svg` with the PNG fallback.
- Keep the "Galo" wordmark next to the emblem; the emblem is decorative there.
## Capabilities
### New Capabilities
- `ui-branding`: the halo emblem and favicon identity — a self-hosted, theme-aware visual mark that appears in the UI and as the browser/tab and touch icon.
### Modified Capabilities
<!-- None: the icon system (ui-iconography) is unchanged; the emblem follows its existing no-external-requests rule. -->
## Impact
- **Frontend:** new `frontend/static/` assets (served through the existing `go:embed` pipeline after build), `frontend/src/app.html`, `frontend/src/lib/components/AppShell.svelte`, `frontend/src/routes/(public)/+layout.svelte`, share page header.
- **Backend:** none (static assets are embedded and served by the existing static handler).
- **Behavior:** the missing favicon 404 is replaced by a served, theme-aware icon; no API changes.
@@ -0,0 +1,62 @@
# Spec Delta
## Purpose
Единая визуальная айдентика приложения: гало-эмблема и фавикон, отдаваемые самим приложением, наследующие тему и читаемые в мелком размере.
## ADDED Requirements
### Requirement: Гало-эмблема
Интерфейс SHALL отображать эмблему «гало» — диск солнца, окружённый отделённым от него кольцом — как встроенную векторную графику, наследующую цвет текущей темы.
#### Scenario: Отображение в шапке
- **WHEN** открыт основной интерфейс
- **THEN** в шапке рядом с надписью «Galo» показана гало-эмблема
#### Scenario: Смена темы
- **WHEN** пользователь переключает тему (light/dark/neutral)
- **THEN** цвет диска и кольца эмблемы меняется вместе с темой
#### Scenario: Мелкий размер
- **WHEN** эмблема отрисована в размере порядка 16-24 px
- **THEN** диск и отделённое кольцо остаются различимыми
### Requirement: Фавикон от приложения
Приложение SHALL отдавать фавикон бренда со своего origin, а разметка страницы SHALL ссылаться на существующий файл.
#### Scenario: Запрос фавикона
- **WHEN** браузер запрашивает фавикон
- **THEN** приложение отвечает изображением SVG с собственным `Content-Type`
#### Scenario: Запасной формат
- **WHEN** клиент не поддерживает SVG-фавикон
- **THEN** разметка предоставляет PNG-запасной вариант
### Requirement: Фавикон под тему
Фавикон SHALL учитывать предпочтение схемы оформления и в тёмной схеме SHALL использовать светлый вариант эмблемы на тёмном фоне.
#### Scenario: Тёмная схема
- **WHEN** система сообщает о предпочтении тёмной схемы
- **THEN** фавикон отображается в варианте для тёмной схемы
#### Scenario: Светлая схема
- **WHEN** система сообщает о предпочтении светлой схемы
- **THEN** фавикон отображается в варианте для светлой схемы
### Requirement: Доступность эмблемы
Эмблема SHALL быть декоративной рядом с текстовым вордмарком и SHALL иметь доступное имя, когда используется как самостоятельный смысловой элемент.
#### Scenario: Эмблема рядом с вордмарком
- **WHEN** эмблема сопровождает видимый текст «Galo»
- **THEN** она скрыта от вспомогательных технологий
#### Scenario: Самостоятельная эмблема
- **WHEN** эмблема является единственным содержимым управляющего элемента
- **THEN** элемент имеет доступное имя
### Requirement: Автономность ассетов бренда
Эмблема и фавикон SHALL загружаться с самого приложения и SHALL NOT требовать запросов к внешним источникам.
#### Scenario: Загрузка без внешней сети
- **WHEN** страница загружается без доступа к внешней сети, кроме своего сервера
- **THEN** эмблема и фавикон отображаются
@@ -0,0 +1,26 @@
# Tasks
## 1. Brand assets
- [x] 1.1 Create `frontend/static/favicon.svg` with the halo mark (sun disc + separated ring) and embedded `prefers-color-scheme` dark/light variants, and verify it opens as valid SVG and renders legibly at 16px
- [x] 1.2 Create `frontend/static/favicon.png` (fallback) and `frontend/static/apple-touch-icon.png` rendered from the same emblem, and verify both files exist at their intended pixel sizes (32x32 and 180x180)
- [x] 1.3 Update `frontend/src/app.html` to reference `favicon.svg` with the PNG as fallback, and verify `make frontend` copies both into `frontend/build/`
## 2. UI emblem
- [x] 2.1 Add an inline SVG emblem component (disc in `--primary`, ring in `--primary` at reduced opacity, monochrome `currentColor` fallback), and verify it renders at 16-24px with the ring and disc still distinct
- [x] 2.2 Verify the emblem changes color with the theme by switching light/dark/neutral and confirming the disc and ring follow the active theme
## 3. Placement
- [x] 3.1 Show the emblem in the `AppShell` header next to the "Galo" wordmark and verify it appears in the main interface
- [x] 3.2 Show the emblem in the public/login layout and on the share page header and verify it appears on both
## 4. Accessibility
- [x] 4.1 Verify every decorative emblem (next to the wordmark) is hidden from assistive technologies and any standalone emblem element has an accessible name
## 5. Integration verification
- [x] 5.1 Run `make build` and verify the served favicon responds as an SVG image (`curl -I` shows the SVG content type) and that no brand asset request returns 404
- [x] 5.2 Validate the change and verify `openspec validate add-halo-branding` passes