Spaces:
Paused
Paused
| @import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,400;0,500;0,600;0,700;1,400&display=swap'); | |
| @tailwind base; | |
| @tailwind components; | |
| @tailwind utilities; | |
| /* Vue transition helpers */ | |
| @layer components { | |
| .modal-fade-enter-active, | |
| .modal-fade-leave-active { @apply transition-opacity duration-200; } | |
| .modal-fade-enter-from, | |
| .modal-fade-leave-to { @apply opacity-0; } | |
| .modal-enter-active, | |
| .modal-leave-active { @apply transition-opacity duration-150 ease-out; } | |
| .modal-enter-from, | |
| .modal-leave-to { @apply opacity-0; } | |
| .popup-fade-enter-active, | |
| .popup-fade-leave-active { @apply transition-all duration-150; } | |
| .popup-fade-enter-from, | |
| .popup-fade-leave-to { @apply scale-95 opacity-0; } | |
| .dropdown-enter-active, | |
| .dropdown-leave-active { @apply transition-all duration-150 ease-out; } | |
| .dropdown-enter-from, | |
| .dropdown-leave-to { @apply scale-[0.97] opacity-0 -translate-y-1.5; } | |
| .toast-enter-active, | |
| .toast-leave-active { @apply transition-all duration-300 ease-out; } | |
| .toast-enter-from, | |
| .toast-leave-to { @apply translate-x-2 opacity-0; } | |
| .study-fade-enter-active, | |
| .study-fade-leave-active { @apply transition-all duration-200; } | |
| .study-fade-enter-from, | |
| .study-fade-leave-to { @apply scale-[0.97] opacity-0; } | |
| .fade-colors-enter-active, | |
| .fade-colors-leave-active { @apply transition-all duration-200; } | |
| .fade-colors-enter-from, | |
| .fade-colors-leave-to { @apply -translate-x-1.5 opacity-0; } | |
| .slide-right-enter-active, | |
| .slide-right-leave-active { @apply transition-transform duration-[250ms] ease-out; } | |
| .slide-right-enter-from, | |
| .slide-right-leave-to { @apply translate-x-full; } | |
| .slide-x-enter-active, | |
| .slide-x-leave-active { @apply transition-all duration-150; } | |
| .slide-x-enter-from, | |
| .slide-x-leave-to { @apply -translate-x-2 opacity-0; } | |
| } | |
| /* Dynamic HTML highlights (reading / speaking / vocab) */ | |
| @layer components { | |
| .hl-grammar-error { @apply rounded-sm bg-red-200 px-0.5 text-red-900; } | |
| .hl-vocab-weak { @apply rounded-sm bg-yellow-200 px-0.5 text-yellow-900; } | |
| .hl-vocab-strong { @apply rounded-sm bg-green-200 px-0.5 text-green-900; } | |
| .vocab-blank { @apply inline-block min-w-[60px] border-b-2 border-emerald-400; } | |
| /* Gap fill inputs (GapFillingHtml dynamic DOM) */ | |
| .gap-wrapper { @apply inline-flex items-center gap-0.5 align-baseline; } | |
| .gap-num { | |
| @apply inline-flex h-[18px] min-w-[18px] shrink-0 items-center justify-center rounded-full bg-emerald-400 text-[10px] font-bold leading-none text-white align-middle; | |
| } | |
| .gap-input { | |
| @apply inline-block max-w-[160px] min-w-[88px] border-0 border-b-2 border-b-neutral-900 bg-transparent px-1 pb-0.5 pt-px align-baseline font-[inherit] text-sm text-neutral-900 outline-none transition-colors duration-150; | |
| } | |
| .gap-input:focus { @apply border-b-emerald-400; } | |
| .gap-input:disabled { @apply cursor-not-allowed opacity-60; } | |
| } | |
| /* Modal with sliding panel */ | |
| .modal-enter-active .modal-box, | |
| .modal-leave-active .modal-box { @apply transition-transform duration-200; } | |
| .modal-enter-from .modal-box, | |
| .modal-leave-to .modal-box { @apply translate-y-2.5; } | |
| @layer utilities { | |
| .scrollbar-hide { | |
| -ms-overflow-style: none; | |
| scrollbar-width: none; | |
| } | |
| .scrollbar-hide::-webkit-scrollbar { | |
| display: none; | |
| } | |
| } | |
| /* ═══════════════════════════════════════════════════════════ | |
| LinguaIELTS — Spotify-inspired design tokens (DESIGN.md) | |
| ═══════════════════════════════════════════════════════════ */ | |
| :root { | |
| /* §2 Primary brand */ | |
| --spotify-green: #1ed760; | |
| --spotify-green-dark: #1db954; | |
| --bg-base: #121212; | |
| --bg-surface: #181818; | |
| --bg-interactive: #1f1f1f; | |
| /* §2 Text */ | |
| --text-base: #ffffff; | |
| --text-subdued: #b3b3b3; | |
| --text-bright: #cbcbcb; | |
| --text-emphasis: #fdfdfd; | |
| /* §2 Semantic */ | |
| --text-negative: #f3727f; | |
| --text-warning: #ffa42b; | |
| --text-announcement: #539df5; | |
| /* §2 Surface & border */ | |
| --surface-card: #252525; | |
| --surface-card-alt: #272727; | |
| --border-button: #4d4d4d; | |
| --border-outlined: #7c7c7c; | |
| --separator: #b3b3b3; | |
| --surface-light: #eeeeee; | |
| /* §6 Shadows */ | |
| --shadow-heavy: rgba(0, 0, 0, 0.5) 0px 8px 24px; | |
| --shadow-medium: rgba(0, 0, 0, 0.3) 0px 8px 8px; | |
| --shadow-inset-border: rgb(18, 18, 18) 0px 1px 0px, rgb(124, 124, 124) 0px 0px 0px 1px inset; | |
| /* §5 Border radius scale */ | |
| --radius-minimal: 2px; | |
| --radius-subtle: 4px; | |
| --radius-standard: 6px; | |
| --radius-comfortable: 8px; | |
| --radius-panel: 10px; | |
| --radius-large: 100px; | |
| --radius-pill: 500px; | |
| --radius-full-pill: 9999px; | |
| --radius-circle: 50%; | |
| /* §3 Typography scale */ | |
| --text-section-title: 1.5rem; | |
| --text-feature: 1.125rem; | |
| --text-body: 1rem; | |
| --text-button: 0.875rem; | |
| --text-caption: 0.875rem; | |
| --text-small: 0.75rem; | |
| --text-badge: 0.66rem; | |
| --text-micro: 0.625rem; | |
| --tracking-button: 1.4px; | |
| --tracking-button-wide: 2px; | |
| /* §3 Font families — Open Sans */ | |
| --font-title: 'Open Sans', 'Helvetica Neue', helvetica, arial, sans-serif; | |
| --font-body: 'Open Sans', 'Helvetica Neue', helvetica, arial, sans-serif; | |
| --font-mono: 'Consolas', 'Courier New', monospace; | |
| /* Layout */ | |
| --container-max: 1200px; | |
| --navbar-height: 64px; | |
| --section-padding-y: 80px; | |
| --transition-base: 0.2s ease; | |
| /* ── Legacy aliases (keep components working) ── */ | |
| --accent: var(--spotify-green); | |
| --bg: var(--bg-base); | |
| --bg2: var(--bg-interactive); | |
| --surface: var(--bg-surface); | |
| --surface2: var(--surface-card); | |
| --border: var(--border-button); | |
| --border2: var(--border-outlined); | |
| --ink: var(--text-base); | |
| --ink2: var(--text-subdued); | |
| --ink3: var(--text-bright); | |
| --purple: var(--spotify-green); | |
| --purple-l: var(--spotify-green); | |
| --purple-d: var(--spotify-green-dark); | |
| --purple-bg: rgba(30, 215, 96, 0.12); | |
| --green: var(--spotify-green-dark); | |
| --green-l: var(--spotify-green); | |
| --green-bg: rgba(30, 215, 96, 0.12); | |
| --amber: var(--text-warning); | |
| --amber-l: var(--text-warning); | |
| --amber-bg: rgba(255, 164, 43, 0.12); | |
| --blue: var(--text-announcement); | |
| --blue-l: var(--text-announcement); | |
| --blue-bg: rgba(83, 157, 245, 0.12); | |
| --rose: var(--text-negative); | |
| --rose-l: var(--text-negative); | |
| --rose-bg: rgba(243, 114, 127, 0.12); | |
| --violet: var(--spotify-green); | |
| --violet-l: var(--spotify-green); | |
| --violet-bg: rgba(30, 215, 96, 0.12); | |
| --gold: var(--text-warning); | |
| --gold-l: var(--text-warning); | |
| --gold-bg: rgba(255, 164, 43, 0.12); | |
| --shadow-sm: var(--shadow-medium); | |
| --shadow: var(--shadow-medium); | |
| --shadow-lg: var(--shadow-heavy); | |
| --r: var(--radius-comfortable); | |
| --r-sm: var(--radius-standard); | |
| --r-lg: var(--radius-panel); | |
| --font-display: var(--font-title); | |
| /* Semantic surfaces */ | |
| --bubble-assistant-bg: var(--surface-card); | |
| --bubble-user-bg: var(--spotify-green); | |
| --bubble-user-text: #000000; | |
| --header-accent-bg: rgba(30, 215, 96, 0.12); | |
| /* Catbot — aligned with page theme (not inverted) */ | |
| --catbot-header-bg: color-mix(in srgb, var(--spotify-green) 14%, var(--bg-surface)); | |
| --catbot-title-color: var(--text-base); | |
| --catbot-subtitle-color: var(--text-subdued); | |
| --catbot-bubble-assistant-bg: var(--bg-interactive); | |
| --catbot-bubble-assistant-text: var(--text-base); | |
| /* Alternating page sections (dark defaults) */ | |
| --section-white: var(--bg-surface); | |
| --section-cream: var(--bg-interactive); | |
| --section-sky: var(--surface-card); | |
| --hero-bg: var(--bg-interactive); | |
| --hero-heading: var(--text-base); | |
| --hero-subtitle: var(--text-subdued); | |
| --cta-accent: var(--spotify-green); | |
| --cta-accent-text: #000000; | |
| } | |
| /* ─── Light theme ─── */ | |
| [data-theme="light"] { | |
| --bg-base: #f5f5f5; | |
| --bg-surface: #ffffff; | |
| --bg-interactive: #eeeeee; | |
| --text-base: #121212; | |
| --text-subdued: #6a6a6a; | |
| --text-bright: #535353; | |
| --text-emphasis: #000000; | |
| --surface-card: #ffffff; | |
| --surface-card-alt: #fafafa; | |
| --border-button: #e5e7eb; | |
| --border-outlined: #d1d5db; | |
| --separator: #9ca3af; | |
| --shadow-heavy: rgba(0, 0, 0, 0.12) 0px 8px 24px; | |
| --shadow-medium: rgba(0, 0, 0, 0.08) 0px 4px 12px; | |
| --shadow-inset-border: rgb(255, 255, 255) 0px 1px 0px, rgb(209, 213, 219) 0px 0px 0px 1px inset; | |
| --purple-bg: rgba(30, 215, 96, 0.1); | |
| --green-bg: rgba(30, 215, 96, 0.1); | |
| --amber-bg: rgba(255, 164, 43, 0.1); | |
| --blue-bg: rgba(83, 157, 245, 0.1); | |
| --rose-bg: rgba(243, 114, 127, 0.1); | |
| --violet-bg: rgba(30, 215, 96, 0.1); | |
| --gold-bg: rgba(255, 164, 43, 0.1); | |
| --bubble-assistant-bg: #ffffff; | |
| --bubble-user-bg: var(--spotify-green); | |
| --bubble-user-text: #000000; | |
| --header-accent-bg: rgba(30, 215, 96, 0.08); | |
| --catbot-header-bg: color-mix(in srgb, var(--spotify-green) 10%, var(--bg-surface)); | |
| --catbot-title-color: var(--text-base); | |
| --catbot-subtitle-color: var(--text-subdued); | |
| --catbot-bubble-assistant-bg: color-mix(in srgb, var(--spotify-green) 8%, var(--bg-surface)); | |
| --catbot-bubble-assistant-text: var(--text-base); | |
| --section-white: #ffffff; | |
| --section-cream: #eeeeee; | |
| --section-sky: #eeeeee; | |
| --hero-bg: var(--bg-surface); | |
| --hero-heading: var(--text-base); | |
| --hero-subtitle: var(--text-subdued); | |
| --cta-accent: var(--spotify-green); | |
| --cta-accent-text: #000000; | |
| --border-button: #121212; | |
| --border-outlined: #292929; | |
| } | |
| html { | |
| color-scheme: dark; | |
| } | |
| [data-theme="light"] { | |
| color-scheme: light; | |
| } | |
| /* ─── RESET ─── */ | |
| *, *::before, *::after { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| html { font-size: 16px; } | |
| body { | |
| font-family: var(--font-body); | |
| font-size: var(--text-body); | |
| font-weight: 400; | |
| line-height: normal; | |
| background: var(--bg-base); | |
| color: var(--text-base); | |
| min-height: 100vh; | |
| -webkit-font-smoothing: antialiased; | |
| -moz-osx-font-smoothing: grayscale; | |
| } | |
| /* §3 Typography base */ | |
| h1, h2, h3, h4, h5, h6 { | |
| font-family: var(--font-title); | |
| font-weight: 600; | |
| color: var(--text-base); | |
| line-height: normal; | |
| } | |
| [data-theme="light"] h1, | |
| [data-theme="light"] h2, | |
| [data-theme="light"] h3, | |
| [data-theme="light"] h4, | |
| [data-theme="light"] h5, | |
| [data-theme="light"] h6 { | |
| color: var(--text-emphasis); | |
| } | |
| /* Inline page header (no colored hero band) */ | |
| .page-header { | |
| margin-bottom: 1.5rem; | |
| } | |
| .page-header h1 { | |
| font-family: var(--font-display); | |
| font-size: var(--text-section-title); | |
| font-weight: 700; | |
| color: var(--ink); | |
| line-height: normal; | |
| } | |
| .page-header .page-subtitle { | |
| font-size: var(--text-caption); | |
| color: var(--ink2); | |
| margin-top: 4px; | |
| } | |
| .page-header--row { | |
| display: flex; | |
| flex-wrap: wrap; | |
| align-items: flex-end; | |
| gap: 12px; | |
| } | |
| /* Spotify-style unified panels */ | |
| .hub-page { | |
| margin: -16px -16px 0; | |
| width: calc(100% + 32px); | |
| } | |
| @media (min-width: 768px) { | |
| .hub-page { | |
| margin: -24px -24px 0; | |
| width: calc(100% + 48px); | |
| } | |
| } | |
| .spotify-panel { | |
| border-radius: var(--radius-panel); | |
| border: 1px solid var(--border-button); | |
| background: var(--bg-surface); | |
| overflow: hidden; | |
| box-shadow: var(--shadow-medium); | |
| } | |
| .spotify-panel__header { | |
| padding: 20px 24px 16px; | |
| border-bottom: 1px solid var(--border-button); | |
| } | |
| .spotify-panel__tabs { | |
| padding: 12px 20px; | |
| border-bottom: 1px solid var(--border-button); | |
| background: var(--bg-base); | |
| overflow-x: auto; | |
| -webkit-overflow-scrolling: touch; | |
| } | |
| .spotify-panel__tabs > .inline-flex { | |
| min-width: max-content; | |
| } | |
| .spotify-panel__body { | |
| padding: 20px 24px 24px; | |
| background: var(--bg-base); | |
| } | |
| .hub-card-stack { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 12px; | |
| padding: 16px 20px 20px; | |
| } | |
| .stat-pill-inline { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 6px; | |
| border-radius: var(--radius-large); | |
| border: 1px solid var(--border-button); | |
| background: var(--bg-interactive); | |
| padding: 6px 12px; | |
| font-size: 12px; | |
| color: var(--ink2); | |
| } | |
| .stat-pill-inline strong { color: var(--ink); } | |
| h1 { font-size: var(--text-section-title); } | |
| h2 { font-size: var(--text-feature); font-weight: 600; line-height: 1.3; } | |
| h3 { font-size: var(--text-body); font-weight: 700; } | |
| p, li { font-size: var(--text-body); color: var(--text-base); } | |
| small, .text-caption { font-size: var(--text-caption); color: var(--text-subdued); } | |
| a { color: var(--text-subdued); transition: color var(--transition-base); } | |
| a:hover { color: var(--text-base); } | |
| /* ─── SCROLLBAR ─── */ | |
| ::-webkit-scrollbar { width: 6px; height: 6px; } | |
| ::-webkit-scrollbar-track { background: transparent; } | |
| ::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 99px; } | |
| ::-webkit-scrollbar-thumb:hover { background: var(--ink3); } | |
| /* ─── ANIMATIONS ─── */ | |
| @keyframes fadeUp { | |
| from { opacity: 0; transform: translateY(14px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; } | |
| to { opacity: 1; } | |
| } | |
| @keyframes pulse-idle { | |
| 0%, 100% { box-shadow: 0 0 0 0 rgba(224,87,128,0.4); } | |
| 50% { box-shadow: 0 0 0 14px rgba(224,87,128,0); } | |
| } | |
| @keyframes pulse-record { | |
| 0%, 100% { box-shadow: 0 0 0 0 rgba(255,59,59,0.5); } | |
| 50% { box-shadow: 0 0 0 20px rgba(255,59,59,0); } | |
| } | |
| @keyframes waveBar { | |
| 0%, 100% { transform: scaleY(0.3); } | |
| 50% { transform: scaleY(1); } | |
| } | |
| @keyframes slideUp { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| /* ─── PAGE TRANSITION ─── */ | |
| .page-enter-active { animation: fadeUp 0.3s ease both; } | |
| .page-leave-active { animation: fadeIn 0.15s ease reverse both; } | |
| /* ─── FLASHCARD ─── */ | |
| .flashcard-container { | |
| perspective: 1200px; | |
| } | |
| .flashcard-inner { | |
| position: relative; | |
| width: 100%; | |
| height: 100%; | |
| transform-style: preserve-3d; | |
| transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| .flashcard-inner.flipped { | |
| transform: rotateY(180deg); | |
| } | |
| .card-face { | |
| position: absolute; | |
| inset: 0; | |
| backface-visibility: hidden; | |
| -webkit-backface-visibility: hidden; | |
| border-radius: var(--r); | |
| overflow: hidden; | |
| } | |
| .card-back-face { | |
| transform: rotateY(180deg); | |
| } | |
| /* ─── WAVEFORM ─── */ | |
| .waveform-bar { | |
| flex: 1; | |
| border-radius: 2px; | |
| background: rgba(255,255,255,0.2); | |
| transition: background 0.15s; | |
| min-height: 4px; | |
| transform-origin: bottom; | |
| } | |
| .waveform-bar.played { background: var(--green-l); } | |
| .waveform-bar.current { background: white; } | |
| .waveform-bar.playing { | |
| animation: waveBar 0.6s ease-in-out infinite; | |
| } | |
| /* ─── RECORD BUTTON ─── */ | |
| .record-btn-idle { | |
| animation: pulse-idle 2.5s infinite; | |
| } | |
| .record-btn-active { | |
| background: #ff3b3b ; | |
| animation: pulse-record 1s infinite; | |
| } | |
| /* ─── HEATMAP ─── */ | |
| .heatmap-day { | |
| aspect-ratio: 1; | |
| border-radius: 5px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 11px; | |
| font-weight: 500; | |
| cursor: pointer; | |
| transition: transform 0.15s, box-shadow 0.15s; | |
| background: var(--bg2); | |
| color: var(--ink3); | |
| position: relative; | |
| } | |
| .heatmap-day:hover { transform: scale(1.12); z-index: 2; } | |
| .heatmap-day.empty { opacity: 0; pointer-events: none; } | |
| .heatmap-day.today { background: var(--ink); color: white; font-weight: 700; } | |
| .heatmap-day.done-1 { background: #bbf7d0; color: var(--green); } | |
| .heatmap-day.done-2 { background: var(--green-l); color: white; } | |
| .heatmap-day.done-3 { background: var(--green); color: white; } | |
| /* ─── AUDIO CONTROLS ─── */ | |
| .ctrl-btn { | |
| @apply flex h-9 w-9 shrink-0 cursor-pointer items-center justify-center rounded-full border-0 text-[15px] text-white transition-colors; | |
| background: rgba(255,255,255,0.12); | |
| } | |
| .ctrl-btn:hover { background: rgba(255,255,255,0.22); } | |
| .ctrl-btn.play { | |
| @apply h-11 w-11; | |
| background: var(--green-l); | |
| } | |
| .ctrl-btn.play:hover { background: #3da771; } | |
| .transcript-html mark { font-weight: 600; } | |
| /* ─── PROGRESS SHIMMER ─── */ | |
| .progress-fill-shimmer { | |
| @apply relative overflow-hidden; | |
| } | |
| .progress-fill-shimmer::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; left: -100%; | |
| width: 200%; height: 100%; | |
| background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.15) 50%, transparent 100%); | |
| animation: shimmer 2s infinite; | |
| } | |
| @keyframes shimmer { to { left: 100%; } } | |
| /* ─── WORD HIGHLIGHT ─── */ | |
| .hl-yellow { background: #fef08a; border-radius: 2px; } | |
| .hl-green { background: #bbf7d0; border-radius: 2px; } | |
| .hl-rose { background: #fecdd3; border-radius: 2px; } | |
| /* ─── DISPLAY FONT ─── */ | |
| .font-display { font-family: var(--font-display); } | |
| .font-mono { font-family: var(--font-mono); } | |
| /* ─── §4 Cards ─── */ | |
| .ct-card { | |
| background: var(--bg-surface); | |
| border: 1px solid var(--border-button); | |
| border-radius: var(--radius-comfortable); | |
| box-shadow: var(--shadow-medium); | |
| transition: background var(--transition-base), box-shadow var(--transition-base), transform var(--transition-base), border-color var(--transition-base); | |
| } | |
| .ct-card:hover { | |
| background: var(--bg-interactive); | |
| box-shadow: var(--shadow-heavy); | |
| transform: translateY(-2px); | |
| } | |
| /* ─── §4 Badges ─── */ | |
| .ct-badge { | |
| display: inline-flex; | |
| align-items: center; | |
| border-radius: var(--radius-full-pill); | |
| padding: 2px 10px; | |
| font-size: var(--text-badge); | |
| font-weight: 600; | |
| line-height: 1.33; | |
| text-transform: capitalize; | |
| background: rgba(30, 215, 96, 0.15); | |
| color: var(--spotify-green); | |
| } | |
| .ct-badge-black { | |
| background: var(--bg-interactive); | |
| color: var(--text-base); | |
| } | |
| .ct-badge-gray { | |
| background: var(--surface-card); | |
| color: var(--text-subdued); | |
| } | |
| /* ─── §4 Buttons ─── */ | |
| .ct-btn, | |
| .btn, | |
| .sh-btn, | |
| .sh-tab, | |
| .theme-toggle-btn, | |
| .history-filter-btn { | |
| transition: var(--transition-base); | |
| } | |
| .ct-btn { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 6px; | |
| border-radius: var(--radius-full-pill); | |
| padding: 8px 16px; | |
| font-size: var(--text-button); | |
| font-weight: 700; | |
| letter-spacing: 0.14px; | |
| cursor: pointer; | |
| transition: background var(--transition-base), color var(--transition-base), border-color var(--transition-base), transform var(--transition-base); | |
| border: 1px solid transparent; | |
| background: var(--bg-interactive); | |
| color: var(--text-subdued); | |
| } | |
| .ct-btn:hover { | |
| background: var(--surface-card); | |
| color: var(--text-base); | |
| } | |
| .ct-btn-primary { | |
| background: var(--spotify-green); | |
| color: #000000; | |
| border-color: transparent; | |
| text-transform: uppercase; | |
| letter-spacing: var(--tracking-button); | |
| } | |
| .ct-btn-primary:hover { | |
| background: var(--spotify-green-dark); | |
| color: #000000; | |
| transform: scale(1.02); | |
| } | |
| .ct-btn-outline { | |
| background: transparent; | |
| color: var(--text-base); | |
| border: 1px solid var(--border-outlined); | |
| } | |
| .ct-btn-outline:hover { | |
| background: var(--bg-interactive); | |
| border-color: var(--text-base); | |
| } | |
| /* ─── §4 Inputs ─── */ | |
| .ct-input { | |
| border: none; | |
| border-radius: var(--radius-pill); | |
| padding: 12px 20px; | |
| font-size: var(--text-button); | |
| outline: none; | |
| font-family: var(--font-body); | |
| background: var(--bg-interactive); | |
| color: var(--text-base); | |
| box-shadow: var(--shadow-inset-border); | |
| transition: box-shadow var(--transition-base), outline var(--transition-base); | |
| } | |
| .ct-input:focus { | |
| outline: 1px solid var(--text-base); | |
| box-shadow: var(--shadow-inset-border); | |
| } | |
| .ct-input::placeholder { color: var(--text-subdued); } | |
| /* ─── SELECT (SaveWordDialog) ─── */ | |
| .ct-select { | |
| width: 100%; | |
| cursor: pointer; | |
| appearance: none; | |
| border: none; | |
| border-radius: var(--radius-pill); | |
| background: var(--bg-interactive) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23b3b3b3' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 16px center; | |
| padding: 12px 40px 12px 16px; | |
| font-size: var(--text-button); | |
| font-family: inherit; | |
| font-weight: 500; | |
| color: var(--text-base); | |
| outline: none; | |
| box-shadow: var(--shadow-inset-border); | |
| transition: box-shadow var(--transition-base), outline var(--transition-base); | |
| } | |
| .ct-select:focus { outline: 1px solid var(--text-base); } | |
| .ct-select:disabled { cursor: not-allowed; opacity: 0.55; } | |
| /* ─── LEGACY COMPAT: .card, .btn ─── */ | |
| .card { | |
| background: var(--bg-surface); | |
| border: none; | |
| border-radius: var(--radius-comfortable); | |
| box-shadow: var(--shadow-medium); | |
| transition: background var(--transition-base), box-shadow var(--transition-base), transform var(--transition-base); | |
| } | |
| .card:hover { | |
| background: var(--bg-interactive); | |
| box-shadow: var(--shadow-heavy); | |
| } | |
| .btn { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 6px; | |
| border-radius: var(--radius-full-pill); | |
| padding: 8px 16px; | |
| font-size: var(--text-button); | |
| font-weight: 700; | |
| cursor: pointer; | |
| border: 1px solid transparent; | |
| transition: background var(--transition-base), color var(--transition-base), border-color var(--transition-base), transform var(--transition-base); | |
| background: var(--bg-interactive); | |
| color: var(--text-subdued); | |
| } | |
| .btn-primary { | |
| background: var(--spotify-green); | |
| color: #000000; | |
| text-transform: uppercase; | |
| letter-spacing: var(--tracking-button); | |
| } | |
| .btn-primary:hover { | |
| background: var(--spotify-green-dark); | |
| transform: scale(1.02); | |
| } | |
| .btn-secondary { | |
| background: transparent; | |
| color: var(--text-base); | |
| border: 1px solid var(--border-outlined); | |
| } | |
| .btn-secondary:hover { background: var(--bg-interactive); } | |
| .btn-danger { | |
| background: transparent; | |
| color: var(--text-negative); | |
| border: 1px solid var(--text-negative); | |
| } | |
| .btn-danger:hover { background: var(--rose-bg); } | |
| .btn-sm { padding: 5px 12px; font-size: var(--text-small); } | |
| .btn-lg { padding: 12px 32px; font-size: var(--text-body); } | |
| /* ─── PAGE WRAPPER ─── */ | |
| .page-wrapper { | |
| padding: 24px; | |
| } | |
| @media (min-width: 640px) { | |
| .page-wrapper { padding: 32px; } | |
| } | |
| @media (min-width: 1024px) { | |
| .page-wrapper { padding: 40px; } | |
| } | |
| .container { | |
| width: 100%; | |
| max-width: var(--container-max); | |
| margin-left: auto; | |
| margin-right: auto; | |
| padding-left: 24px; | |
| padding-right: 24px; | |
| } | |
| /* Layout shell (DESIGN.md §5) */ | |
| .app-container { | |
| width: 100%; | |
| max-width: var(--container-max); | |
| margin-left: auto; | |
| margin-right: auto; | |
| padding-left: 24px; | |
| padding-right: 24px; | |
| } | |
| .app-navbar { | |
| height: var(--navbar-height); | |
| background: var(--bg-surface); | |
| border-bottom: 1px solid var(--border-button); | |
| } | |
| /* Page sections — alternating surfaces (white → cream → sky in light) */ | |
| .section-base { | |
| padding-top: var(--section-padding-y); | |
| padding-bottom: var(--section-padding-y); | |
| background: var(--bg-base); | |
| } | |
| .section-surface { | |
| padding-top: var(--section-padding-y); | |
| padding-bottom: var(--section-padding-y); | |
| background: var(--bg-surface); | |
| } | |
| .section-elevated { | |
| padding-top: var(--section-padding-y); | |
| padding-bottom: var(--section-padding-y); | |
| background: var(--bg-interactive); | |
| } | |
| .section-white { | |
| padding-top: var(--section-padding-y); | |
| padding-bottom: var(--section-padding-y); | |
| background: var(--section-white); | |
| } | |
| .section-cream { | |
| padding-top: var(--section-padding-y); | |
| padding-bottom: var(--section-padding-y); | |
| background: var(--section-cream); | |
| } | |
| .section-sky { | |
| padding-top: var(--section-padding-y); | |
| padding-bottom: var(--section-padding-y); | |
| background: var(--section-sky); | |
| } | |
| .section-hero { | |
| padding-top: var(--section-padding-y); | |
| padding-bottom: var(--section-padding-y); | |
| background: var(--hero-bg); | |
| color: var(--text-base); | |
| } | |
| .section-hero h1, | |
| .section-hero h2 { | |
| color: var(--text-base); | |
| font-size: var(--text-section-title); | |
| font-weight: 700; | |
| line-height: normal; | |
| } | |
| .section-hero .hero-subtitle { | |
| font-size: var(--text-caption); | |
| color: var(--text-subdued); | |
| margin-top: 4px; | |
| } | |
| .section-hero .btn-primary, | |
| .section-hero .ct-btn-primary, | |
| .section-hero .btn-hero-cta { | |
| background: var(--cta-accent); | |
| color: var(--cta-accent-text); | |
| font-size: var(--text-button); | |
| font-weight: 700; | |
| letter-spacing: var(--tracking-button); | |
| transition: var(--transition-base); | |
| } | |
| .section-hero .btn-primary:hover, | |
| .section-hero .ct-btn-primary:hover, | |
| .section-hero .btn-hero-cta:hover { | |
| filter: brightness(1.06); | |
| } | |
| /* App shells — tighter rhythm than marketing pages */ | |
| .section-compact { | |
| padding-top: 48px; | |
| padding-bottom: 48px; | |
| } | |
| .section-hero.section-compact h1 { | |
| font-size: var(--text-section-title); | |
| } | |
| /* Wave divider between sections */ | |
| .wave-divider { | |
| display: block; | |
| width: 100%; | |
| height: 48px; | |
| line-height: 0; | |
| overflow: hidden; | |
| } | |
| .wave-divider svg { | |
| display: block; | |
| width: 100%; | |
| height: 48px; | |
| } | |
| /* Quiz / practice exam shell — header + body share same horizontal rhythm */ | |
| .exam-container { | |
| width: 100%; | |
| max-width: 1400px; | |
| margin-left: auto; | |
| margin-right: auto; | |
| padding-left: 1.25rem; | |
| padding-right: 1.25rem; | |
| } | |
| @media (min-width: 640px) { | |
| .exam-container { | |
| padding-left: 1.5rem; | |
| padding-right: 1.5rem; | |
| } | |
| } | |
| @media (min-width: 1024px) { | |
| .exam-container { | |
| padding-left: 2rem; | |
| padding-right: 2rem; | |
| } | |
| } | |
| /* ─── SLIDE TRANSITION (Quiz / WritingEditor) ─── */ | |
| .slide-enter-active, .slide-leave-active { transition: all 0.2s ease; } | |
| .slide-enter-from, .slide-leave-to { opacity: 0; transform: translateX(20px); } | |
| /* ─── WRITING PROMPT HTML ─── */ | |
| .writing-prompt-html p { margin-bottom: 0.75rem; font-size: 13px; line-height: 1.65; } | |
| .writing-prompt-html em { font-style: italic; } | |
| .writing-prompt-html strong { font-weight: 600; } | |
| /* ─── READING PASSAGE (vocab / review) ─── */ | |
| .vocab-mode .vocab-word { cursor: pointer; } | |
| .vocab-mode .vocab-underline { | |
| text-decoration: underline; | |
| text-underline-offset: 3px; | |
| text-decoration-color: var(--spotify-green); | |
| color: var(--spotify-green); | |
| } | |
| .answer-mark { | |
| border-radius: 3px; | |
| background: #fef08a; | |
| padding: 1px 2px; | |
| font-weight: 600; | |
| } | |
| /* ─── SKILL SEARCH (Speaking / Reading list) ─── */ | |
| .skill-search-wrap { | |
| position: relative; | |
| align-self: flex-start; | |
| width: 100%; | |
| max-width: 100%; | |
| min-width: 0; | |
| } | |
| @media (min-width: 640px) { | |
| .skill-search-wrap { min-width: 240px; width: auto; } | |
| } | |
| .skill-search-icon { | |
| position: absolute; | |
| top: 50%; | |
| left: 0.75rem; | |
| transform: translateY(-50%); | |
| color: var(--ink3); | |
| pointer-events: none; | |
| } | |
| .skill-search-input { | |
| width: 100%; | |
| border: none; | |
| border-radius: var(--radius-pill); | |
| background: var(--bg-interactive); | |
| padding: 0.5rem 0.75rem 0.5rem 2.1rem; | |
| font-size: var(--text-button); | |
| color: var(--text-base); | |
| outline: none; | |
| box-shadow: var(--shadow-inset-border); | |
| transition: box-shadow var(--transition-base), outline var(--transition-base); | |
| } | |
| .skill-search-input:focus { | |
| outline: 1px solid var(--text-base); | |
| } | |
| .page-wrapper--constrained { | |
| max-width: 1280px; | |
| margin-left: auto; | |
| margin-right: auto; | |
| } | |
| /* ─── AUTH (theme-aware, Spotify tokens) ─── */ | |
| .auth-page { | |
| min-height: 100vh; | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| background: var(--bg-base); | |
| color: var(--text-base); | |
| } | |
| .auth-page--centered { | |
| grid-template-columns: 1fr; | |
| place-items: center; | |
| padding: 24px; | |
| } | |
| .auth-page--centered .auth-card { | |
| max-width: 480px; | |
| width: 100%; | |
| border-right: none; | |
| border: 1px solid var(--border-button); | |
| border-radius: var(--radius-panel); | |
| box-shadow: var(--shadow-medium); | |
| } | |
| .auth-card { | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| align-items: center; | |
| padding: 48px clamp(24px, 5vw, 64px); | |
| background: var(--bg-surface); | |
| border-right: 1px solid var(--border-button); | |
| } | |
| .auth-card > * { | |
| width: 100%; | |
| max-width: 420px; | |
| } | |
| .auth-logo { margin-bottom: 32px; } | |
| .logo-mark { | |
| font-size: 24px; | |
| font-weight: 700; | |
| color: var(--text-base); | |
| letter-spacing: -0.02em; | |
| } | |
| .logo-mark span { color: var(--spotify-green); } | |
| .logo-sub { | |
| font-size: 11px; | |
| color: var(--text-subdued); | |
| letter-spacing: 0.1em; | |
| text-transform: uppercase; | |
| margin-top: 4px; | |
| } | |
| .auth-title { | |
| font-size: 28px; | |
| font-weight: 700; | |
| color: var(--text-base); | |
| margin-bottom: 6px; | |
| } | |
| .auth-sub { | |
| font-size: 14px; | |
| color: var(--text-subdued); | |
| margin-bottom: 28px; | |
| line-height: 1.5; | |
| } | |
| .auth-page .form-group { margin-bottom: 16px; } | |
| .auth-page .form-label { | |
| display: block; | |
| font-size: 12px; | |
| font-weight: 600; | |
| color: var(--text-subdued); | |
| margin-bottom: 6px; | |
| } | |
| .auth-page .form-input, | |
| .auth-page select.form-input { | |
| width: 100%; | |
| padding: 12px 18px; | |
| border: none; | |
| border-radius: var(--radius-comfortable); | |
| font-size: 14px; | |
| font-family: inherit; | |
| color: var(--text-base); | |
| background: var(--bg-interactive); | |
| box-shadow: var(--shadow-inset-border); | |
| outline: none; | |
| transition: box-shadow var(--transition-base), outline var(--transition-base); | |
| } | |
| .auth-page .form-input::placeholder { | |
| color: var(--text-subdued); | |
| } | |
| .auth-page .form-input:focus, | |
| .auth-page select.form-input:focus { | |
| outline: 1px solid var(--spotify-green); | |
| box-shadow: var(--shadow-inset-border); | |
| } | |
| .auth-page .error-msg { | |
| font-size: 13px; | |
| color: var(--text-negative); | |
| background: var(--rose-bg); | |
| padding: 10px 14px; | |
| border-radius: var(--radius-comfortable); | |
| border: 1px solid color-mix(in srgb, var(--text-negative) 25%, transparent); | |
| margin-bottom: 12px; | |
| } | |
| .auth-success-msg, | |
| .auth-page .success-msg { | |
| margin-bottom: 12px; | |
| padding: 10px 14px; | |
| border-radius: var(--radius-comfortable); | |
| border: 1px solid color-mix(in srgb, var(--spotify-green) 35%, transparent); | |
| background: var(--green-bg); | |
| text-align: center; | |
| font-size: 13px; | |
| color: var(--spotify-green-dark); | |
| } | |
| [data-theme="dark"] .auth-success-msg, | |
| [data-theme="dark"] .auth-page .success-msg { | |
| color: var(--spotify-green); | |
| } | |
| .auth-page .btn-primary { | |
| width: 100%; | |
| padding: 12px 24px; | |
| border-radius: var(--radius-full-pill); | |
| background: var(--spotify-green); | |
| color: #000000; | |
| font-size: var(--text-button); | |
| font-weight: 700; | |
| text-transform: uppercase; | |
| letter-spacing: var(--tracking-button); | |
| border: none; | |
| cursor: pointer; | |
| font-family: inherit; | |
| transition: background var(--transition-base), transform var(--transition-base); | |
| margin-top: 4px; | |
| } | |
| .auth-page .btn-primary:hover:not(:disabled) { | |
| background: var(--spotify-green-dark); | |
| transform: scale(1.02); | |
| } | |
| .auth-page .btn-primary:disabled { | |
| opacity: 0.6; | |
| cursor: not-allowed; | |
| transform: none; | |
| } | |
| .auth-google-btn { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 10px; | |
| width: 100%; | |
| padding: 11px 18px; | |
| border: none; | |
| border-radius: var(--radius-full-pill); | |
| background: var(--bg-interactive); | |
| color: var(--text-base); | |
| font-size: 14px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| box-shadow: var(--shadow-inset-border); | |
| transition: box-shadow var(--transition-base), outline var(--transition-base); | |
| margin-bottom: 4px; | |
| } | |
| .auth-google-btn:hover:not(:disabled) { | |
| outline: 1px solid var(--border-outlined); | |
| } | |
| .auth-google-btn:disabled { | |
| opacity: 0.6; | |
| cursor: not-allowed; | |
| } | |
| .auth-divider { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| margin: 16px 0 8px; | |
| color: var(--text-subdued); | |
| font-size: 12px; | |
| } | |
| .auth-divider::before, | |
| .auth-divider::after { | |
| content: ''; | |
| flex: 1; | |
| height: 1px; | |
| background: var(--border-button); | |
| } | |
| .auth-footer { | |
| margin-top: 24px; | |
| font-size: 13px; | |
| color: var(--text-subdued); | |
| text-align: center; | |
| } | |
| .auth-footer--stack { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .auth-link { | |
| color: var(--spotify-green); | |
| font-weight: 600; | |
| text-decoration: none; | |
| margin-left: 4px; | |
| background: none; | |
| border: none; | |
| cursor: pointer; | |
| font-family: inherit; | |
| font-size: inherit; | |
| padding: 0; | |
| } | |
| .auth-link:hover:not(:disabled) { | |
| text-decoration: underline; | |
| } | |
| .auth-link:disabled { | |
| opacity: 0.5; | |
| cursor: not-allowed; | |
| } | |
| .auth-deco { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| padding: 48px clamp(24px, 5vw, 60px); | |
| position: relative; | |
| overflow: hidden; | |
| background: linear-gradient( | |
| 155deg, | |
| color-mix(in srgb, var(--spotify-green) 14%, var(--bg-interactive)) 0%, | |
| var(--bg-base) 55%, | |
| var(--bg-surface) 100% | |
| ); | |
| } | |
| [data-theme="light"] .auth-deco { | |
| background: linear-gradient( | |
| 155deg, | |
| color-mix(in srgb, var(--spotify-green) 18%, var(--bg-interactive)) 0%, | |
| var(--bg-base) 50%, | |
| color-mix(in srgb, var(--spotify-green) 6%, var(--bg-surface)) 100% | |
| ); | |
| } | |
| .auth-deco::before { | |
| content: ''; | |
| position: absolute; | |
| bottom: -80px; | |
| right: -60px; | |
| width: 400px; | |
| height: 400px; | |
| background: radial-gradient(circle, color-mix(in srgb, var(--spotify-green) 22%, transparent) 0%, transparent 70%); | |
| pointer-events: none; | |
| } | |
| .auth-deco::after { | |
| content: ''; | |
| position: absolute; | |
| top: -80px; | |
| left: -60px; | |
| width: 300px; | |
| height: 300px; | |
| background: radial-gradient(circle, color-mix(in srgb, var(--text-announcement) 14%, transparent) 0%, transparent 70%); | |
| pointer-events: none; | |
| } | |
| .deco-content { position: relative; z-index: 1; max-width: 400px; } | |
| .deco-badge { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 6px; | |
| padding: 6px 14px; | |
| border-radius: var(--radius-full-pill); | |
| background: var(--green-bg); | |
| color: var(--spotify-green); | |
| font-size: 12px; | |
| font-weight: 600; | |
| margin-bottom: 20px; | |
| border: 1px solid color-mix(in srgb, var(--spotify-green) 30%, transparent); | |
| } | |
| .deco-title { | |
| font-size: clamp(28px, 4vw, 36px); | |
| font-weight: 700; | |
| color: var(--text-base); | |
| line-height: 1.2; | |
| margin-bottom: 28px; | |
| } | |
| .deco-features { display: flex; flex-direction: column; gap: 12px; } | |
| .deco-feature { | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| font-size: 14px; | |
| color: var(--text-subdued); | |
| } | |
| .feature-check { | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 50%; | |
| background: var(--spotify-green); | |
| color: #000000; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| flex-shrink: 0; | |
| } | |
| .auth-register .auth-card { padding: 40px clamp(24px, 5vw, 56px); } | |
| .auth-register .auth-logo { margin-bottom: 24px; } | |
| .auth-register .auth-title { font-size: 26px; } | |
| .auth-register .auth-sub { font-size: 13px; margin-bottom: 24px; } | |
| .auth-register .form-group { margin-bottom: 14px; } | |
| .auth-register .form-label { margin-bottom: 5px; } | |
| .auth-register .form-input { padding: 11px 16px; font-size: 13px; } | |
| .auth-register .btn-primary { font-size: 14px; } | |
| .auth-register .auth-footer { margin-top: 20px; } | |
| .target-row { display: flex; gap: 12px; } | |
| .milestone-list { display: flex; flex-direction: column; gap: 14px; } | |
| .milestone { display: flex; align-items: center; gap: 12px; } | |
| .milestone-band { | |
| font-size: 16px; | |
| font-weight: 700; | |
| color: var(--spotify-green); | |
| width: 36px; | |
| flex-shrink: 0; | |
| } | |
| .milestone-bar { | |
| flex: 1; | |
| height: 6px; | |
| background: color-mix(in srgb, var(--text-base) 12%, transparent); | |
| border-radius: 99px; | |
| overflow: hidden; | |
| } | |
| .milestone-fill { | |
| height: 100%; | |
| background: linear-gradient(to right, var(--spotify-green), var(--text-announcement)); | |
| border-radius: 99px; | |
| } | |
| .milestone-label { | |
| font-size: 12px; | |
| color: var(--text-subdued); | |
| width: 80px; | |
| } | |
| .auth-verify-icon { | |
| display: flex; | |
| height: 64px; | |
| width: 64px; | |
| align-items: center; | |
| justify-content: center; | |
| border-radius: 50%; | |
| background: var(--green-bg); | |
| border: 1px solid color-mix(in srgb, var(--spotify-green) 40%, transparent); | |
| margin: 0 auto 20px; | |
| } | |
| @media (max-width: 768px) { | |
| .auth-page { grid-template-columns: 1fr; } | |
| .auth-deco { display: none; } | |
| .auth-card { | |
| padding: 40px 24px; | |
| border-right: none; | |
| min-height: 100vh; | |
| } | |
| .target-row { flex-direction: column; gap: 0; } | |
| } | |
| /* ─── HISTORY ─── */ | |
| .history-filter-btn { | |
| display: inline-flex; align-items: center; gap: 5px; | |
| padding: 5px 12px; border-radius: 20px; | |
| border: 1.5px solid var(--border2); | |
| background: var(--surface); color: var(--ink2); | |
| font-size: 12px; font-weight: 500; cursor: pointer; | |
| transition: all .15s; | |
| } | |
| .history-filter-btn:hover { border-color: var(--spotify-green); color: var(--spotify-green); } | |
| .history-filter-btn.active { border-color: var(--spotify-green); background: var(--green-bg); color: var(--spotify-green); font-weight: 700; } | |
| .filter-icon { display: flex; align-items: center; } | |
| .history-action-btn { | |
| display: inline-flex; align-items: center; gap: 5px; | |
| margin-left: 0; white-space: nowrap; | |
| border-radius: var(--r-sm); | |
| border: 1px solid var(--border2); | |
| background: transparent; padding: 6px 12px; | |
| font-size: 12px; font-weight: 600; color: var(--ink2); | |
| cursor: pointer; transition: all .15s; | |
| text-decoration: none; | |
| } | |
| .history-action-btn:hover { background: var(--bg2); } | |
| .history-action-btn--primary { | |
| border-color: var(--spotify-green); | |
| background: var(--bg-surface); | |
| color: var(--spotify-green); | |
| } | |
| .history-action-btn--primary:hover { background: var(--bg-interactive); } | |
| [data-theme="dark"] .history-action-btn--primary { | |
| border-color: var(--border2); | |
| background: var(--bg); | |
| color: var(--spotify-green); | |
| } | |
| @media (min-width: 640px) { | |
| .history-action-btn { margin-left: 8px; } | |
| } | |
| .lb-page { max-width: 700px; margin-left: auto; margin-right: auto; width: 100%; } | |
| .podium { display: flex; align-items: flex-end; justify-content: center; gap: 12px; padding: 0 16px; } | |
| .podium-item { display: flex; flex-direction: column; align-items: center; gap: 6px; flex: 1; max-width: 160px; } | |
| .podium-crown { margin-bottom: -4px; } | |
| .podium-avatar-wrap { position: relative; } | |
| .podium-avatar { width: 56px; height: 56px; border-radius: 50%; object-fit: cover; border: 2px solid var(--border); } | |
| .podium-avatar--large { width: 68px; height: 68px; } | |
| .podium-rank { | |
| position: absolute; bottom: -4px; right: -4px; | |
| width: 20px; height: 20px; border-radius: 50%; | |
| display: flex; align-items: center; justify-content: center; | |
| font-size: 10px; font-weight: 700; color: white; border: 1.5px solid white; | |
| } | |
| .rank-1 { background: #f59e0b; } | |
| .rank-2 { background: #9ca3af; } | |
| .rank-3 { background: #b45309; } | |
| .podium-name { font-size: 12px; font-weight: 500; color: var(--ink); text-align: center; max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } | |
| .podium-xp { font-size: 11px; font-weight: 600; color: var(--ink3); } | |
| .xp-gold { color: #d97706; } | |
| .podium-bar { width: 100%; border-radius: 8px 8px 0 0; } | |
| .bar-1 { height: 64px; background: linear-gradient(180deg, #fde68a, #f59e0b); } | |
| .bar-2 { height: 48px; background: linear-gradient(180deg, #e5e7eb, #9ca3af); } | |
| .bar-3 { height: 36px; background: linear-gradient(180deg, #fde8c8, #b45309); } | |
| .lb-row { display: flex; align-items: center; gap: 12px; border-bottom: 1px solid var(--border); padding: 12px 20px; transition: background 0.15s; } | |
| .lb-row:last-child { border-bottom: none; } | |
| .lb-row:hover { background: var(--bg); } | |
| .lb-row--me { background: var(--green-bg); } | |
| .lb-rank { width: 32px; text-align: right; } | |
| .lb-rank-num { font-size: 14px; font-weight: 700; color: var(--ink3); } | |
| .lb-avatar { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; flex-shrink: 0; } | |
| .lb-info { flex: 1; min-width: 0; } | |
| .lb-name { font-size: 13px; font-weight: 600; color: var(--ink); display: flex; align-items: center; gap: 6px; } | |
| .lb-streak { font-size: 11px; color: var(--ink3); display: flex; align-items: center; gap: 3px; margin-top: 2px; } | |
| .lb-you-badge { font-size: 10px; font-weight: 700; background: #d1fae5; color: #065f46; padding: 1px 6px; border-radius: 20px; } | |
| .lb-xp-col { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; min-width: 100px; } | |
| .lb-xp-bar-wrap { width: 80px; height: 4px; background: var(--bg2); border-radius: 2px; overflow: hidden; } | |
| .lb-xp-bar { height: 100%; background: #34d399; border-radius: 2px; transition: width 0.8s ease; } | |
| .lb-xp-num { font-size: 12px; font-weight: 700; color: var(--ink2); } | |
| /* ─── PROFILE ─── */ | |
| .profile-page { max-width: 900px; margin-left: auto; margin-right: auto; width: 100%; } | |
| .profile-stack { display: flex; flex-direction: column; gap: 14px; } | |
| .profile-grid { display: grid; grid-template-columns: 1fr 1.4fr; gap: 20px; } | |
| @media (max-width: 767px) { | |
| .profile-grid { grid-template-columns: 1fr; } | |
| .profile-page .form-row { grid-template-columns: 1fr; } | |
| .stats-row { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; } | |
| .profile-card { padding: 20px; } | |
| } | |
| .profile-page .card { | |
| background: var(--surface); | |
| border: 1px solid var(--border); | |
| border-radius: var(--r); | |
| box-shadow: var(--shadow-sm); | |
| } | |
| .profile-card { padding: 28px; } | |
| .avatar-section { display: flex; align-items: center; gap: 16px; margin-bottom: 16px; } | |
| .avatar-wrapper { position: relative; width: 72px; height: 72px; border-radius: 50%; flex-shrink: 0; } | |
| .avatar-img { width: 72px; height: 72px; border-radius: 50%; object-fit: cover; display: block; } | |
| .avatar-upload-overlay { | |
| position: absolute; inset: 0; border-radius: 50%; | |
| background: rgba(0, 0, 0, 0.45); | |
| display: flex; align-items: center; justify-content: center; | |
| color: white; opacity: 0; cursor: pointer; transition: opacity 0.18s; | |
| } | |
| .avatar-wrapper:hover .avatar-upload-overlay { opacity: 1; } | |
| .upload-status { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ink3); margin-bottom: 8px; } | |
| .user-name { font-size: 18px; font-weight: 600; color: var(--ink); } | |
| .user-email { font-size: 13px; color: var(--ink3); margin-top: 2px; } | |
| .user-level-badge { margin-top: 6px; font-size: 11px; font-weight: 600; color: var(--green); display: flex; align-items: center; gap: 4px; } | |
| .stats-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; padding-top: 20px; border-top: 1px solid var(--border); margin-top: 16px; } | |
| .stat-box { text-align: center; } | |
| .stat-val { font-size: 24px; font-weight: 700; color: var(--ink); } | |
| .stat-label { font-size: 11px; color: var(--ink3); margin-top: 2px; } | |
| .profile-page .section-title { font-size: 16px; font-weight: 600; color: var(--ink); } | |
| .profile-page .form-group { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; } | |
| .profile-page .form-label { font-size: 12px; font-weight: 600; color: var(--ink2); } | |
| .profile-page .form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; } | |
| .profile-page .form-input { | |
| padding: 9px 12px; border: 1.5px solid var(--border2); border-radius: var(--r-sm); | |
| font-size: 13px; font-family: inherit; color: var(--ink); background: var(--bg); | |
| outline: none; transition: border-color 0.18s; | |
| } | |
| .profile-page .form-input:focus { border-color: var(--green-l); } | |
| .profile-page .form-input:disabled { opacity: 0.5; cursor: not-allowed; } | |
| .profile-page .form-actions { display: flex; justify-content: space-between; margin-top: 20px; } | |
| .profile-page .btn-primary { | |
| padding: 9px 20px; border-radius: var(--r-sm); background: var(--green); color: white; | |
| font-size: 13px; font-weight: 600; border: none; cursor: pointer; font-family: inherit; transition: all 0.18s; | |
| } | |
| .profile-page .btn-primary:hover { background: var(--spotify-green-dark); } | |
| .profile-page .btn-primary:disabled { opacity: 0.6; cursor: not-allowed; } | |
| .profile-page .btn-danger { | |
| padding: 9px 20px; border-radius: var(--r-sm); background: transparent; color: var(--rose); | |
| font-size: 13px; font-weight: 600; border: 1px solid var(--rose-l); cursor: pointer; font-family: inherit; transition: all 0.18s; | |
| } | |
| .profile-page .btn-danger:hover { background: var(--rose-bg); } | |
| .profile-page .error-msg { margin-top: 10px; font-size: 13px; color: var(--rose); } | |
| .profile-page .success-msg { margin-top: 10px; font-size: 13px; color: var(--green); } | |
| .avatar-info { flex: 1; min-width: 0; } | |
| .profile-page .badges-section { padding: 24px; } | |
| .profile-password-card { padding: 24px; } | |
| .profile-ai-hint { | |
| margin: 0 0 16px; | |
| font-size: 12px; | |
| line-height: 1.55; | |
| color: var(--ink3); | |
| } | |
| .profile-ai-note { | |
| margin: -8px 0 12px; | |
| font-size: 11px; | |
| color: var(--ink3); | |
| } | |
| .profile-page .badges-header { | |
| display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; | |
| gap: 16px; margin-bottom: 16px; | |
| } | |
| .profile-page .badges-subtitle { margin: 4px 0 0; font-size: 12px; color: var(--ink3); max-width: 420px; } | |
| .profile-page .badges-progress-wrap { min-width: 160px; flex: 0 0 auto; } | |
| .profile-page .badges-progress-label { | |
| display: flex; justify-content: space-between; gap: 8px; | |
| font-size: 12px; font-weight: 600; margin-bottom: 6px; | |
| } | |
| .profile-page .badges-progress-bar { | |
| height: 8px; border-radius: 999px; background: var(--border); overflow: hidden; | |
| } | |
| .profile-page .badges-progress-fill { | |
| height: 100%; border-radius: inherit; | |
| background: linear-gradient(90deg, var(--spotify-green), var(--spotify-green-dark)); | |
| transition: width 0.4s ease; | |
| } | |
| .profile-page .badges-filters { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; } | |
| .profile-page .badges-filter-btn { | |
| padding: 6px 12px; border-radius: 999px; border: 1px solid var(--border); | |
| background: var(--bg-surface); font-size: 12px; font-weight: 600; color: var(--ink2); | |
| cursor: pointer; font-family: inherit; transition: var(--transition-base); | |
| } | |
| .profile-page .badges-filter-btn:hover { border-color: var(--spotify-green); color: var(--ink); } | |
| .profile-page .badges-filter-btn.active { | |
| background: var(--green-bg); border-color: var(--spotify-green); color: var(--spotify-green); | |
| } | |
| .profile-page .badges-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); | |
| gap: 12px; | |
| } | |
| .profile-page .badge-card { | |
| display: flex; align-items: flex-start; gap: 12px; | |
| padding: 14px; border-radius: 14px; border: 1px solid var(--border); | |
| background: var(--bg-surface); position: relative; transition: transform var(--transition-base), box-shadow var(--transition-base); | |
| cursor: pointer; font-family: inherit; text-align: left; width: 100%; | |
| } | |
| .badge-hint-overlay { | |
| position: fixed; inset: 0; z-index: 9000; | |
| display: flex; align-items: center; justify-content: center; | |
| padding: 20px; background: rgba(15, 23, 42, 0.45); | |
| } | |
| .badge-hint-popover { | |
| width: min(100%, 380px); padding: 24px; background: #fff; | |
| border-radius: 16px; box-shadow: 0 20px 50px rgba(15, 23, 42, 0.18); text-align: center; | |
| } | |
| .badge-hint-icon { margin-bottom: 12px; display: flex; justify-content: center; } | |
| .badge-hint-title { margin: 0 0 6px; font-size: 18px; color: var(--ink); } | |
| .badge-hint-desc { margin: 0 0 14px; font-size: 13px; color: var(--ink3); } | |
| .badge-hint-box { | |
| text-align: left; padding: 12px 14px; border-radius: 10px; | |
| background: var(--bg); border: 1px solid var(--border); font-size: 12px; line-height: 1.5; color: var(--ink2); | |
| } | |
| .badge-hint-label { | |
| display: block; font-size: 10px; font-weight: 700; text-transform: uppercase; | |
| letter-spacing: 0.08em; color: var(--ink3); margin-bottom: 6px; | |
| } | |
| .badge-hint-status { margin: 12px 0 0; font-size: 12px; font-weight: 600; color: var(--ink3); } | |
| .badge-hint-status--done { color: #059669; } | |
| .profile-page .badge-card--unlocked { | |
| border-color: var(--spotify-green); background: linear-gradient(145deg, var(--green-bg) 0%, var(--bg-surface) 55%); | |
| box-shadow: var(--shadow-sm); | |
| } | |
| .profile-page .badge-card--unlocked:hover { transform: translateY(-2px); } | |
| .profile-page .badge-card--locked { opacity: 0.72; filter: grayscale(0.35); } | |
| .profile-page .badge-card-icon { font-size: 28px; line-height: 1; flex-shrink: 0; } | |
| .profile-page .badge-card-body { flex: 1; min-width: 0; } | |
| .profile-page .badge-card-title { font-size: 13px; font-weight: 700; color: var(--ink); margin-bottom: 4px; } | |
| .profile-page .badge-card-desc { font-size: 11px; line-height: 1.45; color: var(--ink3); } | |
| .profile-page .badge-card-check { | |
| position: absolute; top: 10px; right: 10px; | |
| width: 20px; height: 20px; border-radius: 50%; | |
| background: var(--spotify-green); color: #000; font-size: 11px; font-weight: 700; | |
| display: flex; align-items: center; justify-content: center; | |
| } | |
| .profile-page .badge-card-lock { | |
| position: absolute; top: 10px; right: 10px; font-size: 12px; opacity: 0.5; | |
| } | |
| /* ─── QUIZ (legacy Quiz.vue) ─── */ | |
| .quiz-header { margin-bottom: 1.5rem; } | |
| .quiz-back-link { font-size: 0.9rem; color: var(--color-text-muted); text-decoration: none; display: inline-block; margin-bottom: 1rem; } | |
| .quiz-back-link:hover { color: var(--color-primary); } | |
| .quiz-subject { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.5rem; } | |
| .quiz-subject h1 { margin: 0; } | |
| .quiz-progress-top { margin-bottom: 1.5rem; } | |
| .quiz-progress-text { font-size: 0.82rem; display: block; margin-top: 6px; text-align: right; } | |
| .quiz-question-card { padding: 2rem; } | |
| .quiz-question-num { font-size: 0.8rem; font-weight: 600; color: var(--color-primary); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 1rem; } | |
| .quiz-question-text { font-size: 1.2rem; font-weight: 700; line-height: 1.5; margin-bottom: 1.75rem; } | |
| .quiz-options-list { display: flex; flex-direction: column; gap: 0.75rem; } | |
| .quiz-option-btn { | |
| display: flex; align-items: center; gap: 1rem; | |
| padding: 1rem 1.25rem; width: 100%; | |
| background: var(--color-surface-2); border: 2px solid var(--color-border); | |
| border-radius: var(--radius-md); cursor: pointer; | |
| text-align: left; color: var(--color-text); | |
| font-family: inherit; font-size: 0.95rem; | |
| transition: all var(--transition-fast); | |
| } | |
| .quiz-option-btn:hover { border-color: var(--color-primary); background: rgba(124,106,247,0.08); } | |
| .quiz-option-btn.selected { border-color: var(--color-primary); background: rgba(124,106,247,0.15); } | |
| .quiz-option-letter { | |
| width: 32px; height: 32px; border-radius: 50%; | |
| background: var(--color-surface); border: 2px solid var(--color-border); | |
| display: flex; align-items: center; justify-content: center; | |
| font-weight: 700; font-size: 0.85rem; flex-shrink: 0; | |
| transition: all var(--transition-fast); | |
| } | |
| .quiz-option-btn.selected .quiz-option-letter { background: var(--color-primary); border-color: var(--color-primary); color: #fff; } | |
| .quiz-nav { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-top: 1.5rem; } | |
| .quiz-dot-indicators { display: flex; gap: 6px; } | |
| .quiz-dot { | |
| width: 10px; height: 10px; border-radius: 50%; | |
| background: var(--color-surface-2); border: 2px solid var(--color-border); | |
| cursor: pointer; transition: all 0.2s; padding: 0; | |
| } | |
| .quiz-dot.answered { background: rgba(124,106,247,0.4); border-color: var(--color-primary); } | |
| .quiz-dot.active { background: var(--color-primary); border-color: var(--color-primary); transform: scale(1.3); } | |
| /* ─── QUIZ RUNNER reading panel ─── */ | |
| .quiz-runner .reading-passage { max-height: 420px; overflow: auto; padding-right: 8px; } | |
| .quiz-runner .reading-paragraph { | |
| display: flex; gap: 10px; padding: 10px 12px; border-radius: 12px; | |
| border: 1px solid transparent; margin-bottom: 10px; background: var(--surface); | |
| } | |
| .quiz-runner .reading-paragraph.is-highlight { border-color: rgba(124, 106, 247, 0.35); background: rgba(124, 106, 247, 0.08); } | |
| .quiz-runner .para-tag { | |
| min-width: 28px; height: 22px; border-radius: 8px; | |
| display: inline-flex; align-items: center; justify-content: center; | |
| font-size: 11px; font-weight: 700; color: var(--ink2); | |
| border: 1px solid var(--border2); background: var(--bg); | |
| } | |
| /* Passage title (parts[].content) — h2/h3 heading above the reading text */ | |
| .passage-title { margin-bottom: 12px; } | |
| .passage-title h1, .passage-title h2, .passage-title h3, | |
| .passage-title h4, .passage-title h5, .passage-title h6 { | |
| font-weight: 700; line-height: 1.4; color: var(--ink); | |
| } | |
| /* GAP_FILLING table styling for quiz content (border from JSON data) */ | |
| .gap-html table, .prose table { | |
| width: 100%; border-collapse: collapse; margin-bottom: 8px; | |
| } | |
| .gap-html td, .gap-html th, .prose td, .prose th { | |
| padding: 6px 10px; border: 1px solid var(--border2); | |
| vertical-align: top; font-size: 13px; | |
| } | |
| .gap-html h4, .prose h4 { text-align: center; font-weight: 700; margin: 4px 0; } | |
| /* --- VOCAB PAGE (Vocabulary.vue) --- */ | |
| /* ── Layout ────────────────────────────────────────────────────────────── */ | |
| .vocab-page { | |
| min-height: 0; | |
| background: transparent; | |
| padding: 0; | |
| } | |
| .vocab-page--sections .vocab-header { | |
| display: none; | |
| } | |
| /* ── Header ──────────────────────────────────────────────────────────── */ | |
| .vocab-header { | |
| display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; | |
| margin-bottom: 24px; | |
| padding: 20px 24px; | |
| background: #fff; border-radius: 16px; | |
| border: 1px solid #e2e8f0; | |
| box-shadow: 0 2px 8px rgba(0,0,0,.04); | |
| } | |
| .vocab-header__title { font-size: 20px; font-weight: 800; color: #0f172a; } | |
| .vocab-header__sub { font-size: 13px; color: #64748b; margin-top: 2px; } | |
| .vocab-header__stats { display: flex; gap: 10px; flex-wrap: wrap; } | |
| .stat-pill { | |
| display: flex; flex-direction: column; align-items: center; | |
| padding: 8px 16px; border-radius: 10px; | |
| border: 1.5px solid #e2e8f0; background: #f8fafc; | |
| min-width: 64px; | |
| } | |
| .stat-pill--green { border-color: #15803d; background: #f0fdf4; } | |
| .stat-pill--amber { border-color: #d97706; background: #fffbeb; } | |
| .stat-num { font-size: 18px; font-weight: 800; color: #0f172a; } | |
| .stat-lbl { font-size: 10px; color: #64748b; text-transform: uppercase; letter-spacing: .06em; margin-top: 1px; } | |
| .stat-pill--green .stat-num { color: #15803d; } | |
| .stat-pill--amber .stat-num { color: #d97706; } | |
| /* ── Main layout ──────────────────────────────────────────────────────── */ | |
| .vocab-layout { display: flex; gap: 20px; align-items: flex-start; } | |
| @media (max-width: 767px) { | |
| .vocab-layout { | |
| flex-direction: column; | |
| gap: 16px; | |
| } | |
| .vocab-sidebar { | |
| width: 100% ; | |
| flex: none ; | |
| } | |
| .vocab-main { | |
| width: 100%; | |
| min-width: 0; | |
| } | |
| .field-grid { grid-template-columns: 1fr ; } | |
| } | |
| .vocab-layout--study { | |
| flex-direction: row; | |
| align-items: stretch; | |
| gap: 0; | |
| } | |
| .vocab-layout--study .vocab-sidebar { | |
| min-width: 180px; | |
| max-width: 50%; | |
| } | |
| .vocab-layout--study .vocab-main { | |
| min-width: 260px; | |
| } | |
| .vocab-layout--resizing { | |
| cursor: col-resize; | |
| user-select: none; | |
| } | |
| .split-handle { | |
| flex-shrink: 0; | |
| width: 10px; | |
| margin: 0 4px; | |
| cursor: col-resize; | |
| border-radius: 6px; | |
| background: transparent; | |
| transition: background 0.15s; | |
| position: relative; | |
| } | |
| .split-handle::after { | |
| content: ''; | |
| position: absolute; | |
| left: 50%; | |
| top: 50%; | |
| transform: translate(-50%, -50%); | |
| width: 3px; | |
| height: 48px; | |
| border-radius: 3px; | |
| background: #e2e8f0; | |
| transition: background 0.15s, height 0.15s; | |
| } | |
| .split-handle:hover::after, | |
| .vocab-layout--resizing .split-handle::after { | |
| background: #15803d; | |
| height: 64px; | |
| } | |
| .vocab-layout--study .topic-list { | |
| max-height: min(520px, calc(100vh - 300px)); | |
| overflow-y: auto; | |
| } | |
| @media (max-width: 768px) { | |
| .vocab-layout--study { | |
| flex-direction: column; | |
| gap: 16px; | |
| } | |
| .vocab-layout--study .split-handle { | |
| display: none; | |
| } | |
| .vocab-layout--study .vocab-sidebar, | |
| .vocab-layout--study .vocab-main { | |
| flex: none ; | |
| width: 100% ; | |
| max-width: none ; | |
| } | |
| } | |
| /* ── Sidebar ──────────────────────────────────────────────────────────── */ | |
| .vocab-sidebar { | |
| width: 240px; flex-shrink: 0; | |
| background: #fff; border-radius: 16px; | |
| border: 1px solid #e2e8f0; | |
| overflow: hidden; | |
| box-shadow: 0 2px 8px rgba(0,0,0,.04); | |
| } | |
| .sidebar-header { | |
| display: flex; align-items: center; justify-content: space-between; | |
| padding: 14px 16px; border-bottom: 1px solid #f1f5f9; | |
| } | |
| .sidebar-title { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: #64748b; } | |
| .sidebar-add-btn { | |
| width: 28px; height: 28px; border-radius: 8px; | |
| border: 1.5px solid #15803d; background: #f0fdf4; color: #15803d; | |
| display: flex; align-items: center; justify-content: center; cursor: pointer; | |
| transition: all .15s; | |
| } | |
| .sidebar-add-btn:hover { background: #15803d; color: #fff; } | |
| .sidebar-loading, .sidebar-empty { padding: 16px; font-size: 13px; color: #94a3b8; text-align: center; line-height: 1.6; } | |
| .sidebar-error { color: #e11d48; display: flex; flex-direction: column; align-items: center; } | |
| .link-btn { background: none; border: none; color: #15803d; cursor: pointer; font-weight: 600; } | |
| .topic-list { padding: 8px; display: flex; flex-direction: column; gap: 2px; } | |
| .topic-item { | |
| display: flex; align-items: center; gap: 4px; | |
| padding: 10px 10px; border-radius: 10px; cursor: pointer; | |
| transition: all .15s; border: 1.5px solid transparent; | |
| } | |
| .topic-item:hover { background: #f8fafc; } | |
| .topic-item.active { background: #f0fdf4; border-color: #15803d; } | |
| .topic-item__body { flex: 1; min-width: 0; } | |
| .topic-item__name { font-size: 13px; font-weight: 600; color: #0f172a; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; } | |
| .topic-item.active .topic-item__name { color: #15803d; } | |
| .topic-item__count { font-size: 10px; color: #94a3b8; margin-top: 1px; display: block; } | |
| .topic-item__menu { flex-shrink: 0; } | |
| .menu-btn { | |
| width: 24px; height: 24px; border-radius: 6px; | |
| background: none; border: none; color: #94a3b8; cursor: pointer; | |
| display: flex; align-items: center; justify-content: center; | |
| opacity: 0; transition: opacity .15s; | |
| } | |
| .topic-item:hover .menu-btn { opacity: 1; } | |
| .menu-btn:hover { background: #f1f5f9; color: #475569; } | |
| /* ── Main panel ─────────────────────────────────────────────────────── */ | |
| .vocab-main { | |
| flex: 1; min-width: 0; | |
| background: #fff; border-radius: 16px; | |
| border: 1px solid #e2e8f0; | |
| overflow: hidden; | |
| box-shadow: 0 2px 8px rgba(0,0,0,.04); | |
| } | |
| .vocab-main--study { | |
| min-height: 420px; | |
| } | |
| .main-header { | |
| display: flex; align-items: center; justify-content: space-between; | |
| padding: 16px 20px; border-bottom: 1px solid #f1f5f9; gap: 12px; | |
| } | |
| .main-title { font-size: 15px; font-weight: 800; color: #0f172a; } | |
| .main-sub { font-size: 12px; color: #94a3b8; margin-top: 2px; } | |
| .main-header-actions { | |
| display: flex; align-items: center; gap: 12px; flex-shrink: 0; flex-wrap: wrap; | |
| } | |
| .word-search-wrap { | |
| position: relative; display: flex; align-items: center; | |
| } | |
| .word-search-icon { | |
| position: absolute; left: 8px; color: #94a3b8; pointer-events: none; | |
| } | |
| .word-search-input { | |
| padding: 7px 28px 7px 26px; | |
| border: 1.5px solid #e2e8f0; | |
| border-radius: 10px; font-size: 12px; | |
| color: #0f172a; background: #f8fafc; | |
| outline: none; width: 160px; | |
| transition: border-color .15s, width .2s; | |
| } | |
| .word-search-input:focus { | |
| border-color: #15803d; width: 200px; | |
| } | |
| .word-search-clear { | |
| position: absolute; right: 6px; | |
| background: none; border: none; cursor: pointer; | |
| color: #94a3b8; display: flex; align-items: center; | |
| padding: 2px; | |
| } | |
| .word-search-clear:hover { color: #0f172a; } | |
| .view-tabs { | |
| display: inline-flex; | |
| gap: 4px; | |
| border-radius: 10px; | |
| border: 1px solid var(--border); | |
| padding: 3px; | |
| background: var(--bg-interactive); | |
| } | |
| .view-tab { | |
| padding: 6px 14px; font-size: 12px; font-weight: 600; border: none; | |
| border-radius: 8px; | |
| background: transparent; | |
| color: var(--ink3); cursor: pointer; | |
| transition: background 0.15s, color 0.15s; | |
| } | |
| .view-tab.active { background: var(--spotify-green); color: #000; } | |
| .add-word-btn { | |
| display: flex; align-items: center; gap: 6px; | |
| padding: 8px 16px; background: #15803d; color: #fff; | |
| border: none; border-radius: 10px; font-size: 13px; font-weight: 600; cursor: pointer; | |
| transition: background .15s; | |
| } | |
| .add-word-btn:hover { background: #166534; } | |
| /* ── Word table ──────────────────────────────────────────────────────── */ | |
| .word-table { padding: 0; } | |
| .word-table-head { | |
| display: flex; gap: 0; padding: 0 20px; | |
| border-bottom: 1px solid #f1f5f9; background: #f8fafc; | |
| } | |
| .th { | |
| padding: 10px 8px; | |
| font-size: 10px; font-weight: 700; text-transform: uppercase; | |
| letter-spacing: .06em; color: #94a3b8; | |
| } | |
| .word-row { | |
| display: flex; align-items: center; gap: 0; padding: 0 20px; | |
| border-bottom: 1px solid #f8fafc; transition: background .1s; | |
| } | |
| .word-row:hover { background: #f8fafc; } | |
| .td { padding: 12px 8px; font-size: 13px; color: #374151; } | |
| .word-cell { display: flex; align-items: center; gap: 6px; } | |
| .word-text { font-weight: 700; color: #0f172a; } | |
| .tts-btn { | |
| padding: 3px; background: none; border: none; cursor: pointer; | |
| color: #94a3b8; border-radius: 4px; transition: all .1s; | |
| } | |
| .tts-btn:hover { color: #15803d; background: #f0fdf4; } | |
| .word-phonetic { font-size: 11px; color: #94a3b8; font-style: italic; margin-top: 1px; } | |
| .word-type-pill { | |
| display: inline-block; | |
| margin-top: 3px; padding: 1px 8px; | |
| background: #dcfce7; color: #15803d; | |
| border-radius: 6px; font-size: 10px; font-weight: 600; text-transform: uppercase; | |
| } | |
| .meaning-vi { color: #15803d; font-weight: 600; } | |
| .example-text { color: #64748b; font-size: 12px; font-style: italic; } | |
| .srs-cell { display: flex; flex-direction: column; gap: 2px; font-size: 11px; } | |
| .srs-due { color: #b45309; font-weight: 700; } | |
| .srs-ok { color: #64748b; } | |
| .srs-meta { color: #94a3b8; font-size: 10px; } | |
| .mastery-select { | |
| border: 1.5px solid #e2e8f0; border-radius: 8px; | |
| padding: 4px 8px; font-size: 11px; font-weight: 600; | |
| background: #f8fafc; cursor: pointer; outline: none; | |
| max-width: 100%; | |
| } | |
| .mastery--new { border-color: #e2e8f0; color: #94a3b8; } | |
| .mastery--learning { border-color: #fbbf24; color: #d97706; background: #fffbeb; } | |
| .mastery--mastered { border-color: #15803d; color: #15803d; background: #f0fdf4; } | |
| .row-actions { display: flex; gap: 4px; } | |
| .row-action-btn { | |
| width: 28px; height: 28px; border-radius: 6px; | |
| background: none; border: 1px solid #e2e8f0; cursor: pointer; | |
| display: flex; align-items: center; justify-content: center; | |
| color: #94a3b8; transition: all .15s; | |
| } | |
| .row-action-btn:hover { border-color: #15803d; color: #15803d; background: #f0fdf4; } | |
| .row-action-btn--del:hover { border-color: #e11d48; color: #e11d48; background: #fff1f2; } | |
| /* ── Empty state ─────────────────────────────────────────────────────── */ | |
| .empty-state { | |
| display: flex; flex-direction: column; align-items: center; justify-content: center; | |
| gap: 12px; padding: 60px 20px; text-align: center; | |
| } | |
| .empty-icon { color: #cbd5e1; } | |
| .empty-title { font-size: 14px; font-weight: 600; color: #94a3b8; } | |
| /* ── Modals ───────────────────────────────────────────────────────────── */ | |
| .modal-overlay { | |
| position: fixed; inset: 0; z-index: 10000; | |
| background: rgba(0,0,0,.4); | |
| display: flex; align-items: center; justify-content: center; padding: 16px; | |
| } | |
| .modal-sm { | |
| background: #fff; border-radius: 20px; width: 100%; max-width: 360px; | |
| box-shadow: 0 24px 80px rgba(0,0,0,.18); overflow: hidden; | |
| } | |
| .modal-lg { | |
| background: #fff; border-radius: 20px; width: 100%; max-width: 560px; | |
| box-shadow: 0 24px 80px rgba(0,0,0,.18); overflow: hidden; | |
| } | |
| .modal-sm-header { | |
| display: flex; align-items: center; justify-content: space-between; | |
| padding: 14px 18px; border-bottom: 1px solid #f1f5f9; | |
| font-size: 14px; font-weight: 700; color: #0f172a; | |
| } | |
| .modal-sm-header button { background: none; border: none; cursor: pointer; color: #94a3b8; padding: 4px; border-radius: 6px; } | |
| .modal-sm-header button:hover { background: #f1f5f9; } | |
| .modal-sm-body { padding: 16px 18px; } | |
| .topic-input { | |
| width: 100%; border: 1.5px solid #e2e8f0; border-radius: 10px; | |
| padding: 10px 14px; font-size: 14px; outline: none; font-family: inherit; | |
| } | |
| .topic-input:focus { border-color: #15803d; } | |
| .modal-lg-body { padding: 16px 18px; } | |
| .field-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; } | |
| .field { display: flex; flex-direction: column; gap: 4px; } | |
| .col-span-2 { grid-column: span 2; } | |
| .field label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: #94a3b8; } | |
| .field input, .field textarea { | |
| border: 1.5px solid #e2e8f0; border-radius: 10px; | |
| padding: 8px 12px; font-size: 13px; outline: none; font-family: inherit; resize: vertical; | |
| } | |
| .field input:focus, .field textarea:focus { border-color: #15803d; } | |
| .modal-sm-footer { | |
| display: flex; justify-content: flex-end; gap: 8px; | |
| padding: 12px 18px; border-top: 1px solid #f1f5f9; | |
| } | |
| .btn-cancel { padding: 8px 16px; border: 1px solid #e2e8f0; border-radius: 8px; background: #f8fafc; color: #475569; font-size: 13px; cursor: pointer; } | |
| .btn-green { padding: 8px 20px; background: #15803d; color: #fff; border: none; border-radius: 8px; font-size: 13px; font-weight: 700; cursor: pointer; } | |
| .btn-green:disabled { opacity: .4; cursor: not-allowed; } | |
| /* ── Topic context menu ────────────────────────────────────────────── */ | |
| .topic-ctx-menu { | |
| position: fixed; z-index: 10100; | |
| background: #fff; border: 1px solid #e2e8f0; border-radius: 10px; | |
| padding: 4px; box-shadow: 0 8px 24px rgba(0,0,0,.15); | |
| min-width: 140px; | |
| } | |
| .topic-ctx-menu button { | |
| display: flex; align-items: center; gap: 8px; | |
| width: 100%; padding: 8px 14px; text-align: left; | |
| background: none; border: none; border-radius: 6px; | |
| font-size: 13px; color: #374151; cursor: pointer; | |
| } | |
| .topic-ctx-menu button:hover { background: #f1f5f9; } | |
| .topic-ctx-menu button.danger { color: #e11d48; } | |
| .topic-ctx-menu button.danger:hover { background: #fff1f2; } | |
| /* ── Source badge (Reading / Listening provenance) ─────────────────── */ | |
| .source-badge { | |
| font-size: 9px; font-weight: 700; text-transform: uppercase; | |
| letter-spacing: .05em; padding: 2px 6px; border-radius: 4px; | |
| line-height: 1.4; | |
| } | |
| .source-badge--reading { background: #e0f2fe; color: #0369a1; } | |
| .source-badge--listening { background: #fef3c7; color: #92400e; } | |
| /* ── Transitions ────────────────────────────────────────────────────── */ | |
| .modal-fade-enter-active, .modal-fade-leave-active { transition: opacity .2s; } | |
| .modal-fade-enter-from, .modal-fade-leave-to { opacity: 0; } | |
| .popup-fade-enter-active, .popup-fade-leave-active { transition: opacity .15s, transform .15s; } | |
| .popup-fade-enter-from, .popup-fade-leave-to { opacity: 0; transform: scale(.95); } | |
| /* --- REVIEW ANSWER (ReviewAnswer.vue) --- */ | |
| /* ── Score summary ─────────────────────────────────────────────────── */ | |
| .score-summary { | |
| display: flex; | |
| align-items: center; | |
| gap: 16px; | |
| padding: 14px 18px; | |
| background: var(--bg-surface); | |
| border: 1px solid var(--border); | |
| border-radius: 14px; | |
| margin-bottom: 4px; | |
| flex-wrap: wrap; | |
| } | |
| .score-ring-wrap { | |
| position: relative; | |
| flex-shrink: 0; | |
| width: 80px; height: 80px; | |
| } | |
| .score-ring-label { | |
| position: absolute; inset: 0; | |
| display: flex; flex-direction: column; | |
| align-items: center; justify-content: center; | |
| } | |
| .score-stats { | |
| display: flex; gap: 12px; flex-shrink: 0; | |
| } | |
| .score-stat { | |
| display: flex; flex-direction: column; align-items: center; | |
| gap: 2px; padding: 8px 14px; | |
| border: 1.5px solid var(--border); border-radius: 10px; | |
| background: var(--bg-interactive); min-width: 60px; | |
| } | |
| .score-stat--correct { border-color: var(--spotify-green-dark); background: var(--green-bg); } | |
| .score-stat--wrong { border-color: var(--rose); background: var(--rose-bg); } | |
| .score-stat svg { color: var(--ink3); } | |
| .score-stat--correct svg { color: var(--spotify-green-dark); } | |
| .score-stat--wrong svg { color: var(--rose); } | |
| .score-stat-num { font-size: 20px; font-weight: 800; color: var(--ink); } | |
| .score-stat-lbl { font-size: 10px; color: var(--ink3); text-transform: uppercase; letter-spacing: .05em; } | |
| .score-stat--correct .score-stat-num { color: var(--spotify-green-dark); } | |
| .score-stat--wrong .score-stat-num { color: var(--rose); } | |
| .part-bars { flex: 1; display: flex; flex-direction: column; gap: 8px; min-width: 160px; } | |
| .part-bar-item { display: flex; align-items: center; gap: 10px; } | |
| .part-bar-item--clickable { | |
| cursor: pointer; | |
| padding: 6px 8px; | |
| margin: -6px -8px; | |
| border-radius: 8px; | |
| transition: background 0.15s; | |
| } | |
| .part-bar-item--clickable:hover { background: var(--bg2); } | |
| .part-bar-item--active { | |
| background: var(--green-bg); | |
| outline: 1px solid var(--spotify-green); | |
| } | |
| .part-bar-item--active .part-bar-label { color: var(--spotify-green-dark); } | |
| .part-bar-label { font-size: 11px; font-weight: 600; color: var(--ink3); white-space: nowrap; min-width: 70px; } | |
| .part-bar-track { flex: 1; height: 8px; background: var(--bg-interactive); border-radius: 99px; overflow: hidden; } | |
| .part-bar-fill { height: 100%; border-radius: 99px; transition: width 1s ease; } | |
| .part-bar-pct { font-size: 11px; font-weight: 700; color: var(--ink2); min-width: 36px; text-align: right; } | |
| /* ── Header ────────────────────────────────────────────────────────── */ | |
| .review-page-header { | |
| background: color-mix(in srgb, var(--bg-surface) 92%, transparent); | |
| } | |
| .review-back-btn { | |
| display: flex; align-items: center; gap: 6px; | |
| font-size: 12px; color: var(--ink3); background: none; border: none; cursor: pointer; | |
| padding: 6px 10px; border-radius: 8px; transition: all .15s; | |
| } | |
| .review-back-btn:hover { background: var(--bg2); color: var(--ink); } | |
| .review-score-badge { | |
| display: flex; flex-direction: column; align-items: center; | |
| border: 1px solid var(--border); border-radius: 12px; | |
| padding: 6px 16px; background: var(--bg); | |
| } | |
| .review-tools-rail { | |
| position: sticky; | |
| top: 120px; | |
| align-self: flex-start; | |
| } | |
| @media (max-width: 1023px) { | |
| .review-layout { | |
| flex-direction: column ; | |
| } | |
| .review-tools-rail { | |
| position: static; | |
| align-self: stretch; | |
| display: flex; | |
| justify-content: center; | |
| width: 100%; | |
| } | |
| .review-split-left { | |
| width: 100% ; | |
| flex: none ; | |
| } | |
| .review-split-divider { | |
| display: none ; | |
| } | |
| } | |
| /* ── App shell (responsive sidebar) ─────────────────────────────── */ | |
| .app-main--with-sidebar { | |
| margin-left: 0; | |
| } | |
| @media (min-width: 1024px) { | |
| .app-main--with-sidebar.app-main--collapsed { margin-left: 64px; } | |
| .app-main--with-sidebar.app-main--expanded { margin-left: 220px; } | |
| } | |
| .app-main__content { | |
| overflow-x: hidden; | |
| } | |
| /* ── Question cards ──────────────────────────────────────────────── */ | |
| .review-question-card { | |
| border: 1.5px solid var(--border); | |
| border-radius: 12px; overflow: hidden; background: var(--bg-surface); | |
| transition: border-color .15s; | |
| } | |
| .review-question-card--correct { border-left: 4px solid var(--spotify-green); } | |
| .review-question-card--wrong { border-left: 4px solid var(--rose); } | |
| .review-q-header { | |
| display: flex; align-items: center; gap: 8px; | |
| padding: 10px 14px; border-bottom: 1px solid var(--border); | |
| } | |
| .review-q-num { font-size: 11px; font-weight: 700; text-transform: uppercase; color: var(--ink3); letter-spacing: .06em; } | |
| .review-q-badge { | |
| margin-left: auto; | |
| border-radius: 99px; padding: 2px 10px; | |
| font-size: 10px; font-weight: 700; text-transform: uppercase; | |
| } | |
| .badge-correct { background: var(--green-bg); color: var(--spotify-green-dark); } | |
| .badge-wrong { background: var(--rose-bg); color: var(--rose); } | |
| .review-explain-btn { | |
| display: flex; align-items: center; gap: 5px; | |
| padding: 4px 10px; border-radius: 8px; border: 1px solid var(--spotify-green-dark); | |
| background: var(--green-bg); color: var(--spotify-green-dark); font-size: 11px; font-weight: 600; cursor: pointer; | |
| transition: all .15s; | |
| } | |
| .review-explain-btn:hover, .review-explain-btn.active { background: var(--spotify-green); color: #000; } | |
| .review-q-text { | |
| padding: 10px 14px; font-size: 13px; color: var(--ink); line-height: 1.6; | |
| border-bottom: 1px solid var(--border); | |
| } | |
| .review-q-stem { | |
| white-space: pre-wrap; | |
| } | |
| .review-answers { padding: 10px 14px; } | |
| .review-answer-row { | |
| display: flex; align-items: center; justify-content: space-between; gap: 8px; | |
| padding: 4px 0; font-size: 12px; | |
| } | |
| .review-answer-row--border { border-top: 1px solid var(--border); padding-top: 8px; margin-top: 4px; } | |
| .review-answer-label { color: var(--ink3); } | |
| .review-answer-val { font-weight: 700; font-family: monospace; } | |
| .val-correct { color: var(--spotify-green-dark); } | |
| .val-wrong { color: var(--rose); } | |
| /* ── Explanation popup ────────────────────────────────────────────── */ | |
| .explain-overlay { | |
| position: fixed; inset: 0; z-index: 9999; | |
| background: rgba(0,0,0,.55); | |
| display: flex; align-items: flex-start; justify-content: center; | |
| padding: 80px 16px 16px; | |
| } | |
| @media (min-width: 640px) { | |
| .explain-overlay { | |
| justify-content: flex-end; | |
| } | |
| } | |
| .explain-box { | |
| width: min(100%, 460px); max-height: calc(100vh - 100px); | |
| background: var(--bg-surface); border: 1px solid var(--border); border-radius: 20px; | |
| box-shadow: var(--shadow-heavy); | |
| display: flex; flex-direction: column; overflow: hidden; | |
| } | |
| .explain-header { | |
| display: flex; align-items: center; justify-content: space-between; | |
| padding: 14px 18px; border-bottom: 1px solid var(--border); flex-shrink: 0; | |
| background: var(--bg-interactive); | |
| } | |
| .explain-title { font-size: 14px; font-weight: 700; color: var(--ink); } | |
| .explain-goto-btn { | |
| border: 1px solid var(--spotify-green); | |
| background: var(--green-bg); | |
| color: var(--spotify-green-dark); | |
| border-radius: 999px; | |
| font-size: 11px; | |
| font-weight: 700; | |
| padding: 4px 10px; | |
| } | |
| .explain-close { | |
| background: none; border: none; cursor: pointer; | |
| color: var(--ink3); padding: 4px; border-radius: 6px; | |
| } | |
| .explain-close:hover { background: var(--bg2); } | |
| .explain-body { | |
| flex: 1; overflow-y: auto; padding: 16px 18px; | |
| font-size: 13px; line-height: 1.7; color: var(--ink); | |
| } | |
| .explain-body u strong { color: var(--spotify-green-dark); } | |
| .explain-body .list-bullet1 { padding-left: 18px; } | |
| /* ── Shadowing studio (Spotify tokens, dark/light) ──────────────── */ | |
| .shadowing-studio { | |
| --sh-accent: var(--spotify-green); | |
| --sh-accent-dark: var(--spotify-green-dark); | |
| --sh-ink: var(--ink); | |
| --sh-surface: var(--bg-surface); | |
| background-color: var(--bg); | |
| background-image: | |
| linear-gradient(rgba(30, 215, 96, 0.06) 1px, transparent 1px), | |
| linear-gradient(90deg, rgba(30, 215, 96, 0.06) 1px, transparent 1px); | |
| background-size: 24px 24px; | |
| color: var(--sh-ink); | |
| } | |
| .sh-tab { | |
| border-radius: 999px; | |
| padding: 8px 16px; | |
| font-size: 12px; | |
| font-weight: 600; | |
| border: 1px solid var(--border); | |
| background: var(--bg-surface); | |
| color: var(--ink2); | |
| cursor: pointer; | |
| transition: background 0.15s, color 0.15s, border-color 0.15s; | |
| } | |
| .sh-tab:hover { border-color: var(--sh-accent); } | |
| .sh-tab.is-active { | |
| background: var(--sh-accent); | |
| border-color: var(--sh-accent-dark); | |
| color: #000; | |
| } | |
| .sh-btn { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 6px; | |
| border-radius: 10px; | |
| padding: 10px 16px; | |
| font-size: 12px; | |
| font-weight: 700; | |
| cursor: pointer; | |
| border: 1px solid var(--border); | |
| background: var(--bg-surface); | |
| color: var(--ink); | |
| transition: background 0.12s, border-color 0.12s; | |
| } | |
| .sh-btn:hover { background: var(--bg-interactive); } | |
| .sh-btn-primary { | |
| background: var(--sh-accent, var(--spotify-green)); | |
| border-color: var(--sh-accent-dark, var(--spotify-green-dark)); | |
| color: #000000 ; | |
| font-weight: 700; | |
| } | |
| .sh-btn-primary:hover { filter: brightness(1.08); } | |
| .sh-btn-primary:disabled { | |
| opacity: 0.5; | |
| color: #000000 ; | |
| } | |
| .sh-btn-block { width: 100%; } | |
| .sh-card { | |
| border-radius: 14px; | |
| border: 1px solid var(--border); | |
| background: var(--bg-surface); | |
| box-shadow: var(--shadow-sm); | |
| } | |
| .sh-panel-title { | |
| font-size: 11px; | |
| font-weight: 800; | |
| letter-spacing: 0.08em; | |
| text-transform: uppercase; | |
| color: var(--ink3); | |
| } | |
| .sh-transcript-card.is-active { | |
| border-color: var(--sh-accent); | |
| box-shadow: 0 0 0 2px rgba(30, 215, 96, 0.35); | |
| } | |
| .sh-transcript-body { | |
| word-wrap: break-word; | |
| overflow-wrap: break-word; | |
| white-space: normal; | |
| } | |
| .sh-transcript-prose { | |
| display: block; | |
| width: 100%; | |
| text-align: left; | |
| } | |
| .sh-word-chip { | |
| display: inline-block; | |
| border-radius: 8px; | |
| border: 1px solid var(--border); | |
| background: var(--bg-interactive); | |
| padding: 6px 12px; | |
| font-size: 15px; | |
| font-weight: 600; | |
| color: var(--ink); | |
| } | |
| .sh-focus-text { | |
| font-size: clamp(1.25rem, 2.5vw, 1.75rem); | |
| font-weight: 700; | |
| line-height: 1.5; | |
| color: var(--ink); | |
| text-align: center; | |
| word-break: normal; | |
| overflow-wrap: break-word; | |
| } | |
| .sh-focus-text .shadowing-vocab-text.vocab-mode { | |
| justify-content: center; | |
| } | |
| .sh-focus-card { | |
| min-height: 120px; | |
| } | |
| .sh-tab-panel { | |
| min-height: 0; | |
| height: 100%; | |
| width: 100%; | |
| } | |
| .sh-middle-panel { | |
| display: flex; | |
| flex-direction: column; | |
| min-height: 0; | |
| height: 100%; | |
| padding: 16px; | |
| overflow: hidden; | |
| } | |
| .sh-middle-panel > * { | |
| flex: 1; | |
| min-height: 0; | |
| } | |
| .shadowing-transcript { | |
| max-width: none; | |
| } | |
| /* Shadowing studio: 3 cột tỉ lệ 3 : 2 : 3 */ | |
| .sh-studio-grid { | |
| display: flex; | |
| flex-direction: column; | |
| min-height: 0; | |
| } | |
| @media (min-width: 1024px) { | |
| .sh-studio-grid { | |
| display: grid; | |
| grid-template-columns: 3fr 2fr 3fr; | |
| grid-template-rows: minmax(0, 1fr); | |
| align-items: stretch; | |
| } | |
| .sh-studio-grid > * { | |
| min-height: 0; | |
| max-height: 100%; | |
| } | |
| } | |
| .sh-left-col { | |
| display: flex; | |
| flex-direction: column; | |
| min-height: 0; | |
| height: 100%; | |
| max-height: 100%; | |
| overflow: hidden; | |
| } | |
| .sh-left-col-scroll { | |
| box-sizing: border-box; | |
| height: 100%; | |
| max-height: 100%; | |
| min-height: 0; | |
| overflow-x: hidden; | |
| overflow-y: auto; | |
| padding: 12px 14px 16px; | |
| -webkit-overflow-scrolling: touch; | |
| overscroll-behavior: contain; | |
| scrollbar-gutter: stable; | |
| } | |
| .sh-video-meta { | |
| margin-bottom: 12px; | |
| } | |
| .sh-video-title { | |
| margin: 8px 0 0; | |
| font-size: 13px; | |
| font-weight: 700; | |
| line-height: 1.5; | |
| color: #111; | |
| word-wrap: break-word; | |
| overflow-wrap: break-word; | |
| white-space: normal; | |
| } | |
| .sh-video-shell { | |
| position: relative; | |
| width: 100%; | |
| margin-bottom: 14px; | |
| overflow: hidden; | |
| border-radius: 12px; | |
| border: 1px solid var(--border-button); | |
| background: #000; | |
| aspect-ratio: 16 / 9; | |
| min-height: 180px; | |
| z-index: 1; | |
| } | |
| .sh-video-player { | |
| position: absolute; | |
| inset: 0; | |
| width: 100%; | |
| height: 100%; | |
| } | |
| .sh-video-player iframe { | |
| display: block; | |
| width: 100% ; | |
| height: 100% ; | |
| } | |
| .sh-left-controls { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 12px; | |
| } | |
| @media (max-width: 1023px) { | |
| .sh-left-col { | |
| max-height: 50vh; | |
| } | |
| } | |
| .shadowing-studio .sh-middle-panel { | |
| min-width: 0; | |
| max-width: 100%; | |
| } | |
| /* ── Transitions ─────────────────────────────────────────────────── */ | |
| .popup-fade-enter-active, .popup-fade-leave-active { transition: opacity .2s, transform .2s; } | |
| .popup-fade-enter-from, .popup-fade-leave-to { opacity: 0; transform: translateX(20px); } | |
| /* ── Vocab page theme bridge (legacy hex → tokens) ─────────────── */ | |
| .vocab-header, | |
| .vocab-sidebar, | |
| .vocab-main, | |
| .modal-sm, | |
| .modal-lg { | |
| background: var(--bg-surface) ; | |
| border-color: var(--border) ; | |
| } | |
| .vocab-header__title, | |
| .main-title, | |
| .word-text, | |
| .topic-item__name, | |
| .modal-sm-header, | |
| .stat-num { color: var(--ink) ; } | |
| .vocab-header__sub, | |
| .main-sub, | |
| .sidebar-title, | |
| .th, | |
| .topic-item__count, | |
| .field label { color: var(--ink3) ; } | |
| .stat-pill { background: var(--bg-interactive) ; border-color: var(--border) ; } | |
| .stat-pill--green { border-color: var(--spotify-green-dark) ; background: var(--green-bg) ; } | |
| .stat-pill--green .stat-num, | |
| .topic-item.active .topic-item__name, | |
| .meaning-vi, | |
| .link-btn, | |
| .sidebar-add-btn, | |
| .add-word-btn, | |
| .view-tab.active, | |
| .word-type-pill { color: var(--spotify-green-dark) ; } | |
| .sidebar-add-btn, | |
| .topic-item.active, | |
| .mastery--mastered, | |
| .row-action-btn:hover, | |
| .tts-btn:hover { background: var(--green-bg) ; border-color: var(--spotify-green-dark) ; } | |
| .topic-item:hover, | |
| .word-row:hover, | |
| .word-table-head { background: var(--bg-interactive) ; } | |
| .word-search-input, | |
| .view-tab, | |
| .mastery-select, | |
| .topic-input, | |
| .field input, | |
| .field textarea { | |
| background: var(--bg-interactive) ; | |
| border-color: var(--border) ; | |
| color: var(--ink) ; | |
| } | |
| .add-word-btn, | |
| .view-tab.active { background: var(--spotify-green) ; color: #000 ; } | |
| .add-word-btn:hover { background: var(--spotify-green-dark) ; } | |
| /* ═══════════════════════════════════════════════════════════ | |
| Theme-aware utility shim (dark mode remaps legacy Tailwind) | |
| ═══════════════════════════════════════════════════════════ */ | |
| @layer utilities { | |
| [data-theme="light"] .spotify-panel, | |
| [data-theme="light"] .ct-card { | |
| border-color: #121212 ; | |
| border-width: 1.5px; | |
| } | |
| [data-theme="dark"] .bg-white { background-color: var(--bg-surface) ; } | |
| [data-theme="dark"] .ct-card { background-color: var(--bg-surface) ; } | |
| [data-theme="dark"] .bg-slate-50, | |
| [data-theme="dark"] .bg-gray-50 { background-color: var(--bg-interactive) ; } | |
| [data-theme="dark"] .bg-slate-100, | |
| [data-theme="dark"] .bg-gray-100 { background-color: var(--bg-interactive) ; } | |
| [data-theme="dark"] .text-slate-900, | |
| [data-theme="dark"] .text-slate-800, | |
| [data-theme="dark"] .text-slate-700, | |
| [data-theme="dark"] .text-gray-900, | |
| [data-theme="dark"] .text-gray-800, | |
| [data-theme="dark"] .text-gray-700 { color: var(--text-base) ; } | |
| [data-theme="dark"] .text-slate-600, | |
| [data-theme="dark"] .text-slate-500, | |
| [data-theme="dark"] .text-slate-400, | |
| [data-theme="dark"] .text-gray-600, | |
| [data-theme="dark"] .text-gray-500, | |
| [data-theme="dark"] .text-gray-400 { color: var(--text-subdued) ; } | |
| [data-theme="dark"] .border-slate-200, | |
| [data-theme="dark"] .border-slate-100, | |
| [data-theme="dark"] .border-gray-200 { border-color: var(--border-button) ; } | |
| .text-green-700, .text-green-800, .text-emerald-600, .text-emerald-700, .text-emerald-800 { | |
| color: var(--spotify-green) ; | |
| } | |
| [data-theme="dark"] .bg-emerald-50, | |
| [data-theme="dark"] .bg-green-50, | |
| [data-theme="dark"] .bg-green-100 { background-color: var(--green-bg) ; } | |
| [data-theme="dark"] .border-emerald-500, | |
| [data-theme="dark"] .border-emerald-600 { border-color: var(--spotify-green) ; } | |
| [data-theme="dark"] .hover\:bg-emerald-50:hover { background-color: var(--green-bg) ; } | |
| [data-theme="dark"] .hover\:bg-slate-50:hover, | |
| [data-theme="dark"] .hover\:bg-gray-50:hover { background-color: var(--bg-interactive) ; } | |
| [data-theme="dark"] .hover\:bg-slate-100:hover { background-color: var(--surface-card) ; } | |
| } | |
| /* Shared semantic UI blocks */ | |
| .chat-header-accent { background: var(--header-accent-bg); } | |
| .catbot-header { | |
| background: var(--catbot-header-bg) ; | |
| border-color: color-mix(in srgb, var(--spotify-green) 35%, var(--border)) ; | |
| } | |
| .catbot-title { color: var(--catbot-title-color); } | |
| .catbot-subtitle { color: var(--catbot-subtitle-color); } | |
| .catbot-bubble-assistant { | |
| background: var(--catbot-bubble-assistant-bg); | |
| color: var(--catbot-bubble-assistant-text); | |
| box-shadow: var(--shadow-medium); | |
| } | |
| .chat-bubble-assistant { | |
| background: var(--bubble-assistant-bg); | |
| color: var(--text-base); | |
| box-shadow: var(--shadow-medium); | |
| } | |
| .chat-bubble-user { | |
| background: var(--bubble-user-bg); | |
| color: var(--bubble-user-text); | |
| } | |
| .accent-hover:hover { | |
| border-color: var(--spotify-green); | |
| background: var(--green-bg); | |
| } | |
| .theme-toggle-btn { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| width: 36px; | |
| height: 36px; | |
| border-radius: var(--radius-circle); | |
| border: 1px solid var(--border-button); | |
| background: var(--bg-interactive); | |
| color: var(--text-subdued); | |
| cursor: pointer; | |
| transition: background var(--transition-base), color var(--transition-base), border-color var(--transition-base); | |
| } | |
| .theme-toggle-btn:hover { | |
| color: var(--text-base); | |
| border-color: var(--spotify-green); | |
| } | |