diff --git a/dev-docs/UX_SPEC_FESTIVAL_HIERARCHY.md b/dev-docs/UX_SPEC_FESTIVAL_HIERARCHY.md
new file mode 100644
index 00000000..01a12f3e
--- /dev/null
+++ b/dev-docs/UX_SPEC_FESTIVAL_HIERARCHY.md
@@ -0,0 +1,322 @@
+# UX-SPEC: Festival hiërarchie in de GUI
+
+> **Status:** Definitief ontwerp — goedgekeurd door product owner
+> **Datum:** April 2026
+> **Doel:** Specificatie voor de weergave van tijdsloten, secties en shifts
+> binnen de festival/sub-event hiërarchie in `apps/app/`
+
+---
+
+## 1. Ontwerpprincipes
+
+### 1.1 Gebruik de namen van de coördinator, niet de onze
+Groepslabels in dropdowns en lijsten zijn altijd de **daadwerkelijke namen**
+van het festival en de programmaonderdelen (sub-events). Nooit technisch
+jargon als "overkoepelend", "cross_event", "parent", of "festival-level".
+
+De coördinator heeft deze namen zelf ingesteld en herkent ze altijd —
+ongeacht of sub-events dagen, locaties, tracks of edities vertegenwoordigen.
+
+### 1.2 Context-behoud boven technische zuiverheid
+Als een coördinator vanuit sub-event "Vrijdag" op sectie "EHBO" klikt,
+blijft de UI in de Vrijdag-context. De coördinator ziet EHBO-diensten
+relevant voor Vrijdag, met een link om uit te zoomen naar het totaaloverzicht.
+
+### 1.3 Progressieve onthulling via info-tooltips
+De interface is standaard schoon. Op drie vaste plekken staan info-iconen
+(ⓘ) met contextuele uitleg en concrete voorbeelden. Wie het concept snapt,
+klikt er nooit op. Wie het niet snapt, leest één keer en begrijpt het.
+
+### 1.4 Eén patroon, overal herkenbaar
+Het visuele patroon is identiek op elk scherm: eigen items bovenaan
+(prominent), festival-items eronder (iets gedimpt, met festivalnaam als
+groepslabel). Eén patroon leren = overal begrijpen.
+
+### 1.5 Flat events = geen complexiteit tonen
+Bij een enkelvoudig evenement (geen sub-events) worden alle groepslabels,
+info-tooltips en hiërarchie-elementen weggelaten. De dropdown is een platte
+lijst. Geen uitleg nodig — het spreekt voor zich.
+
+---
+
+## 2. Vier dropdown-scenario's
+
+### 2.1 Scenario A — Standaard sectie op een sub-event (meest voorkomend)
+
+**Context:** Bijv. "Bar Schirmbar" binnen "Dag 1 — Vrijdag" van "Echt Feesten 2026"
+
+**Dropdown-inhoud:**
+1. Groepslabel: **[sub-event naam]** (bijv. "Dag 1 — Vrijdag")
+2. Tijdsloten van het sub-event — normale opacity, gesorteerd op start_time
+3. Groepslabel: **[festival naam]** (bijv. "Echt Feesten 2026")
+4. Tijdsloten van het festival — **opacity: 0.65**, gesorteerd op datum + start_time
+
+**API-call:** `GET /events/{sub_event_id}/time-slots?include_parent=true`
+
+**Info-tooltip tekst:**
+> Kies het tijdvenster voor deze dienst. Je ziet de tijdsloten van
+> **[sub-event naam]** en de algemene tijdsloten van **[festival naam]**.
+>
+> **Tip:** voor een reguliere dienst kies je een tijdslot van [sub-event naam].
+> Voor een opbouw- of afbraakdienst kies je een festivaltijdslot.
+
+### 2.2 Scenario B — Festival-brede sectie (cross_event)
+
+**Context:** Bijv. "EHBO" (type=cross_event) bekeken vanuit "Dag 1 — Vrijdag"
+
+**Dropdown-inhoud:**
+1. Groepslabel: **[festival naam]** (bijv. "Echt Feesten 2026")
+2. Festival-level tijdsloten — normale opacity
+3. Groepslabel: **[sub-event 1 naam]** (bijv. "Dag 1 — Vrijdag")
+4. Tijdsloten van sub-event 1
+5. Groepslabel: **[sub-event 2 naam]** (bijv. "Dag 2 — Zaterdag")
+6. Tijdsloten van sub-event 2
+7. *(herhaal voor alle sub-events)*
+
+**API-call:** Festival-level tijdsloten via `GET /events/{festival_id}/time-slots`
+plus tijdsloten van alle sub-events. Dit vereist een nieuwe API-optie of
+een frontend-aggregatie van meerdere calls.
+
+**Aandachtspunt voor implementatie:** de dropdown kan lang worden bij grote
+festivals (3 festival-slots + 4 slots × 5 sub-events = 23 items). De
+groepslabels maken het scanbaar. Overweeg bij > 20 items een zoekfilter
+in de dropdown (Vuetify `v-autocomplete` i.p.v. `v-select`).
+
+**Navigatie-indicator:** toon achter de sectienaam in de breadcrumb een
+chip "festival-breed" zodat de coördinator weet dat deze sectie anders
+werkt dan standaard secties.
+
+**Info-tooltip tekst:**
+> **[sectie naam]** is een festival-brede sectie — actief bij elk
+> programmaonderdeel. Je kunt tijdsloten kiezen van **[festival naam]**
+> en van alle programmaonderdelen.
+>
+> **Tip:** plan diensten per programmaonderdeel (bijv. een showavond)
+> of festival-breed (bijv. opbouw, nachtsecurity).
+
+### 2.3 Scenario C — Flat event (geen sub-events)
+
+**Context:** Bijv. "Braderie Dorpstown 2026" — geen hiërarchie.
+
+**Dropdown-inhoud:** platte lijst, geen groepslabels, geen info-tooltip.
+
+**API-call:** `GET /events/{event_id}/time-slots` (geen include_parent)
+
+### 2.4 Scenario D — Locatie-/track-gebaseerde sub-events
+
+**Context:** Bijv. "Cultuurnacht Rotterdam" met locaties als sub-events.
+
+**Gedrag:** identiek aan scenario A. Het patroon werkt automatisch omdat de
+sub-event namen de locatienamen zijn (bijv. "Theater Walhalla"). De
+groepslabels in de dropdown tonen dan locatienamen i.p.v. dagnamen.
+
+---
+
+## 3. Secties-overzicht
+
+### 3.1 Op een sub-event pagina
+
+Festival-brede secties (type=cross_event) tonen de **festivalnaam** als
+context achter de sectienaam. Standaard secties tonen niets extra.
+
+```
+EHBO · Echt Feesten 2026 4 diensten · 12/16
+Security · Echt Feesten 2026 6 diensten · 18/24
+Bar Schirmbar 8 diensten · 20/24
+Podium crew 3 diensten · 6/9
+```
+
+De festivalnaam achter de sectienaam is voldoende context. Geen badges,
+geen groepen, geen kleuren.
+
+**Info-tooltip (ⓘ bij de secties-header):**
+> Sommige secties zijn **festival-breed**: ze zijn bij elk
+> programmaonderdeel actief en worden centraal beheerd. Je herkent ze
+> aan de festivalnaam achter de sectienaam.
+>
+> **Voorbeeld:** EHBO en Security zijn festival-breed — ze staan bij elk
+> programmaonderdeel. Bar Schirmbar hoort alleen bij [sub-event naam].
+
+### 3.2 Op de festival-pagina
+
+Alle secties getoond: standard secties (operationeel) + cross_event secties.
+Geen speciale markering nodig — alles hoort hier.
+
+### 3.3 Op een flat event
+
+Gewoon een platte lijst. Geen contextlabels nodig.
+
+---
+
+## 4. Tijdsloten-pagina
+
+### 4.1 Op een sub-event pagina
+
+Eén lijst, geen tabs. Boven: eigen tijdsloten (bewerkbaar, CRUD-acties).
+Onder: festival-tijdsloten, gescheiden door een stippellijn met slotje.
+
+```
+[Eigen tijdsloten — bewerkbaar]
+Vrijdag avond — vrijwilliger 18:00 – 02:00 [Bewerken] [Verwijderen]
+Vrijdag avond — crew 17:00 – 03:00 [Bewerken] [Verwijderen]
+
+──── 🔒 Echt Feesten 2026 — alleen-lezen ────
+
+Opbouw vrijdag vr 08:00 – 18:00
+Nachtsecurity vr→za vr 23:00 – za 07:00
+
+→ Beheer tijdsloten van Echt Feesten 2026
+```
+
+### 4.2 Op de festival-pagina
+
+Gewone CRUD-lijst met alle festival-level tijdsloten. Geen read-only
+sectie — alles is bewerkbaar op dit niveau.
+
+### 4.3 Op een flat event
+
+Gewone CRUD-lijst. Geen scheiding, geen read-only sectie.
+
+---
+
+## 5. Navigatiegedrag bij festival-brede secties
+
+### 5.1 Klikken op een festival-brede sectie vanuit sub-event context
+
+De coördinator blijft in de sub-event context. Bovenaan de sectie-view
+staat een context-banner:
+
+```
+Je bekijkt EHBO vanuit Dag 1 — Vrijdag [Bekijk alle diensten →]
+```
+
+De shift-lijst toont:
+- Diensten met een tijdslot van dit sub-event
+- Diensten met een festival-level tijdslot
+- NIET: diensten met tijdsloten van andere sub-events
+
+"Bekijk alle diensten" navigeert naar de sectie op festival-niveau, waar
+alle diensten over alle programmaonderdelen zichtbaar zijn.
+
+### 5.2 Festival-brede sectie op festival-niveau
+
+Alle diensten, gegroepeerd per programmaonderdeel (sub-event naam) + een
+groep voor festival-level diensten. Dit is het "totaaloverzicht" voor de
+EHBO-coördinator.
+
+---
+
+## 6. Implementatie-aantekeningen
+
+### 6.1 Backend
+
+**Bestaande API die werkt:**
+- `GET /events/{event}/time-slots?include_parent=true` — retourneert eigen +
+ parent festival tijdsloten, elk met `source` veld (`own` | `festival`) en
+ `event_name`
+
+**Nieuwe API nodig voor scenario B (cross_event sectie):**
+- Optie 1: Frontend doet meerdere calls (festival + alle sub-events)
+- Optie 2: Nieuw endpoint `GET /events/{festival}/time-slots?include_children=true`
+ dat alle tijdsloten van festival + alle sub-events retourneert
+- **Aanbeveling:** optie 2, met `source` = `own` | `{sub_event_id}` en
+ `event_name` per tijdslot
+
+### 6.2 Frontend — v-autocomplete configuratie
+
+```vue
+
+
+
+
+
+ {{ item.raw.groupName }}
+
+
+
+
+ {{ item.raw.timeRange }}
+
+
+
+
+
+
+ {{ item.raw.name }} · {{ item.raw.timeRange }}
+
+
+```
+
+### 6.3 Frontend — bepalen welk scenario actief is
+
+```typescript
+const dropdownScenario = computed(() => {
+ const event = currentEvent.value
+ const section = currentSection.value
+
+ // Flat event — scenario C
+ if (!event?.parent_event_id && !event?.children?.length) {
+ return 'flat'
+ }
+
+ // Cross_event section — scenario B
+ if (section?.type === 'cross_event') {
+ return 'cross_event'
+ }
+
+ // Standard section on sub-event — scenario A (and D)
+ if (event?.parent_event_id) {
+ return 'sub_event_standard'
+ }
+
+ // Standard section on festival — festival-level, no sub-event slots
+ return 'festival_standard'
+})
+```
+
+### 6.4 Seeder-vereisten
+
+De DevSeeder moet consistent zijn met deze hiërarchie:
+- Festival-level tijdsloten op het parent event (opbouw, afbraak, etc.)
+- Sub-event tijdsloten op elk sub-event (programma-specifiek)
+- Shifts in standard secties → tijdsloten van hun eigen event
+- Shifts in cross_event secties → tijdsloten van het parent festival
+- Geen cross-references naar andere sub-events vanuit standard secties
+
+### 6.5 Info-tooltip component
+
+Herbruikbaar component `InfoTooltip.vue`:
+```vue
+
+
+
+
+
+
+
+
+
+
+```
+
+---
+
+## 7. Toekomstige verbeteringen (niet in scope)
+
+- **ARCH-08:** Recurrence voor tijdsloten ("kopieer naar ander sub-event")
+- Zoekfilter in de dropdown bij > 20 tijdsloten
+- Cross_event sectie per-sub-event activatie toggle (B1 — pas bij vraag)
+- Drag-and-drop herordening van tijdsloten in de dropdown