Commit graph

465 commits

Author SHA1 Message Date
aa42b0e257 Starter oppgave 20.1 2026-03-18 07:54:55 +00:00
ad04b0fabe Fullfører oppgave 19.6: Personlig arbeidsflate
Oppdaterer tasks.md (19.6 → ferdig), dokumenterer workspace
node_kind i nodes.md og personlig arbeidsflate i arbeidsflaten.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 07:53:39 +00:00
4eef7d79bb Implementer personlig arbeidsflate (oppgave 19.6)
Brukerens standard arbeidsflate med node_kind='workspace'.
Vises på /workspace når ikke koblet til en samling.

Backend:
- GET /my/workspace: finn eller opprett brukerens workspace-node
- Automatisk provisjonering ved første besøk (STDB + async PG)
- Owner-edge fra bruker til workspace

Frontend:
- /workspace rute med Canvas + BlockShell (gjenbruker spatial canvas)
- Fritt valg av verktøy-paneler fra verktøymeny
- Layout persisteres i workspace-nodens metadata via updateNode
- Tom-tilstand med verktøy-velger for nye brukere
- Responsivt: stacked tabs på mobil, spatial canvas på desktop
- Kontekst-velger i header for navigering til samlinger

Navigasjon:
- "Min flate"-knapp på mottak-siden
- "Min arbeidsflate" i ContextHeader dropdown for samlingssider

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 07:52:52 +00:00
1a2e122edf Starter oppgave 19.6 2026-03-18 07:44:33 +00:00
4e9481edf3 Fullfører oppgave 19.5: Paneler kan minimeres til kompakt header
Dobbeltklikk på panel-header toggler minimert tilstand. Minimerte
paneler viser kun header (ikon + tittel), skjuler innhold og
resize-handles. Posisjon, bredde og full høyde bevares i layout
og gjenopprettes ved nytt dobbeltklikk. Tilstanden persisteres
i edge metadata sammen med resten av workspace-layouten.

Endringer:
- PanelLayout: nytt `minimized?`-felt
- BlockShellEvents: nytt `onMinimizeChange`-event
- BlockShell: minimized-prop, dblclick-handler, minimize-knapp,
  skjuler content/resize når minimert
- Workspace-side: håndterer minimize-state, oppdaterer canvas-
  objekthøyde til PANEL_HEADER_HEIGHT når minimert

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 07:43:19 +00:00
3db0e0f9fe Starter oppgave 19.5 2026-03-18 07:39:32 +00:00
17bda8d20f Fullfører oppgave 19.4: Kontekst-header med kontekst-velger og verktøymeny
Erstatter den statiske headeren på arbeidsflaten med en interaktiv
kontekst-header som lar brukeren:

- Bytte mellom samlinger via nedtrekksmeny (kontekst-velger)
- Søke blant tilgjengelige samlinger
- Se mest brukte samlinger øverst (frekvens + recency-scoring)
- Legge til nye verktøy-paneler via verktøymenyen
- Se hvilke paneler som allerede er aktive på flaten

Nye filer:
- ContextHeader.svelte: header-komponent med kontekst-velger og verktøymeny
- workspace/recency.ts: localStorage-basert frekvens/recency-tracking

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 07:38:15 +00:00
4e01f9f7e5 Starter oppgave 19.4 2026-03-18 07:33:03 +00:00
0caa8eb126 Fullfører oppgave 19.3: Arbeidsflaten layout med Canvas + BlockShell
Skriver om /collection/[id] fra vertikal stack til spatial workspace:

- Desktop: trait-paneler vises som BlockShell-wrappers på Canvas med
  fri pan/zoom, drag-repositionering og resize
- Mobil (<768px): tab-navigasjon med ett synlig panel om gangen
- Tre-lags layout-modell: personlig (edge metadata) > node-default
  (generert fra traits) > plattform-default (grid fallback)
- Layout persisteres debounced (1s) til brukerens owner/member_of
  edge metadata via updateEdge API
- Nye traits legges automatisk til eksisterende layout
- Fjernede traits filtreres ut ved resolving

