diff --git a/.claude/settings.local.json b/.claude/settings.local.json
index a6bfc29..4e46533 100644
--- a/.claude/settings.local.json
+++ b/.claude/settings.local.json
@@ -320,7 +320,12 @@
"Bash(curl -s -o /dev/null -w \"%{http_code}\\\\n\" https://teecup.teeoff.no/dashboard)",
"Bash(curl -s https://teecup.teeoff.no/manifest.webmanifest)",
"Bash(curl -s -o /dev/null -w \"%{http_code}\\\\n\" https://teecup.teeoff.no/sw.js)",
- "Bash(curl -s -o /dev/null -w \"%{http_code}\\\\n\" https://teecup.teeoff.no/icons/icon-512.png)"
+ "Bash(curl -s -o /dev/null -w \"%{http_code}\\\\n\" https://teecup.teeoff.no/icons/icon-512.png)",
+ "Bash(disown)",
+ "Bash(python3 -c \"import httpx\")",
+ "Bash(curl -s http://localhost:18800/health)",
+ "Bash(python3 /tmp/claude-1000/-opt-teecup/a8bd2fc3-4b9c-4682-a2be-cf36e143de78/scratchpad/test_hcp_fix.py)",
+ "Bash(python3 /tmp/claude-1000/-opt-teecup/a8bd2fc3-4b9c-4682-a2be-cf36e143de78/scratchpad/test_tee_gender.py)"
],
"additionalDirectories": [
"/opt/teeoff/deploy",
diff --git a/014_tee_gender_to_rating.sql b/014_tee_gender_to_rating.sql
new file mode 100644
index 0000000..f265e8b
--- /dev/null
+++ b/014_tee_gender_to_rating.sql
@@ -0,0 +1,84 @@
+-- =====================================================================
+-- TeeCup — kjønn hører til RATINGEN, ikke selve utslaget (migrasjon 014)
+-- =====================================================================
+-- Reist av brukeren 2026-07-19: en golfbane har IKKE fysisk kjønnsdelte
+-- utslag -- begge kjønn kan som regel spille fra ethvert utslag. Det
+-- eneste som faktisk varierer per kjønn er om klubben har VALGT å slope
+-- (rate) et gitt utslag for det respektive kjønnet (noen klubber sloper
+-- bevisst ikke det lengste utslaget for damer). `tee.gender` (migrasjon
+-- 001) konflaterte feilaktig utslaget og ratingen -- hvert fysisk utslag
+-- ble lagret som TO separate `tee`-rader (én per kjønn), bekreftet mot
+-- ekte importert Tjøme-data (fire utslag, hver som et rent m/f-par).
+--
+-- Denne migrasjonen flytter `gender` fra `tee` til `tee_rating` (der det
+-- faktisk hører hjemme -- én fysisk tee kan ha 0, 1 eller 2
+-- kjønnsspesifikke ratinger), og slår sammen eksisterende kjønns-par-rader
+-- til én fysisk tee-rad. Se ARCHITECTURE_DECISIONS.md ADR-029.
+--
+-- Kjørt trygt mot ekte data FORDI (bekreftet FØR skriving, read-only):
+-- alle eksisterende tee-rader er rene navnepar (m+f, ingen 'x'), ingen
+-- gruppe har mer enn to rader.
+-- =====================================================================
+
+\set ON_ERROR_STOP on
+
+BEGIN;
+
+ALTER TABLE tee_rating ADD COLUMN gender text;
+
+-- Fyll inn gender på HVER eksisterende tee_rating-rad fra sin (ennå
+-- urørte) eier-tee, FØR noe slås sammen eller slettes.
+UPDATE tee_rating tr
+SET gender = t.gender
+FROM tee t
+WHERE t.id = tr.tee_id;
+
+-- Selve golfregelen: en WHS-rating er alltid for ett bestemt kjønn -- 'x'
+-- (som var gyldig på PLAYER-nivå) gir ikke mening for en rating. Krasjer
+-- høyt her (NOT NULL + CHECK) hvis noen ukjent/uventet rad skulle mangle
+-- et gyldig kjønn -- fanger det FØR det stille blir en umulig rating,
+-- ikke etterpå.
+ALTER TABLE tee_rating ALTER COLUMN gender SET NOT NULL;
+ALTER TABLE tee_rating ADD CONSTRAINT tee_rating_gender_check CHECK (gender IN ('m', 'f'));
+
+-- Den GAMLE unikheten (tee_id, scope) må vekk FØR sammenslåingen under --
+-- å flytte en "duplikat"-tee sin rating over til beholder-tee-en kolliderer
+-- ellers midlertidig med beholderens EGEN eksisterende (tee_id, scope)-rad
+-- (samme scope, men snart ulikt kjønn -- det er jo poenget). Den NYE,
+-- kjønnsbevisste unikheten legges til ETTER sammenslåingen, når den faktisk
+-- kan håndheves riktig.
+ALTER TABLE tee_rating DROP CONSTRAINT tee_rating_tee_id_scope_key;
+
+-- Slå sammen "duplikat"-utslag (samme bane+navn, hittil ulikt kjønn på
+-- selve tee-raden) til ÉN fysisk tee-rad. Velger MIN(id) per
+-- (course_id, name) som "beholderen".
+CREATE TEMP TABLE tee_merge_map AS
+SELECT t.id AS old_id,
+ (SELECT min(t2.id::text)::uuid FROM tee t2
+ WHERE t2.course_id = t.course_id AND t2.name = t.name) AS keeper_id
+FROM tee t;
+
+UPDATE tee_rating tr
+SET tee_id = m.keeper_id
+FROM tee_merge_map m
+WHERE tr.tee_id = m.old_id AND m.old_id <> m.keeper_id;
+
+UPDATE match_participant mp
+SET tee_id = m.keeper_id
+FROM tee_merge_map m
+WHERE mp.tee_id = m.old_id AND m.old_id <> m.keeper_id;
+
+DELETE FROM tee t
+USING tee_merge_map m
+WHERE t.id = m.old_id AND m.old_id <> m.keeper_id;
+
+DROP TABLE tee_merge_map;
+
+-- Unikhet er nå per (tee_id, scope, gender) -- ett utslag kan ha BÅDE en
+-- herre- og en dame-rating for samme scope.
+ALTER TABLE tee_rating ADD CONSTRAINT tee_rating_tee_id_scope_gender_key UNIQUE (tee_id, scope, gender);
+
+ALTER TABLE tee DROP CONSTRAINT tee_gender_check;
+ALTER TABLE tee DROP COLUMN gender;
+
+COMMIT;
diff --git a/ARCHITECTURE_DECISIONS.md b/ARCHITECTURE_DECISIONS.md
index ccbc3e3..3c98fea 100644
--- a/ARCHITECTURE_DECISIONS.md
+++ b/ARCHITECTURE_DECISIONS.md
@@ -1312,6 +1312,99 @@ for oppfølging, se FEATURE_BACKLOG.md sin PWA-tabell og CLAUDE.md sin
---
+## ADR-029: Kjønn hører til tee-RATINGEN, ikke selve utslaget
+
+Reist av brukeren 2026-07-19, som del av en runde med fire rapporterte
+UX-/korrekthetshull fra faktisk testing av blind draw og scorekort. Startet
+som en antatt frontend-fiks ("tee-valget bør følge spillerens kjønn
+automatisk"), men brukeren presiserte at premisset mitt var feil: en
+golfbane har IKKE fysisk kjønnsdelte utslag -- begge kjønn kan som regel
+spille fra ethvert utslag. Det eneste som faktisk varierer per kjønn er om
+klubben har VALGT å slope (rate) et gitt utslag for det respektive kjønnet
+(noen klubber sloper bevisst ikke det lengste utslaget for damer).
+
+**Bekreftet problem, ikke antatt:** `tee.gender` (migrasjon 001) la kjønn på
+selve utslaget, ikke ratingen. Sjekket mot ekte, importert produksjonsdata
+(Tjøme Golfklubb, ADR-019): alle fire utslagene lå som RENE navnepar --
+"32"/m + "32"/f, "44"/m + "44"/f, osv. -- to separate `tee`-rader for
+akkurat samme fysiske utslag. Blind draw-skjermen viste dette som "velg
+Dame- eller Herre-tee", som om det var to ulike steder å slå fra.
+
+**Beslutning A -- `gender` flyttes fra `tee` til `tee_rating`.** Ett fysisk
+utslag (`tee`, identifisert kun ved navn) kan ha 0, 1 eller 2
+kjønnsspesifikke ratinger. `tee_rating` sin unikhet endres fra
+`(tee_id, scope)` til `(tee_id, scope, gender)`. `gender` på `tee_rating`
+er `NOT NULL CHECK IN ('m','f')` -- 'x' (gyldig på PLAYER-nivå) gir ikke
+mening for en WHS-rating, som alltid er for ett bestemt kjønn.
+
+**Beslutning B -- tee-valget blir helt automatisk, ingen manuell
+kjønnsvelger (bekreftet med bruker, valgte det anbefalte alternativet).**
+Organisator/kaptein velger KUN fysisk utslag i blind draw
+(`session-blind-draw.tsx`, ingen "H"/"D"-suffiks lenger). Riktig
+kjønnsspesifikk rating løses AUTOMATISK server-side fra spillerens
+registrerte `player.gender` -- `app/handicap.py` sin
+`compute_and_store_side_handicaps` joiner nå `tee_rating` på
+`(tee_id, scope='full_18', gender = player.gender)` i tillegg til den
+tidligere ADR-028-fiksen (alltid full_18, uavhengig av hole_config).
+
+**Beslutning C -- manglende rating/kjønn feiler tydelig FØR innsetting,
+ingen stille fallback (bekreftet med bruker, valgte det anbefalte
+alternativet).** `matches.py` sin `add_participant` validerer, når
+`config.use_handicap` er sann: (1) spilleren har et registrert kjønn --
+avvist med `VALIDATION_FAILED` hvis ikke ("sett kjønn på spilleren
+først"), (2) valgt utslag har faktisk en `tee_rating` for NØYAKTIG det
+kjønnet -- avvist med `VALIDATION_FAILED` hvis ikke ("dette utslaget har
+ingen dame/herre-rating -- velg et annet utslag"). Samme "fail loudly"-
+prinsipp som ADR-019 sin importvalidering og den eksisterende
+handicap_index-sjekken (2026-07-18) rett ved siden av. `_remap_course`
+(bane-bytte midt i en økt) fikk samme presisering: matcher fortsatt på
+tee-navn, men sjekker nå at den NYE tee-en har en rating for hver berørte
+spillers kjønn, ikke bare at navnet finnes.
+
+**Konsekvens for import/opprettelse:** ADR-019 sin teeoff-import
+(`import_official_course`) lager nå ÉN `tee`-rad per fysisk teeoff-utslag
+(tidligere: to, én per kjønn), med inntil to `tee_rating`-rader under.
+Manuell tee-opprettelse (`POST .../courses/{id}/tees`) redesignet
+tilsvarende: `TeeCreate.ratings` er nå en liste (1-2 elementer, distinkte
+kjønn) i stedet for ett flatt kjønn+rating-sett -- ingen reell
+bruker-/produksjonsdata brukte dette endepunktet fra før (kun Tjøme, som
+er offisielt importert), så ingen bakoverkompatibilitet var nødvendig.
+
+**Migrasjon `014_tee_gender_to_rating.sql`:** flytter `gender` til
+`tee_rating`, slår deretter sammen eksisterende kjønns-par-tee-rader til
+én fysisk tee-rad per (bane, navn) -- velger laveste id som "beholder",
+flytter alle `tee_rating`- og `match_participant.tee_id`-referanser dit,
+sletter duplikatene. Bekreftet TRYGT å kjøre mot ekte data FØR skriving
+(read-only sjekk): alle 8 eksisterende tee-rader (Tjøme) er rene m/f-par,
+ingen `gender='x'`-rader, ingen gruppe med mer enn to rader.
+
+**Scratch-verifisert grundig, flere runder:** (1) selve
+fletting-migrasjonen kjørt mot syntetisk data som gjenskaper Tjøme-
+mønsteret nøyaktig, inkl. én `match_participant`-rad som pekte til
+DUPLIKATEN (ikke beholderen) -- bekreftet korrekt reparert til beholderens
+id etterpå, og et utslag med KUN én rating (ingen duplikat) forblir
+urørt. (2) Manuell tee-opprettelse: to ratinger på ett utslag, kun én
+rating (simulerer "klubben har ikke slopet dette kjønnet"), duplikat
+kjønn i samme innsending avvist. (3) `GET tees` viser riktig sammenslått
+struktur (2 fysiske utslag, ikke 3 rader). (4) `add_participant`: kvinne
++ utslag med dame-rating lykkes; mann + utslag som KUN har dame-rating
+avvist tydelig; spiller uten registrert kjønn avvist tydelig; en full
+kjønnsblandet singel-match scoret korrekt end-to-end. (5) Offisiell
+import kjørt mot EKTE `teeoff_api` (Borregaard Golfklubb) -- bekreftet
+4 fysiske utslag importert med begge kjønnsratinger hver, ikke 8 doble
+rader. (6) `_remap_course`: bane-bytte til en bane UTEN matchende
+kjønnsrating avvist tydelig, bane-bytte til en bane MED matchende
+rating lykket.
+
+**Status: ✅ BYGGET OG SCRATCH-VERIFISERT 2026-07-19, IKKE ENNÅ RULLET UT**
+mot ekte `teecup_db` -- migrasjon 014 endrer ekte produksjonsdata
+(Tjøme-utslagene slås faktisk sammen), venter derfor på eksplisitt
+brukerbekreftelse før den kjøres mot den ekte databasen, i tråd med
+CLAUDE.md sin regel om å alltid vise planen og vente på bekreftelse før
+noe som migrerer ekte data kjøres.
+
+---
+
## Åpne spørsmål (ikke besluttet ennå)
Disse må avklares før eller under de relevante fasene:
diff --git a/CLAUDE.md b/CLAUDE.md
index 51b41cc..ee87039 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -1747,6 +1747,150 @@ Ferdig og verifisert:
Verifisert: `/health`/`dashboard` → 200, `/manifest.webmanifest`/`sw.js`/
`icons/icon-512.png` alle 200 over ekte https, `teeoff.no` upåvirket.
+- **Fire nye hull rapportert fra faktisk testing av blind draw + scorekort
+ (foursome), DIAGNOSTISERT OG NOTERT, IKKE fikset (2026-07-19):** rett
+ etter PWA-runden. Full detalj i FEATURE_BACKLOG.md sin nye seksjon
+ "Rapporterte hull, blind draw + scorekort (2026-07-19)". Kort:
+ 1. **Bekreftet root cause:** valgt spiller forsvinner ikke fra
+ nedtrekkslisten i `AddSlotForm` (`session-blind-draw.tsx`) — den
+ merkes kun `disabled` på `
- {roster.map((p) => (
-
- ))}
+ {roster
+ .filter((p) => !disabledPlayerIds.has(p.id))
+ .map((p) => (
+
+ ))}