diff --git a/docs/architecture.md b/docs/architecture.md
new file mode 100644
index 0000000..b6fadf5
--- /dev/null
+++ b/docs/architecture.md
@@ -0,0 +1,3156 @@
+# Libra Law Firm - Architecture Document
+
+**Version:** 1.1
+**Date:** December 21, 2025
+**Status:** Approved
+**Domain:** libra.ps
+
+---
+
+## Change Log
+
+| Date | Version | Description | Author |
+|------|---------|-------------|--------|
+| Dec 21, 2025 | 1.0 | Initial architecture document | Winston (Architect) |
+| Dec 21, 2025 | 1.1 | Added CI/CD, rollback procedures, monitoring, timezone handling, alternatives analysis | Winston (Architect) |
+
+---
+
+## Table of Contents
+
+1. [Introduction](#1-introduction)
+2. [High Level Architecture](#2-high-level-architecture)
+3. [Technology Stack](#3-technology-stack)
+4. [Data Models](#4-data-models)
+5. [Database Schema](#5-database-schema)
+6. [Application Structure](#6-application-structure)
+7. [Authentication & Authorization](#7-authentication--authorization)
+8. [Core Workflows](#8-core-workflows)
+9. [Routing Structure](#9-routing-structure)
+10. [Email System](#10-email-system)
+11. [Background Jobs & Scheduling](#11-background-jobs--scheduling)
+12. [Localization & Timezone](#12-localization--timezone)
+13. [Security](#13-security)
+14. [Testing Strategy](#14-testing-strategy)
+15. [Performance & Optimization](#15-performance--optimization)
+16. [Deployment & CI/CD](#16-deployment--cicd)
+17. [Monitoring & Alerting](#17-monitoring--alerting)
+18. [Error Handling & Graceful Degradation](#18-error-handling--graceful-degradation)
+19. [Rollback & Recovery Procedures](#19-rollback--recovery-procedures)
+20. [Coding Standards](#20-coding-standards)
+21. [Technology Alternatives Considered](#21-technology-alternatives-considered)
+22. [Appendices](#22-appendices)
+
+---
+
+## 1. Introduction
+
+### 1.1 Purpose
+
+This document outlines the complete architecture for Libra Law Firm's web platform. It serves as the single source of truth for development, ensuring consistency and guiding AI-driven implementation.
+
+### 1.2 Project Overview
+
+Libra Law Firm is a bilingual (Arabic/English) Laravel application serving as both a public-facing website and internal management tool for:
+- Client consultation booking and management
+- Case timeline tracking
+- Legal content publishing
+- Administrative operations
+
+### 1.3 Key Constraints
+
+| Constraint | Details |
+|------------|---------|
+| Single Admin | One lawyer manages all operations |
+| No Online Payments | All payments handled offline |
+| Client-Managed Infrastructure | Rocky Linux 9 server |
+| No Self-Registration | Admin creates all client accounts |
+| Bilingual Requirement | Arabic (RTL) primary, English (LTR) secondary |
+
+### 1.4 Project Context
+
+**Existing Foundation:**
+- Laravel 12.43.1 with Fortify authentication
+- Livewire 3.7.3 + Volt 1.10.1 for reactive components
+- Flux UI Free 2.10.2 component library
+- Tailwind CSS 4.1.11
+- Pest 4.2.0 testing framework
+
+---
+
+## 2. High Level Architecture
+
+### 2.1 Technical Summary
+
+Libra is a **server-rendered Laravel monolith** with Livewire for reactive UI. The architecture follows Laravel's MVC pattern enhanced with:
+
+- **Livewire 3 + Volt** for interactive components without JavaScript complexity
+- **Fortify** for headless authentication with custom Volt views
+- **Eloquent ORM** for database operations
+- **Blade + Flux UI** for consistent, accessible component design
+- **Queue workers** for background email processing and scheduled reminders
+
+This architecture prioritizes **simplicity and maintainability** over distributed complexity.
+
+### 2.2 System Context Diagram
+
+```mermaid
+graph TB
+ subgraph "Users"
+ Admin[Admin/Lawyer]
+ Client[Clients]
+ Public[Public Visitors]
+ end
+
+ subgraph "Libra Platform"
+ App[Laravel Application
libra.ps]
+ end
+
+ subgraph "External Services"
+ SMTP[SMTP Server
no-reply@libra.ps]
+ end
+
+ subgraph "Infrastructure"
+ Server[Rocky Linux 9
Client-Managed]
+ end
+
+ Admin -->|Manage users, bookings,
timelines, posts| App
+ Client -->|Book consultations,
view timelines| App
+ Public -->|View posts,
firm info| App
+
+ App -->|Send emails| SMTP
+ App -->|Deployed on| Server
+```
+
+### 2.3 Container Diagram
+
+```mermaid
+graph TB
+ subgraph "Client Devices"
+ Browser[Web Browser]
+ Mobile[Mobile Browser]
+ end
+
+ subgraph "Web Server - Nginx"
+ Static[Static Assets
CSS/JS/Images]
+ PHP[PHP-FPM 8.4]
+ end
+
+ subgraph "Laravel Application"
+ Router[Route Handler]
+ MW[Middleware Stack
Auth, Locale, CSRF]
+
+ subgraph "Presentation Layer"
+ Volt[Volt Components]
+ Flux[Flux UI Components]
+ Blade[Blade Templates]
+ end
+
+ subgraph "Business Logic Layer"
+ Actions[Action Classes]
+ Fortify[Fortify Auth]
+ Policies[Authorization Policies]
+ end
+
+ subgraph "Data Access Layer"
+ Models[Eloquent Models]
+ Observers[Model Observers]
+ end
+ end
+
+ subgraph "Background Processing"
+ Queue[Queue Worker
Supervisor]
+ Scheduler[Task Scheduler
Cron]
+ end
+
+ subgraph "Data Storage"
+ MariaDB[(MariaDB
Production)]
+ SQLite[(SQLite
Development)]
+ FileStorage[Local Storage
Exports/Logs]
+ end
+
+ subgraph "External"
+ SMTP[SMTP Server]
+ end
+
+ Browser --> Static
+ Browser --> PHP
+ Mobile --> Static
+ Mobile --> PHP
+
+ PHP --> Router
+ Router --> MW
+ MW --> Volt
+ MW --> Blade
+ Volt --> Flux
+ Volt --> Actions
+ Actions --> Fortify
+ Actions --> Policies
+ Actions --> Models
+ Models --> Observers
+ Models --> MariaDB
+ Models --> SQLite
+
+ Queue --> Actions
+ Queue --> SMTP
+ Scheduler --> Queue
+ Actions --> FileStorage
+```
+
+### 2.4 Architectural Patterns
+
+| Pattern | Description | Rationale |
+|---------|-------------|-----------|
+| **MVC + Livewire** | Laravel MVC with Livewire reactive components | Standard Laravel pattern; eliminates need for separate SPA |
+| **Action Classes** | Single-purpose classes for business logic | Keeps controllers thin; reusable; testable |
+| **Form Objects** | Livewire form objects for validation | Encapsulates validation; reusable forms |
+| **Observer Pattern** | Eloquent observers for model events | Automatic audit logging, notification triggers |
+| **Queue-based Processing** | Background jobs for emails and heavy operations | Non-blocking UX; reliable delivery |
+| **Policy-based Authorization** | Laravel Policies for access control | Clean separation of authorization logic |
+| **Repository Pattern** | Optional for complex queries | Only if query complexity warrants |
+
+---
+
+## 3. Technology Stack
+
+### 3.1 Core Technologies
+
+| Category | Technology | Version | Purpose | Rationale |
+|----------|------------|---------|---------|-----------|
+| **Runtime** | PHP | 8.4.x | Server-side language | Latest stable; required by Laravel 12 |
+| **Framework** | Laravel | 12.x | Application framework | Industry standard; excellent ecosystem |
+| **Reactive UI** | Livewire | 3.7.x | Interactive components | No JS build complexity; server-state |
+| **Components** | Volt | 1.10.x | Single-file components | Cleaner organization; class-based |
+| **UI Library** | Flux UI Free | 2.10.x | Pre-built components | Consistent design; accessibility |
+| **CSS** | Tailwind CSS | 4.x | Utility-first styling | Rapid development; RTL support |
+| **Auth** | Laravel Fortify | 1.33.x | Headless auth | Flexible; 2FA support |
+| **Database (Prod)** | MariaDB | 10.11+ | Production database | MySQL-compatible; performant |
+| **Database (Dev)** | SQLite | Latest | Development database | Zero config; fast tests |
+| **Testing** | Pest | 4.x | Testing framework | Elegant syntax; Laravel integration |
+| **Code Style** | Laravel Pint | 1.x | Code formatting | Consistent style |
+| **Queue** | Database Driver | - | Job processing | Simple; no Redis dependency |
+
+### 3.2 Frontend Dependencies
+
+| Package | Version | Purpose |
+|---------|---------|---------|
+| Alpine.js | (via Livewire) | Minimal JS interactivity |
+| Vite | 6.x | Asset bundling |
+| Google Fonts | - | Cairo (Arabic), Montserrat (English) |
+| Heroicons | (via Flux) | Icon library |
+
+### 3.3 Backend Dependencies (To Add)
+
+| Package | Version | Purpose |
+|---------|---------|---------|
+| `barryvdh/laravel-dompdf` | ^3.0 | PDF export generation |
+| `league/csv` | ^9.0 | CSV export generation |
+| `spatie/icalendar-generator` | ^2.0 | .ics calendar file generation |
+
+### 3.4 Development Dependencies
+
+| Package | Purpose |
+|---------|---------|
+| Laravel Sail | Docker development environment (optional) |
+| Laravel Telescope | Debug assistant (dev only) |
+| Laravel Pint | Code formatting |
+
+---
+
+## 4. Data Models
+
+### 4.1 Entity Relationship Diagram
+
+```mermaid
+erDiagram
+ users ||--o{ consultations : "has many"
+ users ||--o{ timelines : "has many"
+ users ||--o{ notifications : "has many"
+ timelines ||--o{ timeline_updates : "has many"
+ users ||--o{ admin_logs : "performed by"
+
+ users {
+ bigint id PK
+ enum user_type "individual|company|admin"
+ string full_name
+ string national_id "nullable, encrypted"
+ string company_name "nullable"
+ string company_cert_number "nullable"
+ string contact_person_name "nullable"
+ string contact_person_id "nullable"
+ string email UK
+ string phone
+ string password "hashed"
+ enum status "active|deactivated"
+ string preferred_language "ar|en"
+ timestamp email_verified_at
+ text two_factor_secret "nullable"
+ text two_factor_recovery_codes "nullable"
+ timestamp two_factor_confirmed_at
+ timestamps created_updated
+ }
+
+ consultations {
+ bigint id PK
+ bigint user_id FK
+ date booking_date
+ time booking_time
+ text problem_summary
+ enum consultation_type "free|paid"
+ decimal payment_amount "nullable"
+ enum payment_status "pending|received|na"
+ enum status "pending|approved|rejected|completed|no_show|cancelled"
+ text admin_notes "nullable"
+ timestamps created_updated
+ }
+
+ timelines {
+ bigint id PK
+ bigint user_id FK
+ string case_name
+ string case_reference "nullable"
+ enum status "active|archived"
+ timestamps created_updated
+ }
+
+ timeline_updates {
+ bigint id PK
+ bigint timeline_id FK
+ bigint admin_id FK
+ text update_text
+ timestamps created_updated
+ }
+
+ posts {
+ bigint id PK
+ json title "ar and en"
+ json body "ar and en"
+ enum status "draft|published"
+ timestamp published_at "nullable"
+ timestamps created_updated
+ }
+
+ working_hours {
+ bigint id PK
+ tinyint day_of_week "0-6 Sunday-Saturday"
+ time start_time
+ time end_time
+ boolean is_active
+ }
+
+ blocked_times {
+ bigint id PK
+ date block_date
+ time start_time "nullable for full day"
+ time end_time "nullable for full day"
+ string reason "nullable"
+ timestamps created_updated
+ }
+
+ notifications {
+ bigint id PK
+ bigint user_id FK
+ string type
+ json data
+ timestamp read_at "nullable"
+ timestamp sent_at "nullable"
+ timestamps created_updated
+ }
+
+ admin_logs {
+ bigint id PK
+ bigint admin_id FK
+ string action
+ string target_type
+ bigint target_id "nullable"
+ json old_values "nullable"
+ json new_values "nullable"
+ string ip_address
+ timestamp created_at
+ }
+
+ settings {
+ bigint id PK
+ string key UK
+ json value
+ timestamps created_updated
+ }
+```
+
+### 4.2 Model Definitions
+
+#### User Model
+
+```php
+// app/Models/User.php
+class User extends Authenticatable
+{
+ use HasFactory, Notifiable, TwoFactorAuthenticatable;
+
+ protected $fillable = [
+ 'user_type',
+ 'full_name',
+ 'national_id',
+ 'company_name',
+ 'company_cert_number',
+ 'contact_person_name',
+ 'contact_person_id',
+ 'email',
+ 'phone',
+ 'password',
+ 'status',
+ 'preferred_language',
+ ];
+
+ protected $hidden = [
+ 'password',
+ 'remember_token',
+ 'two_factor_secret',
+ 'two_factor_recovery_codes',
+ ];
+
+ protected function casts(): array
+ {
+ return [
+ 'user_type' => UserType::class,
+ 'status' => UserStatus::class,
+ 'email_verified_at' => 'datetime',
+ 'two_factor_confirmed_at' => 'datetime',
+ 'password' => 'hashed',
+ ];
+ }
+
+ // Relationships
+ public function consultations(): HasMany;
+ public function timelines(): HasMany;
+ public function notifications(): HasMany;
+ public function adminLogs(): HasMany;
+
+ // Scopes
+ public function scopeActive(Builder $query): Builder;
+ public function scopeClients(Builder $query): Builder;
+ public function scopeIndividuals(Builder $query): Builder;
+ public function scopeCompanies(Builder $query): Builder;
+
+ // Helpers
+ public function isAdmin(): bool;
+ public function isClient(): bool;
+ public function isIndividual(): bool;
+ public function isCompany(): bool;
+ public function canBookOnDate(Carbon $date): bool;
+ public function hasBookingOnDate(Carbon $date): bool;
+}
+```
+
+#### Consultation Model
+
+```php
+// app/Models/Consultation.php
+class Consultation extends Model
+{
+ use HasFactory;
+
+ protected $fillable = [
+ 'user_id',
+ 'booking_date',
+ 'booking_time',
+ 'problem_summary',
+ 'consultation_type',
+ 'payment_amount',
+ 'payment_status',
+ 'status',
+ 'admin_notes',
+ ];
+
+ protected function casts(): array
+ {
+ return [
+ 'booking_date' => 'date',
+ 'booking_time' => 'datetime:H:i',
+ 'consultation_type' => ConsultationType::class,
+ 'payment_status' => PaymentStatus::class,
+ 'status' => ConsultationStatus::class,
+ 'payment_amount' => 'decimal:2',
+ ];
+ }
+
+ // Relationships
+ public function user(): BelongsTo;
+
+ // Scopes
+ public function scopePending(Builder $query): Builder;
+ public function scopeApproved(Builder $query): Builder;
+ public function scopeUpcoming(Builder $query): Builder;
+ public function scopeForDate(Builder $query, Carbon $date): Builder;
+ public function scopeForDateRange(Builder $query, Carbon $start, Carbon $end): Builder;
+
+ // Accessors
+ public function getEndTimeAttribute(): Carbon;
+ public function getStartDateTimeAttribute(): Carbon;
+ public function getEndDateTimeAttribute(): Carbon;
+
+ // Helpers
+ public function isPaid(): bool;
+ public function isPending(): bool;
+ public function canBeApproved(): bool;
+ public function canBeCancelled(): bool;
+}
+```
+
+#### Timeline Model
+
+```php
+// app/Models/Timeline.php
+class Timeline extends Model
+{
+ use HasFactory;
+
+ protected $fillable = [
+ 'user_id',
+ 'case_name',
+ 'case_reference',
+ 'status',
+ ];
+
+ protected function casts(): array
+ {
+ return [
+ 'status' => TimelineStatus::class,
+ ];
+ }
+
+ // Relationships
+ public function user(): BelongsTo;
+ public function updates(): HasMany;
+ public function latestUpdate(): HasOne;
+
+ // Scopes
+ public function scopeActive(Builder $query): Builder;
+ public function scopeArchived(Builder $query): Builder;
+ public function scopeForUser(Builder $query, User $user): Builder;
+}
+```
+
+#### Post Model
+
+```php
+// app/Models/Post.php
+class Post extends Model
+{
+ use HasFactory;
+
+ protected $fillable = [
+ 'title',
+ 'body',
+ 'status',
+ 'published_at',
+ ];
+
+ protected function casts(): array
+ {
+ return [
+ 'title' => 'array',
+ 'body' => 'array',
+ 'status' => PostStatus::class,
+ 'published_at' => 'datetime',
+ ];
+ }
+
+ // Accessors for localized content
+ public function getTitleLocalizedAttribute(): string;
+ public function getBodyLocalizedAttribute(): string;
+
+ // Scopes
+ public function scopePublished(Builder $query): Builder;
+ public function scopeDraft(Builder $query): Builder;
+
+ // Helpers
+ public function isPublished(): bool;
+}
+```
+
+### 4.3 Enums
+
+```php
+// app/Enums/UserType.php
+enum UserType: string
+{
+ case Individual = 'individual';
+ case Company = 'company';
+ case Admin = 'admin';
+
+ public function label(): string
+ {
+ return match($this) {
+ self::Individual => __('enums.user_type.individual'),
+ self::Company => __('enums.user_type.company'),
+ self::Admin => __('enums.user_type.admin'),
+ };
+ }
+}
+
+// app/Enums/UserStatus.php
+enum UserStatus: string
+{
+ case Active = 'active';
+ case Deactivated = 'deactivated';
+}
+
+// app/Enums/ConsultationType.php
+enum ConsultationType: string
+{
+ case Free = 'free';
+ case Paid = 'paid';
+}
+
+// app/Enums/ConsultationStatus.php
+enum ConsultationStatus: string
+{
+ case Pending = 'pending';
+ case Approved = 'approved';
+ case Rejected = 'rejected';
+ case Completed = 'completed';
+ case NoShow = 'no_show';
+ case Cancelled = 'cancelled';
+
+ public function color(): string
+ {
+ return match($this) {
+ self::Pending => 'yellow',
+ self::Approved => 'blue',
+ self::Rejected => 'red',
+ self::Completed => 'green',
+ self::NoShow => 'gray',
+ self::Cancelled => 'red',
+ };
+ }
+}
+
+// app/Enums/PaymentStatus.php
+enum PaymentStatus: string
+{
+ case Pending = 'pending';
+ case Received = 'received';
+ case NotApplicable = 'na';
+}
+
+// app/Enums/TimelineStatus.php
+enum TimelineStatus: string
+{
+ case Active = 'active';
+ case Archived = 'archived';
+}
+
+// app/Enums/PostStatus.php
+enum PostStatus: string
+{
+ case Draft = 'draft';
+ case Published = 'published';
+}
+```
+
+---
+
+## 5. Database Schema
+
+### 5.1 Migration Order
+
+1. `0001_01_01_000000_create_users_table.php` (modify existing)
+2. `0001_01_01_000001_create_cache_table.php` (existing)
+3. `0001_01_01_000002_create_jobs_table.php` (existing)
+4. `2025_01_01_000001_add_profile_fields_to_users_table.php`
+5. `2025_01_01_000002_create_consultations_table.php`
+6. `2025_01_01_000003_create_timelines_table.php`
+7. `2025_01_01_000004_create_timeline_updates_table.php`
+8. `2025_01_01_000005_create_posts_table.php`
+9. `2025_01_01_000006_create_working_hours_table.php`
+10. `2025_01_01_000007_create_blocked_times_table.php`
+11. `2025_01_01_000008_create_notifications_table.php`
+12. `2025_01_01_000009_create_admin_logs_table.php`
+13. `2025_01_01_000010_create_settings_table.php`
+
+### 5.2 Key Migration Examples
+
+#### Users Table Extension
+
+```php
+// database/migrations/2025_01_01_000001_add_profile_fields_to_users_table.php
+public function up(): void
+{
+ Schema::table('users', function (Blueprint $table) {
+ $table->string('user_type')->default('individual')->after('id');
+ $table->string('full_name')->nullable()->after('name');
+ $table->string('national_id')->nullable()->after('full_name');
+ $table->string('company_name')->nullable()->after('national_id');
+ $table->string('company_cert_number')->nullable()->after('company_name');
+ $table->string('contact_person_name')->nullable()->after('company_cert_number');
+ $table->string('contact_person_id')->nullable()->after('contact_person_name');
+ $table->string('phone', 20)->nullable()->after('email');
+ $table->string('status')->default('active')->after('password');
+ $table->string('preferred_language', 2)->default('ar')->after('status');
+
+ $table->index('user_type');
+ $table->index('status');
+ $table->index(['user_type', 'status']);
+ });
+}
+```
+
+#### Consultations Table
+
+```php
+// database/migrations/2025_01_01_000002_create_consultations_table.php
+public function up(): void
+{
+ Schema::create('consultations', function (Blueprint $table) {
+ $table->id();
+ $table->foreignId('user_id')->constrained()->cascadeOnDelete();
+ $table->date('booking_date');
+ $table->time('booking_time');
+ $table->text('problem_summary');
+ $table->string('consultation_type')->default('free');
+ $table->decimal('payment_amount', 10, 2)->nullable();
+ $table->string('payment_status')->default('na');
+ $table->string('status')->default('pending');
+ $table->text('admin_notes')->nullable();
+ $table->timestamps();
+
+ $table->index('booking_date');
+ $table->index('status');
+ $table->index(['booking_date', 'booking_time']);
+ $table->unique(['user_id', 'booking_date']); // One booking per user per day
+ });
+}
+```
+
+#### Working Hours Table
+
+```php
+// database/migrations/2025_01_01_000006_create_working_hours_table.php
+public function up(): void
+{
+ Schema::create('working_hours', function (Blueprint $table) {
+ $table->id();
+ $table->tinyInteger('day_of_week')->unsigned(); // 0=Sunday, 6=Saturday
+ $table->time('start_time');
+ $table->time('end_time');
+ $table->boolean('is_active')->default(true);
+
+ $table->unique('day_of_week');
+ });
+}
+```
+
+### 5.3 Indexes Strategy
+
+| Table | Index | Columns | Purpose |
+|-------|-------|---------|---------|
+| users | user_type_status | user_type, status | Filter clients |
+| consultations | booking_date | booking_date | Calendar queries |
+| consultations | status | status | Filter by status |
+| consultations | user_date_unique | user_id, booking_date | Enforce 1/day limit |
+| timelines | user_status | user_id, status | Client timeline list |
+| posts | status_published | status, published_at | Published posts list |
+| admin_logs | target | target_type, target_id | Audit trail lookup |
+
+---
+
+## 6. Application Structure
+
+### 6.1 Directory Structure
+
+```
+libra/
+├── app/
+│ ├── Actions/ # Business logic (single-purpose)
+│ │ ├── Fortify/ # Auth actions (existing)
+│ │ │ ├── CreateNewUser.php
+│ │ │ ├── ResetUserPassword.php
+│ │ │ └── UpdateUserPassword.php
+│ │ ├── Consultation/
+│ │ │ ├── CreateConsultationAction.php
+│ │ │ ├── ApproveConsultationAction.php
+│ │ │ ├── RejectConsultationAction.php
+│ │ │ ├── CompleteConsultationAction.php
+│ │ │ └── CancelConsultationAction.php
+│ │ ├── Timeline/
+│ │ │ ├── CreateTimelineAction.php
+│ │ │ ├── AddTimelineUpdateAction.php
+│ │ │ └── ArchiveTimelineAction.php
+│ │ ├── User/
+│ │ │ ├── CreateClientAction.php
+│ │ │ ├── UpdateClientAction.php
+│ │ │ ├── DeactivateClientAction.php
+│ │ │ ├── ReactivateClientAction.php
+│ │ │ ├── DeleteClientAction.php
+│ │ │ └── ConvertClientTypeAction.php
+│ │ ├── Post/
+│ │ │ ├── CreatePostAction.php
+│ │ │ ├── UpdatePostAction.php
+│ │ │ ├── PublishPostAction.php
+│ │ │ └── DeletePostAction.php
+│ │ └── Export/
+│ │ ├── ExportUsersAction.php
+│ │ ├── ExportConsultationsAction.php
+│ │ └── GenerateMonthlyReportAction.php
+│ ├── Enums/ # PHP 8.1+ enums
+│ │ ├── UserType.php
+│ │ ├── UserStatus.php
+│ │ ├── ConsultationType.php
+│ │ ├── ConsultationStatus.php
+│ │ ├── PaymentStatus.php
+│ │ ├── TimelineStatus.php
+│ │ └── PostStatus.php
+│ ├── Http/
+│ │ ├── Controllers/ # Minimal controllers
+│ │ │ ├── LanguageController.php
+│ │ │ └── CalendarDownloadController.php
+│ │ └── Middleware/
+│ │ ├── SetLocale.php
+│ │ ├── EnsureUserIsAdmin.php
+│ │ └── EnsureUserIsActive.php
+│ ├── Jobs/ # Queue jobs
+│ │ ├── SendWelcomeEmail.php
+│ │ ├── SendBookingNotification.php
+│ │ ├── SendConsultationReminder.php
+│ │ ├── SendTimelineUpdateNotification.php
+│ │ └── GenerateExportFile.php
+│ ├── Livewire/ # Full-page Livewire components (if any)
+│ │ └── Forms/ # Livewire form objects
+│ │ ├── ConsultationForm.php
+│ │ ├── ClientForm.php
+│ │ ├── TimelineForm.php
+│ │ └── PostForm.php
+│ ├── Mail/ # Mailable classes
+│ │ ├── WelcomeMail.php
+│ │ ├── BookingSubmittedMail.php
+│ │ ├── BookingApprovedMail.php
+│ │ ├── BookingRejectedMail.php
+│ │ ├── ConsultationReminderMail.php
+│ │ ├── TimelineUpdatedMail.php
+│ │ └── NewBookingRequestMail.php
+│ ├── Models/ # Eloquent models
+│ │ ├── User.php
+│ │ ├── Consultation.php
+│ │ ├── Timeline.php
+│ │ ├── TimelineUpdate.php
+│ │ ├── Post.php
+│ │ ├── WorkingHour.php
+│ │ ├── BlockedTime.php
+│ │ ├── Notification.php
+│ │ ├── AdminLog.php
+│ │ └── Setting.php
+│ ├── Observers/ # Model observers
+│ │ ├── ConsultationObserver.php
+│ │ ├── TimelineUpdateObserver.php
+│ │ └── UserObserver.php
+│ ├── Policies/ # Authorization policies
+│ │ ├── ConsultationPolicy.php
+│ │ ├── TimelinePolicy.php
+│ │ ├── PostPolicy.php
+│ │ └── UserPolicy.php
+│ ├── Providers/
+│ │ ├── AppServiceProvider.php
+│ │ └── FortifyServiceProvider.php
+│ └── Services/ # Cross-cutting services
+│ ├── AvailabilityService.php
+│ ├── CalendarService.php
+│ └── ExportService.php
+├── config/
+│ └── libra.php # App-specific config
+├── database/
+│ ├── factories/
+│ │ ├── UserFactory.php
+│ │ ├── ConsultationFactory.php
+│ │ ├── TimelineFactory.php
+│ │ ├── TimelineUpdateFactory.php
+│ │ └── PostFactory.php
+│ ├── migrations/
+│ └── seeders/
+│ ├── DatabaseSeeder.php
+│ ├── AdminSeeder.php
+│ ├── WorkingHoursSeeder.php
+│ └── DemoDataSeeder.php
+├── docs/
+│ ├── architecture.md # This document
+│ ├── prd.md # Product requirements
+│ ├── epics/ # Epic definitions
+│ └── stories/ # User stories
+├── resources/
+│ ├── views/
+│ │ ├── components/ # Blade components
+│ │ │ ├── layouts/
+│ │ │ │ ├── app.blade.php # Main app layout
+│ │ │ │ ├── guest.blade.php # Guest/public layout
+│ │ │ │ └── admin.blade.php # Admin layout
+│ │ │ └── ui/ # Reusable UI components
+│ │ │ ├── card.blade.php
+│ │ │ ├── stat-card.blade.php
+│ │ │ ├── status-badge.blade.php
+│ │ │ └── language-switcher.blade.php
+│ │ ├── emails/ # Email templates
+│ │ │ ├── welcome.blade.php
+│ │ │ ├── booking-submitted.blade.php
+│ │ │ ├── booking-approved.blade.php
+│ │ │ ├── booking-rejected.blade.php
+│ │ │ ├── consultation-reminder.blade.php
+│ │ │ ├── timeline-updated.blade.php
+│ │ │ └── new-booking-request.blade.php
+│ │ ├── livewire/ # Volt single-file components
+│ │ │ ├── admin/ # Admin area
+│ │ │ │ ├── dashboard.blade.php
+│ │ │ │ ├── users/
+│ │ │ │ │ ├── index.blade.php
+│ │ │ │ │ ├── create.blade.php
+│ │ │ │ │ └── edit.blade.php
+│ │ │ │ ├── consultations/
+│ │ │ │ │ ├── index.blade.php
+│ │ │ │ │ ├── pending.blade.php
+│ │ │ │ │ ├── calendar.blade.php
+│ │ │ │ │ └── show.blade.php
+│ │ │ │ ├── timelines/
+│ │ │ │ │ ├── index.blade.php
+│ │ │ │ │ ├── create.blade.php
+│ │ │ │ │ └── show.blade.php
+│ │ │ │ ├── posts/
+│ │ │ │ │ ├── index.blade.php
+│ │ │ │ │ ├── create.blade.php
+│ │ │ │ │ └── edit.blade.php
+│ │ │ │ ├── settings/
+│ │ │ │ │ ├── working-hours.blade.php
+│ │ │ │ │ ├── blocked-times.blade.php
+│ │ │ │ │ └── content-pages.blade.php
+│ │ │ │ └── reports/
+│ │ │ │ └── index.blade.php
+│ │ │ ├── client/ # Client area
+│ │ │ │ ├── dashboard.blade.php
+│ │ │ │ ├── consultations/
+│ │ │ │ │ ├── index.blade.php
+│ │ │ │ │ └── book.blade.php
+│ │ │ │ ├── timelines/
+│ │ │ │ │ ├── index.blade.php
+│ │ │ │ │ └── show.blade.php
+│ │ │ │ └── profile.blade.php
+│ │ │ ├── pages/ # Public pages
+│ │ │ │ ├── home.blade.php
+│ │ │ │ ├── posts/
+│ │ │ │ │ ├── index.blade.php
+│ │ │ │ │ └── show.blade.php
+│ │ │ │ ├── terms.blade.php
+│ │ │ │ └── privacy.blade.php
+│ │ │ ├── auth/ # Auth pages (existing)
+│ │ │ └── settings/ # User settings (existing)
+│ │ ├── pdf/ # PDF templates
+│ │ │ ├── users-export.blade.php
+│ │ │ ├── consultations-export.blade.php
+│ │ │ └── monthly-report.blade.php
+│ │ └── errors/ # Error pages
+│ │ ├── 404.blade.php
+│ │ ├── 403.blade.php
+│ │ └── 500.blade.php
+│ ├── css/
+│ │ └── app.css # Tailwind entry point
+│ ├── js/
+│ │ └── app.js # Minimal JS
+│ └── lang/ # Translations
+│ ├── ar/
+│ │ ├── auth.php
+│ │ ├── validation.php
+│ │ ├── pagination.php
+│ │ ├── passwords.php
+│ │ ├── messages.php
+│ │ ├── models.php
+│ │ ├── enums.php
+│ │ └── emails.php
+│ └── en/
+│ └── ... (same structure)
+├── routes/
+│ ├── web.php # Web routes
+│ └── console.php # Scheduled commands
+├── tests/
+│ ├── Feature/
+│ │ ├── Admin/
+│ │ │ ├── DashboardTest.php
+│ │ │ ├── UserManagementTest.php
+│ │ │ ├── ConsultationManagementTest.php
+│ │ │ ├── TimelineManagementTest.php
+│ │ │ ├── PostManagementTest.php
+│ │ │ └── SettingsTest.php
+│ │ ├── Client/
+│ │ │ ├── DashboardTest.php
+│ │ │ ├── BookingTest.php
+│ │ │ ├── TimelineViewTest.php
+│ │ │ └── ProfileTest.php
+│ │ ├── Public/
+│ │ │ ├── HomePageTest.php
+│ │ │ ├── PostsTest.php
+│ │ │ └── LanguageSwitchTest.php
+│ │ └── Auth/
+│ │ └── ... (existing tests)
+│ └── Unit/
+│ ├── Actions/
+│ ├── Models/
+│ ├── Services/
+│ └── Enums/
+├── storage/
+│ └── app/
+│ └── exports/ # Generated export files
+├── .github/
+│ └── workflows/
+│ └── ci.yml # GitHub Actions CI
+└── public/
+ └── build/ # Compiled assets
+```
+
+---
+
+## 7. Authentication & Authorization
+
+### 7.1 Authentication (Fortify)
+
+**Current Configuration:**
+- Email/password login
+- Email verification
+- Two-factor authentication (TOTP)
+- Password reset
+
+**Modifications Required:**
+1. **Disable public registration** - Admin creates all users
+2. **Custom login redirect** - Admin → `/admin/dashboard`, Client → `/client/dashboard`
+3. **Admin-triggered password reset** - No public reset
+
+```php
+// config/fortify.php
+'features' => [
+ // Features::registration(), // DISABLED
+ Features::resetPasswords(),
+ Features::emailVerification(),
+ Features::updateProfileInformation(),
+ Features::updatePasswords(),
+ Features::twoFactorAuthentication([
+ 'confirm' => true,
+ 'confirmPassword' => true,
+ ]),
+],
+```
+
+### 7.2 Authorization (Policies)
+
+```php
+// app/Policies/ConsultationPolicy.php
+class ConsultationPolicy
+{
+ public function viewAny(User $user): bool
+ {
+ return true; // All authenticated users can see their own
+ }
+
+ public function view(User $user, Consultation $consultation): bool
+ {
+ return $user->isAdmin() || $consultation->user_id === $user->id;
+ }
+
+ public function create(User $user): bool
+ {
+ return $user->isClient();
+ }
+
+ public function update(User $user, Consultation $consultation): bool
+ {
+ return $user->isAdmin();
+ }
+
+ public function delete(User $user, Consultation $consultation): bool
+ {
+ return $user->isAdmin();
+ }
+}
+
+// app/Policies/TimelinePolicy.php
+class TimelinePolicy
+{
+ public function viewAny(User $user): bool
+ {
+ return true;
+ }
+
+ public function view(User $user, Timeline $timeline): bool
+ {
+ return $user->isAdmin() || $timeline->user_id === $user->id;
+ }
+
+ public function create(User $user): bool
+ {
+ return $user->isAdmin();
+ }
+
+ public function update(User $user, Timeline $timeline): bool
+ {
+ return $user->isAdmin();
+ }
+
+ public function addUpdate(User $user, Timeline $timeline): bool
+ {
+ return $user->isAdmin();
+ }
+}
+
+// app/Policies/UserPolicy.php
+class UserPolicy
+{
+ public function viewAny(User $user): bool
+ {
+ return $user->isAdmin();
+ }
+
+ public function view(User $user, User $model): bool
+ {
+ return $user->isAdmin() || $user->id === $model->id;
+ }
+
+ public function create(User $user): bool
+ {
+ return $user->isAdmin();
+ }
+
+ public function update(User $user, User $model): bool
+ {
+ return $user->isAdmin();
+ }
+
+ public function delete(User $user, User $model): bool
+ {
+ return $user->isAdmin() && !$model->isAdmin();
+ }
+}
+```
+
+### 7.3 Middleware
+
+```php
+// app/Http/Middleware/SetLocale.php
+class SetLocale
+{
+ public function handle(Request $request, Closure $next): Response
+ {
+ $locale = session('locale')
+ ?? $request->user()?->preferred_language
+ ?? config('app.locale');
+
+ if (!in_array($locale, ['ar', 'en'])) {
+ $locale = 'ar';
+ }
+
+ app()->setLocale($locale);
+
+ return $next($request);
+ }
+}
+
+// app/Http/Middleware/EnsureUserIsAdmin.php
+class EnsureUserIsAdmin
+{
+ public function handle(Request $request, Closure $next): Response
+ {
+ if (!$request->user()?->isAdmin()) {
+ abort(403, __('messages.unauthorized'));
+ }
+
+ return $next($request);
+ }
+}
+
+// app/Http/Middleware/EnsureUserIsActive.php
+class EnsureUserIsActive
+{
+ public function handle(Request $request, Closure $next): Response
+ {
+ if ($request->user()?->status === UserStatus::Deactivated) {
+ Auth::logout();
+ $request->session()->invalidate();
+ $request->session()->regenerateToken();
+
+ return redirect()->route('login')
+ ->with('error', __('messages.account_deactivated'));
+ }
+
+ return $next($request);
+ }
+}
+```
+
+### 7.4 Middleware Registration
+
+```php
+// bootstrap/app.php
+->withMiddleware(function (Middleware $middleware) {
+ $middleware->web(append: [
+ \App\Http\Middleware\SetLocale::class,
+ ]);
+
+ $middleware->alias([
+ 'admin' => \App\Http\Middleware\EnsureUserIsAdmin::class,
+ 'active' => \App\Http\Middleware\EnsureUserIsActive::class,
+ ]);
+
+ $middleware->validateCsrfTokens(except: [
+ // Add any exceptions here
+ ]);
+})
+```
+
+---
+
+## 8. Core Workflows
+
+### 8.1 Consultation Booking Flow
+
+```mermaid
+sequenceDiagram
+ participant C as Client
+ participant V as Volt Component
+ participant A as Action
+ participant S as AvailabilityService
+ participant M as Model
+ participant Q as Queue
+ participant E as Email (Admin)
+
+ C->>V: Open booking page
+ V->>S: getAvailableSlots(date)
+ S->>M: Query working_hours, blocked_times, consultations
+ S-->>V: Available time slots
+ V-->>C: Display calendar
+
+ C->>V: Select date/time, enter summary
+ V->>V: Validate (date future, slot available, no existing booking)
+
+ alt Validation fails
+ V-->>C: Show error message
+ else Validation passes
+ V->>A: CreateConsultationAction
+ A->>M: Check user has no booking on date
+ A->>M: Create consultation (status: pending)
+ A->>M: Log admin action
+ M-->>A: Consultation created
+ A->>Q: Dispatch SendBookingNotification (to admin)
+ Q->>E: Email admin at no-reply@libra.ps
+ A-->>V: Success
+ V-->>C: Show confirmation message
+ end
+```
+
+### 8.2 Admin Consultation Approval Flow
+
+```mermaid
+sequenceDiagram
+ participant Ad as Admin
+ participant V as Volt Component
+ participant A as Action
+ participant M as Model
+ participant Q as Queue
+ participant E as Email (Client)
+
+ Ad->>V: View pending consultation
+ Ad->>V: Set type (free/paid), amount if paid
+ Ad->>V: Click Approve
+
+ V->>A: ApproveConsultationAction
+ A->>M: Update consultation (status: approved, type, amount)
+ A->>M: Log admin action
+ M-->>A: Updated
+
+ A->>Q: Dispatch SendBookingApprovedMail (with .ics attachment)
+ A->>Q: Schedule SendConsultationReminder (24h before)
+ A->>Q: Schedule SendConsultationReminder (2h before)
+
+ Q->>E: Send approval email to client
+ A-->>V: Success
+ V-->>Ad: Refresh list, show success toast
+```
+
+### 8.3 Timeline Update Flow
+
+```mermaid
+sequenceDiagram
+ participant Ad as Admin
+ participant V as Volt Component
+ participant A as Action
+ participant M as Model
+ participant O as Observer
+ participant Q as Queue
+ participant E as Email
+
+ Ad->>V: Navigate to timeline
+ Ad->>V: Enter update text
+ Ad->>V: Submit
+
+ V->>A: AddTimelineUpdateAction
+ A->>M: Create TimelineUpdate
+ M->>O: TimelineUpdateObserver::created
+ O->>Q: Dispatch SendTimelineUpdateNotification
+ A->>M: Log admin action
+ A-->>V: Success
+
+ Q->>E: Send notification to client
+ V-->>Ad: Refresh timeline, show new update
+```
+
+### 8.4 User Creation Flow
+
+```mermaid
+sequenceDiagram
+ participant Ad as Admin
+ participant V as Volt Component
+ participant A as Action
+ participant M as Model
+ participant Q as Queue
+ participant E as Email
+
+ Ad->>V: Fill user form (type, name, email, etc.)
+ Ad->>V: Set password
+ Ad->>V: Submit
+
+ V->>V: Validate form
+ V->>A: CreateClientAction
+ A->>M: Create User
+ A->>M: Log admin action
+ M-->>A: User created
+ A->>Q: Dispatch SendWelcomeEmail (with credentials)
+ Q->>E: Send welcome email to new user
+ A-->>V: Success
+ V-->>Ad: Redirect to user list
+```
+
+---
+
+## 9. Routing Structure
+
+### 9.1 Route Definitions
+
+```php
+// routes/web.php
+
+use App\Http\Controllers\LanguageController;
+use App\Http\Controllers\CalendarDownloadController;
+use Illuminate\Support\Facades\Route;
+use Livewire\Volt\Volt;
+
+/*
+|--------------------------------------------------------------------------
+| Public Routes
+|--------------------------------------------------------------------------
+*/
+
+// Home
+Volt::route('/', 'pages.home')->name('home');
+
+// Posts
+Volt::route('/posts', 'pages.posts.index')->name('posts.index');
+Volt::route('/posts/{post}', 'pages.posts.show')->name('posts.show');
+
+// Legal pages
+Volt::route('/terms', 'pages.terms')->name('terms');
+Volt::route('/privacy', 'pages.privacy')->name('privacy');
+
+// Language switch
+Route::get('/language/{locale}', LanguageController::class)
+ ->name('language.switch')
+ ->where('locale', 'ar|en');
+
+/*
+|--------------------------------------------------------------------------
+| Client Routes (Authenticated Non-Admin)
+|--------------------------------------------------------------------------
+*/
+
+Route::middleware(['auth', 'verified', 'active'])->prefix('client')->name('client.')->group(function () {
+ Volt::route('/dashboard', 'client.dashboard')->name('dashboard');
+
+ // Consultations
+ Volt::route('/consultations', 'client.consultations.index')->name('consultations.index');
+ Volt::route('/consultations/book', 'client.consultations.book')->name('consultations.book');
+ Route::get('/consultations/{consultation}/calendar', CalendarDownloadController::class)
+ ->name('consultations.calendar');
+
+ // Timelines
+ Volt::route('/timelines', 'client.timelines.index')->name('timelines.index');
+ Volt::route('/timelines/{timeline}', 'client.timelines.show')->name('timelines.show');
+
+ // Profile (view only)
+ Volt::route('/profile', 'client.profile')->name('profile');
+});
+
+/*
+|--------------------------------------------------------------------------
+| Admin Routes
+|--------------------------------------------------------------------------
+*/
+
+Route::middleware(['auth', 'verified', 'admin'])->prefix('admin')->name('admin.')->group(function () {
+ Volt::route('/dashboard', 'admin.dashboard')->name('dashboard');
+
+ // Users
+ Volt::route('/users', 'admin.users.index')->name('users.index');
+ Volt::route('/users/create', 'admin.users.create')->name('users.create');
+ Volt::route('/users/{user}/edit', 'admin.users.edit')->name('users.edit');
+
+ // Consultations
+ Volt::route('/consultations', 'admin.consultations.index')->name('consultations.index');
+ Volt::route('/consultations/pending', 'admin.consultations.pending')->name('consultations.pending');
+ Volt::route('/consultations/calendar', 'admin.consultations.calendar')->name('consultations.calendar');
+ Volt::route('/consultations/{consultation}', 'admin.consultations.show')->name('consultations.show');
+
+ // Timelines
+ Volt::route('/timelines', 'admin.timelines.index')->name('timelines.index');
+ Volt::route('/timelines/create', 'admin.timelines.create')->name('timelines.create');
+ Volt::route('/timelines/{timeline}', 'admin.timelines.show')->name('timelines.show');
+
+ // Posts
+ Volt::route('/posts', 'admin.posts.index')->name('posts.index');
+ Volt::route('/posts/create', 'admin.posts.create')->name('posts.create');
+ Volt::route('/posts/{post}/edit', 'admin.posts.edit')->name('posts.edit');
+
+ // Settings
+ Volt::route('/settings/working-hours', 'admin.settings.working-hours')->name('settings.working-hours');
+ Volt::route('/settings/blocked-times', 'admin.settings.blocked-times')->name('settings.blocked-times');
+ Volt::route('/settings/content-pages', 'admin.settings.content-pages')->name('settings.content-pages');
+
+ // Reports
+ Volt::route('/reports', 'admin.reports.index')->name('reports.index');
+});
+```
+
+### 9.2 Route Summary
+
+| Area | Route Prefix | Middleware | Description |
+|------|--------------|------------|-------------|
+| Public | `/` | none | Home, posts, legal pages |
+| Client | `/client` | auth, verified, active | Client dashboard, bookings, timelines |
+| Admin | `/admin` | auth, verified, admin | Full management interface |
+| Auth | `/` (Fortify) | varies | Login, logout, password, 2FA |
+| Settings | `/settings` | auth, verified | User profile settings |
+
+---
+
+## 10. Email System
+
+### 10.1 Configuration
+
+```php
+// config/mail.php (via .env)
+MAIL_MAILER=smtp
+MAIL_HOST=smtp.libra.ps
+MAIL_PORT=587
+MAIL_USERNAME=no-reply@libra.ps
+MAIL_PASSWORD=****
+MAIL_ENCRYPTION=tls
+MAIL_FROM_ADDRESS=no-reply@libra.ps
+MAIL_FROM_NAME="${APP_NAME}"
+```
+
+### 10.2 Email Templates
+
+| Email Class | Trigger | Recipient | Queue | Attachments |
+|-------------|---------|-----------|-------|-------------|
+| `WelcomeMail` | User created | Client | Yes | None |
+| `BookingSubmittedMail` | Consultation created | Client | Yes | None |
+| `BookingApprovedMail` | Consultation approved | Client | Yes | .ics file |
+| `BookingRejectedMail` | Consultation rejected | Client | Yes | None |
+| `ConsultationReminderMail` | 24h/2h before | Client | Scheduled | .ics file |
+| `TimelineUpdatedMail` | Timeline update added | Client | Yes | None |
+| `NewBookingRequestMail` | Consultation created | Admin | Yes | None |
+
+### 10.3 Email Template Example
+
+```php
+// app/Mail/BookingApprovedMail.php
+class BookingApprovedMail extends Mailable implements ShouldQueue
+{
+ use Queueable, SerializesModels;
+
+ public function __construct(
+ public Consultation $consultation
+ ) {}
+
+ public function envelope(): Envelope
+ {
+ $locale = $this->consultation->user->preferred_language;
+
+ return new Envelope(
+ subject: $locale === 'ar'
+ ? 'تمت الموافقة على موعدك - مكتب ليبرا للمحاماة'
+ : 'Your Consultation Approved - Libra Law Firm',
+ );
+ }
+
+ public function content(): Content
+ {
+ return new Content(
+ markdown: 'emails.booking-approved',
+ with: [
+ 'consultation' => $this->consultation,
+ 'user' => $this->consultation->user,
+ 'locale' => $this->consultation->user->preferred_language,
+ ],
+ );
+ }
+
+ public function attachments(): array
+ {
+ $calendar = app(CalendarService::class);
+
+ return [
+ Attachment::fromData(
+ fn () => $calendar->generateIcs($this->consultation),
+ 'consultation.ics'
+ )->withMime('text/calendar'),
+ ];
+ }
+}
+```
+
+### 10.4 Email Template Structure (Blade)
+
+```blade
+{{-- resources/views/emails/booking-approved.blade.php --}}
+
+{{ config('app.name') }}
+