<script lang="ts">
	import { goto } from '$app/navigation';
	import { page } from '$app/state';
	import { getApiBaseUrl } from '$lib/api/config';
	import { authenticatedFetch, getAuthenticatedUserId } from '$lib/auth';
	import Pagination from '$lib/components/molecules/Pagination/Pagination.svelte';
	import SearchInput from '$lib/components/molecules/SearchInput/SearchInput.svelte';
	import { untrack } from 'svelte';

	interface Evaluation {
		id: string;
		classId: string;
		subjectId: string;
		teacherId: string;
		title: string;
		description: string | null;
		evaluationDate: string;
		gradeScale: number;
		coefficient: number;
		status: string;
		className: string | null;
		subjectName: string | null;
		createdAt: string;
		updatedAt: string;
	}

	interface TeacherAssignment {
		id: string;
		classId: string;
		subjectId: string;
		status: string;
	}

	interface SchoolClass {
		id: string;
		name: string;
	}

	interface Subject {
		id: string;
		name: string;
		code: string;
	}

	// State
	let evaluations = $state<Evaluation[]>([]);
	let assignments = $state<TeacherAssignment[]>([]);
	let classes = $state<SchoolClass[]>([]);
	let subjects = $state<Subject[]>([]);
	let isLoading = $state(true);
	let error = $state<string | null>(null);

	// Pagination & Search
	let currentPage = $state(Number(page.url.searchParams.get('page')) || 1);
	let searchTerm = $state(page.url.searchParams.get('search') ?? '');
	let totalItems = $state(0);
	const itemsPerPage = 30;
	let totalPages = $derived(Math.ceil(totalItems / itemsPerPage));

	// Create modal
	let showCreateModal = $state(false);
	let newClassId = $state('');
	let newSubjectId = $state('');
	let newTitle = $state('');
	let newDescription = $state('');
	let newEvaluationDate = $state('');
	let newGradeScale = $state(20);
	let newCoefficient = $state(1.0);
	let isSubmitting = $state(false);

	// Edit modal
	let showEditModal = $state(false);
	let editEvaluation = $state<Evaluation | null>(null);
	let editTitle = $state('');
	let editDescription = $state('');
	let editEvaluationDate = $state('');
	let editGradeScale = $state(20);
	let editCoefficient = $state(1.0);
	let isUpdating = $state(false);

	// Delete modal
	let showDeleteModal = $state(false);
	let evaluationToDelete = $state<Evaluation | null>(null);
	let isDeleting = $state(false);

	// Class filter
	let filterClassId = $state(page.url.searchParams.get('classId') ?? '');

	// Derived: available subjects for selected class
	let availableSubjectsForCreate = $derived.by(() => {
		if (!newClassId) return [];
		const assignedSubjectIds = assignments
			.filter((a) => a.classId === newClassId && a.status === 'active')
			.map((a) => a.subjectId);
		return subjects.filter((s) => assignedSubjectIds.includes(s.id));
	});

	// Derived: available classes
	let availableClasses = $derived.by(() => {
		const assignedClassIds = [...new Set(assignments.filter((a) => a.status === 'active').map((a) => a.classId))];
		return classes.filter((c) => assignedClassIds.includes(c.id));
	});

	// Derived: grade scale equivalence preview
	let gradeScalePreview = $derived.by(() => {
		if (newGradeScale === 20) return '';
		return `(10/${newGradeScale} = ${((10 / newGradeScale) * 20).toFixed(1)}/20)`;
	});

	// Load on mount
	$effect(() => {
		untrack(() => loadAll());
	});

	function extractCollection<T>(data: Record<string, unknown>): T[] {
		const members = data['hydra:member'] ?? data['member'];
		if (Array.isArray(members)) return members as T[];
		if (Array.isArray(data)) return data as T[];
		return [];
	}

	async function loadAssignments() {
		const userId = await getAuthenticatedUserId();
		if (!userId) return;
		const apiUrl = getApiBaseUrl();
		const res = await authenticatedFetch(`${apiUrl}/teachers/${userId}/assignments`);
		if (!res.ok) throw new Error('Erreur lors du chargement des affectations');
		const data = await res.json();
		assignments = extractCollection<TeacherAssignment>(data);
	}

	async function loadAll() {
		try {
			isLoading = true;
			error = null;
			const apiUrl = getApiBaseUrl();

			const [classesRes, subjectsRes] = await Promise.all([
				authenticatedFetch(`${apiUrl}/classes?itemsPerPage=100`),
				authenticatedFetch(`${apiUrl}/subjects?itemsPerPage=100`),
				loadAssignments().catch((e) => {
					error = e instanceof Error ? e.message : 'Erreur lors du chargement des affectations';
				}),
				loadEvaluations().catch((e) => {
					evaluations = [];
					totalItems = 0;
					error = e instanceof Error ? e.message : 'Erreur inconnue';
				}),
			]);

			if (!classesRes.ok) throw new Error('Erreur lors du chargement des classes');
			if (!subjectsRes.ok) throw new Error('Erreur lors du chargement des matières');

			const [classesData, subjectsData] = await Promise.all([
				classesRes.json(),
				subjectsRes.json(),
			]);

			classes = extractCollection<SchoolClass>(classesData);
			subjects = extractCollection<Subject>(subjectsData);
		} catch (e) {
			error = e instanceof Error ? e.message : 'Erreur inconnue';
		} finally {
			isLoading = false;
		}
	}

	let loadAbortController: AbortController | null = null;

	async function loadEvaluations() {
		loadAbortController?.abort();
		const controller = new AbortController();
		loadAbortController = controller;

		try {
			const apiUrl = getApiBaseUrl();
			const params = new URLSearchParams();
			params.set('page', String(currentPage));
			params.set('itemsPerPage', String(itemsPerPage));
			if (searchTerm) params.set('search', searchTerm);
			if (filterClassId) params.set('classId', filterClassId);

			const response = await authenticatedFetch(`${apiUrl}/evaluations?${params.toString()}`, {
				signal: controller.signal,
			});

			if (controller.signal.aborted) return;

			if (!response.ok) {
				throw new Error('Erreur lors du chargement des évaluations');
			}

			const data = await response.json();
			evaluations = extractCollection<Evaluation>(data);
			totalItems = (data as Record<string, unknown>)['hydra:totalItems'] as number ?? (data as Record<string, unknown>)['totalItems'] as number ?? evaluations.length;
		} catch (e) {
			if (e instanceof DOMException && e.name === 'AbortError') return;
			throw e;
		}
	}

	function updateUrl() {
		const params = new URLSearchParams();
		if (currentPage > 1) params.set('page', String(currentPage));
		if (searchTerm) params.set('search', searchTerm);
		if (filterClassId) params.set('classId', filterClassId);
		const query = params.toString();
		goto(`?${query}`, { replaceState: true, noScroll: true, keepFocus: true });
	}

	function handleSearch(value: string) {
		searchTerm = value;
		currentPage = 1;
		updateUrl();
		loadEvaluations().catch((e) => {
			error = e instanceof Error ? e.message : 'Erreur inconnue';
		});
	}

	function handlePageChange(newPage: number) {
		currentPage = newPage;
		updateUrl();
		loadEvaluations().catch((e) => {
			error = e instanceof Error ? e.message : 'Erreur inconnue';
		});
	}

	function handleClassFilter(newClassId: string) {
		filterClassId = newClassId;
		currentPage = 1;
		updateUrl();
		loadEvaluations().catch((e) => {
			error = e instanceof Error ? e.message : 'Erreur inconnue';
		});
	}

	function getClassName(classId: string): string {
		return classes.find((c) => c.id === classId)?.name ?? classId;
	}

	function getSubjectName(subjectId: string): string {
		return subjects.find((s) => s.id === subjectId)?.name ?? subjectId;
	}

	function formatDate(dateStr: string): string {
		return new Date(dateStr).toLocaleDateString('fr-FR', {
			day: 'numeric',
			month: 'long',
			year: 'numeric',
		});
	}

	function formatGradeScale(scale: number): string {
		return `/${scale}`;
	}

	// --- Create ---
	function openCreateModal() {
		showCreateModal = true;
		newClassId = '';
		newSubjectId = '';
		newTitle = '';
		newDescription = '';
		newEvaluationDate = '';
		newGradeScale = 20;
		newCoefficient = 1.0;
	}

	function closeCreateModal() {
		showCreateModal = false;
	}

	async function handleCreate() {
		if (!newClassId || !newSubjectId || !newTitle.trim() || !newEvaluationDate) return;

		try {
			isSubmitting = true;
			error = null;
			const apiUrl = getApiBaseUrl();
			const response = await authenticatedFetch(`${apiUrl}/evaluations`, {
				method: 'POST',
				headers: { 'Content-Type': 'application/json' },
				body: JSON.stringify({
					classId: newClassId,
					subjectId: newSubjectId,
					title: newTitle.trim(),
					description: newDescription.trim() || null,
					evaluationDate: newEvaluationDate,
					gradeScale: newGradeScale,
					coefficient: newCoefficient,
				}),
			});

			if (!response.ok) {
				const data = await response.json().catch(() => null);
				throw new Error((data as Record<string, string> | null)?.['message'] ?? 'Erreur lors de la création');
			}

			closeCreateModal();
			await loadEvaluations();
		} catch (e) {
			error = e instanceof Error ? e.message : 'Erreur inconnue';
		} finally {
			isSubmitting = false;
		}
	}

	// --- Edit ---
	function openEditModal(evaluation: Evaluation) {
		editEvaluation = evaluation;
		editTitle = evaluation.title;
		editDescription = evaluation.description ?? '';
		editEvaluationDate = evaluation.evaluationDate;
		editGradeScale = evaluation.gradeScale;
		editCoefficient = evaluation.coefficient;
		showEditModal = true;
	}

	function closeEditModal() {
		showEditModal = false;
		editEvaluation = null;
	}

	async function handleUpdate() {
		if (!editEvaluation || !editTitle.trim() || !editEvaluationDate) return;

		try {
			isUpdating = true;
			error = null;
			const apiUrl = getApiBaseUrl();
			const response = await authenticatedFetch(`${apiUrl}/evaluations/${editEvaluation.id}`, {
				method: 'PATCH',
				headers: { 'Content-Type': 'application/merge-patch+json' },
				body: JSON.stringify({
					title: editTitle.trim(),
					description: editDescription.trim() || null,
					evaluationDate: editEvaluationDate,
					gradeScale: editGradeScale,
					coefficient: editCoefficient,
				}),
			});

			if (!response.ok) {
				const data = await response.json().catch(() => null);
				throw new Error((data as Record<string, string> | null)?.['message'] ?? 'Erreur lors de la modification');
			}

			closeEditModal();
			await loadEvaluations();
		} catch (e) {
			error = e instanceof Error ? e.message : 'Erreur inconnue';
		} finally {
			isUpdating = false;
		}
	}

	// --- Delete ---
	function openDeleteModal(evaluation: Evaluation) {
		evaluationToDelete = evaluation;
		showDeleteModal = true;
	}

	function closeDeleteModal() {
		showDeleteModal = false;
		evaluationToDelete = null;
	}

	async function handleDelete() {
		if (!evaluationToDelete) return;

		try {
			isDeleting = true;
			error = null;
			const apiUrl = getApiBaseUrl();
			const response = await authenticatedFetch(`${apiUrl}/evaluations/${evaluationToDelete.id}`, {
				method: 'DELETE',
			});

			if (!response.ok) {
				throw new Error('Erreur lors de la suppression');
			}

			closeDeleteModal();
			await loadEvaluations();
		} catch (e) {
			error = e instanceof Error ? e.message : 'Erreur inconnue';
		} finally {
			isDeleting = false;
		}
	}
