﻿# Admin Template Blueprint

Use this file as the single-source prompt/spec when converting another project to match this admin template. The goal is to reproduce the look, layout, behavior, and component patterns of this Laravel admin system without cloning the full project.

## One-Sentence Identity

Build a polished, dense, glassy university/admin dashboard with a sticky left sidebar, compact topbar, token-driven themes, rounded translucent panels, modal CRUD forms, searchable data tables, configurable dashboard widgets, and a premium dark-mode-first feel.

## Tech Stack To Recreate

- Backend/view style: Laravel Blade component architecture.
- CSS: Tailwind CSS with custom `@layer base` and `@layer components`.
- JS: Alpine.js for UI state, Chart.js for dashboard charts, SweetAlert2 for destructive confirmations.
- Build: Vite.
- Font: Instrument Sans from Bunny Fonts, weights 400, 500, 600, 700, 800.
- Icons: inline SVG component in the original, but another project can use Lucide icons if easier. Keep stroke icons, 1.75-2px, simple and rounded.
- Laravel packages used by the original: `spatie/laravel-permission`, `spatie/laravel-activitylog`, `yajra/laravel-datatables-oracle`, `maatwebsite/excel`, `barryvdh/laravel-dompdf`, Laravel Breeze.

## Visual Personality

- Premium admin workspace, not a marketing site.
- Soft glass panels over a subtle gradient app background.
- Compact typography and dense data screens.
- Rounded UI, but controlled: major panels around `24px`, soft cards around `18-20px`, buttons mostly pill-shaped.
- Accent color controls all emphasis. Avoid hard black/white blocks except inside auth illustrations.
- Surfaces should feel layered: app background, shell, sidebar, panel, soft surface, field.
- Use subtle shadows: large blur, low opacity, no harsh drop shadows.
- Most text is restrained. Use short labels, section kickers, and practical descriptions.

## Theme Token System

The template is driven by CSS variables. Recreate these tokens first, then style everything with variables instead of fixed Tailwind colors.

Core variables:

```css
:root {
  color-scheme: light;
  --font-root: 15px;
  --type-kicker: 0.7rem;
  --type-caption: 0.76rem;
  --type-label: 0.84rem;
  --type-body: 0.94rem;
  --type-body-strong: 0.98rem;
  --type-title-sm: 1.08rem;
  --type-title-md: clamp(1.22rem, 1.12rem + 0.25vw, 1.38rem);
  --type-title-lg: clamp(1.35rem, 1.18rem + 0.52vw, 1.72rem);
  --leading-tight: 1.2;
  --leading-body: 1.55;

  --app-bg: #efe4e6;
  --app-bg-gradient:
    radial-gradient(circle at top left, rgba(181, 76, 90, 0.14), transparent 26%),
    radial-gradient(circle at right 12%, rgba(138, 68, 81, 0.12), transparent 28%),
    linear-gradient(180deg, #f8eef0 0%, #ecdfe2 100%);
  --shell-surface: rgba(248, 239, 241, 0.84);
  --sidebar-surface: rgba(243, 232, 235, 0.92);
  --panel-bg: rgba(252, 246, 247, 0.9);
  --panel-soft: rgba(255, 249, 250, 0.74);
  --panel-border: rgba(132, 88, 95, 0.14);
  --text-primary: #3a2328;
  --text-muted: #7b5b61;
  --text-soft: #9b7d83;
  --field-bg: rgba(255, 250, 251, 0.96);
  --field-border: rgba(168, 122, 130, 0.18);
  --field-focus: rgba(181, 76, 90, 0.16);
  --accent: #b54c5a;
  --accent-strong: #963947;
  --accent-contrast: #fff7f8;
  --shadow-color: rgba(72, 37, 44, 0.09);
}
```

Important presets:

- `cleopatra`: default rose/mauve.
- `eelo`: university blue and gold. Light: `--text-primary #1f2a7a`, `--accent #d99528`. Dark: `--app-bg #0c1130`, `--accent #f0a93a`.
- `midnight`: deep blue, electric accent.
- `lagoon`: teal.
- `sakura`: soft blue/gold.
- `citrus`: green/yellow.
- `ember`: muted mauve.

Implement theme switching by setting:

```html
<html data-theme-preset="cleopatra" class="dark">
```

Dark mode is a class on `html`. Preset is a data attribute. Store preview values in localStorage if supporting settings preview.

## Theme Preset Management

The original project includes a full theme preset management system, not just hard-coded CSS presets. Recreate this if the target project needs the same admin experience.

Database model:

- Model: `ThemePreset`.
- Table: `theme_presets`.
- Route key: `slug`.
- Fields: `slug`, `name`, `description`, `keywords`, `swatches`, `light_tokens`, `dark_tokens`, `is_generated`, timestamps.
- Cast `keywords`, `swatches`, `light_tokens`, and `dark_tokens` to arrays; cast `is_generated` to boolean.
- Activity logging records changes to all preset fields.

Token storage shape:

```json
{
  "slug": "red-velvet-vault-1",
  "name": "Red Velvet Vault",
  "description": "Generated from red, luxury, velvet with a balanced dashboard-first contrast system.",
  "keywords": ["red", "luxury", "velvet"],
  "swatches": ["#f5eeee", "#3a2224", "#f3e7e8", "#b84a55"],
  "light_tokens": {
    "app-bg": "#f5eeee",
    "app-bg-gradient": "radial-gradient(...), linear-gradient(...)",
    "shell-surface": "rgba(...)",
    "sidebar-surface": "rgba(...)",
    "panel-bg": "rgba(...)",
    "panel-soft": "rgba(...)",
    "panel-border": "rgba(...)",
    "text-primary": "#...",
    "text-muted": "#...",
    "text-soft": "#...",
    "field-bg": "rgba(...)",
    "field-border": "rgba(...)",
    "field-focus": "rgba(...)",
    "accent": "#...",
    "accent-strong": "#...",
    "accent-contrast": "#...",
    "shadow-color": "rgba(...)"
  },
  "dark_tokens": {
    "...": "same variable keys as light_tokens"
  },
  "is_generated": true
}
```

