From 1fabf21935ae16a7892dab6666fdf7c77b7213ad Mon Sep 17 00:00:00 2001 From: IK Date: Sat, 12 Sep 2026 09:54:26 +0700 Subject: [PATCH] refactor: introduce semantic brand tokens --- apps/web/src/styles/data-passport.css | 6 +++--- apps/web/src/styles/global.css | 4 ++-- apps/web/src/styles/loading-states.css | 2 +- apps/web/src/styles/source-status.css | 2 +- docs/ROADMAP.md | 2 +- docs/brand-system.md | 2 ++ 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/apps/web/src/styles/data-passport.css b/apps/web/src/styles/data-passport.css index c06d2ac..333f0ea 100644 --- a/apps/web/src/styles/data-passport.css +++ b/apps/web/src/styles/data-passport.css @@ -1,5 +1,5 @@ -.data-passport{margin-top:18px;padding:14px;border:1px solid #cbd7cf;border-radius:13px;background:#f8faf6;color:var(--deep)} -.data-passport header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:11px}.data-passport header>span{font:italic 15px Georgia,serif}.data-passport header strong{padding:4px 8px;border-radius:999px;background:#e2efcf;color:#49651f;font-size:9px;text-transform:uppercase;letter-spacing:.06em}.data-passport header strong[data-passport-status="unverified"]{background:#e8e2f4;color:#59438d}.data-passport header strong[data-passport-status="incomplete"]{background:#f5e6b8;color:#755609} -.data-passport__sources{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:12px}.data-passport dl{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:0}.data-passport dl div{padding-top:8px;border-top:1px solid #d9e1da}.data-passport dt{font-size:8px;text-transform:uppercase;letter-spacing:.08em;color:#72817e}.data-passport dd{margin:3px 0 0;font:400 12px Georgia,serif;color:var(--deep)} +.data-passport{margin-top:18px;padding:14px;border:1px solid var(--border);border-radius:13px;background:var(--surface-soft);color:var(--deep)} +.data-passport header{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:11px}.data-passport header>span{font:italic 15px Georgia,serif}.data-passport header strong{padding:4px 8px;border-radius:999px;background:var(--success-soft);color:var(--success);font-size:9px;text-transform:uppercase;letter-spacing:.06em}.data-passport header strong[data-passport-status="unverified"]{background:#e8e2f4;color:#59438d}.data-passport header strong[data-passport-status="incomplete"]{background:var(--warning-soft);color:var(--warning)} +.data-passport__sources{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:12px}.data-passport dl{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:0}.data-passport dl div{padding-top:8px;border-top:1px solid var(--border-soft)}.data-passport dt{font-size:8px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-subtle)}.data-passport dd{margin:3px 0 0;font:400 12px Georgia,serif;color:var(--deep)} .detail-card .data-passport,.detail-grid aside .data-passport{border-color:#ffffff20;background:#ffffff08;color:#fff}.detail-card .data-passport dd,.detail-grid aside .data-passport dd{color:#fff}.detail-card .data-passport dl div,.detail-grid aside .data-passport dl div{border-color:#ffffff1c}.detail-card .data-passport dt,.detail-grid aside .data-passport dt{color:#a9b8b5}.signal-card .data-passport{position:relative;z-index:1;margin-top:15px;background:#fffdf7;border-color:#ddd3af} @media(max-width:420px){.data-passport dl{grid-template-columns:1fr}.data-passport dl div{display:flex;justify-content:space-between;gap:10px}} diff --git a/apps/web/src/styles/global.css b/apps/web/src/styles/global.css index 896f13a..f7bf2c0 100644 --- a/apps/web/src/styles/global.css +++ b/apps/web/src/styles/global.css @@ -1,9 +1,9 @@ -:root{--paper:#f2f5ee;--deep:#082226;--teal:#12383b;--lime:#c9f45b;--ink:#092226;--muted:#647472;--line:#cbd6ce;--white:#fff;--orange:#ffb65c;font-family:Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;color:var(--ink);background:var(--paper)} +:root{--paper:#f2f5ee;--deep:#082226;--teal:#12383b;--lime:#c9f45b;--ink:#092226;--muted:#647472;--line:#cbd6ce;--white:#fff;--orange:#ffb65c;--surface:var(--white);--surface-soft:#f8faf5;--surface-field:#f3f6f1;--text:var(--ink);--text-muted:#526662;--text-subtle:#647572;--border:var(--line);--border-soft:#d6dfd7;--focus:#7da529;--success:#426315;--success-soft:#e2efcf;--warning:#73550c;--warning-soft:#fff0c7;--danger:#842f25;--danger-soft:#f5d8d2;--source-official:#9a6a22;--source-rf4db:#306f8f;--source-rf4stat:#6951a3;--source-rf4map:#36785a;--source-rf4posts:#b05a3e;--source-players:#55701d;font-family:Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;color:var(--text);background:var(--paper)} /* Mobile horizontal rails: native scrolling without a second visual scrollbar. */ @media(max-width:720px){.topbar nav,.active-filters{overscroll-behavior-inline:contain;scroll-snap-type:x proximity;scrollbar-width:none}.topbar nav::-webkit-scrollbar,.active-filters::-webkit-scrollbar{display:none}.topbar nav a,.active-filters span{scroll-snap-align:start}} @media(max-width:360px){body .records-hero h1,body .form-hero h1{font-size:46px}} *{box-sizing:border-box}[hidden]{display:none!important}html{scroll-behavior:smooth}body{margin:0;min-width:0;background:var(--paper);color:var(--ink)}a{color:inherit}button,input,select,textarea{font:inherit}button{cursor:pointer}.content-grid{width:min(1360px,calc(100% - 64px));margin-inline:auto}main{min-height:calc(100vh - 204px)} -.skip-link{position:fixed;z-index:100;left:12px;top:12px;padding:12px 16px;background:var(--lime);color:var(--deep);font-weight:750;transform:translateY(-150%)}.skip-link:focus{transform:none}:focus-visible{outline:3px solid #7da529;outline-offset:3px}.topbar nav a[aria-current="page"]{font-weight:750}.notice:focus{outline:3px solid #9d3529;outline-offset:3px} +.skip-link{position:fixed;z-index:100;left:12px;top:12px;padding:12px 16px;background:var(--lime);color:var(--deep);font-weight:750;transform:translateY(-150%)}.skip-link:focus{transform:none}:focus-visible{outline:3px solid var(--focus);outline-offset:3px}.topbar nav a[aria-current="page"]{font-weight:750}.notice:focus{outline:3px solid var(--danger);outline-offset:3px} .topbar{height:86px;width:min(1480px,calc(100% - 48px));margin:auto;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:28px}.brand{display:flex;align-items:center;gap:12px;text-decoration:none;min-width:max-content}.brand-mark{width:42px;height:42px;display:grid;place-items:center;border:1px solid #9eb0a7;border-radius:50%;background:var(--deep);color:var(--lime);font-size:28px}.brand-name{display:flex;flex-direction:column;gap:3px;line-height:1}.brand-name strong{font-size:16px;letter-spacing:.035em}.brand-name span{color:#60716e;font:italic 13px Georgia,serif}.topbar nav{height:100%;display:flex;gap:23px;align-items:center}.topbar nav a{height:100%;display:flex;align-items:center;gap:7px;padding:0 8px;text-decoration:none;color:#526461;font-size:14px;border-bottom:3px solid transparent}.topbar nav a.active{color:var(--deep);border-color:var(--deep)}.live-badge{justify-self:end;display:flex;align-items:center;gap:9px;color:#60716e;font-size:13px}.live-badge>span{width:8px;height:8px;border-radius:50%;background:#83b83a;box-shadow:0 0 0 5px #83b83a20} .eyebrow,.overline{text-transform:uppercase;letter-spacing:.14em;font-size:12px;font-weight:750;color:#657673}.eyebrow{display:flex;align-items:center;gap:10px}.eyebrow b{display:grid;place-items:center;min-width:41px;height:25px;padding:0 8px;border:1px solid #9aaa9f;border-radius:20px;color:var(--deep);letter-spacing:.05em}.intro{padding:74px 0 42px;display:grid;grid-template-columns:.92fr 1.08fr;align-items:end;gap:70px}.intro h1,.records-hero h1,.form-hero h1,.spot-hero h1{margin:18px 0 22px;font:400 clamp(58px,6.3vw,102px)/.87 Georgia,"Times New Roman",serif;letter-spacing:-.065em}.intro h1 em,.records-hero h1 em,.form-hero h1 em{color:#497074;font-weight:400}.intro-copy>p{font-size:18px;line-height:1.55;color:#586a68;max-width:560px}.lake-card{position:relative;border-radius:18px;overflow:hidden;height:326px;box-shadow:0 24px 70px #173c3f24}.lake-card img{width:100%;height:100%;object-fit:cover;display:block}.lake-card:after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 35%,#041c20d9)}.lake-overlay{position:absolute;z-index:2;inset:auto 24px 22px 26px;display:flex;justify-content:space-between;align-items:end;color:#fff}.lake-overlay .overline{color:#d2dedb;display:block;margin-bottom:7px}.lake-overlay strong{font:400 21px Georgia,serif}.pulse-orb{width:45px;height:45px;border:1px solid #ffffff7d;border-radius:50%;display:grid;place-items:center}.pulse-orb span{width:9px;height:9px;border-radius:50%;background:var(--lime);box-shadow:0 0 0 8px #c9f45b25} .filters-wrap{background:var(--deep);padding:24px 0;position:sticky;top:0;z-index:20;box-shadow:0 10px 35px #08222620}.filters{display:grid;grid-template-columns:repeat(5,1fr);gap:12px;align-items:end}.filters label,.report-form label,.record-filters label{color:#9fb0ad;font-size:12px;text-transform:uppercase;letter-spacing:.1em;font-weight:700}.filters select{display:block;width:100%;height:48px;margin-top:7px;padding:0 13px;border:1px solid #ffffff29;border-radius:10px;background:#ffffff0c;color:#f5f8f3}.filters option{color:var(--ink)}.filters button,.report-form button,.record-filters button{height:48px;padding:0 24px;border:0;border-radius:10px;background:var(--lime);color:var(--deep);font-weight:750}.filter-advanced-field{display:flex;align-items:center;gap:6px}.filter-compact-hidden{display:none!important}.filter-advanced-fallback{display:contents}.filter-advanced-fallback summary{display:none}.filter-advanced-fallback .advanced-fields{display:contents}.filter-advanced-fallback:not([open]) .advanced-fields{display:none!important}.active-filters{min-height:56px;display:flex;align-items:center;gap:8px;padding-top:10px}.active-filters span{padding:6px 10px;border:1px solid #c8d3cb;border-radius:20px;background:#f8faf5;color:#526662;font-size:12px}.active-filters a{margin-left:auto;color:#4d625e;font-size:13px;text-underline-offset:3px} diff --git a/apps/web/src/styles/loading-states.css b/apps/web/src/styles/loading-states.css index c95510b..b122b58 100644 --- a/apps/web/src/styles/loading-states.css +++ b/apps/web/src/styles/loading-states.css @@ -1 +1 @@ -.loading-grid{display:grid;gap:18px}.loading-card{position:relative;overflow:hidden;min-height:210px;padding:25px;border:1px solid #d4ddd6;border-radius:16px;background:#fff}.loading-card:after{content:"";position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(100deg,transparent 20%,#f7faf5 48%,transparent 76%);animation:loading-sweep 1.4s ease-in-out infinite}.loading-line{display:block;width:100%;height:13px;margin-top:18px;border-radius:999px;background:#e7ede7}.loading-line--label{width:22%;height:9px;margin-top:0;background:#d8e2d8}.loading-line--title{width:48%;height:30px;margin-top:24px}.loading-line--short{width:64%}.moderation-list[aria-busy="true"]{cursor:progress}.sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}@keyframes loading-sweep{to{transform:translateX(100%)}}@media(prefers-reduced-motion:reduce){.loading-card:after{animation:none;background:#f7faf533}} +.loading-grid{display:grid;gap:18px}.loading-card{position:relative;overflow:hidden;min-height:210px;padding:25px;border:1px solid var(--border-soft);border-radius:16px;background:var(--surface)}.loading-card:after{content:"";position:absolute;inset:0;transform:translateX(-100%);background:linear-gradient(100deg,transparent 20%,var(--surface-soft) 48%,transparent 76%);animation:loading-sweep 1.4s ease-in-out infinite}.loading-line{display:block;width:100%;height:13px;margin-top:18px;border-radius:999px;background:#e7ede7}.loading-line--label{width:22%;height:9px;margin-top:0;background:#d8e2d8}.loading-line--title{width:48%;height:30px;margin-top:24px}.loading-line--short{width:64%}.moderation-list[aria-busy="true"]{cursor:progress}.sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}@keyframes loading-sweep{to{transform:translateX(100%)}}@media(prefers-reduced-motion:reduce){.loading-card:after{animation:none;background:#f7faf533}} diff --git a/apps/web/src/styles/source-status.css b/apps/web/src/styles/source-status.css index 6cb217a..e4c3176 100644 --- a/apps/web/src/styles/source-status.css +++ b/apps/web/src/styles/source-status.css @@ -1 +1 @@ -.source-health-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:13px;padding:34px 0 100px}.source-health-grid article{padding:21px;border:1px solid #d3ddd5;border-radius:14px;background:#fff}.source-health-grid article>div{display:flex;justify-content:space-between;gap:8px}.source-health-grid h2{font:400 23px Georgia,serif;margin:18px 0 6px}.source-health-grid strong{font-size:13px}.source-health-grid p{color:#526662;font-size:12px}.health-state{display:flex;align-items:center;gap:6px;font-size:10px;font-weight:750;color:#526662}.health-state i{width:8px;height:8px;border-radius:50%;background:#c59a36}.source-health-grid [data-status="healthy"] .health-state i{background:#79aa36}.source-health-grid [data-status="source_changed"] .health-state i{background:#bc5748}.source-health-grid [data-status="disabled"]{opacity:.65}@media(max-width:900px){.source-health-grid{grid-template-columns:repeat(2,1fr)}}@media(max-width:620px){.source-health-grid{grid-template-columns:1fr}} +.source-health-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:13px;padding:34px 0 100px}.source-health-grid article{padding:21px;border:1px solid var(--border-soft);border-radius:14px;background:var(--surface)}.source-health-grid article>div{display:flex;justify-content:space-between;gap:8px}.source-health-grid h2{font:400 23px Georgia,serif;margin:18px 0 6px}.source-health-grid strong{font-size:13px}.source-health-grid p{color:var(--text-muted);font-size:12px}.health-state{display:flex;align-items:center;gap:6px;font-size:10px;font-weight:750;color:var(--text-muted)}.health-state i{width:8px;height:8px;border-radius:50%;background:#c59a36}.source-health-grid [data-status="healthy"] .health-state i{background:#79aa36}.source-health-grid [data-status="source_changed"] .health-state i{background:#bc5748}.source-health-grid [data-status="disabled"]{opacity:.65}@media(max-width:900px){.source-health-grid{grid-template-columns:repeat(2,1fr)}}@media(max-width:620px){.source-health-grid{grid-template-columns:1fr}} diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 63a6b00..0c5ecb7 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -21,7 +21,7 @@ ### Брендинг и визуальная идентичность - [x] **B01 · Иерархия имени.** RF4 Spotter — единое имя продукта в UI, metadata, manifest и документации; «Ни хвоста, ни чешуи» — поддерживающий слоган. Обновлены wordmark в header/footer и подпись выпуска. -- [ ] **B02 · Дизайн-токены.** Разделить семантические цвета поверхности, текста, границ, источников и состояний; убрать дубли значений из CSS и зафиксировать контрастные пары. +- [x] **B02 · Дизайн-токены.** Добавлены семантические роли поверхностей, текста, границ, фокуса, success/warning/danger и всех источников. На токены переведены паспорта данных, status-карточки, skeleton и focus; контрастные пары зафиксированы в brand system. - [ ] **B03 · Графическая грамматика.** Согласовать применение крючка, поплавка, лески, ряби, координатной сетки и рыбьих силуэтов; убрать случайные декоративные элементы и повторы. - [ ] **B04 · Компонентная подпись.** Унифицировать заголовки секций, CTA, карточки, плашки источников, состояния качества и пустые экраны на публичных и admin-страницах. - [ ] **B05 · Motion-система.** Оставить только смысловые микроанимации поклёвки/пульса/перехода, задать общие длительности и полностью поддержать reduced motion. diff --git a/docs/brand-system.md b/docs/brand-system.md index 409c6b2..bf6a691 100644 --- a/docs/brand-system.md +++ b/docs/brand-system.md @@ -14,6 +14,8 @@ - Оранжевый — приманка и тёплый акцент, но не системный статус ошибки. - Антиква Georgia — крупные редакционные заголовки и числа; Inter/system sans — управление, подписи и данные. +Семантические CSS-токены отделяют роль от оттенка: `--surface*`, `--text*`, `--border*`, `--focus`, `--success*`, `--warning*`, `--danger*` и `--source-*`. Компонент не должен вводить новый системный зелёный, жёлтый или красный без отдельной смысловой роли. Основной текст на светлой поверхности использует `--text`, вторичный — `--text-muted`; `--text-subtle` допустим только для крупного или вспомогательного текста, прошедшего WCAG AA. + ## Фирменные мотивы - Крючок — знак бренда и favicon.