cv-maker / index.html
abeea's picture
Update index.html
cd38686 verified
Raw
History Blame Contribute Delete
84.7 kB
<!DOCTYPE html>
<html lang="en"><head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>CV Maker Pro | Professional Resume Builder</title>
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&amp;family=Playfair+Display:wght@700&amp;family=Fira+Code:wght@400;500&amp;display=swap" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
<style>
:root {
--primary: #4f46e5;
--primary-dark: #4338ca;
--slate-50: #f8fafc;
--slate-100: #f1f5f9;
--slate-200: #e2e8f0;
--slate-300: #cbd5e1;
--slate-400: #94a3b8;
--slate-700: #334155;
--slate-800: #1e293b;
--slate-900: #0f172a;
}
body {
font-family: 'Inter', sans-serif;
background-color: var(--slate-100);
color: var(--slate-900);
overflow: hidden;
}
/* Custom Scrollbar */
::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--slate-300); border-radius: 10px; }
::-webkit-scrollbar-thumb:hover { background: var(--slate-400); }
.app-container {
display: grid;
grid-template-columns: 400px 1fr;
height: 100vh;
padding-bottom: 56px;
}
/* Sidebar */
.sidebar {
background: white;
border-right: 1px solid var(--slate-200);
display: flex;
flex-direction: column;
overflow: hidden;
z-index: 20;
}
.sidebar-content {
flex: 1;
overflow-y: auto;
padding: 20px;
}
/* Preview Panel */
.preview-panel {
background: var(--slate-200);
overflow: auto;
display: flex;
justify-content: center;
padding: 40px 20px;
position: relative;
scroll-behavior: smooth;
}
/* The Paper */
#cv-preview {
width: 210mm;
min-height: 297mm;
background: white;
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
transform-origin: top center;
transition: transform 0.2s ease;
}
/* Responsiveness Logic */
@media (max-width: 1023px) {
.app-container { grid-template-columns: 1fr; overflow-y: auto; height: auto; padding-bottom: 100px; }
.sidebar { height: auto; border-right: none; max-height: none; }
.preview-panel { min-height: 400px; padding: 20px 10px; overflow: hidden; }
/* Auto-scale CV to fit width on mobile */
#cv-preview {
transform: scale(calc((100vw - 40px) / 794)); /* 794px is approx 210mm */
margin-bottom: calc(-297mm + (297mm * (100vw - 40px) / 794) + 20px);
}
}
@media (min-width: 1024px) and (max-width: 1366px) {
.app-container { grid-template-columns: 350px 1fr; }
#cv-preview { transform: scale(0.65); margin-bottom: -100mm; }
}
@media (min-width: 1367px) and (max-width: 1599px) {
#cv-preview { transform: scale(0.8); margin-bottom: -60mm; }
}
@media (min-width: 1600px) {
#cv-preview { transform: scale(0.9); margin-bottom: -30mm; }
}
/* Form Styling */
.form-label {
display: block;
font-size: 0.75rem;
font-weight: 700;
color: var(--slate-700);
margin-bottom: 4px;
text-transform: uppercase;
letter-spacing: 0.025em;
}
.form-input {
width: 100%;
border: 1px solid var(--slate-200);
border-radius: 6px;
padding: 8px 10px;
font-size: 0.9rem;
transition: all 0.2s;
}
.form-input:focus {
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
outline: none;
}
/* Tabs Navigation */
.nav-tabs {
display: flex;
gap: 2px;
padding: 4px;
background: var(--slate-100);
border-radius: 10px;
margin-bottom: 20px;
overflow-x: auto;
-ms-overflow-style: none;
scrollbar-width: none;
}
.nav-tabs::-webkit-scrollbar { display: none; }
.nav-tab {
flex: 1;
min-width: 70px;
padding: 8px 4px;
font-size: 0.75rem;
font-weight: 600;
border-radius: 7px;
white-space: nowrap;
cursor: pointer;
transition: all 0.2s;
color: var(--slate-700);
text-align: center;
}
.nav-tab.active {
background: white;
color: var(--primary);
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
/* Themes Grid */
.theme-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
}
.theme-option {
border: 2px solid var(--slate-100);
border-radius: 8px;
padding: 6px;
cursor: pointer;
transition: all 0.2s;
text-align: center;
background: white;
}
.theme-option:hover { border-color: var(--slate-300); }
.theme-option.active { border-color: var(--primary); background: rgba(79, 70, 229, 0.05); }
.theme-preview-box { height: 40px; border-radius: 4px; margin-bottom: 6px; }
/* CV INTERNAL THEME STYLES (Scope to #cv-preview) */
.cv-text-xs { font-size: 10px; }
.cv-text-sm { font-size: 12px; }
.cv-text-base { font-size: 14px; }
.cv-text-lg { font-size: 18px; }
.cv-bold { font-weight: 700; }
/* Theme: Midnight Pro */
#cv-preview.theme-midnight { color: #fff; background: #0f172a; }
.theme-midnight .cv-sidebar { background: #1e293b; width: 30%; padding: 30px; height: 297mm; float: left; }
.theme-midnight .cv-main { width: 70%; padding: 40px; float: left; color: #f1f5f9; }
.theme-midnight .accent { color: #38bdf8; }
/* Theme: Autumn Gold */
#cv-preview.theme-autumn { background: #fffdf5; color: #1e293b; }
.theme-autumn .cv-header { background: #d97706; color: white; padding: 40px; }
.theme-autumn .cv-body { display: flex; padding: 40px; gap: 30px; }
.theme-autumn .cv-sidebar { width: 35%; }
.theme-autumn .cv-main { flex: 1; }
.theme-autumn .section-h { border-bottom: 2px solid #d97706; padding-bottom: 5px; margin-bottom: 15px; font-family: 'Playfair Display', serif; }
/* Theme: Skyline Blue */
#cv-preview.theme-skyline { background: white; border-top: 15px solid #0369a1; color: #1e293b; }
.theme-skyline .cv-header { padding: 40px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #e0e7ff; }
.theme-skyline .cv-body { display: flex; padding: 40px; gap: 40px; }
.theme-skyline .cv-left { width: 200px; }
.theme-skyline .cv-right { flex: 1; }
.theme-skyline .section-h { color: #0369a1; text-transform: uppercase; letter-spacing: 2px; font-weight: 800; font-size: 12px; }
/* Theme: Rose Quartz */
#cv-preview.theme-rose { background: #fff; color: #4c1d95; }
.theme-rose .cv-container { padding: 40px; }
.theme-rose .cv-header { text-align: center; margin-bottom: 30px; border: 4px double #ddd6fe; padding: 20px; }
.theme-rose .section-h { background: #f5f3ff; padding: 5px 15px; border-radius: 50px; margin-bottom: 15px; }
/* Theme: Emerald Class */
#cv-preview.theme-emerald { background: white; color: #1e293b; }
.theme-emerald .cv-top { height: 180px; background: #064e3b; padding: 40px; display: flex; align-items: center; color: white; gap: 30px; }
.theme-emerald .cv-body { display: grid; grid-template-columns: 2fr 1fr; padding: 40px; gap: 40px; }
.theme-emerald .section-h { color: #059669; font-weight: 800; border-left: 4px solid #059669; padding-left: 10px; }
/* Theme: Industrial Grey */
#cv-preview.theme-industrial { background: #e5e7eb; color: #1e293b; }
.theme-industrial .cv-inner { background: #f9fafb; margin: 40px; padding: 40px; border: 10px solid #374151; height: calc(297mm - 80px); }
.theme-industrial .section-h { background: #374151; color: white; padding: 4px 12px; width: fit-content; }
/* Theme: Royal Gold */
#cv-preview.theme-royal { background: #1a1a1a; color: #d4af37; font-family: 'Playfair Display', serif; }
.theme-royal .cv-inner { padding: 50px; border: 2px solid #d4af37; margin: 30px; height: calc(297mm - 60px); }
.theme-royal .section-h { border-bottom: 1px solid #d4af37; padding-bottom: 5px; text-transform: uppercase; font-size: 14px; letter-spacing: 3px; }
/* ===== THEME: Executive Blue ===== */
.theme-executive .cv-sidebar-col {
width: 260px; min-height: 1123px; background: #0f3460; color: white;
padding: 40px 24px; float: left;
}
.theme-executive .cv-main-col { margin-left: 260px; padding: 40px 32px; }
.theme-executive .cv-photo { width: 120px; height: 120px; border-radius: 50%; border: 4px solid rgba(255,255,255,0.3); object-fit: cover; display: block; margin: 0 auto 20px; }
.theme-executive .cv-photo-placeholder { width: 120px; height: 120px; border-radius: 50%; border: 4px solid rgba(255,255,255,0.3); background: rgba(255,255,255,0.1); display: flex; align-items: center; justify-content: center; font-size: 40px; margin: 0 auto 20px; }
.theme-executive .cv-name { font-size: 28px; font-weight: 700; color: #0f3460; margin-bottom: 4px; }
.theme-executive .cv-title { font-size: 14px; color: #e94560; font-weight: 600; margin-bottom: 24px; text-transform: uppercase; letter-spacing: 1px; }
.theme-executive .sidebar-section-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1.5px; color: rgba(255,255,255,0.5); margin: 20px 0 10px; border-bottom: 1px solid rgba(255,255,255,0.1); padding-bottom: 6px; }
.theme-executive .sidebar-item { font-size: 12px; color: rgba(255,255,255,0.9); margin-bottom: 8px; line-height: 1.5; }
.theme-executive .section-title { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: 1.5px; color: #0f3460; border-bottom: 2px solid #e94560; padding-bottom: 6px; margin: 24px 0 14px; }
.theme-executive .entry-title { font-size: 14px; font-weight: 700; color: #1a1a2e; }
.theme-executive .entry-sub { font-size: 12px; color: #e94560; font-weight: 600; margin: 2px 0; }
.theme-executive .entry-date { font-size: 11px; color: #888; margin-bottom: 4px; }
.theme-executive .entry-desc { font-size: 12px; color: #555; line-height: 1.6; }
.theme-executive .tag { display: inline-block; background: rgba(255,255,255,0.15); color: white; padding: 3px 10px; border-radius: 20px; font-size: 11px; margin: 2px; }
.theme-executive .contact-item { display: flex; align-items: center; gap: 8px; font-size: 11px; color: rgba(255,255,255,0.85); margin-bottom: 8px; word-break: break-all; }
/* ===== THEME: Modern Minimal ===== */
.theme-minimal { padding: 0; }
.theme-minimal .cv-top-bar { background: #1a1a1a; padding: 40px; color: white; display: flex; align-items: center; gap: 30px; }
.theme-minimal .cv-photo-wrap img { width: 90px; height: 90px; border-radius: 50%; object-fit: cover; border: 3px solid #f5a623; }
.theme-minimal .cv-photo-wrap .ph { width: 90px; height: 90px; border-radius: 50%; background: #333; display: flex; align-items: center; justify-content: center; font-size: 36px; border: 3px solid #f5a623; }
.theme-minimal .cv-name { font-size: 30px; font-weight: 800; color: white; letter-spacing: -1px; }
.theme-minimal .cv-title { font-size: 13px; color: #f5a623; text-transform: uppercase; letter-spacing: 2px; margin-top: 4px; }
.theme-minimal .cv-body { display: flex; padding: 0; }
.theme-minimal .cv-left { width: 240px; flex-shrink: 0; background: #f8f8f8; padding: 30px 24px; border-right: 1px solid #eee; }
.theme-minimal .cv-right { flex: 1; padding: 30px 32px; }
.theme-minimal .section-title { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 2px; color: #1a1a1a; margin: 20px 0 12px; }
.theme-minimal .left-label { font-size: 10px; font-weight: 700; color: #888; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 2px; }
.theme-minimal .left-value { font-size: 12px; color: #333; margin-bottom: 10px; word-break: break-all; }
.theme-minimal .skill-pill { display: inline-block; background: #1a1a1a; color: white; padding: 4px 12px; border-radius: 20px; font-size: 11px; margin: 2px; }
.theme-minimal .entry-card { border-left: 3px solid #f5a623; padding-left: 14px; margin-bottom: 18px; }
.theme-minimal .entry-title { font-size: 14px; font-weight: 700; color: #1a1a1a; }
.theme-minimal .entry-sub { font-size: 12px; color: #f5a623; font-weight: 600; }
.theme-minimal .entry-date { font-size: 11px; color: #999; margin: 2px 0; }
.theme-minimal .entry-desc { font-size: 12px; color: #666; line-height: 1.6; margin-top: 4px; }
/* ===== THEME: Creative Coral ===== */
.theme-coral { padding: 0; }
.theme-coral .cv-header { background: linear-gradient(135deg, #e94560 0%, #f5a623 100%); padding: 40px; display: flex; gap: 24px; align-items: center; }
.theme-coral .cv-photo img { width: 100px; height: 100px; border-radius: 16px; object-fit: cover; border: 3px solid rgba(255,255,255,0.6); }
.theme-coral .cv-photo .ph { width: 100px; height: 100px; border-radius: 16px; background: rgba(255,255,255,0.2); display: flex; align-items: center; justify-content: center; font-size: 40px; border: 3px solid rgba(255,255,255,0.6); }
.theme-coral .cv-name { font-size: 32px; font-weight: 800; color: white; letter-spacing: -1px; }
.theme-coral .cv-title { font-size: 13px; color: rgba(255,255,255,0.85); margin-top: 4px; letter-spacing: 1px; }
.theme-coral .contact-row { display: flex; gap: 20px; margin-top: 12px; flex-wrap: wrap; }
.theme-coral .contact-chip { font-size: 11px; color: rgba(255,255,255,0.9); background: rgba(255,255,255,0.2); padding: 4px 12px; border-radius: 20px; }
.theme-coral .cv-body { display: flex; }
.theme-coral .cv-left { width: 230px; flex-shrink: 0; padding: 28px 22px; background: #fff8f6; border-right: 1px solid #fde2d8; }
.theme-coral .cv-right { flex: 1; padding: 28px 30px; }
.theme-coral .section-title { font-size: 13px; font-weight: 800; color: #e94560; text-transform: uppercase; letter-spacing: 1px; margin: 20px 0 10px; }
.theme-coral .skill-tag { display: inline-block; background: white; border: 1.5px solid #e94560; color: #e94560; padding: 3px 10px; border-radius: 20px; font-size: 11px; margin: 2px; }
.theme-coral .entry-title { font-size: 14px; font-weight: 700; color: #1a1a1a; }
.theme-coral .entry-sub { font-size: 12px; color: #e94560; font-weight: 600; margin: 2px 0; }
.theme-coral .entry-date { font-size: 11px; color: #999; margin-bottom: 4px; }
.theme-coral .entry-desc { font-size: 12px; color: #666; line-height: 1.6; }
.theme-coral .entry-wrap { margin-bottom: 14px; }
/* ===== Additional Index.html Themes ===== */
.theme-forest .cv-sidebar-col, .theme-clean .cv-sidebar-col { width: 230px; min-height: 1123px; background: #1b4332; color: white; padding: 36px 22px; float: left; }
.theme-forest .cv-main-col, .theme-clean .cv-main-col { margin-left: 230px; padding: 36px 30px; }
.theme-forest .entry-title, .theme-clean .entry-title { font-size: 14px; font-weight: 700; color: #1b4332; }
.theme-forest .entry-sub, .theme-clean .entry-sub { font-size: 12px; color: #40916c; font-weight: 600; margin: 2px 0; }
.theme-forest .entry-date, .theme-clean .entry-date { font-size: 11px; color: #999; margin-bottom: 4px; }
.theme-forest .entry-desc, .theme-clean .entry-desc { font-size: 12px; color: #555; line-height: 1.6; }
.theme-portfolio .cv-top, .theme-slate .cv-header, .theme-ocean .cv-header { padding: 40px; display: flex; align-items: center; gap: 28px; }
.theme-portfolio .cv-body, .theme-slate .cv-body, .theme-ocean .cv-body { display: flex; padding: 40px; }
.theme-modern .cv-header, .theme-tech .cv-header, .theme-elegant .cv-header { background: linear-gradient(135deg, #111827, #6366f1); padding: 40px; color: white; }
.clearfix::after { content: ""; clear: both; display: table; }
/* Footer */
.footer-fixed {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 56px;
background: white;
border-top: 1px solid var(--slate-200);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
z-index: 50;
}
@media (max-width: 640px) {
.footer-fixed { flex-direction: column; height: auto; padding: 12px; gap: 8px; text-align: center; }
.footer-fixed > div { width: 100%; justify-content: center; }
}
/* Responsive upgrades */
@media (max-width: 900px) {
body { overflow:auto; }
.app-container { grid-template-columns:1fr; height:auto; min-height:100vh; padding-bottom:70px; }
.sidebar { height:auto; max-height:none; }
.preview-panel { min-height:100vh; padding:15px; overflow:auto; }
#cv-preview { transform:none !important; width:100% !important; min-height:auto !important; }
.theme-grid { grid-template-columns:repeat(3,1fr); }
}
@media (max-width:520px) {
.sidebar-content { padding:12px; }
.theme-grid { grid-template-columns:repeat(2,1fr); }
.preview-panel { padding:8px; }
}
</style>
</head>
<body>
<div class="app-container">
<!-- SIDEBAR -->
<aside class="sidebar">
<div class="p-4 border-b border-slate-100 flex items-center justify-between bg-white sticky top-0 z-10">
<div class="flex items-center gap-2">
<span class="material-symbols-outlined text-indigo-600 text-2xl">description</span>
<h1 class="text-lg font-bold tracking-tight text-slate-800">CV Maker Pro</h1>
</div>
<button class="bg-indigo-600 hover:bg-indigo-700 text-white px-3 py-1.5 rounded-lg text-xs font-bold flex items-center gap-1.5 transition-all shadow-lg shadow-indigo-100 active:scale-95" onclick="downloadPDF()">
<span class="material-symbols-outlined text-sm">download</span> Export
</button>
</div>
<div class="sidebar-content">
<nav class="nav-tabs" id="main-tabs">
<div class="nav-tab active" data-tab="personal">Personal</div>
<div class="nav-tab" data-tab="education">Education</div>
<div class="nav-tab" data-tab="experience">Work</div>
<div class="nav-tab" data-tab="skills">Skills</div>
<div class="nav-tab" data-tab="themes">Themes</div>
</nav>
<!-- PANELS -->
<div class="tab-panel" id="panel-personal">
<div class="mb-5">
<label class="form-label">Profile Picture</label>
<div class="border-2 border-dashed border-slate-200 rounded-lg p-4 text-center cursor-pointer hover:border-indigo-400 hover:bg-indigo-50 transition-all group" onclick="document.getElementById('photo-input').click()">
<input accept="image/*" class="hidden" id="photo-input" onchange="handlePhoto(event)" type="file"/>
<div id="photo-drop-zone">
<span class="material-symbols-outlined text-slate-400 text-3xl group-hover:text-indigo-500 transition-colors">add_a_photo</span>
<p class="text-[10px] text-slate-500 font-medium mt-1 uppercase tracking-wider">Click to upload</p>
</div>
</div>
</div>
<div class="space-y-4">
<div class="form-group">
<label class="form-label">Full Name</label>
<input class="form-input" id="f-name" oninput="updateCV()" placeholder="Muhammad Abdullah" type="text"/>
</div>
<div class="form-group">
<label class="form-label">Professional Title</label>
<input class="form-input" id="f-title" oninput="updateCV()" placeholder="Web Developer &amp; Content Creator" type="text"/>
</div>
<div class="form-group">
<label class="form-label">Bio / Summary</label>
<textarea class="form-input" id="f-summary" oninput="updateCV()" placeholder="Brief professional summary..." rows="4"></textarea>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div class="form-group">
<label class="form-label">Email</label>
<input class="form-input" id="f-email" oninput="updateCV()" placeholder="your@email.com" type="email"/>
</div>
<div class="form-group">
<label class="form-label">Phone</label>
<input class="form-input" id="f-phone" oninput="updateCV()" placeholder="+92 342 4844392" type="text"/>
</div>
</div>
<div class="form-group">
<label class="form-label">Location</label>
<input class="form-input" id="f-location" oninput="updateCV()" placeholder="Lahore, Pakistan" type="text"/>
</div>
<div class="form-group">
<label class="form-label">Website / Portfolio</label>
<input class="form-input" id="f-website" oninput="updateCV()" placeholder="www.portfolio.com" type="text"/>
</div>
</div>
</div>
<div class="tab-panel hidden" id="panel-education">
<div class="space-y-4" id="education-list"></div>
<button class="w-full mt-4 py-3 border-2 border-dashed border-slate-200 rounded-xl text-slate-500 text-sm font-bold hover:bg-slate-50 hover:border-slate-300 transition-all flex items-center justify-center gap-2" onclick="addEntry('education')">
<span class="material-symbols-outlined text-base">add</span> Add Education
</button>
</div>
<div class="tab-panel hidden" id="panel-experience">
<div class="space-y-4" id="experience-list"></div>
<button class="w-full mt-4 py-3 border-2 border-dashed border-slate-200 rounded-xl text-slate-500 text-sm font-bold hover:bg-slate-50 hover:border-slate-300 transition-all flex items-center justify-center gap-2" onclick="addEntry('experience')">
<span class="material-symbols-outlined text-base">add</span> Add Experience
</button>
</div>
<div class="tab-panel hidden" id="panel-skills">
<div class="space-y-4">
<div class="form-group">
<label class="form-label">Technical Skills (Comma separated)</label>
<textarea class="form-input" id="f-skills" oninput="updateCV()" placeholder="JavaScript, Python, React..." rows="3"></textarea>
</div>
<div class="form-group">
<label class="form-label">Languages</label>
<input class="form-input" id="f-languages" oninput="updateCV()" placeholder="English, Urdu, German" type="text"/>
</div>
<div class="form-group">
<label class="form-label">Certifications (One per line)</label>
<textarea class="form-input" id="f-diplomas" oninput="updateCV()" placeholder="AWS Certified Architect..." rows="3"></textarea>
</div>
</div>
</div>
<div class="tab-panel hidden" id="panel-themes">
<div class="theme-grid"><div class="theme-option active" data-theme="midnight" onclick="setTheme('midnight')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(0,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Midnight</span>
</div><div class="theme-option " data-theme="autumn" onclick="setTheme('autumn')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(18,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Autumn</span>
</div><div class="theme-option " data-theme="skyline" onclick="setTheme('skyline')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(36,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Skyline</span>
</div><div class="theme-option " data-theme="rose" onclick="setTheme('rose')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(54,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Rose</span>
</div><div class="theme-option " data-theme="emerald" onclick="setTheme('emerald')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(72,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Emerald</span>
</div><div class="theme-option " data-theme="industrial" onclick="setTheme('industrial')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(144,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Industrial</span>
</div><div class="theme-option " data-theme="royal" onclick="setTheme('royal')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(162,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Royal</span>
</div><div class="theme-option " data-theme="minimal" onclick="setTheme('minimal')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(180,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Minimal</span>
</div><div class="theme-option " data-theme="executive" onclick="setTheme('executive')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(216,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Executive</span>
</div><div class="theme-option " data-theme="modern" onclick="setTheme('modern')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(234,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Modern</span>
</div><div class="theme-option " data-theme="classic" onclick="setTheme('classic')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(252,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Classic</span>
</div><div class="theme-option " data-theme="tech" onclick="setTheme('tech')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(270,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Tech</span>
</div><div class="theme-option " data-theme="elegant" onclick="setTheme('elegant')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(288,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Elegant</span>
</div><div class="theme-option " data-theme="bold" onclick="setTheme('bold')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(306,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Bold</span>
</div><div class="theme-option " data-theme="clean" onclick="setTheme('clean')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(324,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Clean</span>
</div><div class="theme-option " data-theme="portfolio" onclick="setTheme('portfolio')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,hsl(342,70%,45%),#fff)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Portfolio</span>
</div><div class="theme-option " data-theme="coral" onclick="setTheme('coral')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,#e94560,#f5a623)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Coral</span>
</div><div class="theme-option " data-theme="forest" onclick="setTheme('forest')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,#1b4332,#40916c)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Forest</span>
</div><div class="theme-option " data-theme="purple" onclick="setTheme('purple')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,#4a0e8f,#9b59b6)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Purple</span>
</div><div class="theme-option " data-theme="slate" onclick="setTheme('slate')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,#2d3748,#718096)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Slate</span>
</div><div class="theme-option " data-theme="ocean" onclick="setTheme('ocean')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,#006BA6,#0496FF)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Ocean</span>
</div><div class="theme-option " data-theme="sunsetorange" onclick="setTheme('sunsetorange')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,#FF6B35,#F7931E)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Sunset Org</span>
</div><div class="theme-option " data-theme="mint" onclick="setTheme('mint')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,#00D9C0,#00B4A0)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Mint</span>
</div><div class="theme-option " data-theme="rosegold" onclick="setTheme('rosegold')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,#C9A9A6,#E8B4B8)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Rose Gold</span>
</div><div class="theme-option " data-theme="dark" onclick="setTheme('dark')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,#000,#FFD700)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Dark Night</span>
</div><div class="theme-option " data-theme="crimson" onclick="setTheme('crimson')">
<div class="theme-preview-box" style="background:linear-gradient(135deg,#8B0000,#DC143C)"></div>
<span class="text-[10px] font-bold uppercase tracking-wide">Crimson</span>
</div></div>
</div>
</div>
</aside>
<!-- PREVIEW AREA -->
<main class="preview-panel">
<div id="cv-preview">
<!-- Generated content goes here -->
</div>
</main>
</div>
<!-- FIXED FOOTER -->
<footer class="footer-fixed">
<div class="flex items-center gap-2 text-[11px] text-slate-500 font-bold uppercase tracking-widest">
<span class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></span> Live Sync
</div>
<div class="text-[11px] font-semibold text-slate-400">
Built with <span class="text-rose-500">โ™ฅ</span> by <a class="text-slate-800 hover:text-indigo-600 transition-colors" href="https://famstagency.com/about-developer.html" target="_blank">Abdullah Tarar</a>
</div>
<div class="flex items-center gap-3">
<button class="text-slate-400 hover:text-slate-800 transition-colors" onclick="zoom('out')"><span class="material-symbols-outlined text-lg">zoom_out</span></button>
<div class="h-4 w-[1px] bg-slate-200"></div>
<button class="text-slate-400 hover:text-slate-800 transition-colors" onclick="zoom('in')"><span class="material-symbols-outlined text-lg">zoom_in</span></button>
</div>
</footer>
<script>
let currentTheme = 'midnight';
let photoDataURL = null;
let eduEntries = [];
let expEntries = [];
let currentScale = 0.9;
// Adjust initial scale based on screen width
if (window.innerWidth < 1024) {
currentScale = (window.innerWidth - 40) / 794;
} else if (window.innerWidth < 1440) {
currentScale = 0.7;
}
function zoom(dir) {
if (dir === 'in') currentScale += 0.05;
else currentScale -= 0.05;
const cv = document.getElementById('cv-preview');
cv.style.transform = `scale(${currentScale})`;
// Update margin to fix layout gap after scaling
const heightCorrection = (297 * 3.78) * (1 - currentScale); // mm to px approx
cv.style.marginBottom = `-${heightCorrection}px`;
}
// App initialization
function init() {
document.getElementById('f-name').value = "Muhammad Abdullah";
document.getElementById('f-title').value = "Content Creator & Web Developer";
document.getElementById('f-summary').value = "Passionate digital professional with expertise in ethical hacking, content creation, and web development. Experienced in managing content strategy and delivering freelance projects across diverse industries.";
document.getElementById('f-phone').value = "+92 342 4844392";
document.getElementById('f-email').value = "muhammadabdullahtarar392@gmail.com";
document.getElementById('f-location').value = "Lahore, Pakistan";
document.getElementById('f-website').value = "libsi.pk";
document.getElementById('f-skills').value = "Ethical Hacking, Photoshop, Web Development, SEO, WordPress, Social Media";
document.getElementById('f-languages').value = "Urdu (Native), English (Professional)";
document.getElementById('f-diplomas').value = "Diploma in Ethical Hacking\nPhotoshop Course Certificate";
addEntry('education', { degree: 'Intermediate (F.Sc)', institution: 'BISE Lahore', year: '2020-2022' });
addEntry('experience', { role: 'Content Head', company: 'Libsi.pk', period: '2022-Present', desc: 'Led content strategy and team of 5 writers.' });
updateCV();
setupTabs();
}
function setupTabs() {
const tabs = document.querySelectorAll('.nav-tab');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
tabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active');
const targetPanel = tab.getAttribute('data-tab');
document.querySelectorAll('.tab-panel').forEach(panel => {
panel.classList.add('hidden');
});
document.getElementById('panel-' + targetPanel).classList.remove('hidden');
// On mobile, scroll to top of sidebar content when tab changes
if (window.innerWidth < 1024) {
document.querySelector('.sidebar-content').scrollTop = 0;
}
});
});
}
function setTheme(theme) {
currentTheme = theme;
document.querySelectorAll('.theme-option').forEach(opt => {
opt.classList.toggle('active', opt.getAttribute('data-theme') === theme);
});
updateCV();
}
function handlePhoto(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (ev) => {
photoDataURL = ev.target.result;
document.getElementById('photo-drop-zone').innerHTML = `
<img src="${photoDataURL}" class="w-14 h-14 rounded-full mx-auto object-cover border-2 border-indigo-500 shadow-md">
<p class="text-[10px] text-indigo-500 font-bold mt-1 uppercase">Change</p>
`;
updateCV();
};
reader.readAsDataURL(file);
}
function addEntry(type, data = {}) {
const listId = type + '-list';
const id = Date.now() + Math.random().toString(36).substr(2, 9);
const entry = { id, ...data };
if (type === 'education') eduEntries.push(entry);
else expEntries.push(entry);
const entryEl = document.createElement('div');
entryEl.id = 'entry-' + id;
entryEl.className = 'p-3 bg-slate-50 rounded-lg border border-slate-200 relative group';
const fields = type === 'education' ?
`<div class="space-y-2">
<input type="text" placeholder="Degree" class="form-input text-xs" value="${data.degree || ''}" oninput="updateEntry('${type}','${id}','degree',this.value)">
<input type="text" placeholder="Institution" class="form-input text-xs" value="${data.institution || ''}" oninput="updateEntry('${type}','${id}','institution',this.value)">
<input type="text" placeholder="Year Range" class="form-input text-xs" value="${data.year || ''}" oninput="updateEntry('${type}','${id}','year',this.value)">
</div>` :
`<div class="space-y-2">
<input type="text" placeholder="Job Title" class="form-input text-xs" value="${data.role || ''}" oninput="updateEntry('${type}','${id}','role',this.value)">
<input type="text" placeholder="Company" class="form-input text-xs" value="${data.company || ''}" oninput="updateEntry('${type}','${id}','company',this.value)">
<input type="text" placeholder="Period" class="form-input text-xs" value="${data.period || ''}" oninput="updateEntry('${type}','${id}','period',this.value)">
<textarea placeholder="Description" class="form-input text-xs" oninput="updateEntry('${type}','${id}','desc',this.value)">${data.desc || ''}</textarea>
</div>`;
entryEl.innerHTML = `
<button onclick="removeEntry('${type}','${id}')" class="absolute -top-2 -right-2 bg-rose-500 text-white p-1 rounded-full opacity-0 group-hover:opacity-100 transition-opacity z-10 shadow-sm">
<span class="material-symbols-outlined text-[14px]">close</span>
</button>
${fields}
`;
document.getElementById(listId).appendChild(entryEl);
updateCV();
}
function updateEntry(type, id, field, value) {
const list = type === 'education' ? eduEntries : expEntries;
const item = list.find(e => e.id === id);
if (item) {
item[field] = value;
updateCV();
}
}
function removeEntry(type, id) {
if (type === 'education') eduEntries = eduEntries.filter(e => e.id !== id);
else expEntries = expEntries.filter(e => e.id !== id);
document.getElementById('entry-' + id).remove();
updateCV();
}
function updateCV() {
const data = {
name: document.getElementById('f-name').value || 'John Doe',
title: document.getElementById('f-title').value || 'Professional Role',
summary: document.getElementById('f-summary').value,
email: document.getElementById('f-email').value,
phone: document.getElementById('f-phone').value,
location: document.getElementById('f-location').value,
website: document.getElementById('f-website').value,
skills: document.getElementById('f-skills').value.split(',').filter(s => s.trim()),
langs: document.getElementById('f-languages').value.split(',').filter(l => l.trim()),
certs: document.getElementById('f-diplomas').value.split('\n').filter(c => c.trim()),
edu: eduEntries,
exp: expEntries,
photo: photoDataURL
};
const preview = document.getElementById('cv-preview');
preview.className = 'theme-' + currentTheme;
preview.innerHTML = generateThemeHTML(data);
}
function generateThemeHTML(d) {
const profileImg = d.photo ? `<img src="${d.photo}" style="width:100px; height:100px; object-fit:cover; border-radius:50%; border:3px solid rgba(255,255,255,0.2);">` : `<div style="width:100px;height:100px;background:rgba(255,255,255,0.1);border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:40px;">๐Ÿ‘ค</div>`;
const skillList = d.skills.map(s => `<span style="display:inline-block; margin-right:8px; margin-bottom:8px; padding:2px 10px; background:rgba(128,128,128,0.1); border-radius:4px; font-size:10px;">${s.trim()}</span>`).join('');
const eduList = d.edu.map(e => `<div style="margin-bottom:15px;"><div class="cv-bold cv-text-base">${e.degree}</div><div class="cv-text-sm">${e.institution} | ${e.year}</div></div>`).join('');
const expList = d.exp.map(e => `<div style="margin-bottom:20px;"><div class="cv-bold cv-text-base">${e.role}</div><div class="accent cv-bold cv-text-sm">${e.company} | ${e.period}</div><div class="cv-text-sm" style="margin-top:5px; opacity:0.8;">${e.desc}</div></div>`).join('');
switch(currentTheme) {
case 'midnight':
return `
<div class="cv-sidebar clearfix">
<div style="text-align:center; margin-bottom:30px;">${profileImg}</div>
<div class="cv-bold cv-text-sm accent" style="margin-bottom:10px;">CONTACT</div>
<div class="cv-text-xs" style="margin-bottom:20px;"><div>${d.email}</div><div>${d.phone}</div><div>${d.location}</div><div>${d.website}</div></div>
<div class="cv-bold cv-text-sm accent" style="margin-bottom:10px;">SKILLS</div>
<div style="margin-bottom:20px;">${skillList}</div>
<div class="cv-bold cv-text-sm accent" style="margin-bottom:10px;">LANGUAGES</div>
<div class="cv-text-xs">${d.langs.join(', ')}</div>
</div>
<div class="cv-main">
<div class="cv-bold cv-text-lg" style="font-size:32px;">${d.name.toUpperCase()}</div>
<div class="accent cv-bold" style="letter-spacing:2px; margin-bottom:30px;">${d.title.toUpperCase()}</div>
<div style="margin-bottom:30px;" class="cv-text-sm">${d.summary}</div>
<div class="cv-bold cv-text-sm accent" style="margin-bottom:15px; border-bottom:1px solid #334155; padding-bottom:5px;">EXPERIENCE</div>
${expList}
<div class="cv-bold cv-text-sm accent" style="margin-bottom:15px; border-bottom:1px solid #334155; padding-bottom:5px; margin-top:30px;">EDUCATION</div>
${eduList}
</div>
`;
case 'autumn':
return `
<div class="cv-header">
<div style="font-size:36px; font-weight:700; font-family:'Playfair Display';">${d.name}</div>
<div style="font-size:16px; opacity:0.9;">${d.title}</div>
</div>
<div class="cv-body">
<div class="cv-sidebar">
<div class="section-h">Contact</div>
<div class="cv-text-sm">${d.email}<br>${d.phone}<br>${d.location}</div>
<div class="section-h" style="margin-top:30px;">Skills</div>
<div class="cv-text-sm">${d.skills.join(' โ€ข ')}</div>
</div>
<div class="cv-main">
<div class="section-h">Profile</div>
<div class="cv-text-sm" style="margin-bottom:30px;">${d.summary}</div>
<div class="section-h">Experience</div>
${expList}
<div class="section-h" style="margin-top:30px;">Education</div>
${eduList}
</div>
</div>
`;
case 'skyline':
return `
<div class="cv-header">
<div><div style="font-size:28px; font-weight:900;">${d.name.toUpperCase()}</div><div class="accent" style="font-weight:700;">${d.title}</div></div>
<div class="cv-text-xs" style="text-align:right;">${d.email}<br>${d.phone}<br>${d.location}</div>
</div>
<div class="cv-body">
<div class="cv-left">
<div class="section-h">Skills</div>
<div style="margin:10px 0 30px;">${d.skills.join(', ')}</div>
<div class="section-h">Languages</div>
<div style="margin:10px 0;">${d.langs.join(', ')}</div>
</div>
<div class="cv-right">
<div class="section-h">About Me</div>
<div class="cv-text-sm" style="margin:10px 0 30px;">${d.summary}</div>
<div class="section-h">History</div>
<div style="margin-top:15px;">${expList}</div>
</div>
</div>
`;
case 'rose':
return `
<div class="cv-container">
<div class="cv-header">
<div style="font-size:32px; font-weight:800;">${d.name}</div>
<div style="color:#7c3aed; font-weight:600;">${d.title}</div>
<div class="cv-text-xs" style="margin-top:10px;">${d.email} โ€ข ${d.phone} โ€ข ${d.location}</div>
</div>
<div class="section-h cv-bold cv-text-sm">ABOUT</div>
<div class="cv-text-sm" style="margin-bottom:25px;">${d.summary}</div>
<div class="section-h cv-bold cv-text-sm">EXPERIENCE</div>
${expList}
</div>
`;
case 'emerald':
return `
<div class="cv-top">
${profileImg}
<div><div style="font-size:32px; font-weight:800;">${d.name}</div><div style="font-size:14px; opacity:0.8;">${d.title}</div></div>
</div>
<div class="cv-body">
<div class="cv-main">
<div class="section-h cv-text-sm">PROFILE</div>
<div class="cv-text-sm" style="margin:15px 0 30px;">${d.summary}</div>
<div class="section-h cv-text-sm">EXPERIENCE</div>
${expList}
</div>
<div class="cv-sidebar">
<div class="section-h cv-text-sm">CONTACT</div>
<div class="cv-text-xs" style="margin:15px 0 30px;">${d.email}<br>${d.phone}</div>
<div class="section-h cv-text-sm">SKILLS</div>
<div style="margin:15px 0;">${skillList}</div>
</div>
</div>
`;
case 'industrial':
return `<div class="cv-inner"><div style="display:flex; justify-content:space-between; margin-bottom:40px;"><div><div style="font-size:32px; font-weight:900;">${d.name.toUpperCase()}</div><div style="font-weight:700;">${d.title}</div></div><div class="cv-text-xs">${d.email}</div></div><div class="section-h">SUMMARY</div><div class="cv-text-sm" style="margin:10px 0 30px;">${d.summary}</div><div class="section-h">EXPERIENCE</div>${expList}</div>`;
case 'royal':
return `<div class="cv-inner"><div style="text-align:center; margin-bottom:40px;"><div style="font-size:38px; font-weight:700;">${d.name}</div><div style="font-size:14px; letter-spacing:4px;">${d.title.toUpperCase()}</div></div><div class="section-h">Profile</div><div class="cv-text-sm" style="margin:15px 0 35px; text-align:center;">${d.summary}</div><div class="section-h">Experience</div>${expList}</div>`;
case 'executive':
const execSkillTags = d.skills.filter(s=>s.trim()).map(s => `<span class="tag">${s.trim()}</span>`).join('');
const execEdu = d.edu.map(e => `<div style="margin-bottom:12px;"><div class="sidebar-item"><strong>${e.degree||''}</strong>${e.institution||''}</div><div style="font-size:11px;color:rgba(255,255,255,0.5);margin-top:2px;">${e.year||''}</div></div>`).join('');
const execExp = d.exp.map(e => `<div class="entry-wrap" style="margin-bottom:16px;"><div class="entry-title">${e.role||''}</div><div class="entry-sub">${e.company||''}</div><div class="entry-date">${e.period||''}</div><div class="entry-desc">${e.desc||''}</div></div>`).join('');
const execCerts = d.certs.map(c => `<div class="sidebar-item">โœฆ ${c}</div>`).join('');
return `
<div class="theme-executive clearfix">
<div class="cv-sidebar-col">
${d.photo ? `<img src="${d.photo}" class="cv-photo" alt="Profile">` : `<div class="cv-photo-placeholder">๐Ÿ‘ค</div>`}
<div style="text-align:center;color:white;font-size:16px;font-weight:700;margin-bottom:2px;">${d.name}</div>
<div style="text-align:center;color:#f5a623;font-size:11px;letter-spacing:1px;margin-bottom:20px;">${d.title}</div>
<div class="sidebar-section-title">Contact</div>
${d.phone?`<div class="contact-item">๐Ÿ“ž ${d.phone}</div>`:''}
${d.email?`<div class="contact-item">โœ‰ ${d.email}</div>`:''}
${d.location?`<div class="contact-item">๐Ÿ“ ${d.location}</div>`:''}
${d.website?`<div class="contact-item">๐ŸŒ ${d.website}</div>`:''}
${d.skills.length?`<div class="sidebar-section-title">Skills</div><div>${execSkillTags}</div>`:''}
${d.langs.length?`<div class="sidebar-section-title">Languages</div>${d.langs.filter(l=>l.trim()).map(l=>`<div class="sidebar-item">โ€ข ${l.trim()}</div>`).join('')}`:''}
${d.certs.length?`<div class="sidebar-section-title">Certifications</div>${execCerts}`:''}
</div>
<div class="cv-main-col">
<div class="cv-name">${d.name}</div>
<div class="cv-title">${d.title}</div>
${d.summary?`<div class="section-title">Profile</div><div class="entry-desc">${d.summary}</div>`:''}
${execExp?`<div class="section-title">Experience</div>${execExp}`:''}
${execEdu?`<div class="section-title">Education</div>${execEdu}`:''}
</div>
</div>`;
case 'minimal':
const minSkillPills = d.skills.filter(s=>s.trim()).map(s=>`<span class="skill-pill">${s.trim()}</span>`).join('');
const minEdu = d.edu.map(e=>`<div class="entry-card"><div class="entry-title">${e.degree||''}</div><div class="entry-sub">${e.institution||''}</div><div class="entry-date">${e.year||''}</div></div>`).join('');
const minExp = d.exp.map(e=>`<div class="entry-card"><div class="entry-title">${e.role||''}</div><div class="entry-sub">${e.company||''}</div><div class="entry-date">${e.period||''}</div><div class="entry-desc">${e.desc||''}</div></div>`).join('');
return `
<div class="theme-minimal">
<div class="cv-top-bar">
<div class="cv-photo-wrap">${d.photo?`<img src="${d.photo}" alt="Profile">`:`<div class="ph">๐Ÿ‘ค</div>`}</div>
<div><div class="cv-name">${d.name}</div><div class="cv-title">${d.title}</div></div>
</div>
<div class="cv-body">
<div class="cv-left">
<div class="section-title">Contact</div>
${d.phone?`<div class="left-label">Phone</div><div class="left-value">${d.phone}</div>`:''}
${d.email?`<div class="left-label">Email</div><div class="left-value">${d.email}</div>`:''}
${d.location?`<div class="left-label">Location</div><div class="left-value">${d.location}</div>`:''}
${d.skills.length?`<div class="section-title" style="margin-top:20px;">Skills</div><div>${minSkillPills}</div>`:''}
</div>
<div class="cv-right">
${d.summary?`<div class="section-title">About</div><p class="entry-desc" style="margin-bottom:16px;">${d.summary}</p>`:''}
${minExp?`<div class="section-title">Experience</div>${minExp}`:''}
${minEdu?`<div class="section-title">Education</div>${minEdu}`:''}
</div>
</div>
</div>`;
case 'coral':
const coralSkillTags = d.skills.filter(s=>s.trim()).map(s=>`<span class="skill-tag">${s.trim()}</span>`).join('');
const coralEdu = d.edu.map(e=>`<div class="entry-wrap"><div class="entry-title">${e.degree||''}</div><div class="entry-sub">${e.institution||''}</div><div class="entry-date">${e.year||''}</div></div>`).join('');
const coralExp = d.exp.map(e=>`<div class="entry-wrap"><div class="entry-title">${e.role||''}</div><div class="entry-sub">${e.company||''}</div><div class="entry-date">${e.period||''}</div><div class="entry-desc">${e.desc||''}</div></div>`).join('');
return `
<div class="theme-coral">
<div class="cv-header">
<div class="cv-photo">${d.photo?`<img src="${d.photo}" alt="Profile">`:`<div class="ph">๐Ÿ‘ค</div>`}</div>
<div>
<div class="cv-name">${d.name}</div>
<div class="cv-title">${d.title}</div>
<div class="contact-row">
${d.phone?`<span class="contact-chip">๐Ÿ“ž ${d.phone}</span>`:''}
${d.email?`<span class="contact-chip">โœ‰ ${d.email}</span>`:''}
${d.location?`<span class="contact-chip">๐Ÿ“ ${d.location}</span>`:''}
</div>
</div>
</div>
<div class="cv-body">
<div class="cv-left">
${d.skills.length?`<div class="section-title">Skills</div><div>${coralSkillTags}</div>`:''}
${d.langs.length?`<div class="section-title" style="margin-top:16px;">Languages</div>${d.langs.filter(l=>l.trim()).map(l=>`<div style="margin-bottom:8px;">โ€ข ${l.trim()}</div>`).join('')}`:''}
</div>
<div class="cv-right">
${d.summary?`<div class="section-title">About Me</div><div class="entry-desc" style="margin-bottom:16px;">${d.summary}</div>`:''}
${coralExp?`<div class="section-title">Experience</div>${coralExp}`:''}
${coralEdu?`<div class="section-title">Education</div>${coralEdu}`:''}
</div>
</div>
</div>`;
case 'forest':
case 'clean':
const forestSkills = d.skills.filter(s=>s.trim()).map(s=>`<div style="font-size:12px;color:rgba(255,255,255,0.85);margin-bottom:6px;"><span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:#40916c;margin:2px 4px 2px 0;vertical-align:middle;"></span>${s.trim()}</div>`).join('');
const forestEdu = d.edu.map(e=>`<div style="margin-bottom:14px;padding-bottom:14px;border-bottom:1px solid #eee;"><div class="entry-title">${e.degree||''}</div><div class="entry-sub">${e.institution||''}</div><div class="entry-date">${e.year||''}</div></div>`).join('');
const forestExp = d.exp.map(e=>`<div style="margin-bottom:14px;padding-bottom:14px;border-bottom:1px solid #eee;"><div class="entry-title">${e.role||''}</div><div class="entry-sub">${e.company||''}</div><div class="entry-date">${e.period||''}</div><div class="entry-desc">${e.desc||''}</div></div>`).join('');
return `
<div class="theme-forest clearfix" style="padding:0;">
<div class="cv-sidebar-col">
<div class="cv-photo">${d.photo?`<img src="${d.photo}" alt="Profile" style="width:110px;height:110px;border-radius:50%;object-fit:cover;border:4px solid #40916c;display:block;margin:0 auto 16px;">`:`<div class="ph" style="width:110px;height:110px;border-radius:50%;background:#40916c;display:flex;align-items:center;justify-content:center;font-size:40px;border:4px solid #74c69d;margin:0 auto 16px;">๐Ÿ‘ค</div>`}</div>
<div style="text-align:center;color:white;font-size:15px;font-weight:700;">${d.name}</div>
<div style="text-align:center;color:#74c69d;font-size:10px;letter-spacing:1.5px;margin-bottom:20px;margin-top:4px;">${d.title}</div>
<div style="font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#74c69d;margin:18px 0 8px;">Contact</div>
${d.phone?`<div style="font-size:11px;color:rgba(255,255,255,0.85);margin-bottom:6px;">๐Ÿ“ž ${d.phone}</div>`:''}
${d.email?`<div style="font-size:11px;color:rgba(255,255,255,0.85);margin-bottom:6px;">โœ‰ ${d.email}</div>`:''}
${d.location?`<div style="font-size:11px;color:rgba(255,255,255,0.85);margin-bottom:6px;">๐Ÿ“ ${d.location}</div>`:''}
${d.skills.length?`<div style="font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#74c69d;margin:18px 0 8px;">Skills</div>${forestSkills}`:''}
</div>
<div class="cv-main-col">
<div style="font-size:26px;font-weight:700;color:#1b4332;margin-bottom:4px;">${d.name}</div>
<div style="font-size:12px;color:#40916c;font-weight:700;text-transform:uppercase;letter-spacing:1.5px;margin-bottom:28px;">${d.title}</div>
${d.summary?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#1b4332;border-left:4px solid #40916c;padding-left:10px;margin:22px 0 12px;">Profile</div><div class="entry-desc" style="margin-bottom:8px;">${d.summary}</div>`:''}
${forestExp?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#1b4332;border-left:4px solid #40916c;padding-left:10px;margin:22px 0 12px;">Work Experience</div>${forestExp}`:''}
${forestEdu?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#1b4332;border-left:4px solid #40916c;padding-left:10px;margin:22px 0 12px;">Education</div>${forestEdu}`:''}
</div>
</div>`;
case 'purple':
case 'tech':
const purpleSkillBars = d.skills.filter(s=>s.trim()).slice(0,8).map(s=>`<div style="font-size:11px;color:#555;margin-bottom:4px;display:flex;justify-content:space-between;"><span>${s.trim()}</span></div><div style="background:#e9d5ff;border-radius:4px;height:5px;margin-bottom:8px;"><div style="background:linear-gradient(90deg,#4a0e8f,#9b59b6);border-radius:4px;height:5px;width:${Math.floor(Math.random()*30+65)}%"></div></div>`).join('');
const purpleEdu = d.edu.map(e=>`<div style="display:flex;gap:12px;margin-bottom:16px;"><div style="display:flex;flex-direction:column;align-items:center;width:12px;flex-shrink:0;"><div style="width:8px;height:8px;background:#4a0e8f;border-radius:50%;flex-shrink:0;margin-top:5px;"></div></div><div style="flex:1;"><div class="entry-title">${e.degree||''}</div><div style="font-size:12px;color:#7d3c98;font-weight:600;margin:2px 0;">${e.institution||''}</div><div class="entry-date">${e.year||''}</div></div></div>`).join('');
const purpleExp = d.exp.map(e=>`<div style="display:flex;gap:12px;margin-bottom:16px;"><div style="display:flex;flex-direction:column;align-items:center;width:12px;flex-shrink:0;"><div style="width:8px;height:8px;background:#4a0e8f;border-radius:50%;flex-shrink:0;margin-top:5px;"></div></div><div style="flex:1;"><div class="entry-title">${e.role||''}</div><div class="entry-sub">${e.company||''}</div><div class="entry-date">${e.period||''}</div><div class="entry-desc">${e.desc||''}</div></div></div>`).join('');
return `
<div style="padding:0;">
<div style="background:#4a0e8f;padding:0;display:flex;min-height:180px;">
<div style="width:240px;flex-shrink:0;background:#3a0b70;padding:36px 24px;display:flex;flex-direction:column;align-items:center;">
${d.photo?`<img src="${d.photo}" style="width:100px;height:100px;border-radius:50%;object-fit:cover;border:3px solid #9b59b6;" alt="Profile">`:`<div style="width:100px;height:100px;border-radius:50%;background:#6c3483;display:flex;align-items:center;justify-content:center;font-size:40px;border:3px solid #9b59b6;">๐Ÿ‘ค</div>`}
</div>
<div style="flex:1;padding:36px 30px;display:flex;flex-direction:column;justify-content:center;">
<div style="font-size:28px;font-weight:800;color:white;letter-spacing:-0.5px;">${d.name}</div>
<div style="font-size:13px;color:#c39bd3;margin-top:6px;letter-spacing:1px;">${d.title}</div>
<div style="display:flex;flex-wrap:wrap;gap:10px;margin-top:16px;">
${d.phone?`<div style="font-size:11px;color:rgba(255,255,255,0.85);">๐Ÿ“ž ${d.phone}</div>`:''}
${d.email?`<div style="font-size:11px;color:rgba(255,255,255,0.85);">โœ‰ ${d.email}</div>`:''}
</div>
</div>
</div>
<div style="display:flex;">
<div style="width:240px;flex-shrink:0;background:#f9f5ff;padding:24px;border-right:1px solid #e9d5ff;">
${purpleSkillBars?`<div style="font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#4a0e8f;margin:18px 0 10px;border-bottom:2px solid #c39bd3;padding-bottom:4px;">Skills</div>${purpleSkillBars}`:''}
</div>
<div style="flex:1;padding:24px 30px;">
${d.summary?`<div style="font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#4a0e8f;margin:18px 0 10px;border-bottom:2px solid #c39bd3;padding-bottom:4px;">About</div><div class="entry-desc" style="margin-bottom:12px;">${d.summary}</div>`:''}
${purpleExp?`<div style="font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#4a0e8f;margin:18px 0 10px;border-bottom:2px solid #c39bd3;padding-bottom:4px;">Experience</div>${purpleExp}`:''}
</div>
</div>
</div>`;
case 'slate':
case 'modern':
const slateSkillDots = d.skills.filter(s=>s.trim()).slice(0,7).map(s => {
const lvl = Math.floor(Math.random()*2+4);
const dots = Array.from({length:5},(_,i)=>`<div style="width:8px;height:8px;border-radius:50%;${i<lvl?'background:#2d3748':'background:#e2e8f0'}"></div>`).join('');
return `<div style="display:flex;justify-content:space-between;align-items:center;font-size:12px;color:#4a5568;margin-bottom:6px;"><span>${s.trim()}</span><div style="display:flex;gap:3px;">${dots}</div></div>`;
}).join('');
const slateEdu = d.edu.map(e=>`<div style="margin-bottom:14px;padding-bottom:14px;border-bottom:1px solid #edf2f7;"><div class="entry-title">${e.degree||''}</div><div style="font-size:12px;color:#4a5568;font-weight:600;margin:2px 0;">${e.institution||''}</div><div style="font-size:11px;color:#718096;margin-bottom:4px;">${e.year||''}</div></div>`).join('');
const slateExp = d.exp.map(e=>`<div style="margin-bottom:14px;padding-bottom:14px;border-bottom:1px solid #edf2f7;"><div class="entry-title">${e.role||''}</div><div style="font-size:12px;color:#4a5568;font-weight:600;margin:2px 0;">${e.company||''}</div><div style="font-size:11px;color:#718096;margin-bottom:4px;">${e.period||''}</div><div style="font-size:12px;color:#718096;line-height:1.6;">${e.desc||''}</div></div>`).join('');
return `
<div style="padding:0;">
<div style="background:#2d3748;padding:36px 40px;display:flex;align-items:center;gap:28px;">
${d.photo?`<img src="${d.photo}" style="width:95px;height:95px;border-radius:12px;object-fit:cover;border:3px solid #4a5568;" alt="Profile">`:`<div style="width:95px;height:95px;border-radius:12px;background:#4a5568;display:flex;align-items:center;justify-content:center;font-size:38px;border:3px solid #718096;">๐Ÿ‘ค</div>`}
<div>
<div style="font-size:30px;font-weight:800;color:white;">${d.name}</div>
<div style="font-size:13px;color:#a0aec0;margin-top:4px;">${d.title}</div>
<div style="display:flex;gap:16px;margin-top:12px;flex-wrap:wrap;">
${d.phone?`<span style="font-size:11px;color:#a0aec0;">๐Ÿ“ž ${d.phone}</span>`:''}
${d.email?`<span style="font-size:11px;color:#a0aec0;">โœ‰ ${d.email}</span>`:''}
</div>
</div>
</div>
<div style="display:flex;">
<div style="width:220px;flex-shrink:0;background:#f7fafc;padding:24px 20px;border-right:2px solid #edf2f7;">
${slateSkillDots?`<div style="font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#2d3748;background:#edf2f7;padding:6px 10px;border-radius:4px;margin:18px 0 10px;">Skills</div>${slateSkillDots}`:''}
</div>
<div style="flex:1;padding:24px 30px;">
${d.summary?`<div style="font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#2d3748;background:#edf2f7;padding:6px 10px;border-radius:4px;margin:18px 0 10px;">Profile</div><div class="entry-desc" style="margin-bottom:12px;">${d.summary}</div>`:''}
${slateExp?`<div style="font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#2d3748;background:#edf2f7;padding:6px 10px;border-radius:4px;margin:18px 0 10px;">Experience</div>${slateExp}`:''}
</div>
</div>
</div>`;
case 'ocean':
case 'elegant':
const oceanSkillBadges = d.skills.filter(s=>s.trim()).map(s=>`<span style="display:inline-block;background:#006BA6;color:white;padding:5px 14px;border-radius:20px;font-size:11px;margin:3px;font-weight:600;">${s.trim()}</span>`).join('');
const oceanEdu = d.edu.map(e=>`<div style="background:#f0f9ff;border-left:4px solid #0496FF;padding:14px;margin-bottom:14px;border-radius:6px;"><div class="entry-title">${e.degree||''}</div><div style="font-size:12px;color:#006BA6;font-weight:600;margin:2px 0;">${e.institution||''}</div><div style="font-size:11px;color:#999;margin-bottom:4px;">${e.year||''}</div></div>`).join('');
const oceanExp = d.exp.map(e=>`<div style="background:#f0f9ff;border-left:4px solid #0496FF;padding:14px;margin-bottom:14px;border-radius:6px;"><div class="entry-title">${e.role||''}</div><div style="font-size:12px;color:#006BA6;font-weight:600;margin:2px 0;">${e.company||''}</div><div style="font-size:11px;color:#999;margin-bottom:4px;">${e.period||''}</div><div class="entry-desc">${e.desc||''}</div></div>`).join('');
return `
<div style="padding:0;">
<div style="background:linear-gradient(135deg,#006BA6 0%,#0496FF 100%);padding:40px;text-align:center;color:white;">
${d.photo?`<img src="${d.photo}" style="width:110px;height:110px;border-radius:50%;object-fit:cover;border:4px solid rgba(255,255,255,0.4);display:block;margin:0 auto 16px;" alt="Profile">`:`<div style="width:110px;height:110px;border-radius:50%;background:rgba(255,255,255,0.2);display:flex;align-items:center;justify-content:center;font-size:42px;border:4px solid rgba(255,255,255,0.4);margin:0 auto 16px;">๐Ÿ‘ค</div>`}
<div style="font-size:32px;font-weight:800;color:white;letter-spacing:-1px;">${d.name}</div>
<div style="font-size:14px;color:rgba(255,255,255,0.9);margin-top:6px;letter-spacing:1px;">${d.title}</div>
<div style="display:flex;gap:14px;justify-content:center;margin-top:16px;flex-wrap:wrap;">
${d.phone?`<span style="font-size:11px;color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.15);padding:5px 14px;border-radius:20px;">๐Ÿ“ž ${d.phone}</span>`:''}
${d.email?`<span style="font-size:11px;color:rgba(255,255,255,0.85);background:rgba(255,255,255,0.15);padding:5px 14px;border-radius:20px;">โœ‰ ${d.email}</span>`:''}
</div>
</div>
<div style="padding:32px 36px;">
${d.summary?`<div style="font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#006BA6;border-bottom:3px solid #0496FF;padding-bottom:6px;margin:24px 0 14px;">Professional Summary</div><div class="entry-desc" style="margin-bottom:16px;">${d.summary}</div>`:''}
${oceanSkillBadges?`<div style="font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#006BA6;border-bottom:3px solid #0496FF;padding-bottom:6px;margin:24px 0 14px;">Skills</div><div style="margin-bottom:16px;">${oceanSkillBadges}</div>`:''}
${oceanExp?`<div style="font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#006BA6;border-bottom:3px solid #0496FF;padding-bottom:6px;margin:24px 0 14px;">Work Experience</div>${oceanExp}`:''}
${oceanEdu?`<div style="font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#006BA6;border-bottom:3px solid #0496FF;padding-bottom:6px;margin:24px 0 14px;">Education</div>${oceanEdu}`:''}
</div>
</div>`;
case 'sunsetorange':
case 'bold':
const sunsetSkills = d.skills.filter(s=>s.trim()).map(s=>`<div style="font-size:11px;color:rgba(255,255,255,0.9);margin-bottom:8px;line-height:1.5;"><span style="display:inline-block;width:10px;height:10px;border-radius:50%;background:white;margin-right:6px;vertical-align:middle;"></span>${s.trim()}</div>`).join('');
const sunsetEdu = d.edu.map(e=>`<div style="margin-bottom:16px;"><div class="entry-title">${e.degree||''}</div><div style="font-size:12px;color:#FF6B35;font-weight:600;margin:2px 0;">${e.institution||''}</div><div style="font-size:11px;color:#999;margin-bottom:4px;">${e.year||''}</div></div>`).join('');
const sunsetExp = d.exp.map(e=>`<div style="margin-bottom:16px;"><div class="entry-title">${e.role||''}</div><div style="font-size:12px;color:#FF6B35;font-weight:600;margin:2px 0;">${e.company||''}</div><div style="font-size:11px;color:#999;margin-bottom:4px;">${e.period||''}</div><div class="entry-desc">${e.desc||''}</div></div>`).join('');
return `
<div class="clearfix" style="padding:0;">
<div style="width:250px;min-height:1123px;background:linear-gradient(180deg,#FF6B35 0%,#F7931E 100%);color:white;padding:36px 24px;float:left;">
${d.photo?`<img src="${d.photo}" style="width:115px;height:115px;border-radius:20px;object-fit:cover;border:4px solid rgba(255,255,255,0.4);display:block;margin:0 auto 18px;" alt="Profile">`:`<div style="width:115px;height:115px;border-radius:20px;background:rgba(255,255,255,0.2);display:flex;align-items:center;justify-content:center;font-size:44px;border:4px solid rgba(255,255,255,0.4);margin:0 auto 18px;">๐Ÿ‘ค</div>`}
<div style="text-align:center;font-size:18px;font-weight:700;color:white;margin-bottom:4px;">${d.name}</div>
<div style="text-align:center;font-size:11px;color:rgba(255,255,255,0.8);letter-spacing:1px;margin-bottom:24px;">${d.title}</div>
<div style="font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:white;margin:20px 0 10px;border-bottom:2px solid rgba(255,255,255,0.3);padding-bottom:6px;">Contact</div>
${d.phone?`<div style="font-size:11px;color:rgba(255,255,255,0.9);margin-bottom:8px;">๐Ÿ“ž ${d.phone}</div>`:''}
${d.email?`<div style="font-size:11px;color:rgba(255,255,255,0.9);margin-bottom:8px;">โœ‰ ${d.email}</div>`:''}
${sunsetSkills?`<div style="font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:white;margin:20px 0 10px;border-bottom:2px solid rgba(255,255,255,0.3);padding-bottom:6px;">Skills</div>${sunsetSkills}`:''}
</div>
<div style="margin-left:250px;padding:36px 32px;">
<div style="font-size:28px;font-weight:700;color:#1a1a2e;margin-bottom:4px;">${d.name}</div>
<div style="font-size:13px;color:#FF6B35;font-weight:700;text-transform:uppercase;letter-spacing:1.5px;margin-bottom:28px;">${d.title}</div>
${d.summary?`<div style="font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#FF6B35;margin:24px 0 14px;display:flex;align-items:center;gap:8px;"><span style="color:#F7931E;font-size:16px;">โ—</span>About</div><div class="entry-desc" style="margin-bottom:12px;">${d.summary}</div>`:''}
${sunsetExp?`<div style="font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#FF6B35;margin:24px 0 14px;display:flex;align-items:center;gap:8px;"><span style="color:#F7931E;font-size:16px;">โ—</span>Experience</div>${sunsetExp}`:''}
${sunsetEdu?`<div style="font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#FF6B35;margin:24px 0 14px;display:flex;align-items:center;gap:8px;"><span style="color:#F7931E;font-size:16px;">โ—</span>Education</div>${sunsetEdu}`:''}
</div>
</div>`;
case 'mint':
case 'classic':
const mintSkillBoxes = d.skills.filter(s=>s.trim()).map(s=>`<span style="display:inline-block;background:white;border:2px solid #00D9C0;color:#00B4A0;padding:4px 12px;border-radius:6px;font-size:11px;margin:3px;font-weight:600;">${s.trim()}</span>`).join('');
const mintEdu = d.edu.map(e=>`<div style="margin-bottom:14px;padding-bottom:14px;border-bottom:1px solid #e8f8f6;"><div class="entry-title">${e.degree||''}</div><div style="font-size:12px;color:#00B4A0;font-weight:600;margin:2px 0;">${e.institution||''}</div><div style="font-size:11px;color:#999;margin-bottom:4px;">${e.year||''}</div></div>`).join('');
const mintExp = d.exp.map(e=>`<div style="margin-bottom:14px;padding-bottom:14px;border-bottom:1px solid #e8f8f6;"><div class="entry-title">${e.role||''}</div><div style="font-size:12px;color:#00B4A0;font-weight:600;margin:2px 0;">${e.company||''}</div><div style="font-size:11px;color:#999;margin-bottom:4px;">${e.period||''}</div><div class="entry-desc">${e.desc||''}</div></div>`).join('');
return `
<div style="padding:0;">
<div style="background:#00D9C0;padding:40px;display:flex;align-items:center;gap:30px;">
${d.photo?`<img src="${d.photo}" style="width:105px;height:105px;border-radius:50%;object-fit:cover;border:5px solid white;box-shadow:0 4px 12px rgba(0,0,0,0.15);" alt="Profile">`:`<div style="width:105px;height:105px;border-radius:50%;background:#00B4A0;display:flex;align-items:center;justify-content:center;font-size:42px;border:5px solid white;box-shadow:0 4px 12px rgba(0,0,0,0.15);">๐Ÿ‘ค</div>`}
<div>
<div style="font-size:32px;font-weight:800;color:white;letter-spacing:-1px;">${d.name}</div>
<div style="font-size:14px;color:rgba(255,255,255,0.95);margin-top:6px;">${d.title}</div>
<div style="display:flex;gap:18px;margin-top:14px;flex-wrap:wrap;">
${d.phone?`<div style="font-size:11px;color:rgba(255,255,255,0.95);">๐Ÿ“ž ${d.phone}</div>`:''}
${d.email?`<div style="font-size:11px;color:rgba(255,255,255,0.95);">โœ‰ ${d.email}</div>`:''}
</div>
</div>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:0;">
<div style="padding:30px;background:#f0fffe;border-right:1px solid #d0f5f1;">
${d.summary?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#00B4A0;margin:20px 0 12px;position:relative;padding-left:16px;"><span style="position:absolute;left:0;top:50%;transform:translateY(-50%);width:8px;height:8px;background:#00D9C0;border-radius:50%;"></span>About</div><div class="entry-desc" style="margin-bottom:12px;">${d.summary}</div>`:''}
${mintSkillBoxes?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#00B4A0;margin:20px 0 12px;position:relative;padding-left:16px;"><span style="position:absolute;left:0;top:50%;transform:translateY(-50%);width:8px;height:8px;background:#00D9C0;border-radius:50%;"></span>Skills</div><div style="margin-bottom:12px;">${mintSkillBoxes}</div>`:''}
</div>
<div style="padding:30px;">
${mintExp?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#00B4A0;margin:20px 0 12px;position:relative;padding-left:16px;"><span style="position:absolute;left:0;top:50%;transform:translateY(-50%);width:8px;height:8px;background:#00D9C0;border-radius:50%;"></span>Experience</div>${mintExp}`:''}
${mintEdu?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#00B4A0;margin:20px 0 12px;position:relative;padding-left:16px;"><span style="position:absolute;left:0;top:50%;transform:translateY(-50%);width:8px;height:8px;background:#00D9C0;border-radius:50%;"></span>Education</div>${mintEdu}`:''}
</div>
</div>
</div>`;
case 'rosegold':
case 'portfolio':
const roseSkillTags = d.skills.filter(s=>s.trim()).map(s=>`<span style="display:inline-block;background:#E8B4B8;color:#5D3A3A;padding:4px 12px;border-radius:20px;font-size:11px;margin:3px;font-weight:600;">${s.trim()}</span>`).join('');
const roseEdu = d.edu.map(e=>`<div style="margin-bottom:14px;"><div class="entry-title">${e.degree||''}</div><div style="font-size:12px;color:#C9A9A6;font-weight:600;margin:2px 0;">${e.institution||''}</div><div style="font-size:11px;color:#999;margin-bottom:4px;">${e.year||''}</div></div>`).join('');
const roseExp = d.exp.map(e=>`<div style="margin-bottom:14px;"><div class="entry-title">${e.role||''}</div><div style="font-size:12px;color:#C9A9A6;font-weight:600;margin:2px 0;">${e.company||''}</div><div style="font-size:11px;color:#999;margin-bottom:4px;">${e.period||''}</div><div class="entry-desc">${e.desc||''}</div></div>`).join('');
return `
<div style="padding:0;">
<div style="background:linear-gradient(135deg,#C9A9A6 0%,#E8B4B8 100%);padding:38px 40px;">
<div style="display:flex;align-items:center;gap:26px;">
${d.photo?`<img src="${d.photo}" style="width:100px;height:100px;border-radius:16px;object-fit:cover;border:3px solid rgba(255,255,255,0.6);" alt="Profile">`:`<div style="width:100px;height:100px;border-radius:16px;background:rgba(255,255,255,0.3);display:flex;align-items:center;justify-content:center;font-size:40px;border:3px solid rgba(255,255,255,0.6);">๐Ÿ‘ค</div>`}
<div>
<div style="font-size:30px;font-weight:800;color:#5D3A3A;">${d.name}</div>
<div style="font-size:13px;color:#8B6B6B;margin-top:4px;letter-spacing:0.5px;">${d.title}</div>
<div style="display:flex;gap:16px;margin-top:14px;flex-wrap:wrap;">
${d.phone?`<span style="font-size:11px;color:#8B6B6B;background:rgba(255,255,255,0.5);padding:4px 12px;border-radius:20px;">๐Ÿ“ž ${d.phone}</span>`:''}
${d.email?`<span style="font-size:11px;color:#8B6B6B;background:rgba(255,255,255,0.5);padding:4px 12px;border-radius:20px;">โœ‰ ${d.email}</span>`:''}
</div>
</div>
</div>
</div>
<div style="display:flex;">
<div style="width:235px;flex-shrink:0;background:#FAF4F4;padding:26px 22px;border-right:2px solid #F0E5E5;">
${roseSkillTags?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#C9A9A6;margin:20px 0 12px;padding-bottom:6px;border-bottom:2px solid #E8B4B8;">Skills</div><div style="margin-bottom:12px;">${roseSkillTags}</div>`:''}
</div>
<div style="flex:1;padding:26px 32px;">
${d.summary?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#C9A9A6;margin:20px 0 12px;padding-bottom:6px;border-bottom:2px solid #E8B4B8;">About Me</div><div class="entry-desc" style="margin-bottom:14px;">${d.summary}</div>`:''}
${roseExp?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#C9A9A6;margin:20px 0 12px;padding-bottom:6px;border-bottom:2px solid #E8B4B8;">Experience</div>${roseExp}`:''}
${roseEdu?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#C9A9A6;margin:20px 0 12px;padding-bottom:6px;border-bottom:2px solid #E8B4B8;">Education</div>${roseEdu}`:''}
</div>
</div>
</div>`;
case 'dark':
const darkSkillPills = d.skills.filter(s=>s.trim()).map(s=>`<span style="display:inline-block;background:#FFD700;color:#000;padding:4px 12px;border-radius:20px;font-size:11px;margin:3px;font-weight:700;">${s.trim()}</span>`).join('');
const darkEdu = d.edu.map(e=>`<div style="margin-bottom:14px;padding-bottom:14px;border-bottom:1px solid #333;"><div class="entry-title">${e.degree||''}</div><div style="font-size:12px;color:#FFD700;font-weight:600;margin:2px 0;">${e.institution||''}</div><div style="font-size:11px;color:#999;margin-bottom:4px;">${e.year||''}</div></div>`).join('');
const darkExp = d.exp.map(e=>`<div style="margin-bottom:14px;padding-bottom:14px;border-bottom:1px solid #333;"><div class="entry-title">${e.role||''}</div><div style="font-size:12px;color:#FFD700;font-weight:600;margin:2px 0;">${e.company||''}</div><div style="font-size:11px;color:#999;margin-bottom:4px;">${e.period||''}</div><div style="font-size:12px;color:#ccc;line-height:1.6;">${e.desc||''}</div></div>`).join('');
return `
<div style="padding:0;background:#1a1a1a;">
<div style="background:#000;padding:40px;border-bottom:3px solid #FFD700;">
<div style="display:flex;align-items:center;gap:28px;">
${d.photo?`<img src="${d.photo}" style="width:100px;height:100px;border-radius:50%;object-fit:cover;border:4px solid #FFD700;" alt="Profile">`:`<div style="width:100px;height:100px;border-radius:50%;background:#333;display:flex;align-items:center;justify-content:center;font-size:40px;border:4px solid #FFD700;">๐Ÿ‘ค</div>`}
<div>
<div style="font-size:32px;font-weight:800;color:white;letter-spacing:-1px;">${d.name}</div>
<div style="font-size:14px;color:#FFD700;margin-top:6px;letter-spacing:1px;text-transform:uppercase;">${d.title}</div>
<div style="display:flex;gap:18px;margin-top:14px;flex-wrap:wrap;">
${d.phone?`<div style="font-size:11px;color:#ccc;">๐Ÿ“ž ${d.phone}</div>`:''}
${d.email?`<div style="font-size:11px;color:#ccc;">โœ‰ ${d.email}</div>`:''}
</div>
</div>
</div>
</div>
<div style="display:flex;">
<div style="width:240px;flex-shrink:0;background:#222;padding:28px 24px;border-right:1px solid #333;">
${darkSkillPills?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#FFD700;margin:20px 0 12px;">Skills</div><div style="margin-bottom:12px;">${darkSkillPills}</div>`:''}
</div>
<div style="flex:1;padding:28px 32px;background:#1a1a1a;">
${d.summary?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#FFD700;margin:20px 0 12px;">About</div><div style="font-size:12px;color:#ccc;line-height:1.6;margin-bottom:14px;">${d.summary}</div>`:''}
${darkExp?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#FFD700;margin:20px 0 12px;">Experience</div>${darkExp}`:''}
${darkEdu?`<div style="font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:2px;color:#FFD700;margin:20px 0 12px;">Education</div>${darkEdu}`:''}
</div>
</div>
</div>`;
case 'crimson':
const crimsonSkillRects = d.skills.filter(s=>s.trim()).map(s=>`<span style="display:inline-block;background:#8B0000;color:white;padding:5px 12px;border-radius:4px;font-size:11px;margin:3px;font-weight:600;">${s.trim()}</span>`).join('');
const crimsonEdu = d.edu.map(e=>`<div style="margin-bottom:14px;"><div class="entry-title">${e.degree||''}</div><div style="font-size:12px;color:#8B0000;font-weight:600;margin:2px 0;">${e.institution||''}</div><div style="font-size:11px;color:#999;margin-bottom:4px;">${e.year||''}</div></div>`).join('');
const crimsonExp = d.exp.map(e=>`<div style="margin-bottom:14px;"><div class="entry-title">${e.role||''}</div><div style="font-size:12px;color:#8B0000;font-weight:600;margin:2px 0;">${e.company||''}</div><div style="font-size:11px;color:#999;margin-bottom:4px;">${e.period||''}</div><div class="entry-desc">${e.desc||''}</div></div>`).join('');
return `
<div style="padding:0;">
<div style="background:#8B0000;padding:36px 40px;color:white;">
<div style="display:flex;align-items:center;gap:26px;">
${d.photo?`<img src="${d.photo}" style="width:95px;height:95px;border-radius:12px;object-fit:cover;border:3px solid rgba(255,255,255,0.4);" alt="Profile">`:`<div style="width:95px;height:95px;border-radius:12px;background:#A52A2A;display:flex;align-items:center;justify-content:center;font-size:38px;border:3px solid rgba(255,255,255,0.4);">๐Ÿ‘ค</div>`}
<div>
<div style="font-size:30px;font-weight:800;color:white;letter-spacing:-0.5px;">${d.name}</div>
<div style="font-size:13px;color:rgba(255,255,255,0.85);margin-top:4px;">${d.title}</div>
<div style="display:flex;gap:16px;margin-top:12px;flex-wrap:wrap;">
${d.phone?`<div style="font-size:11px;color:rgba(255,255,255,0.85);">๐Ÿ“ž ${d.phone}</div>`:''}
${d.email?`<div style="font-size:11px;color:rgba(255,255,255,0.85);">โœ‰ ${d.email}</div>`:''}
</div>
</div>
</div>
</div>
<div style="padding:32px 40px;">
${d.summary?`<div style="font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#8B0000;margin:24px 0 14px;border-left:5px solid #8B0000;padding-left:12px;">Professional Profile</div><div class="entry-desc" style="margin-bottom:16px;">${d.summary}</div>`:''}
<div style="display:grid;grid-template-columns:1fr 1fr;gap:32px;">
<div>
${crimsonExp?`<div style="font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#8B0000;margin:24px 0 14px;border-left:5px solid #8B0000;padding-left:12px;">Experience</div>${crimsonExp}`:''}
</div>
<div>
${crimsonEdu?`<div style="font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#8B0000;margin:24px 0 14px;border-left:5px solid #8B0000;padding-left:12px;">Education</div>${crimsonEdu}`:''}
${crimsonSkillRects?`<div style="font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:1.5px;color:#8B0000;margin:24px 0 14px;border-left:5px solid #8B0000;padding-left:12px;">Skills</div><div style="margin-bottom:12px;">${crimsonSkillRects}</div>`:''}
</div>
</div>
</div>
</div>`;
default:
return `
<div class="cv-header" style="padding:40px;background:linear-gradient(135deg,#111827,#6366f1);color:white">
<div style="font-size:36px;font-weight:800">${d.name}</div>
<div>${d.title}</div>
</div>
<div class="cv-body" style="display:flex;padding:35px;gap:30px">
<div class="cv-sidebar" style="width:35%"><b>Skills</b><p>${d.skills.join(', ')}</p></div>
<div class="cv-main"><b>Profile</b><p>${d.summary}</p><b>Experience</b>${expList}<b>Education</b>${eduList}</div>
</div>`;
}
}
async function downloadPDF() {
const btn = document.querySelector('button[onclick="downloadPDF()"]');
const originalText = btn.innerHTML;
btn.innerHTML = '<span class="material-symbols-outlined animate-spin text-[14px]">sync</span> Exporting...';
btn.disabled = true;
const cv = document.getElementById('cv-preview');
const originalTransform = cv.style.transform;
const originalMargin = cv.style.margin;
cv.style.transform = 'none';
cv.style.margin = '0';
try {
const canvas = await html2canvas(cv, {
scale: 2,
useCORS: true,
allowTaint: true,
backgroundColor: '#ffffff',
width: 794,
height: 1123
});
const imgData = canvas.toDataURL('image/jpeg', 0.95);
const { jsPDF } = window.jspdf;
const pdf = new jsPDF('p', 'mm', 'a4');
pdf.addImage(imgData, 'JPEG', 0, 0, 210, 297);
const name = document.getElementById('f-name').value || 'CV';
pdf.save(`${name.replace(/\s+/g, '_')}_CV.pdf`);
btn.innerHTML = '<span class="material-symbols-outlined text-[14px]">check</span> Done!';
setTimeout(() => {
btn.innerHTML = originalText;
btn.disabled = false;
}, 2000);
} catch (err) {
console.error(err);
btn.innerHTML = '<span class="material-symbols-outlined text-[14px]">error</span> Failed';
setTimeout(() => {
btn.innerHTML = originalText;
btn.disabled = false;
}, 2000);
} finally {
cv.style.transform = originalTransform;
cv.style.margin = originalMargin;
updateCV();
}
}
// Start the app
init();
</script>
</body></html>