Settings service responsibilities:

- `themePresets()`: return built-in presets merged with saved custom presets.
- `customPresetLibrary()`: return saved `ThemePreset` records ordered for display.
- `themeModes()`: return `light`, `dark`, and `system`.
- `themePresetStyles()`: generate CSS blocks for saved custom presets, e.g. `html[data-theme-preset='custom-slug'] { --accent: ... }` and `html.dark[data-theme-preset='custom-slug'] { ... }`.
- `saveThemePreset(attributes, replace = false)`: create or optionally replace a saved preset.
- `duplicateThemePreset(preset)`: clone a preset into a new slug/name for editing or reuse.
- `deleteThemePreset(preset)`: remove a saved custom preset.
- `resetThemePresetSelection(deletedSlugs)`: if the active selected preset is deleted, reset the app setting to a safe built-in preset.
- `exportThemePresetPack(slugs = [], includeBuiltIn = false)`: output JSON with selected custom presets and optionally built-ins.
- `importThemePresetPack(payload, replace = false)`: validate and save presets from a JSON pack.

Settings page sections:

- `Branding`: project title, logo upload, favicon upload.
- `Themes`: built-in and custom theme cards. Each card shows name, description, selected chip, and four swatches. Selection is Alpine state, saved through hidden `theme_preset`.
- `Theme mode`: cards for light, dark, and system. Selection is Alpine state, saved through hidden `theme_mode`.
- `Preset studio`: keyword textarea, curated keyword pack cards, candidate count selector, preview button.
- `Preview results`: generated candidate grid with checkbox selection, swatches, keyword chips, and `Replace matching slugs` checkbox.
- `Saved presets`: custom library list with slug chip, Generated/Manual chip, keyword chips, swatches, Duplicate button, and Delete button with destructive confirmation.

Theme card CSS:

```css
.theme-card {
  border: 1px solid var(--panel-border);
  background: color-mix(in srgb, var(--panel-soft) 100%, transparent);
  border-radius: 20px;
  padding: 1rem;
  transition: 150ms ease;
}

.theme-card:hover {
  transform: translateY(-2px);
}

.theme-card-button {
  cursor: pointer;
  text-align: left;
  width: 100%;
}

.theme-card.is-selected {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--panel-soft));
}

.preset-pack-grid,
.preset-preview-grid {
  display: grid;
  gap: 0.9rem;
}

@media (min-width: 640px) {
  .preset-pack-grid,
  .preset-preview-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1280px) {
  .preset-preview-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.preset-pack-card {
  display: block;
  border: 1px solid var(--panel-border);
  border-radius: 20px;
  background: color-mix(in srgb, var(--panel-soft) 100%, transparent);
  padding: 1rem;
  cursor: pointer;
}

.preset-check-indicator {
  display: inline-flex;
  width: 0.9rem;
  height: 0.9rem;
  border-radius: 999px;
  border: 1px solid var(--panel-border);
  background: var(--field-bg);
}

.peer:checked ~ * .preset-check-indicator,
.peer:checked ~ .preset-check-indicator {
  background: var(--accent);
  border-color: var(--accent);
}
```

Preset generator:

- Service: `ThemePresetGeneratorService`.
- It accepts freeform keywords plus curated packs.
- It normalizes keywords, resolves a hue/saturation/lightness profile, generates 1-100 candidate presets, and returns complete light/dark token arrays.
- Generated names combine the keyword with premium words such as `Velvet`, `Signal`, `Atlas`, `Glass`, `Harbor`, `Aurora`, `Summit`, `Orbit`, `Loom`, `Foundry`, `Crown`, `Ember`, plus trailing words such as `Mist`, `Pulse`, `Canvas`, `Vault`, `Drift`, `Thread`, `Studio`, `Current`, `Beacon`, `Grove`, `Flare`, `Field`.
- Curated pack keys: `campus`, `luxury`, `fintech`, `health`, `sunset`, `royal-red`, `deep-ocean`.

Routes/actions to include:

- `PUT admin.settings.update`: saves branding, `theme_preset`, and `theme_mode`.
- `POST admin.settings.theme-presets.preview`: generate candidate presets from keywords/packs/count and flash candidates back to settings page.
- `POST admin.settings.theme-presets.store`: decode generated preset payload, save selected slugs, optionally replace existing matching slugs.
- `POST admin.settings.theme-presets.duplicate`: duplicate a custom preset.
- `DELETE admin.settings.theme-presets.destroy`: delete a custom preset and reset active selection if needed.

Console commands:

```bash
php artisan theme:generate-presets red luxury velvet --count=50 --save=1,4,8
php artisan theme:generate-presets --list-packs
php artisan theme:generate-presets --pack=campus,fintech --count=24 --save=all --replace
php artisan theme:export-presets storage/app/theme-preset-pack.json --include-built-in
php artisan theme:export-presets storage/app/custom-pack.json --slugs=red-velvet-vault-1,atlas-mist-2
php artisan theme:import-presets storage/app/theme-preset-pack.json --replace
php artisan theme:delete-preset red-velvet-vault-1
php artisan theme:delete-preset --all --except=important-slug
```

Runtime injection:

- Load built-in CSS preset blocks from `resources/css/app.css`.
- Load database custom preset CSS using `SettingsService::themePresetStyles()`.
- In `layouts/app.blade.php` and `layouts/guest.blade.php`, inject custom styles after Vite assets:

