/* Минимальные стили веб-интерфейса Kind Clusters Dashboard. Автор: Сергей Антропов — https://devops.org.ru */ /* Тема: тёмная по умолчанию; светлая — html[data-theme="light"]. Переключатель в шапке + localStorage. */ html { font-family: system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, sans-serif; } html:not([data-theme="light"]) { color-scheme: dark; --bg: #0f1419; --fg: #e7ecf1; --muted: #8b98a5; --card: #1a2332; --accent: #3b82f6; --border: #2f3d52; /* Текст на кнопках/ссылках с фоном --accent (тёмная и светлая тема) */ --on-accent: #ffffff; /* Текстовые ссылки: та же синяя гамма, что и акценты UI (без отдельного цвета :visited) */ --link: #93c5fd; --link-hover: #e0f2fe; } /* Светлая тема: основной текст и акценты в синей гамме (как тёмная), без «чистого» чёрного */ html[data-theme="light"] { color-scheme: light; --bg: #eef2fb; --fg: #172c46; --muted: #5a6f8f; --card: #ffffff; --border: #b8c9e8; --accent: #3b82f6; --on-accent: #ffffff; --link: #2563eb; --link-hover: #1e3a8a; } body { margin: 0; padding: 0; background: var(--bg); color: var(--fg); line-height: 1.45; } body.modal-open { overflow: hidden; } /* Обычные ссылки : единый вид до и после перехода (перебиваем системный :visited). :where — низкая специфичность. */ a:where([href]) { color: var(--link); text-decoration: underline; /* Fallback без color-mix; поверх — смешивание с --accent */ text-decoration-color: rgba(59, 130, 246, 0.4); text-decoration-color: color-mix(in srgb, var(--accent) 42%, transparent); text-underline-offset: 0.22em; text-decoration-thickness: max(1px, 0.065em); text-decoration-skip-ink: auto; transition: color 0.15s ease, text-decoration-color 0.15s ease; } a:where([href]):visited { color: var(--link); text-decoration-color: rgba(59, 130, 246, 0.4); text-decoration-color: color-mix(in srgb, var(--accent) 42%, transparent); } a:where([href]):hover { color: var(--link-hover); text-decoration-color: rgba(59, 130, 246, 0.65); text-decoration-color: color-mix(in srgb, var(--accent) 72%, transparent); } a:where([href]):visited:hover { color: var(--link-hover); text-decoration-color: rgba(59, 130, 246, 0.65); text-decoration-color: color-mix(in srgb, var(--accent) 72%, transparent); } a:where([href]):focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; } /* Пропуск к основному содержимому (a11y) */ .skip-link { position: absolute; left: -9999px; top: 0.5rem; z-index: 200; padding: 0.5rem 1rem; background: var(--accent); color: var(--on-accent); border-radius: 6px; font-weight: 600; } .skip-link:focus { left: 0.5rem; outline: 2px solid var(--fg); outline-offset: 2px; } /* Верхняя навигация */ .top-nav { border-bottom: 1px solid var(--border); background: var(--card); } .top-nav-inner { max-width: 72rem; margin: 0 auto; padding: 0.65rem 1.25rem; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem; } .nav-brand { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; } .nav-brand-link { text-decoration: none; color: inherit; } .nav-brand-link:hover .nav-title { color: var(--accent); } .nav-brand-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 6px; } .nav-logo-img { width: 1.75rem; height: 1.75rem; flex-shrink: 0; display: block; } .nav-title { font-weight: 700; font-size: 1.05rem; } /* Тёмная тема: название в шапке — чисто белый (остальной текст остаётся --fg) */ html:not([data-theme="light"]) .nav-brand-link .nav-title { color: #ffffff; } html:not([data-theme="light"]) .nav-brand-link:hover .nav-title { color: var(--accent); } .nav-tag { font-size: 0.8rem; } /* Шапка: один flex-ряд, все пилюли + API + тема с align-items: center */ .nav-links { display: flex; flex-wrap: nowrap; align-items: center; gap: 0.45rem; } .nav-links.top-nav-actions { justify-content: flex-end; flex: 1 1 auto; min-width: 0; /* Не overflow-x: здесь — иначе обрезается .nav-dropdown__menu (absolute под кнопкой API). */ overflow: visible; } /* Горизонтальная прокрутка только подписей «Панель» / «Документация», без выпадающего меню. */ .nav-links-scroll { display: flex; flex-wrap: nowrap; align-items: center; gap: 0.45rem; min-width: 0; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: thin; /* * При overflow-x: auto вертикаль становится auto — обрезает translateY(-1px) и тень у .nav-pill:hover. * Внутренний padding даёт место сверху/снизу; API вне .nav-links-scroll, там обрезки не было. * z-index как у .nav-dropdown — общий stacking context при overflow. */ padding-top: 0.45rem; padding-bottom: 0.45rem; position: relative; z-index: 160; } /* Выпадающее меню «API»: Swagger, ReDoc, Health в отдельном окне */ .nav-dropdown { position: relative; z-index: 160; display: inline-flex; align-items: center; flex-shrink: 0; align-self: center; } .nav-dropdown__trigger { font: inherit; cursor: pointer; margin: 0; } .nav-dropdown__trigger::after { content: "▾"; margin-left: 0.35rem; font-size: 0.72em; opacity: 0.85; display: inline-block; transition: transform 0.18s ease; vertical-align: middle; } .nav-dropdown--open .nav-dropdown__trigger::after { transform: rotate(-180deg); } .nav-dropdown__menu { position: absolute; top: calc(100% + 0.35rem); right: 0; z-index: 160; min-width: 11rem; margin: 0; padding: 0.35rem 0; list-style: none; background: var(--card); border: 1px solid var(--border); border-radius: 10px; box-shadow: 0 10px 28px rgba(0, 0, 0, 0.35); } html[data-theme="light"] .nav-dropdown__menu { box-shadow: 0 10px 28px rgba(0, 0, 0, 0.12); } .nav-dropdown__menu[hidden] { display: none !important; } .nav-dropdown__menu li { margin: 0; } .nav-dropdown__link { display: flex; align-items: center; width: 100%; box-sizing: border-box; padding: 0.48rem 1rem; font-size: 0.8125rem; font-weight: 600; text-decoration: none; color: var(--fg); background: transparent; border: none; cursor: pointer; font-family: inherit; } .nav-dropdown__link:hover, .nav-dropdown__link:focus-visible { background: rgba(59, 130, 246, 0.14); color: var(--accent); outline: none; } .nav-dropdown__link.nav-pill--ext::after { content: "↗"; margin-left: auto; padding-left: 0.5rem; font-size: 0.72em; opacity: 0.72; font-weight: 700; } /* Переключатель светлая / тёмная тема (в конце шапки, высота как у пилюль) */ .theme-toggle { display: inline-flex; align-items: center; justify-content: center; padding: 0.42rem 0.75rem; min-width: 2.5rem; border-radius: 999px; font-size: 0.8125rem; font-weight: 600; border: 1px solid var(--border); background: rgba(0, 0, 0, 0.18); color: var(--fg); cursor: pointer; transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease, box-shadow 0.18s ease; } html[data-theme="light"] .theme-toggle { background: rgba(59, 130, 246, 0.1); border-color: rgba(59, 130, 246, 0.28); color: var(--accent); } .theme-toggle:hover { border-color: var(--accent); background: rgba(59, 130, 246, 0.14); color: var(--accent); box-shadow: 0 2px 12px rgba(59, 130, 246, 0.2); } .theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; } .theme-toggle__icon { display: block; width: 1.1rem; height: 1.1rem; flex-shrink: 0; } html[data-theme="light"] .theme-toggle__icon--sun { display: none; } html[data-theme="light"] .theme-toggle__icon--moon { display: block; } html:not([data-theme="light"]) .theme-toggle__icon--sun { display: block; } html:not([data-theme="light"]) .theme-toggle__icon--moon { display: none; } /* Визуально кнопка темы сидела ниже пилюль ( vs