VibeCoderzVibeCoderz
Telegram
All Prompts
LexaFlow AI - Legal Review Hub UI Preview

LexaFlow AI - Legal Review Hub

Интерактивный прототип приложения для юристов: управление контрактами, AI-анализ, блокировка, принятие решений и передача дел. Демонстрация UI/UX.

by We Are Viewtiful creative studioLive Preview

Prompt

# LexaFlow AI - Legal Review Hub

Build a FULLY FUNCTIONAL interactive prototype for an internal legal contract review app. Single-page HTML application with state management and full interactivity.

STRUCTURE:

1. Start Page (Action Queue):

   - 4 lanes: "Ready to Review", "Blocked", "Ready to Decide", "Ready to Hand Off"
   - 5 realistic sample cases distributed across lanes
   - Click any case to open Request Details page
   - Triage summary bar at top shows count of cases in each lane

2. Request Details Page:

   - Full case information hierarchy (ID, title, priority, status, ownership, due date, context fields)
   - AI case brief section (clearly labeled as AI-generated)
   - Primary CTA (changes based on case state: Review, Unblock, Make Decision, Hand Off)
   - Case sections: Description, Attachments (grouped), Stakeholders, Communication Thread, Audit Log
   - Progressive disclosure: Secondary info in collapsible drawers/panels

3. INTERACTIVE BEHAVIORS:\
   a) Block/Unblock Flow:

   - When case is blocked, UI switches to "blocked mode" (visual distinction, top accent bar)
   - Blocker reason is prominent
   - Primary CTA: "Escalate to [Owner]" or "Follow Up with [Stakeholder]"
   - "Unblock" button opens modal to record resolution
   - Clicking unblock moves case back to previous action type lane
   - Audit log records: who blocked, reason, who unblocked, resolution, timestamp

   b) Make Decision Flow:

   - "Ready to Decide" cases show key risk identified by AI
   - 3 action buttons: "Approve", "Approve with Conditions", "Escalate/Reject"
   - Clicking any decision opens modal with reason input field
   - After decision, case moves to "Ready to Hand Off" lane
   - Audit log records decision, reason, who decided, timestamp

   c) Hand Off Flow:

   - Shows next owner and handoff checklist
   - "Complete Handoff" button opens modal with pre-filled next owner
   - After handoff, case moves to completed state (case disappears from queue or moves to history)
   - Audit log records handoff info

   d) Audit Trail:

   - Full timeline of all actions: created, reviewed changes, decisions made, blocks/unblocks, handoffs
   - Each entry shows: action, actor, timestamp, reason/notes, AI involvement (if applicable)
   - Audit log is read-only and always visible in case details

