From de205a598d5e0ba94bcd8487ccec7493386b8c76 Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Mon, 1 Jun 2026 10:06:06 +0300 Subject: [PATCH] =?UTF-8?q?style(flashcards):=20=D1=80=D0=B5=D0=B4=D0=B8?= =?UTF-8?q?=D0=B7=D0=B0=D0=B9=D0=BD=20=E2=80=94=20=D1=86=D0=B2=D0=B5=D1=82?= =?UTF-8?q?=D0=BD=D1=8B=D0=B5=20=D0=B7=D0=B0=D0=B3=D0=BE=D0=BB=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=BA=D0=BE=D0=BB=D0=BE=D0=B4,=20=D1=83=D0=BB?= =?UTF-8?q?=D1=83=D1=87=D1=88=D0=B5=D0=BD=D0=BD=D1=8B=D0=B5=20=D0=BA=D0=B0?= =?UTF-8?q?=D1=80=D1=82=D0=BE=D1=87=D0=BA=D0=B8=20=D0=B8=D0=B7=D1=83=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F,=20=D1=81=D1=82=D0=B0=D1=82-=D0=B1?= =?UTF-8?q?=D0=B0=D1=80=20=D1=81=20=D0=B8=D0=BA=D0=BE=D0=BD=D0=BA=D0=B0?= =?UTF-8?q?=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/flashcards.html | 313 +++++++++++++++++++++++++-------------- 1 file changed, 198 insertions(+), 115 deletions(-) diff --git a/frontend/flashcards.html b/frontend/flashcards.html index 4bdc33c..b745e23 100644 --- a/frontend/flashcards.html +++ b/frontend/flashcards.html @@ -13,91 +13,134 @@ .fc-wrap { max-width: 1100px; margin: 0 auto; padding: 28px 28px 80px; } /* ── header ── */ - .fc-header { display: flex; align-items: center; gap: 14px; margin-bottom: 28px; } - .fc-back { display: none; background: none; border: 1.5px solid var(--border); - border-radius: 8px; padding: 6px 12px; cursor: pointer; font-size: .82rem; - color: var(--text-2); transition: .15s; } + .fc-header { display: flex; align-items: center; gap: 12px; margin-bottom: 28px; flex-wrap: wrap; } + .fc-back { display: none; background: #fff; border: 1.5px solid var(--border); + border-radius: 10px; padding: 7px 14px; cursor: pointer; font-size: .82rem; + color: var(--text-2); transition: .15s; font-family: 'Manrope', sans-serif; font-weight: 600; } .fc-back:hover { background: var(--surface-2); } .fc-back.visible { display: flex; align-items: center; gap: 6px; } .fc-title { font-family: 'Unbounded', sans-serif; font-size: 1.25rem; font-weight: 800; color: var(--text); flex: 1; } - .fc-btn { padding: 8px 16px; border-radius: 9px; border: none; cursor: pointer; + .fc-btn { padding: 9px 18px; border-radius: 10px; border: none; cursor: pointer; font-family: 'Manrope', sans-serif; font-size: .82rem; font-weight: 700; - transition: .15s; } - .fc-btn-primary { background: var(--violet); color: #fff; } - .fc-btn-primary:hover { filter: brightness(1.12); } - .fc-btn-ghost { background: var(--surface); border: 1.5px solid var(--border); color: var(--text-2); } + transition: .18s; white-space: nowrap; } + .fc-btn-primary { background: var(--violet); color: #fff; + box-shadow: 0 2px 10px rgba(155,93,229,.3); } + .fc-btn-primary:hover { filter: brightness(1.1); transform: translateY(-1px); + box-shadow: 0 4px 16px rgba(155,93,229,.4); } + .fc-btn-ghost { background: #fff; border: 1.5px solid var(--border); color: var(--text-2); } .fc-btn-ghost:hover { background: var(--surface-2); } .fc-btn-danger { background: #FEE2E2; border: 1.5px solid #FECACA; color: #DC2626; } .fc-btn-danger:hover { background: #FECACA; } /* ── stats bar ── */ - .fc-stats { display: flex; gap: 12px; margin-bottom: 24px; flex-wrap: wrap; } - .fc-stat { background: #fff; border: 1.5px solid var(--border); border-radius: 12px; - padding: 12px 18px; display: flex; flex-direction: column; gap: 2px; min-width: 110px; } - .fc-stat-val { font-family: 'Unbounded', sans-serif; font-size: 1.4rem; font-weight: 800; color: var(--violet); } - .fc-stat-lbl { font-size: .72rem; font-weight: 600; color: var(--text-3); text-transform: uppercase; letter-spacing: .04em; } + .fc-stats { display: flex; gap: 12px; margin-bottom: 28px; flex-wrap: wrap; } + .fc-stat { background: #fff; border: 1.5px solid var(--border); border-radius: 14px; + padding: 14px 16px 12px; display: flex; flex-direction: column; gap: 3px; + min-width: 112px; position: relative; overflow: hidden; } + .fc-stat::before { content: ''; position: absolute; top: 0; left: 0; width: 3px; + height: 100%; background: var(--stat-color, var(--violet)); + border-radius: 0 2px 2px 0; } + .fc-stat-icon { width: 28px; height: 28px; border-radius: 8px; + background: var(--stat-bg, rgba(155,93,229,.1)); + display: flex; align-items: center; justify-content: center; + color: var(--stat-color, var(--violet)); margin-bottom: 4px; } + .fc-stat-icon .ic { width: 14px; height: 14px; } + .fc-stat-val { font-family: 'Unbounded', sans-serif; font-size: 1.5rem; font-weight: 800; + color: var(--text); line-height: 1; } + .fc-stat-lbl { font-size: .7rem; font-weight: 600; color: var(--text-3); + text-transform: uppercase; letter-spacing: .04em; } /* ── deck grid ── */ - .deck-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; } - .deck-card { background: #fff; border: 1.5px solid var(--border); border-radius: 16px; - overflow: hidden; cursor: pointer; transition: box-shadow .18s, transform .18s; + .deck-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 18px; } + .deck-card { background: #fff; border: 1.5px solid var(--border); border-radius: 20px; + overflow: hidden; cursor: default; transition: box-shadow .22s, transform .22s; display: flex; flex-direction: column; } - .deck-card:hover { box-shadow: 0 6px 24px rgba(0,0,0,.1); transform: translateY(-2px); } - .deck-stripe { height: 6px; } - .deck-body { padding: 16px 18px 14px; flex: 1; } + .deck-card:hover { box-shadow: 0 10px 32px var(--dc-shadow, rgba(0,0,0,.12)); + transform: translateY(-3px); } + + /* deck colored header */ + .deck-head { height: 80px; display: flex; align-items: center; padding: 0 16px; gap: 12px; + position: relative; overflow: hidden; cursor: pointer; flex-shrink: 0; } + .deck-head::before { content: ''; position: absolute; inset: 0; + background: linear-gradient(135deg, rgba(255,255,255,.2) 0%, rgba(0,0,0,.07) 100%); + pointer-events: none; } + .deck-head::after { content: ''; position: absolute; right: -14px; bottom: -22px; + width: 78px; height: 78px; border-radius: 50%; + background: rgba(255,255,255,.1); pointer-events: none; } + .deck-head-letter { width: 42px; height: 42px; border-radius: 12px; + background: rgba(255,255,255,.3); display: flex; align-items: center; + justify-content: center; font-family: 'Unbounded', sans-serif; + font-size: 1.05rem; font-weight: 800; color: #fff; flex-shrink: 0; + position: relative; z-index: 1; text-shadow: 0 1px 4px rgba(0,0,0,.18); + border: 1px solid rgba(255,255,255,.35); } + .deck-head-count { position: relative; z-index: 1; margin-left: auto; + font-family: 'Manrope', sans-serif; font-size: .7rem; font-weight: 700; + color: rgba(255,255,255,.95); background: rgba(0,0,0,.16); + padding: 3px 10px; border-radius: 20px; } + + .deck-body { padding: 14px 16px 10px; flex: 1; cursor: pointer; } .deck-name { font-family: 'Manrope', sans-serif; font-weight: 700; font-size: .96rem; - color: var(--text); margin-bottom: 5px; } - .deck-desc { font-size: .78rem; color: var(--text-3); margin-bottom: 12px; + color: var(--text); margin-bottom: 4px; } + .deck-desc { font-size: .78rem; color: var(--text-3); margin-bottom: 10px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } - .deck-meta { display: flex; gap: 8px; align-items: center; margin-bottom: 14px; } - .deck-badge { padding: 3px 9px; border-radius: 20px; font-size: .7rem; font-weight: 700; - background: var(--surface-2); color: var(--text-2); } - .deck-badge.due { background: #FEF3C7; color: #D97706; } + .deck-meta { display: flex; gap: 7px; align-items: center; flex-wrap: wrap; } + .deck-badge { padding: 3px 8px; border-radius: 20px; font-size: .68rem; font-weight: 700; + background: var(--surface-2); color: var(--text-2); + display: inline-flex; align-items: center; gap: 4px; } + .deck-badge .ic { width: 11px; height: 11px; } + .deck-badge.due { background: #FEF3C7; color: #D97706; } .deck-badge.zero { background: #DCFCE7; color: #16A34A; } - .deck-actions { display: flex; gap: 8px; padding: 0 18px 14px; } - .deck-btn-study { flex: 1; padding: 7px; border-radius: 8px; border: none; cursor: pointer; + .deck-actions { display: flex; gap: 8px; padding: 10px 16px 14px; } + .deck-btn-study { flex: 1; padding: 8px 10px; border-radius: 10px; border: none; cursor: pointer; background: var(--violet); color: #fff; font-family: 'Manrope', sans-serif; - font-size: .8rem; font-weight: 700; transition: .15s; } - .deck-btn-study:hover { filter: brightness(1.1); } - .deck-btn-study:disabled { background: var(--surface-2); color: var(--text-3); cursor: default; filter: none; } - .deck-btn-edit { padding: 7px 12px; border-radius: 8px; border: 1.5px solid var(--border); + font-size: .8rem; font-weight: 700; transition: .18s; + display: flex; align-items: center; justify-content: center; gap: 6px; } + .deck-btn-study:hover { filter: brightness(1.1); transform: translateY(-1px); } + .deck-btn-study:disabled { background: var(--surface-2); color: var(--text-3); + cursor: default; filter: none; transform: none; } + .deck-btn-edit { padding: 8px 13px; border-radius: 10px; border: 1.5px solid var(--border); cursor: pointer; background: none; color: var(--text-2); + display: flex; align-items: center; justify-content: center; gap: 5px; font-size: .8rem; font-weight: 700; font-family: 'Manrope', sans-serif; transition: .15s; } .deck-btn-edit:hover { background: var(--surface-2); } - /* new deck card */ - .deck-add { border: 2px dashed var(--border); border-radius: 16px; min-height: 140px; + /* new deck add card */ + .deck-add { border: 2px dashed var(--border); border-radius: 20px; min-height: 175px; display: flex; align-items: center; justify-content: center; - cursor: pointer; transition: .15s; flex-direction: column; gap: 8px; - color: var(--text-3); font-size: .84rem; font-weight: 600; } - .deck-add:hover { border-color: var(--violet); color: var(--violet); background: rgba(155,93,229,.04); } - .deck-add svg { opacity: .5; } + cursor: pointer; transition: all .2s; flex-direction: column; gap: 10px; + color: var(--text-3); font-size: .84rem; font-weight: 600; + font-family: 'Manrope', sans-serif; } + .deck-add:hover { border-color: var(--violet); color: var(--violet); + background: rgba(155,93,229,.04); transform: translateY(-2px); } + .deck-add svg { transition: opacity .2s; opacity: .4; } + .deck-add:hover svg { opacity: .9; } /* ── card list (deck detail) ── */ #view-cards { display: none; } .card-list { display: flex; flex-direction: column; gap: 10px; margin-bottom: 24px; } - .card-item { background: #fff; border: 1.5px solid var(--border); border-radius: 12px; - display: flex; gap: 0; overflow: hidden; } + .card-item { background: #fff; border: 1.5px solid var(--border); border-radius: 14px; + display: flex; gap: 0; overflow: hidden; transition: box-shadow .15s; } + .card-item:hover { box-shadow: 0 3px 14px rgba(0,0,0,.07); } .card-item.editing { border-color: var(--violet); } .card-item.dragging { opacity: .45; } .card-item.drag-over-top { box-shadow: inset 0 3px 0 0 var(--violet); } .card-item.drag-over-bottom { box-shadow: inset 0 -3px 0 0 var(--violet); } - .card-drag { display: flex; align-items: center; padding: 0 6px; cursor: grab; + .card-drag { display: flex; align-items: center; padding: 0 8px; cursor: grab; color: var(--text-3); flex-shrink: 0; border-right: 1px solid var(--border); } .card-drag:active { cursor: grabbing; } - .card-drag:hover { color: var(--violet); background: var(--surface-2); } + .card-drag:hover { color: var(--violet); background: rgba(155,93,229,.05); } .card-drag .ic { width: 18px; height: 18px; } .card-side { flex: 1; padding: 12px 14px; min-width: 0; } .card-divider { width: 1px; background: var(--border); flex-shrink: 0; } - .card-side-lbl { font-size: .68rem; font-weight: 700; text-transform: uppercase; - letter-spacing: .06em; color: var(--text-3); margin-bottom: 5px; } + .card-side-lbl { font-size: .66rem; font-weight: 700; text-transform: uppercase; + letter-spacing: .07em; color: var(--violet); margin-bottom: 5px; opacity: .75; } .card-text { font-size: .88rem; color: var(--text); white-space: pre-wrap; } .card-textarea { width: 100%; border: none; outline: none; resize: none; background: transparent; font-family: 'Manrope', sans-serif; font-size: .88rem; color: var(--text); min-height: 48px; line-height: 1.5; padding: 0; } .card-actions { display: flex; flex-direction: column; gap: 0; border-left: 1px solid var(--border); } - .card-act-btn { padding: 0 12px; height: 100%; flex: 1; border: none; background: none; + .card-act-btn { padding: 0 14px; height: 100%; flex: 1; border: none; background: none; cursor: pointer; color: var(--text-3); transition: .15s; display: flex; align-items: center; justify-content: center; } .card-act-btn:hover { background: var(--surface-2); color: var(--text); } @@ -107,7 +150,7 @@ .card-add-input { flex: 1; padding: 10px 14px; border: 1.5px solid var(--border); border-radius: 10px; font-family: 'Manrope', sans-serif; font-size: .88rem; background: #fff; color: var(--text); outline: none; transition: .15s; } - .card-add-input:focus { border-color: var(--violet); } + .card-add-input:focus { border-color: var(--violet); box-shadow: 0 0 0 3px rgba(155,93,229,.1); } /* card search */ .card-search-bar { display: flex; align-items: center; gap: 8px; margin-bottom: 14px; @@ -121,17 +164,18 @@ /* ── study mode ── */ #view-study { display: none; } .study-wrap { max-width: 600px; margin: 0 auto; } - .study-progress-bar { height: 5px; background: var(--surface-2); border-radius: 3px; - margin-bottom: 22px; overflow: hidden; } - .study-progress-fill { height: 100%; background: var(--violet); border-radius: 3px; - transition: width .35s ease; } + .study-progress-bar { height: 6px; background: var(--surface-2); border-radius: 3px; + margin-bottom: 20px; overflow: hidden; } + .study-progress-fill { height: 100%; background: var(--deck-color, var(--violet)); + border-radius: 3px; transition: width .4s ease; } .study-counter { text-align: center; font-size: .8rem; color: var(--text-3); font-weight: 600; margin-bottom: 18px; } - /* card */ - .study-card-scene { perspective: 1000px; height: 260px; margin-bottom: 22px; cursor: pointer; + /* flip card */ + .study-card-scene { perspective: 1200px; height: 320px; margin-bottom: 22px; cursor: pointer; user-select: none; -webkit-user-select: none; } - .study-card-inner { width: 100%; height: 100%; position: relative; transition: transform .5s cubic-bezier(.4,0,.2,1); + .study-card-inner { width: 100%; height: 100%; position: relative; + transition: transform .5s cubic-bezier(.4,0,.2,1); transform-style: preserve-3d; will-change: transform; } .study-card-inner.flipped { transform: rotateY(180deg); } .study-card-inner.swipe-right { animation: swipeRight .4s ease forwards; } @@ -139,18 +183,25 @@ @keyframes swipeRight { to { transform: translateX(110%) rotate(20deg) rotateY(0deg); opacity: 0; } } @keyframes swipeLeft { to { transform: translateX(-110%) rotate(-20deg) rotateY(180deg); opacity: 0; } } - .study-face { position: absolute; inset: 0; border-radius: 18px; padding: 28px 32px; + .study-face { position: absolute; inset: 0; border-radius: 22px; padding: 36px 40px; display: flex; align-items: center; justify-content: center; backface-visibility: hidden; -webkit-backface-visibility: hidden; border: 1.5px solid var(--border); overflow: auto; } - .study-face-front { background: #fff; box-shadow: 0 4px 24px rgba(0,0,0,.08); } - .study-face-back { background: #fff; transform: rotateY(180deg); - box-shadow: 0 4px 24px rgba(0,0,0,.08); } - .study-face-text { font-family: 'Manrope', sans-serif; font-size: 1.15rem; font-weight: 600; - color: var(--text); text-align: center; line-height: 1.6; } - .study-face-label { position: absolute; top: 12px; left: 16px; font-size: .65rem; font-weight: 700; - text-transform: uppercase; letter-spacing: .06em; color: var(--text-3); } - .study-hint { text-align: center; font-size: .77rem; color: var(--text-3); margin-bottom: 20px; } + .study-face-front { background: linear-gradient(170deg, var(--deck-color-a, rgba(155,93,229,.07)) 0%, #fff 38%); + box-shadow: 0 10px 40px rgba(0,0,0,.1), 0 2px 8px rgba(0,0,0,.06); } + .study-face-back { background: linear-gradient(170deg, rgba(246,243,255,.9) 0%, #fff 45%); + transform: rotateY(180deg); + box-shadow: 0 10px 40px rgba(0,0,0,.1), 0 2px 8px rgba(0,0,0,.06); + border-color: rgba(155,93,229,.22); } + .study-face-text { font-family: 'Manrope', sans-serif; font-size: 1.22rem; font-weight: 600; + color: var(--text); text-align: center; line-height: 1.7; } + .study-face-label { position: absolute; top: 14px; left: 18px; font-size: .63rem; font-weight: 700; + text-transform: uppercase; letter-spacing: .08em; + color: var(--deck-color, var(--violet)); + background: var(--deck-color-a, rgba(155,93,229,.1)); + padding: 3px 10px; border-radius: 20px; } + .study-hint { text-align: center; font-size: .77rem; color: var(--text-3); margin-bottom: 20px; + display: flex; align-items: center; justify-content: center; gap: 6px; } /* drag tilt */ .study-card-inner.drag-right { transform: rotate(6deg) translateX(30px); } @@ -159,68 +210,78 @@ /* answer quality buttons */ .study-btns { display: none; gap: 10px; justify-content: center; flex-wrap: wrap; margin-bottom: 24px; } .study-btns.visible { display: flex; } - .sq-btn { padding: 10px 20px; border-radius: 10px; border: 2px solid transparent; + .sq-btn { padding: 11px 20px; border-radius: 12px; border: 2px solid transparent; cursor: pointer; font-family: 'Manrope', sans-serif; font-size: .84rem; font-weight: 700; - transition: .18s; display: flex; flex-direction: column; align-items: center; gap: 2px; } + transition: .18s; display: flex; flex-direction: column; align-items: center; gap: 3px; + box-shadow: 0 2px 8px rgba(0,0,0,.07); } + .sq-btn:hover { transform: translateY(-2px); box-shadow: 0 5px 16px rgba(0,0,0,.1); } + .sq-btn:active { transform: translateY(0); } .sq-btn .sq-top { display: flex; align-items: center; gap: 6px; } - .sq-btn .sq-days { font-size: .66rem; font-weight: 600; opacity: .65; } + .sq-btn .sq-days { font-size: .66rem; font-weight: 600; opacity: .7; } .fc-kbd { font-family: 'Manrope', sans-serif; font-size: .62rem; font-weight: 800; line-height: 1; - padding: 2px 5px; border-radius: 5px; background: rgba(0,0,0,.08); - border: 1px solid rgba(0,0,0,.12); color: inherit; opacity: .8; } + padding: 2px 5px; border-radius: 5px; background: rgba(0,0,0,.09); + border: 1px solid rgba(0,0,0,.13); color: inherit; opacity: .8; } .study-hint .fc-kbd { opacity: .9; } .sq-btn-again { background: #FEE2E2; border-color: #FECACA; color: #DC2626; } - .sq-btn-again:hover { background: #FECACA; } + .sq-btn-again:hover { background: #FECACA; border-color: #FCA5A5; } .sq-btn-hard { background: #FEF3C7; border-color: #FDE68A; color: #D97706; } - .sq-btn-hard:hover { background: #FDE68A; } + .sq-btn-hard:hover { background: #FDE68A; border-color: #FCD34D; } .sq-btn-good { background: #DBEAFE; border-color: #BFDBFE; color: #2563EB; } - .sq-btn-good:hover { background: #BFDBFE; } + .sq-btn-good:hover { background: #BFDBFE; border-color: #93C5FD; } .sq-btn-easy { background: #DCFCE7; border-color: #BBF7D0; color: #16A34A; } - .sq-btn-easy:hover { background: #BBF7D0; } + .sq-btn-easy:hover { background: #BBF7D0; border-color: #86EFAC; } /* swipe indicator */ - .swipe-indicator { position: absolute; top: 18px; font-size: 1.4rem; font-weight: 900; - letter-spacing: .04em; padding: 5px 14px; border-radius: 8px; - opacity: 0; pointer-events: none; transition: opacity .1s; z-index: 10; } + .swipe-indicator { position: absolute; top: 18px; font-size: .9rem; font-weight: 900; + letter-spacing: .04em; padding: 6px 14px; border-radius: 10px; + opacity: 0; pointer-events: none; transition: opacity .1s; z-index: 10; + display: flex; align-items: center; gap: 6px; } .swipe-right-ind { right: 20px; background: #DCFCE7; color: #16A34A; border: 2px solid #BBF7D0; } .swipe-left-ind { left: 20px; background: #FEE2E2; color: #DC2626; border: 2px solid #FECACA; } + .swipe-indicator .ic { width: 15px; height: 15px; } /* finished state */ .study-done { text-align: center; padding: 48px 24px; } - .study-done-icon { font-size: 3rem; margin-bottom: 16px; } + .study-done-icon { margin-bottom: 18px; display: flex; align-items: center; justify-content: center; } + .study-done-icon .ic { width: 56px; height: 56px; color: var(--violet); + filter: drop-shadow(0 4px 14px rgba(155,93,229,.35)); } .study-done h2 { font-family: 'Unbounded', sans-serif; font-size: 1.4rem; font-weight: 800; color: var(--text); margin-bottom: 8px; } .study-done p { color: var(--text-3); font-size: .88rem; margin-bottom: 24px; } .study-session-stats { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; margin-bottom: 28px; } - .ss-stat { background: #fff; border: 1.5px solid var(--border); border-radius: 12px; - padding: 12px 20px; text-align: center; } - .ss-stat-n { font-family: 'Unbounded', sans-serif; font-size: 1.4rem; font-weight: 800; } - .ss-stat-l { font-size: .72rem; color: var(--text-3); font-weight: 600; } + .ss-stat { background: #fff; border: 1.5px solid var(--border); border-radius: 14px; + padding: 14px 22px; text-align: center; } + .ss-stat-n { font-family: 'Unbounded', sans-serif; font-size: 1.5rem; font-weight: 800; } + .ss-stat-l { font-size: .72rem; color: var(--text-3); font-weight: 600; margin-top: 3px; } /* ── modals ── */ .fc-modal { position: fixed; inset: 0; z-index: 300; display: none; align-items: center; justify-content: center; padding: 16px; } .fc-modal.open { display: flex; } - .fc-modal-bg { position: absolute; inset: 0; background: rgba(0,0,0,.45); } - .fc-modal-box { position: relative; z-index: 1; background: #fff; border-radius: 18px; - padding: 28px; width: 100%; max-width: 480px; box-shadow: 0 20px 60px rgba(0,0,0,.18); } + .fc-modal-bg { position: absolute; inset: 0; background: rgba(0,0,0,.45); backdrop-filter: blur(4px); } + .fc-modal-box { position: relative; z-index: 1; background: #fff; border-radius: 20px; + padding: 28px; width: 100%; max-width: 480px; + box-shadow: 0 24px 64px rgba(0,0,0,.18); } .fc-modal-title { font-family: 'Unbounded', sans-serif; font-size: 1rem; font-weight: 800; color: var(--text); margin-bottom: 20px; } .fc-modal-field { margin-bottom: 14px; } - .fc-modal-label { font-size: .75rem; font-weight: 700; color: var(--text-2); - text-transform: uppercase; letter-spacing: .05em; margin-bottom: 5px; } - .fc-modal-input { width: 100%; padding: 9px 12px; border: 1.5px solid var(--border); - border-radius: 9px; font-family: 'Manrope', sans-serif; font-size: .88rem; + .fc-modal-label { font-size: .75rem; font-weight: 700; color: var(--text-2); display: block; + text-transform: uppercase; letter-spacing: .05em; margin-bottom: 6px; } + .fc-modal-input { width: 100%; padding: 10px 14px; border: 1.5px solid var(--border); + border-radius: 10px; font-family: 'Manrope', sans-serif; font-size: .88rem; color: var(--text); outline: none; box-sizing: border-box; transition: .15s; } - .fc-modal-input:focus { border-color: var(--violet); } + .fc-modal-input:focus { border-color: var(--violet); box-shadow: 0 0 0 3px rgba(155,93,229,.1); } .fc-modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 22px; } - .color-picker-row { display: flex; gap: 8px; flex-wrap: wrap; } - .cp-swatch { width: 28px; height: 28px; border-radius: 50%; cursor: pointer; - border: 3px solid transparent; transition: .15s; } - .cp-swatch.active, .cp-swatch:hover { border-color: var(--text); transform: scale(1.15); } + .color-picker-row { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 2px; } + .cp-swatch { width: 30px; height: 30px; border-radius: 50%; cursor: pointer; + border: 3px solid transparent; transition: .18s; } + .cp-swatch.active, .cp-swatch:hover { border-color: var(--text); transform: scale(1.2); + box-shadow: 0 2px 8px rgba(0,0,0,.2); } /* ── empty ── */ .fc-empty { text-align: center; padding: 60px 24px; } - .fc-empty-icon { font-size: 3rem; margin-bottom: 14px; } + .fc-empty-icon { margin-bottom: 14px; display: flex; align-items: center; justify-content: center; } + .fc-empty-icon .ic { width: 48px; height: 48px; color: var(--text-3); } .fc-empty h3 { font-family: 'Unbounded', sans-serif; font-size: 1rem; font-weight: 800; color: var(--text); margin-bottom: 8px; } .fc-empty p { color: var(--text-3); font-size: .84rem; margin-bottom: 22px; } @@ -229,10 +290,10 @@ .fc-wrap { padding: 16px 14px 60px; } .fc-title { font-size: 1rem; } .fc-stats { gap: 8px; } - .fc-stat { min-width: 90px; padding: 10px 12px; } - .fc-stat-val { font-size: 1.1rem; } + .fc-stat { min-width: 92px; padding: 10px 12px; } + .fc-stat-val { font-size: 1.2rem; } .deck-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; } - .study-face { padding: 24px 18px; } + .study-face { padding: 24px 20px; } .sq-btn { padding: 9px 16px; font-size: .8rem; } } @media (max-width: 480px) { @@ -401,6 +462,12 @@ /* ════ Constants & State ════ */ const COLORS = ['#9B5DE5','#EF476F','#FF9F1C','#06D6E0','#22d399','#3B82F6','#F15BB5','#6B7280']; +function _hexAlpha(hex, a) { + const h = (hex || '#9B5DE5').replace('#',''); + const r = parseInt(h.slice(0,2),16), g = parseInt(h.slice(2,4),16), b = parseInt(h.slice(4,6),16); + return `rgba(${r},${g},${b},${a})`; +} + let _decks = []; let _curDeck = null; let _cards = []; @@ -479,13 +546,18 @@ function renderStats(s) { if (!s) return; const bar = document.getElementById('fc-stats-bar'); bar.innerHTML = [ - { val: s.decks_count, lbl: 'Колод', col: '#9B5DE5' }, - { val: s.cards_count, lbl: 'Карточек', col: '#3B82F6' }, - { val: s.due_count, lbl: 'К повторению', col: '#D97706' }, - { val: s.reviewed_today, lbl: 'Сегодня', col: '#16A34A' }, - ].map(s => `
- ${s.val} - ${s.lbl} + { val: s.decks_count, lbl: 'Колод', col: '#9B5DE5', bg: 'rgba(155,93,229,.1)', + icon: '' }, + { val: s.cards_count, lbl: 'Карточек', col: '#3B82F6', bg: 'rgba(59,130,246,.1)', + icon: '' }, + { val: s.due_count, lbl: 'К повторению', col: '#D97706', bg: 'rgba(217,119,6,.1)', + icon: '' }, + { val: s.reviewed_today, lbl: 'Сегодня', col: '#16A34A', bg: 'rgba(22,163,74,.1)', + icon: '' }, + ].map(x => `
+
${x.icon}
+ ${x.val} + ${x.lbl}
`).join(''); } @@ -503,29 +575,37 @@ function renderDecks() { } grid.innerHTML = _decks.map(d => { const due = d.due_count; + const color = d.color || '#9B5DE5'; + const letter = (d.title || '?')[0].toUpperCase(); + const shadow = _hexAlpha(color, .22); const dueHtml = due > 0 - ? ` ${due} к повторению` - : ` Актуально`; - return `
-
+ ? `${due} к повторению` + : `Актуально`; + return `
+
+
${letter}
+ ${d.card_count} карт. +
${esc(d.title)}
${d.description ? `
${esc(d.description)}
` : ''} -
- ${d.card_count} карточек - ${dueHtml} -
+
${dueHtml}
- + -
`; }).join('') + `
- + Новая колода
`; } @@ -777,6 +857,9 @@ async function startStudyForDeck(deckId) { _studyFlipped = false; _sessionStats = { again: 0, hard: 0, good: 0, easy: 0 }; document.getElementById('study-deck-title').textContent = _curDeck.title; + const _dc = _curDeck.color || '#9B5DE5'; + const wrap = document.querySelector('.study-wrap'); + if (wrap) { wrap.style.setProperty('--deck-color', _dc); wrap.style.setProperty('--deck-color-a', _hexAlpha(_dc, .08)); } document.getElementById('study-done').style.display = 'none'; document.getElementById('study-scene').style.display = 'block'; document.getElementById('study-flip-hint').style.display = 'block';