diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3dc28a8..8c0f973 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -70,6 +70,15 @@ This doc captures the main issues encountered while setting up/running the app l
- **20th session:** Synced Students dojo filter to URL and reset pagination on filter change (with global navigation loader).
- **20th session:** Centralized profile display-name derivation for OAuth and improved profile auto-create/update behavior (role + full_name).
+- **21st session:** Added shimmer-based `Skeleton` UI primitive and global CSS animation for consistent skeleton loading states.
+- **21st session:** Replaced the dashboard root loading screen with a skeleton layout matching the home bento + list surfaces.
+- **21st session:** Added route-level skeleton `loading.tsx` for Entries, Events, Events Browser, and Students.
+
+- **22nd session:** Improved coach “Register athletes” dialog sizing/scrolling to work better on mobile and small viewports.
+- **22nd session:** Made coach register filters/action bar responsive (full-width controls, horizontal scroll where needed) and allowed table horizontal scroll.
+- **22nd session:** Tuned dashboard mobile header stacking (z-index/borders) and reduced mobile drawer width for better content context.
+- **22nd session:** Minor copy polish on dashboard Students metric (“Total Athletes”).
+
## 1) Supabase migration error: `must be owner of table users`
**Symptom**
@@ -4118,3 +4127,90 @@ This session focused on making student management “dojo-aware” end-to-end (d
- `src/lib/auth/profile.ts`
- `src/lib/auth/require-role.ts`
- `src/app/dashboard/events-browser/actions/index.ts`
+
+---
+
+# Session 21 — Skeleton Loading States + Shimmer UI (2026-02-26)
+
+This session focused on improving perceived performance by using skeleton placeholders (instead of blank/spinners) across key dashboard routes.
+
+## 1) Added a `Skeleton` primitive + shimmer animation
+
+**Change**
+- Added a reusable `Skeleton` component backed by a `.shimmer` utility class.
+- Added `.shimmer` styles + keyframes in global CSS for both light and dark theme.
+
+**Where**
+- `src/components/ui/skeleton.tsx`
+- `src/app/globals.css`
+
+---
+
+## 2) Dashboard root loading now matches dashboard layout
+
+**Change**
+- Replaced the previous dashboard loading component with a structured skeleton: page header, bento-style cards, and list rows.
+
+**Where**
+- `src/app/dashboard/loading.tsx`
+
+---
+
+## 3) Added route-level loading skeletons for major dashboard pages
+
+**Change**
+- Added dedicated route-level `loading.tsx` skeletons so each section shows an immediate, layout-accurate placeholder while server components stream.
+
+**Where**
+- `src/app/dashboard/entries/loading.tsx`
+- `src/app/dashboard/events/loading.tsx`
+- `src/app/dashboard/events-browser/loading.tsx`
+- `src/app/dashboard/students/loading.tsx`
+
+---
+
+# Session 22 — Coach Register UX + Mobile Nav Polish (2026-02-26)
+
+This session focused on tightening the coach registration UX on small screens and polishing the dashboard’s mobile navigation/header layering.
+
+## 1) Coach “Register athletes” dialog is viewport-friendly
+
+**Change**
+- Updated the register dialog to use viewport-aware width and max-height, with scrolling enabled so the form stays usable on smaller devices.
+
+**Where**
+- `src/components/coach/coach-dashboard.tsx`
+
+---
+
+## 2) Coach register filters/action bar/table are responsive
+
+**Change**
+- Filters bar now stacks nicely on mobile and uses full-width inputs/selects.
+- Action controls (event day + participation + add) handle narrow screens via horizontal scrolling and tighter button copy.
+- Table container now supports horizontal scrolling with a sensible minimum table width.
+
+**Where**
+- `src/components/coach/coach-student-register.tsx`
+
+---
+
+## 3) Mobile nav + header layering polish
+
+**Change**
+- Reduced mobile drawer width so it doesn’t fully cover the screen on small devices.
+- Increased mobile header z-index and refined border/background styles to prevent overlay/clipping issues.
+
+**Where**
+- `src/components/dashboard/mobile-nav.tsx`
+- `src/components/dashboard/responsive-dashboard-frame.tsx`
+
+---
+
+## 4) Small dashboard copy improvement
+
+**Change**
+- Renamed Students metric helper text from “Total registered” → “Total Athletes”.
+
+**Where**
+- `src/app/dashboard/page.tsx`
diff --git a/src/app/dashboard/entries/loading.tsx b/src/app/dashboard/entries/loading.tsx
new file mode 100644
index 0000000..8215584
--- /dev/null
+++ b/src/app/dashboard/entries/loading.tsx
@@ -0,0 +1,74 @@
+import { Skeleton } from '@/components/ui/skeleton'
+
+export default function EntriesLoading() {
+ return (
+
+ {/* Header section */}
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Stats Overview */}
+
+ {Array.from({ length: 4 }).map((_, i) => (
+
+
+
+
+ ))}
+
+
+ {/* Entries List Area */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Table Skeleton */}
+
+
+
+
+
+
+ {Array.from({ length: 5 }).map((_, i) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+ )
+}
diff --git a/src/app/dashboard/events-browser/loading.tsx b/src/app/dashboard/events-browser/loading.tsx
new file mode 100644
index 0000000..9571c98
--- /dev/null
+++ b/src/app/dashboard/events-browser/loading.tsx
@@ -0,0 +1,69 @@
+import { Skeleton } from '@/components/ui/skeleton'
+
+export default function EventBrowserLoading() {
+ return (
+
+
+
+
+
+
+
+ {/* Approved Events */}
+
+
+
+
+
+
+
+ {Array.from({ length: 2 }).map((_, i) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+ {/* Active Events */}
+
+
+
+
+
+
+
+ {Array.from({ length: 4 }).map((_, i) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+
+
+ )
+}
diff --git a/src/app/dashboard/events/loading.tsx b/src/app/dashboard/events/loading.tsx
new file mode 100644
index 0000000..e9411a4
--- /dev/null
+++ b/src/app/dashboard/events/loading.tsx
@@ -0,0 +1,53 @@
+import { Skeleton } from '@/components/ui/skeleton'
+
+export default function EventsLoading() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ {Array.from({ length: 5 }).map((_, i) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+ {Array.from({ length: 3 }).map((_, i) => (
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+ )
+}
diff --git a/src/app/dashboard/loading.tsx b/src/app/dashboard/loading.tsx
index c464a22..48444e6 100644
--- a/src/app/dashboard/loading.tsx
+++ b/src/app/dashboard/loading.tsx
@@ -1,9 +1,45 @@
-import { DashboardLoading } from '@/components/dashboard/dashboard-loading'
+import { Skeleton } from '@/components/ui/skeleton'
-export default function Loading() {
- return (
-
-
+export default function DashboardLoading() {
+ return (
+
+
+
+
+
+
+ {/* Bento Grid Skeleton */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {Array.from({ length: 4 }).map((_, i) => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ))}
- )
+
+
+ )
}
diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx
index 1640e3f..b2cbae2 100644
--- a/src/app/dashboard/page.tsx
+++ b/src/app/dashboard/page.tsx
@@ -293,7 +293,7 @@ export default async function DashboardPage() {
Students
{studentsCount ?? 0}
-
Total registered
+
Total Athletes
diff --git a/src/app/dashboard/students/loading.tsx b/src/app/dashboard/students/loading.tsx
new file mode 100644
index 0000000..d43b1eb
--- /dev/null
+++ b/src/app/dashboard/students/loading.tsx
@@ -0,0 +1,52 @@
+import { Skeleton } from '@/components/ui/skeleton'
+
+export default function StudentsLoading() {
+ return (
+