/* ============================================================ HanziLearn – Main Stylesheet ============================================================ */ /* ── CSS Variables ──────────────────────────────────────────── */ :root { --accent: #E63946; --accent-soft: rgba(230,57,70,.12); --accent-glow: rgba(230,57,70,.3); --bg-base: #0d0f14; --bg-card: #141720; --bg-elevated: #1a1e2a; --border: rgba(255,255,255,.08); --text-primary: #f0f2f7; --text-muted: #8890a4; --hanzi-font: 'Noto Serif SC', serif; --ui-font: 'DM Sans', sans-serif; --mono-font: 'JetBrains Mono', monospace; --radius: 12px; --radius-lg: 20px; --shadow-md: 0 8px 32px rgba(0,0,0,.4); --shadow-lg: 0 20px 60px rgba(0,0,0,.6); --trans: .2s cubic-bezier(.4,0,.2,1); /* HSK colours */ --hsk1: #4CAF50; --hsk2: #8BC34A; --hsk3: #FFC107; --hsk4: #FF9800; --hsk5: #F44336; --hsk6: #9C27B0; } /* ── Reset / Base ────────────────────────────────────────────── */ *, *::before, *::after { box-sizing: border-box; margin: 0; } html { scroll-behavior: smooth; } body { font-family: var(--ui-font); background: var(--bg-base); color: var(--text-primary); line-height: 1.65; padding-top: 68px; } .py-6 { padding-top: 5rem; padding-bottom: 5rem; } /* ── Typography ─────────────────────────────────────────────── */ .brand-hanzi { font-family: var(--hanzi-font); font-weight: 700; color: var(--accent); } /* ── Buttons ─────────────────────────────────────────────────── */ .btn-accent { background: var(--accent); color: #fff; border: none; font-weight: 600; transition: all var(--trans); } .btn-accent:hover { background: #c1121f; color: #fff; transform: translateY(-1px); box-shadow: 0 6px 20px var(--accent-glow); } .btn-outline-accent { border: 1.5px solid var(--accent); color: var(--accent); background: transparent; font-weight: 500; transition: all var(--trans); } .btn-outline-accent:hover { background: var(--accent-soft); color: var(--accent); } .bg-accent { background: var(--accent) !important; } /* ── Navbar ──────────────────────────────────────────────────── */ #mainNav { background: rgba(13,15,20,.85); backdrop-filter: blur(20px); border-bottom: 1px solid var(--border); padding: .75rem 0; transition: background var(--trans); } .navbar-brand { display:flex; align-items:center; gap:.5rem; text-decoration:none; } .brand-text { font-weight:600; font-size:1.1rem; color:var(--text-primary); } .nav-link { color: var(--text-muted) !important; font-weight:500; padding: .5rem .75rem !important; border-radius:8px; transition: color var(--trans); } .nav-link:hover, .nav-link.active { color: var(--text-primary) !important; background: rgba(255,255,255,.05); } .dropdown-menu { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius); padding: .5rem; min-width:220px; box-shadow: var(--shadow-md); } .dropdown-item { color: var(--text-muted); border-radius:8px; padding:.5rem .75rem; display:flex; align-items:center; gap:.75rem; transition: all var(--trans); } .dropdown-item:hover { background:var(--accent-soft); color:var(--text-primary); } /* HSK badges */ .hsk-badge { font-family: var(--mono-font); font-size:.7rem; font-weight:600; padding:.15rem .45rem; border-radius:5px; color:#fff; } .hsk1 { background:var(--hsk1); } .hsk2 { background:var(--hsk2); } .hsk3 { background:var(--hsk3); color:#000; } .hsk4 { background:var(--hsk4); } .hsk5 { background:var(--hsk5); } .hsk6 { background:var(--hsk6); } #usernameBtn { border-color:var(--border); color:var(--text-muted); font-size:.85rem; } #usernameBtn:hover { border-color:var(--accent); color:var(--accent); } /* ── Username Modal ──────────────────────────────────────────── */ .modal-content { background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-lg); } .modal-hanzi { font-family:var(--hanzi-font); font-size:3rem; color:var(--accent); } #usernameInput { background:var(--bg-base); border:1.5px solid var(--border); color:var(--text-primary); border-radius:var(--radius); } #usernameInput:focus { border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-soft); background:var(--bg-base); color:var(--text-primary); } /* ── Hero ────────────────────────────────────────────────────── */ .hero-section { position:relative; overflow:hidden; min-height:100vh; background: radial-gradient(ellipse 80% 60% at 60% 40%, rgba(230,57,70,.08) 0%, transparent 70%), var(--bg-base); } .hero-bg-glyph { position:absolute; top:50%; right:-5%; transform:translateY(-50%); font-family:var(--hanzi-font); font-size:clamp(200px,25vw,400px); font-weight:700; color:rgba(230,57,70,.04); user-select:none; pointer-events:none; line-height:1; } .hero-content { position:relative; z-index:1; } .hero-badge { display:inline-flex; align-items:center; gap:.35rem; background:var(--accent-soft); border:1px solid rgba(230,57,70,.25); color:var(--accent); padding:.35rem 1rem; border-radius:999px; font-size:.85rem; font-weight:500; } .hero-title { font-size:clamp(2.5rem,6vw,4rem); font-weight:600; line-height:1.15; margin-bottom:1.25rem; } .hero-hanzi { font-family:var(--hanzi-font); color:var(--accent); display:block; font-size:clamp(2rem,5vw,3.5rem); } .hero-subtitle { font-size:1.1rem; color:var(--text-muted); max-width:480px; margin-bottom:2rem; } .hero-stats { display:flex; align-items:center; gap:1.5rem; } .stat-item { display:flex; flex-direction:column; } .stat-num { font-size:1.5rem; font-weight:700; font-family:var(--mono-font); } .stat-label { font-size:.8rem; color:var(--text-muted); } .stat-divider { width:1px; height:36px; background:var(--border); } /* Demo cards */ .hero-card-stack { position:relative; width:280px; height:320px; } .demo-card { position:absolute; width:240px; background:var(--bg-elevated); border:1px solid var(--border); border-radius:20px; padding:2rem; text-align:center; box-shadow:var(--shadow-lg); } .demo-card--back { top:20px; left:40px; transform:rotate(6deg); opacity:.6; } .demo-card--front { top:0; left:0; z-index:2; animation:float 4s ease-in-out infinite; } .demo-hanzi { font-family:var(--hanzi-font); font-size:3rem; font-weight:700; color:var(--accent); } .demo-pinyin { color:var(--text-muted); font-size:.9rem; margin-top:.25rem; } .demo-meaning { font-size:.85rem; color:var(--text-primary); margin-top:.5rem; } @keyframes float { 0%,100%{transform:translateY(0)} 50%{transform:translateY(-12px)} } /* ── Features ────────────────────────────────────────────────── */ .features-section { background:var(--bg-card); } .section-title { font-size:2rem; font-weight:700; margin-bottom:.5rem; } .feature-card { background:var(--bg-elevated); border:1px solid var(--border); border-radius:var(--radius-lg); padding:2rem; height:100%; transition:all var(--trans); } .feature-card:hover { border-color:rgba(230,57,70,.3); transform:translateY(-4px); box-shadow:var(--shadow-md); } .feature-icon { width:56px; height:56px; border-radius:var(--radius); display:flex; align-items:center; justify-content:center; font-size:1.5rem; margin-bottom:1.25rem; } /* ── HSK Level Cards ─────────────────────────────────────────── */ .hsk-section { background:var(--bg-base); } .hsk-level-card { display:block; background:var(--bg-elevated); border:1px solid var(--border); border-radius:var(--radius-lg); padding:1.5rem 1rem; text-align:center; text-decoration:none; transition:all var(--trans); position:relative; overflow:hidden; } /* Top accent line per level */ .hsk-level-card::before { content:''; position:absolute; top:0; left:0; right:0; height:3px; transform:scaleX(0); transform-origin:left; transition:transform var(--trans); } .hsk-level-card--1::before { background:var(--hsk1); } .hsk-level-card--2::before { background:var(--hsk2); } .hsk-level-card--3::before { background:var(--hsk3); } .hsk-level-card--4::before { background:var(--hsk4); } .hsk-level-card--5::before { background:var(--hsk5); } .hsk-level-card--6::before { background:var(--hsk6); } .hsk-level-card:hover::before { transform:scaleX(1); } .hsk-level-card:hover { transform:translateY(-4px); box-shadow:var(--shadow-md); } .hsk-level-card--1 .hsk-level-num { color:var(--hsk1); } .hsk-level-card--2 .hsk-level-num { color:var(--hsk2); } .hsk-level-card--3 .hsk-level-num { color:var(--hsk3); } .hsk-level-card--4 .hsk-level-num { color:var(--hsk4); } .hsk-level-card--5 .hsk-level-num { color:var(--hsk5); } .hsk-level-card--6 .hsk-level-num { color:var(--hsk6); } .hsk-level-num { font-family:var(--mono-font); font-size:1.1rem; font-weight:700; margin-bottom:.25rem; } .hsk-level-words { font-size:.75rem; color:var(--text-muted); font-family:var(--mono-font); } .hsk-level-desc { font-size:.75rem; color:var(--text-muted); margin-top:.5rem; line-height:1.4; } .hsk-level-arrow { margin-top:.75rem; opacity:0; transition:opacity var(--trans); } .hsk-level-card--1 .hsk-level-arrow { color:var(--hsk1); } .hsk-level-card--2 .hsk-level-arrow { color:var(--hsk2); } .hsk-level-card--3 .hsk-level-arrow { color:var(--hsk3); } .hsk-level-card--4 .hsk-level-arrow { color:var(--hsk4); } .hsk-level-card--5 .hsk-level-arrow { color:var(--hsk5); } .hsk-level-card--6 .hsk-level-arrow { color:var(--hsk6); } .hsk-level-card:hover .hsk-level-arrow { opacity:1; } /* ── CTA ─────────────────────────────────────────────────────── */ .cta-section { background:var(--bg-card); } .cta-card { background:linear-gradient(135deg,rgba(230,57,70,.1),rgba(230,57,70,.02)); border:1px solid rgba(230,57,70,.2); border-radius:var(--radius-lg); padding:3rem; } .cta-title { font-size:1.75rem; font-weight:700; margin-bottom:.75rem; } /* ── Footer ──────────────────────────────────────────────────── */ .site-footer { background:var(--bg-card); border-top:1px solid var(--border); padding:2.5rem 0; color:var(--text-muted); font-size:.9rem; } /* ── Page header (inner pages) ───────────────────────────────── */ .page-header { background:var(--bg-elevated); border-bottom:1px solid var(--border); padding:3rem 0 2rem; } .page-title { font-size:2rem; font-weight:700; margin-bottom:.25rem; } /* ── Dictionary ──────────────────────────────────────────────── */ .dict-search-wrap { max-width:640px; margin:0 auto; } .dict-search-box { position:relative; background:var(--bg-elevated); border:2px solid var(--border); border-radius:var(--radius-lg); display:flex; align-items:center; padding:.75rem 1.25rem; transition:border-color var(--trans); } .dict-search-box:focus-within { border-color:var(--accent); box-shadow:0 0 0 4px var(--accent-soft); } .dict-search-icon { color:var(--text-muted); font-size:1.2rem; margin-right:.75rem; } .dict-search-input { flex:1; background:transparent; border:none; outline:none; color:var(--text-primary); font-family:var(--ui-font); font-size:1rem; } .dict-search-input::placeholder { color:var(--text-muted); } .dict-search-clear { background:none; border:none; color:var(--text-muted); cursor:pointer; padding:.25rem; border-radius:50%; transition:all var(--trans); } .dict-search-clear:hover { color:var(--accent); background:var(--accent-soft); } .dict-search-hint { text-align:center; color:var(--text-muted); font-size:.85rem; margin-top:.75rem; } /* Dictionary grid */ .dict-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(320px,1fr)); gap:1rem; } .dict-card { background:var(--bg-elevated); border:1px solid var(--border); border-radius:var(--radius); padding:1.25rem 1.5rem; display:flex; align-items:flex-start; gap:1.25rem; cursor:pointer; transition:all var(--trans); } .dict-card:hover { border-color:rgba(230,57,70,.35); transform:translateX(4px); box-shadow:var(--shadow-md); } .dict-hanzi { font-family:var(--hanzi-font); font-size:2.25rem; font-weight:700; color:var(--accent); min-width:60px; text-align:center; flex-shrink:0; } .dict-info { flex:1; min-width:0; } .dict-pinyin { font-family:var(--mono-font); font-size:.85rem; color:var(--text-muted); margin-bottom:.2rem; } .dict-meaning { font-size:.9rem; color:var(--text-primary); } .dict-vi { font-size:.8rem; color:var(--text-muted); margin-top:.15rem; } /* Tags on card */ .dict-card-meta { display:flex; flex-direction:column; align-items:flex-end; gap:.35rem; flex-shrink:0; } .dict-tag { font-size:.7rem; background:rgba(255,255,255,.06); border:1px solid var(--border); color:var(--text-muted); padding:.15rem .5rem; border-radius:999px; white-space:nowrap; } .dict-hsk { font-family:var(--mono-font); font-size:.7rem; font-weight:600; padding:.15rem .45rem; border-radius:5px; color:#fff; white-space:nowrap; } /* Skeleton loader */ .skeleton { background:linear-gradient(90deg,var(--bg-elevated) 25%,var(--bg-card) 50%,var(--bg-elevated) 75%); background-size:200% 100%; animation:shimmer 1.5s infinite; border-radius:6px; } .skeleton-card { background:var(--bg-elevated); border:1px solid var(--border); border-radius:var(--radius); padding:1.25rem 1.5rem; display:flex; align-items:center; gap:1.25rem; } .skeleton-hanzi { width:60px; height:52px; border-radius:8px; } .skeleton-line { height:14px; } .w-25 { width:25%; } .w-50 { width:50%; } @keyframes shimmer { to { background-position:-200% 0; } } .empty-hanzi { font-family:var(--hanzi-font); font-size:5rem; color:var(--accent); } /* ── Word detail modal ───────────────────────────────────────── */ .word-modal-hanzi { font-family:var(--hanzi-font); font-size:4rem; font-weight:700; color:var(--accent); line-height:1; } .word-modal-pinyin { font-family:var(--mono-font); color:var(--text-muted); font-size:1.1rem; margin:.5rem 0 1rem; } .word-detail-row { background:var(--bg-base); border-radius:var(--radius); padding:.75rem 1rem; margin-bottom:.5rem; text-align:left; } .word-detail-label { font-size:.72rem; color:var(--text-muted); text-transform:uppercase; letter-spacing:.05em; } .word-detail-value { font-size:.95rem; color:var(--text-primary); margin-top:.2rem; } /* Collocation list inside modal */ .coll-list { display:flex; flex-wrap:wrap; gap:.5rem; margin-top:.5rem; } .coll-item { display:inline-flex; flex-direction:column; align-items:center; background:var(--bg-elevated); border:1px solid var(--border); border-radius:var(--radius); padding:.4rem .75rem; } .coll-kanji { font-family:var(--hanzi-font); font-size:1.1rem; color:var(--accent); } .coll-pinyin { font-family:var(--mono-font); font-size:.72rem; color:var(--text-muted); margin-top:.1rem; } /* ── Scrollbar ───────────────────────────────────────────────── */ ::-webkit-scrollbar { width:6px; } ::-webkit-scrollbar-track { background:var(--bg-base); } ::-webkit-scrollbar-thumb { background:var(--border); border-radius:3px; } ::-webkit-scrollbar-thumb:hover { background:var(--text-muted); }