# SIGNAL_IMPLEMENTATION_SPEC — ugovor za Claude Code
R404_BRAND_SIGNAL_R01 · 2026-08-19
Cilj: CC nastavlja sajt BEZ pitanja „kako brend izgleda na ovoj sekciji". Uz ovo čitaj `SIGNAL_MOTION_SYSTEM.md` (gramatika) i `16_TOKENS/brand-tokens.css` (vrednosti).

## 1. Šta SIGNAL znači u UI terminima
Signal = pokazivač pažnje. Ono što signal pronađe = ono što korisnik treba da vidi. Zato: **jedan signal-događaj po sekciji, jedan cilj po događaju** (izuzetak: grananje na max 3 cilja u „radovi"/„usluge" tipu sekcije).

## 2. Kada se pojavljuje / nestaje
- Pojavljuje se kad sekcija-domaćin uđe ~20% u viewport; scrub prati skrol progres te sekcije.
- Nestaje: ulaskom iza neprozirnog bloka, ili fade repa 300ms nakon FOUND.
- Sekcije bez signala: prikazuju STATIC posledicu (upaljen element, zlatna linija, status etiketa). Minimum svake stranice: bar jedan FOUND trag, nikad više od 2 živa putovanja po stranici.

## 3. DOM / slojevi (preporučena strategija)
```html
<section class="sig-host">            <!-- position:relative -->
  <canvas class="sig-canvas" aria-hidden="true"></canvas>  <!-- z-index:var(--z-behind); pointer-events:none -->
  <div class="content">…</div>        <!-- z-index:var(--z-content); blokovi imaju neproziran bg -->
  <canvas class="sig-canvas--front"></canvas>              <!-- z-index:var(--z-front); SAMO kad treba prolaz ispred -->
</section>
```
- Canvas po sekciji-domaćinu (ne globalni full-page canvas — jeftinije, jednostavniji lifecycle).
- `sig-canvas--front` montirati samo za sekcije koje imaju prolaz ispred; inače ne postoji u DOM-u.
- Prolaz „iza blokova": jedan canvas iza + neprozirni blokovi. Ne koristiti maske/clip-path za ovo.
- Ulazak u sliku: signal na z-behind nestaje na ivici okvira slike; unutar okvira CSS FOUND stanje (etiketa + border + tačka).

## 4. Tehnika po tipu zadatka
| Zadatak | Tehnika |
|---|---|
| putovanje + rep + iskre | **canvas 2D** (jedina JS animacija; rAF; offscreen gradient za rep) |
| aktivacija cilja (gradijent, glow, tačka) | **CSS** (klase `.is-weak/.is-found`, transition tokeni) |
| flash | CSS pseudo-element, `--t-flash`, opacity keyframe |
| puls | CSS animation `--t-pulse` ±5% filter brightness |
| scrub veza sa skrolom | JS: progres = f(scroll), rAF lerp 0.16 (kod obrazac u SIGNAL home `main.js`) |
| hero | postojeći video scrub (blob load — CF Pages Range zamka!) |
| WebGL | **NE** — nema opravdanja; budžet čitljivosti i održavanja važniji |

## 5. Stanja kao CSS klase
```css
.sig-target            { color: #2e2d2a; }                    /* SLAB/čelik */
.sig-target.is-weak    { animation: sigFlicker 1.8s infinite; }
.sig-target.is-found   { background: var(--sig-gradient); -webkit-background-clip:text; color:transparent;
                         filter: var(--sig-glow); transition: filter var(--t-activate) var(--ease-out); }
.sig-dot               { width:.14em; height:.14em; border-radius:50%; background:var(--ink); } /* bela tačka */
```
JS postavlja klase; sadržaj je čitljiv i BEZ JS-a (progressive enhancement: bez JS = sve u FOUND stanju).

## 6. Canvas fizika (parametri)
- Bezier staza; uzorkovanje 400 tačaka; glava index = easeInOut(progres).
- Rep: 12–18% staze, širina 1.5→0.6px, boja gold-deep→gold-hi, alpha 0.25→1.
- Glava: r 5–7px gold-hi + shadowBlur 8 gold; iskre ≤10, r 1.4px, radius 2–26px.
- Glow: canvas shadowBlur (8 / 26) u dva poteza — NE stack-ovati više od 2 blur prolaza po frame-u.
- DPR cap 2. Canvas rezolucija = element × min(devicePixelRatio, 2).
- 60fps cilj; ako frame > 20ms u 10 uzastopnih frejmova → prepolovi iskre pa isključi halo (degradacija u tom redu).

## 7. Skrol
- IntersectionObserver aktivira host (20% vidljivosti), scroll listener + rAF lerp za progres.
- Sticky pozornice: max 360svh track; posle FOUND sekcija se „pušta" (nema zadržavanja).
- NIKAD: preotimanje wheel eventa, umetanje scroll kontejnera, momentum hakovi.

## 8. Mobile
- `(max-aspect-ratio: 1/1)` → mobile gramatika: vertikalne staze, ≤24 čestice, ≤2 kraka, jači flash.
- Hero: režirani stage (copy u mraku gore, scena dole) — obrazac iz SIGNAL home.
- Touch nema hover: sva signal stanja vezana za skrol/viewport, ne za hover.

## 9. Reduced motion + fallback
- `prefers-reduced-motion`: ne montirati canvas uopšte; svi `.sig-target` odmah `.is-found`; video → poster.
- `<noscript>`/JS greška: isto kao reduced motion. Sadržaj nikad ne zavisi od signala.

## 10. Performanse (budžeti)
- JS za signal sistem: ≤ 12 KB min+gzip, bez biblioteka (bez GSAP za ovo — fizika je trivijalna).
- 0 long-taskova > 50ms od signala; canvas pauziran van viewporta (IO unobserve).
- CLS od signala = 0 (canvas apsolutno pozicioniran, nikad ne pomera layout).
- LCP element nikad ne čeka signal (poster/tekst prvi, kao u SIGNAL home).

## 11. Veliki simboli (familija + ponašanje)
Dozvoljeni monumentalni objekti: `404`, stvarne metrike (`54%`, cene, rokovi), `%`, `→`, `+`, lokacijski pin, lupa/search, koordinate, status reči (`PRONAĐENO`, `UŽIVO`). Svaki MORA imati razlog u sadržaju sekcije — nikad tech-ikona dekoracija.
Ponašanje: simbol se rađa SLAB → signal ga pronađe → FOUND (Archivo 800 gradijent ili 250 linijski; metrike: broj Archivo, jedinica/etiketa mono).

## 12. Redosled ugradnje na postojeći sajt
1. Uvezi `brand-tokens.css`; zameni nav tekst-logo sa `biro404-lockup-on-dark.svg` (min 120px).
2. Favicon set iz `13_FAVICON_OG` + OG default.
3. Signal engine (canvas modul + klase) na naslovnoj: hero (postoji) + 1 sekcija „radovi" (grananje) + CTA (spajanje).
4. Interne strane: SAMO static posledice + po jedan mali FOUND događaj; bez putovanja na svakoj strani.
5. QA po §10 budžetima + reduced-motion + 320px.

## 13. Anti-patterns
Vidi `SIGNAL_MOTION_SYSTEM.md §8`. Plus implementaciono: bez global scroll-hijacka; bez WebGL; bez GSAP zavisnosti za signal; bez animiranja `top/left` (samo transform/opacity); bez novih fontova.
