Files

1122 lines
52 KiB
Markdown
Raw Permalink Normal View History

2026-06-28 03:19:32 +03:00
# Dark Crime Theme Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Apply a dark, crime-themed UI to the full Laravel/Blade/Tailwind game — sidebar layout, blood-red accents, near-black backgrounds — across all game and auth pages.
**Architecture:** All styling is done via Tailwind utility classes directly in Blade templates. A custom color palette (`syndicate`, `crime`, `gold`) is registered in `tailwind.config.js`. No new CSS files are created — the existing `resources/css/app.css` (`@tailwind base/components/utilities`) is sufficient.
**Tech Stack:** Laravel 11, Blade templates, Tailwind CSS v3, `@tailwindcss/forms`, Alpine.js (already present via `x-data`), Bunny Fonts.
## Global Constraints
- Never add new PHP files — only modify Blade templates and `tailwind.config.js`
- Keep all existing route names and form actions unchanged
- Preserve Alpine.js `x-data` / `@click` attributes on the navigation
- Use exact color token names: `syndicate-{950,900,800,700,600}`, `crime-{600,500,400}`, `gold-{500,400}`
- Font families: `font-sans` = Inter, `font-display` = Rajdhani
- Bunny Fonts URL format: `https://fonts.bunny.net/css?family=inter:400,500,600|rajdhani:600,700&display=swap`
- No mobile sidebar collapse — out of scope
---
## File Map
| File | Action | Responsibility |
|---|---|---|
| `tailwind.config.js` | Modify | Register color palette + font-display |
| `resources/views/layouts/app.blade.php` | Modify | Dark body bg, new font link |
| `resources/views/layouts/guest.blade.php` | Modify | Dark auth wrapper + card |
| `resources/views/layouts/game.blade.php` | Rewrite | Sidebar + top bar shell |
| `resources/views/layouts/navigation.blade.php` | Rewrite | Sidebar nav links (replaces top-nav) |
| `resources/views/game/partials/stats-bar.blade.php` | Rewrite | Compact HP/Energy/Cash pills |
| `resources/views/components/primary-button.blade.php` | Modify | Crime-red button |
| `resources/views/components/secondary-button.blade.php` | Modify | Syndicate-dark button |
| `resources/views/components/text-input.blade.php` | Modify | Dark input field |
| `resources/views/components/input-label.blade.php` | Modify | Light label text |
| `resources/views/game/dashboard.blade.php` | Modify | Dark card classes throughout |
| `resources/views/game/crimes/index.blade.php` | Modify | Dark card/button classes |
| `resources/views/game/inventory/index.blade.php` | Modify | Dark card/button classes |
| `resources/views/game/hospital.blade.php` | Modify | Dark card classes |
| `resources/views/game/jail.blade.php` | Modify | Dark card classes |
---
### Task 1: Register color palette and fonts in Tailwind config
**Files:**
- Modify: `tailwind.config.js`
- Modify: `resources/views/layouts/app.blade.php`
- Modify: `resources/views/layouts/guest.blade.php`
**Interfaces:**
- Produces: color tokens `syndicate-{950,900,800,700,600}`, `crime-{600,500,400}`, `gold-{500,400}`, font family `font-display` — used by every subsequent task
- [ ] **Step 1: Update tailwind.config.js**
Replace the entire file content with:
```js
import defaultTheme from 'tailwindcss/defaultTheme';
import forms from '@tailwindcss/forms';
/** @type {import('tailwindcss').Config} */
export default {
content: [
'./vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php',
'./storage/framework/views/*.php',
'./resources/views/**/*.blade.php',
],
theme: {
extend: {
fontFamily: {
sans: ['Inter', ...defaultTheme.fontFamily.sans],
display: ['Rajdhani', ...defaultTheme.fontFamily.sans],
},
colors: {
syndicate: {
950: '#0a0a0c',
900: '#111114',
800: '#1a1a1f',
700: '#242429',
600: '#2e2e35',
},
crime: {
600: '#dc2626',
500: '#ef4444',
400: '#f87171',
},
gold: {
500: '#d97706',
400: '#fbbf24',
},
},
},
},
plugins: [forms],
};
```
- [ ] **Step 2: Update app.blade.php font link and body class**
Replace `resources/views/layouts/app.blade.php` with:
```blade
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>@yield('title', config('app.name', 'Laravel'))</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=inter:400,500,600|rajdhani:600,700&display=swap" rel="stylesheet" />
<!-- Scripts -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="font-sans antialiased bg-syndicate-950 text-gray-100 min-h-screen">
@yield('content')
</body>
</html>
```
- [ ] **Step 3: Update guest.blade.php for dark auth layout**
Replace `resources/views/layouts/guest.blade.php` with:
```blade
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=inter:400,500,600|rajdhani:600,700&display=swap" rel="stylesheet" />
<!-- Scripts -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="font-sans antialiased bg-syndicate-950 text-gray-100 min-h-screen">
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0">
<div class="mb-6">
<a href="/" class="font-display text-3xl font-bold text-crime-400 tracking-wide uppercase">
{{ config('app.name', 'The Crime Syndicate') }}
</a>
</div>
<div class="w-full sm:max-w-md px-8 py-8 bg-syndicate-800 border border-syndicate-700 shadow-xl overflow-hidden sm:rounded-lg">
{{ $slot }}
</div>
</div>
</body>
</html>
```
- [ ] **Step 4: Build assets and verify no Tailwind errors**
Run:
```bash
cd /home/liquidsky/Projects/thecrimesyndicate && npm run build 2>&1 | tail -20
```
Expected: build completes with no errors. The output should mention `app.css` and `app.js`.
- [ ] **Step 5: Commit**
```bash
cd /home/liquidsky/Projects/thecrimesyndicate
git add tailwind.config.js resources/views/layouts/app.blade.php resources/views/layouts/guest.blade.php
git commit -m "feat: register syndicate/crime/gold color palette and Inter/Rajdhani fonts"
```
---
### Task 2: Rewrite game layout with sidebar + top bar
**Files:**
- Rewrite: `resources/views/layouts/game.blade.php`
- Rewrite: `resources/views/layouts/navigation.blade.php`
- Rewrite: `resources/views/game/partials/stats-bar.blade.php`
**Interfaces:**
- Consumes: color tokens from Task 1
- Produces: `@yield('game-content')` content slot consumed by all game pages; `$character` variable (already passed by game controllers)
- [ ] **Step 1: Rewrite game.blade.php**
Replace `resources/views/layouts/game.blade.php` with:
```blade
@extends('layouts.app')
@section('title', config('game.name', 'The Crime Syndicate') . ' - ' . ($title ?? 'Game'))
@section('content')
<div class="flex flex-col min-h-screen">
{{-- TOP BAR --}}
<header class="bg-syndicate-900 border-b border-syndicate-700 h-14 flex items-center px-6 flex-shrink-0 z-10">
{{-- Logo --}}
<a href="{{ route('game.dashboard') }}" class="font-display font-bold text-xl text-crime-400 uppercase tracking-widest mr-8 flex-shrink-0">
{{ config('game.name', 'The Crime Syndicate') }}
</a>
{{-- Stats bar --}}
<div class="flex-1 flex items-center justify-center space-x-4">
@if(auth()->check() && auth()->user()->character)
@include('game.partials.stats-bar')
@endif
</div>
{{-- User menu --}}
<div class="flex items-center space-x-3 flex-shrink-0">
<span class="text-sm text-gray-400">{{ auth()->user()->name ?? '' }}</span>
<div x-data="{ open: false }" class="relative">
<button @click="open = !open" class="flex items-center text-gray-400 hover:text-gray-100 transition">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" />
</svg>
</button>
<div x-show="open" @click.away="open = false"
class="absolute right-0 mt-2 w-48 bg-syndicate-800 border border-syndicate-700 rounded-lg shadow-xl z-50">
<a href="{{ route('profile.edit') }}" class="block px-4 py-2 text-sm text-gray-300 hover:bg-syndicate-700 hover:text-gray-100 rounded-t-lg transition">
Settings
</a>
<form method="POST" action="{{ route('logout') }}">
@csrf
<button type="submit" class="w-full text-left px-4 py-2 text-sm text-gray-300 hover:bg-syndicate-700 hover:text-gray-100 rounded-b-lg transition">
Log Out
</button>
</form>
</div>
</div>
</div>
</header>
{{-- BODY: sidebar + content --}}
<div class="flex flex-1">
{{-- SIDEBAR --}}
@include('layouts.navigation')
{{-- CONTENT --}}
<main class="flex-1 bg-syndicate-950 p-6 overflow-auto">
{{-- Flash messages --}}
@if(session('success'))
<div class="mb-4 px-4 py-3 bg-green-900/40 border border-green-700 text-green-400 rounded-lg text-sm">
{{ session('success') }}
</div>
@endif
@if(session('error'))
<div class="mb-4 px-4 py-3 bg-red-900/40 border border-red-800 text-red-400 rounded-lg text-sm">
{{ session('error') }}
</div>
@endif
@yield('game-content')
</main>
</div>
{{-- FOOTER --}}
<footer class="bg-syndicate-900 border-t border-syndicate-700 py-3 text-center text-xs text-gray-600">
&copy; {{ date('Y') }} {{ config('game.name', 'The Crime Syndicate') }} &mdash; v{{ config('game.version', '1.0.0') }}
</footer>
</div>
@endsection
```
- [ ] **Step 2: Rewrite navigation.blade.php as sidebar**
Replace `resources/views/layouts/navigation.blade.php` with:
```blade
<aside class="bg-syndicate-900 border-r border-syndicate-700 w-56 flex-shrink-0 flex flex-col">
<nav class="flex-1 py-4">
<ul class="space-y-1 px-2">
<li>
<a href="{{ route('game.dashboard') }}"
class="flex items-center space-x-3 px-3 py-2 rounded-lg text-sm transition
{{ request()->routeIs('game.dashboard') ? 'border-l-2 border-crime-500 bg-syndicate-800 text-gray-100 pl-[10px]' : 'text-gray-400 hover:bg-syndicate-800 hover:text-gray-100' }}">
<span class="text-base">🏠</span>
<span>Dashboard</span>
</a>
</li>
<li>
<a href="{{ route('game.crimes.index') }}"
class="flex items-center space-x-3 px-3 py-2 rounded-lg text-sm transition
{{ request()->routeIs('game.crimes.*') ? 'border-l-2 border-crime-500 bg-syndicate-800 text-gray-100 pl-[10px]' : 'text-gray-400 hover:bg-syndicate-800 hover:text-gray-100' }}">
<span class="text-base">🎯</span>
<span>Crimes</span>
</a>
</li>
<li>
<a href="{{ route('game.inventory.index') }}"
class="flex items-center space-x-3 px-3 py-2 rounded-lg text-sm transition
{{ request()->routeIs('game.inventory.*') ? 'border-l-2 border-crime-500 bg-syndicate-800 text-gray-100 pl-[10px]' : 'text-gray-400 hover:bg-syndicate-800 hover:text-gray-100' }}">
<span class="text-base">🎒</span>
<span>Inventory</span>
</a>
</li>
<li>
<a href="{{ route('game.character.show') }}"
class="flex items-center space-x-3 px-3 py-2 rounded-lg text-sm transition
{{ request()->routeIs('game.character.show') ? 'border-l-2 border-crime-500 bg-syndicate-800 text-gray-100 pl-[10px]' : 'text-gray-400 hover:bg-syndicate-800 hover:text-gray-100' }}">
<span class="text-base">👤</span>
<span>Profile</span>
</a>
</li>
@if(auth()->check() && auth()->user()->character)
@php $charStatus = auth()->user()->character->status; @endphp
@if($charStatus === \App\Enums\CharacterStatus::IN_HOSPITAL)
<li class="pt-2 border-t border-syndicate-700 mt-2">
<a href="{{ route('game.hospital') }}"
class="flex items-center space-x-3 px-3 py-2 rounded-lg text-sm transition border-l-2 border-red-500 bg-syndicate-800 text-red-400 pl-[10px]">
<span class="text-base">🏥</span>
<span>Hospital</span>
</a>
</li>
@endif
@if($charStatus === \App\Enums\CharacterStatus::IN_JAIL)
<li class="pt-2 border-t border-syndicate-700 mt-2">
<a href="{{ route('game.jail') }}"
class="flex items-center space-x-3 px-3 py-2 rounded-lg text-sm transition border-l-2 border-yellow-500 bg-syndicate-800 text-yellow-400 pl-[10px]">
<span class="text-base">🚔</span>
<span>Jail</span>
</a>
</li>
@endif
@endif
</ul>
</nav>
</aside>
```
- [ ] **Step 3: Rewrite stats-bar.blade.php as compact pills**
Replace `resources/views/game/partials/stats-bar.blade.php` with:
```blade
@php $character = auth()->user()->character; @endphp
<div class="flex items-center space-x-3 text-sm">
{{-- HP --}}
<div class="flex items-center space-x-1 bg-syndicate-800 border border-syndicate-700 rounded px-2 py-1">
<span class="text-red-400">❤</span>
<span class="text-gray-300">{{ $character->health }}<span class="text-gray-600">/{{ $character->max_health }}</span></span>
</div>
{{-- Energy --}}
<div class="flex items-center space-x-1 bg-syndicate-800 border border-syndicate-700 rounded px-2 py-1">
<span class="text-yellow-400">⚡</span>
<span class="text-gray-300">{{ $character->energy }}<span class="text-gray-600">/{{ $character->max_energy }}</span></span>
</div>
{{-- Cash --}}
<div class="flex items-center space-x-1 bg-syndicate-800 border border-syndicate-700 rounded px-2 py-1">
<span class="text-gold-400">$</span>
<span class="text-gray-300">{{ number_format($character->money) }}</span>
</div>
{{-- Level --}}
<div class="bg-syndicate-700 text-gray-300 rounded px-2 py-1 text-xs font-medium">
Lv.{{ $character->level }}
</div>
{{-- Non-active status badge --}}
@if($character->status !== \App\Enums\CharacterStatus::ACTIVE)
<span class="px-2 py-1 text-xs rounded {{ $character->status->color() }}">
{{ $character->status->label() }}
</span>
@endif
</div>
```
- [ ] **Step 4: Build assets**
```bash
cd /home/liquidsky/Projects/thecrimesyndicate && npm run build 2>&1 | tail -20
```
Expected: build succeeds with no errors.
- [ ] **Step 5: Commit**
```bash
cd /home/liquidsky/Projects/thecrimesyndicate
git add resources/views/layouts/game.blade.php resources/views/layouts/navigation.blade.php resources/views/game/partials/stats-bar.blade.php
git commit -m "feat: sidebar + top bar game layout with dark crime theme"
```
---
### Task 3: Restyle Blade components (buttons + form inputs)
**Files:**
- Modify: `resources/views/components/primary-button.blade.php`
- Modify: `resources/views/components/secondary-button.blade.php`
- Modify: `resources/views/components/text-input.blade.php`
- Modify: `resources/views/components/input-label.blade.php`
**Interfaces:**
- Consumes: color tokens from Task 1
- Produces: restyled `<x-primary-button>`, `<x-secondary-button>`, `<x-text-input>`, `<x-input-label>` used by auth pages and game pages
- [ ] **Step 1: Restyle primary-button**
Replace `resources/views/components/primary-button.blade.php` with:
```blade
<button {{ $attributes->merge(['type' => 'submit', 'class' => 'inline-flex items-center px-4 py-2 bg-crime-600 border border-transparent rounded-md font-semibold text-sm text-white uppercase tracking-widest hover:bg-crime-500 focus:outline-none focus:ring-2 focus:ring-crime-500 focus:ring-offset-2 focus:ring-offset-syndicate-800 transition ease-in-out duration-150']) }}>
{{ $slot }}
</button>
```
- [ ] **Step 2: Restyle secondary-button**
Replace `resources/views/components/secondary-button.blade.php` with:
```blade
<button {{ $attributes->merge(['type' => 'button', 'class' => 'inline-flex items-center px-4 py-2 bg-syndicate-700 border border-syndicate-600 rounded-md font-semibold text-sm text-gray-300 uppercase tracking-widest hover:bg-syndicate-600 hover:text-gray-100 focus:outline-none focus:ring-2 focus:ring-syndicate-600 focus:ring-offset-2 focus:ring-offset-syndicate-800 disabled:opacity-25 transition ease-in-out duration-150']) }}>
{{ $slot }}
</button>
```
- [ ] **Step 3: Restyle text-input**
Replace `resources/views/components/text-input.blade.php` with:
```blade
@props(['disabled' => false])
<input @disabled($disabled) {{ $attributes->merge(['class' => 'bg-syndicate-700 border-syndicate-600 text-gray-100 placeholder-gray-500 focus:border-crime-500 focus:ring-crime-500 rounded-md shadow-sm']) }}>
```
- [ ] **Step 4: Restyle input-label**
Replace `resources/views/components/input-label.blade.php` with:
```blade
@props(['value'])
<label {{ $attributes->merge(['class' => 'block font-medium text-sm text-gray-300']) }}>
{{ $value ?? $slot }}
</label>
```
- [ ] **Step 5: Build assets**
```bash
cd /home/liquidsky/Projects/thecrimesyndicate && npm run build 2>&1 | tail -20
```
Expected: build succeeds with no errors.
- [ ] **Step 6: Commit**
```bash
cd /home/liquidsky/Projects/thecrimesyndicate
git add resources/views/components/primary-button.blade.php resources/views/components/secondary-button.blade.php resources/views/components/text-input.blade.php resources/views/components/input-label.blade.php
git commit -m "feat: restyle form components for dark crime theme"
```
---
### Task 4: Restyle game dashboard
**Files:**
- Modify: `resources/views/game/dashboard.blade.php`
**Interfaces:**
- Consumes: color tokens from Task 1, game layout from Task 2
- Consumes: `$character`, `$recentActivity` variables (passed by `GameController`)
- [ ] **Step 1: Replace dashboard.blade.php**
Replace `resources/views/game/dashboard.blade.php` with:
```blade
@extends('layouts.game')
@section('title', 'Dashboard')
@section('game-content')
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{{-- Welcome Card --}}
<div class="bg-syndicate-800 border border-syndicate-700 rounded-lg p-6">
<h2 class="font-display text-xl font-semibold text-gray-100 mb-4">
Welcome, {{ $character->name }}!
</h2>
<p class="text-gray-400 text-sm">
You are in <strong class="text-gray-200">{{ $character->location->name ?? 'Unknown Location' }}</strong>.
</p>
<p class="text-gray-400 text-sm mt-2">
Level {{ $character->level }} &mdash; {{ number_format($character->experience) }} / {{ number_format($character->experience_for_next_level) }} EXP
</p>
<div class="w-full bg-syndicate-700 rounded-full h-1.5 mt-3">
<div class="bg-crime-600 h-1.5 rounded-full" style="width: {{ $character->experience_progress }}%"></div>
</div>
<p class="text-xs text-gray-600 mt-1">{{ number_format($character->experience_progress, 1) }}% to next level</p>
</div>
{{-- Quick Stats --}}
<div class="bg-syndicate-800 border border-syndicate-700 rounded-lg p-6">
<h3 class="font-display text-lg font-semibold text-gray-100 mb-4">Quick Stats</h3>
<div class="space-y-2 text-sm">
<div class="flex justify-between">
<span class="text-gray-400">Strength</span>
<span class="text-gray-200 font-medium">{{ $character->strength }}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-400">Defense</span>
<span class="text-gray-200 font-medium">{{ $character->defense }}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-400">Speed</span>
<span class="text-gray-200 font-medium">{{ $character->speed }}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-400">Dexterity</span>
<span class="text-gray-200 font-medium">{{ $character->dexterity }}</span>
</div>
<div class="flex justify-between pt-2 border-t border-syndicate-700">
<span class="text-gray-400">Attack Power</span>
<span class="text-crime-400 font-medium">{{ $character->attack_power }}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-400">Total Defense</span>
<span class="text-blue-400 font-medium">{{ $character->defense }}</span>
</div>
</div>
</div>
{{-- Finances --}}
<div class="bg-syndicate-800 border border-syndicate-700 rounded-lg p-6">
<h3 class="font-display text-lg font-semibold text-gray-100 mb-4">Finances</h3>
<div class="space-y-3 text-sm">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-2">
<span class="text-gold-400">💰</span>
<span class="text-gray-400">Cash</span>
</div>
<span class="text-gold-400 font-medium">${{ number_format($character->money) }}</span>
</div>
<div class="flex items-center justify-between">
<div class="flex items-center space-x-2">
<span class="text-blue-400">🏦</span>
<span class="text-gray-400">Bank</span>
</div>
<span class="text-gray-200 font-medium">${{ number_format($character->bank) }}</span>
</div>
<div class="pt-2 border-t border-syndicate-700 space-y-2">
<a href="#" onclick="event.preventDefault(); document.getElementById('deposit-form').submit();"
class="block w-full text-center bg-crime-600 hover:bg-crime-500 text-white py-2 px-4 rounded text-sm transition">
Deposit to Bank
</a>
<form id="deposit-form" action="{{ route('game.character.deposit') }}" method="POST" class="hidden">
@csrf
<input type="number" name="amount" value="1000" min="1" max="{{ $character->money }}">
</form>
<a href="#" onclick="event.preventDefault(); document.getElementById('withdraw-form').submit();"
class="block w-full text-center bg-syndicate-700 hover:bg-syndicate-600 text-gray-300 py-2 px-4 rounded text-sm transition">
Withdraw from Bank
</a>
<form id="withdraw-form" action="{{ route('game.character.withdraw') }}" method="POST" class="hidden">
@csrf
<input type="number" name="amount" value="1000" min="1" max="{{ $character->bank }}">
</form>
</div>
</div>
</div>
{{-- Quick Actions --}}
<div class="bg-syndicate-800 border border-syndicate-700 rounded-lg p-6 lg:col-span-2">
<h3 class="font-display text-lg font-semibold text-gray-100 mb-4">Quick Actions</h3>
<div class="grid grid-cols-2 md:grid-cols-4 gap-3">
<a href="{{ route('game.crimes.index') }}"
class="flex flex-col items-center justify-center bg-syndicate-700 border border-syndicate-600 hover:border-crime-600 text-gray-300 hover:text-gray-100 py-4 px-2 rounded-lg transition">
<span class="text-2xl mb-1">🎯</span>
<span class="text-sm font-medium">Crimes</span>
<span class="text-xs text-gray-500">Commit crimes</span>
</a>
<a href="{{ route('game.inventory.index') }}"
class="flex flex-col items-center justify-center bg-syndicate-700 border border-syndicate-600 hover:border-crime-600 text-gray-300 hover:text-gray-100 py-4 px-2 rounded-lg transition">
<span class="text-2xl mb-1">🎒</span>
<span class="text-sm font-medium">Inventory</span>
<span class="text-xs text-gray-500">Manage items</span>
</a>
<a href="{{ route('game.character.show') }}"
class="flex flex-col items-center justify-center bg-syndicate-700 border border-syndicate-600 hover:border-crime-600 text-gray-300 hover:text-gray-100 py-4 px-2 rounded-lg transition">
<span class="text-2xl mb-1">👤</span>
<span class="text-sm font-medium">Profile</span>
<span class="text-xs text-gray-500">View profile</span>
</a>
<a href="{{ route('profile.edit') }}"
class="flex flex-col items-center justify-center bg-syndicate-700 border border-syndicate-600 hover:border-crime-600 text-gray-300 hover:text-gray-100 py-4 px-2 rounded-lg transition">
<span class="text-2xl mb-1">⚙️</span>
<span class="text-sm font-medium">Settings</span>
<span class="text-xs text-gray-500">Account settings</span>
</a>
</div>
</div>
{{-- Recent Activity --}}
<div class="bg-syndicate-800 border border-syndicate-700 rounded-lg p-6 lg:col-span-3">
<h3 class="font-display text-lg font-semibold text-gray-100 mb-4">Recent Activity</h3>
@if($recentActivity->isEmpty())
<p class="text-gray-500 text-center py-4 text-sm">No recent activity.</p>
@else
<div class="space-y-2">
@foreach($recentActivity as $activity)
<div class="flex items-start space-x-3 p-3 bg-syndicate-700 rounded-lg">
<span class="text-gray-500 text-base">
@switch($activity->action)
@case('crime_attempt')
@if(str_contains($activity->description, 'success')) ✅ @else ❌ @endif
@break
@case('money_earned') 💰 @break
@case('money_spent') 💸 @break
@case('character_created') 🎉 @break
@default 📝
@endswitch
</span>
<div class="flex-1">
<p class="text-sm font-medium text-gray-200">
{{ ucfirst(str_replace('_', ' ', $activity->action)) }}
</p>
<p class="text-xs text-gray-500">{{ $activity->description }}</p>
<p class="text-xs text-gray-600 mt-1">{{ $activity->created_at->diffForHumans() }}</p>
</div>
</div>
@endforeach
</div>
@endif
</div>
</div>
@endsection
```
- [ ] **Step 2: Build assets**
```bash
cd /home/liquidsky/Projects/thecrimesyndicate && npm run build 2>&1 | tail -20
```
Expected: build succeeds.
- [ ] **Step 3: Commit**
```bash
cd /home/liquidsky/Projects/thecrimesyndicate
git add resources/views/game/dashboard.blade.php
git commit -m "feat: restyle game dashboard with dark crime theme"
```
---
### Task 5: Restyle crimes page
**Files:**
- Modify: `resources/views/game/crimes/index.blade.php`
**Interfaces:**
- Consumes: color tokens from Task 1, game layout from Task 2
- Consumes: `$character`, `$availableCrimes`, `$recentAttempts`, `$crimeService` (passed by `CrimeController`)
- [ ] **Step 1: Replace crimes/index.blade.php**
Replace `resources/views/game/crimes/index.blade.php` with:
```blade
@extends('layouts.game')
@section('title', 'Crimes')
@section('game-content')
<div class="max-w-4xl mx-auto space-y-6">
{{-- Header card --}}
<div class="bg-syndicate-800 border border-syndicate-700 rounded-lg">
<div class="px-6 py-4 border-b border-syndicate-700 flex justify-between items-center">
<h1 class="font-display text-xl font-semibold text-gray-100">Available Crimes</h1>
<div class="text-sm text-gray-400">
Energy: <span class="text-yellow-400 font-medium">{{ $character->energy }}/{{ $character->max_energy }}</span>
</div>
</div>
<div class="p-6">
@if($availableCrimes->isEmpty())
<p class="text-center text-gray-500 py-8 text-sm">No crimes available. Try leveling up or restoring your energy.</p>
@else
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
@foreach($availableCrimes as $crime)
@php
$onCooldown = $crimeService->isOnCooldown($character, $crime);
$cooldownRemaining = $onCooldown ? $crimeService->getCooldownRemaining($character, $crime) : 0;
$successRate = $crime->calculateSuccessRate($character);
@endphp
<div class="bg-syndicate-700 border border-syndicate-600 hover:border-crime-600 rounded-lg p-4 transition">
<div class="flex justify-between items-start mb-2">
<div>
<h3 class="font-medium text-gray-100">{{ $crime->name }}</h3>
<p class="text-xs text-gray-500 mt-1">{{ $crime->difficulty_label }} Difficulty</p>
</div>
<span class="text-xs px-2 py-1 rounded-full {{ $crime->difficulty_color }} text-white flex-shrink-0">
{{ number_format($successRate * 100, 1) }}% Success
</span>
</div>
<p class="text-sm text-gray-400 mb-3">{{ Str::limit($crime->description, 100) }}</p>
<div class="grid grid-cols-2 gap-2 text-xs text-gray-400 mb-3">
<div class="flex items-center space-x-1">
<span class="text-yellow-400">⚡</span>
<span>{{ $crime->energy_cost }} Energy</span>
</div>
<div class="flex items-center space-x-1">
<span class="text-gold-400">💰</span>
<span>${{ $crime->reward_min }}-{{ $crime->reward_max }}</span>
</div>
<div class="flex items-center space-x-1">
<span class="text-blue-400">📈</span>
<span>{{ $crime->experience }} EXP</span>
</div>
<div class="flex items-center space-x-1">
<span class="text-gray-500">⏱</span>
<span>{{ $crime->cooldown }}s Cooldown</span>
</div>
</div>
@if($onCooldown)
<button disabled
class="w-full py-2 px-4 text-sm text-center bg-syndicate-600 text-gray-600 rounded-lg cursor-not-allowed">
On Cooldown ({{ ceil($cooldownRemaining / 60) }}m)
</button>
@else
<form action="{{ route('game.crimes.attempt', $crime) }}" method="POST">
@csrf
<button type="submit"
class="w-full py-2 px-4 text-sm text-center bg-crime-600 hover:bg-crime-500 text-white rounded-lg transition">
Attempt Crime
</button>
</form>
@endif
@if($crime->requires_level)
<p class="text-xs text-gray-600 mt-2">Requires Level {{ $crime->requires_level }}+</p>
@endif
</div>
@endforeach
</div>
@endif
</div>
</div>
{{-- Recent Attempts --}}
<div class="bg-syndicate-800 border border-syndicate-700 rounded-lg">
<div class="px-6 py-4 border-b border-syndicate-700">
<h3 class="font-display text-lg font-semibold text-gray-100">Recent Attempts</h3>
</div>
<div class="p-6">
@if($recentAttempts->isEmpty())
<p class="text-center text-gray-500 py-4 text-sm">No recent crime attempts.</p>
@else
<div class="space-y-2">
@foreach($recentAttempts as $attempt)
<div class="flex items-center justify-between p-3 bg-syndicate-700 rounded-lg">
<div class="flex items-center space-x-3">
<span>
@if($attempt->success)
<span class="text-green-400">✅</span>
@else
<span class="text-red-400">❌</span>
@endif
</span>
<div>
<p class="font-medium text-gray-200 text-sm">{{ $attempt->crime->name }}</p>
<p class="text-xs text-gray-500">{{ $attempt->attempted_at->diffForHumans() }}</p>
</div>
</div>
<div class="text-right">
@if($attempt->success)
<p class="text-sm text-gold-400">+${{ number_format($attempt->reward) }}</p>
<p class="text-xs text-gray-500">+{{ $attempt->experience_gained }} EXP</p>
@else
<p class="text-sm text-red-400">Failed</p>
@endif
</div>
</div>
@endforeach
</div>
@endif
</div>
</div>
</div>
@endsection
```
- [ ] **Step 2: Build and commit**
```bash
cd /home/liquidsky/Projects/thecrimesyndicate && npm run build 2>&1 | tail -5
git add resources/views/game/crimes/index.blade.php
git commit -m "feat: restyle crimes page with dark crime theme"
```
---
### Task 6: Restyle inventory, hospital, and jail pages
**Files:**
- Modify: `resources/views/game/inventory/index.blade.php`
- Modify: `resources/views/game/hospital.blade.php`
- Modify: `resources/views/game/jail.blade.php`
**Interfaces:**
- Consumes: color tokens from Task 1, game layout from Task 2
- Consumes: `$inventory` (inventory page), `$character` + `$releaseTime` + `$reviveCost` (hospital), `$character` + `$releaseTime` (jail)
- [ ] **Step 1: Replace inventory/index.blade.php**
Replace `resources/views/game/inventory/index.blade.php` with:
```blade
@extends('layouts.game')
@section('title', 'Inventory')
@section('game-content')
<div class="max-w-4xl mx-auto">
<div class="bg-syndicate-800 border border-syndicate-700 rounded-lg">
<div class="px-6 py-4 border-b border-syndicate-700">
<h1 class="font-display text-xl font-semibold text-gray-100">Inventory</h1>
<p class="mt-1 text-sm text-gray-400">Equip weapons and armor, or use consumables.</p>
</div>
<div class="p-6">
@if($inventory->isEmpty())
<p class="text-center text-gray-500 py-8 text-sm">Your inventory is empty.</p>
@else
<div class="space-y-6">
@foreach($inventory->groupBy('item.type') as $type => $items)
<div>
<h3 class="font-display text-base font-semibold text-gray-300 capitalize mb-3">
{{ ucfirst($type) }}s ({{ $items->sum('quantity') }})
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
@foreach($items as $item)
<div class="bg-syndicate-700 border border-syndicate-600 rounded-lg p-4">
<div class="flex justify-between items-start mb-2">
<div>
<h4 class="font-medium text-gray-100">{{ $item->item->name }}</h4>
<p class="text-xs text-gray-500">x{{ $item->quantity }}</p>
</div>
@if($item->equipped)
<span class="text-xs px-2 py-1 bg-green-800/60 border border-green-700 text-green-400 rounded-full">Equipped</span>
@endif
</div>
@if($item->item->description)
<p class="text-sm text-gray-400 mb-3">{{ Str::limit($item->item->description, 80) }}</p>
@endif
<div class="grid grid-cols-2 gap-2 text-xs text-gray-400 mb-3">
@if($item->item->attack_bonus > 0)
<div class="flex items-center space-x-1">
<span class="text-crime-400">⚔️</span>
<span>+{{ $item->item->attack_bonus }} Attack</span>
</div>
@endif
@if($item->item->defense_bonus > 0)
<div class="flex items-center space-x-1">
<span class="text-blue-400">🛡️</span>
<span>+{{ $item->item->defense_bonus }} Defense</span>
</div>
@endif
@if($item->item->health_bonus > 0)
<div class="flex items-center space-x-1">
<span class="text-green-400">❤️</span>
<span>+{{ $item->item->health_bonus }} Health</span>
</div>
@endif
@if($item->item->energy_bonus > 0)
<div class="flex items-center space-x-1">
<span class="text-yellow-400">⚡</span>
<span>+{{ $item->item->energy_bonus }} Energy</span>
</div>
@endif
</div>
<div class="flex space-x-2">
@if($item->item->canEquip())
@if($item->equipped)
<form action="{{ route('game.inventory.unequip', $item) }}" method="POST">
@csrf
<button type="submit"
class="px-3 py-1 text-xs bg-syndicate-600 hover:bg-syndicate-500 text-gray-300 rounded transition">
Unequip
</button>
</form>
@else
<form action="{{ route('game.inventory.equip', $item) }}" method="POST">
@csrf
<button type="submit"
class="px-3 py-1 text-xs bg-crime-600 hover:bg-crime-500 text-white rounded transition">
Equip
</button>
</form>
@endif
@endif
@if($item->item->canUse())
<form action="{{ route('game.inventory.use', $item) }}" method="POST">
@csrf
<button type="submit"
class="px-3 py-1 text-xs bg-green-700 hover:bg-green-600 text-white rounded transition">
Use
</button>
</form>
@endif
<form action="{{ route('game.inventory.drop', $item) }}" method="POST">
@csrf
<input type="number" name="quantity" value="1" min="1" max="{{ $item->quantity }}" class="hidden">
<button type="submit"
class="px-3 py-1 text-xs bg-red-900/60 hover:bg-red-800/80 border border-red-800 text-red-400 rounded transition">
Drop
</button>
</form>
</div>
</div>
@endforeach
</div>
</div>
@endforeach
</div>
@endif
</div>
</div>
</div>
@endsection
```
- [ ] **Step 2: Replace hospital.blade.php**
Replace `resources/views/game/hospital.blade.php` with:
```blade
@extends('layouts.game')
@section('title', 'Hospital')
@section('game-content')
<div class="max-w-2xl mx-auto">
<div class="bg-syndicate-800 border border-syndicate-700 rounded-lg">
<div class="p-8 text-center">
<div class="mb-6">
<span class="text-6xl">🏥</span>
</div>
<h1 class="font-display text-2xl font-bold text-gray-100 mb-4">You're in the Hospital</h1>
<p class="text-gray-400 mb-6 text-sm">Your character has been injured and is currently recovering.</p>
<div class="bg-red-900/20 border border-red-800 rounded-lg p-6 mb-6 text-left">
<h3 class="font-display text-base font-semibold text-red-300 mb-3">Your Status</h3>
<div class="space-y-2 text-sm">
<div class="flex justify-between">
<span class="text-gray-400">Health</span>
<span class="text-gray-200 font-medium">{{ $character->health }}/{{ $character->max_health }}</span>
</div>
<div class="flex justify-between">
<span class="text-gray-400">Status</span>
<span class="text-red-400 font-medium">
@if($character->health <= 0) Dead @else In Hospital @endif
</span>
</div>
<div class="flex justify-between">
<span class="text-gray-400">Release Time</span>
<span class="text-gray-200 font-medium">{{ $releaseTime }}</span>
</div>
</div>
</div>
<div class="space-y-4">
<form action="{{ route('game.character.revive') }}" method="POST">
@csrf
<button type="submit"
class="w-full flex items-center justify-center px-6 py-4 bg-green-700 hover:bg-green-600 text-white font-medium rounded-lg transition">
<span class="mr-2">💵</span>
Revive Now for ${{ number_format($reviveCost) }}
</button>
</form>
<p class="text-sm text-gray-600">Or wait to be automatically released when your health regenerates.</p>
<a href="{{ route('game.dashboard') }}"
class="inline-flex items-center text-gray-500 hover:text-gray-300 transition text-sm">
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
</svg>
Back to Dashboard
</a>
</div>
</div>
</div>
</div>
@endsection
```
- [ ] **Step 3: Replace jail.blade.php**
Replace `resources/views/game/jail.blade.php` with:
```blade
@extends('layouts.game')
@section('title', 'Jail')
@section('game-content')
<div class="max-w-2xl mx-auto">
<div class="bg-syndicate-800 border border-syndicate-700 rounded-lg">
<div class="p-8 text-center">
<div class="mb-6">
<span class="text-6xl">🚔</span>
</div>
<h1 class="font-display text-2xl font-bold text-gray-100 mb-4">You're in Jail</h1>
<p class="text-gray-400 mb-6 text-sm">Your character has been arrested and is currently serving time.</p>
<div class="bg-yellow-900/20 border border-yellow-800 rounded-lg p-6 mb-6 text-left">
<h3 class="font-display text-base font-semibold text-yellow-300 mb-3">Your Status</h3>
<div class="space-y-2 text-sm">
<div class="flex justify-between">
<span class="text-gray-400">Status</span>
<span class="text-yellow-400 font-medium">In Jail</span>
</div>
<div class="flex justify-between">
<span class="text-gray-400">Release Time</span>
<span class="text-gray-200 font-medium">{{ $releaseTime }}</span>
</div>
</div>
</div>
<div class="space-y-4">
<p class="text-sm text-gray-600">You must wait for your sentence to complete.</p>
<a href="{{ route('game.dashboard') }}"
class="inline-flex items-center text-gray-500 hover:text-gray-300 transition text-sm">
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" />
</svg>
Back to Dashboard
</a>
</div>
</div>
</div>
</div>
@endsection
```
- [ ] **Step 4: Build assets**
```bash
cd /home/liquidsky/Projects/thecrimesyndicate && npm run build 2>&1 | tail -5
```
Expected: build succeeds.
- [ ] **Step 5: Commit**
```bash
cd /home/liquidsky/Projects/thecrimesyndicate
git add resources/views/game/inventory/index.blade.php resources/views/game/hospital.blade.php resources/views/game/jail.blade.php
git commit -m "feat: restyle inventory, hospital, and jail pages with dark crime theme"
```
---
## Self-Review Checklist
**Spec coverage:**
- ✅ Color system (syndicate/crime/gold) — Task 1
- ✅ Typography (Inter + Rajdhani) — Task 1
- ✅ `app.blade.php` dark body — Task 1
- ✅ `guest.blade.php` dark auth layout — Task 1
- ✅ Game layout (sidebar + top bar) — Task 2
- ✅ Sidebar nav links with conditional Hospital/Jail — Task 2
- ✅ Stats bar compact pills (HP/Energy/Cash/Level) — Task 2
- ✅ Flash messages dark variant — Task 2 (inside game.blade.php)
- ✅ Primary/Secondary/Ghost buttons — Task 3
- ✅ Dark text-input and input-label — Task 3
- ✅ Dashboard restyled — Task 4
- ✅ Crimes page restyled — Task 5
- ✅ Inventory page restyled — Task 6
- ✅ Hospital page restyled — Task 6
- ✅ Jail page restyled — Task 6
**No placeholders found.**
**Type/name consistency:**
- `CharacterStatus::ACTIVE`, `CharacterStatus::IN_HOSPITAL`, `CharacterStatus::IN_JAIL` — consistent across Tasks 2 and 4
- `$character->status->color()` / `->label()` — consistent with the enum definition
- Color tokens identical across all tasks (no drift)