style(flashcards): редизайн — цветные заголовки колод, улучшенные карточки изучения, стат-бар с иконками
This commit is contained in:
+198
-115
@@ -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 => `<div class="fc-stat">
|
||||
<span class="fc-stat-val" style="color:${s.col}">${s.val}</span>
|
||||
<span class="fc-stat-lbl">${s.lbl}</span>
|
||||
{ val: s.decks_count, lbl: 'Колод', col: '#9B5DE5', bg: 'rgba(155,93,229,.1)',
|
||||
icon: '<svg class="ic" viewBox="0 0 24 24"><rect x="3" y="5" width="13" height="15" rx="2"/><path d="M8 5V3.5A1.5 1.5 0 0 1 9.5 2h9A1.5 1.5 0 0 1 20 3.5V16a1.5 1.5 0 0 1-1.5 1.5H16"/></svg>' },
|
||||
{ val: s.cards_count, lbl: 'Карточек', col: '#3B82F6', bg: 'rgba(59,130,246,.1)',
|
||||
icon: '<svg class="ic" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>' },
|
||||
{ val: s.due_count, lbl: 'К повторению', col: '#D97706', bg: 'rgba(217,119,6,.1)',
|
||||
icon: '<svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>' },
|
||||
{ val: s.reviewed_today, lbl: 'Сегодня', col: '#16A34A', bg: 'rgba(22,163,74,.1)',
|
||||
icon: '<svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>' },
|
||||
].map(x => `<div class="fc-stat" style="--stat-color:${x.col};--stat-bg:${x.bg}">
|
||||
<div class="fc-stat-icon">${x.icon}</div>
|
||||
<span class="fc-stat-val">${x.val}</span>
|
||||
<span class="fc-stat-lbl">${x.lbl}</span>
|
||||
</div>`).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
|
||||
? `<span class="deck-badge due"><svg class="ic" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg> ${due} к повторению</span>`
|
||||
: `<span class="deck-badge zero"><svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg> Актуально</span>`;
|
||||
return `<div class="deck-card">
|
||||
<div class="deck-stripe" style="background:${d.color}"></div>
|
||||
? `<span class="deck-badge due"><svg class="ic" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>${due} к повторению</span>`
|
||||
: `<span class="deck-badge zero"><svg class="ic" viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>Актуально</span>`;
|
||||
return `<div class="deck-card" style="--dc-shadow:${shadow}">
|
||||
<div class="deck-head" style="background:${color}" onclick="openDeck(${d.id})">
|
||||
<div class="deck-head-letter">${letter}</div>
|
||||
<span class="deck-head-count">${d.card_count} карт.</span>
|
||||
</div>
|
||||
<div class="deck-body" onclick="openDeck(${d.id})">
|
||||
<div class="deck-name">${esc(d.title)}</div>
|
||||
${d.description ? `<div class="deck-desc">${esc(d.description)}</div>` : ''}
|
||||
<div class="deck-meta">
|
||||
<span class="deck-badge"><svg class="ic" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg> ${d.card_count} карточек</span>
|
||||
${dueHtml}
|
||||
</div>
|
||||
<div class="deck-meta">${dueHtml}</div>
|
||||
</div>
|
||||
<div class="deck-actions">
|
||||
<button class="deck-btn-study" ${due===0&&d.card_count>0?'':''}
|
||||
onclick="openDeckStudy(${d.id})" ${d.card_count===0?'disabled':''}>
|
||||
${due > 0 ? `<svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg> Повторить (${due})` : d.card_count > 0 ? '<svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg> Изучать' : 'Нет карточек'}
|
||||
<button class="deck-btn-study" onclick="openDeckStudy(${d.id})" ${d.card_count===0?'disabled':''}>
|
||||
${due > 0
|
||||
? `<svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg>Повторить (${due})`
|
||||
: d.card_count > 0
|
||||
? `<svg class="ic" viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg>Изучать`
|
||||
: 'Нет карточек'}
|
||||
</button>
|
||||
<button class="deck-btn-edit" onclick="openDeck(${d.id})">
|
||||
<svg class="ic" viewBox="0 0 24 24"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.12 2.12 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
|
||||
</button>
|
||||
<button class="deck-btn-edit" onclick="openDeck(${d.id})"><svg class="ic" viewBox="0 0 24 24"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.12 2.12 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>️</button>
|
||||
</div>
|
||||
</div>`;
|
||||
}).join('') + `<div class="deck-add" onclick="openNewDeckModal()">
|
||||
<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 8v8M8 12h8"/></svg>
|
||||
<svg width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 8v8M8 12h8"/></svg>
|
||||
Новая колода
|
||||
</div>`;
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user