restyle
This commit is contained in:
1 parent
b5b4254d20
commit
834bef915e
10 files changed
+373
-205
No files matched your search
+360
-200
@@ -1,10 +1,89 @@
|
||||
/* JapLearn — мобильный PWA, интервальные повторения (Vanilla + Vite) */
|
||||
/* JapLearn — мобильный PWA, интервальные повторения (Vanilla + Vite).
|
||||
|
||||
Тема перенесена из десктопного приложения JapLearn
|
||||
(/home/micial/projects/rust/jap_learn, Rust + iced 0.14, Theme::GruvboxDark).
|
||||
Значения цветов посчитаны той же математикой, что в iced:
|
||||
palette::Palette::GRUVBOX_DARK + Extended::generate (mix — в linear-light,
|
||||
deviate — в OKLCH), readable() — подбор текста под фон.
|
||||
Геометрия и типографика — из десктопного src/styling.rs:
|
||||
DEFAULT_SPACING = 16 (half 8 / quarter 4), BUTTON_RADIUS = 8,
|
||||
ACCENT_FONT_SIZE = 22, default_text_size = 18, шрифт Noto Sans JP.
|
||||
Плоско: ни одна iced-стиль-функция десктопа не задаёт shadow -> теней нет. */
|
||||
|
||||
/* Локальный Noto Sans JP (variable, 100–900): файл лежит в public/fonts,
|
||||
в проде отдаётся как /fonts/NotoSansJP-VariableFont_wght.ttf. */
|
||||
@font-face {
|
||||
font-family: 'Noto Sans JP';
|
||||
src: url('/fonts/NotoSansJP-VariableFont_wght.ttf') format('truetype');
|
||||
font-weight: 100 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
:root {
|
||||
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
||||
color-scheme: dark;
|
||||
|
||||
/* --- Gruvbox Dark: 4 акцента + фон/текст (Palette::GRUVBOX_DARK) --- */
|
||||
--bg: #282828; /* BG_0 */
|
||||
--fg: #fbf1c7; /* FG0_29 */
|
||||
|
||||
/* Поверхности background.* = deviate(#282828, amount) в OKLCH; полный набор
|
||||
десктопа — .03 / .07 / .1 / .125 / .15 / .175 / .2 (#2f2f2f … #5d5d5d). */
|
||||
--bg-weakest: #2f2f2f; /* .03 — карточки */
|
||||
--bg-weak: #414141; /* .1 — рамки карточек, раскрытые доп. поля */
|
||||
--bg-strong: #4f4f4f; /* .15 — рамки инпутов и rule::default */
|
||||
|
||||
/* secondary.* = mix(deviate(bg, .1/.2/.3), text, .2); это же — «приглушённый»
|
||||
текст десктопа (placeholder у text_input) и фон cta_button */
|
||||
--muted: #908c7c; /* secondary.base */
|
||||
--secondary: #908c7c;
|
||||
--secondary-strong: #9f9b8d;
|
||||
--on-secondary: #1f1e1a;
|
||||
|
||||
/* primary.* : base #458588 (BLUE_4), weak = 0.6*base + 0.4*bg, strong = +0.1 L */
|
||||
--primary: #458588;
|
||||
--primary-weak: #3b6c6e;
|
||||
--primary-strong: #49a8ac;
|
||||
--on-primary: #0a1c1d; /* readable(primary, text) в iced даёт почти чёрный */
|
||||
|
||||
/* success/warning/danger: strong = deviate(base, .1), weak = mix(base, bg, .4) */
|
||||
--success: #98971a; /* GREEN_2 */
|
||||
--success-strong: #7c7900;
|
||||
--on-success: #222102;
|
||||
--warning: #d79921; /* YELLOW_3 */
|
||||
--warning-strong: #b67a00;
|
||||
--on-warning: #342203;
|
||||
--danger: #cc241d; /* RED_1 */
|
||||
--danger-strong: #ff0000; /* deviate(#cc241d, .1) */
|
||||
--on-danger: #fdf9f9;
|
||||
|
||||
/* Текст ошибки: чистый --danger даёт на тёмном фоне контраст 2.4:1,
|
||||
поэтому для текста берём bright red из той же палитры gruvbox (red_1). */
|
||||
--danger-text: #fb4934;
|
||||
|
||||
/* Приглушённый текст = iced text.scale_alpha(...) */
|
||||
--fg-soft: rgb(251 241 199 / 0.85);
|
||||
--fg-faint: rgb(251 241 199 / 0.3);
|
||||
/* Оверлей кнопок-строк: iced nav_style -> WHITE.scale_alpha(0.1) */
|
||||
--surface-press: rgb(255 255 255 / 0.1);
|
||||
--surface-press-soft: rgb(255 255 255 / 0.08);
|
||||
|
||||
/* --- Геометрия (styling.rs) --- */
|
||||
--space: 16px;
|
||||
--space-half: 8px;
|
||||
--space-quarter: 4px;
|
||||
--radius: 8px; /* BUTTON_RADIUS */
|
||||
--radius-sm: 5px; /* container::bordered_box */
|
||||
--radius-xs: 2px; /* iced border::rounded(2) — карточки/инпуты по умолчанию */
|
||||
|
||||
/* Noto Sans JP первым: японский и латиница — из него, кириллица
|
||||
(её в Noto Sans JP нет) автоматически доберётся из системного
|
||||
шрифта — браузеры подбирают fallback поглифно. */
|
||||
font-family: 'Noto Sans JP', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
||||
font-size: 17px; /* десктоп: default_text_size 18 */
|
||||
line-height: 1.5;
|
||||
color: #1e1b2e;
|
||||
background: #f4f1fa;
|
||||
color: var(--fg);
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
* {
|
||||
@@ -16,28 +95,25 @@ body {
|
||||
min-height: 100dvh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background: var(--bg);
|
||||
color: var(--fg);
|
||||
padding: env(safe-area-inset-top) env(safe-area-inset-right)
|
||||
env(safe-area-inset-bottom) env(safe-area-inset-left);
|
||||
}
|
||||
|
||||
/* iced: selection = primary.weak, а ярких фонов при выделении нет */
|
||||
::selection {
|
||||
background: var(--primary-weak);
|
||||
color: var(--fg);
|
||||
}
|
||||
|
||||
#app {
|
||||
width: 100%;
|
||||
max-width: 480px;
|
||||
padding: 24px 16px 32px;
|
||||
padding: var(--space) var(--space) calc(var(--space) * 2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.app-header h1 {
|
||||
margin: 0;
|
||||
font-size: 1.75rem;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
.app-subtitle {
|
||||
margin: 4px 0 0;
|
||||
color: #6d6390;
|
||||
gap: var(--space);
|
||||
}
|
||||
|
||||
/* --- Топ-бар + бургер --- */
|
||||
@@ -48,12 +124,15 @@ body {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/* Кнопки навигации десктопа — button::text / nav_style: без фона и рамки, радиус 8,
|
||||
на нажатие — 10% белого поверх фона. */
|
||||
.burger-btn {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border: 2px solid #d9d2f0;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
border: none;
|
||||
border-radius: var(--radius);
|
||||
background: transparent;
|
||||
color: var(--fg);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -68,24 +147,30 @@ body {
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
border-radius: 2px;
|
||||
background: #4c446b;
|
||||
border-radius: 1px;
|
||||
background: currentColor;
|
||||
}
|
||||
|
||||
.burger-btn:active,
|
||||
.burger-btn[aria-expanded='true'] {
|
||||
border-color: #7c3aed;
|
||||
background: var(--surface-press);
|
||||
}
|
||||
|
||||
.burger-btn[aria-expanded='true'] span {
|
||||
background: var(--primary-strong);
|
||||
}
|
||||
|
||||
.top-bar-title h1 {
|
||||
margin: 0;
|
||||
font-size: 1.4rem;
|
||||
font-size: 22px; /* ACCENT_FONT_SIZE */
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.top-bar-title p {
|
||||
margin: 0;
|
||||
font-size: 0.9rem;
|
||||
color: #6d6390;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.top-bar-spacer {
|
||||
@@ -95,7 +180,7 @@ body {
|
||||
.app-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
gap: var(--space);
|
||||
}
|
||||
|
||||
/* --- Выдвижное меню --- */
|
||||
@@ -103,7 +188,7 @@ body {
|
||||
.drawer-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgb(30 27 46 / 0.45);
|
||||
background: rgb(40 40 40 / 0.72);
|
||||
z-index: 40;
|
||||
}
|
||||
|
||||
@@ -111,75 +196,87 @@ body {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Панель — поверхность background.weakest; тень не используем (iced — плоско),
|
||||
поэтому отделяем её рамкой. */
|
||||
.drawer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: min(300px, 85vw);
|
||||
background: #fff;
|
||||
background: var(--bg-weakest);
|
||||
border-right: 1px solid var(--bg-weak);
|
||||
z-index: 50;
|
||||
transform: translateX(-105%);
|
||||
transition: transform 0.22s ease;
|
||||
/* visibility гасит панель до/после анимации: закрытая она не видна и не мешает
|
||||
(в dev Vite вставляет CSS скриптом, поэтому без этого панель мигала бы на первом кадре) */
|
||||
visibility: hidden;
|
||||
transition: transform 0.22s ease, visibility 0s linear 0.22s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding: 20px 14px;
|
||||
box-shadow: 8px 0 32px rgb(30 27 46 / 0.18);
|
||||
gap: var(--space-quarter);
|
||||
padding: var(--space) var(--space-half);
|
||||
}
|
||||
|
||||
.drawer.open {
|
||||
transform: translateX(0);
|
||||
visibility: visible;
|
||||
transition: transform 0.22s ease, visibility 0s;
|
||||
}
|
||||
|
||||
.drawer-header {
|
||||
padding: 4px 8px 14px;
|
||||
border-bottom: 1px solid #eee9fb;
|
||||
margin-bottom: 8px;
|
||||
padding: var(--space-quarter) var(--space-half) 14px;
|
||||
border-bottom: 1px solid var(--bg-strong);
|
||||
margin-bottom: var(--space-half);
|
||||
}
|
||||
|
||||
.drawer-logo {
|
||||
font-size: 1.3rem;
|
||||
font-size: 22px; /* ACCENT_FONT_SIZE */
|
||||
font-weight: 800;
|
||||
color: #7c3aed;
|
||||
color: var(--primary-strong);
|
||||
}
|
||||
|
||||
.drawer-subtitle {
|
||||
font-size: 0.9rem;
|
||||
color: #6d6390;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.drawer-btn {
|
||||
border: none;
|
||||
background: transparent;
|
||||
text-align: left;
|
||||
font: inherit;
|
||||
font-size: 1.05rem;
|
||||
font-weight: 600;
|
||||
color: #1e1b2e;
|
||||
color: var(--fg);
|
||||
padding: 13px 12px;
|
||||
border-radius: 12px;
|
||||
border-radius: var(--radius);
|
||||
cursor: pointer;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
.drawer-btn.active {
|
||||
background: #f1eafe;
|
||||
color: #6d28d9;
|
||||
.drawer-btn:hover,
|
||||
.drawer-btn:active {
|
||||
background: var(--surface-press);
|
||||
}
|
||||
|
||||
.drawer-btn:active {
|
||||
background: #e9defc;
|
||||
/* Активный пункт = nav_style с primary-цветом текста (как «Сбросить» в словаре) */
|
||||
.drawer-btn.active {
|
||||
background: var(--surface-press);
|
||||
color: var(--primary-strong);
|
||||
}
|
||||
|
||||
body.drawer-open {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* --- Карточка = container::bordered_box: background.weakest + рамка background.weak --- */
|
||||
|
||||
.card {
|
||||
background: #fff;
|
||||
border-radius: 16px;
|
||||
padding: 20px 16px;
|
||||
box-shadow: 0 8px 24px rgb(124 58 237 / 0.12);
|
||||
background: var(--bg-weakest);
|
||||
border: 1px solid var(--bg-weak);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: var(--space);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
@@ -188,11 +285,12 @@ body.drawer-open {
|
||||
.card-title {
|
||||
margin: 0;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.card-hint {
|
||||
margin: 0;
|
||||
color: #6d6390;
|
||||
color: var(--muted);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
@@ -201,83 +299,137 @@ body.drawer-open {
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.token-input {
|
||||
width: 100%;
|
||||
padding: 14px 12px;
|
||||
font-size: 1.05rem;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||
letter-spacing: 0.04em;
|
||||
border: 2px solid #d9d2f0;
|
||||
border-radius: 12px;
|
||||
/* --- Инпуты = text_input::default ---
|
||||
фон background.base, рамка 1px background.strong, радиус 2,
|
||||
placeholder = secondary.base, focus -> рамка primary.strong,
|
||||
disabled -> фон background.weak. */
|
||||
|
||||
.token-input,
|
||||
.words-search,
|
||||
.words-group {
|
||||
padding: 12px;
|
||||
font: inherit;
|
||||
font-size: 1rem;
|
||||
color: var(--fg);
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--bg-strong);
|
||||
border-radius: var(--radius-xs);
|
||||
outline: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.token-input:focus {
|
||||
border-color: #7c3aed;
|
||||
.token-input::placeholder,
|
||||
.words-search::placeholder {
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.token-input:focus,
|
||||
.words-search:focus,
|
||||
.words-group:focus {
|
||||
border-color: var(--primary-strong);
|
||||
}
|
||||
|
||||
.token-input:disabled {
|
||||
background: var(--bg-weak);
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.token-input {
|
||||
width: 100%;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.token-input.invalid {
|
||||
border-color: #dc2626;
|
||||
background: #fef2f2;
|
||||
border-color: var(--danger-text);
|
||||
}
|
||||
|
||||
.token-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
gap: var(--space-half);
|
||||
min-height: 1.4em;
|
||||
}
|
||||
|
||||
.token-error {
|
||||
color: #dc2626;
|
||||
color: var(--danger-text);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.token-counter {
|
||||
color: #6d6390;
|
||||
color: var(--muted);
|
||||
font-variant-numeric: tabular-nums;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* --- Кнопки --- */
|
||||
|
||||
.btn-row {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/* cta_button: secondary.base с рамкой 1px (рамка в iced прозрачная) + BUTTON_RADIUS */
|
||||
.btn {
|
||||
flex: 1;
|
||||
padding: 14px 12px;
|
||||
padding: 12px 14px;
|
||||
font: inherit;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
border-radius: 12px;
|
||||
border: 2px solid #7c3aed;
|
||||
background: #fff;
|
||||
color: #7c3aed;
|
||||
border: 1px solid transparent;
|
||||
border-radius: var(--radius);
|
||||
background: var(--secondary);
|
||||
color: var(--on-secondary);
|
||||
cursor: pointer;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #7c3aed;
|
||||
color: #fff;
|
||||
.btn:not(:disabled):active {
|
||||
background: var(--secondary-strong);
|
||||
}
|
||||
|
||||
/* jl_button! -> button::primary: заливка primary, текст readable(primary, text) */
|
||||
.btn-primary {
|
||||
background: var(--primary);
|
||||
color: var(--on-primary);
|
||||
}
|
||||
|
||||
.btn-primary:not(:disabled):active {
|
||||
background: var(--primary-strong);
|
||||
}
|
||||
|
||||
/* disabled(base) в iced: фон и текст на 50% альфы */
|
||||
.btn:disabled {
|
||||
opacity: 0.4;
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn:not(:disabled):active {
|
||||
transform: scale(0.98);
|
||||
/* Кнопка-ссылка «назад» = nav_style: прозрачная, текст основного цвета */
|
||||
.btn-ghost {
|
||||
align-self: flex-start;
|
||||
flex: none;
|
||||
padding: 10px 12px;
|
||||
border-color: transparent;
|
||||
background: transparent;
|
||||
color: var(--fg);
|
||||
}
|
||||
|
||||
.btn-ghost:not(:disabled):active {
|
||||
background: var(--surface-press);
|
||||
}
|
||||
|
||||
/* --- Статусы ---
|
||||
Форма уведомления iced: фон = color.scale_alpha(0.3), рамка 1px тем же цветом,
|
||||
радиус 8. Нейтральный статус — «цвет» secondary, баннер базы — warning. */
|
||||
|
||||
.status-bar {
|
||||
margin: 0;
|
||||
padding: 10px 12px;
|
||||
border-radius: 10px;
|
||||
background: #f4f1fa;
|
||||
color: #4c446b;
|
||||
border-radius: var(--radius);
|
||||
background: rgb(144 140 124 / 0.18);
|
||||
border: 1px solid rgb(144 140 124 / 0.45);
|
||||
color: var(--fg);
|
||||
font-size: 0.95rem;
|
||||
word-break: break-word;
|
||||
}
|
||||
@@ -286,17 +438,16 @@ body.drawer-open {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Компактный баннер статуса БД: виден только при проблеме.
|
||||
В норме скрыт — слова занимают весь экран. */
|
||||
.db-banner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 10px;
|
||||
background: #fff7e6;
|
||||
color: #7a5b00;
|
||||
font-size: 0.85rem;
|
||||
gap: var(--space-half);
|
||||
padding: 10px 12px;
|
||||
border-radius: var(--radius);
|
||||
background: rgb(215 153 33 / 0.3);
|
||||
border: 1px solid var(--warning);
|
||||
color: var(--fg);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.db-banner[hidden] {
|
||||
@@ -311,15 +462,20 @@ body.drawer-open {
|
||||
.db-banner-link {
|
||||
flex: none;
|
||||
border: none;
|
||||
border-radius: var(--radius);
|
||||
background: transparent;
|
||||
padding: 4px;
|
||||
padding: 4px 6px;
|
||||
font: inherit;
|
||||
font-weight: 700;
|
||||
color: #7c3aed;
|
||||
color: var(--fg);
|
||||
cursor: pointer;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
.db-banner-link:active {
|
||||
background: var(--surface-press);
|
||||
}
|
||||
|
||||
.db-banner-link[hidden] {
|
||||
display: none;
|
||||
}
|
||||
@@ -328,23 +484,12 @@ body.drawer-open {
|
||||
|
||||
.words-toolbar {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
gap: var(--space-half);
|
||||
}
|
||||
|
||||
.words-search {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 12px;
|
||||
font-size: 1rem;
|
||||
border: 2px solid #d9d2f0;
|
||||
border-radius: 12px;
|
||||
outline: none;
|
||||
background: #fff;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.words-search:focus {
|
||||
border-color: #7c3aed;
|
||||
}
|
||||
|
||||
.words-group {
|
||||
@@ -353,15 +498,6 @@ body.drawer-open {
|
||||
padding: 12px 8px;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
color: #4c446b;
|
||||
border: 2px solid #d9d2f0;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.words-group:focus {
|
||||
border-color: #7c3aed;
|
||||
}
|
||||
|
||||
.words-list {
|
||||
@@ -369,9 +505,10 @@ body.drawer-open {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Плоская строка: ключ + перевод слева, тег справа. Без карточек. */
|
||||
/* Плоская строка: ключ + перевод слева, тег справа. Разделитель = rule::default
|
||||
(background.strong), нажатие — 10% белого (nav_style десктопа). */
|
||||
.word-row-wrap {
|
||||
border-bottom: 1px solid #eee9fb;
|
||||
border-bottom: 1px solid var(--bg-strong);
|
||||
}
|
||||
|
||||
.word-row-wrap:last-child {
|
||||
@@ -381,9 +518,9 @@ body.drawer-open {
|
||||
.word-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
gap: var(--space-half);
|
||||
width: 100%;
|
||||
padding: 11px 4px;
|
||||
padding: 11px 6px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font: inherit;
|
||||
@@ -391,19 +528,16 @@ body.drawer-open {
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
touch-action: manipulation;
|
||||
border-radius: 8px;
|
||||
border-radius: var(--radius-xs);
|
||||
}
|
||||
|
||||
.word-row:disabled {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.word-row:not(:disabled):active {
|
||||
background: #f4f1fa;
|
||||
}
|
||||
|
||||
.word-row:not(:disabled):active,
|
||||
.word-row.open {
|
||||
background: #f4f1fa;
|
||||
background: var(--surface-press-soft);
|
||||
}
|
||||
|
||||
.word-main {
|
||||
@@ -417,14 +551,14 @@ body.drawer-open {
|
||||
}
|
||||
|
||||
.word-sep {
|
||||
color: #6d6390;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.word-value {
|
||||
color: #4c446b;
|
||||
color: var(--fg-soft);
|
||||
}
|
||||
|
||||
/* Тег справа — плоской подписью, без плашки */
|
||||
/* Тег справа — плоской подписью в цвете secondary.base (как placeholder в iced) */
|
||||
.word-tag {
|
||||
flex: none;
|
||||
max-width: 38%;
|
||||
@@ -432,7 +566,7 @@ body.drawer-open {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 0.8rem;
|
||||
color: #6d6390;
|
||||
color: var(--muted);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@@ -442,8 +576,7 @@ body.drawer-open {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background: #7c3aed;
|
||||
opacity: 0.55;
|
||||
background: var(--primary-strong);
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
@@ -452,20 +585,21 @@ body.drawer-open {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* container::rounded_box: фон background.weak, радиус 2 */
|
||||
.word-extra-list {
|
||||
margin: 0 0 10px;
|
||||
padding: 10px 12px;
|
||||
background: #f4f1fa;
|
||||
border-radius: 10px;
|
||||
background: var(--bg-weak);
|
||||
border-radius: var(--radius-xs);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
gap: var(--space-half);
|
||||
}
|
||||
|
||||
.word-extra-row dt {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 700;
|
||||
color: #6d6390;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.word-extra-row dd {
|
||||
@@ -475,14 +609,14 @@ body.drawer-open {
|
||||
|
||||
/* Пустые значения в раскрытии колоды — приглушённое тире */
|
||||
.empty-val {
|
||||
opacity: 0.5;
|
||||
color: var(--fg-faint);
|
||||
}
|
||||
|
||||
/* Кнопка-строка колоды: div-обёртка + button в одном элементе.
|
||||
.word-row сбрасывает border — возвращаем разделитель. */
|
||||
button.word-row-wrap {
|
||||
border: none;
|
||||
border-bottom: 1px solid #eee9fb;
|
||||
border-bottom: 1px solid var(--bg-strong);
|
||||
}
|
||||
|
||||
button.word-row-wrap:last-child {
|
||||
@@ -490,55 +624,43 @@ button.word-row-wrap:last-child {
|
||||
}
|
||||
|
||||
button.word-row-wrap:not(:disabled):hover {
|
||||
background: #f4f1fa;
|
||||
}
|
||||
|
||||
/* Призрачная кнопка «назад» + подзаголовок на странице колоды */
|
||||
.btn-ghost {
|
||||
align-self: flex-start;
|
||||
flex: none;
|
||||
border: 2px solid #d9d2f0;
|
||||
background: #fff;
|
||||
color: #4c446b;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.btn-ghost:active {
|
||||
background: #f1eafe;
|
||||
border-color: #7c3aed;
|
||||
background: var(--surface-press-soft);
|
||||
}
|
||||
|
||||
/* Форма редактирования колоды: инпуты + статус. id/name — только чтение. */
|
||||
.deck-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
gap: var(--space-half);
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.deck-form .field-label {
|
||||
margin-top: 4px;
|
||||
margin-top: var(--space-quarter);
|
||||
}
|
||||
|
||||
.deck-form .btn-row {
|
||||
margin-top: 8px;
|
||||
margin-top: var(--space-half);
|
||||
}
|
||||
|
||||
.deck-form .card-hint:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Подзаголовок блока = text + rule::default под ним */
|
||||
.deck-sub {
|
||||
margin: 16px 0 8px;
|
||||
margin: var(--space) 0 var(--space-half);
|
||||
padding-bottom: var(--space-half);
|
||||
border-bottom: 1px solid var(--bg-strong);
|
||||
font-size: 1rem;
|
||||
color: #4c446b;
|
||||
color: var(--fg);
|
||||
}
|
||||
|
||||
/* Строка колоды: div-обёртка — name слева тянется, «▶» справа фиксирован. */
|
||||
.deck-row {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 4px;
|
||||
gap: var(--space-quarter);
|
||||
}
|
||||
|
||||
.deck-name {
|
||||
@@ -546,30 +668,30 @@ button.word-row-wrap:not(:disabled):hover {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* deck-play -> button::primary, но компактная цель под палец */
|
||||
.deck-play {
|
||||
flex: none;
|
||||
align-self: center;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border: 2px solid #d9d2f0;
|
||||
border-radius: 12px;
|
||||
background: #f1eafe;
|
||||
color: #6d28d9;
|
||||
border: none;
|
||||
border-radius: var(--radius);
|
||||
background: var(--primary);
|
||||
color: var(--on-primary);
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
touch-action: manipulation;
|
||||
}
|
||||
|
||||
.deck-play:active {
|
||||
background: #e9defc;
|
||||
border-color: #7c3aed;
|
||||
background: var(--primary-strong);
|
||||
}
|
||||
|
||||
/* --- История ответов колоды: плоские строки, цветы оценок --- */
|
||||
/* --- История ответов колоды: плоские строки, оценки-плашки --- */
|
||||
|
||||
.hist-row-wrap {
|
||||
padding: 9px 4px;
|
||||
border-bottom: 1px solid #eee9fb;
|
||||
padding: 9px 6px;
|
||||
border-bottom: 1px solid var(--bg-strong);
|
||||
}
|
||||
|
||||
.hist-row-wrap:last-child {
|
||||
@@ -583,26 +705,45 @@ button.word-row-wrap:not(:disabled):hover {
|
||||
.hist-meta {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
margin-top: 4px;
|
||||
gap: var(--space-half);
|
||||
margin-top: var(--space-quarter);
|
||||
}
|
||||
|
||||
/* Плашка оценки = форма уведомления iced: 30% цвета + рамка 1px тем же цветом */
|
||||
.hist-grade {
|
||||
flex: none;
|
||||
padding: 2px 10px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 999px;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 700;
|
||||
color: var(--fg);
|
||||
}
|
||||
|
||||
.hist-grade.grade-fail {
|
||||
background: rgb(204 36 29 / 0.3);
|
||||
border-color: var(--danger);
|
||||
}
|
||||
|
||||
.hist-grade.grade-hard {
|
||||
background: rgb(215 153 33 / 0.3);
|
||||
border-color: var(--warning);
|
||||
}
|
||||
|
||||
.hist-grade.grade-good {
|
||||
background: rgb(152 151 26 / 0.3);
|
||||
border-color: var(--success);
|
||||
}
|
||||
|
||||
.hist-grade.grade-fail,
|
||||
.hist-grade.grade-hard,
|
||||
.hist-grade.grade-good,
|
||||
.hist-grade.grade-easy {
|
||||
border: none;
|
||||
background: rgb(69 133 136 / 0.3);
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
/* --- Повторение: карточка + 4 кнопки оценок --- */
|
||||
/* --- Повторение: карточка + 4 кнопки оценок ---
|
||||
Десктоп: forward и backward на всю ширину, между ними rule::horizontal(2),
|
||||
размеры текста draw_key = 36, draw_value/reading/context = 24,
|
||||
до открытия backward показывает «?», подсказка — text.scale_alpha(0.3). */
|
||||
|
||||
#review-body {
|
||||
display: flex;
|
||||
@@ -615,10 +756,10 @@ button.word-row-wrap:not(:disabled):hover {
|
||||
.review-card {
|
||||
display: block;
|
||||
width: 100%;
|
||||
border: 2px solid #d9d2f0;
|
||||
border-radius: 14px;
|
||||
background: #fbfaff;
|
||||
padding: 20px 16px;
|
||||
border: 1px solid var(--bg-weak);
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--bg-weakest);
|
||||
padding: var(--space) 12px;
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
text-align: center;
|
||||
@@ -627,72 +768,91 @@ button.word-row-wrap:not(:disabled):hover {
|
||||
}
|
||||
|
||||
.review-card:active {
|
||||
border-color: #7c3aed;
|
||||
border-color: var(--primary-strong);
|
||||
}
|
||||
|
||||
.review-side {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
gap: var(--space-half);
|
||||
}
|
||||
|
||||
.review-line {
|
||||
margin: 0;
|
||||
overflow-wrap: break-word;
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
/* Первая строка лицевой стороны — крупный ключ (draw_key, 36px) */
|
||||
.review-front .review-line:first-child {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 800;
|
||||
font-size: 36px;
|
||||
font-weight: 600;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
/* Разделитель лицевой и обратной стороны — rule::horizontal(2) */
|
||||
.review-hr {
|
||||
border: none;
|
||||
border-top: 1px solid #eee9fb;
|
||||
border-top: 2px solid var(--bg-strong);
|
||||
margin: 14px 0;
|
||||
}
|
||||
|
||||
.review-tap {
|
||||
margin: 12px 0 0;
|
||||
font-size: 0.85rem;
|
||||
color: #6d6390;
|
||||
color: var(--fg-faint);
|
||||
}
|
||||
|
||||
.review-grades {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px;
|
||||
gap: var(--space-half);
|
||||
}
|
||||
|
||||
.review-grade {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Оценки — плоские оттенки смысла, текст всегда тёмный для контраста. */
|
||||
.grade-fail {
|
||||
background: #fee2e2;
|
||||
color: #991b1b;
|
||||
box-shadow: none;
|
||||
/* Оценки — семантические заливки палитры; текст подобран readable(), как в iced.
|
||||
Не получилось — danger, трудно — warning, хорошо — success, легко — primary. */
|
||||
.review-grade.grade-fail {
|
||||
background: var(--danger);
|
||||
color: var(--on-danger);
|
||||
}
|
||||
|
||||
.grade-hard {
|
||||
background: #ffedd5;
|
||||
color: #9a3412;
|
||||
box-shadow: none;
|
||||
.review-grade.grade-fail:not(:disabled):active {
|
||||
background: var(--danger-strong);
|
||||
}
|
||||
|
||||
.grade-good {
|
||||
background: #dcfce7;
|
||||
color: #166534;
|
||||
box-shadow: none;
|
||||
.review-grade.grade-hard {
|
||||
background: var(--warning);
|
||||
color: var(--on-warning);
|
||||
}
|
||||
|
||||
.grade-easy {
|
||||
background: #dbeafe;
|
||||
color: #1e40af;
|
||||
box-shadow: none;
|
||||
.review-grade.grade-hard:not(:disabled):active {
|
||||
background: var(--warning-strong);
|
||||
}
|
||||
|
||||
.review-grade:active {
|
||||
filter: brightness(0.95);
|
||||
.review-grade.grade-good {
|
||||
background: var(--success);
|
||||
color: var(--on-success);
|
||||
}
|
||||
|
||||
.review-grade.grade-good:not(:disabled):active {
|
||||
background: var(--success-strong);
|
||||
}
|
||||
|
||||
.review-grade.grade-easy {
|
||||
background: var(--primary);
|
||||
color: var(--on-primary);
|
||||
}
|
||||
|
||||
.review-grade.grade-easy:not(:disabled):active {
|
||||
background: var(--primary-strong);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.drawer {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user