</script>

<svelte:head>
	<title>Mes évaluations - Classeo</title>
</svelte:head>

<div class="evaluations-page">
	<header class="page-header">
		<div class="header-content">
			<h1>Mes évaluations</h1>
			<p class="subtitle">Créez et gérez les évaluations pour vos classes</p>
		</div>
		<button class="btn-primary" onclick={openCreateModal} disabled={availableClasses.length === 0}>
			<span class="btn-icon">+</span>
			Nouvelle évaluation
		</button>
	</header>

	{#if error}
		<div class="alert alert-error">
			<span class="alert-icon">&#9888;</span>
			{error}
			<button class="alert-close" onclick={() => (error = null)}>&times;</button>
		</div>
	{/if}

	<div class="filters-row">
		<SearchInput value={searchTerm} onSearch={handleSearch} placeholder="Rechercher par titre..." />
		<div class="class-filter">
			<select
				value={filterClassId}
				aria-label="Filtrer par classe"
				onchange={(e) => handleClassFilter((e.target as HTMLSelectElement).value)}
			>
				<option value="">Toutes les classes</option>
				{#each availableClasses as cls (cls.id)}
					<option value={cls.id}>{cls.name}</option>
				{/each}
			</select>
		</div>
	</div>

	{#if isLoading}
		<div class="loading-state" aria-live="polite" role="status">
			<div class="spinner"></div>
			<p>Chargement des évaluations...</p>
		</div>
	{:else if evaluations.length === 0}
		<div class="empty-state">
			<span class="empty-icon">&#128221;</span>
			{#if searchTerm}
				<h2>Aucun résultat</h2>
				<p>Aucune évaluation ne correspond à votre recherche</p>
				<button class="btn-secondary" onclick={() => handleSearch('')}>Effacer la recherche</button>
			{:else}
				<h2>Aucune évaluation</h2>
				<p>Commencez par créer votre première évaluation</p>
				<button class="btn-primary" onclick={openCreateModal} disabled={availableClasses.length === 0}>
					Créer une évaluation
				</button>
			{/if}
		</div>
	{:else}
		<div class="evaluation-list">
			{#each evaluations as ev (ev.id)}
				<div class="evaluation-card">
					<div class="evaluation-header">
						<h3 class="evaluation-title">{ev.title}</h3>
						<div class="evaluation-badges">
							<span class="badge-scale" title="Barème">{formatGradeScale(ev.gradeScale)}</span>
							<span class="badge-coeff" title="Coefficient">x{ev.coefficient}</span>
						</div>
					</div>

					<div class="evaluation-meta">
						<span class="meta-item" title="Classe">
							<span class="meta-icon">&#127979;</span>
							{ev.className ?? getClassName(ev.classId)}
						</span>
						<span class="meta-item" title="Matière">
							<span class="meta-icon">&#128214;</span>
							{ev.subjectName ?? getSubjectName(ev.subjectId)}
						</span>
						<span class="meta-item" title="Date d'évaluation">
							<span class="meta-icon">&#128197;</span>
							{formatDate(ev.evaluationDate)}
						</span>
					</div>

					{#if ev.description}
						<p class="evaluation-description">{ev.description}</p>
					{/if}

					{#if ev.status === 'published'}
						<div class="evaluation-actions">
							<a class="btn-primary btn-sm" href="/dashboard/teacher/evaluations/{ev.id}/grades">
								Saisir les notes
							</a>
							<button class="btn-secondary btn-sm" onclick={() => openEditModal(ev)}>
								Modifier
							</button>
							<button class="btn-danger btn-sm" onclick={() => openDeleteModal(ev)}>
								Supprimer
							</button>
						</div>
					{/if}
				</div>
			{/each}
		</div>
		<Pagination {currentPage} {totalPages} onPageChange={handlePageChange} />
	{/if}
</div>

<!-- Create Modal -->
{#if showCreateModal}
	<!-- svelte-ignore a11y_no_static_element_interactions -->
	<div class="modal-overlay" onclick={closeCreateModal} role="presentation">
		<div
			class="modal"
			role="dialog"
			aria-modal="true"
			aria-labelledby="create-modal-title"
			tabindex="-1"
			onclick={(e) => e.stopPropagation()}
			onkeydown={(e) => { if (e.key === 'Escape') closeCreateModal(); }}
		>
			<header class="modal-header">
				<h2 id="create-modal-title">Nouvelle évaluation</h2>
				<button class="modal-close" onclick={closeCreateModal} aria-label="Fermer">&times;</button>
			</header>

			<form
				class="modal-body"
				onsubmit={(e) => {
					e.preventDefault();
					handleCreate();
				}}
			>
				<div class="form-group">
					<label for="ev-class">Classe *</label>
					<select
						id="ev-class"
						bind:value={newClassId}
						required
						onchange={() => (newSubjectId = '')}
					>
						<option value="">-- Sélectionner une classe --</option>
						{#each availableClasses as cls (cls.id)}
							<option value={cls.id}>{cls.name}</option>
						{/each}
					</select>
				</div>

				<div class="form-group">
					<label for="ev-subject">Matière *</label>
					<select id="ev-subject" bind:value={newSubjectId} required disabled={!newClassId}>
						<option value="">-- Sélectionner une matière --</option>
						{#each availableSubjectsForCreate as subj (subj.id)}
							<option value={subj.id}>{subj.name}</option>
						{/each}
					</select>
					{#if newClassId && availableSubjectsForCreate.length === 0}
						<small class="form-hint form-hint-warning">Aucune matière affectée pour cette classe</small>
					{/if}
				</div>

				<div class="form-group">
					<label for="ev-title">Titre *</label>
					<input
						type="text"
						id="ev-title"
						bind:value={newTitle}
						placeholder="ex: Contrôle chapitre 5"
						required
						minlength="2"
						maxlength="255"
					/>
				</div>

				<div class="form-group">
					<label for="ev-description">Description</label>
					<textarea
						id="ev-description"
						bind:value={newDescription}
						placeholder="Description de l'évaluation (optionnel)"
						rows="3"
					></textarea>
				</div>

				<div class="form-group">
					<label for="ev-date">Date d'évaluation *</label>
					<input
						type="date"
						id="ev-date"
						bind:value={newEvaluationDate}
						required
					/>
				</div>

				<div class="form-row">
					<div class="form-group form-group-half">
						<label for="ev-scale">Barème *</label>
						<input
							type="number"
							id="ev-scale"
							bind:value={newGradeScale}
							min="1"
							max="100"
							step="1"
							required
						/>
						{#if gradeScalePreview}
							<small class="form-hint">{gradeScalePreview}</small>
						{/if}
					</div>

					<div class="form-group form-group-half">
						<label for="ev-coeff">Coefficient</label>
						<input
							type="number"
							id="ev-coeff"
							bind:value={newCoefficient}
							min="0.1"
							max="10"
							step="0.1"
						/>
					</div>
				</div>

				<div class="modal-footer">
					<button type="button" class="btn-secondary" onclick={closeCreateModal}>Annuler</button>
					<button type="submit" class="btn-primary" disabled={isSubmitting}>
						{isSubmitting ? 'Création...' : 'Créer'}
					</button>
				</div>
			</form>
		</div>
	</div>
{/if}

<!-- Edit Modal -->
{#if showEditModal && editEvaluation}
	<!-- svelte-ignore a11y_no_static_element_interactions -->
	<div class="modal-overlay" onclick={closeEditModal} role="presentation">
		<div
			class="modal"
			role="dialog"
			aria-modal="true"
			aria-labelledby="edit-modal-title"
			tabindex="-1"
			onclick={(e) => e.stopPropagation()}
			onkeydown={(e) => { if (e.key === 'Escape') closeEditModal(); }}
		>
			<header class="modal-header">
				<h2 id="edit-modal-title">Modifier l'évaluation</h2>
				<button class="modal-close" onclick={closeEditModal} aria-label="Fermer">&times;</button>
			</header>

			<form
				class="modal-body"
				onsubmit={(e) => {
					e.preventDefault();
					handleUpdate();
				}}
			>
				<div class="form-group">
					<label for="edit-title">Titre *</label>
					<input
						type="text"
						id="edit-title"
						bind:value={editTitle}
						required
						minlength="2"
						maxlength="255"
					/>
				</div>

				<div class="form-group">
					<label for="edit-description">Description</label>
					<textarea
						id="edit-description"
						bind:value={editDescription}
						rows="3"
					></textarea>
				</div>

				<div class="form-group">
					<label for="edit-date">Date d'évaluation *</label>
					<input
						type="date"
						id="edit-date"
						bind:value={editEvaluationDate}
						required
					/>
				</div>

				<div class="form-row">
					<div class="form-group form-group-half">
						<label for="edit-scale">Barème</label>
						<input
							type="number"
							id="edit-scale"
							bind:value={editGradeScale}
							min="1"
							max="100"
							step="1"
						/>
					</div>

					<div class="form-group form-group-half">
						<label for="edit-coeff">Coefficient</label>
						<input
							type="number"
							id="edit-coeff"
							bind:value={editCoefficient}
							min="0.1"
							max="10"
							step="0.1"
						/>
					</div>
				</div>

				<div class="modal-footer">
					<button type="button" class="btn-secondary" onclick={closeEditModal}>Annuler</button>
					<button type="submit" class="btn-primary" disabled={isUpdating}>
						{isUpdating ? 'Enregistrement...' : 'Enregistrer'}
					</button>
				</div>
			</form>
		</div>
	</div>
{/if}

<!-- Delete Modal -->
{#if showDeleteModal && evaluationToDelete}
	<!-- svelte-ignore a11y_no_static_element_interactions -->
	<div class="modal-overlay" onclick={closeDeleteModal} role="presentation">
		<div
			class="modal"
			role="alertdialog"
			aria-modal="true"
			aria-labelledby="delete-modal-title"
			tabindex="-1"
			onclick={(e) => e.stopPropagation()}
			onkeydown={(e) => { if (e.key === 'Escape') closeDeleteModal(); }}
		>
			<header class="modal-header">
				<h2 id="delete-modal-title">Supprimer l'évaluation</h2>
				<button class="modal-close" onclick={closeDeleteModal} aria-label="Fermer">&times;</button>
			</header>

			<div class="modal-body">
				<p>Voulez-vous vraiment supprimer l'évaluation <strong>{evaluationToDelete.title}</strong> ?</p>
				<p class="text-muted">Cette action est irréversible.</p>

				<div class="modal-footer">
					<button type="button" class="btn-secondary" onclick={closeDeleteModal}>Annuler</button>
					<button type="button" class="btn-danger" onclick={handleDelete} disabled={isDeleting}>
						{isDeleting ? 'Suppression...' : 'Supprimer'}
					</button>
				</div>
			</div>
		</div>
	</div>
{/if}

<style>
	/* Page layout */
	.evaluations-page {
		max-width: 64rem;
		margin: 0 auto;
		padding: 1.5rem;
	}

	.page-header {
		display: flex;
		justify-content: space-between;
		align-items: flex-start;
		gap: 1rem;
		margin-bottom: 1.5rem;
	}

	.header-content h1 {
		margin: 0;
		font-size: 1.5rem;
		font-weight: 700;
		color: #1f2937;
	}

	.subtitle {
		margin: 0.25rem 0 0;
		color: #6b7280;
		font-size: 0.875rem;
	}

	/* Buttons */
	.btn-primary {
		display: flex;
		align-items: center;
		gap: 0.5rem;
		padding: 0.625rem 1.25rem;
		background: #3b82f6;
		color: white;
		border: none;
		border-radius: 0.5rem;
		font-size: 0.875rem;
		font-weight: 600;
		cursor: pointer;
		transition: background 0.2s;
	}

	.btn-primary:hover:not(:disabled) {
		background: #2563eb;
	}

	.btn-primary:disabled {
		opacity: 0.5;
		cursor: not-allowed;
	}

	.btn-secondary {
		padding: 0.5rem 1rem;
		background: white;
		color: #374151;
		border: 1px solid #d1d5db;
		border-radius: 0.5rem;
		font-size: 0.875rem;
		cursor: pointer;
		transition: background 0.2s;
	}

	.btn-secondary:hover {
		background: #f9fafb;
	}

	.btn-danger {
		padding: 0.5rem 1rem;
		background: #dc2626;
		color: white;
		border: none;
		border-radius: 0.5rem;
		font-size: 0.875rem;
		cursor: pointer;
		transition: background 0.2s;
	}

	.btn-danger:hover:not(:disabled) {
		background: #b91c1c;
	}

	.btn-danger:disabled {
		opacity: 0.5;
		cursor: not-allowed;
	}

	.btn-sm {
		padding: 0.375rem 0.75rem;
		font-size: 0.8125rem;
	}

	.btn-icon {
		font-size: 1.125rem;
		line-height: 1;
	}

	/* Filters */
	.filters-row {
		display: flex;
		gap: 1rem;
		margin-bottom: 1.5rem;
		flex-wrap: wrap;
	}

	.class-filter select {
		padding: 0.5rem 0.75rem;
		border: 1px solid #d1d5db;
		border-radius: 0.5rem;
		font-size: 0.875rem;
		background: white;
	}

	/* Alerts */
	.alert {
		display: flex;
		align-items: flex-start;
		gap: 0.75rem;
		padding: 0.75rem 1rem;
		border-radius: 0.5rem;
		margin-bottom: 1rem;
	}

	.alert-error {
		background: #fef2f2;
		border: 1px solid #fecaca;
		color: #991b1b;
	}

	.alert-icon {
		flex-shrink: 0;
		font-size: 1.125rem;
	}

	.alert-close {
		margin-left: auto;
		padding: 0.25rem 0.5rem;
		background: none;
		border: none;
		font-size: 1.25rem;
		cursor: pointer;
		opacity: 0.6;
	}

	.alert-close:hover {
		opacity: 1;
	}

	/* Loading & Empty states */
	.loading-state,
	.empty-state {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		padding: 3rem;
		text-align: center;
		background: white;
		border-radius: 0.75rem;
		border: 2px dashed #e5e7eb;
	}

	.spinner {
		width: 2rem;
		height: 2rem;
		border: 3px solid #e5e7eb;
		border-top-color: #3b82f6;
		border-radius: 50%;
		animation: spin 0.8s linear infinite;
	}

	@keyframes spin {
		to {
			transform: rotate(360deg);
		}
	}

	.empty-icon {
		font-size: 3rem;
		margin-bottom: 1rem;
	}

	.empty-state h2 {
		margin: 0 0 0.5rem;
		font-size: 1.25rem;
		color: #1f2937;
	}

	.empty-state p {
		margin: 0 0 1.5rem;
		color: #6b7280;
	}

	/* Evaluation list */
	.evaluation-list {
		display: flex;
		flex-direction: column;
		gap: 1rem;
	}

	.evaluation-card {
		padding: 1.25rem;
		background: white;
		border: 1px solid #e5e7eb;
		border-radius: 0.75rem;
		transition: box-shadow 0.2s;
	}

	.evaluation-card:hover {
		box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
	}

	.evaluation-header {
		display: flex;
		justify-content: space-between;
		align-items: flex-start;
		gap: 0.75rem;
		margin-bottom: 0.75rem;
	}

	.evaluation-title {
		margin: 0;
		font-size: 1.125rem;
		font-weight: 600;
		color: #1f2937;
	}

	.evaluation-badges {
		display: flex;
		gap: 0.5rem;
		flex-shrink: 0;
	}

	.badge-scale {
		padding: 0.125rem 0.5rem;
		border-radius: 9999px;
		font-size: 0.75rem;
		font-weight: 600;
		background: #e0e7ff;
		color: #4338ca;
	}

	.badge-coeff {
		padding: 0.125rem 0.5rem;
		border-radius: 9999px;
		font-size: 0.75rem;
		font-weight: 600;
		background: #fef3c7;
		color: #92400e;
	}

	.evaluation-meta {
		display: flex;
		gap: 1.25rem;
		flex-wrap: wrap;
		margin-bottom: 0.75rem;
	}

	.meta-item {
		display: flex;
		align-items: center;
		gap: 0.25rem;
		font-size: 0.875rem;
		color: #6b7280;
	}

	.meta-icon {
		font-size: 0.875rem;
	}

	.evaluation-description {
		margin: 0 0 0.75rem;
		font-size: 0.875rem;
		color: #4b5563;
		line-height: 1.5;
		white-space: pre-line;
	}

	.evaluation-actions {
		display: flex;
		gap: 0.5rem;
	}

	/* Modal */
	.modal-overlay {
		position: fixed;
		inset: 0;
		background: rgba(0, 0, 0, 0.5);
		display: flex;
		align-items: center;
		justify-content: center;
		padding: 1rem;
		z-index: 100;
	}

	.modal {
		background: white;
		border-radius: 0.75rem;
		width: 100%;
		max-width: 32rem;
		max-height: 90vh;
		overflow: auto;
		box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
	}

	.modal-header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 1.25rem 1.5rem;
		border-bottom: 1px solid #e5e7eb;
	}

	.modal-header h2 {
		margin: 0;
		font-size: 1.125rem;
		font-weight: 600;
		color: #1f2937;
	}

	.modal-close {
		padding: 0.25rem 0.5rem;
		background: none;
		border: none;
		font-size: 1.5rem;
		color: #6b7280;
		cursor: pointer;
	}

	.modal-close:hover {
		color: #1f2937;
	}

	.modal-body {
		padding: 1.5rem;
	}

	.modal-footer {
		display: flex;
		justify-content: flex-end;
		gap: 0.75rem;
		padding-top: 1rem;
	}

	/* Forms */
	.form-group {
		margin-bottom: 1rem;
	}

	.form-group label {
		display: block;
		margin-bottom: 0.375rem;
		font-size: 0.875rem;
		font-weight: 500;
		color: #374151;
	}

	.form-group input,
	.form-group select,
	.form-group textarea {
		width: 100%;
		padding: 0.5rem 0.75rem;
		border: 1px solid #d1d5db;
		border-radius: 0.5rem;
		font-size: 0.875rem;
		box-sizing: border-box;
	}

	.form-group input:focus,
	.form-group select:focus,
	.form-group textarea:focus {
		outline: none;
		border-color: #3b82f6;
		box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
	}

	.form-hint {
		display: block;
		margin-top: 0.25rem;
		font-size: 0.75rem;
		color: #6b7280;
	}

	.form-hint-warning {
		color: #d97706;
	}

	.form-row {
		display: flex;
		gap: 1rem;
	}

	.form-group-half {
		flex: 1;
	}

	.text-muted {
		color: #6b7280;
		font-size: 0.875rem;
	}

	/* Responsive */
	@media (max-width: 640px) {
		.page-header {
			flex-direction: column;
		}

		.filters-row {
			flex-direction: column;
		}

		.form-row {
			flex-direction: column;
		}

		.evaluation-meta {
			flex-direction: column;
			gap: 0.5rem;
		}
	}
</style>