```blade
@vite(['resources/css/app.css', 'resources/js/app.js'])
@if (! empty($appThemePresetStyles))
    <style>
{!! $appThemePresetStyles !!}
    </style>
@endif
```

Alpine theme settings store:

```js
Alpine.data('themeSettings', (preset = 'cleopatra', mode = 'dark') => ({
  selectedPreset: preset ?? 'cleopatra',
  selectedMode: mode ?? 'dark',
  selectPreset(preset) {
    this.selectedPreset = preset;
    window.applyThemePreference({ mode: this.selectedMode, preset: this.selectedPreset });
  },
  selectMode(mode) {
    this.selectedMode = mode;
    window.applyThemePreference({ mode: this.selectedMode, preset: this.selectedPreset });
  },
}));
```

Important behavior:

- Selecting a theme card previews instantly before saving.
- The real default only changes after saving settings.
- Custom presets must use the exact same token keys as built-ins.
- If a custom preset is deleted while active, reset to `cleopatra` or another safe built-in preset.
- Generated candidates are preview-only until explicitly selected and saved.

## Global Base

```css
html {
  font-size: var(--font-root);
  scroll-behavior: smooth;
}

body {
  background-color: var(--app-bg);
  background-image: var(--app-bg-gradient);
  color: var(--text-primary);
  font-family: "Instrument Sans", sans-serif;
  font-size: var(--type-body);
  line-height: var(--leading-body);
  text-rendering: optimizeLegibility;
}

[x-cloak] {
  display: none !important;
}
```

On smaller screens, reduce root/body font sizes slightly:

- max-width 1023px: `html 14.5px`, `body 14px`.
- max-width 767px: `html 14px`, `body 13.5px`.

## Core Utility Components

Use these class recipes everywhere.

```css
.panel {
  background: color-mix(in srgb, var(--panel-bg) 100%, transparent);
  border: 1px solid var(--panel-border);
  box-shadow: 0 18px 42px -24px var(--shadow-color);
  border-radius: 24px;
  backdrop-filter: blur(12px);
}

.surface-soft {
  background: color-mix(in srgb, var(--panel-soft) 100%, transparent);
  border: 1px solid var(--panel-border);
  border-radius: 20px;
}

.form-input {
  width: 100%;
  margin-top: 0.5rem;
  border-radius: 0.75rem;
  border: 1px solid var(--field-border);
  background: var(--field-bg);
  color: var(--text-primary);
  padding: 0.625rem 0.875rem;
  font-size: var(--type-label);
  line-height: 1.45;
  outline: none;
  transition: 150ms ease;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.35);
}

.form-input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--field-focus);
}

.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  padding: 0.625rem 1rem;
  font-size: var(--type-caption);
  font-weight: 600;
  letter-spacing: 0.02em;
  background: linear-gradient(135deg, var(--accent), var(--accent-strong));
  color: var(--accent-contrast);
  box-shadow: 0 14px 24px -18px var(--shadow-color);
}

.btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  border: 1px solid var(--panel-border);
  padding: 0.625rem 1rem;
  font-size: var(--type-caption);
  font-weight: 600;
  letter-spacing: 0.02em;
  background: color-mix(in srgb, var(--panel-soft) 100%, transparent);
  color: var(--text-primary);
}

.icon-button {
  display: inline-flex;
  width: 2.25rem;
  height: 2.25rem;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  border: 1px solid var(--panel-border);
  background: color-mix(in srgb, var(--panel-soft) 100%, transparent);
  color: var(--text-primary);
}

.icon-label-button {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

.section-kicker {
  color: var(--accent);
  font-size: var(--type-kicker);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.28em;
}

.text-muted {
  color: var(--text-muted);
}
```

Typography classes:

```css
.type-page-title {
  font-size: clamp(1rem, 0.94rem + 0.22vw, 1.2rem) !important;
  line-height: 1.15 !important;
  font-weight: 900;
}

.type-section-title {
  font-size: var(--type-title-md);
  line-height: 1.28;
  font-weight: 900;
}

.type-card-title {
  font-size: var(--type-title-sm);
  line-height: 1.34;
  font-weight: 600;
}

.type-body {
  font-size: var(--type-label);
  line-height: var(--leading-body);
}

.type-meta {
  font-size: var(--type-caption);
  line-height: 1.45;
}
```

## Main App Layout

The layout has these regions:

1. Full-screen `body` with gradient background.
2. Centered app shell: `max-width: 1600px`, min-height screen, flex row, small padding.
3. Sticky desktop sidebar: width `18rem`, hidden below `lg`, class `app-sidebar panel`.
4. Optional sub-sidebar for settings pages: `settings-sub-sidebar panel`, visible at `xl`.
5. Main column: compact topbar plus page content.
6. Mobile sidebar overlay and slide-in sidebar below `lg`.
7. Global loading overlay, toast stack, and CRUD modal mount live at root.

Shell HTML shape:

```html
<div class="min-h-screen">
  <div class="app-shell mx-auto flex min-h-screen max-w-[1600px] gap-4 px-3 py-3 lg:px-5">
    <aside class="app-sidebar panel hidden shrink-0 overflow-hidden lg:flex lg:w-72 lg:flex-col">
      <!-- brand + sidebar links -->
    </aside>

    <div class="flex min-h-screen flex-1 flex-col gap-6">
      <header class="app-topbar panel relative z-40 flex flex-col gap-3 px-3 py-2.5 sm:px-4 sm:py-3 lg:px-5">
        <!-- top row: menu, mobile brand, search, mode toggle, notifications, user menu -->
        <!-- bottom row: page title, breadcrumbs, header actions -->
      </header>

      <main class="space-y-6">
        <!-- page content -->
      </main>
    </div>
  </div>
</div>
```

