Files
KindClustersDashboard/app/static/style.css
T
Sergey Antropoff d55e69c756 UI: карточка установленных аддонов на странице кластера; API аддонов и правки стилей
- Отдельная section.card после сводки ресурсов узлов, выравнивание бейджа Helm с заголовком
- Расширение эндпоинтов аддонов, схемы, helm_addons, cluster_addons.js/html
- Обновление api_routes.md
2026-04-04 14:13:01 +03:00

3454 lines
77 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Минимальные стили веб-интерфейса 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;
}
/* Светлая тема: основной текст и акценты в синей гамме (как тёмная), без «чистого» чёрного */
html[data-theme="light"] {
color-scheme: light;
--bg: #eef2fb;
--fg: #172c46;
--muted: #5a6f8f;
--card: #ffffff;
--border: #b8c9e8;
--accent: #3b82f6;
}
body {
margin: 0;
padding: 0;
background: var(--bg);
color: var(--fg);
line-height: 1.45;
}
body.modal-open {
overflow: hidden;
}
/* Пропуск к основному содержимому (a11y) */
.skip-link {
position: absolute;
left: -9999px;
top: 0.5rem;
z-index: 200;
padding: 0.5rem 1rem;
background: var(--accent);
color: #fff;
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;
}
.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;
}
/* Визуально кнопка темы сидела ниже пилюль (<a> vs <button>); поднимаем на 0.75rem */
.theme-toggle--nav-end {
flex-shrink: 0;
align-self: center;
padding-left: 0.65rem;
padding-right: 0.65rem;
min-height: calc(0.8125rem * 1.35 + 0.84rem);
box-sizing: border-box;
transform: translateY(-0.3rem);
}
/* Пункты меню: компактные «пилюли» */
.nav-link.nav-pill {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.42rem 0.95rem;
border-radius: 999px;
font-size: 0.8125rem;
font-weight: 600;
letter-spacing: 0.02em;
text-decoration: none;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.18);
color: var(--fg);
transition:
background 0.18s ease,
border-color 0.18s ease,
color 0.18s ease,
box-shadow 0.18s ease,
transform 0.12s ease;
}
.nav-link.nav-pill:hover {
text-decoration: none;
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);
transform: translateY(-1px);
}
.nav-link.nav-pill:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
}
/* Активный раздел: «Панель» на дашборде или «Документация» на /documentation */
.nav-link.nav-pill.nav-pill--active:not(.nav-pill--ext) {
border-color: rgba(59, 130, 246, 0.85);
box-shadow: 0 0 0 1px rgba(59, 130, 246, 0.35), 0 2px 14px rgba(59, 130, 246, 0.18);
background: rgba(59, 130, 246, 0.16);
color: #93c5fd;
}
html[data-theme="light"] .nav-link.nav-pill {
background: rgba(59, 130, 246, 0.1);
border-color: rgba(59, 130, 246, 0.28);
color: var(--fg);
}
html[data-theme="light"] .nav-link.nav-pill.nav-pill--active:not(.nav-pill--ext) {
color: #1d4ed8;
background: rgba(59, 130, 246, 0.18);
border-color: rgba(37, 99, 235, 0.45);
}
/* Внешние окна: иконка «новое окно» */
.nav-link.nav-pill--ext::after {
content: "↗";
margin-left: 0.35rem;
font-size: 0.72em;
opacity: 0.72;
font-weight: 700;
}
/* Обычная ссылка без пилюли (если понадобится) */
.nav-link:not(.nav-pill) {
color: var(--accent);
text-decoration: none;
font-size: 0.9rem;
}
.nav-link:not(.nav-pill):hover {
text-decoration: underline;
}
.app-main {
max-width: 72rem;
margin: 0 auto;
padding: 1.25rem;
outline: none;
}
.app-footer {
max-width: 72rem;
margin: 0 auto;
padding: 1rem 1.25rem 2rem;
border-top: 1px solid var(--border);
font-size: 0.85rem;
}
.footer-inner {
text-align: center;
}
.footer-line {
margin: 0 0 0.5rem;
}
.footer-copyright {
margin: 0;
font-size: 0.9rem;
color: var(--fg);
}
.footer-copyright a {
color: var(--accent);
font-weight: 600;
}
/* Верхний ряд: CTA «Создать кластер» и статистика по ~50% ширины */
.top-dashboard-row {
display: grid;
gap: 1rem;
margin-bottom: 1rem;
align-items: stretch;
}
@media (min-width: 960px) {
.top-dashboard-row {
grid-template-columns: 1fr 1fr;
}
}
/* Левая карточка — переход к форме создания */
.cta-hero-card {
margin-bottom: 0;
display: flex;
align-items: center;
justify-content: center;
min-height: min(16rem, 42vh);
}
.cta-hero-inner {
text-align: center;
padding: 1.35rem 1.25rem;
width: 100%;
max-width: 26rem;
margin: 0 auto;
}
.cta-hero-card .page-title {
margin: 0 0 0.5rem;
font-size: clamp(1.35rem, 2.5vw, 1.65rem);
}
.cta-hero-lead {
margin: 0 0 2.15rem;
font-size: 0.92rem;
line-height: 1.5;
max-width: 22rem;
margin-left: auto;
margin-right: auto;
}
.cta-hero-inner .btn-cta-large {
margin-top: 0.15rem;
}
.stats-side-card {
display: flex;
flex-direction: column;
gap: 0.85rem;
}
.stats-side-card h2 {
margin: 0;
flex-shrink: 0;
font-size: 1.05rem;
}
/* Отдельная карточка на панели: донаты + список кластеров (GET /stats) */
.home-resources-summary-inner {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.home-resources-summary-card .donuts-card-title {
margin-bottom: 0.5rem;
}
/* Пояснение: узлы kind и метрики идут через Docker или Podman (CONTAINER_CLI) */
.stats-engine-hint {
margin: 0;
flex-shrink: 0;
font-size: 0.8rem;
line-height: 1.35;
}
/* Одна карточка «Ошибка» на всю ширину блока статистики (health или /stats) */
.stats-failure-wrap {
width: 100%;
flex-shrink: 0;
}
.stats-failure-card {
width: 100%;
box-sizing: border-box;
min-height: 4.75rem;
padding: 0.85rem 0.65rem;
}
/* Среда: Docker API · Kind · Kubectl (3 в ряд); число каталогов — в сетке метрик под ними */
.stats-env-cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.65rem;
flex-shrink: 0;
}
@media (max-width: 520px) {
.stats-env-cards {
grid-template-columns: 1fr;
}
}
.stats-env-placeholder {
grid-column: 1 / -1;
margin: 0;
font-size: 0.85rem;
text-align: center;
padding: 0.5rem 0;
}
.stats-env-card {
min-height: 4.5rem;
padding: 0.65rem 0.4rem;
}
.stats-env-card--ok {
border-color: rgba(34, 197, 94, 0.45);
background: rgba(34, 197, 94, 0.08);
}
.stats-env-card--bad {
border-color: rgba(239, 68, 68, 0.45);
background: rgba(239, 68, 68, 0.08);
}
.stats-env-card--bad .stats-tile__value {
color: #f87171;
}
html[data-theme="light"] .stats-env-card--bad .stats-tile__value {
color: #b91c1c;
}
.stats-env-card__detail {
display: block;
font-size: 0.7rem;
line-height: 1.3;
margin-top: 0.35rem;
text-align: center;
word-break: break-word;
}
.stats-env-card--metric {
border-color: var(--border);
background: rgba(0, 0, 0, 0.08);
}
html[data-theme="light"] .stats-env-card--metric {
background: rgba(59, 130, 246, 0.07);
}
/* Метрики панели: по 3 карточки в ряд */
.stats-metrics-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.65rem;
flex: 1 1 auto;
align-content: start;
}
@media (max-width: 520px) {
.stats-metrics-grid {
grid-template-columns: 1fr;
}
}
.stats-tile {
border-radius: 10px;
padding: 0.72rem 0.45rem;
text-align: center;
display: flex;
flex-direction: column;
gap: 0.3rem;
justify-content: center;
min-height: 4.1rem;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.1);
}
html[data-theme="light"] .stats-tile {
background: rgba(59, 130, 246, 0.07);
}
.stats-tile__value {
font-size: 1.28rem;
font-weight: 700;
font-variant-numeric: tabular-nums;
color: var(--accent);
line-height: 1.15;
}
.stats-tile__label {
font-size: 0.68rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.045em;
color: var(--muted);
line-height: 1.25;
}
/* Метрики узла (общие стили: донаты на главной и раскрытие под строкой кластера) */
.stats-node-res {
margin-bottom: 0.45rem;
padding: 0.35rem 0.45rem;
border-radius: 6px;
background: rgba(0, 0, 0, 0.12);
border: 1px solid var(--border);
}
.stats-node-res code {
display: block;
font-size: 0.76rem;
margin-bottom: 0.25rem;
word-break: break-all;
}
.stats-node-res__metrics {
margin: 0;
padding-left: 1rem;
list-style: disc;
}
.stats-node-res__metrics li {
margin: 0.1rem 0;
}
.stats-node-res__metrics strong {
font-weight: 600;
color: var(--muted);
}
html[data-theme="light"] .stats-node-res {
background: rgba(59, 130, 246, 0.07);
}
.btn-cta-large {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: min(22rem, 100%);
margin-top: 0;
padding: 0.95rem 2.25rem;
font-size: 1.15rem;
font-weight: 650;
border-radius: 12px;
text-decoration: none;
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18);
border: 1px solid transparent;
background: var(--accent);
color: #fff;
cursor: pointer;
}
a.btn-cta-large:hover {
filter: brightness(1.08);
}
/* Сводка-денаты по узлам */
.aggregate-donuts-card {
margin-bottom: 1rem;
}
.donuts-card-title {
margin: 0 0 0.75rem;
}
.donut-grid {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-evenly;
align-items: flex-start;
gap: 1rem 1.5rem;
overflow-x: auto;
padding-bottom: 0.35rem;
-webkit-overflow-scrolling: touch;
scrollbar-width: thin;
}
.donut-item {
flex: 0 0 auto;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
gap: 0.35rem;
}
.donut-svg {
width: 6.5rem;
height: 6.5rem;
flex-shrink: 0;
}
.donut-track {
stroke: var(--border);
}
.donut-fill {
stroke: var(--accent);
stroke-linecap: round;
}
.donut-meta {
display: flex;
flex-direction: column;
gap: 0.12rem;
max-width: 11rem;
}
.donut-meta__title {
font-size: 0.72rem;
font-weight: 650;
text-transform: uppercase;
letter-spacing: 0.03em;
color: var(--muted);
}
.donut-meta__val {
font-size: 0.88rem;
font-weight: 600;
word-break: break-word;
}
.donut-meta__sub {
font-size: 0.75rem;
}
.aggregate-donuts-placeholder {
margin: 0;
font-size: 0.9rem;
line-height: 1.45;
max-width: 40rem;
}
.cluster-nodes-resources__empty {
margin: 0.25rem 0 0;
font-size: 0.85rem;
}
/* Карточки узлов: полосы CPU, RAM %, память от лимита, сеть, диск + подсказка справа */
.cluster-nodes-resources__cards-row {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: stretch;
gap: 0.75rem;
margin-top: 0.35rem;
overflow-x: auto;
padding-bottom: 0.25rem;
-webkit-overflow-scrolling: touch;
scrollbar-width: thin;
}
.cluster-node-res-card {
flex: 0 0 auto;
width: min(17.5rem, 88vw);
min-width: 14rem;
box-sizing: border-box;
padding: 0.55rem 0.65rem 0.5rem;
border-radius: 10px;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.12);
border-left: 3px solid var(--accent);
}
html[data-theme="light"] .cluster-node-res-card {
background: rgba(59, 130, 246, 0.08);
}
.cluster-node-res-card__head {
margin: 0 0 0.45rem;
}
.cluster-node-res-card__head code {
font-size: 0.78rem;
word-break: break-all;
line-height: 1.35;
}
.cluster-node-res-card__bars {
display: flex;
flex-direction: column;
gap: 0.35rem;
}
.cluster-node-res-card__bar-row {
display: grid;
grid-template-columns: 3rem minmax(0, 1fr) minmax(2.8rem, 4.5rem);
align-items: center;
gap: 0.3rem 0.35rem;
}
.cluster-node-res-card__bar-hint {
font-size: 0.62rem;
line-height: 1.2;
text-align: right;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
}
.cluster-node-res-card__bar-label {
font-size: 0.68rem;
font-weight: 650;
text-transform: uppercase;
letter-spacing: 0.02em;
color: var(--muted);
}
.cluster-node-res-card__bar-track {
height: 0.45rem;
border-radius: 999px;
background: rgba(255, 255, 255, 0.08);
overflow: hidden;
}
html[data-theme="light"] .cluster-node-res-card__bar-track {
background: rgba(0, 0, 0, 0.06);
}
.cluster-node-res-card__bar-fill {
height: 100%;
border-radius: inherit;
background: linear-gradient(90deg, rgba(59, 130, 246, 0.55), var(--accent));
min-width: 2px;
transition: width 0.25s ease;
}
.cluster-node-res-card__foot {
margin-top: 0.45rem;
font-size: 0.72rem;
line-height: 1.4;
word-break: break-word;
}
.cluster-create-hero {
margin-bottom: 1.35rem;
}
/* Карточка формы: чуть плотнее внутри, заголовок отступает от полей */
.card.create-cluster-card {
padding: 0.85rem 1rem 1rem;
margin-bottom: 1rem;
}
.create-cluster-card__title {
margin: 0 0 1rem;
padding: 0;
font-size: 1.02rem;
}
/* Сетка 2×2: имя | тег, затем подсказка на всю ширину, workers | версия; выравнивание по нижнему краю ячеек */
.create-form-grid {
display: grid;
gap: 0.4rem 1.15rem;
margin-top: 0;
}
.create-form-field {
display: flex;
flex-direction: column;
gap: 0.2rem;
min-width: 0;
}
.create-form-field > label {
margin: 0;
font-size: 0.8125rem;
line-height: 1.3;
font-weight: 600;
}
.create-form-grid .create-form-field input:not([type="checkbox"]),
.create-form-grid .create-form-field select {
width: 100%;
max-width: none;
margin: 0;
padding: 0.35rem 0.5rem;
min-height: 2.3rem;
box-sizing: border-box;
line-height: 1.25;
}
@media (min-width: 640px) {
.create-form-grid {
grid-template-columns: 1fr 1fr;
align-items: end;
}
}
.create-form-span {
grid-column: 1 / -1;
}
/* Ссылка на актуальные теги kindest/node (Docker Hub), новая вкладка */
.create-form-doc-link {
color: var(--accent);
font-weight: 650;
text-decoration: none;
}
.create-form-doc-link:hover {
text-decoration: underline;
text-underline-offset: 2px;
}
.create-form-doc-link:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
border-radius: 3px;
}
.create-form-doc-link__ext {
margin-left: 0.12rem;
font-size: 0.82em;
font-weight: 700;
color: var(--accent);
opacity: 0.85;
}
.create-form-label-rest {
font-weight: 600;
}
.create-ver-hint {
margin: 0;
font-size: 0.8rem;
line-height: 1.35;
}
.create-ver-hint--full {
grid-column: 1 / -1;
margin: 0.1rem 0 0.25rem;
}
.create-form-grid .create-actions {
margin-top: 0.35rem;
padding-top: 0.15rem;
width: 100%;
justify-content: center;
}
.create-form-grid .create-actions button {
margin-top: 0;
}
/* Одна карточка: заголовок + описание + строка состояния среды */
.hero-panel {
margin-bottom: 1rem;
}
.hero-panel-main {
margin-bottom: 0.85rem;
}
.hero-panel .page-title {
margin: 0 0 0.35rem;
}
.hero-panel .page-lead {
margin: 0;
max-width: 48rem;
}
.hero-panel-status {
margin: 0;
border-radius: 8px;
padding: 0.65rem 0.85rem;
font-size: 0.9rem;
border: 1px solid var(--border);
}
.hero-panel-status.ok {
border-color: #15803d;
background: rgba(34, 197, 94, 0.12);
}
.hero-panel-status.degraded {
border-color: #b45309;
background: rgba(245, 158, 11, 0.12);
}
.hero-panel-status.err {
border-color: #b91c1c;
background: rgba(239, 68, 68, 0.12);
}
/* Страница «Кластеры»: заголовок слева, кнопка «Создать кластер» справа */
.clusters-page-hero-row {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: space-between;
gap: 1rem 1.5rem;
}
.clusters-page-hero-text {
flex: 1 1 14rem;
min-width: 0;
}
.clusters-page-hero-lead {
margin: 0;
}
.clusters-page-hero-actions {
flex: 0 0 auto;
display: flex;
align-items: center;
padding-top: 0.15rem;
}
.clusters-page-create-btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.6rem 1.35rem;
font-size: 0.95rem;
font-weight: 650;
border-radius: 10px;
text-decoration: none;
border: 1px solid transparent;
background: var(--accent);
color: #fff;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.14);
white-space: nowrap;
}
.clusters-page-create-btn:hover {
filter: brightness(1.08);
}
/* Прогресс создания кластера */
.create-progress-wrap {
margin-top: 1rem;
padding-top: 0.75rem;
border-top: 1px solid var(--border);
}
.create-progress-hint {
margin: 0 0 0.65rem;
font-size: 0.85rem;
}
.progress-track {
height: 0.65rem;
border-radius: 999px;
background: rgba(0, 0, 0, 0.25);
border: 1px solid var(--border);
overflow: hidden;
}
.progress-bar {
height: 100%;
border-radius: 999px;
background: linear-gradient(90deg, var(--accent), #60a5fa);
transition: width 0.35s ease;
}
.progress-label {
margin: 0.45rem 0 0.65rem;
font-size: 0.88rem;
min-height: 1.35rem;
}
#create-progress-wrap .btn-secondary {
margin-top: 0;
}
/* Журнал kind create в панели прогресса (потоковые строки из API) */
.job-log-panel-wrap {
margin: 0 0 0.65rem;
}
.job-log-label {
display: block;
font-size: 0.8rem;
margin-bottom: 0.25rem;
}
.job-log-panel {
margin: 0;
max-height: min(55vh, 420px);
overflow: auto;
padding: 0.5rem 0.65rem;
font-size: 0.78rem;
line-height: 1.35;
background: rgba(0, 0, 0, 0.2);
border: 1px solid var(--border);
border-radius: 6px;
white-space: pre-wrap;
word-break: break-word;
}
/* Заголовок блока заданий + кнопка «Журнал» у failed/cancelled */
.jobs-msg-cell .jobs-msg-primary {
margin-bottom: 0.35rem;
}
.jobs-open-log-btn {
margin-top: 0.25rem;
font-size: 0.875rem;
}
.jobs-card-toolbar {
margin-bottom: 0.65rem;
}
.jobs-card-title {
margin: 0;
font-size: 1.15rem;
line-height: 1.3;
}
.page-intro {
margin-bottom: 1rem;
}
.page-title {
margin: 0 0 0.35rem;
font-size: 1.35rem;
}
.page-lead {
margin: 0;
max-width: 42rem;
}
.toolbar {
margin-bottom: 1rem;
}
/* Тост уведомлений */
.toast {
position: fixed;
top: 1rem;
right: 1rem;
z-index: 150;
max-width: min(22rem, calc(100vw - 2rem));
padding: 0.65rem 1rem;
border-radius: 8px;
border: 1px solid var(--border);
background: var(--card);
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.25);
font-size: 0.9rem;
}
.toast-ok {
border-color: #15803d;
}
.toast-error {
border-color: #b91c1c;
}
/* Бейджи статусов */
.badge {
display: inline-block;
padding: 0.15rem 0.45rem;
border-radius: 999px;
font-size: 0.75rem;
font-weight: 600;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.15);
}
html[data-theme="light"] .badge {
background: rgba(59, 130, 246, 0.12);
}
.badge-ok {
border-color: #15803d;
color: #4ade80;
}
/* Светлая тема: насыщенный зелёный текст и фон — иначе «Запущен» сливается с белым карточным фоном */
html[data-theme="light"] .badge-ok {
border-color: #166534;
color: #14532d;
background: rgba(22, 101, 52, 0.12);
}
.badge-err {
border-color: #b91c1c;
color: #f87171;
}
.badge-run {
border-color: #b45309;
color: #fbbf24;
}
.badge-cancelled {
border-color: #6b7280;
color: #d1d5db;
}
.badge-stopped {
border-color: #b45309;
color: #fcd34d;
}
.cluster-name {
font-weight: 600;
}
/* Состояние загрузки таблиц */
.job-details {
margin-top: 0.75rem;
border: 1px solid var(--border);
border-radius: 8px;
padding: 0.5rem 0.75rem;
background: rgba(0, 0, 0, 0.12);
}
html[data-theme="light"] .job-details {
background: rgba(59, 130, 246, 0.08);
}
.job-details summary {
cursor: pointer;
font-size: 0.9rem;
font-weight: 600;
}
.job-json-pre {
max-height: 12rem;
margin-top: 0.5rem;
}
/* Спиннер в модалке */
.modal-head {
margin-bottom: 0.5rem;
align-items: flex-start;
}
.modal-head--cluster {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.65rem;
margin-bottom: 0.65rem;
text-align: center;
}
.modal-title-text--center {
width: 100%;
text-align: center;
padding-right: 0;
flex: none;
}
.modal-toolbar {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 0.65rem 1rem;
}
.modal-title-text {
margin: 0;
font-size: 1.05rem;
flex: 1;
padding-right: 0.5rem;
}
.modal-sub {
margin: 0 0 0.75rem;
}
.modal-section-title {
margin: 0.5rem 0 0;
font-size: 0.85rem;
}
.modal-spinner {
display: flex;
align-items: center;
justify-content: center;
gap: 0.65rem;
padding: 1rem 0;
}
.spinner {
width: 1.5rem;
height: 1.5rem;
border: 3px solid var(--border);
border-top-color: var(--accent);
border-radius: 50%;
animation: spin 0.7s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
button:disabled,
input:disabled,
select:disabled {
opacity: 0.55;
cursor: not-allowed;
}
button:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
summary:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
.header h1 {
margin: 0 0 0.25rem;
font-size: 1.5rem;
}
.muted {
color: var(--muted);
}
.grid {
display: grid;
gap: 1rem;
margin: 1.25rem 0;
}
@media (min-width: 900px) {
.grid {
grid-template-columns: 1fr 1fr;
align-items: start;
}
}
.card {
background: var(--card);
border: 1px solid var(--border);
border-radius: 10px;
padding: 1rem 1.1rem;
}
.card h2 {
margin-top: 0;
font-size: 1.1rem;
}
label {
display: block;
margin: 0.65rem 0 0.25rem;
font-size: 0.9rem;
}
input,
select,
button {
font: inherit;
}
input:not([type="checkbox"]),
select {
width: 100%;
max-width: 28rem;
padding: 0.45rem 0.55rem;
border-radius: 6px;
border: 1px solid var(--border);
background: transparent;
color: inherit;
}
/* Чекбоксы: без растягивания на ширину полей text/select */
input[type="checkbox"] {
width: auto;
max-width: none;
}
button {
margin-top: 0.75rem;
padding: 0.45rem 0.85rem;
border-radius: 6px;
border: 1px solid var(--border);
background: var(--accent);
color: #fff;
cursor: pointer;
}
button:hover {
filter: brightness(1.08);
}
.row {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
align-items: center;
}
.row.spread {
justify-content: space-between;
align-items: center;
}
.mono {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
font-size: 0.85rem;
white-space: pre-wrap;
word-break: break-word;
background: rgba(0, 0, 0, 0.2);
padding: 0.6rem;
border-radius: 6px;
max-height: 14rem;
overflow: auto;
}
html[data-theme="light"] .mono {
background: rgba(59, 130, 246, 0.1);
}
.table-wrap {
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.9rem;
}
th .th-hint {
font-weight: 500;
opacity: 0.7;
font-size: 0.82em;
}
th,
td {
border-bottom: 1px solid var(--border);
padding: 0.45rem 0.35rem;
text-align: left;
vertical-align: top;
}
.msg {
margin-top: 0.5rem;
}
.hidden {
display: none;
}
.footer {
margin-top: 2rem;
font-size: 0.9rem;
}
.footer a {
color: var(--accent);
}
/* Плашка состояния среды (Docker/Podman, kind, kubectl) */
.status-banner {
border-radius: 8px;
padding: 0.65rem 0.85rem;
margin-bottom: 1rem;
font-size: 0.9rem;
border: 1px solid var(--border);
}
.status-banner.ok {
border-color: #15803d;
background: rgba(34, 197, 94, 0.12);
}
.status-banner.degraded {
border-color: #b45309;
background: rgba(245, 158, 11, 0.12);
}
.status-banner.err {
border-color: #b91c1c;
background: rgba(239, 68, 68, 0.12);
}
.stats-dl {
display: grid;
grid-template-columns: auto 1fr;
gap: 0.25rem 1rem;
margin: 0;
font-size: 0.9rem;
}
.stats-dl dt {
margin: 0;
color: var(--muted);
}
.stats-dl dd {
margin: 0;
}
button.btn-secondary,
a.btn-secondary {
background: transparent;
color: var(--accent);
border-color: var(--accent);
text-decoration: none;
display: inline-block;
margin-top: 0;
margin-right: 0.35rem;
padding: 0.35rem 0.65rem;
font-size: 0.85rem;
}
button.btn-small {
margin-top: 0;
padding: 0.3rem 0.55rem;
font-size: 0.8rem;
}
/* Таблица кластеров: колонка «Имя» 40 % ширины таблицы (без width:1%, из‑за него в UI казалось «1 %») */
#tbl-clusters {
table-layout: fixed;
width: 90%;
}
#tbl-clusters th.col-cluster-name,
#tbl-clusters td.col-cluster-name {
width: 40%;
min-width: 0;
text-align: left;
vertical-align: middle;
overflow-wrap: break-word;
word-break: break-word;
}
/* Остальные колонки — компактно; содержимое по центру */
#tbl-clusters th.col-kind,
#tbl-clusters td.col-kind,
#tbl-clusters th.col-kubeconfig,
#tbl-clusters td.col-kubeconfig,
#tbl-clusters th.col-workers,
#tbl-clusters td.col-workers,
#tbl-clusters th.col-state,
#tbl-clusters td.col-state {
padding-left: 0.5rem;
padding-right: 0.5rem;
text-align: center;
vertical-align: middle;
white-space: nowrap;
}
#tbl-clusters th.col-version,
#tbl-clusters td.col-version {
padding-left: 0.5rem;
padding-right: 0.5rem;
text-align: center;
vertical-align: middle;
}
#tbl-clusters th.col-version {
white-space: nowrap;
}
#tbl-clusters td.col-version {
white-space: normal;
word-break: break-word;
}
/* Колонка «Действия»: доля от оставшихся 50 %, иконки в ряд */
#tbl-clusters th.col-actions,
#tbl-clusters td.actions {
padding: 0.3rem 0.25rem;
text-align: center;
vertical-align: middle;
}
#tbl-clusters td.actions {
white-space: nowrap;
}
.actions-toolbar {
display: inline-flex;
flex-wrap: nowrap;
align-items: center;
gap: 0.12rem;
}
/* Обёртка иконки; текст подсказки — в #action-tooltip (JS, fixed), иначе режется overflow таблицы */
.icon-tooltip-host {
position: relative;
display: inline-flex;
vertical-align: middle;
}
/* Плавающая подсказка над/под иконкой (полный текст, переносы строк) */
.action-tooltip-floating {
position: fixed;
z-index: 400;
left: 0;
top: 0;
max-width: min(22rem, calc(100vw - 20px));
max-height: min(70vh, 22rem);
overflow-y: auto;
padding: 0.55rem 0.7rem;
box-sizing: border-box;
font-size: 0.8rem;
font-weight: 500;
line-height: 1.45;
text-align: left;
white-space: normal;
overflow-wrap: break-word;
word-break: break-word;
hyphens: auto;
color: var(--fg);
background: var(--card);
border: 1px solid var(--border);
border-radius: 8px;
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
pointer-events: none;
}
.action-tooltip-floating.hidden {
display: none;
}
.icon-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 1.95rem;
height: 1.95rem;
padding: 0;
margin: 0;
border: 1px solid var(--border);
border-radius: 6px;
background: rgba(0, 0, 0, 0.15);
color: var(--fg);
cursor: pointer;
transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.icon-btn:hover:not(:disabled) {
background: rgba(59, 130, 246, 0.2);
border-color: var(--accent);
color: var(--accent);
}
.icon-btn:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
.icon-btn:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.icon-btn svg {
width: 1.05rem;
height: 1.05rem;
flex-shrink: 0;
}
.icon-btn--secondary {
background: transparent;
}
.icon-btn--danger {
color: #f87171;
border-color: rgba(185, 28, 28, 0.5);
background: rgba(185, 28, 28, 0.08);
}
.icon-btn--danger:hover:not(:disabled) {
color: #fca5a5;
border-color: #ef4444;
background: rgba(239, 68, 68, 0.14);
}
html[data-theme="light"] .icon-btn {
background: rgba(59, 130, 246, 0.08);
}
html[data-theme="light"] .icon-btn--danger {
color: #b91c1c;
}
/* Модальное окно «Состояние кластера» */
.modal-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.55);
display: flex;
align-items: center;
justify-content: center;
padding: 1.25rem 1rem;
z-index: 100;
overflow-y: auto;
}
.modal-overlay.hidden {
display: none;
}
/* Поверх модалки «Состояние» (z-index 100), если когда-либо понадобится стек */
.confirm-modal-overlay {
z-index: 150;
}
/* Информация после сохранения конфига на странице редактирования кластера */
.cluster-edit-save-modal-overlay {
z-index: 160;
}
.modal-box--cluster-edit-save {
max-width: min(34rem, 100%);
text-align: left;
}
.cluster-edit-save-modal-title {
margin: 0 0 0.65rem;
font-size: 1.05rem;
text-align: center;
}
.cluster-edit-save-modal-body {
margin: 0;
font-size: 0.92rem;
line-height: 1.55;
}
.cluster-edit-save-modal-body p {
margin: 0 0 0.65rem;
}
.cluster-edit-save-modal-body p:last-child {
margin-bottom: 0;
}
.cluster-edit-save-modal-body ul {
margin: 0.35rem 0 0.85rem 1.15rem;
padding: 0;
list-style: disc;
}
.cluster-edit-save-modal-body li {
margin-bottom: 0.45rem;
}
.cluster-edit-save-modal-body li:last-child {
margin-bottom: 0;
}
.cluster-edit-save-modal-body code {
font-size: 0.86em;
word-break: break-word;
}
.cluster-edit-save-modal-body .cluster-edit-save-modal-lead {
margin-top: 0;
font-weight: 500;
color: var(--text);
}
/* Журнал развёртывания: поверх шапки и выпадающего меню API (до z-index 160); ниже полноэкранного спиннера (9998) */
.provision-log-modal-overlay {
z-index: 500;
}
.job-log-modal-overlay {
z-index: 500;
}
.modal-box--job-log .job-log-modal-body {
max-height: min(70vh, 32rem);
overflow: auto;
margin: 0.35rem 0 0;
padding: 0.65rem 0.75rem;
font-size: 0.78rem;
line-height: 1.45;
white-space: pre-wrap;
word-break: break-word;
border-radius: 8px;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.2);
}
html[data-theme="light"] .modal-box--job-log .job-log-modal-body {
background: rgba(0, 0, 0, 0.04);
}
.modal-box--provision-log .provision-log-body {
max-height: min(70vh, 32rem);
overflow: auto;
margin: 0.35rem 0 0;
padding: 0.65rem 0.75rem;
font-size: 0.78rem;
line-height: 1.45;
white-space: pre-wrap;
word-break: break-word;
border-radius: 8px;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.2);
}
html[data-theme="light"] .modal-box--provision-log .provision-log-body {
background: rgba(0, 0, 0, 0.04);
}
.modal-box--confirm {
max-width: 24rem;
text-align: center;
}
.confirm-modal-title {
margin: 0 0 0.5rem;
font-size: 1.05rem;
text-align: center;
}
.confirm-modal-message {
margin: 0 0 0.25rem;
white-space: pre-wrap;
text-align: center;
}
.confirm-modal-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 0.65rem 0.85rem;
margin-top: 1.15rem;
}
.confirm-modal-actions button {
margin-top: 0;
}
.modal-box {
background: var(--card);
border: 1px solid var(--border);
border-radius: 10px;
max-width: 52rem;
width: 100%;
max-height: calc(100vh - 2.5rem);
max-height: calc(100dvh - 2.5rem);
overflow-y: auto;
padding: 1rem 1.15rem;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.35);
margin: auto;
}
.modal-box h3 {
margin: 0 0 0.75rem;
font-size: 1.05rem;
}
.modal-box pre {
max-height: 40vh;
margin: 0.5rem 0 1rem;
}
.modal-close {
flex-shrink: 0;
margin-top: 0;
}
button.btn-danger,
a.btn-danger {
background: transparent;
color: #f87171;
border-color: #b91c1c;
}
html[data-theme="light"] button.btn-danger,
html[data-theme="light"] a.btn-danger {
color: #b91c1c;
}
button.btn-danger:hover {
filter: brightness(1.12);
}
/* Хлебные крошки на странице документации — ширина как у .app-main (с дашбордом). */
.doc-breadcrumbs {
max-width: none;
width: 100%;
margin: 0 0 0.65rem;
padding: 0;
box-sizing: border-box;
}
.doc-breadcrumbs__list {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.35rem 0.15rem;
margin: 0;
padding: 0;
list-style: none;
font-size: 0.8125rem;
}
.doc-breadcrumbs__item {
display: inline-flex;
align-items: center;
gap: 0.35rem;
}
.doc-breadcrumbs__item:not(:last-child)::after {
content: "";
opacity: 0.45;
font-weight: 500;
margin-left: 0.2rem;
}
.doc-breadcrumbs__link {
color: var(--accent);
text-decoration: none;
}
.doc-breadcrumbs__link:hover {
text-decoration: underline;
text-underline-offset: 2px;
}
.doc-breadcrumbs__item--current {
color: var(--muted);
font-weight: 600;
max-width: 100%;
word-break: break-word;
}
/* Страница «Документация»: Markdown → карточки; ширина блока = ширина main (как card на дашборде). */
.readme-doc-shell {
max-width: none;
width: 100%;
margin: 0;
box-sizing: border-box;
}
.readme-doc-loading {
margin: 0 0 0.75rem;
font-size: 0.9rem;
}
.readme-doc-page {
width: 100%;
}
.readme-doc-page-inner {
width: 100%;
}
.readme-doc-root {
display: flex;
flex-direction: column;
gap: 1rem;
}
.readme-section-card {
margin: 0;
}
/* Заголовок секции (h2) и содержимое — в одной карточке: без лишнего зазора сверху у первого заголовка */
.readme-section-card.markdown-body > h1:first-child,
.readme-section-card.markdown-body > h2:first-child {
margin-top: 0;
}
.readme-section-card.markdown-body {
font-size: 0.95rem;
line-height: 1.55;
}
.readme-section-card.markdown-body h1,
.readme-section-card.markdown-body h2,
.readme-section-card.markdown-body h3,
.readme-section-card.markdown-body h4 {
margin: 1.25rem 0 0.5rem;
line-height: 1.25;
font-weight: 650;
}
.readme-section-card.markdown-body h1 {
font-size: 1.45rem;
border-bottom: 1px solid var(--border);
padding-bottom: 0.35rem;
}
.readme-section-card.markdown-body h2 {
font-size: 1.2rem;
border-bottom: 1px solid var(--border);
padding-bottom: 0.25rem;
}
.readme-section-card.markdown-body h3 {
font-size: 1.05rem;
}
.readme-section-card.markdown-body p {
margin: 0.5rem 0;
}
.readme-section-card.markdown-body ul,
.readme-section-card.markdown-body ol {
margin: 0.5rem 0;
padding-left: 1.35rem;
}
.readme-section-card.markdown-body li {
margin: 0.2rem 0;
}
.readme-section-card.markdown-body a {
color: var(--accent);
text-decoration: underline;
text-underline-offset: 2px;
}
.readme-section-card.markdown-body a:hover {
filter: brightness(1.15);
}
.readme-section-card.markdown-body code {
font-size: 0.88em;
padding: 0.12em 0.35em;
border-radius: 4px;
background: rgba(0, 0, 0, 0.22);
border: 1px solid var(--border);
}
.readme-section-card.markdown-body pre {
margin: 0.65rem 0;
padding: 0.65rem 0.85rem;
overflow-x: auto;
border-radius: 8px;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.25);
font-size: 0.82rem;
line-height: 1.4;
}
.readme-section-card.markdown-body pre code {
padding: 0;
border: none;
background: transparent;
font-size: inherit;
}
.readme-section-card.markdown-body blockquote {
margin: 0.65rem 0;
padding: 0.35rem 0.75rem;
border-left: 4px solid var(--accent);
background: rgba(59, 130, 246, 0.08);
color: var(--muted);
}
.readme-section-card.markdown-body table {
width: 100%;
border-collapse: collapse;
margin: 0.75rem 0;
font-size: 0.88rem;
}
.readme-section-card.markdown-body th,
.readme-section-card.markdown-body td {
border: 1px solid var(--border);
padding: 0.4rem 0.55rem;
text-align: left;
}
.readme-section-card.markdown-body th {
background: rgba(0, 0, 0, 0.15);
font-weight: 600;
}
.readme-section-card.markdown-body hr {
border: none;
border-top: 1px solid var(--border);
margin: 1.25rem 0;
}
html[data-theme="light"] .readme-section-card.markdown-body code {
background: rgba(59, 130, 246, 0.1);
}
html[data-theme="light"] .readme-section-card.markdown-body pre {
background: rgba(59, 130, 246, 0.06);
}
html[data-theme="light"] .readme-section-card.markdown-body th {
background: rgba(59, 130, 246, 0.14);
}
/* Страница кластера: /cluster/<имя> — сводка, kubectl, действия */
.cluster-detail-breadcrumb {
margin: 0 0 1rem;
font-size: 0.9rem;
}
.cluster-detail-breadcrumb a {
color: var(--accent);
text-decoration: none;
}
.cluster-detail-breadcrumb a:hover {
text-decoration: underline;
}
/* Ссылка на страницу кластера в таблице: контраст в светлой и тёмной теме */
.cluster-name-link {
text-decoration: none;
font-weight: 600;
border-bottom: 1px solid transparent;
}
html[data-theme="light"] .cluster-name-link {
color: #0369a1;
}
html[data-theme="light"] .cluster-name-link:hover {
color: #0c4a6e;
border-bottom-color: #0369a1;
}
html[data-theme="light"] .cluster-name-link .cluster-name {
color: inherit;
}
html[data-theme="dark"] .cluster-name-link {
color: #7dd3fc;
}
html[data-theme="dark"] .cluster-name-link:hover {
color: #e0f2fe;
border-bottom-color: #38bdf8;
}
html[data-theme="dark"] .cluster-name-link .cluster-name {
color: inherit;
}
/* Страница кластера: отступы между карточками */
body.cluster-detail-page .app-main > .card {
margin-bottom: 1.35rem;
}
body.cluster-detail-page .app-main > .card:last-child {
margin-bottom: 0;
}
/* Шапка страницы кластера: слева заголовок и кнопки, справа мета столбиком */
.cluster-detail-hero-layout {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: space-between;
gap: 1rem 1.75rem;
}
.cluster-detail-hero-left {
flex: 1 1 14rem;
min-width: 0;
}
.cluster-detail-hero-meta {
flex: 0 0 auto;
align-self: flex-start;
}
.cluster-detail-hero-card .page-title {
margin-bottom: 0.5rem;
}
.cluster-detail-meta {
min-width: 14rem;
max-width: 28rem;
}
/* Компактная карточка сводки (kind, kubeconfig, состояние, версия, workers) */
.cluster-detail-meta-card {
border-radius: 12px;
border: 1px solid var(--border);
background: linear-gradient(
155deg,
rgba(59, 130, 246, 0.09) 0%,
rgba(15, 23, 42, 0.35) 48%,
rgba(15, 23, 42, 0.2) 100%
);
padding: 0.65rem 0.75rem 0.7rem;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
}
html[data-theme="light"] .cluster-detail-meta-card {
background: linear-gradient(
155deg,
rgba(59, 130, 246, 0.12) 0%,
rgba(255, 255, 255, 0.95) 55%,
rgba(241, 245, 249, 0.9) 100%
);
box-shadow: 0 4px 18px rgba(15, 23, 42, 0.08);
}
.cluster-detail-meta-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 0.5rem 0.55rem;
}
@media (max-width: 720px) {
.cluster-detail-meta-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 400px) {
.cluster-detail-meta-grid {
grid-template-columns: 1fr;
}
}
.cluster-meta-tile {
display: flex;
flex-direction: column;
gap: 0.2rem;
padding: 0.35rem 0.4rem;
border-radius: 8px;
background: rgba(0, 0, 0, 0.14);
border: 1px solid rgba(255, 255, 255, 0.06);
min-width: 0;
}
html[data-theme="light"] .cluster-meta-tile {
background: rgba(255, 255, 255, 0.65);
border-color: rgba(59, 130, 246, 0.15);
}
.cluster-meta-tile__label {
font-size: 0.65rem;
font-weight: 650;
text-transform: uppercase;
letter-spacing: 0.06em;
line-height: 1.2;
}
.cluster-meta-tile__value {
font-size: 0.88rem;
font-weight: 600;
line-height: 1.25;
min-height: 1.25rem;
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 0.2rem;
}
.cluster-meta-tile--wide {
grid-column: 1 / -1;
}
.cluster-meta-badge {
font-size: 0.78rem !important;
padding: 0.12rem 0.45rem !important;
}
.cluster-meta-badge--muted {
background: transparent !important;
border: 1px dashed var(--border) !important;
color: var(--muted) !important;
font-weight: 500 !important;
}
.cluster-meta-version-tag {
font-size: 0.78rem;
font-weight: 600;
padding: 0.1rem 0.35rem;
border-radius: 6px;
background: rgba(0, 0, 0, 0.2);
border: 1px solid var(--border);
}
html[data-theme="light"] .cluster-meta-version-tag {
background: rgba(59, 130, 246, 0.08);
}
.cluster-meta-workers {
font-variant-numeric: tabular-nums;
font-size: 0.95rem;
}
/* Обёртка кнопок действий под заголовком кластера */
.cluster-detail-actions-card {
display: inline-flex;
align-items: center;
padding: 0.4rem 0.45rem;
margin-bottom: 0.35rem;
border-radius: 10px;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.1);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
}
html[data-theme="light"] .cluster-detail-actions-card {
background: rgba(15, 23, 42, 0.03);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8);
}
.cluster-detail-actions-card .cluster-detail-toolbar {
margin: 0;
}
/* Карточка «Установленные аддоны» на странице кластера (отдельный section.card) */
.cluster-detail-addons-card.hidden {
display: none;
}
.cluster-detail-addons-card__header {
margin-bottom: 1rem;
}
.cluster-detail-addons-card__head-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.5rem 0.75rem;
margin-bottom: 0.45rem;
}
/* Бейдж и заголовок в одной линии по вертикали: сброс margin у .cluster-detail-section-title (он задаётся ниже по файлу). */
.cluster-detail-addons-card__head-row h2.cluster-detail-section-title {
margin: 0;
line-height: 1.25;
}
.cluster-detail-addons-card__helm-badge {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
align-self: center;
padding: 0.22rem 0.55rem;
min-height: 1.35em;
font-size: 0.68rem;
font-weight: 700;
line-height: 1;
letter-spacing: 0.06em;
text-transform: uppercase;
color: #fff;
border-radius: 6px;
background: linear-gradient(135deg, #0f766e 0%, #0d9488 40%, #14b8a6 100%);
box-shadow: 0 1px 3px rgba(15, 118, 110, 0.35);
}
.cluster-detail-addons-card__title {
margin: 0;
font-size: 1.12rem;
font-weight: 700;
letter-spacing: -0.02em;
line-height: 1.25;
}
.cluster-detail-addons-card__lead {
margin: 0;
max-width: 44rem;
font-size: 0.86rem;
line-height: 1.5;
}
.cluster-detail-addons-card__lead code {
font-size: 0.82em;
}
.cluster-detail-addons-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(15.5rem, 1fr));
gap: 0.75rem 1rem;
width: 100%;
box-sizing: border-box;
}
.cluster-detail-addon-mini {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 0.35rem;
padding: 0.75rem 0.85rem 0.7rem;
min-height: 5.5rem;
border-radius: 10px;
border: 1px solid var(--border);
border-left: 4px solid rgba(59, 130, 246, 0.75);
background: var(--surface);
color: inherit;
text-decoration: none;
box-sizing: border-box;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
transition:
border-color 0.18s ease,
box-shadow 0.18s ease,
transform 0.15s ease,
background 0.18s ease;
}
html[data-theme="light"] .cluster-detail-addon-mini {
box-shadow: 0 2px 10px rgba(15, 23, 42, 0.06);
}
.cluster-detail-addon-mini:hover {
border-color: rgba(59, 130, 246, 0.4);
box-shadow: 0 6px 20px rgba(59, 130, 246, 0.12);
transform: translateY(-2px);
background: rgba(59, 130, 246, 0.04);
}
.cluster-detail-addon-mini:focus-visible {
outline: 2px solid rgba(59, 130, 246, 0.65);
outline-offset: 3px;
}
.cluster-detail-addon-mini__title {
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
font-weight: 600;
font-size: 0.82rem;
line-height: 1.3;
color: var(--text);
}
.cluster-detail-addon-mini__ver {
font-size: 0.78rem;
line-height: 1.4;
color: var(--muted);
word-break: break-word;
flex: 1 1 auto;
}
.cluster-detail-addon-mini__ns {
display: inline-flex;
align-items: center;
margin-top: auto;
padding: 0.15rem 0.4rem;
font-size: 0.7rem;
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
color: var(--muted);
background: rgba(0, 0, 0, 0.12);
border-radius: 4px;
}
html[data-theme="light"] .cluster-detail-addon-mini__ns {
background: rgba(15, 23, 42, 0.06);
}
.cluster-detail-addons-card__footer {
margin-top: 1rem;
padding-top: 0.85rem;
border-top: 1px solid var(--border);
}
.cluster-detail-addons-card__cta {
font-size: 0.88rem;
font-weight: 600;
color: rgba(59, 130, 246, 0.95);
text-decoration: none;
transition: color 0.15s ease;
}
.cluster-detail-addons-card__cta:hover {
color: rgba(96, 165, 250, 1);
text-decoration: underline;
}
.cluster-detail-addons-card__cta:focus-visible {
outline: 2px solid rgba(59, 130, 246, 0.55);
outline-offset: 2px;
border-radius: 4px;
}
.cluster-k8s-scope-hint {
margin: 0 0 0.85rem;
font-size: 0.86rem;
line-height: 1.45;
max-width: 48rem;
}
.cluster-k8s-scope-hint code {
font-size: 0.8em;
}
.cluster-detail-meta__column {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 0.35rem 0;
text-align: right;
}
.cluster-detail-meta__line {
display: grid;
grid-template-columns: auto 1fr;
gap: 0.35rem 0.65rem;
align-items: baseline;
font-size: 0.88rem;
width: 100%;
max-width: 22rem;
}
.cluster-detail-meta__label {
justify-self: end;
white-space: nowrap;
}
.cluster-detail-meta__value {
justify-self: start;
text-align: left;
min-width: 0;
}
.cluster-detail-hero-main {
flex: 1 1 12rem;
min-width: 0;
}
.cluster-detail-hero-actions {
flex: 0 0 auto;
align-self: flex-end;
}
.cluster-detail-hero-actions .actions-toolbar {
justify-content: flex-end;
flex-wrap: wrap;
gap: 0.35rem;
max-width: 22rem;
}
@media (max-width: 640px) {
.cluster-detail-hero-layout {
flex-direction: column;
align-items: stretch;
}
.cluster-detail-hero-meta {
align-self: stretch;
}
.cluster-detail-meta {
max-width: none;
}
.cluster-detail-meta__column {
align-items: flex-start;
text-align: left;
}
.cluster-detail-meta__line {
grid-template-columns: 6.5rem 1fr;
max-width: none;
}
.cluster-detail-meta__label {
justify-self: start;
}
.cluster-detail-meta__value {
justify-self: start;
}
.cluster-detail-hero-actions {
align-self: stretch;
}
.cluster-detail-hero-actions .actions-toolbar {
justify-content: flex-start;
max-width: none;
}
}
.cluster-detail-section-title {
font-size: 1.05rem;
margin: 0 0 0.65rem;
}
.cluster-detail-meta__row {
display: flex;
flex-wrap: wrap;
gap: 0.5rem 1.25rem;
margin-top: 0.5rem;
}
.cluster-detail-meta__item {
font-size: 0.88rem;
}
.cluster-detail-toolbar {
margin: 0;
}
.cluster-kube-hint {
margin: 0;
padding: 0.5rem 0.65rem;
border-radius: 8px;
border: 1px solid var(--border);
background: rgba(234, 179, 8, 0.12);
}
/* Ожидаемое состояние: узлы остановлены — не предупреждение, а подсказка */
.cluster-kube-hint.cluster-kube-hint--info {
background: rgba(59, 130, 246, 0.12);
border-color: rgba(59, 130, 246, 0.35);
}
html[data-theme="light"] .cluster-kube-hint.cluster-kube-hint--info {
background: rgba(59, 130, 246, 0.08);
border-color: rgba(37, 99, 235, 0.35);
}
/* Вводная карточка kubectl + отдельная карточка на каждый ресурс (как в шаблоне cluster_detail) */
.cluster-k8s-intro-card .cluster-k8s-scope-hint {
margin: 0 0 0.75rem;
}
.cluster-k8s-resource-card .cluster-detail-section-title {
margin: 0 0 0.55rem;
font-size: 1.02rem;
}
/* Заголовок карточки K8s + выпадающий фильтр namespace справа */
.cluster-k8s-card-header {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 0.5rem 1rem;
margin-bottom: 0.55rem;
}
.cluster-k8s-card-header .cluster-detail-section-title {
margin: 0;
flex: 1 1 auto;
min-width: 0;
}
.cluster-k8s-ns-filter-wrap {
flex: 0 0 auto;
}
.cluster-k8s-ns-select {
width: auto;
min-width: 10rem;
max-width: min(18rem, 100%);
margin: 0;
padding: 0.35rem 0.5rem;
font-size: 0.88rem;
}
/* Сетка карточек узлов на странице кластера: не более 3 карточек в ряд */
.cluster-page-node-cards--wide.cluster-nodes-resources__cards-row {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 0.75rem;
flex-wrap: wrap;
overflow-x: visible;
width: 100%;
}
@media (max-width: 52rem) {
.cluster-page-node-cards--wide.cluster-nodes-resources__cards-row {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 32rem) {
.cluster-page-node-cards--wide.cluster-nodes-resources__cards-row {
grid-template-columns: 1fr;
}
}
.cluster-page-node-cards--wide .cluster-node-res-card {
width: auto;
min-width: 0;
flex: none;
}
/* Таблицы Kubernetes (kubectl -o json) */
.cluster-k8s-root {
min-height: 1.5rem;
}
.cluster-k8s-msg {
margin: 0;
font-size: 0.85rem;
line-height: 1.45;
}
.cluster-k8s-table-scroll {
width: 100%;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
border-radius: 8px;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.12);
}
html[data-theme="light"] .cluster-k8s-table-scroll {
background: rgba(15, 23, 42, 0.04);
}
.cluster-k8s-table {
width: 100%;
min-width: 36rem;
border-collapse: collapse;
font-size: 0.8rem;
}
.cluster-k8s-table th,
.cluster-k8s-table td {
padding: 0.4rem 0.55rem;
text-align: left;
border-bottom: 1px solid var(--border);
vertical-align: middle;
}
.cluster-k8s-table th {
font-weight: 650;
color: var(--muted);
white-space: nowrap;
background: rgba(0, 0, 0, 0.18);
}
html[data-theme="light"] .cluster-k8s-table th {
background: rgba(59, 130, 246, 0.1);
}
.cluster-k8s-table tbody tr:last-child td {
border-bottom: none;
}
.cluster-k8s-table td:last-child {
width: 1%;
white-space: nowrap;
}
.cluster-k8s-table .icon-tooltip-host {
display: inline-flex;
vertical-align: middle;
}
.btn-k8s-restart {
display: inline-flex;
align-items: center;
gap: 0.35rem;
padding: 0.25rem 0.5rem;
font-size: 0.78rem;
}
.btn-k8s-restart svg {
width: 1rem;
height: 1rem;
flex-shrink: 0;
}
/* Рестарт пода: только иконка; подсказка — #action-tooltip (.icon-tooltip-host) */
.btn-k8s-restart--solo {
width: 2rem;
height: 2rem;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 8px;
}
.btn-k8s-restart--solo svg {
width: 1.05rem;
height: 1.05rem;
}
.cluster-kube-pre {
max-height: 16rem;
overflow: auto;
margin: 0;
padding: 0.5rem 0.65rem;
font-size: 0.78rem;
line-height: 1.35;
border-radius: 8px;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.2);
}
html[data-theme="light"] .cluster-kube-pre {
background: rgba(15, 23, 42, 0.04);
}
/* Полноэкранный спиннер первой загрузки главной панели */
body.dashboard-home-loading {
overflow: hidden;
}
/* Полноэкранный спиннер первой загрузки страницы кластера */
body.cluster-page-loading {
overflow: hidden;
}
/* Первая загрузка страниц «Аддоны» и «Журнал» */
body.cluster-addons-page-loading,
body.journal-page-loading {
overflow: hidden;
}
.page-loading-overlay {
position: fixed;
inset: 0;
z-index: 9998;
display: flex;
align-items: center;
justify-content: center;
}
.page-loading-overlay.hidden {
display: none;
pointer-events: none;
}
/* Старт/стоп кластера: тот же полноэкранный паттерн, z-index ниже полноэкранных ошибок при необходимости */
.cluster-lifecycle-job-overlay {
z-index: 9996;
}
body.cluster-lifecycle-job-busy {
overflow: hidden;
}
.page-loading-backdrop {
position: absolute;
inset: 0;
background: rgba(15, 23, 42, 0.52);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
html[data-theme="light"] .page-loading-backdrop {
background: rgba(241, 245, 249, 0.72);
}
.page-loading-center {
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
padding: 1.35rem 1.75rem;
border-radius: 12px;
border: 1px solid var(--border);
background: var(--card);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
}
html[data-theme="light"] .page-loading-center {
box-shadow: 0 12px 40px rgba(15, 23, 42, 0.12);
}
.page-loading-spinner {
width: 2.5rem;
height: 2.5rem;
border-width: 4px;
}
.page-loading-label {
font-size: 0.92rem;
color: var(--muted);
text-align: center;
max-width: 18rem;
line-height: 1.4;
}
/* Редактирование кластера (cluster_edit.html).
Автор: Сергей Антропов — https://devops.org.ru */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.cluster-edit-hint {
margin: 0 0 1rem;
font-size: 0.92rem;
line-height: 1.45;
}
.cluster-edit-mode-fieldset {
border: none;
margin: 0 0 1.25rem;
padding: 0;
}
.cluster-edit-mode-legend {
font-size: 0.78rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--muted);
margin: 0 0 0.65rem;
padding: 0;
}
/* Сегментный переключатель «Простой / Расширенный»: одна строка, равная высота */
.cluster-edit-segmented {
display: flex;
flex-wrap: nowrap;
align-items: stretch;
width: 100%;
max-width: 42rem;
padding: 4px;
border-radius: 14px;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.18);
gap: 4px;
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.12);
}
html[data-theme="light"] .cluster-edit-segmented {
background: rgba(15, 23, 42, 0.06);
box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.06);
}
.cluster-edit-segment-item {
position: relative;
display: flex;
flex: 1 1 0;
min-width: 0;
min-height: 5.35rem;
}
.cluster-edit-segment-native {
position: absolute;
opacity: 0;
width: 1px;
height: 1px;
margin: 0;
pointer-events: none;
}
.cluster-edit-segment-label {
display: flex;
flex: 1;
flex-direction: column;
justify-content: center;
align-items: flex-start;
gap: 0;
margin: 0;
padding: 0.75rem 1.05rem;
border-radius: 10px;
cursor: pointer;
border: 1px solid transparent;
box-sizing: border-box;
transition:
background 0.18s ease,
color 0.18s ease,
border-color 0.18s ease,
box-shadow 0.18s ease;
color: var(--muted);
font-weight: 500;
line-height: 1.25;
min-height: 100%;
}
.cluster-edit-segment-title {
font-size: 0.98rem;
color: inherit;
font-weight: 600;
}
.cluster-edit-segment-sub-wrap {
display: flex;
flex-direction: column;
gap: 0.12rem;
margin-top: 0.35rem;
}
.cluster-edit-segment-sub {
font-size: 0.76rem;
font-weight: 400;
opacity: 0.9;
line-height: 1.32;
}
.cluster-edit-segment-native:focus-visible + .cluster-edit-segment-label {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
.cluster-edit-segment-native:checked + .cluster-edit-segment-label {
background: var(--accent);
color: #f8fafc;
border-color: var(--accent);
box-shadow: 0 2px 14px rgba(59, 130, 246, 0.35);
}
.cluster-edit-segment-native:checked + .cluster-edit-segment-label .cluster-edit-segment-sub {
color: inherit;
opacity: 0.92;
}
.cluster-edit-mode-hint {
margin: 0.75rem 0 0;
font-size: 0.88rem;
line-height: 1.45;
max-width: 40rem;
}
.cluster-edit-advanced-wrap {
margin-bottom: 1rem;
}
.cluster-edit-advanced-intro {
margin: 0 0 1.15rem;
padding: 0.75rem 1rem;
border-radius: 10px;
border: 1px solid var(--border);
background: rgba(59, 130, 246, 0.08);
}
html[data-theme="light"] .cluster-edit-advanced-intro {
background: rgba(59, 130, 246, 0.06);
}
.cluster-edit-advanced-intro-text {
margin: 0;
font-size: 0.88rem;
line-height: 1.5;
color: var(--fg);
}
.cluster-edit-panels {
display: flex;
flex-direction: column;
gap: 1rem;
margin-bottom: 1.15rem;
}
.cluster-edit-panel {
border-radius: 12px;
border: 1px solid var(--border);
background: var(--card);
overflow: hidden;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.04) inset;
}
html[data-theme="light"] .cluster-edit-panel {
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
}
.cluster-edit-panel-head {
padding: 0.85rem 1.1rem 0.75rem;
border-bottom: 1px solid var(--border);
background: rgba(0, 0, 0, 0.14);
}
html[data-theme="light"] .cluster-edit-panel-head {
background: rgba(15, 23, 42, 0.04);
}
.cluster-edit-panel-title {
margin: 0 0 0.35rem;
font-size: 1rem;
font-weight: 600;
letter-spacing: -0.01em;
}
.cluster-edit-panel-desc {
margin: 0;
font-size: 0.82rem;
line-height: 1.45;
}
.cluster-edit-panel-body {
padding: 1rem 1.1rem 1.05rem;
}
.cluster-edit-panel-grid {
display: grid;
grid-template-columns: 1fr;
gap: 0.85rem 1.25rem;
}
@media (min-width: 640px) {
.cluster-edit-panel-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
.cluster-edit-panel-grid--tight {
gap: 0.65rem 1rem;
}
.cluster-edit-panel-span {
grid-column: 1 / -1;
}
.cluster-edit-check-label {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
align-items: center;
gap: 0.5rem;
font-size: 0.9rem;
line-height: 1.35;
cursor: pointer;
text-align: left;
}
.cluster-edit-check-label input[type="checkbox"] {
margin: 0;
flex-shrink: 0;
}
.cluster-edit-check-label--card {
display: inline-flex;
align-items: center;
box-sizing: border-box;
padding: 0.55rem 0.75rem;
border-radius: 8px;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.12);
max-width: 100%;
}
/* Один ряд: краткий заголовок — пояснение (сжимается с многоточием при нехватке места) */
.cluster-edit-check-inline {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
gap: 0.35rem;
min-width: 0;
flex: 1;
overflow: hidden;
}
.cluster-edit-check-title {
flex: 0 1 auto;
min-width: 0;
max-width: min(22rem, 58%);
font-weight: 600;
margin: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.cluster-edit-check-sep {
flex-shrink: 0;
padding: 0 0.05rem;
user-select: none;
}
.cluster-edit-check-hint {
flex: 1;
min-width: 0;
margin: 0;
font-size: 0.86em;
line-height: 1.35;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.cluster-edit-check-hint a {
white-space: nowrap;
}
html[data-theme="light"] .cluster-edit-check-label--card {
background: rgba(15, 23, 42, 0.03);
}
.cluster-edit-port-card {
margin-top: 0.75rem;
padding: 0.85rem 0.9rem 0.95rem;
border-radius: 10px;
border: 1px dashed var(--border);
background: rgba(0, 0, 0, 0.1);
}
html[data-theme="light"] .cluster-edit-port-card {
background: rgba(15, 23, 42, 0.03);
}
.create-cluster-card .field-hint {
display: block;
margin-top: 0.3rem;
font-size: 0.76rem;
line-height: 1.35;
}
.cluster-edit-kubeadm-textarea {
width: 100%;
min-height: 7rem;
resize: vertical;
font-size: 0.82rem;
line-height: 1.35;
}
.cluster-edit-yaml-preview-card {
border-radius: 10px;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.2);
overflow: hidden;
}
html[data-theme="light"] .cluster-edit-yaml-preview-card {
background: rgba(15, 23, 42, 0.04);
}
.cluster-edit-yaml-preview-head {
display: flex;
flex-wrap: wrap;
align-items: baseline;
justify-content: space-between;
gap: 0.35rem 0.75rem;
padding: 0.5rem 0.75rem;
border-bottom: 1px solid var(--border);
background: rgba(0, 0, 0, 0.12);
}
html[data-theme="light"] .cluster-edit-yaml-preview-head {
background: rgba(15, 23, 42, 0.05);
}
.cluster-edit-yaml-preview-title {
font-size: 0.82rem;
font-weight: 600;
}
.cluster-edit-yaml-preview-note {
font-size: 0.75rem;
}
.cluster-edit-yaml-preview-pre {
margin: 0;
padding: 0.75rem 1rem;
max-height: 22rem;
overflow: auto;
font-size: 0.78rem;
line-height: 1.4;
white-space: pre-wrap;
word-break: break-word;
}
.cluster-edit-actions {
gap: 0.75rem;
align-items: center;
flex-wrap: wrap;
}
.cluster-edit-cancel-link {
text-decoration: none;
display: inline-flex;
align-items: center;
justify-content: center;
}
/* Страница «Аддоны»: Helm-чарты по выбранному кластеру */
.cluster-addons-toolbar-card .cluster-addons-cluster-row {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
gap: 0.65rem 1rem;
margin-bottom: 0.35rem;
}
.cluster-addons-cluster-label {
display: block;
width: 100%;
font-size: 0.8125rem;
font-weight: 600;
margin-bottom: 0.2rem;
}
.cluster-addons-cluster-select {
min-width: min(100%, 18rem);
flex: 1 1 14rem;
max-width: 28rem;
}
.cluster-addons-status-bar {
margin-top: 0.85rem;
}
.cluster-addons-status-bar--message .cluster-addons-status-msg {
margin: 0;
font-size: 0.88rem;
line-height: 1.45;
}
.cluster-addons-status-cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr));
gap: 0.65rem;
}
.cluster-addons-status-card {
border-radius: 10px;
border: 1px solid var(--border);
padding: 0.65rem 0.75rem;
background: rgba(0, 0, 0, 0.14);
display: flex;
flex-direction: column;
gap: 0.35rem;
min-height: 3.5rem;
justify-content: center;
transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
html[data-theme="light"] .cluster-addons-status-card {
background: rgba(15, 23, 42, 0.04);
}
.cluster-addons-status-card--on {
border-color: rgba(34, 197, 94, 0.45);
box-shadow: 0 0 0 1px rgba(34, 197, 94, 0.12);
}
.cluster-addons-status-card--off {
border-color: var(--border);
opacity: 0.92;
}
.cluster-addons-status-card__label {
font-size: 0.78rem;
font-weight: 600;
color: var(--muted);
line-height: 1.25;
word-break: break-word;
}
.cluster-addons-status-card__value {
font-size: 1.05rem;
font-weight: 700;
letter-spacing: 0.02em;
}
.cluster-addons-status-card--on .cluster-addons-status-card__value {
color: rgb(34, 197, 94);
}
.cluster-addons-status-card--off .cluster-addons-status-card__value {
color: var(--muted);
}
.cluster-addons-grid {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 1rem;
margin: 1rem 0;
}
/* Шапка карточки аддона: заголовок + бейдж «установлен» справа */
.cluster-addon-card__header {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: space-between;
gap: 0.65rem;
margin-bottom: 0.35rem;
}
.cluster-addon-card__header .cluster-addon-card__title {
margin: 0;
flex: 1 1 auto;
min-width: 0;
font-size: 1.05rem;
line-height: 1.3;
}
.cluster-addon-card__badge {
flex: 0 0 auto;
font-size: 0.68rem;
font-weight: 700;
letter-spacing: 0.03em;
text-transform: uppercase;
padding: 0.28rem 0.5rem;
border-radius: 6px;
border: 1px solid var(--border);
line-height: 1.2;
white-space: nowrap;
}
.cluster-addon-card__badge--on {
border-color: rgba(34, 197, 94, 0.5);
color: rgb(34, 197, 94);
background: rgba(34, 197, 94, 0.1);
}
.cluster-addon-card__badge--off {
color: var(--muted);
background: rgba(0, 0, 0, 0.12);
}
html[data-theme="light"] .cluster-addon-card__badge--off {
background: rgba(15, 23, 42, 0.06);
}
.cluster-addon-card__values-details {
margin: 0.75rem 0 0;
border-radius: 8px;
border: 1px solid var(--border);
padding: 0.5rem 0.65rem;
background: rgba(0, 0, 0, 0.08);
}
html[data-theme="light"] .cluster-addon-card__values-details {
background: rgba(15, 23, 42, 0.03);
}
.cluster-addon-card__values-summary {
cursor: pointer;
font-weight: 600;
font-size: 0.88rem;
list-style-position: outside;
padding: 0.15rem 0;
}
.cluster-addon-card__values-hint {
margin: 0.5rem 0 0.45rem;
font-size: 0.78rem;
line-height: 1.45;
}
.cluster-addon-card__values-subhead {
margin: 0.65rem 0 0.35rem;
font-size: 0.8rem;
font-weight: 700;
color: var(--text);
}
.cluster-addon-card__values-details .cluster-addon-card__values-subhead:first-of-type {
margin-top: 0.35rem;
}
.cluster-addon-card__values-textarea {
display: block;
width: 100%;
box-sizing: border-box;
margin: 0;
min-height: 6rem;
padding: 0.5rem 0.6rem;
font-size: 0.78rem;
line-height: 1.4;
border-radius: 6px;
border: 1px solid var(--border);
background: rgba(0, 0, 0, 0.18);
color: inherit;
resize: vertical;
}
html[data-theme="light"] .cluster-addon-card__values-textarea {
background: rgba(255, 255, 255, 0.85);
}
.cluster-addon-card__desc {
margin: 0 0 0.75rem;
font-size: 0.85rem;
line-height: 1.45;
}
/* Кнопки «Установить / Обновить / Удалить» — по содержимому, не на всю ширину карточки */
.cluster-addon-card__actions--inline {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-top: 0.85rem;
gap: 0.5rem;
align-items: center;
justify-content: flex-start;
}
.cluster-addon-card__actions--inline .btn-addon-install,
.cluster-addon-card__actions--inline .btn-addon-remove {
flex: 0 0 auto;
min-width: 7.5rem;
min-height: 2.65rem;
margin-top: 0;
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.5rem 1rem;
font-size: 0.9rem;
}
.cluster-addon-card--wide {
grid-column: 1;
}
.cluster-addon-istio-grid {
margin-top: 0.25rem;
}
.cluster-addon-istio-load-field {
grid-column: 1 / -1;
}
.cluster-addon-card__field-label {
display: block;
margin-bottom: 0.35rem;
font-size: 0.88rem;
font-weight: 600;
color: var(--text);
}
.cluster-addon-version-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.5rem 0.65rem;
}
.cluster-addon-version-row .cluster-addons-version-select {
flex: 1 1 12rem;
width: auto;
min-width: 10rem;
max-width: 22rem;
}
.cluster-addon-card__values-panel {
margin-top: 0.65rem;
}
.btn-addon-load-values {
flex: 0 0 auto;
white-space: nowrap;
}
/* Якорь для блока прогресса до первой операции; пустой, когда секция перенесена в карточку */
.cluster-addons-helm-dock:empty {
display: none;
}
.cluster-addons-helm-dock:not(:empty) {
margin-bottom: 1.5rem;
}
/* Карточка хода Helm на странице аддонов (разметка как у create-progress-wrap + job-log-panel) */
.cluster-addons-helm-progress {
margin-bottom: 1.5rem;
}
.cluster-addon-card > .cluster-addons-helm-progress {
margin-top: 1rem;
margin-bottom: 0;
width: 100%;
box-sizing: border-box;
}
.cluster-addons-helm-progress .job-log-panel {
max-height: min(55vh, 420px);
}
.cluster-addons-bootstrap-msg {
margin: 0.5rem 0 0;
font-size: 0.88rem;
line-height: 1.45;
}
/* Версии чартов на странице аддонов */
.cluster-addons-version-select {
width: 100%;
max-width: 22rem;
padding: 0.45rem 0.6rem;
font-size: 0.9rem;
border-radius: 8px;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
}
/* Страница «Журнал» */
.journal-toolbar-card .journal-toolbar-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.75rem 1rem;
margin-top: 0.35rem;
}
.journal-status {
margin: 0.65rem 0 0;
}
.journal-empty {
margin: 0.5rem 0;
}
.journal-table-wrap {
overflow-x: auto;
margin-top: 0.5rem;
}
.journal-table {
width: 100%;
border-collapse: collapse;
font-size: 0.85rem;
}
.journal-table th,
.journal-table td {
padding: 0.45rem 0.55rem;
text-align: left;
border-bottom: 1px solid var(--border);
vertical-align: top;
}
.journal-table th {
font-weight: 600;
color: var(--muted);
}
.journal-code {
font-size: 0.8rem;
}
.journal-cell-time {
white-space: nowrap;
}
.journal-cell-msg {
max-width: 14rem;
word-break: break-word;
}
.journal-cell-actions {
white-space: nowrap;
}
.journal-status-pill {
display: inline-block;
padding: 0.12rem 0.45rem;
border-radius: 999px;
font-size: 0.78rem;
background: rgba(148, 163, 184, 0.2);
}
.journal-status-pill--ok {
background: rgba(34, 197, 94, 0.2);
color: var(--text);
}
.journal-status-pill--err {
background: rgba(239, 68, 68, 0.2);
}
.journal-status-pill--warn {
background: rgba(234, 179, 8, 0.22);
}
.journal-details-cell {
padding: 0.5rem 0.55rem 0.85rem;
background: rgba(0, 0, 0, 0.08);
}
html[data-theme="light"] .journal-details-cell {
background: rgba(15, 23, 42, 0.04);
}
.journal-log-pre {
margin: 0;
max-height: min(40vh, 18rem);
overflow: auto;
padding: 0.5rem 0.65rem;
font-size: 0.76rem;
line-height: 1.35;
white-space: pre-wrap;
word-break: break-word;
border-radius: 8px;
border: 1px solid var(--border);
}
/* Три сегмента на странице журнала — шире блок переключателя */
.journal-toolbar-card .cluster-edit-segmented {
max-width: 100%;
flex-wrap: wrap;
}
@media (min-width: 960px) {
.journal-toolbar-card .cluster-edit-segmented {
flex-wrap: nowrap;
max-width: 56rem;
}
}
.journal-view-fieldset {
margin-bottom: 0.25rem;
}
.journal-cluster-picker {
margin-top: 1rem;
margin-bottom: 0.5rem;
}
.journal-cluster-picker.hidden {
display: none;
}
.journal-cluster-picker-label {
display: block;
font-size: 0.88rem;
font-weight: 600;
margin-bottom: 0.35rem;
}
.journal-cluster-select {
width: 100%;
max-width: 24rem;
padding: 0.45rem 0.65rem;
font-size: 0.9rem;
border-radius: 8px;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
}
.journal-cluster-picker-hint {
margin: 0.45rem 0 0;
font-size: 0.84rem;
max-width: 40rem;
}
.journal-toolbar-actions {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.75rem 1rem;
margin-top: 0.65rem;
}
.journal-cell-kind {
word-break: break-word;
max-width: 12rem;
}
/* Пагинация журнала */
.journal-pagination {
margin-top: 1.25rem;
padding-top: 1rem;
border-top: 1px solid var(--border);
}
.journal-pagination-inner {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 0.35rem 0.5rem;
}
.journal-pag-btn {
padding: 0.4rem 0.65rem;
font-size: 0.82rem;
border-radius: 8px;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
cursor: pointer;
transition: background 0.15s ease, border-color 0.15s ease;
}
.journal-pag-btn:hover:not(:disabled) {
background: rgba(99, 102, 241, 0.12);
border-color: rgba(99, 102, 241, 0.45);
}
.journal-pag-btn:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.journal-pag-pages {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.25rem;
margin: 0 0.15rem;
}
.journal-pag-num {
min-width: 2.35rem;
padding: 0.4rem 0.5rem;
font-size: 0.85rem;
font-weight: 500;
border-radius: 8px;
border: 1px solid transparent;
background: transparent;
color: var(--text);
cursor: pointer;
transition: background 0.15s ease, color 0.15s ease;
}
.journal-pag-num:hover:not(:disabled) {
background: rgba(99, 102, 241, 0.1);
}
.journal-pag-num--active {
background: linear-gradient(135deg, rgba(99, 102, 241, 0.35), rgba(129, 140, 248, 0.25));
border-color: rgba(99, 102, 241, 0.5);
color: var(--text);
cursor: default;
box-shadow: 0 2px 8px rgba(99, 102, 241, 0.2);
}
.journal-pag-ellipsis {
padding: 0 0.2rem;
color: var(--muted);
font-size: 0.9rem;
user-select: none;
}
@media (max-width: 640px) {
.journal-pagination-inner {
flex-direction: column;
}
.journal-pag-pages {
order: -1;
margin: 0.25rem 0;
}
}