Files
thecrimesynticate/docs/superpowers/plans/2026-06-28-dark-crime-theme.md
T
2026-06-28 03:19:32 +03:00

52 KiB

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:

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:

<!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:

<!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:

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
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:

@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:

<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:

@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
cd /home/liquidsky/Projects/thecrimesyndicate && npm run build 2>&1 | tail -20

Expected: build succeeds with no errors.

  • Step 5: Commit
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:

<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:

<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:

@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:

@props(['value'])

<label {{ $attributes->merge(['class' => 'block font-medium text-sm text-gray-300']) }}>
    {{ $value ?? $slot }}
</label>
  • Step 5: Build assets
cd /home/liquidsky/Projects/thecrimesyndicate && npm run build 2>&1 | tail -20

Expected: build succeeds with no errors.

  • Step 6: Commit
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:

@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
cd /home/liquidsky/Projects/thecrimesyndicate && npm run build 2>&1 | tail -20

Expected: build succeeds.

  • Step 3: Commit
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:

@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
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:

@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:

@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:

@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
cd /home/liquidsky/Projects/thecrimesyndicate && npm run build 2>&1 | tail -5

Expected: build succeeds.

  • Step 5: Commit
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)