Topbar behavior:

- Desktop: left menu collapse button, search input, theme toggle, notifications, user menu.
- Mobile: menu opens slide-in sidebar, brand appears in topbar, search becomes icon button with expandable search panel.
- Header bottom row contains page title on left and breadcrumbs/header actions on right.
- Page title is intentionally compact; descriptions inside header are hidden by CSS in the topbar.

## Sidebar

Sidebar is grouped by domain. Each group has a small uppercase kicker and rounded links.

Groups in this project:

- Overview: Dashboard.
- People & access: Users, Roles, Permissions.
- Academic: Faculties, Departments, Programs, Courses, Academic years, Semesters, Classes, Rooms, Grading scales.
- People: Students, Teachers.
- Admissions: Intakes, Applications, Credit transfers.
- Enrollment & Results: Enrollments, Assessments, Result batches, Comprehensive results, Exam permits.
- Finance: Fee heads, Fee schedules, Invoices, Payments, Cashier sessions, Ledger.
- Timetable: Course assignments, Weekly timetable, Exam timetable, Room bookings.
- Attendance: Sessions, Records, Overrides.
- Credentials: ID cards, ID card templates, Transcripts, Certificates, Graduation batches.
- Operations: Complaints, Broadcasts, SMS logs.
- Data migration: Migration reports, Person map, Assessment conflicts.
- Insights: Reports, Intelligence.
- System: Notifications, Activity.
- Account: Profile, Settings.

Sidebar classes:

```css
.app-sidebar {
  background: color-mix(in srgb, var(--sidebar-surface) 100%, transparent);
  position: sticky;
  top: 0.75rem;
  max-height: calc(100vh - 1.5rem);
}

.app-sidebar-scroll {
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--accent) 34%, var(--panel-border)) transparent;
}

.sidebar-group + .sidebar-group {
  border-top: 1px solid color-mix(in srgb, var(--panel-border) 92%, transparent);
  margin-top: 0.5rem;
  padding-top: 0.75rem;
}

.sidebar-group-kicker {
  color: var(--text-soft);
  font-size: 0.68rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  padding: 0 0.5rem 0.5rem;
  font-weight: 700;
}

.sidebar-link {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  border-radius: 0.75rem;
  padding: 0.625rem 0.875rem;
  color: var(--text-muted);
  font-size: var(--type-body-strong);
  font-weight: 600;
}

.sidebar-link:hover {
  background: color-mix(in srgb, var(--panel-soft) 100%, transparent);
  color: var(--text-primary);
}

.sidebar-link-active {
  background: linear-gradient(135deg, var(--accent), var(--accent-strong));
  color: var(--accent-contrast);
  box-shadow: 0 16px 28px -22px var(--shadow-color);
}
```

Pending links are allowed. Mark with `data-pending` and show a tiny `soon` pill.

## Header Search

Search is a pill-shaped input with a circular icon and circular submit button.

```css
.header-search-shell {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 0.5rem;
  border-radius: 999px;
  border: 1px solid var(--panel-border);
  padding: 0.25rem;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--panel-soft) 100%, transparent),
    color-mix(in srgb, var(--panel-bg) 100%, transparent));
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.18), 0 12px 24px -20px var(--shadow-color);
}

.header-search-input {
  min-width: 0;
  width: 100%;
  border: 0;
  background: transparent;
  color: var(--text-primary);
  font-size: var(--type-label);
  outline: none;
}
```

## Dashboard Pattern

The dashboard is widget-based and configurable.

Page header:

- Title: `Dashboard`.
- Subtitle: `Configurable stats, clean charts, and drag-ready widgets.`
- Super Admin action: `Dashboard controls`.

Content states:

- Initial skeleton while Alpine initializes.
- Control panel with widget chips.
- CSS grid canvas with 12 columns.
- Widgets can be full, half, wide, or side.

Widget classes:

```css
.dashboard-canvas {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: repeat(12, minmax(0, 1fr));
}

.dashboard-widget { grid-column: span 12 / span 12; }
.dashboard-widget.is-full { grid-column: span 12 / span 12; }
.dashboard-widget.is-half { grid-column: span 12 / span 12; }
.dashboard-widget.is-wide { grid-column: span 12 / span 12; }

@media (min-width: 1024px) {
  .dashboard-widget.is-half { grid-column: span 6 / span 6; }
  .dashboard-widget.is-wide { grid-column: span 7 / span 7; }
  .dashboard-widget.is-side { grid-column: span 5 / span 5; }
}
```

Dashboard widgets to include:

- Top stats: four stat cards.
- Chart widgets: Chart.js line/bar/pie panels.
- Recent activity.
- Quick actions.
- Intelligence preview.

Stat card shape:

```html
<div class="panel p-6">
  <div class="flex items-start justify-between gap-4">
    <div>
      <p class="section-kicker">Total users</p>
      <p class="mt-3 text-2xl font-black" style="color: var(--text-primary);">128</p>
    </div>
    <span class="inline-flex h-11 w-11 items-center justify-center rounded-2xl border"
      style="border-color: color-mix(in srgb, var(--accent) 18%, var(--panel-border)); background: color-mix(in srgb, var(--accent) 12%, var(--panel-soft)); color: var(--accent);">
      <!-- icon -->
    </span>
  </div>
  <p class="mt-2 text-sm text-muted">Short useful description.</p>
</div>
```

Chart style:

- Use Chart.js.
- Colors come from `--accent`, `--accent-strong`, `--text-primary`, `--text-soft`, plus a couple secondary colors.
- Tooltip background uses `--panel-bg`.
- Axis/grid color uses `--panel-border`.
- Line charts use tension around `0.42`, rounded points, subtle gradient fill.
- Bar charts use rounded bars, max bar thickness around `34`.
- Pie charts have custom legend above chart and optional callout labels.