Ny fil: frontend/src/lib/workspace/types.ts
  - PanelLayout/WorkspaceLayout typer
  - TRAIT_PANEL_INFO med default størrelse/ikon per trait
  - generateDefaultLayout(): grid-arrangement fra trait-liste
  - resolveLayout(): tre-lags merging med saved layout

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 07:31:40 +00:00
4b6310ce53 Starter oppgave 19.3 2026-03-18 07:26:56 +00:00
28a1bf8e89 Fullfører oppgave 19.2: BlockShell wrapper-komponent
BlockShell er panelrammen for arbeidsflaten — wrapper rundt hvert
verktøy-panel (trait). Gir konsistent header med tittel, fullskjerm-
og lukk-knapper, drag-handles for repositionering via header,
resize-handles på alle kanter og hjørner, og drop-sone med visuell
feedback (blå glow for kompatibel, rød for inkompatibel).

Responsivt: min/max constraints, mobil-tilpasning (stacked layout,
større touch-targets, ingen resize-handles). Bruker HTML5 drag-and-drop
API for overføring mellom paneler, pointer events for repositionering.

Filer:
- blockshell/types.ts — SizeConstraints, BlockReceiver, DropZoneState
- blockshell/BlockShell.svelte — selve wrapper-komponenten
- blockshell/index.ts — eksporter

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 07:25:33 +00:00
79140d22ca Starter oppgave 19.2 2026-03-18 07:19:55 +00:00
3be2a57f88 Fullfører oppgave 19.1: Canvas-primitiv Svelte-komponent
Implementerer det felles canvas-underlaget som whiteboard, storyboard
og fremtidige canvas-views skal bruke. Ren Svelte 5 komponent uten
backend-avhengigheter.

Funksjoner:
- Pan/zoom kamera med CSS transforms (transform-origin: 0 0)
- Viewport culling med 200px margin for smooth scrolling
- Pointer events (unified mus + touch)
- Pinch-zoom og to-finger-pan for touch
- Snap-to-grid (toggle med G-tast eller toolbar)
- Fullskjermsmodus (fixed positioning)
- Lasso-seleksjon og shift+klikk multi-select
- Edge-pan ved drag nær kanter
- Responsivt: 44px touch targets på mobil, tilpasset toolbar
- zoomToFit() for å sentrere alle objekter
- Consumer-rendering via Svelte 5 snippets

Filer:
- frontend/src/lib/components/canvas/Canvas.svelte
- frontend/src/lib/components/canvas/types.ts
- frontend/src/lib/components/canvas/index.ts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 07:18:29 +00:00
e1c2a0cd08 Starter oppgave 19.1 2026-03-18 07:13:02 +00:00
8b5425fb59 Fullfører oppgave 18.6: Egendefinerte AI-presets
Brukere kan nå opprette egne AI-preset-noder med custom prompt,
dele dem med samlinger/team via shared_with-edges, og redigere/slette
egne presets. Modellprofil (flash/standard) er låst — kun admin
kan oppgradere fra flash til standard.

Backend:
- POST /intentions/create_ai_preset: Oppretter custom preset med
  tvunget category=custom og model_profile=flash. Valgfri deling
  til samling i samme kall.
- update_node: Beskytter model_profile mot endring av ikke-admin.
  Forhindrer kategori-endring fra custom til standard.

Frontend:
- AiToolPanel: "+ Nytt preset"-knapp, opprett/rediger-skjema med
  tittel, prompt, retning, ikon og farge. Rediger/slett/del-knapper
  for egne custom presets. Egendefinerte presets markert med "egn."
- createAiPreset() i api.ts.

Dokumentasjon:
- ai_verktoy.md: Oppdatert fasestatus, ny § 10 om egendefinerte
  presets med API-eksempler og modellprofil-beskyttelse.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 07:11:34 +00:00
