/* ============================================================ ЗОВ MiniApp — design system v4 Три варианта: brand (default) · a (Editorial Calm) · c (Architectural Clean) Переключатель — ``, состояние в localStorage. ============================================================ */ /* =========================================================== 1. BRAND (default :root) — мой гибрид с палитрой ЗОВ =========================================================== */ :root { --paper: var(--tg-theme-bg-color, #FAFAF7); --paper-2: var(--tg-theme-secondary-bg-color, #F0EDE5); --card: var(--tg-theme-section-bg-color, #FFFFFF); --ink: var(--tg-theme-text-color, #0F0F0E); --ink-2: #2A2622; --muted: var(--tg-theme-hint-color, #6E6A62); --muted-2: #A09C92; --line: rgba(15, 15, 14, 0.08); --line-strong: rgba(15, 15, 14, 0.16); --accent-1: #003E7E; /* brand blue */ --accent-2: #76BD22; /* brand green */ --accent-3: #C0392B; --status-active: #76BD22; --status-lapsed: #C0392B; --status-grace: #B07E00; --r-card: 14px; --r-btn: 12px; --r-tag: 4px; --r-pill: 999px; --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 20px; --s6: 24px; --s7: 32px; --s8: 40px; --font-ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, system-ui, sans-serif; --font-display: "Instrument Serif", Georgia, "Times New Roman", serif; --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; --ribbon: linear-gradient(90deg, var(--accent-1) 0%, var(--accent-2) 100%); } @media (prefers-color-scheme: dark) { :root { color-scheme: dark; } } html[data-theme="dark"]:not([data-variant="a"]):not([data-variant="c"]) { --paper: var(--tg-theme-bg-color, #14130E); --paper-2: var(--tg-theme-secondary-bg-color, #1F1D17); --card: var(--tg-theme-section-bg-color, #1C1A14); --ink: var(--tg-theme-text-color, #F4F1EA); --ink-2: #C8C3B5; --muted: var(--tg-theme-hint-color, #A5A299); --muted-2: #807D74; --line: rgba(255, 255, 255, 0.10); --line-strong: rgba(255, 255, 255, 0.20); } /* =========================================================== 2. VARIANT A — Editorial Calm (палитра/шрифты — дословно из мокапа) =========================================================== */ html[data-variant="a"] { --paper: #FBF7F0; --paper-2: #F5EDDC; --card: #FBF7F0; --ink: #1F1A14; --ink-2: #8B8275; --muted: #8B8275; --muted-2: #9A9085; --line: rgba(31, 26, 20, 0.18); --line-strong: rgba(31, 26, 20, 0.40); --accent-1: #3C5278; /* editorial blue */ --accent-2: #6B4A2B; /* walnut */ --accent-3: #B85A2D; /* terracotta */ --status-active: #B85A2D; --status-lapsed: #B85A2D; --status-grace: #B85A2D; --r-card: 0; --r-btn: 0; --r-tag: 3px; --r-pill: 100px; --font-ui: "Geist", "Manrope", -apple-system, system-ui, sans-serif; --font-display: "Newsreader", "Cormorant Garamond", Georgia, serif; --font-mono: "JetBrains Mono", ui-monospace, monospace; --ribbon: linear-gradient(90deg, var(--accent-1) 0%, var(--accent-2) 50%, var(--accent-3) 100%); } /* =========================================================== 3. VARIANT C — Architectural Clean =========================================================== */ html[data-variant="c"] { --paper: #FAFAF7; --paper-2: #EEEAE0; --card: #FAFAF7; --ink: #0F0F0E; --ink-2: #1F1A14; --muted: #6E6A62; --muted-2: #A09C92; --line: rgba(15, 15, 14, 0.18); --line-strong: rgba(15, 15, 14, 0.40); --accent-1: #3A6B44; /* blueprint green */ --accent-2: #5A3F26; /* walnut */ --accent-3: #8C3F1E; --status-active: #3A6B44; --status-lapsed: #8C3F1E; --status-grace: #5A3F26; --r-card: 0; --r-btn: 0; --r-tag: 4px; --r-pill: 100px; --font-ui: "Geist", -apple-system, system-ui, sans-serif; --font-display: "Instrument Serif", "Cormorant Garamond", Georgia, serif; --font-mono: "JetBrains Mono", ui-monospace, monospace; --ribbon: linear-gradient(90deg, var(--accent-2) 0%, var(--accent-1) 100%); } /* ============================================================ Reset ============================================================ */ * { box-sizing: border-box; -webkit-tap-highlight-color: transparent; } html, body { margin: 0; padding: 0; } body { font-family: var(--font-ui); font-size: 15px; font-weight: 400; line-height: 1.45; letter-spacing: -0.01em; color: var(--ink); background: var(--paper); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; } a { color: inherit; text-decoration: none; } button { font: inherit; cursor: pointer; border: none; background: none; color: inherit; padding: 0; } /* ============================================================ Layout ============================================================ */ #app { max-width: 560px; margin: 0 auto; padding: var(--s4) var(--s4) calc(var(--s8) + env(safe-area-inset-bottom)); min-height: 100vh; } /* ============================================================ Theme switcher (top of page) ============================================================ */ .theme-switch { display: flex; gap: 0; margin-bottom: var(--s5); border: 1px solid var(--line-strong); border-radius: var(--r-tag); overflow: hidden; background: var(--card); } .theme-switch button { flex: 1; padding: 8px 6px; font-family: var(--font-mono); font-size: 10px; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); border-right: 1px solid var(--line-strong); transition: all 0.12s; } .theme-switch button:last-child { border-right: none; } .theme-switch button.active { background: var(--ink); color: var(--paper); } /* ============================================================ Loader ============================================================ */ .loader { display: grid; place-items: center; min-height: 60vh; } .spinner { width: 32px; height: 32px; border: 1.5px solid var(--line-strong); border-top-color: var(--accent-1); border-radius: var(--r-pill); animation: spin 0.7s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* ============================================================ Profile card ============================================================ */ .profile-card { background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-card); padding: var(--s6) var(--s5) var(--s5); margin-bottom: var(--s7); position: relative; overflow: hidden; } .profile-card::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: var(--ribbon); } .profile-card .role-tag { font-family: var(--font-mono); font-size: 11px; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); margin-bottom: var(--s3); display: inline-flex; align-items: center; gap: var(--s2); } .profile-card .role-tag::after { content: ""; display: inline-block; width: 24px; height: 1px; background: var(--line-strong); } .profile-card .head-row { display: flex; align-items: flex-start; gap: var(--s4); margin-bottom: var(--s4); } .profile-card .info { flex: 1; min-width: 0; } .profile-card .name { font-family: var(--font-display); font-style: italic; font-size: 30px; font-weight: 400; line-height: 1.05; letter-spacing: -0.02em; color: var(--ink); margin-bottom: var(--s2); word-break: break-word; } .profile-card .meta { font-size: 14px; color: var(--ink-2); } .profile-card .avatar { width: 52px; height: 52px; border-radius: var(--r-pill); background: var(--paper-2); display: grid; place-items: center; flex-shrink: 0; font-family: var(--font-display); font-style: italic; font-size: 26px; font-weight: 400; color: var(--accent-1); border: 1px solid var(--line-strong); } .profile-card .meta-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); font-family: var(--font-mono); font-size: 11px; font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid var(--line); } .profile-card .meta-row .sep { color: var(--muted-2); } .profile-card .status-row { display: inline-flex; align-items: center; gap: var(--s2); } .profile-card .status-dot { width: 7px; height: 7px; border-radius: var(--r-pill); background: var(--status-active); box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-active) 22%, transparent); animation: pulse 2.5s ease-in-out infinite; } @keyframes pulse { 0%, 100% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-active) 22%, transparent); } 50% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--status-active) 0%, transparent); } } .profile-card .status-dot.lapsed { background: var(--status-lapsed); box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-lapsed) 22%, transparent); animation: none; } .profile-card .status-dot.grace { background: var(--status-grace); box-shadow: 0 0 0 3px color-mix(in srgb, var(--status-grace) 22%, transparent); } /* ============================================================ Section label ============================================================ */ .section-label { font-family: var(--font-mono); font-size: 11px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.14em; color: var(--muted); padding: 0 var(--s4); margin: var(--s7) 0 var(--s3); display: flex; align-items: center; gap: var(--s3); } .section-label::after { content: ""; flex: 1; height: 1px; background: var(--line-strong); } /* ============================================================ Menu (grouped list) ============================================================ */ .menu { background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-card); overflow: hidden; } .menu + .menu { margin-top: var(--s4); } .menu-item { display: flex; align-items: center; gap: var(--s4); padding: var(--s4) var(--s5); min-height: 64px; color: var(--ink); cursor: pointer; transition: background 0.12s; position: relative; } .menu-item + .menu-item::before { content: ""; position: absolute; top: 0; left: var(--s5); right: 0; height: 1px; background: var(--line); } .menu-item:active { background: var(--paper-2); } .menu-item .icon { width: 32px; height: 32px; display: grid; place-items: center; flex-shrink: 0; color: var(--ink); } .menu-item .icon svg { width: 22px; height: 22px; stroke-width: 1.6; } .menu-item .icon.green { color: var(--status-active); } .menu-item .icon.blue { color: var(--accent-1); } .menu-item .icon.gold { color: var(--accent-2); } .menu-item .text { flex: 1; min-width: 0; } .menu-item .label { font-family: var(--font-ui); font-size: 15px; font-weight: 500; letter-spacing: -0.01em; display: flex; align-items: center; gap: var(--s2); } .menu-item .sub { font-family: var(--font-mono); font-size: 11px; font-weight: 400; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); margin-top: 4px; } .menu-item .chevron { color: var(--muted-2); flex-shrink: 0; display: flex; align-items: center; } .menu-item .chevron svg { width: 18px; height: 18px; } .menu-item.disabled { cursor: not-allowed; } .menu-item.disabled .label, .menu-item.disabled .icon { color: var(--muted); opacity: 0.65; } .badge { display: inline-block; font-family: var(--font-mono); font-size: 9.5px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.1em; padding: 2px 8px; border-radius: var(--r-tag); background: var(--paper-2); color: var(--muted); vertical-align: 2px; } /* ============================================================ Footer ============================================================ */ .footer-hint { text-align: center; margin-top: var(--s8); padding: var(--s5) var(--s4) 0; border-top: 1px solid var(--line); } .footer-hint .signature { font-family: var(--font-display); font-style: italic; font-size: 16px; color: var(--ink-2); margin-bottom: var(--s2); } .footer-hint .meta { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); } .footer-hint a { color: var(--accent-1); } /* ============================================================ Error ============================================================ */ .error { background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-card); padding: var(--s7) var(--s5); text-align: center; color: var(--muted); } .error h3 { font-family: var(--font-display); font-style: italic; font-size: 22px; font-weight: 400; margin: 0 0 var(--s2); color: var(--ink); }