## Data Table Pages

List pages share this structure:

```html
<x-app-layout>
  <x-slot name="header">
    <div>
      <h1 class="type-page-title" style="color: var(--text-primary);">Users</h1>
      <p class="type-body mt-1 text-muted">Manage accounts, profile images, and role assignments.</p>
    </div>
  </x-slot>

  <div class="panel p-5 sm:p-6">
    <div class="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
      <div>
        <p class="section-kicker">Directory</p>
        <h2 class="type-section-title mt-2" style="color: var(--text-primary);">All users</h2>
      </div>
      <div class="flex flex-col gap-3 sm:flex-row">
        <input type="search" placeholder="Search..." class="form-input mt-0 sm:w-72">
        <div class="flex flex-wrap gap-2">
          <button class="btn-secondary">CSV</button>
          <button class="btn-secondary">Excel</button>
          <button class="btn-secondary">PDF</button>
        </div>
        <a class="btn-primary icon-label-button">Create item</a>
      </div>
    </div>

    <div class="mt-6 overflow-x-auto rounded-3xl border" style="border-color: var(--panel-border);">
      <table class="min-w-[720px] divide-y xl:min-w-full table-shell">
        <!-- compact uppercase header, server-rendered or AJAX body -->
      </table>
    </div>
  </div>
</x-app-layout>
```

Table behavior:

- Server-side AJAX fetching is supported through `window.initServerTable`.
- Search input filters records.
- Headers with `data-column` are sortable.
- Export buttons use `data-export-url`.
- Pagination is rendered below table with Previous/Next rounded buttons.
- Loading rows show an inline spinner.

## CRUD Modal Pattern

Create/edit buttons can open modal forms instead of full pages.

Trigger:

```html
<a href="/admin/users/create" data-modal-url="/admin/users/create" class="btn-primary icon-label-button">
  Create user
</a>
```

Root modal in layout:

```html
<div x-show="modalOpen" x-cloak class="crud-modal-backdrop" @click.self="closeCrudModal()">
  <div class="crud-modal-shell">
    <div class="crud-modal-card panel" x-ref="modalContent"></div>
  </div>
</div>
```

Modal content shape:

```html
<div class="crud-modal-content">
  <div class="crud-modal-header">
    <div>
      <p class="section-kicker">Create user</p>
      <h2 class="mt-2 text-2xl font-black" style="color: var(--text-primary);">New account</h2>
      <p class="mt-2 text-sm text-muted">Add a new record with validation and assignment controls.</p>
    </div>
    <button type="button" class="icon-button" data-modal-close><!-- x icon --></button>
  </div>

  <div class="crud-modal-body">
    <form method="POST" data-modal-form="true" class="space-y-6">
      <!-- form fields -->
    </form>
  </div>
</div>
```

Modal CSS:

```css
.crud-modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 160;
  padding: 1.25rem 0.75rem;
  background: rgba(5, 10, 18, 0.62);
  backdrop-filter: blur(14px);
}

.crud-modal-shell {
  margin: 0 auto;
  display: flex;
  height: 100%;
  max-width: 64rem;
  align-items: center;
  justify-content: center;
}

.crud-modal-card {
  max-height: min(92vh, 960px);
  width: min(100%, 1080px);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.crud-modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  border-bottom: 1px solid color-mix(in srgb, var(--panel-border) 92%, transparent);
  padding: 1.25rem;
}

.crud-modal-body {
  min-height: 0;
  overflow-y: auto;
  padding: 1.25rem;
}
```

Validation:

- Add `data-field-error="field_name"` below each field.
- JS applies `.is-invalid` to failed fields.
- Toast displays the first validation error.

## Form Design Pattern

Forms are not plain vertical fields. They usually include a "smart" side panel or preview.

Example user form:

- Left: avatar preview, name/email/password/image fields.
- Right: role picker panel.
- Password strength meter: track, fill, status pill.
- Role picker: searchable list, selected chips, selected-only filter, summary card.

Useful classes:

```css
.selection-chip {
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  border: 1px solid var(--panel-border);
  background: color-mix(in srgb, var(--panel-soft) 100%, transparent);
  color: var(--text-muted);
  padding: 0.35rem 0.75rem;
  font-size: var(--type-caption);
  font-weight: 700;
}

.selection-chip.is-selected {
  border-color: color-mix(in srgb, var(--accent) 35%, var(--panel-border));
  background: color-mix(in srgb, var(--accent) 14%, var(--panel-soft));
  color: var(--text-primary);
}

.password-meter-track {
  height: 0.5rem;
  overflow: hidden;
  border-radius: 999px;
  background: color-mix(in srgb, var(--panel-soft) 100%, transparent);
}

.password-meter-fill {
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, #d97757, var(--accent));
  transition: width 300ms ease;
}
```

## Auth Layout

Auth pages use a split panel:

- Full viewport centered card.
- Background is the same `--app-bg-gradient`.
- Desktop: left visual/brand panel and right form panel.
- Mobile: brand moves above form; visual hides.
- The left side has animated SVG illustration or custom uploaded image.
- The form uses normal `.form-input`, `.btn-primary`, icon password visibility toggle.

Auth shell:

