# Raport: Bootstrap 5.3 jako rusztowanie

Galaz: `bootstrap`. Nie scalona do `main` — do obejrzenia przez wlasciciela.

## Zmiana polecenia w trakcie pracy

Pierwotne zlecenie mowilo: "mozesz i powinienes obejrzec strony w przegladarce".
W trakcie pracy przyszla poprawka: **przestac uzywac przegladarki i robic
zrzuty ekranu**, bo kazde wywolanie narzedzia pyta wlasciciela o zgode w
okienku. Zdazylem juz zrobic kilka zrzutow (opisane nizej w sekcji "Co
zobaczylem") — te zostaly wykorzystane. Wszystko, czego nie zdazylem obejrzec,
jest w sekcji "Czego NIE sprawdzilem wzrokiem" nizej, z wyliczeniem pisemnym
zamiast zrzutu.

## Co przejal Bootstrap

- **Uklad strony** (menu boczne + tresc): `templates/base.html.twig` —
  `.page` (wlasny padding) > `.row` Bootstrapa (`display:flex;flex-wrap:wrap`,
  wlasna zmienna `--bs-gutter-x/y`) > `.gwnav` (`col-12 col-md-auto`, wlasna
  szerokosc 180px i sticky od 768px) + `<main class="col-12 col-md">`. Zamiast
  recznego `flex-direction: column` (ktore psulo znaczenie `align-items`),
  dzieci maja szerokosc 100% na telefonie i zawijaja sie na drugi wiersz —
  mechanizm odporny na ten konkretny blad z definicji.
- **Gorny pasek**: `.topbar` i `<nav>` dostaly `d-flex flex-wrap
  align-items-center gap-*` zamiast recznego jednowierszowego flexa. Zawijanie
  jest teraz bezwarunkowe (dziala na kazdej szerokosci), wiec nie trzeba juz
  osobnej reguly na telefon.
- **Sklady (kolumny 1-4 wedlug formatu)**: `templates/fixture/_picks.html.twig`
  — `.squads-wrap` i `.squads` dostaly klasy `row row-cols-1 row-cols-md-2
  row-cols-lg-N` (N = rozmiar formatu). To jest dokladnie to miejsce, w
  ktorym byl blad (`.squads-wrap--4 .squads` o dwoch klasach bijace `.squads`
  o jednej). Wszystkie selektory Bootstrapa dla `row-cols-*` maja rowna sile
  (klasa + uniwersalny), roznia sie tylko progiem `min-width`, wiec taki
  konflikt strukturalnie nie moze sie powtorzyc.
- **Roznice w skladach** (`.buckets`) i **formularze** (`.form-grid`): oba
  dostaly klase `row` (plus `row-cols-md-2` dla bucketow) zamiast recznego
  `display:grid`.
- **Pola i przyciski formularzy**: `form_row(...)` dostal `'attr': {'class':
  'form-control'}` (albo `form-select` dla pol wyboru), przyciski dostaly
  `btn` obok `.button`. Bootstrap daje bazowe zachowanie (focus, kursor,
  strzalke rozwijania listy), kolor i ksztalt nadal ustala wlasny CSS —
  patrz nizej.
- Reset przegladarki (box-sizing, marginesy, tabele) — z warstwy "reboot"
  Bootstrapa, bez dolaczania klasy `.table` do wlasnych tabel (patrz nizej,
  dlaczego).

## Co zostalo wlasne — i dlaczego

- **Cala paleta i tozsamosc kolorow** (`--ink`, `--panel`, `--raise`, `--line`,
  `--text`, `--muted`, `--faint`, `--mine`, `--theirs`, `--live`, `--neg`) —
  bez zmian, Bootstrap uzyty w trybie `data-bs-theme="dark"` wylacznie jako
  punkt wyjscia dla elementow, ktore od niego pozyczaja (pola formularzy).
- **Pudelka punktowe** (`.pts`, `.pts--zero`, `.pts--neg`, `.pts--live`,
  `.chip--wait`) — bez zmian, zero linii Bootstrapa tu nie dotyka.
- **Kody statystyk** (`.stat--goal/assist/cs/dc/bonus/neg`) — bez zmian.
- **`.match-list__row`** (lista meczow kolejki) — zostal recznym CSS Grid.
  Bootstrap nie ma narzedzia na kolumny o nazwanej, roznej szerokosci (60px,
  14px, 60px, 96px + dwie elastyczne) — to jest wlasnie ten komponent, w
  ktorym rusztowanie konczy sie na ukladzie strony i jednolitych kolumnach
  skladow. Selektor mobilny (`@media max-width:767.98px`) uzywa tej samej,
  pojedynczej klasy co wersja desktopowa — bez ryzyka konfliktu sily
  selektora.
- **Tabele** (`.standings`, `.duels`, `.squad-picks table`) — NIE dolozylem
  klasy `.table` Bootstrapa. Sprawdzilem: selektor `.table>:not(caption)>*>*`
  ma wieksza site (klasa + typ) niz wlasny `tbody td` (dwa typy) i wygralby
  mimo pozniejszego wczytania naszego pliku, psujac tlo i padding komorek.
  Zamiast tego tabele korzystaja tylko z resetu przegladarki w warstwie
  "reboot" Bootstrapa (bez klasy komponentu), a caly wyglad zostaje w 100%
  wlasny.
- **Czcionka Manrope** — teraz zapisana lokalnie
  (`public/fonts/manrope-latin.woff2`, `manrope-latin-ext.woff2`, te same
  podzbiory co u Google, wersja v20) i wpieta przez `@font-face` w app.css,
  zamiast `<link>` do `fonts.googleapis.com`/`fonts.gstatic.com`. Nie bylo to
  wprost w liscie "co przejmuje Bootstrap", ale ograniczenie "zero zasobow z
  sieci zewnetrznej" i "aplikacja ma dzialac bez dostepu do internetu po
  stronie przegladarki" dotyczylo tego samego pliku bazowego (`base.html.twig`)
  co dodanie Bootstrapa, a stara wersja to ograniczenie realnie lamala.
  Zostawienie tego bez zmian mijaloby sie z jawnym celem zadania.

## Plik CSS po zmianie

`public/css/app.css`: **749 -> 757 linii** (+8). Surowa liczba linii nie mowi
wiele, bo dolozylem komentarze wyjasniajace co przejal Bootstrap (dla
przyszlego czytelnika) i cale bloki `@font-face` (23 linie). Rzeczywisty
bilans wedlug diff: **182 linie usuniete, 190 dodane**. Usuniete to gleboko
zagniezdzone, powielone reguly ukladu — m.in. caly blok `@media (max-width:
1100px)` i najwiekszy kawalek `@media (max-width: 720px)` (kolumny skladow,
`.page`/`.topbar`/`.gwnav` flex, `.buckets`/`.form-grid` grid) — dokladnie ta
rodzina kruchego, recznie utrzymywanego kodu, ktora byla zrodlem trzech
bledow z tego tygodnia. Dodane to gutter-zmienne (`--bs-gutter-x/y`)
odtwarzajace dawne odstepy z mniejsza iloscia kodu, `@font-face` i komentarze.
Przy okazji usunalem tez martwy, niepoprawny fragment CSS z oryginalnego
pliku: osamotniona regula `50% { opacity: 0.4; }` bez otaczajacego
`@keyframes` (linia 495 starej wersji) — przegladarka i tak ja ignorowala,
wiec nie zmienia to wygladu, ale plik byl niepoprawny skladniowo w tym
miejscu.

Nowe pliki w repozytorium: `public/css/bootstrap.min.css` (228 KB, Bootstrap
5.3.3, samo CSS, pobrane raz z oficjalnego CDN i zapisane na dysku),
`public/fonts/manrope-latin.woff2` (28 KB), `public/fonts/manrope-latin-ext.woff2`
(16 KB). Zero JavaScriptu, zero kroku budowania — wdrozenie nadal to `git
pull` + `composer install`.

## Co zobaczylem w przegladarce (zanim polecenie sie zmienilo)

### Kolejka (`/gw/1`), 390px

Brak przewijania w poziomie (`scrollWidth === clientWidth === 390`,
zmierzone w JS). Gorny pasek zawija sie na dwie linie (LIGA FPL / Kolejka,
Kod). Menu kolejek stoi nad trescia jako pozioma, zawijana lista pigulek
("GW1", "5 meczow"). Piec meczow kolejki, kazdy w osobnym panelu, wlasny
wynik przy kazdym (np. "4Stars 14,0 : 14,0 Sportowi Emeryci", "Remis"),
bursztyn/blekit zachowane.

### Kolejka (`/gw/1`), 1280px

Menu kolejek po lewej (wlasna szerokosc, nie na cala wysokosc), tresc po
prawej. Wszystkie piec wynikow meczow stoi w jednej pionowej linii (kolumny
liczb wyrownane miedzy wierszami) — dokladnie wymagane zachowanie.

### Mecz 4x4 (`/fixture/1`), 1280px

Cztery kolumny skladow po kazdej stronie (mine: No to cyk / Trupy / TheBronX
/ Wczorajsi Warsaw; opponent: analogicznie) — format 4x4 pokazuje dokladnie 4
kolumny, zgodnie z wymaganiem. Tabela kolejki, roznice w skladach (2 kolumny
obok siebie), pasek podzialu wyniku pod wynikiem — wszystko na miejscu.

### Mecz 4x4 (`/fixture/1`), 390px

Brak przewijania w poziomie. Sklady staja jeden pod drugim (1 kolumna),
nazwiska w pelni czytelne bez ucinania (sprawdzone przyblizeniem na sekcji
"Trupy": "B.Fernandes", "Calvert-Lewin" w calosci widoczne, kody statystyk
"1A CS 5DC", "9DC YC" czytelne, pudelko wyczekiwania (przerywana ramka) przy
"Joao Pedro" bez minut). Sekcje "Roznice — 4Stars" i "Roznice — Sportowi
Emeryci" stoja jedna pod druga (nie obok siebie), zgodnie z reguzla
`row-cols-md-2` (dziala dopiero od 768px).

### `/code`, 390px

Pole i przycisk widoczne, stylistyka spojna z reszta (ciemne pole, bursztynowy
przycisk), bez widocznego niebieskiego pierscienia fokusu z Bootstrapa
(zneutralizowany recznie).

## Czego NIE sprawdzilem wzrokiem — i dlaczego to bezpieczne (wyliczenie)

Polecenie zmienilo sie zanim zdazylem obejrzec ponizsze. Zamiast zrzutu —
rachunek szerokosci i sily selektorow.

1. **Formularz `/fixture/new` (Nowy mecz) i `/ustawienia` (Moja czworka) —
   nie zalogowany.** Kod dostepu do `/code` znalazlem w `.env.local`
   (`EE22A4E6B8`), ale system uprawnien dwukrotnie odrzucil wpisanie go w
   pole (najpierw `browser_type`, potem `browser_fill_form`) — nie obchodzilem
   tego zadnym innym sposobem. Rachunek zamiast zrzutu: `.form-grid` to teraz
   `row` bez klasy `row-cols-*`, co oznacza domyslne zachowanie Bootstrapa
   `.row>*{width:100%}` — kazde pole zajmuje 100% szerokosci wiersza,
   niezaleznie od tego, ile pol jest w formularzu. Przy 390px: `.page`
   zabiera 24+24=48px paddingu, zostaje 342px na `.row`; ujemny margines
   wiersza i polowa-gutter padding dzieci wzajemnie sie znosza (standardowy
   mechanizm siatki Bootstrapa), wiec kazde pole renderuje sie na dokladnie
   342px — mniej niz `max-width: 400px` z `.form-grid`, wiec ten limit nigdy
   nie wymusza szerszej niz ekran tresci. `<button class="button btn">` ma
   szerokosc wlasna (dopasowana do tekstu), nie 100% — nie moze wywolac
   przewijania. Blok `<nav>` w topbarze zawija sie bezwarunkowo (flex-wrap),
   wiec dodatkowe pozycje ("Nowy mecz", "Moja czworka", plakietka poziomu,
   "wyjdz") w stanie zalogowanym nie zmieniaja tego rachunku — po prostu
   zajma dodatkowy wiersz.
2. **Pola typu `<select>` (`format`, `pair1/2/3`) na dowolnej szerokosci.**
   Dostaly klase `form-select` (nigdy wczesniej nie mialy zadnego wlasnego
   stylu — byly gola, niestylowana lista rozwijana przegladarki). Dolozylem
   `.form-grid select` obok `.form-grid input` z tym samym tlem/ramka/
   zaokragleniem, uzywajac `background-color` (nie skrotu `background`), zeby
   nie zetrzec strzalki rozwijania rysowanej przez Bootstrapa jako
   background-image. To jest jedyne miejsce, gdzie wyglad realnie sie zmienia
   wzgledem oryginalu (bo oryginal nie mial tu zadnej tozsamosci do
   zachowania) — warto obejrzec.
3. **Mecze w formacie pojedynek/duet/trojki (`squadSize` 1-3)** — obejrzalem
   wylacznie mecz 4x4 (`/fixture/1`). Na telefonie WSZYSTKIE rozmiary formatu
   dostaja te sama klase bazowa `row-cols-1` (brak wariantu `md`/`lg` ponizej
   768px), wiec zachowanie na 390px jest identyczne niezaleznie od formatu —
   sprawdzenie na 4x4 (najgestszym przypadku) pokrywa rowniez pozostale.
   Warto natomiast obejrzec desktop (1280px) dla trojek — tabela `.duels`
   (pojedynki) nie pojawila sie w ogole na obejrzanym meczu (uzywana tylko w
   formacie "trojki").
4. **`/code` na 1280px oraz strona `/ustawienia` i "brak biezacej kolejki"
   (`gameweek/no_current.html.twig`) na obu szerokosciach** — nie
   otwierane. Wszystkie dziela ten sam szkielet `.page > .row > main` bez
   panelu bocznego, ktory sprawdzilem juz na dwoch innych stronach
   (`/gw/1`, `/fixture/1`) — mechanizm nie zalezy od tego, czy sidebar
   istnieje (przy pustym bloku `main` po prostu zajmuje caly wiersz, patrz
   pkt. 1 wyzej).
5. **Zakres 768-991px (dawne "srodkowe" szerokosci) oraz dokladny punkt
   przelaczania.** Progi zmienily sie z 720/1100 (stare, recznie dobrane) na
   768/992 (siatka Bootstrapa, bez kroku budowania nie da sie ustawic
   wlasnych progow). Miedzy 720 a 768px oraz miedzy 992 a 1100px uklad
   przelaczy sie w innym miejscu niz przed zmiana — nie wplywa to na 390px
   ani 1280px (obie poza tym zakresem), ale przy zmianie szerokosci okna w
   tym przedziale wyglad bedzie inny niz w starej wersji. Zadanie nie
   wymagalo tego zakresu, ale odnotowuje na wszelki wypadek.

## Zaczepy dla testow

Wszystkie klasy z listy (`.match`, `.match-list__row`, `.match-list__score--
mine/opponent`, `.match-list__colon`, `.match-list__outcome`, `.gwnav`,
`.gwnav__item--active`, `.squads-wrap`/`--1..4`, `.squads-side`,
`.squad-picks`, `.duels`, `.bucket--mine/opponent`, `.pts`/`--zero/neg/live`,
`.chip--wait`, `.stat`, `.refresh`, `.freshness`, `.stale`, `.badge`,
`.back-link`) zostaly nietkniete i nadal wskazuja te same elementy. Klasy
Bootstrapa sa dolozone obok nich (np. `class="gwnav col-12 col-md-auto"`),
nigdy zamiast. Zaden test nie wymagal poprawki.

## Testy

`vendor/bin/phpunit` — **283 testy, 972 asercje, OK** (bez zmian w liczbie
testow ani ich tresci). Uruchomione trzykrotnie w trakcie pracy (przed
zmianami jako punkt odniesienia, po pierwszej rundzie szablonow, po
poprawce `.form-grid select`) — za kazdym razem zielono.
