/* Стилі панелі.
 *
 * Орієнтир — професійна хостинг-панель (DirectAdmin): темна вузька рейка
 * зліва, світла робоча область на всю ширину екрана, великі очевидні дії.
 * Панеллю користуються діти, тому дрібного тексту й тонких сірих підписів
 * тут немає.
 *
 * ТЕМИ ТУТ ОДНА — СВІТЛА, і це рішення, а не недогляд. Раніше в кінці файлу
 * жив блок @media (prefers-color-scheme: dark), і на шкільному комп'ютері з
 * темною темою ОС панель ставала темно-синьою: синій текст на темно-синьому
 * фоні, підписів не видно. Діти працюють удень, монітори різні й часто
 * дешеві — світлий екран читається завжди. color-scheme: light нижче
 * тримає ще й системні елементи браузера (поля, скроли) світлими.
 *
 * Збірки фронтенду немає й не буде: один css-файл, який можна прочитати. */

:root {
  color-scheme: light;

  /* Поверхні */
  --bg: #f4f7fb;         /* сторінка */
  --surface: #fff;       /* картка */
  --surface-2: #f2f6fb;  /* поле, hover, зебра в таблиці */
  --line: #e3e9f2;       /* межа */

  /* Текст */
  --ink: #0f172a;        /* головний */
  --ink-soft: #475569;   /* другорядний */
  --muted: #6b7c95;      /* підпис */

  /* Дія */
  --accent: #2563eb;
  --accent-dark: #1d4ed8;
  --accent-soft: #e8f0ff;

  /* Рейка меню. Темна навмисно: вона має читатись як «край екрана», а не як
   * ще одна картка, і саме цей контраст робить світлу сторінку схожою на
   * панель, а не на документ. */
  --rail: #16233c;
  --rail-2: #1e3054;
  --rail-ink: #cfd9ea;

  /* Стани. Пари «текст + м'який фон» — щоб чіп і плашка були з однієї сім'ї. */
  --ok: #15803d;
  --ok-soft: #dcfce7;
  --warn: #a16207;
  --warn-soft: #fef3c7;
  --danger: #b91c1c;
  --danger-dark: #991b1b;
  --danger-soft: #fee2e2;
  --info: #1e40af;
  --info-soft: #dbeafe;

  /* Текст НА кольоровій кнопці. Окремо від --surface, хоч зараз обидва білі:
   * --surface означає «колір поверхні картки», і плутати їх не можна —
   * колись саме через це кожна кнопка панелі малювалась темним по синьому. */
  --on-accent: #fff;

  --radius: 14px;
  --radius-lg: 18px;
  --shadow-1: 0 1px 2px rgb(15 23 42 / 6%), 0 4px 12px rgb(15 23 42 / 5%);
  --shadow-2: 0 12px 32px rgb(15 23 42 / 14%);

  --rail-w: 92px;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* Сторінки-картки (вхід, реєстрація, «профіль ще не увімкнено», 403, зміна
 * пароля, новий проект): одна картка по центру, без рейки. */
body:not(.app) {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

a { color: var(--accent); }

h1 { margin: 0; font-size: 27px; letter-spacing: -0.02em; }
h2 { margin: 0 0 14px; font-size: 19px; letter-spacing: -0.01em; }

.lead { margin: 0 0 24px; color: var(--ink-soft); }
.note { margin: 12px 0 0; color: var(--muted); font-size: 14.5px; }
.help { margin: 4px 0 0; color: var(--muted); font-size: 14.5px; }

/* ─────────────────────────────────────────────────────────────────────────
 * Іконки: свій спрайт із static/img/icons.svg (інтернету в панелі немає)
 * ───────────────────────────────────────────────────────────────────────── */

.ic {
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.ic-lg { width: 26px; height: 26px; }

/* ─────────────────────────────────────────────────────────────────────────
 * Оболонка: рейка + робоча область
 * ───────────────────────────────────────────────────────────────────────── */

.shell { display: flex; min-height: 100vh; }

.rail {
  position: sticky;
  top: 0;
  align-self: flex-start;
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 0 0 var(--rail-w);
  width: var(--rail-w);
  height: 100vh;
  padding: 14px 8px;
  background: var(--rail);
  color: var(--rail-ink);
  overflow-y: auto;
}

/* Знак панелі вгорі рейки — щоб верх меню не починався одразу пунктом. */
.rail-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  margin-bottom: 10px;
  color: #fff;
}

.rail-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 10px 4px 8px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: var(--rail-ink);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}

.rail-item:hover { background: var(--rail-2); color: #fff; }

/* Активний пункт — заливкою, а не рискою: рискa на 12-піксельному підписі
 * читається як артефакт, а заливка видно з іншого кінця класу. */
.rail-item.is-active { background: var(--accent); color: #fff; }

.rail-spacer { flex: 1 1 auto; }

/* «Вийти» — це POST-форма, а не посилання; форма не має з'їдати ширину. */
.rail form { display: block; margin: 0; }
.rail form button { width: 100%; }

/* Хто зайшов. Кружечок з першою літерою імені — обличчя акаунта; за одним
 * комп'ютером сидять різні діти, і «це не мій кабінет» має бути видно. */
.rail-who {
  display: flex;
  border-radius: 12px;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 4px;
  border-top: 1px solid rgb(255 255 255 / 10%);
  color: var(--rail-ink);
  font-size: 11.5px;
  text-align: center;
  text-decoration: none;
  overflow-wrap: anywhere;
}

.rail-who:hover { background: var(--rail-2); color: #fff; }
.rail-who.is-active { background: var(--accent); color: #fff; }
.rail-who.is-active .avatar { background: #fff; color: var(--accent); }

/* Логін не переносимо по складах: довгий обрізається трьома крапками, а
 * повністю його все одно видно у «Профілі». */
.rail-who .login {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.avatar {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  text-transform: uppercase;
}

.avatar-lg { width: 56px; height: 56px; font-size: 24px; }

.workspace {
  flex: 1 1 auto;
  min-width: 0;   /* без цього широка таблиця розсуває всю сторінку */
  padding: 22px 28px 48px;
}

/* Плашки всередині робочої колонки: розсунуті на всю її ширину, впритул до
 * країв, — щоб виглядали смугою на весь екран, а не карткою з полями.
 * Самого контейнера немає, коли показувати нічого (умова в app.html). */
.banners { margin: -22px -28px 18px; }
.banners > * { margin: 0; }

.pagehead {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}

.pagehead .sub { margin: 4px 0 0; color: var(--muted); }

.pagehead-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.pagehead-actions form { margin: 0; }

/* ─────────────────────────────────────────────────────────────────────────
 * Картки
 * ───────────────────────────────────────────────────────────────────────── */

/* Картка форми по центру екрана (вхід, реєстрація, новий проект). */
.card {
  width: 100%;
  max-width: 430px;
  padding: 36px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}

/* Секція всередині робочої області. */
.block {
  margin-bottom: 18px;
  padding: 22px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}

.block > :last-child { margin-bottom: 0; }

/* Шапка секції: заголовок зліва, дії секції справа. */
.block-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.block-head h2 { margin: 0; }

/* Секція, яка чекає на дію людини («Нові учні»). Тепла смуга зліва — щоб
 * вона не загубилась серед однакових білих карток. */
.block-attention {
  border-color: #f2d9a0;
  border-left: 5px solid #eab308;
  background: #fffdf5;
}

.block.archived { opacity: 0.8; }
.archive-title { margin: 28px 0 10px; color: var(--muted); font-size: 17px; }

/* ─────────────────────────────────────────────────────────────────────────
 * Кнопки й форми
 * ───────────────────────────────────────────────────────────────────────── */

/* Кнопка ЗАВЖДИ не менша за 44px: по ній тикають діти мишею шкільного
 * комп'ютера, а не дизайнер трекпадом. */
button,
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 11px 18px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

button:hover:not(:disabled),
.btn:hover { background: var(--surface-2); border-color: #cfd9e8; }

button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-primary,
button.btn-primary {
  border-color: transparent;
  background: var(--accent);
  color: var(--on-accent);
}

.btn-primary:hover:not(:disabled) { background: var(--accent-dark); border-color: transparent; }

/* «Вимкнути профіль» і «Скинути пароль» стоять поруч, і рука тисне швидше,
 * ніж око читає, — небезпечне мусить виглядати інакше. */
.btn-danger,
button.btn-danger {
  border-color: transparent;
  background: var(--danger);
  color: #fff;
}

.btn-danger:hover:not(:disabled) { background: var(--danger-dark); border-color: transparent; }

/* Дрібна кнопка в рядку списку. */
.btn-sm { min-height: 36px; padding: 6px 12px; font-size: 14px; border-radius: 9px; }

/* Кнопка-іконка з підписом (панель дій файлового менеджера, кнопки сайту). */
.btn-icon { flex-direction: column; gap: 4px; min-width: 84px; padding: 10px 12px; font-size: 13px; }

.form {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

label { margin-top: 12px; font-weight: 600; font-size: 15px; }

/* select разом з input: без явного кольору браузер малює список по-своєму. */
input, select, textarea {
  padding: 12px 14px;
  border: 1.5px solid var(--line);
  border-radius: 11px;
  font: inherit;
  background: var(--surface);
  color: var(--ink);
}

input:focus, select:focus, textarea:focus {
  outline: 3px solid var(--accent-soft);
  border-color: var(--accent);
}

input:disabled { background: var(--surface-2); cursor: not-allowed; }

/* Галочка й радіо — не поле вводу: без цього вони в колонці .form
 * розтягуються на всю ширину картки й виглядають як поламана рамка. */
input[type="checkbox"], input[type="radio"] {
  width: 18px;
  height: 18px;
  align-self: flex-start;
  padding: 0;
  border-radius: 5px;
  accent-color: var(--accent);
}

/* Вибір мови проекту — плитками з іконками: три речі з обличчям читаються
 * швидше за три однакові рядки з кружечками. Сам radio лишається на місці
 * (просто невидимий), тож форма, клавіатура й фокус працюють як були. */
.lang-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 10px;
  margin-top: 6px;
}

.lang-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 14px 10px;
  border: 2px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer;
  text-align: center;
}

.lang-tile input { position: absolute; opacity: 0; pointer-events: none; }
.lang-tile:hover { border-color: #c7d3e6; background: var(--surface-2); }
.lang-tile:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.lang-tile:has(input:focus-visible) { outline: 3px solid var(--accent-soft); }
.lang-name { font-size: 14.5px; font-weight: 600; }

/* Версія PHP — своя колонка «підпис / поле / підказка», як у решти полів:
 * усередині <div> вони інакше стають в один рядок. */
.php-version { display: flex; flex-direction: column; gap: 4px; }
/* Без цього рядка hidden не працює: display: flex вище сильніший за
 * display: none, який браузер дає атрибуту hidden. Саме тому «Версія PHP»
 * показувалась і для Python, і для Node. */
.php-version[hidden] { display: none; }

/* Перемикач із двох варіантів: обидва видно одразу, обраний — залитий.
 * Той самий прийом, що в плитках мови: справжній radio на місці, просто
 * невидимий, тож клавіатура й форма працюють як були. */
.segmented {
  display: inline-flex;
  gap: 4px;
  margin-top: 6px;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-2);
  align-self: flex-start;
}

.segment {
  margin: 0;
  padding: 8px 16px;
  border-radius: 9px;
  color: var(--ink-soft);
  font-size: 14.5px;
  font-weight: 600;
  cursor: pointer;
}

.segment input { position: absolute; opacity: 0; pointer-events: none; }
.segment:hover { color: var(--ink); }
.segment:has(input:checked) { background: var(--surface); color: var(--accent); box-shadow: var(--shadow-1); }
.segment:has(input:focus-visible) { outline: 3px solid var(--accent-soft); }

/* Підпис групи полів — там, де <label> не прив'язаний до одного поля. */
.form .label { margin-top: 12px; font-weight: 600; font-size: 15px; }

/* Галочка з підписом в один рядок (а не підпис зверху, як у полів). */
.checkbox-row {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 600;
  font-size: 15px;
}

.checkbox-row input { align-self: center; }

/* Список варіантів (вибір мови проекту) — маркерів не треба. */
.form ul { list-style: none; margin: 4px 0 0; padding: 0; }
.form ul li { display: flex; align-items: center; gap: 8px; padding: 4px 0; }
.form ul label { margin: 0; font-weight: 500; }

/* Кнопка під формою-стовпчиком стоїть окремо від останнього поля. */
.form button { margin-top: 18px; }

/* Форма-стовпчик усередині широкої картки («Додати викладача», «Ім'я» в
 * профілі): поле на всю ширину екрана читається як помилка верстки, а не
 * як запрошення писати — рядок імені не буває на 1300 пікселів. */
.block > .form { max-width: 460px; }

/* Кілька форм-кнопок в один ряд (на картці учня їх три). */
.row-forms {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.row-forms form { margin: 0; }

.search { display: flex; gap: 10px; flex-wrap: wrap; }
.search input, .search select { flex: 1 1 180px; }
.search button { flex: 0 0 auto; }
/* Підпис усередині рядка пошуку («ivan_» перед полем назви бази). */
.search label { margin-top: 0; align-self: center; }

/* Відступ зверху там, де блок іде впритул до попереднього (форма під
 * списком, таблиця результату під полем SQL). Окремим класом, бо це
 * виняток на кілька місць, а не властивість самих блоків. */
.gap-top { margin-top: 16px; }

.field-error { margin: 4px 0 0; color: var(--danger); font-size: 14.5px; }

/* ─────────────────────────────────────────────────────────────────────────
 * Підказка при наведенні
 *
 * Своя, а не title=«…»: системна спливає з секундною затримкою і зникає, поки
 * читаєш довге речення, — а тут саме довгі речення й пояснюють, ЩО станеться
 * після натискання. Показується і на фокусі з клавіатури.
 * ───────────────────────────────────────────────────────────────────────── */

.hint { position: relative; }

.hint::after {
  content: attr(data-hint);
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 25;
  width: max-content;
  max-width: 300px;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--rail);
  color: #fff;
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.45;
  text-align: left;
  white-space: normal;
  box-shadow: var(--shadow-2);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.12s ease;
  /* Підказка НЕ ловить мишу: вона висить над сусідніми кнопками, і без цього
   * рядка клік по тому, що під нею, потрапляв би в порожню хмарку. */
  pointer-events: none;
}

.hint:hover::after, .hint:focus-visible::after { opacity: 1; visibility: visible; }

/* Підказка у вікні. <dialog> у браузері має overflow: auto — тобто ріже все,
 * що виходить за його межі, а вікно вузьке, і підказка обрізалась з будь-якого
 * боку. Тому вікна з підказками позначені класом modal-hints: їм overflow
 * знімається, і хмарка вільно виходить за край. Сама вона при цьому
 * центрується під кнопкою, а не чіпляється краєм. */
.modal-hints { overflow: visible; }
.modal .hint::after { right: auto; left: 50%; transform: translateX(-50%); }

@media (prefers-reduced-motion: reduce) {
  .hint::after { transition: none; }
}

/* ─────────────────────────────────────────────────────────────────────────
 * Чіпи, повідомлення, плашки
 * ───────────────────────────────────────────────────────────────────────── */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--ink-soft);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}

/* Кольори станів. Пропущений стан — це не дрібниця: плашка без кольору
 * означає помилку, схожу на звичайний текст. */
.badge-ok { background: var(--ok-soft); color: var(--ok); }
.badge-off { background: var(--danger-soft); color: var(--danger); }
/* «Спить» — не тривога: сайт живий, просто відпочиває й прокинеться сам. */
.badge-sleep { background: var(--info-soft); color: var(--info); }
.badge-warn { background: var(--warn-soft); color: var(--warn); }

/* Кружечок стану перед адресою сайту. */
.dot { width: 9px; height: 9px; border-radius: 50%; background: currentColor; }

.msg {
  margin: 0 0 14px;
  padding: 13px 16px;
  border-radius: 12px;
  font-size: 15.5px;
}

.msg-error { background: var(--danger-soft); color: var(--danger-dark); }
.msg-success { background: var(--ok-soft); color: #14532d; }
.msg-info { background: var(--info-soft); color: #1e3a8a; }
.msg-warning { background: var(--warn-soft); color: #713f12; }
.msg-debug { background: var(--surface-2); color: var(--muted); }

/* Тимчасовий пароль після скидання. Показується РІВНО ОДИН РАЗ, тому має
 * бути помітним настільки, щоб вчитель його не проґавив. */
.secret {
  padding: 20px;
  border-radius: var(--radius);
  background: var(--warn-soft);
  color: #713f12;
}

/* Пароль великим моноширинним: його переписують з екрана на папірець, а
 * потім з папірця в поле. Кожен крок — шанс сплутати символ. */
.pill {
  display: inline-block;
  padding: 8px 16px;
  border-radius: 10px;
  background: var(--surface);
  border: 2px dashed #d9c66a;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: 0.08em;
}

/* Банер «ти не в себе».
 *
 * Липкий і кричущий навмисне: вчитель, який забув, що сидить у чужому
 * кабінеті, — це вчитель, який зараз зробить щось від імені дитини. */
.impersonating {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 10px 20px;
  background: #fde68a;
  color: #422006;
  font-weight: 600;
}

.impersonating button {
  min-height: 38px;
  padding: 7px 16px;
  border-color: transparent;
  background: #422006;
  color: #fde68a;
}

.impersonating button:hover:not(:disabled) { background: #1c1917; border-color: transparent; }

/* Диск майже повний — на всіх сторінках вчителя. */
.disk-alarm {
  position: relative;
  z-index: 20;
  padding: 11px 20px;
  background: var(--danger);
  color: #fff;
  text-align: center;
  font-weight: 600;
}

.disk-alarm a { color: #fff; }

/* ─────────────────────────────────────────────────────────────────────────
 * Плитки: проекти учня, лічильники вчителя, швидкі переходи
 * ───────────────────────────────────────────────────────────────────────── */

.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
}

.tiles-sm { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }

/* Плитка проекту. Уся плитка — посилання: дитина цілиться в прямокутник, а
 * не в рядок тексту. */
.tile {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
  color: var(--ink);
  text-decoration: none;
}

a.tile:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-2);
  transform: translateY(-2px);
}

a.tile { transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease; }

@media (prefers-reduced-motion: reduce) {
  a.tile { transition: none; }
  a.tile:hover { transform: none; }
}

.tile-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.tile-name { font-size: 18px; font-weight: 700; letter-spacing: -0.01em; }
.tile-sub { color: var(--muted); font-size: 14px; overflow-wrap: anywhere; }

/* Кольоровий значок мови: PHP, Python, Node видно з іншого кінця кабінету. */
.lang {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 12px;
  background: var(--accent-soft);
  color: var(--accent);
}

.lang-php { background: #f1e9ff; color: #7c3aed; }
.lang-python { background: #e4efff; color: #1d4ed8; }
.lang-node { background: #e3f6e8; color: #15803d; }

/* Плитка «＋ Новий проект»: пунктир — універсальна мова «сюди можна додати». */
.tile-new {
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 150px;
  border: 2px dashed #c7d3e6;
  background: transparent;
  box-shadow: none;
  color: var(--accent);
  font-weight: 700;
}

.tile-new:hover { background: var(--accent-soft); border-color: var(--accent); }
.tile-new .lang { background: var(--accent-soft); color: var(--accent); }

/* Лічильник вчителя: велике число, під ним підпис. */
.stat {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
}

.stat .lang { background: var(--accent-soft); color: var(--accent); }
.stat-number { font-size: 28px; font-weight: 700; line-height: 1.1; }
.stat-label { color: var(--muted); font-size: 13.5px; }

/* ─────────────────────────────────────────────────────────────────────────
 * Списки людей і рядкові таблиці
 * ───────────────────────────────────────────────────────────────────────── */

.roster { list-style: none; margin: 0; padding: 0; }

.roster li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 11px 10px;
  border-radius: 12px;
}

.roster li:hover { background: var(--surface-2); }
.roster li + li { border-top: 1px solid var(--line); border-radius: 0; }

.who-cell { display: flex; align-items: center; gap: 11px; min-width: 0; }
.roster .who { font-weight: 600; color: var(--ink); text-decoration: none; }
.roster .who:hover { color: var(--accent); }
.roster .login { color: var(--muted); font-size: 14px; }

/* Список бібліотек: кнопка «＋ назва» і поруч — навіщо вона. */
/* Значення, яке копіюють у код: моноширинне й з кнопкою поруч. */
.copy-cell { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.copy-cell code {
  padding: 4px 10px;
  border-radius: 8px;
  background: var(--surface-2);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 14.5px;
  overflow-wrap: anywhere;
}

/* Журнал: рядки, а не таблиця — на вузькому екрані таблиця з'їжджає, а тут
 * усе одно читають зверху вниз. */
.log { list-style: none; margin: 0; padding: 0; }

.log li {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: baseline;
  padding: 10px 0;
  border-top: 1px solid var(--line);
}

.log li:first-child { border-top: none; }
.log-when { color: var(--muted); font-variant-numeric: tabular-nums; font-size: 14px; }
.log-who { font-weight: 600; }
.log-target { color: var(--accent); }
.log-note { color: var(--muted); }

/* Список чисел «Загалом» — рівні відступи без маркерів. */
.facts { list-style: none; padding: 0; margin: 0; }
.facts li { padding: 7px 0; border-bottom: 1px solid var(--line); }
.facts li:last-child { border-bottom: none; }

/* Справжня таблиця: вміст бази, топи на сторінці «Сервер». */
.table-scroll { overflow-x: auto; }

.data-table {
  border-collapse: collapse;
  width: 100%;
  font-size: 15px;
}

.data-table th, .data-table td {
  border-bottom: 1px solid var(--line);
  padding: 9px 12px;
  text-align: left;
  white-space: nowrap;
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;   /* довге значення не розвалює рядок */
}

.data-table th {
  background: var(--surface-2);
  color: var(--ink-soft);
  font-size: 13.5px;
  font-weight: 600;
}

.data-table tr:hover td { background: var(--surface-2); }

/* ─────────────────────────────────────────────────────────────────────────
 * Смуги заповнення
 * ───────────────────────────────────────────────────────────────────────── */

.quota-bar, .disk-bar {
  height: 9px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
}

.disk-bar { height: 12px; margin-bottom: 10px; }
.quota-fill, .disk-fill { height: 100%; background: var(--accent); border-radius: 999px; }
.quota-fill.quota-full { background: var(--danger); }
.disk-ok .disk-fill { background: #16a34a; }
.disk-warn .disk-fill { background: #d97706; }
.disk-critical .disk-fill { background: var(--danger); }

/* Квота проекту в шапці файлової картки: смуга й підпис в один рядок. */
.quota-inline { display: flex; align-items: center; gap: 10px; min-width: 220px; }
.quota-inline .quota-bar { flex: 1 1 auto; }
.quota-inline .note { margin: 0; white-space: nowrap; }

/* ─────────────────────────────────────────────────────────────────────────
 * Сторінка проекту: смуга сайту й файловий менеджер
 * ───────────────────────────────────────────────────────────────────────── */

/* Смуга сайту: стан, адреса, пояснення й кнопки — один рядок, кнопки
 * праворуч. Висока картка з кнопками під адресою лишала півсмуги порожньою. */
.site-bar { padding: 14px 18px; }

.site-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.site-url {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 17px;
  font-weight: 600;
  text-decoration: none;
  overflow-wrap: anywhere;   /* довга адреса не розтягує мобільний екран */
}

.site-url:hover { text-decoration: underline; }
.site-row .note { margin: 0; }
/* flex-shrink: 0 — інакше кнопки стискаються й розсипаються в стовпчик. */
.site-actions { margin-left: auto; flex: 0 0 auto; }

/* Дві панелі: дерево тек і файли. Мінімальна ширина колонки з файлами
 * важливіша за дерево, тому minmax(0, 1fr). */
.filemanager {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  gap: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1);
  /* Без overflow: hidden навмисно — воно обрізало б меню «⋯» останнього
   * рядка по краю картки. Кути натомість заокруглює сама панель дерева. */
}

.fm-tree { border-radius: var(--radius-lg) 0 0 var(--radius-lg); }

.fm-tree {
  padding: 16px 12px;
  background: var(--surface-2);
  overflow-x: auto;
}

.fm-tree > summary {
  margin-bottom: 10px;
  padding: 4px 6px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}

.tree, .tree ul { list-style: none; margin: 0; padding: 0; }
.tree ul { margin-left: 14px; border-left: 1px solid var(--line); padding-left: 6px; }

/* Рядок дерева — і тека (summary), і файл (a) виглядають однаково: різниця
 * між ними в іконці й у тому, що тека згортається. */
.tree a,
.tree summary {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 8px;
  border-radius: 9px;
  color: var(--ink-soft);
  font-size: 14.5px;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  list-style: none;
}

.tree summary::-webkit-details-marker { display: none; }
.tree summary { padding: 0; }
.tree a:hover, .tree summary:hover { background: #e6edf7; color: var(--ink); }
.tree a.is-current { background: var(--accent); color: #fff; font-weight: 600; }
.tree a.is-current .ic { color: #fff; }

/* Назва теки всередині summary — таке саме посилання, як файл, і займає
 * увесь рядок: цілитись у слово завширшки «js» дитина не має. */
.tree .tree-folder {
  flex: 1 1 auto;
  min-width: 0;
  padding: 6px 8px;
  border-radius: 9px;
}

/* Тека жовта, файл сірий — те саме, що в списку файлів праворуч. */
.tree .tree-folder .ic { color: #d69e2e; }
.tree .tree-file .ic { color: var(--muted); }
.tree .tree-root { font-weight: 600; color: var(--ink); }

/* Стрілка — окрема ціль: клік по ній тільки згортає й розгортає гілку
 * (стандартна поведінка <summary>), а клік по назві відкриває теку праворуч. */
.tree-toggle {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 20px;
  height: 26px;
  margin-left: 4px;
  border-radius: 6px;
  color: var(--muted);
}

.tree-toggle::before { content: "›"; transition: transform 0.1s ease; }
.tree-toggle:hover { background: #d8e2f0; color: var(--ink); }
.tree details[open] > summary .tree-toggle::before { transform: rotate(90deg); }
.tree-empty { margin: 0 0 0 26px; padding: 4px 0; color: var(--muted); font-size: 13px; }

@media (prefers-reduced-motion: reduce) {
  .tree-toggle::before { transition: none; }
}

.fm-main { min-width: 0; padding: 16px 18px 20px; }

.file-toolbar {
  display: flex;
  align-items: stretch;
  gap: 8px;
  flex-wrap: wrap;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
}

.file-toolbar form { margin: 0; }

/* Хлібні крихти: шлях, кожна частина — посилання на свою теку. */
.crumbs {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  padding: 12px 2px;
  font-size: 15px;
}

.crumbs a { display: inline-flex; align-items: center; gap: 6px; text-decoration: none; font-weight: 600; }
.crumbs a:hover { text-decoration: underline; }
.crumbs .sep { color: var(--muted); }

/* Список файлів: рядки, а не <table> — та сама причина, що в журналі. */
.files { list-style: none; margin: 0; padding: 0; }

.file-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 10px;
  border-radius: 10px;
  border-top: 1px solid var(--line);
}

.file-row:first-child { border-top: none; }
.file-row:hover { background: var(--surface-2); }
.file-row-empty { color: var(--muted); justify-content: center; padding: 22px; }

.file-name {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1 1 auto;
  min-width: 0;
  color: var(--ink);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.file-name:hover { color: var(--accent); }
.file-name .ic { color: var(--muted); }
.file-name.is-dir .ic { color: #d69e2e; }
.file-name.is-dir { font-weight: 600; }

.file-size, .file-when {
  color: var(--muted);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.file-size { width: 90px; text-align: right; }
.file-when { width: 120px; text-align: right; }

/* Шапка колонок списку файлів. */
.files-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 6px 10px;
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
}

.files-head .file-name { color: var(--muted); }
.file-menu-space { width: 34px; flex: 0 0 auto; }   /* під кнопку «⋯» у рядку */

/* Меню «⋯» (рядок файлу, картка класу) і меню «Новий файл» — <details>
 * без javascript. */
.menu, .toolbar-menu { position: relative; }

.menu > summary {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  cursor: pointer;
  color: var(--muted);
  list-style: none;
}

.menu > summary::-webkit-details-marker { display: none; }
.menu > summary:hover, .menu[open] > summary { background: #e2e9f4; color: var(--ink); }

.toolbar-menu > summary {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-width: 84px;
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 11px;
  background: var(--surface);
  color: var(--ink);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}

.toolbar-menu > summary::-webkit-details-marker { display: none; }
.toolbar-menu > summary:hover { background: var(--surface-2); }

.menu-list, .toolbar-menu form {
  position: absolute;
  z-index: 15;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 250px;
  margin-top: 6px;
  padding: 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow-2);
}

.menu-list { right: 0; }
.menu-list .btn, .menu-list button { min-height: 38px; padding: 8px 12px; }

/* Форма всередині меню («Перейменувати» — поле плюс кнопка) стає стовпчиком:
 * у рядок вони не влазять і вилазять за межі меню. Ширина меню фіксована,
 * а ім'я файлу буває довгим — поле мусить мати цілий рядок. */
.menu-list form {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  width: 100%;
}

.menu-list form input { flex: 1 1 100%; min-width: 0; }
.menu-list form button { flex: 1 1 auto; }
/* Пункти меню — однакової ширини й з підписом від лівого краю: колонка з
 * різнокаліберних кнопок читається як випадковий набір, а не як список дій.
 * Форма з полем усередині (перейменування файлу) під це не підпадає — там
 * кнопка стоїть поруч із полем, а не сама. */
/* Пункти меню — однакової ширини й з підписом від лівого краю: колонка з
 * різнокаліберних кнопок читається як випадковий набір, а не як список дій. */
.menu-list > button,
.menu-list > .btn,
.menu-list > form > button { justify-content: flex-start; width: 100%; }
.toolbar-menu form { flex-direction: row; }
.toolbar-menu input { width: 190px; }
.toolbar-menu form button { min-height: 38px; }

/* Зона перетягування. Активною її робить files.js під час drag. */
.dropzone {
  margin-top: 14px;
  padding: 22px;
  border: 2px dashed #c7d3e6;
  border-radius: var(--radius);
  color: var(--muted);
  text-align: center;
}

.dropzone-active { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }

/* Сюди files.js пише лічильник «5 із 23» і помилки по файлах. */
.upload-status { margin-top: 12px; }
.upload-status p { margin: 4px 0; }

/* ─────────────────────────────────────────────────────────────────────────
 * Модальні вікна (нативний <dialog>, див. static/js/modal.js)
 * ───────────────────────────────────────────────────────────────────────── */

.modal {
  width: min(460px, calc(100vw - 32px));
  padding: 26px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-2);
}

.modal::backdrop { background: rgb(15 23 42 / 45%); }
.modal h2 { margin-bottom: 8px; font-size: 21px; }
.modal p { color: var(--ink-soft); }
.modal .form { margin-top: 8px; }
.modal .form button { margin-top: 0; }

/* Ряд кнопок унизу вікна. «Скасувати» ЗЛІВА від дії й нейтральна, дія —
 * справа: рука тягнеться до правого краю, і там має бути те, по що прийшли. */
.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 22px;
}

.modal-actions form { margin: 0; }
.modal-actions button { margin-top: 0; }

/* ─────────────────────────────────────────────────────────────────────────
 * Редактор коду
 * ───────────────────────────────────────────────────────────────────────── */

/* Смуга відкритого файлу — на місці панелі дій зі списку файлів. */
.editor-bar { align-items: center; gap: 12px; }
.editor-bar .editor-path {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-right: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 15px;
  font-weight: 600;
  overflow-wrap: anywhere;
}
.editor-bar .note { margin: 0; }
/* Права панель редактора без бічних відступів: код прилягає до країв. */
.editor-page .fm-main { padding: 16px 0 0; }
.editor-page .editor-bar { padding: 0 18px 14px; }

.editor-page #editor {
  width: 100%;
  min-height: 60vh;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 15px;
}

/* CodeMirror стандартної теми розрахований на світлий фон — а панель тепер
 * світла завжди, тож вендорити ще й темну тему нема потреби. */
/* Код — без своєї рамки й без заокруглень: він займає всю праву панель, а
 * картка в картці давала подвійні лінії, які не сходились між собою (рамка
 * панелі, рамка редактора й межа смуги номерів). Від смуги дій його відділяє
 * та сама лінія, що й список файлів на сусідньому екрані. */
.editor-page .CodeMirror {
  height: calc(100vh - 290px);
  min-height: 320px;
  border: 0;
  border-radius: 0;
  font-size: 15px;
}

/* Смуга з номерами рядків — без рамки й без свого фону: вертикальна риска
 * на всю висоту повз єдиний рядок коду читається як щось зайве, що стирчить,
 * а не як межа колонки. Номери й так відділені відступом. */
.editor-page .CodeMirror-gutters { background: transparent; border-right: 0; }
.editor-page .CodeMirror-linenumber { color: var(--muted); }

/* Логи контейнера: моноширинні, зі скролом, найсвіжіше внизу. */
.logs, .snippet {
  background: #0f172a;
  color: #e2e8f0;
  border-radius: 12px;
  padding: 14px 16px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 14px;
  overflow-x: auto;
}

.logs { max-height: 60vh; overflow-y: auto; white-space: pre-wrap; overflow-wrap: anywhere; }

/* Поле «Виконати SQL». */
.sql-box textarea {
  width: 100%;
  min-height: 120px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 15px;
}

.sql-box button { margin-top: 12px; }

/* ─────────────────────────────────────────────────────────────────────────
 * Профіль
 * ───────────────────────────────────────────────────────────────────────── */

.profile-head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.profile-head .name { font-size: 22px; font-weight: 700; }

.two-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 18px;
  align-items: start;
}

.two-cols > .block { margin-bottom: 0; }

/* ─────────────────────────────────────────────────────────────────────────
 * Вузький екран
 *
 * Рейка їде вниз і стає панеллю на весь низ екрана — великі цілі під палець,
 * і руки не закривають вміст. Дерево тек ховається в <details>: у дитини
 * часто три файли, і на телефоні дерево з'їдало б пів екрана.
 * ───────────────────────────────────────────────────────────────────────── */

@media (max-width: 860px) {
  .filemanager { grid-template-columns: minmax(0, 1fr); }
  .fm-tree { border-bottom: 1px solid var(--line); }
  .file-when { display: none; }   /* спершу зникає час, потім розмір */
}

@media (max-width: 720px) {
  .shell { flex-direction: column; }

  .rail {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    top: auto;
    z-index: 30;
    flex-direction: row;
    width: auto;
    height: auto;
    padding: 6px 8px;
    overflow-x: auto;
    box-shadow: 0 -6px 20px rgb(15 23 42 / 18%);
  }

  /* Знак і розпірка зникають — у нижній панелі місце коштує дорого. Чіп
   * користувача лишається: це єдиний вхід у «Профіль». */
  .rail-mark, .rail-spacer { display: none; }
  .rail-who { flex: 1 0 auto; min-width: 68px; border-top: none; padding: 6px 4px; }
  .rail-item { flex: 1 0 auto; min-width: 68px; padding: 6px 4px; }
  .rail form { flex: 1 0 auto; min-width: 68px; }

  .workspace { padding: 16px 14px 96px; }   /* місце під нижню панель */
  .banners { margin: -16px -14px 14px; }
  h1 { font-size: 23px; }
  .file-size { width: auto; }
  .btn-icon, .toolbar-menu > summary { min-width: 74px; }
}