```html
<div class="relative flex min-h-screen items-center justify-center overflow-hidden px-3 py-6 sm:px-4 sm:py-10">
  <div class="absolute inset-0" style="background: var(--app-bg-gradient);"></div>
  <div class="relative grid w-full max-w-6xl overflow-hidden rounded-[1.5rem] border shadow-2xl backdrop-blur xl:grid-cols-[1.15fr_0.85fr]"
    style="border-color: var(--panel-border); background: color-mix(in srgb, var(--shell-surface) 100%, transparent); box-shadow: 0 34px 80px -42px var(--shadow-color);">
    <div class="hidden p-10 xl:flex xl:flex-col xl:justify-between">
      <!-- brand and illustration -->
    </div>
    <div class="px-5 py-7 sm:px-8 sm:py-8 xl:px-12 xl:py-10" style="background: color-mix(in srgb, var(--panel-bg) 100%, transparent);">
      <div class="mx-auto w-full max-w-md">
        <!-- auth form -->
      </div>
    </div>
  </div>
</div>
```

Login content:

- Kicker: `Admin access`.
- Heading: `Welcome back to {project title}.`
- Text: `Sign in and continue where your work left off.`
- Fields: email, password with visibility icon, remember me, forgot password, primary full-width login button.

## Toasts, Loading, Confirmations

Global loading overlay:

```html
<div class="loading-overlay">
  <div class="loading-card">
    <span class="loader-spinner"></span>
    <p class="text-sm font-semibold">Loading workspace...</p>
  </div>
</div>
```

Toast stack:

- Fixed top-right.
- Width `min(24rem, calc(100vw - 2rem))`.
- Each toast is `.toast-item`, rounded `24px`, panel colors, border.
- Success uses accent border and sparkles/check icon.
- Error uses warm error border.

SweetAlert2:

- Use custom classes `theme-swal-popup`, `theme-swal-title`, `theme-swal-body`, `btn-danger`, `btn-secondary`.
- Confirm destructive actions with `reverseButtons: true` and focus cancel.

## JavaScript Behaviors To Keep

Global helpers:

- `applyThemePreference({ mode, preset })`: sets `html.dataset.themePreset` and toggles dark class.
- `dispatchAppToast(type, message)`.
- `startAppLoading(message)` and `stopAppLoading()`.
- `downloadFile({ url, filename, message })`.
- `confirmDestructiveAction({ title, text })`.
- `initDashboardCharts(configs)`.
- `initServerTable(config)`.

Alpine stores:

- `themeManager`: manages theme mode, preset, mobile nav, mobile search, sidebar collapse, CRUD modal, loading overlay, toasts, password visibility, async forms.
- `dashboardWidgets`: widget visibility, order, dragging, persistence.
- `userForm`: profile image preview and password strength.
- `rolePicker`: searchable multi-role selection.
- `permissionMatrix`: searchable grouped permission toggles.
- `templateEditor`: built-in/custom PDF, Excel, and email template selection with settings/preview tabs and CKEditor-backed rich text for email HTML.
- `dashboardStudioEditor`: editable dashboard stat/chart definitions and auth visual upload previews.
- `resultBatchForm`: derives admission year from selected academic year/class for result batches.
- `pageControls`: show/hide local control panels.

Persist sidebar collapse in localStorage key:

```js
admin-sidebar-collapsed
```

Persist theme preview signature in:

```js
theme-preview-default-signature
```

## Settings Studio Systems

The settings page is not only branding/theme selection. It is a full admin studio with multiple panels. Preserve these major systems.

Settings sub-sidebar:

- On settings pages, use a secondary sticky sidebar via the `subSidebar` slot.
- Sidebar items are numbered pill links pointing to anchors: Branding, Themes, Dashboard studio, Document templates, Email presets, Preset studio, Saved presets, RBAC generator.
- Classes: `settings-sub-sidebar`, `settings-subnav-link`, `settings-subnav-label`, `settings-subnav-index`, `settings-anchor-section`.

Dashboard studio:

- Route: `PUT admin.settings.dashboard-studio.update`.
- Stores `dashboard_stats`, `dashboard_charts`, `auth_login_visual_mode`, `auth_register_visual_mode`, `auth_login_visual_image`, and `auth_register_visual_image`.
- Use `dashboardStudioEditor` Alpine store.
- Stats are editable rows with source, label, description, icon, move up/down, remove, and add stat.
- Charts are editable rows with source, title, description, chart type, audience, move up/down, remove, and add chart.
- Stat sources and chart sources come from `DashboardService`.
- Icon options come from `DashboardService::iconOptions()`.
- Chart types come from `DashboardService::chartTypeOptions()`.
- Hidden inputs store JSON for stats/charts.
- Auth visuals support default animated SVG or custom uploaded image, with live preview in the auth layout.

Document template presets:

- Model/table: `TemplatePreset` and `template_presets`.
- Types: `pdf_header`, `excel_header`, `email`.
- Built-in PDF presets: `executive-crimson`, `scholastic-slate`, `campus-parchment`.
- Built-in Excel presets: `crimson-ledger`, `ocean-sheet`, `bronze-register`.
- Built-in email presets: `welcome-crimson`, `alert-slate`, `campaign-gold`.
- Special dynamic slug: `match-selected-theme`, used to sync document/email styling to the selected app theme.
- PDF fields: kicker, title, subtitle, accent start/end, surface, border, text primary, text muted, heading background, heading text.
- Excel fields: title, subtitle, accent, title text, meta background, meta text, heading background, heading text, body border.
- Email fields: subject, headline, greeting, body HTML, button label, signature, accent, surface.
- Template UI uses `theme-card` preset choices, `selection-chip` tabs for settings/preview, and live preview panels.
- Email body uses CKEditor Classic loaded from CDN only when needed via `window.loadClassicEditor()`.

Template variables documentation:

- Route: `admin.settings.template-documentation`.
- Explain supported tokens: `{{ project_title }}`, `{{ export_title }}`, `{{ export_subtitle }}`, `{{ export_generated_at }}`, `{{ recipient_name }}`, `{{ action_url }}`, `{{ support_email }}`.
- Documentation pages use normal `panel`, `theme-card`, `section-kicker`, `type-section-title`, and `surface-soft` styling.