d8897bf9b9 Starter oppgave 18.6 2026-03-18 06:59:35 +00:00
35d39962dd Fullfører oppgave 18.5: Drag-and-drop integrasjon mellom verktøy
Implementerer toveis drag-and-drop mellom AI-verktøypanelet og
innholdspaneler, med visuell feedback og kompatibilitetssjekking.

Nye filer:
- transfer.ts: Sentralisert transfer-tjeneste med kompatibilitetsmatrise,
  DragPayload-format (application/x-synops-transfer), og
  inkompatibilitets-meldinger for lyd/bilde-noder.

Endringer:
- AiToolPanel: Drop-sone bruker presetets farge (dynamisk border/bg),
  viser rød sone med forklaring ved inkompatible noder (lyd/bilde),
  presets er draggable ut (for tool_to_node retning).
- EditorTrait: Aksepterer AI-preset drops på innholdsnoder (tool_to_node),
  viser visuell feedback (lilla=kompatibel, rød=inkompatibel),
  trigger in-place revisjon via aiProcess API.
- ChatTrait: Kommunikasjonsnoder er nå draggable til AI-verktøyet.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 06:58:15 +00:00
999f46f15d Starter oppgave 18.5 2026-03-18 06:51:42 +00:00
d4de8b3619 Fullfører oppgave 18.4: AI-verktøy panel (frontend)
Svelte-komponent for AI-prosessering i arbeidsflaten:
- AiToolPanel.svelte: Viser ai_preset-noder fra STDB som velgbare
  verktøy, med modell-indikator (flash/standard) og prompt-forhåndsvisning
- Drag-and-drop mottak for tekstnoder med visuell feedback
- Validerer kompatibilitet (kun content/communication-noder)
- Kaller /intentions/ai_process via ny aiProcess()-funksjon i api.ts
- Integrert i collection-siden, tilgjengelig for alle innloggede brukere
- EditorTrait: innholdsnoder er nå draggable for AI-prosessering
- Fritekst-felt for egendefinert instruksjon (backend-støtte kommer i 18.6)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 06:50:29 +00:00
42384c318d Starter oppgave 18.4 2026-03-18 06:42:08 +00:00
776bc895c1 Fullfører oppgave 18.3: Direction-logikk for AI-prosessering
Implementerer de to retningene for AI-verktøyet:

- tool_to_node ("Penselen"): Lagrer original content som revisjon i
  ny node_revisions-tabell, deretter oppdaterer noden med AI-output
  i både STDB (sanntid) og PG (persistering).

- node_to_tool ("Kverna"): Oppretter ny node med AI-output, med
  derived_from-edge tilbake til kildenoden og processed_by-edge
  til AI-preseten. Full sporbarhet i grafen.

Ny PG-tabell: node_revisions (node_id, content, title, metadata,
revision_type, created_by, ai_preset_id, job_id).

Ref: docs/features/ai_verktoy.md § 2.2, § 6.1

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 06:40:26 +00:00
9855488d12 Starter oppgave 18.3 2026-03-18 06:25:44 +00:00
bca0ff1deb Fullfører oppgave 18.2: AI-prosessering endepunkt
POST /intentions/ai_process med source_node_id, ai_preset_id og
direction (node_to_tool / tool_to_node).

Endepunktet validerer input, sjekker at kilde-node og AI-preset
finnes, verifiserer skrivetilgang for tool_to_node-retning, og
legger en ai_process-jobb i køen.

Jobb-handleren (ai_process.rs) henter kilde-content og preset-prompt,
mapper modellprofil → LiteLLM-alias (flash → sidelinja/rutine,
standard → sidelinja/resonering), kaller AI Gateway, og logger
forbruk i både ai_usage_log og resource_usage_log.

Direction-logikk (opprett ny node vs. oppdater eksisterende)
implementeres i oppgave 18.3.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 06:24:31 +00:00
7224cf9897 Starter oppgave 18.2 2026-03-18 06:14:26 +00:00
cad3f4b699 Fullfører oppgave 18.1: AI-preset node-type
Implementerer node_kind 'ai_preset' med metadata-validering og
8 standardprompter som seed-data.

