Files
english/stitch-exports/toeic-app-design.html
2026-04-12 18:54:59 +07:00

1291 lines
72 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>EnglishAI — Luyện TOEIC thông minh</title>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet"/>
<script src="https://cdn.tailwindcss.com?plugins=forms"></script>
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: { sans: ['Plus Jakarta Sans', 'sans-serif'] },
colors: {
primary: '#2563EB',
'primary-dark': '#1d4ed8',
'primary-light': '#eff6ff',
success: '#16A34A',
'success-light': '#f0fdf4',
danger: '#DC2626',
'danger-light': '#fef2f2',
amber: '#D97706',
'amber-light': '#fffbeb',
surface: '#F8FAFC',
card: '#FFFFFF',
border: '#e2e8f0',
muted: '#94a3b8',
body: '#1e293b',
subtle: '#475569',
}
}
}
}
</script>
<style>
* { font-family: 'Plus Jakarta Sans', sans-serif; }
.material-symbols-outlined { font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24; vertical-align: middle; }
/* Screen fade transitions */
.screen { display: none; opacity: 0; transition: opacity 0.25s ease; }
.screen.active { display: block; opacity: 1; }
.screen.fade-in { animation: fadeIn 0.25s ease forwards; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
/* Sidebar active state */
.nav-item { display: flex; align-items: center; gap: 12px; padding: 10px 16px; margin: 2px 8px; border-radius: 10px; font-size: 14px; font-weight: 500; color: #475569; cursor: pointer; transition: all 0.15s; text-decoration: none; }
.nav-item:hover { background: white; color: #1e293b; }
.nav-item.active { background: white; color: #2563EB; font-weight: 600; box-shadow: 0 1px 4px rgba(37,99,235,0.1); }
.nav-item.active .material-symbols-outlined { color: #2563EB; }
/* Card hover */
.part-card { transition: transform 0.2s, box-shadow 0.2s; }
.part-card:hover { transform: translateY(-4px); box-shadow: 0 12px 24px rgba(0,0,0,0.08); }
/* Answer buttons */
.answer-btn { transition: all 0.15s; }
.answer-btn.selected { background: #eff6ff; border-color: #2563EB; color: #2563EB; }
.answer-btn.correct { background: #f0fdf4; border-color: #16A34A; color: #16A34A; }
.answer-btn.wrong { background: #fef2f2; border-color: #DC2626; color: #DC2626; }
/* Flashcard 3D flip */
.card-scene { perspective: 1000px; }
.card-inner { position: relative; transform-style: preserve-3d; transition: transform 0.55s cubic-bezier(0.4,0,0.2,1); }
.card-inner.flipped { transform: rotateY(180deg); }
.card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; border-radius: 20px; }
.card-back { transform: rotateY(180deg); }
/* Progress bar */
.progress-bar { height: 6px; border-radius: 3px; background: #e2e8f0; overflow: hidden; }
.progress-fill { height: 100%; background: #2563EB; border-radius: 3px; transition: width 0.4s ease; }
/* Circular progress SVG */
.ring-bg { stroke: #e2e8f0; }
.ring-fill { stroke: #2563EB; stroke-linecap: round; transition: stroke-dashoffset 0.5s ease; }
/* Timer */
#timer { font-variant-numeric: tabular-nums; }
#timer.urgent { color: #DC2626; animation: pulse 1s infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } }
/* Dot grid questions */
.q-dot { width: 32px; height: 32px; border-radius: 50%; border: 2px solid #e2e8f0; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 600; cursor: pointer; transition: all 0.15s; color: #94a3b8; }
.q-dot.answered { background: #2563EB; border-color: #2563EB; color: white; }
.q-dot.current { border-color: #2563EB; color: #2563EB; box-shadow: 0 0 0 3px rgba(37,99,235,0.2); }
/* Mobile bottom nav */
.mobile-nav { display: none; }
@media (max-width: 768px) {
.sidebar { display: none !important; }
.main-header { left: 0 !important; }
.main-content { margin-left: 0 !important; }
.mobile-nav { display: flex; position: fixed; bottom: 0; left: 0; right: 0; background: white; border-top: 1px solid #e2e8f0; z-index: 50; padding: 8px 0; }
.main-content { padding-bottom: 80px !important; }
}
.mobile-nav-item { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 6px 4px; font-size: 11px; font-weight: 500; color: #94a3b8; cursor: pointer; transition: color 0.15s; min-height: 44px; }
.mobile-nav-item.active { color: #2563EB; }
/* Tablet: icon-only sidebar */
@media (min-width: 769px) and (max-width: 1024px) {
.sidebar { width: 68px !important; }
.sidebar .nav-label, .sidebar .brand-sub, .sidebar .brand-name { display: none; }
.sidebar .nav-item { justify-content: center; padding: 10px; }
.main-header { left: 68px !important; }
.main-content { margin-left: 68px !important; }
}
/* Scrollbar */
::-webkit-scrollbar { width: 4px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 2px; }
/* Feedback sections */
.feedback-section { border-radius: 12px; padding: 16px; margin-bottom: 12px; }
.feedback-section .header { font-weight: 700; font-size: 13px; margin-bottom: 8px; display: flex; align-items: center; gap: 6px; }
.feedback-section ul { list-style: none; padding: 0; margin: 0; }
.feedback-section li { font-size: 13px; padding: 4px 0; padding-left: 16px; position: relative; }
.feedback-section li::before { content: '•'; position: absolute; left: 4px; }
/* Writing improved toggle */
.collapsible-content { display: none; }
.collapsible-content.open { display: block; }
/* Chart bars */
.chart-bar { transition: height 0.5s ease; }
/* Default grid layouts */
.parts-grid { grid-template-columns: repeat(4, 1fr); }
.vocab-3col { grid-template-columns: 200px 1fr 220px; }
.vocab-topics-mobile { display: none; }
/* Mobile responsive adjustments */
@media (max-width: 768px) {
.hero-split { flex-direction: column; }
.hero-preview { display: none; }
.feature-cards { grid-template-columns: 1fr !important; }
.parts-grid { grid-template-columns: repeat(2, 1fr) !important; }
.exam-layout { flex-direction: column; }
.results-bottom { flex-direction: column; }
.writing-layout { flex-direction: column; }
.vocab-3col { grid-template-columns: 1fr !important; }
.vocab-topics-side { display: none; }
.vocab-stats-side { display: none; }
.vocab-topics-mobile { display: flex !important; }
}
</style>
</head>
<body class="bg-surface text-body">
<!-- ===== SIDEBAR ===== -->
<aside class="sidebar fixed left-0 top-0 h-full w-60 bg-[#f8fafc] border-r border-border flex flex-col z-50 overflow-hidden" style="width:240px">
<div class="px-6 py-6 border-b border-border">
<div class="brand-name text-xl font-bold text-primary">EnglishAI</div>
<div class="brand-sub text-xs text-muted mt-0.5">Học tập thông minh</div>
</div>
<nav class="flex-1 py-4 overflow-y-auto">
<a class="nav-item active" data-screen="home" onclick="navigate('home')">
<span class="material-symbols-outlined" style="font-size:20px">home</span>
<span class="nav-label">Trang chủ</span>
</a>
<a class="nav-item" data-screen="parts" onclick="navigate('parts')">
<span class="material-symbols-outlined" style="font-size:20px">assignment</span>
<span class="nav-label">Luyện đề TOEIC</span>
</a>
<a class="nav-item" data-screen="writing" onclick="navigate('writing')">
<span class="material-symbols-outlined" style="font-size:20px">edit_note</span>
<span class="nav-label">AI Writing</span>
</a>
<a class="nav-item" data-screen="vocab" onclick="navigate('vocab')">
<span class="material-symbols-outlined" style="font-size:20px">menu_book</span>
<span class="nav-label">Từ vựng</span>
</a>
</nav>
<div class="px-4 py-4 border-t border-border">
<div class="flex items-center gap-3 bg-white rounded-xl p-3">
<div class="w-9 h-9 rounded-full bg-primary flex items-center justify-center text-white font-bold text-sm flex-shrink-0">M</div>
<div class="min-w-0">
<div class="nav-label text-sm font-semibold truncate">Minh Anh</div>
<div class="brand-sub text-xs text-muted">Dùng thử miễn phí</div>
</div>
</div>
</div>
</aside>
<!-- ===== TOP HEADER ===== -->
<header class="main-header fixed top-0 right-0 h-16 bg-white/90 backdrop-blur-md border-b border-border flex items-center justify-between px-6 z-40" style="left:240px">
<div id="header-title" class="text-base font-semibold text-body">Trang chủ</div>
<div class="flex items-center gap-2">
<button class="w-9 h-9 flex items-center justify-center rounded-full hover:bg-surface transition-colors">
<span class="material-symbols-outlined text-muted" style="font-size:20px">notifications</span>
</button>
<button class="w-9 h-9 flex items-center justify-center rounded-full hover:bg-surface transition-colors">
<span class="material-symbols-outlined text-muted" style="font-size:20px">help_outline</span>
</button>
</div>
</header>
<!-- ===== MOBILE BOTTOM NAV ===== -->
<nav class="mobile-nav">
<div class="mobile-nav-item active" data-screen="home" onclick="navigate('home')">
<span class="material-symbols-outlined" style="font-size:22px">home</span>
<span>Home</span>
</div>
<div class="mobile-nav-item" data-screen="parts" onclick="navigate('parts')">
<span class="material-symbols-outlined" style="font-size:22px">assignment</span>
<span>Luyện đề</span>
</div>
<div class="mobile-nav-item" data-screen="writing" onclick="navigate('writing')">
<span class="material-symbols-outlined" style="font-size:22px">edit_note</span>
<span>Writing</span>
</div>
<div class="mobile-nav-item" data-screen="vocab" onclick="navigate('vocab')">
<span class="material-symbols-outlined" style="font-size:22px">menu_book</span>
<span>Từ vựng</span>
</div>
</nav>
<!-- ============================================================ -->
<!-- SCREEN 1: HOME -->
<!-- ============================================================ -->
<main id="screen-home" class="screen active main-content" style="margin-left:240px; padding-top:64px;">
<div class="px-8 py-8 max-w-6xl mx-auto">
<!-- Hero -->
<section class="hero-split flex gap-10 items-center mb-12">
<div class="flex-1 min-w-0">
<div class="inline-flex items-center gap-2 bg-primary-light text-primary text-xs font-bold px-3 py-1.5 rounded-full mb-5 uppercase tracking-wide">
<span class="material-symbols-outlined" style="font-size:14px">auto_awesome</span>
AI-Powered Learning
</div>
<h1 class="text-5xl font-extrabold leading-tight mb-4" style="letter-spacing:-0.02em">
Luyện TOEIC<br/>thông minh<br/>
<span class="text-primary italic">cùng AI</span>
</h1>
<p class="text-subtle text-lg leading-relaxed mb-8 max-w-md">
Cá nhân hóa lộ trình học tập để bứt phá điểm số trong thời gian ngắn nhất. AI phân tích điểm yếu và tối ưu bài tập cho bạn.
</p>
<div class="flex gap-3 flex-wrap">
<button onclick="navigate('parts')" class="bg-primary text-white px-8 py-3.5 rounded-xl font-bold text-sm hover:bg-primary-dark transition-colors shadow-lg shadow-primary/20">
Bắt đầu ngay
</button>
<button onclick="navigate('writing')" class="border border-border px-8 py-3.5 rounded-xl font-bold text-sm text-subtle hover:bg-white hover:border-primary hover:text-primary transition-all">
Thử AI Writing
</button>
</div>
<!-- Mini stats -->
<div class="flex gap-6 mt-8">
<div><span class="text-2xl font-extrabold text-primary">350+</span><div class="text-xs text-muted mt-0.5">Câu hỏi TOEIC</div></div>
<div class="w-px bg-border"></div>
<div><span class="text-2xl font-extrabold text-success">720</span><div class="text-xs text-muted mt-0.5">Từ vựng</div></div>
<div class="w-px bg-border"></div>
<div><span class="text-2xl font-extrabold" style="color:#D97706">AI</span><div class="text-xs text-muted mt-0.5">Writing Checker</div></div>
</div>
</div>
<!-- Hero preview card -->
<div class="hero-preview flex-shrink-0 w-80">
<div class="bg-card rounded-2xl p-6 shadow-xl border border-border">
<div class="flex items-center justify-between mb-5">
<div>
<div class="font-bold text-base">Tiến độ tuần này</div>
<div class="text-xs text-muted mt-0.5">Bạn đang làm rất tốt!</div>
</div>
<div class="bg-success-light text-success text-xs font-bold px-2.5 py-1 rounded-lg">+12%</div>
</div>
<div class="mb-4">
<div class="flex justify-between text-xs font-semibold mb-1.5">
<span>Reading Score</span><span class="text-primary">420/495</span>
</div>
<div class="progress-bar"><div class="progress-fill" style="width:85%"></div></div>
</div>
<div class="mb-4">
<div class="flex justify-between text-xs font-semibold mb-1.5">
<span>Listening Score</span><span class="text-primary">380/495</span>
</div>
<div class="progress-bar"><div class="progress-fill" style="width:77%;background:#16A34A"></div></div>
</div>
<div class="grid grid-cols-2 gap-3 mt-4">
<div class="bg-primary-light rounded-xl p-3 border-l-4 border-primary">
<span class="material-symbols-outlined text-primary" style="font-size:18px">local_fire_department</span>
<div class="text-xl font-extrabold text-primary mt-1">14</div>
<div class="text-xs text-muted">Ngày Streak</div>
</div>
<div class="bg-success-light rounded-xl p-3 border-l-4 border-success">
<span class="material-symbols-outlined text-success" style="font-size:18px;font-variation-settings:'FILL' 1">star</span>
<div class="text-xl font-extrabold text-success mt-1">1,250</div>
<div class="text-xs text-muted">Điểm tích lũy</div>
</div>
</div>
<div class="mt-4 pt-4 border-t border-border flex items-center gap-3">
<div class="w-8 h-8 rounded-full bg-surface flex items-center justify-center flex-shrink-0">
<span class="material-symbols-outlined text-subtle" style="font-size:16px">psychology</span>
</div>
<div class="text-xs text-subtle"><span class="font-semibold">AI gợi ý:</span> Ôn thêm Part 5 — Ngữ pháp</div>
</div>
</div>
</div>
</section>
<!-- Feature cards -->
<section>
<h2 class="text-2xl font-extrabold mb-2">Tính năng nổi bật</h2>
<p class="text-subtle mb-6">Hệ sinh thái học tập toàn diện được thiết kế để tối ưu hoá điểm số.</p>
<div class="feature-cards grid grid-cols-3 gap-6">
<div onclick="navigate('parts')" class="part-card bg-card rounded-2xl p-6 border border-border cursor-pointer border-l-4 border-l-primary">
<div class="w-12 h-12 bg-primary-light rounded-xl flex items-center justify-center mb-4">
<span class="material-symbols-outlined text-primary">assignment</span>
</div>
<h3 class="font-bold text-base mb-2">Luyện đề TOEIC</h3>
<p class="text-subtle text-sm leading-relaxed mb-4">Kho đề thi cập nhật theo cấu trúc mới nhất. Phân tích điểm yếu chi tiết.</p>
<div class="flex items-center gap-1.5 text-primary text-sm font-bold">
Bắt đầu ngay <span class="material-symbols-outlined" style="font-size:16px">arrow_forward</span>
</div>
</div>
<div onclick="navigate('writing')" class="part-card bg-card rounded-2xl p-6 border border-border cursor-pointer border-l-4" style="border-left-color:#16A34A">
<div class="w-12 h-12 rounded-xl flex items-center justify-center mb-4" style="background:#f0fdf4">
<span class="material-symbols-outlined" style="color:#16A34A">auto_fix_high</span>
</div>
<h3 class="font-bold text-base mb-2">AI Chấm Writing</h3>
<p class="text-subtle text-sm leading-relaxed mb-4">Phản hồi tức thì về ngữ pháp, từ vựng, cấu trúc và bài viết mẫu.</p>
<div class="flex items-center gap-1.5 text-sm font-bold" style="color:#16A34A">
Thử ngay <span class="material-symbols-outlined" style="font-size:16px">arrow_forward</span>
</div>
</div>
<div onclick="navigate('vocab')" class="part-card bg-card rounded-2xl p-6 border border-border cursor-pointer border-l-4" style="border-left-color:#D97706">
<div class="w-12 h-12 rounded-xl flex items-center justify-center mb-4" style="background:#fffbeb">
<span class="material-symbols-outlined" style="color:#D97706">menu_book</span>
</div>
<h3 class="font-bold text-base mb-2">Từ vựng thông minh</h3>
<p class="text-subtle text-sm leading-relaxed mb-4">720 từ TOEIC theo 6 chủ đề. Flashcard với phương pháp lặp lại ngắt quãng.</p>
<div class="flex items-center gap-1.5 text-sm font-bold" style="color:#D97706">
Khám phá <span class="material-symbols-outlined" style="font-size:16px">arrow_forward</span>
</div>
</div>
</div>
</section>
<!-- CTA banner -->
<section class="mt-10">
<div class="bg-primary rounded-2xl p-8 flex items-center justify-between overflow-hidden relative">
<div class="absolute right-0 top-0 bottom-0 w-32 opacity-10 flex items-center justify-end pr-6">
<span class="material-symbols-outlined text-white" style="font-size:120px">emoji_events</span>
</div>
<div class="relative z-10">
<h3 class="text-2xl font-extrabold text-white mb-2">Sẵn sàng chinh phục 990 TOEIC?</h3>
<p class="text-blue-100 mb-5">Không cần đăng nhập — dùng thử ngay miễn phí hôm nay.</p>
<button onclick="navigate('parts')" class="bg-white text-primary px-6 py-3 rounded-xl font-bold text-sm hover:bg-blue-50 transition-colors">
Bắt đầu luyện đề
</button>
</div>
</div>
</section>
</div>
</main>
<!-- ============================================================ -->
<!-- SCREEN 2: PART SELECTION -->
<!-- ============================================================ -->
<main id="screen-parts" class="screen main-content" style="margin-left:240px; padding-top:64px;">
<div class="px-8 py-8 max-w-6xl mx-auto">
<div class="mb-8">
<h1 class="text-3xl font-extrabold mb-2">Chọn Part TOEIC</h1>
<p class="text-subtle">Hệ thống ôn luyện theo cấu trúc bài thi TOEIC thực tế. Chọn phần cụ thể để bắt đầu.</p>
</div>
<!-- Part cards grid -->
<div class="parts-grid grid gap-5">
<!-- Part 1 -->
<div class="part-card bg-card rounded-2xl p-5 border border-border cursor-pointer" onclick="startExam(1,'Mô tả hình ảnh')">
<div class="flex justify-between items-start mb-5">
<div class="w-10 h-10 bg-primary-light rounded-xl flex items-center justify-center">
<span class="material-symbols-outlined text-primary" style="font-size:18px">image</span>
</div>
<div class="relative w-11 h-11 flex items-center justify-center flex-shrink-0">
<svg class="w-11 h-11 -rotate-90" viewBox="0 0 44 44">
<circle cx="22" cy="22" r="18" fill="none" stroke="#e2e8f0" stroke-width="3.5"/>
<circle cx="22" cy="22" r="18" fill="none" stroke="#2563EB" stroke-width="3.5" stroke-linecap="round"
stroke-dasharray="113.1" stroke-dashoffset="45.24"/>
</svg>
<span class="absolute text-[10px] font-bold text-body">60%</span>
</div>
</div>
<div class="font-extrabold text-lg mb-0.5">Part 1</div>
<div class="text-sm font-semibold text-body mb-2">Mô tả hình ảnh</div>
<div class="flex items-center gap-1.5 text-xs text-muted">
<span class="material-symbols-outlined" style="font-size:14px">list_alt</span> 45 câu hỏi
</div>
</div>
<!-- Part 2 -->
<div class="part-card bg-card rounded-2xl p-5 border border-border cursor-pointer" onclick="startExam(2,'Hỏi-đáp')">
<div class="flex justify-between items-start mb-5">
<div class="w-10 h-10 bg-primary-light rounded-xl flex items-center justify-center">
<span class="material-symbols-outlined text-primary" style="font-size:18px">question_answer</span>
</div>
<div class="relative w-11 h-11 flex items-center justify-center flex-shrink-0">
<svg class="w-11 h-11 -rotate-90" viewBox="0 0 44 44">
<circle cx="22" cy="22" r="18" fill="none" stroke="#e2e8f0" stroke-width="3.5"/>
<circle cx="22" cy="22" r="18" fill="none" stroke="#2563EB" stroke-width="3.5" stroke-linecap="round"
stroke-dasharray="113.1" stroke-dashoffset="67.86"/>
</svg>
<span class="absolute text-[10px] font-bold text-body">40%</span>
</div>
</div>
<div class="font-extrabold text-lg mb-0.5">Part 2</div>
<div class="text-sm font-semibold text-body mb-2">Hỏi-đáp</div>
<div class="flex items-center gap-1.5 text-xs text-muted">
<span class="material-symbols-outlined" style="font-size:14px">list_alt</span> 30 câu hỏi
</div>
</div>
<!-- Part 3 -->
<div class="part-card bg-card rounded-2xl p-5 border border-border cursor-pointer" onclick="startExam(3,'Đoạn hội thoại')">
<div class="flex justify-between items-start mb-5">
<div class="w-10 h-10 bg-primary-light rounded-xl flex items-center justify-center">
<span class="material-symbols-outlined text-primary" style="font-size:18px">forum</span>
</div>
<div class="relative w-11 h-11 flex items-center justify-center flex-shrink-0">
<svg class="w-11 h-11 -rotate-90" viewBox="0 0 44 44">
<circle cx="22" cy="22" r="18" fill="none" stroke="#e2e8f0" stroke-width="3.5"/>
<circle cx="22" cy="22" r="18" fill="none" stroke="#2563EB" stroke-width="3.5" stroke-linecap="round"
stroke-dasharray="113.1" stroke-dashoffset="84.83"/>
</svg>
<span class="absolute text-[10px] font-bold text-body">25%</span>
</div>
</div>
<div class="font-extrabold text-lg mb-0.5">Part 3</div>
<div class="text-sm font-semibold text-body mb-2">Đoạn hội thoại</div>
<div class="flex items-center gap-1.5 text-xs text-muted">
<span class="material-symbols-outlined" style="font-size:14px">list_alt</span> 39 câu hỏi
</div>
</div>
<!-- Part 4 -->
<div class="part-card bg-card rounded-2xl p-5 border border-border cursor-pointer" onclick="startExam(4,'Bài nói')">
<div class="flex justify-between items-start mb-5">
<div class="w-10 h-10 bg-primary-light rounded-xl flex items-center justify-center">
<span class="material-symbols-outlined text-primary" style="font-size:18px">record_voice_over</span>
</div>
<div class="relative w-11 h-11 flex items-center justify-center flex-shrink-0">
<svg class="w-11 h-11 -rotate-90" viewBox="0 0 44 44">
<circle cx="22" cy="22" r="18" fill="none" stroke="#e2e8f0" stroke-width="3.5"/>
<circle cx="22" cy="22" r="18" fill="none" stroke="#2563EB" stroke-width="3.5" stroke-linecap="round"
stroke-dasharray="113.1" stroke-dashoffset="101.79"/>
</svg>
<span class="absolute text-[10px] font-bold text-body">10%</span>
</div>
</div>
<div class="font-extrabold text-lg mb-0.5">Part 4</div>
<div class="text-sm font-semibold text-body mb-2">Bài nói</div>
<div class="flex items-center gap-1.5 text-xs text-muted">
<span class="material-symbols-outlined" style="font-size:14px">list_alt</span> 30 câu hỏi
</div>
</div>
<!-- Part 5 -->
<div class="part-card bg-card rounded-2xl p-5 border border-border cursor-pointer" onclick="startExam(5,'Điền từ')">
<div class="flex justify-between items-start mb-5">
<div class="w-10 h-10 bg-primary-light rounded-xl flex items-center justify-center">
<span class="material-symbols-outlined text-primary" style="font-size:18px">history_edu</span>
</div>
<div class="relative w-11 h-11 flex items-center justify-center flex-shrink-0">
<svg class="w-11 h-11 -rotate-90" viewBox="0 0 44 44">
<circle cx="22" cy="22" r="18" fill="none" stroke="#e2e8f0" stroke-width="3.5"/>
<circle cx="22" cy="22" r="18" fill="none" stroke="#2563EB" stroke-width="3.5" stroke-linecap="round"
stroke-dasharray="113.1" stroke-dashoffset="22.62"/>
</svg>
<span class="absolute text-[10px] font-bold text-body">80%</span>
</div>
</div>
<div class="font-extrabold text-lg mb-0.5">Part 5</div>
<div class="text-sm font-semibold text-body mb-2">Điền từ</div>
<div class="flex items-center gap-1.5 text-xs text-muted">
<span class="material-symbols-outlined" style="font-size:14px">list_alt</span> 40 câu hỏi
</div>
</div>
<!-- Part 6 -->
<div class="part-card bg-card rounded-2xl p-5 border border-border cursor-pointer" onclick="startExam(6,'Điền đoạn')">
<div class="flex justify-between items-start mb-5">
<div class="w-10 h-10 bg-primary-light rounded-xl flex items-center justify-center">
<span class="material-symbols-outlined text-primary" style="font-size:18px">article</span>
</div>
<div class="relative w-11 h-11 flex items-center justify-center flex-shrink-0">
<svg class="w-11 h-11 -rotate-90" viewBox="0 0 44 44">
<circle cx="22" cy="22" r="18" fill="none" stroke="#e2e8f0" stroke-width="3.5"/>
<circle cx="22" cy="22" r="18" fill="none" stroke="#2563EB" stroke-width="3.5" stroke-linecap="round"
stroke-dasharray="113.1" stroke-dashoffset="56.55"/>
</svg>
<span class="absolute text-[10px] font-bold text-body">50%</span>
</div>
</div>
<div class="font-extrabold text-lg mb-0.5">Part 6</div>
<div class="text-sm font-semibold text-body mb-2">Điền đoạn</div>
<div class="flex items-center gap-1.5 text-xs text-muted">
<span class="material-symbols-outlined" style="font-size:14px">list_alt</span> 16 câu hỏi
</div>
</div>
<!-- Part 7 -->
<div class="part-card bg-card rounded-2xl p-5 border border-border cursor-pointer" onclick="startExam(7,'Đọc hiểu')">
<div class="flex justify-between items-start mb-5">
<div class="w-10 h-10 bg-primary-light rounded-xl flex items-center justify-center">
<span class="material-symbols-outlined text-primary" style="font-size:18px">chrome_reader_mode</span>
</div>
<div class="relative w-11 h-11 flex items-center justify-center flex-shrink-0">
<svg class="w-11 h-11 -rotate-90" viewBox="0 0 44 44">
<circle cx="22" cy="22" r="18" fill="none" stroke="#e2e8f0" stroke-width="3.5"/>
<circle cx="22" cy="22" r="18" fill="none" stroke="#2563EB" stroke-width="3.5" stroke-linecap="round"
stroke-dasharray="113.1" stroke-dashoffset="79.17"/>
</svg>
<span class="absolute text-[10px] font-bold text-body">30%</span>
</div>
</div>
<div class="font-extrabold text-lg mb-0.5">Part 7</div>
<div class="text-sm font-semibold text-body mb-2">Đọc hiểu</div>
<div class="flex items-center gap-1.5 text-xs text-muted">
<span class="material-symbols-outlined" style="font-size:14px">list_alt</span> 54 câu hỏi
</div>
</div>
<!-- Full Test -->
<div class="part-card rounded-2xl p-5 cursor-pointer relative overflow-hidden" style="background:linear-gradient(135deg,#f59e0b,#d97706)" onclick="startExam(0,'Full Test')">
<div class="absolute top-0 right-0 opacity-10">
<span class="material-symbols-outlined text-white" style="font-size:80px">workspace_premium</span>
</div>
<div class="relative z-10">
<div class="w-10 h-10 bg-white/20 rounded-xl flex items-center justify-center mb-5">
<span class="material-symbols-outlined text-white" style="font-size:18px">military_tech</span>
</div>
<div class="font-extrabold text-2xl text-white mb-0.5">Full Test</div>
<div class="text-sm font-semibold text-amber-50 mb-2">Mô phỏng thi thật 2h</div>
<div class="flex items-center gap-1.5 text-xs text-amber-100">
<span class="material-symbols-outlined" style="font-size:14px">timer</span> 120 phút • 200 câu
</div>
</div>
</div>
</div>
<!-- Tip card -->
<div class="mt-8 bg-primary-light border border-primary/20 rounded-2xl p-5 flex items-start gap-4">
<span class="material-symbols-outlined text-primary flex-shrink-0 mt-0.5">tips_and_updates</span>
<div>
<div class="font-semibold text-primary text-sm mb-1">Mẹo luyện thi</div>
<p class="text-subtle text-sm">Bắt đầu từ Part 5 (Điền từ) — đây là phần mang lại điểm số nhanh nhất vì không phụ thuộc vào kỹ năng nghe. Mỗi ngày 20 câu, sau 2 tuần bạn sẽ thấy cải thiện rõ rệt.</p>
</div>
</div>
</div>
</main>
<!-- ============================================================ -->
<!-- SCREEN 3: EXAM SESSION -->
<!-- ============================================================ -->
<main id="screen-exam" class="screen main-content" style="margin-left:240px; padding-top:64px;">
<div class="px-6 py-6 max-w-6xl mx-auto">
<!-- Mobile progress bar -->
<div class="lg:hidden mb-4">
<div class="flex items-center justify-between mb-2 text-sm font-semibold">
<span id="mob-header">Part 2 — Câu 1/10</span>
<span id="mob-timer" class="text-primary font-bold">10:00</span>
</div>
<div class="progress-bar"><div id="mob-progress" class="progress-fill" style="width:10%"></div></div>
</div>
<div class="exam-layout flex gap-6">
<!-- Left: Question -->
<div class="flex-1 min-w-0">
<div class="bg-card rounded-2xl p-6 border border-border mb-4">
<div class="flex items-center gap-2 mb-4">
<div class="bg-primary text-white text-xs font-bold px-3 py-1 rounded-full" id="q-label">Câu 1</div>
<div class="text-xs text-muted" id="q-part-label">Part 2 — Hỏi-đáp</div>
</div>
<p class="text-base font-medium leading-relaxed mb-6" id="q-text">
What does the man suggest the woman do about the budget report?
</p>
<div class="space-y-3" id="answer-options">
<!-- Rendered by JS -->
</div>
</div>
<!-- Nav buttons -->
<div class="flex items-center justify-between">
<button onclick="prevQuestion()" class="flex items-center gap-2 px-5 py-2.5 border border-border rounded-xl text-sm font-semibold hover:bg-surface transition-colors">
<span class="material-symbols-outlined" style="font-size:18px">chevron_left</span> Câu trước
</button>
<div class="text-xs text-muted" id="q-counter">1 / 10</div>
<button onclick="nextQuestion()" class="flex items-center gap-2 px-5 py-2.5 bg-primary text-white rounded-xl text-sm font-semibold hover:bg-primary-dark transition-colors">
Câu tiếp theo <span class="material-symbols-outlined" style="font-size:18px">chevron_right</span>
</button>
</div>
</div>
<!-- Right: Timer + dots + submit -->
<div class="w-64 flex-shrink-0 hidden lg:block">
<div class="bg-card rounded-2xl p-5 border border-border mb-4">
<div class="text-xs text-muted text-center mb-2 font-medium">Thời gian còn lại</div>
<div id="timer" class="text-5xl font-extrabold text-center text-primary mb-1" style="font-variant-numeric:tabular-nums">10:00</div>
<div class="text-xs text-center text-muted">phút : giây</div>
</div>
<div class="bg-card rounded-2xl p-5 border border-border mb-4">
<div class="text-xs text-muted font-medium mb-3">Danh sách câu hỏi</div>
<div class="grid grid-cols-5 gap-2" id="q-dots"></div>
<div class="flex items-center gap-3 mt-4 text-xs text-muted">
<span class="w-5 h-5 rounded-full bg-primary inline-block"></span> Đã trả lời
<span class="w-5 h-5 rounded-full border-2 border-border inline-block"></span> Chưa làm
</div>
</div>
<button onclick="submitExam()" class="w-full py-3 bg-danger text-white rounded-xl font-bold text-sm hover:bg-red-700 transition-colors flex items-center justify-center gap-2">
<span class="material-symbols-outlined" style="font-size:18px">send</span> Nộp bài
</button>
</div>
</div>
<!-- Mobile submit -->
<div class="lg:hidden mt-4">
<button onclick="submitExam()" class="w-full py-3.5 bg-danger text-white rounded-xl font-bold text-sm">
Nộp bài ngay
</button>
</div>
</div>
</main>
<!-- ============================================================ -->
<!-- SCREEN 4: RESULTS -->
<!-- ============================================================ -->
<main id="screen-results" class="screen main-content" style="margin-left:240px; padding-top:64px;">
<div class="px-8 py-8 max-w-6xl mx-auto">
<!-- Top stats row -->
<div class="flex flex-wrap items-center gap-6 mb-8">
<!-- Score circle -->
<div class="flex-shrink-0">
<div class="relative w-28 h-28">
<svg class="w-28 h-28 -rotate-90" viewBox="0 0 112 112">
<circle cx="56" cy="56" r="48" fill="none" stroke="#e2e8f0" stroke-width="8"/>
<circle cx="56" cy="56" r="48" fill="none" stroke="#16A34A" stroke-width="8" stroke-linecap="round"
stroke-dasharray="301.59" stroke-dashoffset="60.32"/>
</svg>
<div class="absolute inset-0 flex flex-col items-center justify-center">
<div class="text-3xl font-extrabold text-success">8/10</div>
<div class="text-xs text-muted font-medium">điểm</div>
</div>
</div>
</div>
<!-- Title + stats -->
<div class="flex-1 min-w-0">
<h1 class="text-3xl font-extrabold mb-1">Hoàn thành!</h1>
<p class="text-subtle mb-4">Bạn đã hoàn thành bài kiểm tra Part 2 — Hỏi-đáp</p>
<div class="flex flex-wrap gap-3">
<div class="bg-success-light text-success px-4 py-2 rounded-xl text-sm font-bold flex items-center gap-1.5">
<span class="material-symbols-outlined" style="font-size:16px">check_circle</span> 8 Đúng
</div>
<div class="bg-danger-light text-danger px-4 py-2 rounded-xl text-sm font-bold flex items-center gap-1.5">
<span class="material-symbols-outlined" style="font-size:16px">cancel</span> 2 Sai
</div>
<div class="bg-surface text-subtle px-4 py-2 rounded-xl text-sm font-bold flex items-center gap-1.5">
<span class="material-symbols-outlined" style="font-size:16px">schedule</span> 4:32
</div>
</div>
</div>
<!-- Action buttons -->
<div class="flex gap-3">
<button onclick="navigate('parts')" class="px-5 py-2.5 border border-border rounded-xl text-sm font-bold hover:bg-surface transition-colors">
Làm lại
</button>
<button onclick="navigate('home')" class="px-5 py-2.5 bg-primary text-white rounded-xl text-sm font-bold hover:bg-primary-dark transition-colors">
Về trang chủ
</button>
</div>
</div>
<!-- Bottom: chart + review -->
<div class="results-bottom flex gap-6">
<!-- Chart -->
<div class="bg-card rounded-2xl p-6 border border-border" style="width:340px;flex-shrink:0">
<h3 class="font-bold text-base mb-5">Phân tích kết quả</h3>
<div class="space-y-3">
<div>
<div class="flex justify-between text-xs font-semibold mb-1.5">
<span>Part 2 — Hỏi-đáp</span><span class="text-success">80%</span>
</div>
<div class="flex gap-1.5 h-6">
<div class="bg-success rounded flex-1" style="flex:8"></div>
<div class="bg-danger rounded" style="flex:2"></div>
</div>
</div>
<div class="mt-6">
<h4 class="font-semibold text-sm mb-3">Điểm mạnh</h4>
<div class="space-y-2 text-sm text-subtle">
<div class="flex items-center gap-2"><span class="material-symbols-outlined text-success" style="font-size:16px">check</span>Câu hỏi thì hiện tại</div>
<div class="flex items-center gap-2"><span class="material-symbols-outlined text-success" style="font-size:16px">check</span>Câu hỏi cú pháp đơn giản</div>
</div>
<h4 class="font-semibold text-sm mb-3 mt-4">Cần cải thiện</h4>
<div class="space-y-2 text-sm text-subtle">
<div class="flex items-center gap-2"><span class="material-symbols-outlined text-danger" style="font-size:16px">close</span>Câu hỏi gián tiếp</div>
<div class="flex items-center gap-2"><span class="material-symbols-outlined" style="font-size:16px;color:#D97706">warning</span>Diễn đạt mơ hồ</div>
</div>
</div>
</div>
</div>
<!-- Answer review list -->
<div class="flex-1 bg-card rounded-2xl border border-border overflow-hidden">
<div class="px-6 py-4 border-b border-border font-bold text-base">Xem lại đáp án</div>
<div class="overflow-y-auto" style="max-height:440px">
<div id="review-list"></div>
</div>
</div>
</div>
</div>
</main>
<!-- ============================================================ -->
<!-- SCREEN 5: AI WRITING -->
<!-- ============================================================ -->
<main id="screen-writing" class="screen main-content" style="margin-left:240px; padding-top:64px;">
<div class="px-8 py-8 max-w-6xl mx-auto">
<div class="mb-6">
<h1 class="text-3xl font-extrabold mb-1.5">AI Chấm Writing</h1>
<p class="text-subtle">Nhập bài writing của bạn để nhận phản hồi chi tiết từ AI về ngữ pháp, từ vựng và cấu trúc.</p>
</div>
<div class="writing-layout flex gap-6">
<!-- Left: Input -->
<div class="flex-1 min-w-0">
<div class="bg-card rounded-2xl p-6 border border-border h-full flex flex-col">
<div class="flex items-center justify-between mb-3">
<label class="font-semibold text-sm">Bài writing của bạn</label>
<div class="flex items-center gap-2 text-xs text-muted">
<span class="material-symbols-outlined" style="font-size:14px">bolt</span>
<span class="bg-amber-light text-amber-font-semibold px-2.5 py-1 rounded-full font-semibold" style="color:#D97706">Còn 2/3 lượt hôm nay</span>
</div>
</div>
<textarea id="writing-input"
class="flex-1 w-full border border-border rounded-xl p-4 text-sm leading-relaxed resize-none focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"
rows="14"
placeholder="Nhập bài writing của bạn vào đây..."
oninput="updateCharCount(this)"
>The company has decided to implement a new remote work policy starting next month. All employees will be able to work from home for three days per week. This change is expected to improve work-life balance and increase productivity. However, some managers are concern about communication challenges and team collaboration. The HR department will organize training sessions to help teams adapt to this new arrangement.</textarea>
<div class="flex items-center justify-between mt-3">
<span id="char-count" class="text-xs text-muted">356 / 1000 ký tự</span>
<button onclick="checkWriting()" class="flex items-center gap-2 bg-primary text-white px-6 py-3 rounded-xl font-bold text-sm hover:bg-primary-dark transition-colors shadow-md shadow-primary/20">
<span class="material-symbols-outlined" style="font-size:18px">auto_awesome</span>
Chấm bài ngay
</button>
</div>
<div class="mt-4 bg-surface rounded-xl p-4 text-xs text-muted leading-relaxed">
<strong class="text-body">Gợi ý đề bài:</strong> Viết một email thông báo thay đổi chính sách làm việc cho nhân viên (80150 từ). Yêu cầu: nêu lý do, giải thích thay đổi, và trình bày rõ kế hoạch triển khai.
</div>
</div>
</div>
<!-- Right: Feedback panel -->
<div class="w-96 flex-shrink-0">
<div class="bg-card rounded-2xl border border-border overflow-hidden" id="feedback-panel">
<!-- Band score -->
<div class="bg-primary p-5 text-center">
<div class="text-white/70 text-xs font-semibold mb-1">Band Score ước tính</div>
<div class="text-5xl font-extrabold text-white">6.5</div>
<div class="text-blue-200 text-xs mt-1">Upper Intermediate</div>
</div>
<div class="p-4 space-y-3 overflow-y-auto" style="max-height:520px">
<!-- Grammar -->
<div class="feedback-section bg-danger-light" style="border-left:4px solid #DC2626">
<div class="header text-danger">
<span class="material-symbols-outlined" style="font-size:16px;font-variation-settings:'FILL' 1">error</span>
Ngữ pháp (Grammar)
</div>
<ul style="color:#DC2626">
<li>"managers are <strong>concern</strong>" → nên dùng <strong>"concerned"</strong> (tính từ)</li>
<li>"has decided to implement" → đúng nhưng có thể dùng "will implement" tự nhiên hơn</li>
<li>Thiếu mạo từ "a" trước "new arrangement" ở câu cuối</li>
</ul>
</div>
<!-- Vocabulary -->
<div class="feedback-section bg-amber-light" style="border-left:4px solid #D97706">
<div class="header" style="color:#D97706">
<span class="material-symbols-outlined" style="font-size:16px;font-variation-settings:'FILL' 1">lightbulb</span>
Từ vựng (Vocabulary)
</div>
<ul style="color:#92400e">
<li>Tốt: "implement", "productivity", "collaboration", "arrangement"</li>
<li>Gợi ý nâng cao: "enhance" thay "increase", "address" thay "help"</li>
<li>Cần thêm từ nối: "Nevertheless", "In addition", "As a result"</li>
</ul>
</div>
<!-- Structure -->
<div class="feedback-section bg-primary-light" style="border-left:4px solid #2563EB">
<div class="header text-primary">
<span class="material-symbols-outlined" style="font-size:16px;font-variation-settings:'FILL' 1">segment</span>
Cấu trúc bài (Structure)
</div>
<p style="font-size:13px;color:#1e40af">Bài viết có cấu trúc rõ ràng với mở đầu, thân bài và kết luận ngầm. Tuy nhiên, cần phát triển thêm phần giải thích tác động và thêm ví dụ cụ thể để bài hoàn chỉnh hơn.</p>
</div>
<!-- Summary -->
<div class="feedback-section bg-surface" style="border-left:4px solid #94a3b8">
<div class="header text-subtle">
<span class="material-symbols-outlined" style="font-size:16px">summarize</span>
Tổng nhận xét
</div>
<p style="font-size:13px;color:#475569">Bài viết đạt mức Upper Intermediate với ý tưởng rõ ràng. Cần sửa lỗi ngữ pháp cơ bản và bổ sung từ vựng phong phú hơn để đạt band 7.0+.</p>
</div>
<!-- Improved version (collapsible) -->
<div class="bg-success-light rounded-xl border border-green-200">
<button onclick="toggleImproved()" class="w-full flex items-center justify-between p-4 text-left">
<span class="font-bold text-sm text-success flex items-center gap-2">
<span class="material-symbols-outlined" style="font-size:16px;font-variation-settings:'FILL' 1">auto_fix_high</span>
Bài viết cải thiện
</span>
<span class="material-symbols-outlined text-success" style="font-size:18px" id="improved-icon">expand_more</span>
</button>
<div id="improved-content" class="collapsible-content px-4 pb-4">
<p class="text-sm leading-relaxed" style="color:#166534">The company has decided to <strong>implement</strong> a new remote work policy starting next month. All employees will be able to work from home for three days per week. This change is expected to <strong>enhance</strong> work-life balance and <strong>boost overall</strong> productivity. Nevertheless, some managers are <strong>concerned</strong> about communication challenges and team collaboration. <strong>To address</strong> these concerns, the HR department will organize training sessions to help teams adapt to this new arrangement <strong>effectively</strong>.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<!-- ============================================================ -->
<!-- SCREEN 6: FLASHCARD VOCABULARY -->
<!-- ============================================================ -->
<main id="screen-vocab" class="screen main-content" style="margin-left:240px; padding-top:64px;">
<div class="px-8 py-8 max-w-6xl mx-auto">
<div class="mb-6">
<h1 class="text-3xl font-extrabold mb-1.5">Từ vựng TOEIC</h1>
<p class="text-subtle">Học từ vựng theo chủ đề với Flashcard và phương pháp lặp lại ngắt quãng.</p>
</div>
<!-- Mobile topic chips -->
<div class="vocab-topics-mobile overflow-x-auto pb-2 mb-5 gap-2 flex-nowrap">
<!-- Rendered by JS -->
</div>
<div class="vocab-3col grid gap-6">
<!-- Left: Topics -->
<div class="vocab-topics-side">
<div class="bg-card rounded-2xl border border-border overflow-hidden">
<div class="px-4 py-3 border-b border-border font-semibold text-sm">Chủ đề</div>
<div id="topic-list" class="py-2">
<!-- Rendered by JS -->
</div>
</div>
</div>
<!-- Center: Flashcard -->
<div class="flex flex-col items-center">
<!-- Card flip scene -->
<div class="card-scene w-full" style="max-width:420px;height:280px;margin-bottom:24px">
<div class="card-inner w-full h-full" id="card-inner" onclick="flipCard()">
<!-- Front -->
<div class="card-face bg-card border border-border flex flex-col items-center justify-center p-8 cursor-pointer shadow-lg" style="height:280px">
<div class="text-4xl font-extrabold mb-2" id="card-word">negotiate</div>
<div class="text-muted text-lg mb-4" id="card-phonetic">/nɪˈɡoʊʃieɪt/</div>
<div class="bg-primary-light text-primary text-xs font-bold px-3 py-1 rounded-full" id="card-topic-badge">Business</div>
<div class="mt-6 text-xs text-muted flex items-center gap-1">
<span class="material-symbols-outlined" style="font-size:14px">touch_app</span>
Nhấn để xem nghĩa
</div>
</div>
<!-- Back -->
<div class="card-face card-back flex flex-col items-center justify-center p-8 cursor-pointer shadow-lg" style="height:280px;background:linear-gradient(135deg,#eff6ff,#dbeafe)">
<div class="text-3xl font-extrabold text-primary mb-2" id="card-meaning">đàm phán</div>
<div class="text-xs text-muted mb-4 font-semibold uppercase tracking-wide">Nghĩa tiếng Việt</div>
<div class="bg-white rounded-xl p-3 border border-blue-100 text-sm text-subtle italic text-center" id="card-example">
"We need to <strong>negotiate</strong> the contract terms before signing."
</div>
</div>
</div>
</div>
<!-- Action buttons -->
<div class="flex gap-3 mb-5">
<button onclick="markNeedReview()" class="flex items-center gap-2 px-6 py-3 border-2 border-border rounded-xl text-sm font-bold hover:border-amber-500 hover:text-amber-500 transition-colors min-h-[44px]">
<span class="material-symbols-outlined" style="font-size:18px">replay</span> Cần ôn
</button>
<button onclick="markKnown()" class="flex items-center gap-2 px-6 py-3 bg-success text-white rounded-xl text-sm font-bold hover:bg-green-700 transition-colors min-h-[44px]">
<span class="material-symbols-outlined" style="font-size:18px">check</span> Đã thuộc
</button>
</div>
<!-- Progress -->
<div class="w-full max-w-sm">
<div class="flex justify-between text-xs font-semibold mb-2">
<span id="vocab-progress-text">32 / 120 từ đã thuộc</span>
<span class="text-primary" id="vocab-progress-pct">27%</span>
</div>
<div class="progress-bar"><div class="progress-fill" id="vocab-bar" style="width:27%"></div></div>
</div>
<!-- Prev/Next -->
<div class="flex items-center gap-4 mt-4">
<button onclick="prevCard()" class="w-10 h-10 flex items-center justify-center border border-border rounded-full hover:bg-surface transition-colors min-h-[44px] min-w-[44px]">
<span class="material-symbols-outlined" style="font-size:20px">chevron_left</span>
</button>
<span class="text-sm text-muted" id="card-counter">1 / 24</span>
<button onclick="nextCard()" class="w-10 h-10 flex items-center justify-center border border-border rounded-full hover:bg-surface transition-colors min-h-[44px] min-w-[44px]">
<span class="material-symbols-outlined" style="font-size:20px">chevron_right</span>
</button>
</div>
</div>
<!-- Right: Stats -->
<div class="vocab-stats-side space-y-4">
<div class="bg-card rounded-2xl border border-border p-4">
<div class="font-semibold text-sm mb-4">Hôm nay</div>
<div class="space-y-3">
<div class="flex items-center justify-between">
<div class="flex items-center gap-2 text-sm text-subtle">
<span class="material-symbols-outlined text-primary" style="font-size:18px">school</span>Đã học
</div>
<span class="font-bold text-sm">12 từ</span>
</div>
<div class="flex items-center justify-between">
<div class="flex items-center gap-2 text-sm text-subtle">
<span class="material-symbols-outlined text-success" style="font-size:18px;font-variation-settings:'FILL' 1">check_circle</span>Đã thuộc
</div>
<span class="font-bold text-sm text-success">8 từ</span>
</div>
<div class="flex items-center justify-between">
<div class="flex items-center gap-2 text-sm text-subtle">
<span class="material-symbols-outlined" style="font-size:18px;color:#D97706">local_fire_department</span>Streak
</div>
<span class="font-bold text-sm" style="color:#D97706">🔥 5 ngày</span>
</div>
</div>
</div>
<div class="bg-card rounded-2xl border border-border p-4">
<div class="font-semibold text-sm mb-3">Vừa thuộc</div>
<div class="space-y-2" id="recent-words">
<div class="flex items-center gap-2 text-xs py-1.5 border-b border-border">
<span class="material-symbols-outlined text-success" style="font-size:14px;font-variation-settings:'FILL' 1">check_circle</span>
<span class="font-semibold">collaborate</span><span class="text-muted">hợp tác</span>
</div>
<div class="flex items-center gap-2 text-xs py-1.5 border-b border-border">
<span class="material-symbols-outlined text-success" style="font-size:14px;font-variation-settings:'FILL' 1">check_circle</span>
<span class="font-semibold">submit</span><span class="text-muted">nộp, gửi đi</span>
</div>
<div class="flex items-center gap-2 text-xs py-1.5">
<span class="material-symbols-outlined text-success" style="font-size:14px;font-variation-settings:'FILL' 1">check_circle</span>
<span class="font-semibold">delegate</span><span class="text-muted">uỷ quyền</span>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<!-- ============================================================ -->
<!-- JAVASCRIPT -->
<!-- ============================================================ -->
<script>
// ---- Data ----
const QUESTIONS = [
{ q: "What does the man suggest the woman do about the budget report?", opts: ["A. Submit it immediately", "B. Review it again carefully", "C. Postpone the deadline", "D. Ask a colleague for help"], ans: 1 },
{ q: "Where most likely are the speakers?", opts: ["A. In a restaurant", "B. At a conference", "C. In an office", "D. At an airport"], ans: 2 },
{ q: "Why is the man calling?", opts: ["A. To confirm a reservation", "B. To cancel an appointment", "C. To reschedule a meeting", "D. To order supplies"], ans: 0 },
{ q: "What will the woman do next?", opts: ["A. Call the manager", "B. Send an email", "C. Check the inventory", "D. Update the schedule"], ans: 3 },
{ q: "What problem does the man mention?", opts: ["A. A delayed shipment", "B. A broken device", "C. A missing document", "D. A scheduling conflict"], ans: 0 },
{ q: "How does the woman respond to the proposal?", opts: ["A. She accepts it", "B. She rejects it", "C. She needs more time", "D. She suggests modifications"], ans: 3 },
{ q: "What is the purpose of the announcement?", opts: ["A. To introduce new products", "B. To notify schedule changes", "C. To welcome new employees", "D. To announce a promotion"], ans: 1 },
{ q: "What does the woman ask the man to do?", opts: ["A. Prepare a presentation", "B. Contact the client", "C. Review the contract", "D. Attend a training session"], ans: 2 },
{ q: "When will the project be completed?", opts: ["A. By the end of this week", "B. Next Monday", "C. In two weeks", "D. Next month"], ans: 0 },
{ q: "What is being discussed at the meeting?", opts: ["A. Budget allocations", "B. Marketing strategies", "C. Product launches", "D. Staff promotions"], ans: 1 },
];
const VOCAB = {
"Tất cả": [
{ word: "negotiate", ph: "/nɪˈɡoʊʃieɪt/", vi: "đàm phán", topic: "Business", ex: "We need to negotiate the contract terms." },
{ word: "collaborate", ph: "/kəˈlæbəreɪt/", vi: "hợp tác", topic: "Business", ex: "Teams need to collaborate effectively." },
{ word: "submit", ph: "/səbˈmɪt/", vi: "nộp, gửi đi", topic: "Office", ex: "Please submit your report by Friday." },
{ word: "delegate", ph: "/ˈdelɪɡeɪt/", vi: "uỷ quyền, phân công", topic: "Business", ex: "A good manager knows how to delegate tasks." },
{ word: "itinerary", ph: "/aɪˈtɪnəreri/", vi: "lịch trình chuyến đi", topic: "Travel", ex: "Here is your travel itinerary for the conference." },
{ word: "reimburse", ph: "/ˌriːɪmˈːrs/", vi: "hoàn tiền", topic: "Finance", ex: "The company will reimburse your travel expenses." },
{ word: "recruit", ph: "/rɪˈkruːt/", vi: "tuyển dụng", topic: "HR", ex: "We are recruiting experienced engineers." },
{ word: "campaign", ph: "/kæmˈpeɪn/", vi: "chiến dịch", topic: "Marketing", ex: "The marketing campaign was very successful." },
],
"Business": [
{ word: "negotiate", ph: "/nɪˈɡoʊʃieɪt/", vi: "đàm phán", topic: "Business", ex: "We need to negotiate the contract terms." },
{ word: "collaborate", ph: "/kəˈlæbəreɪt/", vi: "hợp tác", topic: "Business", ex: "Teams need to collaborate effectively." },
{ word: "delegate", ph: "/ˈdelɪɡeɪt/", vi: "uỷ quyền", topic: "Business", ex: "A good manager delegates tasks well." },
{ word: "implement", ph: "/ˈɪmplɪment/", vi: "triển khai, thực hiện", topic: "Business", ex: "We plan to implement the new strategy next quarter." },
{ word: "merger", ph: "/ˈːrdʒər/", vi: "sáp nhập công ty", topic: "Business", ex: "The merger will create a stronger company." },
],
"Office": [
{ word: "submit", ph: "/səbˈmɪt/", vi: "nộp, gửi đi", topic: "Office", ex: "Please submit your report by Friday." },
{ word: "agenda", ph: "/əˈdʒendə/", vi: "chương trình nghị sự", topic: "Office", ex: "The agenda has been sent to all participants." },
{ word: "minutes", ph: "/ˈmɪnɪts/", vi: "biên bản họp", topic: "Office", ex: "Could you take the meeting minutes today?" },
{ word: "photocopier", ph: "/ˈfoʊtəkɒpiər/", vi: "máy photocopy", topic: "Office", ex: "The photocopier on the third floor is broken." },
],
"Travel": [
{ word: "itinerary", ph: "/aɪˈtɪnəreri/", vi: "lịch trình chuyến đi", topic: "Travel", ex: "Here is your travel itinerary for the conference." },
{ word: "boarding pass", ph: "/ˈːrdɪŋ pæs/", vi: "thẻ lên máy bay", topic: "Travel", ex: "Please have your boarding pass ready." },
{ word: "layover", ph: "/ˈleɪoʊvər/", vi: "thời gian quá cảnh", topic: "Travel", ex: "There is a two-hour layover in Singapore." },
{ word: "check-in", ph: "/ˈtʃekɪn/", vi: "làm thủ tục", topic: "Travel", ex: "Online check-in opens 24 hours before departure." },
],
"Finance": [
{ word: "reimburse", ph: "/ˌriːɪmˈːrs/", vi: "hoàn tiền", topic: "Finance", ex: "The company will reimburse travel expenses." },
{ word: "invoice", ph: "/ˈɪnvɔɪs/", vi: "hoá đơn", topic: "Finance", ex: "Please send us the invoice by email." },
{ word: "budget", ph: "/ˈbʌdʒɪt/", vi: "ngân sách", topic: "Finance", ex: "We need to stay within budget." },
{ word: "revenue", ph: "/ˈrevɪnjuː/", vi: "doanh thu", topic: "Finance", ex: "Revenue increased by 15% last quarter." },
],
"HR": [
{ word: "recruit", ph: "/rɪˈkruːt/", vi: "tuyển dụng", topic: "HR", ex: "We are actively recruiting new talent." },
{ word: "probation", ph: "/proʊˈbeɪʃən/", vi: "thử việc", topic: "HR", ex: "New employees have a 3-month probation period." },
{ word: "appraisal", ph: "/əˈpreɪzəl/", vi: "đánh giá nhân viên", topic: "HR", ex: "Annual appraisals will be held in December." },
{ word: "resignation", ph: "/ˌrezɪɡˈneɪʃən/", vi: "đơn từ chức", topic: "HR", ex: "She submitted her resignation letter this morning." },
],
"Marketing": [
{ word: "campaign", ph: "/kæmˈpeɪn/", vi: "chiến dịch", topic: "Marketing", ex: "The marketing campaign was very successful." },
{ word: "demographics", ph: "/ˌdeməˈɡræfɪks/", vi: "nhân khẩu học", topic: "Marketing", ex: "We need to understand our target demographics." },
{ word: "endorse", ph: "/ɪnˈːrs/", vi: "chứng thực, bảo trợ", topic: "Marketing", ex: "The product is endorsed by professional athletes." },
{ word: "branding", ph: "/ˈbrændɪŋ/", vi: "xây dựng thương hiệu", topic: "Marketing", ex: "Consistent branding builds customer trust." },
],
};
// ---- State ----
let currentScreen = 'home';
let examPart = 2;
let examPartName = 'Hỏi-đáp';
let currentQ = 0;
let answers = new Array(10).fill(null);
let timerInterval = null;
let timeLeft = 600;
let vocabTopic = 'Tất cả';
let vocabIndex = 0;
let knownCount = 32;
let cardFlipped = false;
let writingChecked = false;
// ---- Navigation ----
const SCREEN_TITLES = { home: 'Trang chủ', parts: 'Luyện đề TOEIC', exam: examPartName, results: 'Kết quả bài thi', writing: 'AI Chấm Writing', vocab: 'Từ vựng' };
function navigate(id) {
document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
const el = document.getElementById('screen-' + id);
if (!el) return;
el.classList.add('active');
el.classList.add('fade-in');
setTimeout(() => el.classList.remove('fade-in'), 300);
currentScreen = id;
// Sidebar active
document.querySelectorAll('.nav-item').forEach(n => n.classList.remove('active'));
const navKey = (id === 'exam' || id === 'results') ? 'parts' : id;
document.querySelectorAll('.nav-item[data-screen="' + navKey + '"]').forEach(n => n.classList.add('active'));
// Mobile nav active
document.querySelectorAll('.mobile-nav-item').forEach(n => n.classList.remove('active'));
document.querySelectorAll('.mobile-nav-item[data-screen="' + navKey + '"]').forEach(n => n.classList.add('active'));
// Header title
const titles = { home: 'Trang chủ', parts: 'Luyện đề TOEIC', exam: 'Part ' + examPart + ' — ' + examPartName, results: 'Kết quả bài thi', writing: 'AI Chấm Writing', vocab: 'Từ vựng TOEIC' };
document.getElementById('header-title').textContent = titles[id] || '';
if (id !== 'exam' && timerInterval) { clearInterval(timerInterval); timerInterval = null; }
}
// ---- Exam ----
function startExam(part, name) {
examPart = part || 2;
examPartName = name || 'Hỏi-đáp';
currentQ = 0;
answers = new Array(10).fill(null);
timeLeft = 600;
if (timerInterval) clearInterval(timerInterval);
renderExam();
navigate('exam');
startTimer();
}
function renderExam() {
const q = QUESTIONS[currentQ];
document.getElementById('q-label').textContent = 'Câu ' + (currentQ + 1);
document.getElementById('q-part-label').textContent = 'Part ' + examPart + ' — ' + examPartName;
document.getElementById('q-text').textContent = q.q;
document.getElementById('q-counter').textContent = (currentQ + 1) + ' / 10';
document.getElementById('mob-header').textContent = 'Part ' + examPart + ' — Câu ' + (currentQ + 1) + '/10';
document.getElementById('mob-progress').style.width = ((currentQ + 1) / 10 * 100) + '%';
document.getElementById('header-title').textContent = 'Part ' + examPart + ' — Câu ' + (currentQ + 1) + '/10';
const opts = document.getElementById('answer-options');
const labels = ['A', 'B', 'C', 'D'];
opts.innerHTML = q.opts.map((o, i) => {
const sel = answers[currentQ] === i;
return `<button class="answer-btn w-full flex items-center gap-3 p-4 border-2 rounded-xl text-sm font-medium text-left transition-all ${sel ? 'selected' : 'border-border hover:border-primary/30 hover:bg-primary-light'}" onclick="selectAnswer(${i})">
<span class="w-8 h-8 rounded-full flex items-center justify-center text-xs font-bold flex-shrink-0 ${sel ? 'bg-primary text-white' : 'bg-surface text-subtle'}">${labels[i]}</span>
${o}
</button>`;
}).join('');
// Dots
const dots = document.getElementById('q-dots');
dots.innerHTML = Array.from({length:10},(_,i) => {
let cls = 'q-dot';
if (i === currentQ) cls += ' current';
else if (answers[i] !== null) cls += ' answered';
return `<div class="${cls}" onclick="goToQ(${i})">${i+1}</div>`;
}).join('');
}
function selectAnswer(i) {
answers[currentQ] = i;
renderExam();
}
function goToQ(i) { currentQ = i; renderExam(); }
function prevQuestion() { if (currentQ > 0) { currentQ--; renderExam(); } }
function nextQuestion() { if (currentQ < 9) { currentQ++; renderExam(); } else { submitExam(); } }
function startTimer() {
updateTimerDisplay();
timerInterval = setInterval(() => {
timeLeft--;
updateTimerDisplay();
if (timeLeft <= 0) { clearInterval(timerInterval); submitExam(); }
}, 1000);
}
function updateTimerDisplay() {
const m = String(Math.floor(timeLeft/60)).padStart(2,'0');
const s = String(timeLeft%60).padStart(2,'0');
const t = m + ':' + s;
document.getElementById('timer').textContent = t;
document.getElementById('mob-timer').textContent = t;
if (timeLeft < 60) {
document.getElementById('timer').classList.add('urgent');
}
}
function submitExam() {
if (timerInterval) { clearInterval(timerInterval); timerInterval = null; }
renderResults();
navigate('results');
}
// ---- Results ----
function renderResults() {
const list = document.getElementById('review-list');
const labels = ['A','B','C','D'];
list.innerHTML = QUESTIONS.map((q, i) => {
const userAns = answers[i];
const correct = q.ans;
const isCorrect = userAns === correct;
const explanations = [
'Câu trả lời B cho thấy sự thận trọng trong xử lý tài liệu tài chính.',
'Dựa vào ngữ cảnh hội thoại, địa điểm được xác định là văn phòng.',
'Mục đích của cuộc gọi được thể hiện qua từ "confirm" trong câu đầu.',
'Từ "next" ở cuối cuộc hội thoại cho biết hành động tiếp theo.',
'Từ "delayed" được nhắc đến rõ ràng trong đoạn hội thoại.',
'Người phụ nữ đề xuất điều chỉnh thay vì chấp nhận hoàn toàn.',
'Thông báo này nhằm thay đổi lịch trình.',
'Người phụ nữ yêu cầu review hợp đồng trước khi ký.',
'Cụm từ "by the end of this week" xuất hiện trong hội thoại.',
'Chủ đề "marketing strategies" được đề cập ngay từ đầu cuộc họp.',
];
return `<div class="px-6 py-4 border-b border-border last:border-0">
<div class="flex items-start gap-3">
<div class="flex-shrink-0 w-7 h-7 rounded-full flex items-center justify-center text-xs font-bold ${isCorrect ? 'bg-success-light text-success' : 'bg-danger-light text-danger'}">${i+1}</div>
<div class="flex-1 min-w-0">
<p class="text-sm font-medium mb-2 leading-relaxed">${q.q}</p>
<div class="flex flex-wrap gap-2 mb-2">
${userAns !== null ? `<span class="text-xs px-2 py-0.5 rounded-full font-semibold ${isCorrect ? 'bg-success-light text-success' : 'bg-danger-light text-danger'}">Bạn chọn: ${labels[userAns]}</span>` : '<span class="text-xs px-2 py-0.5 rounded-full bg-surface text-muted font-semibold">Chưa trả lời</span>'}
${!isCorrect ? `<span class="text-xs px-2 py-0.5 rounded-full bg-success-light text-success font-semibold">Đáp án đúng: ${labels[correct]}</span>` : ''}
</div>
<p class="text-xs text-muted leading-relaxed">💡 ${explanations[i]}</p>
</div>
</div>
</div>`;
}).join('');
}
// ---- Writing ----
function updateCharCount(el) {
const count = el.value.length;
document.getElementById('char-count').textContent = count + ' / 1000 ký tự';
}
function toggleImproved() {
const c = document.getElementById('improved-content');
const icon = document.getElementById('improved-icon');
c.classList.toggle('open');
icon.textContent = c.classList.contains('open') ? 'expand_less' : 'expand_more';
}
function checkWriting() {
const btn = event.target.closest('button');
btn.innerHTML = '<span class="material-symbols-outlined animate-spin" style="font-size:18px;animation:spin 1s linear infinite">refresh</span> Đang chấm...';
btn.disabled = true;
setTimeout(() => {
btn.innerHTML = '<span class="material-symbols-outlined" style="font-size:18px">auto_awesome</span> Chấm bài ngay';
btn.disabled = false;
// feedback panel is always shown; add pulse effect
document.getElementById('feedback-panel').style.boxShadow = '0 0 0 3px rgba(37,99,235,0.2)';
setTimeout(() => { document.getElementById('feedback-panel').style.boxShadow = ''; }, 1000);
}, 1800);
}
// ---- Vocab ----
function initVocab() {
// Topic list
const topics = Object.keys(VOCAB);
document.getElementById('topic-list').innerHTML = topics.map(t => {
const count = VOCAB[t].length;
return `<div class="flex items-center justify-between px-4 py-2.5 mx-2 rounded-xl cursor-pointer transition-all ${t === vocabTopic ? 'bg-primary-light text-primary font-semibold' : 'text-subtle hover:bg-surface'}" onclick="selectTopic('${t}')">
<span class="text-sm">${t}</span>
<span class="text-xs ${t === vocabTopic ? 'text-primary' : 'text-muted'} font-medium">${count}</span>
</div>`;
}).join('');
// Mobile chips
const mobileTopics = document.querySelector('.vocab-topics-mobile');
if (mobileTopics) {
mobileTopics.innerHTML = topics.map(t => `
<button onclick="selectTopic('${t}')" class="flex-shrink-0 px-4 py-2 rounded-full text-xs font-bold border transition-all ${t === vocabTopic ? 'bg-primary text-white border-primary' : 'bg-white border-border text-subtle'}">${t}</button>
`).join('');
}
renderCard();
}
function selectTopic(t) {
vocabTopic = t;
vocabIndex = 0;
cardFlipped = false;
initVocab();
}
function renderCard() {
const cards = VOCAB[vocabTopic];
const card = cards[vocabIndex];
document.getElementById('card-inner').classList.remove('flipped');
cardFlipped = false;
document.getElementById('card-word').textContent = card.word;
document.getElementById('card-phonetic').textContent = card.ph;
document.getElementById('card-topic-badge').textContent = card.topic;
document.getElementById('card-meaning').textContent = card.vi;
document.getElementById('card-example').innerHTML = '"' + card.ex.replace(new RegExp(card.word, 'gi'), '<strong>$&</strong>') + '"';
document.getElementById('card-counter').textContent = (vocabIndex + 1) + ' / ' + cards.length;
}
function flipCard() {
cardFlipped = !cardFlipped;
document.getElementById('card-inner').classList.toggle('flipped', cardFlipped);
}
function nextCard() {
const cards = VOCAB[vocabTopic];
vocabIndex = (vocabIndex + 1) % cards.length;
renderCard();
}
function prevCard() {
const cards = VOCAB[vocabTopic];
vocabIndex = (vocabIndex - 1 + cards.length) % cards.length;
renderCard();
}
function markKnown() {
knownCount = Math.min(knownCount + 1, 120);
const pct = Math.round(knownCount / 120 * 100);
document.getElementById('vocab-progress-text').textContent = knownCount + ' / 120 từ đã thuộc';
document.getElementById('vocab-progress-pct').textContent = pct + '%';
document.getElementById('vocab-bar').style.width = pct + '%';
nextCard();
}
function markNeedReview() { nextCard(); }
// ---- CSS spin for loading ----
const style = document.createElement('style');
style.textContent = '@keyframes spin { to { transform: rotate(360deg); } } .animate-spin { display: inline-block; animation: spin 1s linear infinite; }';
document.head.appendChild(style);
// ---- Init ----
initVocab();
renderExam();
navigate('home');
</script>
</body>
</html>