Dashboard documentation:

- Route: `admin.settings.dashboard-documentation`.
- Shows available stat sources, chart sources, icons, and chart types in theme cards.
- Use this to help admins understand which data powers dashboard widgets.

RBAC generator panel:

- Route: `POST admin.settings.generate`.
- Calls the admin setup/permission generator.
- UI is a visually stronger `generator-card` panel with action row and primary button.
- Sends an admin notification after roles/permissions are regenerated.

## Special Admin Pages

These pages are part of the template personality and should be preserved when the target project has equivalent features.

Reports:

- Route: `admin.reports.index`; exports: `admin.reports.export` with `xlsx` and `pdf`.
- Layout starts with four stat cards, then a two-column grid: filter/export panel on the left, report content on the right.
- Filters: date from and date to.
- Export buttons use `data-download`, `data-download-filename`, and loading messages.
- Report modules use `.module-report-card`.
- Include Chart.js line chart for activity over time and pie chart for role distribution.
- Activity stream groups records by module with `.activity-item`.

Activity report:

- Route: `admin.activity.index`.
- Super Admin only.
- Starts with summary stat cards.
- Filter panel fields: user, module, activity event, date from, date to.
- Result panel uses `.activity-item`, chips for module/event, actor name, record id, timestamp, and pagination.

Search:

- Route: `admin.search.index`.
- Header search submits here.
- Empty state tells the user to start typing in the header search.
- Query state shows three stat panels: Query, Results, Sources.
- Restricted domain notice uses `.notice-card`.
- Results render as grouped panels in a two-column grid. Each group has an accent icon button, section kicker, match count, and clickable `.activity-item` results.

Notifications:

- Routes: notifications index, mark single read, mark all read.
- Topbar bell appears for Super Admin and shows unread count badge.
- Popover lists the five most recent notifications, each in `.surface-soft`, with mark-read actions.
- Notification index should use panel/list styling consistent with activity/search.

Profile:

- Profile page is more polished than a standard Breeze profile.
- It has a large `profile-showcase panel` hero with animated SVG scene, cover chrome, cover badges, brand mark, avatar, identity pills, and stat cards.
- Includes sticky `profile-nav-strip` pills for About, Identity, Security, Account.
- Uses a two-column `profile-layout-grid`: sidebar overview/completion cards and main editable forms.
- Important classes include `profile-showcase`, `profile-showcase-cover`, `profile-showcase-body`, `profile-showcase-main`, `profile-avatar-shell`, `profile-meta-pill`, `profile-showcase-stat`, `profile-nav-pill`, `profile-sidebar-card`, `profile-section-header`, `profile-field-block`, `profile-upload-card`, `profile-danger-card`.
- Preserve account completion progress, role chips, verification status, avatar preview/upload, password/security section, and delete account danger section.

Dashboard intelligence:

- Route: `admin.intelligence.index`.
- Super Admin only.
- Works as a master insight page using stat cards, recommendation panels, activity/report summaries, and the same panel/chip/chart styling.
- Dashboard home can show an intelligence preview widget linking to the full page.

Result batches:

- Result batches are a special bulk-upload workflow, not a simple CRUD page.
- Routes include data, create, show, edit, sample download, upload, row update, clear rows, revalidate, preview, preview PDF, publish, and delete.
- Show page contains summary cards for total/valid/invalid/published, toolbox actions, sample download in `.xlsx` and `.csv`, upload-and-validate form, preview marksheet, revalidate, clear rows, publish valid results, and paginated row table.
- Rows can be edited inline via `form[data-row-form]` and saved with fetch; status/errors update in-place.
- Destructive actions use `data-confirm-delete` and loading messages.
- Result batch form uses `resultBatchForm` to derive admission year from year/class selection.
- Preview pages and PDF preview use the same export/document template branding system.

Exports:

- CSV/XLSX/PDF export links are common across index pages.
- Use `data-export-url` for AJAX table exports and `data-download` for direct download pages.
- Export files should use the selected PDF/Excel header templates via `SettingsService::pdfBranding()` and `SettingsService::excelBranding()`.

Admin notifications:

- `AdminNotificationService` sends system notifications after settings updates, dashboard studio updates, template saves, theme preset saves/deletes/duplicates, and RBAC generation.
- Preserve this feedback loop if the target app has notifications.

## Page Recipe For Any New Module

For every admin module, create these views:

- `index`: panel with title, search, export buttons, create button, AJAX table.
- `create`: full-page form in a panel, also reusable by modal.
- `edit`: same as create with existing values.
- `show`: profile/detail page with hero or overview panel and metadata cards.
- `_form`: reusable form partial.
- `partials/modal-form`: CRUD modal wrapper.
- `partials/name-cell`: rich table identity cell with title and subtitle.
- `partials/status-cell`: rounded status chip.
- `partials/actions`: icon buttons for view/edit/delete.

Index page copy pattern:

- Header title: plural module name.
- Header subtitle: one sentence about managing the resource.
- Inner kicker: module category, e.g. `Directory`, `Academic`, `Finance`.
- Inner heading: `All {resources}`.
- Search placeholder: `Search {resources}...`.
- Export buttons: CSV, Excel, PDF.
- Create button: `Create {resource}` with plus icon.

## Permissions And Visibility

The original uses role/permission gates heavily:

- `@role('Super Admin')` for system-wide admin features.
- `@can('read-user')`, `@can('create-user')`, etc. for CRUD access.
- Sidebar groups only show when the user can read those modules.
- Dashboard controls and sensitive widgets are Super Admin only.

When adapting to another project, map these to the project's permission system but keep the same visibility behavior.

## Responsive Rules