Validering i maskinrommet (create_node + update_node):
- prompt (påkrevd, ikke-tom streng)
- model_profile (flash | standard)
- category (standard | custom)
- default_direction (tool_to_node | node_to_tool | both)
- icon (påkrevd, ikke-tom streng)
- color (påkrevd, hex-farge #RRGGBB)

Seed-presets: Rens tekst, Korrektør, Oppsummering, Oversett,
Skriv om for publisering, Trekk ut fakta, Forenkle, Endre tone.

8 enhetstester for valideringsfunksjonen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 06:13:09 +00:00
dae06eecc6 Starter oppgave 18.1 2026-03-18 06:05:11 +00:00
a3cdfa9dc2 Fullfører oppgave 17.7: FFmpeg feilmeldinger til bruker
Tre endringer som sammen gir brukeren innsyn i FFmpeg-feil:

1. Backend: Nytt GET /query/job_status-endepunkt i queries.rs.
   Frontenden pollet allerede denne URLen, men endepunktet manglet.
   Returnerer status, result og error_msg fra job_queue.

2. RenderDialog: Ny error-tilstand med formatFfmpegError() som
   trekker ut lesbar feilmelding fra FFmpeg stderr-dump. Viser
   kort oppsummering + ekspanderbar full feilmelding via <details>.

3. Studio-side: Sender renderError til RenderDialog som errorMessage.
   Toast-varselet vises kun når dialogen er lukket (unngår duplisering).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 06:03:59 +00:00
9f4dfee232 Starter oppgave 17.7 2026-03-18 05:58:19 +00:00
ce56e31de2 Fullfører oppgave 17.6: Periodisk CAS tmp-opprydding
Legger til cleanup_tmp() i CasStore som sletter orphaned .tmp-filer
eldre enn 1 time. Disse oppstår når en skriveprosess krasjer midt i
en atomisk CAS-skriveoperasjon (skriv til tmp, rename til endelig path).

Ny bakgrunnsloop start_tmp_cleanup_loop() kjører hver time og fjerner
foreldede temp-filer. Følger samme mønster som pruning- og
disk-monitor-loopene.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 05:57:10 +00:00
a3f8ca2dfa Starter oppgave 17.6 2026-03-18 05:54:47 +00:00
6f50f66431 Fullfører oppgave 17.5: Job-polling opprydding i lydstudioet
Tre forbedringer i studio-siden:

1. Interval/timeout-opprydding ved navigering: Polling-interval og
   timeout lagres i komponent-variabler og ryddes opp via $effect
   cleanup når komponenten demonteres. Forhindrer memory leaks og
   ghost-requests etter navigering bort fra studio-siden.

2. Feilmelding etter N mislykkede polling-forsøk: Etter 5 feilede
   statussjekker (nettverksfeil eller HTTP-feil) vises en
   feilmelding til brukeren i stedet for stille ignorering.
   Timeout-feil og jobb-feil vises også i UI.

3. Metadata JSON.parse i try/catch: Hindrer at ugyldig metadata-JSON
   krasjer hele studio-siden. Logger feilen og returnerer null.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 05:53:28 +00:00
24d752024c Starter oppgave 17.5 2026-03-18 05:50:51 +00:00
6e04f3c013 Fullfører oppgave 17.4: Frontend input-begrensninger
Legger til min/max-attributter på alle tallfelter i OperationPanel
slik at nettleseren hindrer ugyldig input før det sendes til backend.
Grensene matcher backend-valideringen i audio.rs:

- silenceThreshold: -96 til 0 dB
- silenceMinMs: 1 til 60000 ms
- normTarget: -70 til 0 LUFS
- fadeInMs/fadeOutMs: 1 til 300000 ms
- compThreshold: -60 til 0 dB
- compRatio: 1 til 20 (max lagt til, min fantes allerede)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 05:49:42 +00:00
b20642a433 Starter oppgave 17.4 2026-03-18 05:48:17 +00:00
1d1a316a1c Fullfører oppgave 17.3: Fade/silence-logikk
Tre fikser i audio.rs:

1. Fade-out start clampes til 0 i stedet for å hoppes over
   når effective_duration < fade_duration. Tidligere ble faden
   stille droppet — nå starter den alltid fra minst 0.

2. Adaptiv silence-margin: margin (200ms) begrenses til maks
   halve regionens varighet. Korte stillhetsregioner (<400ms)
   fikk tidligere hele marginen spist opp og ble aldri kuttet.

3. Ny validate_fade_durations() gir feilmelding når fade-varighet
   overstiger lydens totale varighet. Kalles fra process_audio
   etter at vi kjenner faktisk varighet.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 05:47:07 +00:00
4ea0229935 Starter oppgave 17.3 2026-03-18 05:44:41 +00:00
7eccbd0dc3 Fullfører oppgave 17.2: FFmpeg-parametervalidering
Legger til validate_operations() som sjekker alle numeriske verdier
i EDL-operasjoner før de interpoleres i FFmpeg-filterstrenger.
Dette forhindrer ugyldige/farlige verdier fra å nå ffmpeg subprocess.

Validerte parametere:
- Cut: start/end ikke-negativ, end > start
- Normalize: target_lufs mellom -70 og 0
- TrimSilence: threshold_db -96..0, min_duration 1..60000ms
- FadeIn/Out: duration 1..300000ms
- NoiseReduction: strength_db -80..0
- Equalizer: gain -30..+30 dB per bånd
- Compressor: threshold -60..0 dB, ratio 1..20

Validering kjøres ved inngang til process_audio() og detect_silence().
NaN/Inf-verdier avvises eksplisitt. Alle feil samles og returneres samlet.

12 enhetstester verifiserer grenseverdier og feiltilfeller.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 05:43:31 +00:00
a4e2a112d5 Starter oppgave 17.2 2026-03-18 05:40:43 +00:00
9f66f114ff Fullfører oppgave 17.1: Responsivt studio-layout
Lydstudioet var kun desktop-optimalisert med fast sidebar (w-72).
Nå responsivt med to moduser:

- Desktop (lg+): Sidebar med verktøypanel til høyre, som før
- Mobil/tablet (< lg): Waveform fyller full bredde, verktøypanel
  tilgjengelig via flytende knapp som åpner bottom sheet (modal).
  Operation-badge på knappen viser antall aktive operasjoner.

Header: Kompaktere padding på mobil, tittel truncates, audio-info
skjules på små skjermer. min-w-0 på hovedområdet hindrer overflow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 05:39:19 +00:00
4edad399cd Starter oppgave 17.1 2026-03-18 05:36:17 +00:00
ac8f8c508d Fullfører oppgave 16.7: Stemmeeffekter med robot og monster voice
Robotstemme: Ring-modulasjon via OscillatorNode som modulerer
GainNode.gain — gir metallisk, Dalek-aktig effekt. Justerbar
frekvens (30–300 Hz) og modulasjonsdybde (0–100%).

Monsterstemme: Egenutviklet AudioWorkletProcessor med phase vocoder
for sanntids pitch-shifting. Bruker overlap-add med 2048-sample FFT
og 4x overlap for ~42ms latens ved 48kHz. Pitch-faktor 0.5x–2.0x.

UI: Effektvelger-knapper (Robot/Monster) i FX-seksjon per kanal,
med fargekodede parametersliders som vises når effekten er aktiv.
On/off-state synkroniseres via STDB toggle_effect, parametere er
per-klient (ulike brukere kan ha forskjellige monitorinnstillinger).

STDB: Lagt til set_effect_param reducer for fremtidig param-synk
(krever spacetime CLI for publish — ikke deployet ennå).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 05:34:59 +00:00
6732a15e4d Starter oppgave 16.7 2026-03-18 05:25:46 +00:00
171c9b991a Fullfører oppgave 16.6: EQ-effektkjede med per-kanal toggles og presets
Implementerer tre EQ-effekter i Web Audio-grafen:
- Fat bottom: BiquadFilterNode lowshelf +8dB @ 200Hz
- Sparkle: BiquadFilterNode highshelf +4dB @ 10kHz
- Exciter: WaveShaperNode (soft-clip saturation) + highshelf +4dB @ 3.5kHz
- Highpass 80Hz alltid aktiv for rumble-fjerning

Signalkjede per kanal:
  Source → Analyser → HighPass → FatBottom → Exciter → Sparkle → Gain → Master

Per-kanal toggles synkroniseres via STDB toggle_effect reducer
(allerede implementert i fase B). UI viser fargede toggle-knapper
og preset-velger (Av, Podcast-stemme, Radio-stemme).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 05:24:24 +00:00
28a600dd9e Starter oppgave 16.6 2026-03-18 05:18:54 +00:00
8acb5a8731 Fullfører oppgave 16.5: Sound pads med 4×2 pad-grid
Implementerer lydpads (inspirert av RødeCaster Pro II) i mixeren:

- mixer.ts: Nytt pad-system med AudioBuffer-caching, GainNode per pad,
  og one-shot AudioBufferSourceNode-avspilling. Funksjoner for load,
  play, stop, og gain-kontroll.

- livekit.ts: Data message-støtte (sendDataMessage, onDataMessage) for
  synkronisert pad-avspilling på tvers av LiveKit-deltakere. Bruker
  reliable delivery med topic-filtrering.

- SoundPadGrid.svelte: 4×2 responsivt pad-grid med fargede knapper.
  Forhåndslaster lydfiler fra CAS til AudioBuffer. Visuell feedback
  ved avspilling (scale-animasjon). Konfigurasjonsmodus for å sette
  label, farge og laste opp lydfil per pad. Pad-konfig lagres i
  metadata.mixer.pads på samlingsnoden.

- MixerTrait.svelte: Integrerer SoundPadGrid mellom kanalstriper og
  master-seksjon. Sender isViewer-prop for tilgangskontroll.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 05:17:30 +00:00
00d4df6f53 Starter oppgave 16.5 2026-03-18 05:09:36 +00:00
453ec4fb59 Fullfører oppgave 16.4: Delt mixer-kontroll via SpacetimeDB
Implementerer sanntids mixer-synkronisering mellom alle deltakere i et
LiveKit-rom via SpacetimeDB. Når én deltaker justerer gain eller muter
en kanal, oppdateres alle klienters Web Audio-graf og UI umiddelbart.

SpacetimeDB-modul (Rust):
- MixerChannel-tabell med room_id/target_user_id-indekser
- Reducers: set_gain (clamped 0.0-1.5), set_mute, toggle_effect,
  create/delete_mixer_channel, set_mixer_role (editor/viewer)
- Viewer-sjekk i reducers — viewer kan ikke endre andres kanaler
- Opprydding av mixer-kanaler i close_live_room og clear_all

Frontend (SvelteKit):
- mixerChannelStore med reaktive callbacks og room_id-indeks
- MixerTrait leser delt state fra STDB, skriver endringer via reducers
- suppressRemoteSync-flagg forhindrer feedback-loop ved egne endringer
- Viewer-modus: disabled sliders/knapper for låste deltakere
- Visuell (V)-indikator for viewer-kanaler

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 05:08:23 +00:00
de498f26a1 Starter oppgave 16.4 2026-03-18 04:58:37 +00:00
f1c9b281bc Fullfører oppgave 16.3: MixerTrait-komponent med kanalstriper
Implementerer Mixer-UI som trait-komponent for samlingssider:
- Kanalstripe per deltaker med volumslider (0–150%), VU-meter (CSS),
  nød-mute-knapp (rød, tydelig) og navnelabel
- Master-seksjon med fader, VU-meter og master-mute
- Responsivt design: stacked layout på mobil, horisontal på desktop
- Animert VU-meter via requestAnimationFrame og AnalyserNode-data
- Integrert i collection-siden som 'mixer'-trait

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 04:57:22 +00:00
82c45c4208 Starter oppgave 16.3 2026-03-18 04:54:25 +00:00