4. SAMPLE DATA (5 cases):

   - Case 1: "Globex Vendor Agreement" - Ready to Review, HIGH priority, due in 2 days, new redline detected
   - Case 2: "InfoSec SLA Amendment" - Blocked, waiting on InfoSec clarification, assigned to Marcus (you're waiting on him)
   - Case 3: "Cloud Services MSA" - Ready to Decide, medium risk identified, needs legal judgment
   - Case 4: "Maintenance Contract Renewal" - Ready to Hand Off, legal review complete, going to Procurement
   - Case 5: "Data Processing Agreement" - Blocked, missing client input, overdue (escalation needed)

5. VISUAL DESIGN:

   - Modern enterprise aesthetic, clean hierarchy
   - Color-coded action types (blue=review, red/orange=blocked, amber=decide, green=handoff)
   - Use distinctive typography for scanning (Plus Jakarta Sans or similar)
   - Modal dialogs for confirmations and reason inputs
   - Toast notifications for state changes ("Case unblocked!", "Decision recorded")
   - Audit log uses compact timeline format (not tables)

6. TECHNICAL IMPLEMENTATION:

   - Use vanilla JS with DOM state management (no frameworks)
   - Data stored in local state (not persistent, just for demo)
   - Navigation between Start Page and Case Details via JS (no page reloads)
   - Forms with validation before state change
   - Real timestamps for audit entries
   - Progressive disclosure using data-state attributes and CSS classes

CRITICAL INTERACTION REQUIREMENTS:

- Block state logic: When case is blocked, "Review" button is disabled, blocker reason blocks the primary action path
- Unblock modal: Requires reason input before allowing state change
- Decision modal: Requires one of 3 decision options + optional reason
- Handoff modal: Shows next owner, checklist status, and requires confirmation
- Audit log: Always shows complete history, updates in real-time as actions occur
- State persistence across page views: If user blocks a case, goes back to start page, then re-enters case, it's still blocked

Enterprise focus, clear accountability, no generic dashboards.

Here is a reference implementation:

~~~html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>LexaFlow AI | Internal Legal Review</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://code.iconify.design/iconify-icon/1.0.7/iconify-icon.min.js"></script>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
    <style>
        body {
            font-family: 'Plus Jakarta Sans', sans-serif;
            background-color: #f8fafc;
        }
        .custom-scrollbar::-webkit-scrollbar {
            width: 6px;
        }
        .custom-scrollbar::-webkit-scrollbar-track {
            background: transparent;
        }
        .custom-scrollbar::-webkit-scrollbar-thumb {
            background: #e2e8f0;
            border-radius: 10px;
        }
        .lane-height {
            height: calc(100vh - 240px);
        }
        .modal-enter {
            animation: modalFadeIn 0.2s cubic-bezier(0.16, 1, 0.3, 1);
        }
        @keyframes modalFadeIn {
            from { opacity: 0; transform: scale(0.95); }
            to { opacity: 1; transform: scale(1); }
        }
        .blocked-accent {
            background: repeating-linear-gradient(
                45deg,
                #fee2e2,
                #fee2e2 10px,
                #fef2f2 10px,
                #fef2f2 20px
            );
        }
        .transition-view {
            transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;
        }
    </style>
</head>
<body>
    <div id="app-root" class="min-h-screen flex flex-col">
        <!-- State Management will render here -->
    </div>

    <!-- Template: Toast Notifications -->
    <div id="toast-container" class="fixed bottom-8 right-8 z-50 flex flex-col gap-3"></div>

    <script>
        // --- STATE MANAGEMENT ---
        const INITIAL_CASES = [
            {
                id: "LGL-2024-001",
                title: "Globex Vendor Agreement",
                priority: "High",
                status: "Ready to Review",
                step: "Legal Review",
                owner: "Sarah Jenkins",
                dueDate: "2024-05-24",
                dept: "Procurement",
                region: "EMEA",
                value: "$240,000",
                account: "Globex Corp",
                description: "Standard vendor master agreement for logistics services. Key concerns around liability caps and data indemnity clauses in Section 14.",
                aiBrief: "New redline detected in Section 14.3. The vendor has proposed a 1x contract value liability cap, which deviates from our standard 3x requirement. Previous 3 agreements with Globex accepted 2x.",
                isBlocked: false,
                blockerReason: "",
                attachments: {
                    primary: [{ name: "Master_Agreement_v3_REDLINE.docx", size: "2.4MB", date: "2 hours ago" }],
                    supporting: [{ name: "Vendor_Risk_Assessment.pdf", size: "840KB", date: "Yesterday" }],
                    history: [{ name: "v2_Draft.docx", date: "May 20" }, { name: "v1_Original.docx", date: "May 18" }]
                },
                stakeholders: [
                    { name: "Mark Thompson", role: "Procurement Lead", avatar: "MT" },
                    { name: "Elena Rossi", role: "InfoSec", avatar: "ER" }
                ],
                auditLog: [
                    { action: "Case Created", user: "System", timestamp: "2024-05-18 09:15", note: "Request initiated via Workday" },
                    { action: "Assigned", user: "Alex Chen", timestamp: "2024-05-18 10:00", note: "Assigned to Legal (Sarah Jenkins)" }
                ]
            },
            {
                id: "LGL-2024-002",
                title: "InfoSec SLA Amendment",
                priority: "Medium",
                status: "Blocked",
                step: "Security Validation",
                owner: "Marcus Wright",
                dueDate: "2024-05-26",
                dept: "IT Infrastructure",
                region: "Global",
                value: "$0",
                account: "AWS Services",
                description: "Updating the uptime availability metrics for core cloud infrastructure to align with 2024 corporate reliability standards.",
                aiBrief: "Case is currently stalled. InfoSec has not responded to the last 3 pings regarding the uptime calculation methodology.",
                isBlocked: true,
                blockerReason: "Waiting on InfoSec clarification for Section 4.2 (Uptime Credits)",
                attachments: { primary: [{ name: "SLA_Amendment_Final.pdf", size: "1.1MB", date: "3 days ago" }], supporting: [], history: [] },
                stakeholders: [{ name: "Marcus Wright", role: "InfoSec Specialist", avatar: "MW" }],
                auditLog: [
                    { action: "Blocked", user: "Sarah Jenkins", timestamp: "2024-05-21 14:20", note: "Infrastructure team hasn't provided the availability formulas." }
                ]
            },
            {
                id: "LGL-2024-003",
                title: "Cloud Services MSA",
                priority: "High",
                status: "Ready to Decide",
                step: "Final Approval",
                owner: "Legal Lead",
                dueDate: "2024-05-23",
                dept: "Technology",
                region: "NAMER",
                value: "$1.2M",
                account: "Azure Enterprise",
                description: "New Master Services Agreement for regional cloud expansion. Significant investment with standard terms, but requires executive sign-off due to deal size.",
                aiBrief: "Medium risk identified: Jurisdiction set to Delaware but our standard is New York. However, Finance has approved the $1.2M budget allocation.",
                isBlocked: false,
                blockerReason: "",
                attachments: { primary: [{ name: "Azure_MSA_v5.docx", size: "4.2MB", date: "1 day ago" }], supporting: [{ name: "Budget_Approval.msg", size: "45KB", date: "May 21" }], history: [] },
                stakeholders: [{ name: "Janet Yuen", role: "Finance VP", avatar: "JY" }],
                auditLog: [
                    { action: "Review Completed", user: "Sarah Jenkins", timestamp: "2024-05-22 11:30", note: "Ready for final decision." }
                ]
            },
            {
                id: "LGL-2024-004",
                title: "Maintenance Contract",
                priority: "Low",
                status: "Ready to Hand Off",
                step: "Post-Review",
                owner: "Sarah Jenkins",
                dueDate: "2024-06-05",
                dept: "Facilities",
                region: "APAC",
                value: "$45,000",
                account: "Abesco Facilities",
                description: "Annual renewal for office maintenance services in Singapore office. No changes from previous year's terms.",
                aiBrief: "No critical changes detected from 2023 version. 100% compliance with current templates. Ready for Procurement execution.",
                isBlocked: false,
                blockerReason: "",
                attachments: { primary: [{ name: "Renewal_2024.pdf", size: "240KB", date: "May 15" }], supporting: [], history: [] },
                stakeholders: [{ name: "Liam Tan", role: "Facilities Manager", avatar: "LT" }],
                auditLog: [
                    { action: "Decision Made", user: "Sarah Jenkins", timestamp: "2024-05-20 15:45", note: "Approved without conditions." }
                ]
            },
            {
                id: "LGL-2024-005",
                title: "Data Processing Agreement",
                priority: "High",
                status: "Blocked",
                step: "Privacy Review",
                owner: "Privacy Officer",
                dueDate: "2024-05-20",
                dept: "Marketing",
                region: "APAC",
                value: "$12,000",
                account: "SendGrid",
                description: "DPA for new marketing email automation tool. Specifically focusing on data residency in Singapore.",
                aiBrief: "CRITICAL: Missing client data retention policy input. Without this, the privacy review cannot proceed.",
                isBlocked: true,
                blockerReason: "Missing client input for data retention periods (Section 8)",
                attachments: { primary: [{ name: "SendGrid_DPA.docx", size: "1.8MB", date: "May 12" }], supporting: [], history: [] },
                stakeholders: [{ name: "Chloe Sim", role: "Privacy Officer", avatar: "CS" }],
                auditLog: [
                    { action: "Blocked", user: "Chloe Sim", timestamp: "2024-05-19 10:10", note: "Awaiting marketing to provide data retention schedule." }
                ]
            }
        ];

        let state = {
            cases: [...INITIAL_CASES],
            view: 'queue', // 'queue' or 'details'
            activeCaseId: null,
            notification: null
        };

        // --- HELPERS ---
        const saveState = () => {
            // In a real app, this would persist to a DB
        };

        const showToast = (message, type = 'success') => {
            const container = document.getElementById('toast-container');
            const toast = document.createElement('div');
            toast.className = `flex items-center gap-3 px-4 py-3 rounded-xl shadow-lg border animate-bounce-in ${
                type === 'success' ? 'bg-emerald-50 border-emerald-200 text-emerald-800' : 'bg-rose-50 border-rose-200 text-rose-800'
            }`;
            toast.innerHTML = `
                <iconify-icon icon="${type === 'success' ? 'lucide:check-circle' : 'lucide:alert-circle'}"></iconify-icon>
                <span class="font-medium">${message}</span>
            `;
            container.appendChild(toast);
            setTimeout(() => {
                toast.classList.add('opacity-0', 'translate-y-2', 'transition-all', 'duration-300');
                setTimeout(() => toast.remove(), 300);
            }, 3000);
        };

        // --- RENDERING LOGIC ---
        const render = () => {
            const root = document.getElementById('app-root');
            root.innerHTML = '';

            if (state.view === 'queue') {
                root.appendChild(renderQueue());
            } else {
                root.appendChild(renderDetails(state.activeCaseId));
            }
        };

        const renderQueue = () => {
            const container = document.createElement('div');
            container.className = "flex-1 flex flex-col p-8 overflow-hidden";

            // Header/Summary
            const counts = {
                'Ready to Review': state.cases.filter(c => c.status === 'Ready to Review').length,
                'Blocked': state.cases.filter(c => c.status === 'Blocked').length,
                'Ready to Decide': state.cases.filter(c => c.status === 'Ready to Decide').length,
                'Ready to Hand Off': state.cases.filter(c => c.status === 'Ready to Hand Off').length
            };

            container.innerHTML = `
                <header class="flex justify-between items-end mb-8">
                    <div>
                        <h1 class="text-3xl font-extrabold text-slate-900 tracking-tight">Action Queue</h1>
                        <p class="text-slate-500 mt-1 font-medium">Legal Review Operations & AI Copilot</p>
                    </div>
                    <div class="flex gap-4">
                        <div class="flex items-center bg-white border border-slate-200 rounded-lg px-4 py-2 gap-3">
                            <div class="text-xs font-bold text-slate-400 uppercase tracking-widest">Efficiency Score</div>
                            <div class="text-xl font-bold text-indigo-600">92%</div>
                        </div>
                    </div>
                </header>

                <div class="grid grid-cols-4 gap-4 mb-8">
                    <div class="bg-white rounded-2xl p-5 border border-slate-200 shadow-sm">
                        <div class="flex justify-between items-start">
                            <span class="p-2 bg-sky-50 text-sky-600 rounded-lg"><iconify-icon icon="lucide:glasses"></iconify-icon></span>
                            <span class="text-2xl font-bold">${counts['Ready to Review']}</span>
                        </div>
                        <p class="text-sm font-semibold text-slate-500 mt-3 uppercase tracking-wider">To Review</p>
                    </div>
                    <div class="bg-white rounded-2xl p-5 border border-slate-200 shadow-sm">
                        <div class="flex justify-between items-start">
                            <span class="p-2 bg-rose-50 text-rose-600 rounded-lg"><iconify-icon icon="lucide:octagon-pause"></iconify-icon></span>
                            <span class="text-2xl font-bold">${counts['Blocked']}</span>
                        </div>
                        <p class="text-sm font-semibold text-slate-500 mt-3 uppercase tracking-wider">Blocked</p>
                    </div>
                    <div class="bg-white rounded-2xl p-5 border border-slate-200 shadow-sm">
                        <div class="flex justify-between items-start">
                            <span class="p-2 bg-amber-50 text-amber-600 rounded-lg"><iconify-icon icon="lucide:gavel"></iconify-icon></span>
                            <span class="text-2xl font-bold">${counts['Ready to Decide']}</span>
                        </div>
                        <p class="text-sm font-semibold text-slate-500 mt-3 uppercase tracking-wider">To Decide</p>
                    </div>
                    <div class="bg-white rounded-2xl p-5 border border-slate-200 shadow-sm">
                        <div class="flex justify-between items-start">
                            <span class="p-2 bg-emerald-50 text-emerald-600 rounded-lg"><iconify-icon icon="lucide:send"></iconify-icon></span>
                            <span class="text-2xl font-bold">${counts['Ready to Hand Off']}</span>
                        </div>
                        <p class="text-sm font-semibold text-slate-500 mt-3 uppercase tracking-wider">To Hand Off</p>
                    </div>
                </div>

                <div class="flex gap-6 flex-1 overflow-x-auto pb-4">
                    ${renderLane('Ready to Review', 'sky', 'lucide:glasses')}
                    ${renderLane('Blocked', 'rose', 'lucide:octagon-pause')}
                    ${renderLane('Ready to Decide', 'amber', 'lucide:gavel')}
                    ${renderLane('Ready to Hand Off', 'emerald', 'lucide:send')}
                </div>
            `;

            return container;
        };

        const renderLane = (status, color, icon) => {
            const casesInLane = state.cases.filter(c => c.status === status);
            return `
                <div class="flex-1 min-w-[320px] flex flex-col">
                    <div class="flex items-center justify-between mb-4">
                        <div class="flex items-center gap-2">
                            <div class="w-2 h-2 rounded-full bg-${color}-500"></div>
                            <h3 class="font-bold text-slate-800">${status}</h3>
                            <span class="px-2 py-0.5 bg-slate-200 text-slate-600 text-xs font-bold rounded-full">${casesInLane.length}</span>
                        </div>
                    </div>
                    <div class="flex-1 bg-slate-100/50 rounded-2xl p-3 flex flex-col gap-3 overflow-y-auto custom-scrollbar">
                        ${casesInLane.map(c => renderCaseCard(c, color)).join('')}
                        ${casesInLane.length === 0 ? '<div class="text-center py-12 text-slate-400 text-sm italic">Queue Clear</div>' : ''}
                    </div>
                </div>
            `;
        };

        const renderCaseCard = (c, color) => {
            const priorityColors = {
                'High': 'text-rose-600 bg-rose-50',
                'Medium': 'text-amber-600 bg-amber-50',
                'Low': 'text-emerald-600 bg-emerald-50'
            };
            
            return `
                <div onclick="openCase('${c.id}')" class="group bg-white p-4 rounded-xl border border-slate-200 shadow-sm hover:shadow-md hover:border-${color}-300 transition-all cursor-pointer">
                    <div class="flex justify-between items-start mb-2">
                        <span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">${c.id}</span>
                        <span class="px-2 py-0.5 rounded text-[10px] font-bold uppercase tracking-tighter ${priorityColors[c.priority]}">${c.priority}</span>
                    </div>
                    <h4 class="font-bold text-slate-900 group-hover:text-indigo-600 transition-colors leading-tight mb-2">${c.title}</h4>
                    <div class="flex items-center justify-between mt-4 pt-4 border-t border-slate-50">
                        <div class="flex items-center gap-2">
                            <div class="w-6 h-6 rounded-full bg-slate-200 flex items-center justify-center text-[10px] font-bold text-slate-600">${c.stakeholders[0]?.avatar || '??'}</div>
                            <span class="text-xs font-semibold text-slate-500 truncate max-w-[80px]">${c.owner}</span>
                        </div>
                        <div class="text-xs font-bold text-slate-400 flex items-center gap-1">
                            <iconify-icon icon="lucide:calendar"></iconify-icon>
                            ${c.dueDate}
                        </div>
                    </div>
                </div>
            `;
        };

        const renderDetails = (caseId) => {
            const c = state.cases.find(item => item.id === caseId);
            if (!c) return document.createElement('div');

            const container = document.createElement('div');
            container.className = "flex-1 flex flex-col h-screen overflow-hidden";

            container.innerHTML = `
                <!-- Case Header Bar -->
                <div class="h-16 bg-white border-b border-slate-200 flex items-center justify-between px-8 shrink-0">
                    <div class="flex items-center gap-4">
                        <button onclick="backToQueue()" class="p-2 hover:bg-slate-100 rounded-lg text-slate-500 transition-colors">
                            <iconify-icon icon="lucide:arrow-left" class="text-xl"></iconify-icon>
                        </button>
                        <div class="h-6 w-px bg-slate-200"></div>
                        <div>
                            <div class="flex items-center gap-2">
                                <span class="text-xs font-bold text-slate-400 tracking-widest">${c.id}</span>
                                <span class="px-2 py-0.5 bg-slate-100 text-slate-600 text-[10px] font-bold rounded">${c.step.toUpperCase()}</span>
                            </div>
                            <h2 class="font-bold text-slate-900">${c.title}</h2>
                        </div>
                    </div>
                    <div class="flex items-center gap-4">
                        <div class="flex -space-x-2">
                            ${c.stakeholders.map(s => `<div title="${s.name} (${s.role})" class="w-8 h-8 rounded-full bg-indigo-100 border-2 border-white flex items-center justify-center text-xs font-bold text-indigo-600">${s.avatar}</div>`).join('')}
                            <div class="w-8 h-8 rounded-full bg-slate-100 border-2 border-white flex items-center justify-center text-xs font-bold text-slate-400 cursor-pointer hover:bg-slate-200 transition-colors">+</div>
                        </div>
                        <button class="px-4 py-2 text-sm font-semibold text-slate-600 hover:bg-slate-100 rounded-lg transition-colors">
                            Share Case
                        </button>
                    </div>
                </div>

                <!-- Main Scrollable Area -->
                <div class="flex-1 flex overflow-hidden">
                    <!-- Left Sidebar (Details) -->
                    <div class="w-80 border-r border-slate-200 bg-white overflow-y-auto custom-scrollbar p-6 flex flex-col gap-8 shrink-0">
                        <div>
                            <h3 class="text-xs font-bold text-slate-400 uppercase tracking-widest mb-4">Context</h3>
                            <dl class="grid grid-cols-1 gap-4">
                                <div>
                                    <dt class="text-[10px] uppercase font-bold text-slate-400">Account</dt>
                                    <dd class="text-sm font-semibold text-slate-800">${c.account}</dd>
                                </div>
                                <div>
                                    <dt class="text-[10px] uppercase font-bold text-slate-400">Department</dt>
                                    <dd class="text-sm font-semibold text-slate-800">${c.dept}</dd>
                                </div>
                                <div>
                                    <dt class="text-[10px] uppercase font-bold text-slate-400">Contract Value</dt>
                                    <dd class="text-sm font-semibold text-indigo-600 font-bold">${c.value}</dd>
                                </div>
                                <div>
                                    <dt class="text-[10px] uppercase font-bold text-slate-400">Region</dt>
                                    <dd class="text-sm font-semibold text-slate-800">${c.region}</dd>
                                </div>
                            </dl>
                        </div>

                        <div>
                            <h3 class="text-xs font-bold text-slate-400 uppercase tracking-widest mb-4">Primary Stakeholders</h3>
                            <div class="space-y-3">
                                ${c.stakeholders.map(s => `
                                    <div class="flex items-center gap-3">
                                        <div class="w-10 h-10 rounded-xl bg-slate-100 flex items-center justify-center font-bold text-slate-600">${s.avatar}</div>
                                        <div>
                                            <p class="text-sm font-bold text-slate-800">${s.name}</p>
                                            <p class="text-xs text-slate-500 font-medium">${s.role}</p>
                                        </div>
                                    </div>
                                `).join('')}
                            </div>
                        </div>

                        <div class="mt-auto p-4 bg-slate-50 rounded-xl border border-slate-200">
                            <button onclick="openModal('audit')" class="w-full flex items-center justify-between text-xs font-bold text-slate-600 uppercase tracking-widest hover:text-indigo-600 transition-colors">
                                Full Audit Log
                                <iconify-icon icon="lucide:history"></iconify-icon>
                            </button>
                        </div>
                    </div>

                    <!-- Center Content -->
                    <div class="flex-1 overflow-y-auto custom-scrollbar flex flex-col">
                        ${c.isBlocked ? `
                            <div class="blocked-accent border-b border-rose-200 px-8 py-4 flex items-center justify-between sticky top-0 z-10">
                                <div class="flex items-center gap-4 text-rose-800">
                                    <div class="w-10 h-10 rounded-full bg-rose-500 text-white flex items-center justify-center">
                                        <iconify-icon icon="lucide:octagon-pause" class="text-xl"></iconify-icon>
                                    </div>
                                    <div>
                                        <h4 class="font-extrabold">CASE BLOCKED</h4>
                                        <p class="text-sm font-medium">${c.blockerReason}</p>
                                    </div>
                                </div>
                                <button onclick="openModal('unblock')" class="bg-rose-600 hover:bg-rose-700 text-white px-6 py-2.5 rounded-xl font-bold shadow-lg shadow-rose-200 transition-all flex items-center gap-2">
                                    Resolve Blocker
                                    <iconify-icon icon="lucide:arrow-right-circle"></iconify-icon>
                                </button>
                            </div>
                        ` : ''}

                        <div class="p-8 max-w-4xl mx-auto w-full">
                            <!-- AI Brief Section -->
                            <div class="bg-indigo-50 border border-indigo-100 rounded-2xl p-6 mb-8 relative overflow-hidden">
                                <div class="flex items-center gap-3 mb-4">
                                    <div class="flex items-center justify-center p-2 bg-indigo-600 text-white rounded-lg">
                                        <iconify-icon icon="lucide:sparkles"></iconify-icon>
                                    </div>
                                    <div>
                                        <h3 class="font-bold text-indigo-900">AI Case Brief</h3>
                                        <p class="text-[10px] font-bold text-indigo-400 uppercase tracking-widest">Analysis generated 2m ago</p>
                                    </div>
                                </div>
                                <p class="text-indigo-800 font-medium leading-relaxed">
                                    ${c.aiBrief}
                                </p>
                                <div class="absolute top-0 right-0 w-32 h-32 bg-indigo-100/50 blur-3xl -z-1"></div>
                            </div>

                            <!-- Action Section (Changes based on status) -->
                            <div class="mb-12">
                                <div class="flex items-center justify-between mb-6">
                                    <h3 class="text-xl font-extrabold text-slate-900">Primary Work Area</h3>
                                    ${!c.isBlocked ? `
                                        <div class="flex gap-2">
                                            <button onclick="openModal('block')" class="text-xs font-bold text-slate-400 hover:text-rose-600 flex items-center gap-1 transition-colors uppercase tracking-widest">
                                                <iconify-icon icon="lucide:pause-circle"></iconify-icon>
                                                Flag Blocker
                                            </button>
                                        </div>
                                    ` : ''}
                                </div>

                                <div class="bg-white border border-slate-200 rounded-2xl p-8">
                                    ${renderActionContent(c)}
                                </div>
                            </div>

                            <!-- Documentation Section -->
                            <div class="space-y-6">
                                <h3 class="text-lg font-bold text-slate-900 flex items-center gap-2">
                                    <iconify-icon icon="lucide:file-text" class="text-slate-400"></iconify-icon>
                                    Attachments
                                </h3>
                                
                                <div class="grid grid-cols-2 gap-4">
                                    <div class="col-span-2 bg-slate-50 border border-slate-200 rounded-xl p-4">
                                        <p class="text-[10px] uppercase font-bold text-slate-400 mb-3">Primary Document</p>
                                        <div class="flex items-center justify-between bg-white p-4 rounded-lg border border-slate-200">
                                            <div class="flex items-center gap-3">
                                                <iconify-icon icon="lucide:file-word" class="text-3xl text-sky-500"></iconify-icon>
                                                <div>
                                                    <p class="text-sm font-bold text-slate-800">${c.attachments.primary[0].name}</p>
                                                    <p class="text-xs text-slate-500 font-medium">${c.attachments.primary[0].size} • ${c.attachments.primary[0].date}</p>
                                                </div>
                                            </div>
                                            <button class="p-2 hover:bg-slate-100 rounded-lg transition-colors">
                                                <iconify-icon icon="lucide:download"></iconify-icon>
                                            </button>
                                        </div>
                                    </div>

                                    <details class="col-span-1 group">
                                        <summary class="list-none cursor-pointer p-4 bg-white border border-slate-200 rounded-xl flex items-center justify-between font-bold text-sm text-slate-600">
                                            Supporting Docs (${c.attachments.supporting.length})
                                            <iconify-icon icon="lucide:chevron-down" class="group-open:rotate-180 transition-transform"></iconify-icon>
                                        </summary>
                                        <div class="mt-2 space-y-2 px-1">
                                            ${c.attachments.supporting.length > 0 ? c.attachments.supporting.map(f => `
                                                <div class="flex items-center justify-between p-3 border border-slate-100 rounded-lg">
                                                    <span class="text-xs font-semibold text-slate-700 truncate">${f.name}</span>
                                                    <iconify-icon icon="lucide:eye" class="text-slate-400 cursor-pointer"></iconify-icon>
                                                </div>
                                            `).join('') : '<p class="text-xs text-slate-400 p-2 italic">No supporting docs</p>'}
                                        </div>
                                    </details>

                                    <details class="col-span-1 group">
                                        <summary class="list-none cursor-pointer p-4 bg-white border border-slate-200 rounded-xl flex items-center justify-between font-bold text-sm text-slate-600">
                                            Version History
                                            <iconify-icon icon="lucide:chevron-down" class="group-open:rotate-180 transition-transform"></iconify-icon>
                                        </summary>
                                        <div class="mt-2 space-y-2 px-1">
                                            ${c.attachments.history.length > 0 ? c.attachments.history.map(f => `
                                                <div class="flex items-center justify-between p-3 border border-slate-100 rounded-lg">
                                                    <span class="text-xs font-semibold text-slate-700 truncate">${f.name}</span>
                                                    <span class="text-[10px] font-bold text-slate-400">${f.date}</span>
                                                </div>
                                            `).join('') : '<p class="text-xs text-slate-400 p-2 italic">No previous versions</p>'}
                                        </div>
                                    </details>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            `;

            return container;
        };

        const renderActionContent = (c) => {
            if (c.isBlocked) {
                return `
                    <div class="text-center py-8">
                        <div class="inline-flex items-center justify-center p-4 bg-rose-50 rounded-2xl mb-4">
                            <iconify-icon icon="lucide:lock" class="text-4xl text-rose-500"></iconify-icon>
                        </div>
                        <h4 class="text-lg font-bold text-slate-900 mb-2">Review Stalled</h4>
                        <p class="text-slate-500 max-w-sm mx-auto mb-6">
                            This request is currently flagged as blocked. Please address the outstanding issue with <b>${c.stakeholders[0]?.name}</b> to proceed.
                        </p>
                        <div class="flex justify-center gap-3">
                            <button class="px-6 py-2 border border-slate-200 font-bold rounded-xl text-slate-600 hover:bg-slate-50 transition-all">Nudge Stakeholder</button>
                            <button onclick="openModal('unblock')" class="px-6 py-2 bg-slate-900 text-white font-bold rounded-xl hover:bg-slate-800 transition-all">Resolve Manually</button>
                        </div>
                    </div>
                `;
            }

            if (c.status === 'Ready to Review') {
                return `
                    <div class="flex flex-col gap-6">
                        <div class="flex items-start gap-4 p-4 bg-slate-50 rounded-xl">
                            <iconify-icon icon="lucide:info" class="text-indigo-600 text-xl mt-0.5"></iconify-icon>
                            <p class="text-sm text-slate-600 leading-relaxed">
                                Review the latest redlines in <b>Section 14</b>. AI has identified a deviation from the corporate standard liability cap. Please confirm if the proposed 2x limit is acceptable given the relationship history.
                            </p>
                        </div>
                        <div class="h-40 bg-slate-200/30 border border-dashed border-slate-300 rounded-xl flex flex-col items-center justify-center text-slate-400">
                            <iconify-icon icon="lucide:file-search" class="text-3xl mb-2"></iconify-icon>
                            <p class="text-sm font-medium">Diff View (Click to expand)</p>
                        </div>
                        <div class="flex justify-end gap-3">
                            <button onclick="openModal('decide')" class="px-8 py-3 bg-indigo-600 hover:bg-indigo-700 text-white font-extrabold rounded-xl shadow-lg shadow-indigo-100 transition-all">Complete Review & Decide</button>
                        </div>
                    </div>
                `;
            }

            if (c.status === 'Ready to Decide') {
                return `
                    <div class="flex flex-col items-center py-6">
                        <h4 class="text-xl font-extrabold text-slate-900 mb-2">Final Legal Determination Required</h4>
                        <p class="text-slate-500 text-center max-w-lg mb-8">Review is finished. AI confirms no other major deviations. Choose the final status for this contract.</p>
                        <div class="grid grid-cols-3 gap-4 w-full">
                            <button onclick="submitDecision('Approve')" class="p-6 rounded-2xl border border-emerald-200 bg-emerald-50 hover:bg-emerald-100 transition-all flex flex-col items-center gap-3">
                                <iconify-icon icon="lucide:check-circle" class="text-3xl text-emerald-600"></iconify-icon>
                                <span class="font-extrabold text-emerald-800">Approve</span>
                            </button>
                            <button onclick="submitDecision('Approve with Conditions')" class="p-6 rounded-2xl border border-amber-200 bg-amber-50 hover:bg-amber-100 transition-all flex flex-col items-center gap-3">
                                <iconify-icon icon="lucide:shield-alert" class="text-3xl text-amber-600"></iconify-icon>
                                <span class="font-extrabold text-amber-800">Approve with Conditions</span>
                            </button>
                            <button onclick="submitDecision('Reject')" class="p-6 rounded-2xl border border-rose-200 bg-rose-50 hover:bg-rose-100 transition-all flex flex-col items-center gap-3">
                                <iconify-icon icon="lucide:x-circle" class="text-3xl text-rose-600"></iconify-icon>
                                <span class="font-extrabold text-rose-800">Reject / Redraft</span>
                            </button>
                        </div>
                    </div>
                `;
            }

            if (c.status === 'Ready to Hand Off') {
                return `
                    <div class="flex flex-col gap-6">
                        <div class="p-6 bg-emerald-50 border border-emerald-100 rounded-2xl flex items-center gap-4">
                            <div class="w-12 h-12 rounded-full bg-emerald-500 text-white flex items-center justify-center">
                                <iconify-icon icon="lucide:party-popper" class="text-2xl"></iconify-icon>
                            </div>
                            <div>
                                <h4 class="font-extrabold text-emerald-900">Review Cycle Complete</h4>
                                <p class="text-sm text-emerald-700">Legal sign-off has been recorded in the system.</p>
                            </div>
                        </div>
                        
                        <div>
                            <h5 class="text-[10px] font-bold text-slate-400 uppercase tracking-widest mb-4">Handoff Checklist</h5>
                            <div class="space-y-3">
                                <label class="flex items-center gap-3 bg-white p-3 border border-slate-200 rounded-xl cursor-pointer">
                                    <input type="checkbox" checked disabled class="w-4 h-4 rounded border-slate-300 text-indigo-600">
                                    <span class="text-sm font-semibold text-slate-700">Final version uploaded to Vault</span>
                                </label>
                                <label class="flex items-center gap-3 bg-white p-3 border border-slate-200 rounded-xl cursor-pointer">
                                    <input type="checkbox" checked disabled class="w-4 h-4 rounded border-slate-300 text-indigo-600">
                                    <span class="text-sm font-semibold text-slate-700">Internal approvals documented</span>
                                </label>
                            </div>
                        </div>

                        <div class="flex justify-between items-center p-4 bg-slate-50 border border-slate-200 rounded-xl">
                            <div class="flex items-center gap-3">
                                <div class="w-10 h-10 rounded-lg bg-white border border-slate-200 flex items-center justify-center text-xs font-extrabold text-slate-400">PL</div>
                                <div>
                                    <p class="text-xs font-bold text-slate-400 uppercase tracking-tight">Next Owner</p>
                                    <p class="text-sm font-bold text-slate-800">Procurement Lead</p>
                                </div>
                            </div>
                            <button onclick="completeHandoff()" class="px-6 py-2.5 bg-emerald-600 hover:bg-emerald-700 text-white font-extrabold rounded-xl shadow-lg shadow-emerald-100 transition-all">Submit to Procurement</button>
                        </div>
                    </div>
                `;
            }
        };

        // --- MODAL SYSTEM ---
        const openModal = (type) => {
            const c = state.cases.find(item => item.id === state.activeCaseId);
            const modalOverlay = document.createElement('div');
            modalOverlay.id = 'modal-overlay';
            modalOverlay.className = "fixed inset-0 bg-slate-900/60 backdrop-blur-sm z-[100] flex items-center justify-center p-4";
            
            let content = '';
            if (type === 'unblock') {
                content = `
                    <div class="bg-white rounded-3xl w-full max-w-md overflow-hidden modal-enter">
                        <div class="p-8">
                            <div class="flex items-center gap-3 mb-6">
                                <div class="w-10 h-10 rounded-xl bg-rose-50 text-rose-500 flex items-center justify-center"><iconify-icon icon="lucide:unlocked" class="text-xl"></iconify-icon></div>
                                <h3 class="text-xl font-extrabold text-slate-900">Resolve Blocker</h3>
                            </div>
                            <p class="text-sm text-slate-500 mb-6">Record how this blocker was resolved. This will be added to the permanent audit trail.</p>
                            <textarea id="modal-note" class="w-full h-32 p-4 bg-slate-50 border border-slate-200 rounded-2xl text-sm font-medium focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-all" placeholder="Describe the resolution..."></textarea>
                        </div>
                        <div class="bg-slate-50 px-8 py-4 flex gap-3 justify-end">
                            <button onclick="closeModal()" class="px-6 py-2 text-sm font-bold text-slate-500 hover:text-slate-800">Cancel</button>
                            <button onclick="submitUnblock()" class="px-6 py-2 bg-indigo-600 hover:bg-indigo-700 text-white text-sm font-bold rounded-xl">Confirm Resolution</button>
                        </div>
                    </div>
                `;
            } else if (type === 'audit') {
                content = `
                    <div class="bg-white rounded-3xl w-full max-w-2xl overflow-hidden modal-enter flex flex-col max-h-[80vh]">
                        <div class="p-8 border-b border-slate-100">
                            <div class="flex items-center justify-between">
                                <div class="flex items-center gap-3">
                                    <div class="w-10 h-10 rounded-xl bg-indigo-50 text-indigo-500 flex items-center justify-center"><iconify-icon icon="lucide:history" class="text-xl"></iconify-icon></div>
                                    <h3 class="text-xl font-extrabold text-slate-900">Audit History</h3>
                                </div>
                                <button onclick="closeModal()" class="p-2 hover:bg-slate-100 rounded-lg text-slate-400"><iconify-icon icon="lucide:x" class="text-xl"></iconify-icon></button>
                            </div>
                        </div>
                        <div class="flex-1 overflow-y-auto p-8 space-y-8 custom-scrollbar">
                            ${c.auditLog.map((log, i) => `
                                <div class="relative pl-8">
                                    ${i < c.auditLog.length - 1 ? '<div class="absolute left-[11px] top-6 bottom-[-24px] w-[2px] bg-slate-100"></div>' : ''}
                                    <div class="absolute left-0 top-1.5 w-[24px] h-[24px] rounded-full bg-white border-4 border-indigo-100 flex items-center justify-center">
                                        <div class="w-[8px] h-[8px] rounded-full bg-indigo-600"></div>
                                    </div>
                                    <div class="flex flex-col gap-1">
                                        <div class="flex items-center justify-between">
                                            <span class="text-sm font-extrabold text-slate-900">${log.action}</span>
                                            <span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">${log.timestamp}</span>
                                        </div>
                                        <p class="text-xs font-bold text-indigo-600">${log.user}</p>
                                        <p class="text-sm text-slate-500 mt-1 bg-slate-50 p-3 rounded-lg border border-slate-100">${log.note}</p>
                                    </div>
                                </div>
                            `).join('')}
                        </div>
                        <div class="bg-slate-50 p-4 text-center">
                            <p class="text-[10px] font-bold text-slate-400 uppercase tracking-widest flex items-center justify-center gap-2">
                                <iconify-icon icon="lucide:lock"></iconify-icon>
                                Immutable Blockchain-Verified Audit Trail
                            </p>
                        </div>
                    </div>
                `;
            } else if (type === 'block') {
                content = `
                    <div class="bg-white rounded-3xl w-full max-w-md overflow-hidden modal-enter">
                        <div class="p-8">
                            <div class="flex items-center gap-3 mb-6">
                                <div class="w-10 h-10 rounded-xl bg-rose-50 text-rose-500 flex items-center justify-center"><iconify-icon icon="lucide:pause-octagon" class="text-xl"></iconify-icon></div>
                                <h3 class="text-xl font-extrabold text-slate-900">Block Case</h3>
                            </div>
                            <p class="text-sm text-slate-500 mb-6">Please provide the reason for blocking this request. All stakeholders will be notified.</p>
                            <textarea id="modal-block-reason" class="w-full h-32 p-4 bg-slate-50 border border-slate-200 rounded-2xl text-sm font-medium focus:outline-none focus:ring-2 focus:ring-rose-500 transition-all" placeholder="What is preventing progress?"></textarea>
                        </div>
                        <div class="bg-slate-50 px-8 py-4 flex gap-3 justify-end">
                            <button onclick="closeModal()" class="px-6 py-2 text-sm font-bold text-slate-500 hover:text-slate-800">Cancel</button>
                            <button onclick="submitBlock()" class="px-6 py-2 bg-rose-600 hover:bg-rose-700 text-white text-sm font-bold rounded-xl">Confirm Block</button>
                        </div>
                    </div>
                `;
            }
            
            modalOverlay.innerHTML = content;
            document.body.appendChild(modalOverlay);
        };

        const closeModal = () => {
            const modal = document.getElementById('modal-overlay');
            if (modal) modal.remove();
        };

        // --- ACTIONS ---
        const openCase = (id) => {
            state.view = 'details';
            state.activeCaseId = id;
            render();
        };

        const backToQueue = () => {
            state.view = 'queue';
            state.activeCaseId = null;
            render();
        };

        const submitUnblock = () => {
            const reason = document.getElementById('modal-note').value;
            if (!reason) return showToast('Please enter a reason', 'error');

            const c = state.cases.find(item => item.id === state.activeCaseId);
            c.isBlocked = false;
            c.blockerReason = "";
            c.status = (c.id === 'LGL-2024-002') ? 'Ready to Review' : 'Ready to Review'; // Logic to decide where it returns
            c.auditLog.unshift({
                action: "Unblocked",
                user: "Sarah Jenkins",
                timestamp: new Date().toISOString().replace('T', ' ').slice(0, 16),
                note: `Resolution: ${reason}`
            });

            closeModal();
            render();
            showToast('Case successfully unblocked');
        };

        const submitBlock = () => {
            const reason = document.getElementById('modal-block-reason').value;
            if (!reason) return showToast('Please enter a reason', 'error');

            const c = state.cases.find(item => item.id === state.activeCaseId);
            c.isBlocked = true;
            c.blockerReason = reason;
            c.status = 'Blocked';
            c.auditLog.unshift({
                action: "Blocked",
                user: "Sarah Jenkins",
                timestamp: new Date().toISOString().replace('T', ' ').slice(0, 16),
                note: `Reason: ${reason}`
            });

            closeModal();
            render();
            showToast('Case flagged as blocked', 'error');
        };

        const submitDecision = (decision) => {
            const c = state.cases.find(item => item.id === state.activeCaseId);
            c.status = 'Ready to Hand Off';
            c.auditLog.unshift({
                action: "Decision Recorded",
                user: "Sarah Jenkins",
                timestamp: new Date().toISOString().replace('T', ' ').slice(0, 16),
                note: `Final Decision: ${decision}`
            });

            render();
            showToast(`Case marked as ${decision}`);
        };

        const completeHandoff = () => {
            const cIndex = state.cases.findIndex(item => item.id === state.activeCaseId);
            state.cases.splice(cIndex, 1); // Move to history (remove from queue in this demo)

            backToQueue();
            showToast('Case successfully handed off to Procurement');
        };

        // Init
        render();

    </script>
</body>
</html>
~~~
All Prompts