- Desktop sidebar hidden below `lg`; mobile sidebar slides from left with dark overlay.
- Content uses `space-y-6`.
- Panels use `p-5 sm:p-6`.
- Toolbars stack on mobile, become row layouts at `md` or `sm`.
- Tables always live inside `overflow-x-auto`; minimum width around `720px`.
- Dashboard grid is one column on mobile and 12-column at desktop.
- Header actions must not wrap awkwardly. Use compact labels on mobile and full labels on larger screens.

## Exact Design Do/Don't

Do:

- Use CSS variables everywhere.
- Use `color-mix()` for soft variants.
- Use uppercase letter-spaced kickers.
- Put important content in `.panel`, secondary content in `.surface-soft`.
- Use compact but readable type.
- Prefer icon buttons for tiny actions.
- Use modal CRUD for quick create/edit.
- Keep pages operational and dense.

Do not:

- Build a marketing landing page as the admin home.
- Use hard-coded slate/gray Tailwind colors for new UI except inside temporary legacy table markup.
- Make giant hero sections inside admin pages.
- Add decorative gradient blobs beyond the subtle background gradients.
- Nest many cards inside cards. Use panels for sections and small cards only for repeated data items.
- Make text large just because there is space.

## Minimal Files Another AI Should Create Or Modify

If porting this template to another Laravel project, ask the AI to create/modify:

- `resources/css/app.css`: token system and component classes.
- `tailwind.config.js`: dark mode class, Instrument Sans.
- `resources/js/app.js`: Alpine stores, Chart.js setup, server table, modal CRUD, toasts/loading.
- `resources/views/layouts/app.blade.php`: admin shell.
- `resources/views/layouts/guest.blade.php`: auth shell.
- `resources/views/components/icon.blade.php`: icons or replace with Lucide.
- `resources/views/components/stat-card.blade.php`.
- `resources/views/components/breadcrumbs.blade.php`.
- `resources/views/components/admin/sidebar-links.blade.php`.
- `resources/views/components/admin/user-menu.blade.php`.
- `resources/views/components/avatar.blade.php`, alert, modal, input, dropdown, nav, and button components.
- `resources/views/profile/edit.blade.php` plus profile partials.
- `resources/views/admin/dashboard.blade.php`, `reports`, `search`, `activity`, `notifications`, `intelligence`, `settings`, and `result-batches` special pages.
- Admin module views following the page recipe.
- `app/Models/ThemePreset.php` and `database/migrations/*create_theme_presets_table.php`.
- `app/Models/TemplatePreset.php` and `database/migrations/*create_template_presets_table.php`.
- `app/Models/UserDashboardPreference.php` and dashboard preference migrations for widget state, layout, and drag setting.
- `app/Services/SettingsService.php`, `DashboardService.php`, `ThemePresetGeneratorService.php`, `PermissionGeneratorService.php`, `ReportsService.php`, `AdminNotificationService.php`, `AdminDataExportService.php`.
- `app/Http/Controllers/Admin/SettingsController.php`, `DashboardController.php`, `DashboardPreferenceController.php`, `DashboardIntelligenceController.php`, `ReportsController.php`, `SearchController.php`, `ActivityReportController.php`, `NotificationController.php`, `DataExportController.php`.
- Request classes for settings, dashboard studio, document templates, email templates, theme generation, and generated preset storage.
- Console commands: `app:setup-admin`, `theme:generate-presets`, `theme:import-presets`, `theme:export-presets`, `theme:delete-preset`.
- Middleware: no-back-history behavior and any idempotency middleware if keeping safe form submissions.
- Routes for dashboard widgets, search, reports exports, notifications, settings studio, theme presets, document/email templates, dashboard documentation, template documentation, and every admin CRUD module.

## Completion Checklist

Before considering the template recreated, verify these are present:

- App shell has desktop sidebar, mobile sidebar, topbar search, theme toggle, notification popover, user menu, breadcrumbs, header actions, global loading overlay, toast stack, and CRUD modal mount.
- CSS variables cover every token in `THEME_TOKEN_KEYS` for light and dark.
- Built-in presets and saved database presets both work through `data-theme-preset`.
- Settings can save branding, default preset, theme mode, dashboard studio config, auth visuals, PDF/Excel/email templates, generated theme presets, duplicate/delete presets, and RBAC generation.
- Dashboard supports stat cards, Chart.js widgets, controls panel, widget visibility, drag order, skeleton loading, quick actions, activity, and intelligence preview.
- CRUD pages support index data table, search, export, create/edit modal, show page, reusable form, status/name/actions cells, and permissions.
- Special pages exist for reports, search, activity, notifications, intelligence, profile, and result batches.
- Auth pages use split layout, animated/default visual or custom uploaded image, password visibility, and shared theme tokens.
- Exports use selected document templates and branded PDF/Excel headers.
- Commands exist for setup admin and theme preset import/export/generate/delete.
- Responsive behavior is checked on mobile and desktop.

## Prompt To Give Another AI

Paste this:

> Convert my project admin UI to match the attached Admin Template Blueprint exactly. Recreate the full admin template, not only the colors: token-driven glassy shell, sticky sidebar groups, compact topbar with search/theme/user menu, notification popover, breadcrumbs, panel/surface/button/form classes, modal CRUD, dashboard widgets and dashboard studio, theme preset management, document/email template presets, branded exports, reports/search/activity/notifications/intelligence/profile pages, result-batch workflow, AJAX tables, toasts/loading/SweetAlert behavior, and split auth layout. Keep my project's data models and routes where possible, but change the views, CSS, JS, services, settings, and routes needed to follow the blueprint. Use CSS variables and `data-theme-preset`/`.dark` theme behavior. Every admin module should use the same index/create/edit/show/form/modal partial structure described in the blueprint.
