/* Light theme is the default. Switch by setting `data-theme="dark"` on <html>. */
:root {
  color-scheme: light;
  --bg: #f5f7fa;
  --card: #ffffff;
  --card2: #eef1f6;
  --border: #d6dbe3;
  --text: #1a1d24;
  --muted: #6b7280;
  --accent: #2563d8;
  --accent-fg: #ffffff;
  --accent-dim: #4ea1ff;
  --accent-soft: rgba(37, 99, 216, 0.16);
  --ok: #1f9b4f;
  --warn: #b9760e;
  --err: #c14040;
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0f1115;
  --card: #1a1d24;
  --card2: #232732;
  --border: #2c313d;
  --text: #e6e8eb;
  --muted: #8a92a3;
  --accent: #4ea1ff;
  --accent-fg: #0a1422;
  --accent-dim: #2d6db8;
  --accent-soft: rgba(78, 161, 255, 0.18);
  --ok: #58c97a;
  --warn: #e0a04e;
  --err: #e06464;
}

* { box-sizing: border-box; }

/* Global: HTML `hidden` attribute must always win over author `display:*`.
   Avoids the recurring trap where `.thing { display: flex }` overrides the
   UA `[hidden] { display: none }` rule due to specificity. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  font-size: 15px;
  line-height: 1.45;
}

header {
  padding: 18px 20px 12px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
}
header h1 {
  font-size: 20px;
  margin: 0;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
header h1 .brand { font-weight: 600; display: inline-flex; align-items: center; color: inherit; text-decoration: none; }
/* Square logo with explicit aspect-ratio so the browser reserves space
   before the SVG payload finishes loading - prevents the header from
   shifting around on first paint. */
.brand-logo {
  height: 36px;
  width: 36px;
  aspect-ratio: 1 / 1;
  display: block;
  flex: none;
}
.brand-logo-lg {
  height: 80px;
  width: 80px;
  margin: 4px auto 8px;
}
@media (max-width: 600px) {
  .brand-logo { height: 30px; width: 30px; }
  .brand-logo-lg { height: 64px; width: 64px; }
}
header h1 .tagline {
  font-size: 13px;
  font-weight: 400;
  color: var(--muted);
}
@media (max-width: 900px) {
  header h1 .tagline { display: none; }
}

/* ---- Admin top nav ---- */
.top-nav {
  display: flex;
  gap: 4px;
  flex: 1 1 auto;
  margin-left: 24px;
}
.top-nav .nav-link {
  display: inline-block;
  padding: 6px 14px;
  border-radius: 6px;
  color: var(--muted);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
}
.top-nav .nav-link:hover { color: var(--text); background: var(--card2); }
.top-nav .nav-link.active {
  color: var(--accent);
  background: var(--card2);
}

/* ---- Pagination ---- */
.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
}
.pagination button {
  background: var(--card2);
  color: var(--text);
  border: 1px solid var(--border);
  padding: 5px 10px;
  font-size: 13px;
}
.pagination button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.pagination .page-info { color: var(--muted); font-size: 13px; }

.bell {
  background: transparent;
  border: 0;
  padding: 0 4px;
  margin: 0;
  cursor: pointer;
  font-size: 20px;
  line-height: 1;
  transition: filter 0.15s, opacity 0.15s, transform 0.1s;
}
.bell:hover { transform: scale(1.1); }
.bell.on {
  opacity: 1;
  filter: drop-shadow(0 0 6px rgba(78, 161, 255, 0.7));
}
.bell.off {
  opacity: 0.4;
  filter: grayscale(1);
}

main {
  padding: 16px 20px 60px;
  max-width: 1400px;
  margin: 0 auto;
}

.view-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
}

@media (min-width: 900px) {
  .view-grid { grid-template-columns: 1fr 1fr; }
  .view-grid > .top-row { grid-column: 1 / -1; }
  #watcher-form.grid { grid-template-columns: repeat(2, 1fr); }
}

/* ---- Mobile-specific overrides (≤ 600px, e.g. Pixel 8) ---- */
@media (max-width: 600px) {
  body { font-size: 14px; }
  header {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 8px;
    padding: 10px 14px 8px;
  }
  header h1 { font-size: 18px; flex: 1 1 auto; }
  .top-nav {
    order: 3;
    flex: 0 0 100%;
    margin-left: 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .top-nav .nav-link {
    padding: 6px 10px;
    white-space: nowrap;
    font-size: 13px;
  }
  .header-actions {
    flex: 0 0 auto;
  }

  main { padding: 12px; }
  .view-grid { gap: 12px; }

  .card { padding: 12px; }
  .card h2, .card-title { font-size: 15px; }

  /* Calendar header: select + filter wrap on small screens */
  .calendar-card .row-between {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
  }
  .grid-controls { flex-wrap: wrap; gap: 8px; }
  .grid-filter {
    flex-wrap: wrap;
    gap: 8px;
    width: 100%;
  }
  select.park-inline {
    width: 100%;
    min-width: 0;
  }
  .grid-filter input[type="time"] { width: 90px; flex: 0 0 auto; }
  .grid-presets { flex-wrap: wrap; }
  .grid-checkbox { flex: 0 0 auto; }

  /* Calendar grid cells: shrink so 4-5 fit per row */
  .grid-cell { width: 52px; }
  .grid-cells { gap: 4px; }

  /* Free-slots popup inside watcher row */
  .free-grid { grid-template-columns: repeat(auto-fill, minmax(72px, 1fr)); }

  /* Welcome card text */
  .welcome-list { padding-left: 18px; }
  .welcome-card p { font-size: 13px; }

  /* Users management form: stack fields */
  .users-form label { flex: 1 1 100%; }

  /* Watcher form: single column */
  #watcher-form.grid { grid-template-columns: 1fr; }
  .weekdays { gap: 6px 10px; }

  /* Item rows: title and actions stack */
  .item {
    flex-direction: column;
    align-items: stretch;
  }
  .item-actions {
    width: 100%;
    justify-content: flex-end;
    flex-wrap: wrap;
  }

  /* Feedback paginator */
  .pagination button { padding: 6px 10px; }
}

/* Always: prevent horizontal scroll caused by anything overflowing */
html, body { overflow-x: hidden; }
.card, .view { max-width: 100%; overflow-wrap: break-word; }
/* `main` is NOT in the rule above on purpose - it owns the page's outer
   centered container (max-width + margin: 0 auto, defined further up),
   and overriding it with max-width:100% here would left-anchor every page. */

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
}
.card h2 { margin: 0 0 12px; font-size: 16px; }

form.grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
form .full { grid-column: 1 / -1; }
form label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
  color: var(--muted);
}
form input, form select {
  background: var(--card2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  font-size: 14px;
  font-family: inherit;
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
}
form input:focus, form select:focus { outline: 2px solid var(--accent-dim); }

fieldset.weekdays {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 14px;
  color: var(--text);
}
fieldset.weekdays legend { color: var(--muted); font-size: 13px; padding: 0 6px; }
fieldset.weekdays label {
  flex-direction: row;
  align-items: center;
  gap: 4px;
  color: var(--text);
}

.actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 4px;
}

button {
  background: var(--accent);
  color: var(--accent-fg);
  border: none;
  border-radius: 6px;
  padding: 9px 14px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
}
button:hover { filter: brightness(1.08); }
button.ghost {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  font-weight: 500;
}
button.danger { background: var(--err); color: #fff; }
button.small { padding: 4px 10px; font-size: 12px; }

.list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.list .empty {
  color: var(--muted);
  padding: 12px;
  text-align: center;
  font-style: italic;
}

.item {
  background: var(--card2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.item.disabled { opacity: 0.55; }
.item-meta { color: var(--muted); font-size: 12px; }
.item-title { font-weight: 600; }
.item-actions { display: flex; gap: 6px; }

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

.free-panel {
  background: var(--card2);
  border: 1px solid var(--border);
  border-top: none;
  border-radius: 0 0 8px 8px;
  margin-top: -6px;
  padding: 10px 12px;
}
.free-head {
  color: var(--muted);
  font-size: 12px;
  margin-bottom: 8px;
}
.free-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 6px;
}
.free-slot {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 8px;
  font-size: 13px;
  text-align: center;
}
.free-slot a { text-decoration: none; }
.free-slot a:hover { text-decoration: underline; }
.free-empty {
  color: var(--muted);
  font-size: 13px;
  padding: 6px 0;
}
.free-empty.error { color: var(--err); }
.free-empty.account-active-empty {
  /* "Активных броней пока нет" + CTA на календарь — рисуем по центру,
     с воздухом, чтобы карточка не выглядела пустой одной строкой. */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 24px 16px;
  text-align: center;
}
.free-empty.account-active-empty p { margin: 0; }
.free-empty.park-closed {
  font-size: 15px;
  padding: 60px 16px;
  color: var(--muted);
  letter-spacing: 0.5px;
  text-align: center;
}

/* ---- Unified grid ---- */
.grid-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.card-title {
  margin: 0 0 12px;
  font-size: 16px;
}

/* ---- Top row: welcome + calendar ---- */
.top-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
}
@media (min-width: 900px) {
  .top-row {
    grid-column: 1 / -1;
    grid-template-columns: 280px 1fr;
    align-items: start;
  }
}
.welcome-card p {
  margin: 8px 0;
  color: var(--text);
  line-height: 1.5;
  font-size: 14px;
}
.welcome-list {
  margin: 6px 0 12px;
  padding-left: 22px;
  font-size: 14px;
  color: var(--text);
  line-height: 1.5;
}
.welcome-list li { margin: 2px 0; }
.welcome-parks .welcome-extra { display: none; }
.welcome-parks.expanded .welcome-extra { display: list-item; }
.welcome-more {
  margin: -4px 0 8px;
  padding: 0;
  font-size: 13px;
}
.welcome-parks.expanded + .welcome-more { display: none; }
.muted-text {
  color: var(--muted) !important;
  font-size: 13px !important;
  font-style: italic;
}

/* ---- Feedback form ---- */
.feedback-form {
  margin-top: 18px;
  padding: 14px 14px 12px;
  border: 1px solid var(--accent-dim);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 6%, var(--card));
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.feedback-label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 13px;
  color: var(--muted);
}
.feedback-form textarea,
.feedback-form input[type="text"] {
  background: var(--card2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  font-family: inherit;
  font-size: 14px;
}
.feedback-form textarea {
  resize: vertical;
  min-height: 60px;
}
.feedback-form textarea:focus,
.feedback-form input[type="text"]:focus { outline: 2px solid var(--accent-dim); }
.feedback-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.feedback-counter { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.feedback-msg { font-size: 13px; }
.feedback-msg.ok { color: var(--ok); }
.feedback-msg.error { color: var(--err); }
.feedback-message {
  margin-top: 6px;
  padding: 8px 10px;
  background: var(--card2);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 14px;
  color: var(--text);
  white-space: pre-wrap;
  word-wrap: break-word;
}
.park-picker {
  display: inline-flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  color: var(--muted);
  cursor: pointer;
}
select.park-inline {
  background: var(--card2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 15px;
  font-family: inherit;
  font-weight: 600;
  min-width: 220px;
}
select.park-inline:focus { outline: 2px solid var(--accent-dim); }
.park-row {
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
}
.catch-cta {
  font-size: 13px;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
}
.catch-cta-icon { margin-right: 2px; }
.catch-cta-action {
  color: var(--accent);
  font-weight: 600;
  margin-left: 4px;
}
.catch-cta:hover { color: var(--text); }
.catch-cta:hover .catch-cta-action { text-decoration: underline; }
.grid-filter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.grid-filter input[type="time"] {
  background: var(--card2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 13px;
  font-family: inherit;
  width: 100px;
}
.grid-filter input[type="time"]:focus { outline: 2px solid var(--accent-dim); }
.grid-presets {
  display: inline-flex;
  gap: 4px;
  padding-left: 4px;
}
.grid-presets button.active {
  background: var(--accent);
  color: var(--accent-fg);
  border-color: var(--accent);
}
.grid-checkbox {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  user-select: none;
}
.legend-item { cursor: pointer; user-select: none; }
.legend-item input[type="checkbox"] { margin: 0; }
.grid-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  padding: 8px 10px;
  margin-bottom: 12px;
  background: var(--card2);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 13px;
}
.legend-item { display: inline-flex; align-items: center; gap: 6px; }
.legend-swatch {
  display: inline-block;
  width: 14px; height: 14px;
  border-radius: 3px;
}
.grid-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 36px 20px;
  color: var(--muted);
  font-size: 14px;
}
.spinner {
  width: 22px;
  height: 22px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.grid-day { margin-bottom: 18px; }
.grid-day-title {
  font-size: 14px;
  margin: 0 0 8px;
  color: var(--text);
}
/* Сводка погоды на день (иконка + макс. температура) рядом с
   заголовком дня. Open-Meteo через /api/weather; маппинг
   парк → координаты — в app/routes/weather_api.py. */
.grid-day-title .wx {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  margin-left: 10px;
  color: var(--muted);
  font-weight: 500;
  font-size: 13px;
}
.grid-day-title .wx-icon { font-size: 16px; line-height: 1; }
.grid-day-title .wx-temp { color: var(--text); }
.grid-cells {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.grid-cell {
  width: 60px;
  background: var(--card2);
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  position: relative;
}
/* Free cells: tinted background + accent border + soft glow.
   .has-mine / .has-autobook come later in the file and override these
   (their orange border + star/clock corner mark take precedence). */
.grid-cell.has-free {
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--accent) 12%, var(--card2)),
    var(--card2));
  border-color: var(--accent);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent),
    0 2px 8px color-mix(in srgb, var(--accent) 15%, transparent);
}
/* Pre-attentive green dot — strongest at-a-glance signal that something
   is bookable in this hour. Suppressed when the cell is also has-mine /
   has-autobook: they also paint ::after, and because their rules come
   later in the file they only partially override ours, producing a
   hybrid (star character + green box at the wrong corner). The :not()s
   make sure their ::after takes over cleanly. */
.grid-cell.has-free:not(.has-mine):not(.has-autobook)::after {
  content: '';
  position: absolute;
  top: 4px;
  right: 4px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ok);
  box-shadow: 0 0 6px var(--ok);
  pointer-events: none;
}
/* Fully busy cells (no free lines) - fade out so free slots stand out. */
.grid-cell:not(.has-free) {
  background: transparent;
  border-color: color-mix(in srgb, var(--border) 45%, transparent);
  opacity: 0.5;
}
.grid-cell:not(.has-free) .grid-time {
  color: var(--muted);
  opacity: 0.6;
}
.grid-cell:not(.has-free) .grid-svcs {
  border-top-color: color-mix(in srgb, var(--border) 45%, transparent);
}
.grid-time {
  font-size: 12px;
  padding: 4px 2px;
  text-align: center;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.grid-svcs {
  display: flex;
  height: 14px;
  border-top: 1px solid var(--border);
}
.grid-svc {
  flex: 1;
  background: var(--c, var(--muted));
  border: none;
  padding: 0;
  display: block;
  text-decoration: none;
}
.grid-svc.free {
  opacity: 1;
}
.grid-svc.free[href] {
  cursor: pointer;
}
.grid-svc.free[href]:hover {
  filter: brightness(1.2);
}
.grid-svc.busy {
  /* Busy badges recede into the background so free slots dominate
     visually. 0.10 + light grayscale kills most colour identity (busy
     slot identity isn't important to the reader; what's free is). The
     cell-level dot + glow on free cells carry the positive signal. */
  opacity: 0.10;
  filter: grayscale(0.7);
}
.grid-svc.missing {
  flex: 1;
  background: transparent;
  background-image: repeating-linear-gradient(45deg, var(--border) 0 2px, transparent 2px 5px);
}

/* Author rules above set display:flex/grid/block, which override the UA
   `[hidden] { display: none }`. Force-hide for elements toggled by JS. */
/* (global `[hidden]` rule at top of file handles all forced-hide cases) */

.badge {
  display: inline-block;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  background: var(--card);
  border: 1px solid var(--border);
  color: var(--muted);
  padding: 1px 6px;
  border-radius: 4px;
  margin-right: 6px;
  vertical-align: middle;
}

.find { border-left: 3px solid var(--ok); }
.find.fresh {
  animation: pulse 1.6s ease-out 3;
  border-left-color: var(--accent);
}
@keyframes pulse {
  0% { background: var(--accent-soft); }
  100% { background: var(--card2); }
}

.row-between {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 12px;
}

.muted { color: var(--muted); font-size: 12px; }
.status {
  color: var(--muted);
  font-size: 12px;
}
.status.ok { color: var(--ok); }
.status.err { color: var(--err); }

footer {
  padding: 12px 20px 30px;
  text-align: center;
  border-top: 1px solid var(--border);
}
footer.site-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 20px 20px;
  text-align: left;
}
.footer-legal-link {
  font-size: 11px;
  color: var(--muted);
  text-decoration: none;
}
.footer-legal-link:hover { color: var(--text); text-decoration: underline; }
footer.site-footer #app-version { font-size: 11px; }

/* ---- Cookie banner ---- */
.cookie-banner {
  position: fixed;
  left: 16px;
  right: 16px;
  bottom: 16px;
  z-index: 1000;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.18);
  font-size: 13px;
  line-height: 1.4;
  max-width: 720px;
  margin: 0 auto;
}
.cookie-banner-text { flex: 1; color: var(--text); }
.cookie-banner-btn {
  flex: none;
  padding: 6px 14px;
  font-size: 13px;
  border-radius: 6px;
  cursor: pointer;
  background: var(--accent);
  color: var(--accent-fg);
  border: 1px solid var(--accent);
}
.cookie-banner-btn:hover { background: var(--accent-dim); border-color: var(--accent-dim); }
@media (max-width: 600px) {
  .cookie-banner {
    flex-direction: column;
    align-items: stretch;
    left: 8px;
    right: 8px;
    bottom: 8px;
    font-size: 12px;
  }
  .cookie-banner-btn { align-self: flex-end; }
}

/* ---- Legal documents ---- */
.legal-doc h2 {
  font-size: 17px;
  margin: 20px 0 8px;
}
.legal-doc h3 { font-size: 15px; margin: 14px 0 6px; }
.legal-doc code {
  font-size: 12px;
  padding: 1px 5px;
  background: var(--card2);
  border-radius: 4px;
}

/* ---- Signup consent ---- */
.consent-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 12px;
  color: var(--muted);
  line-height: 1.4;
  margin: 4px 0 2px;
}
.consent-row input[type="checkbox"] {
  margin-top: 2px;
  flex: none;
}
.consent-row a { color: var(--accent); }

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

/* ---- Collapsible card ---- */
.collapsible .collapsible-header {
  cursor: pointer;
  user-select: none;
  margin: 0;
  display: flex;
  align-items: center;
  gap: 8px;
}
.collapsible .collapsible-header:hover { color: var(--accent); }
.collapsible .caret {
  display: inline-block;
  font-size: 11px;
  color: var(--muted);
  transition: transform 0.15s;
  width: 12px;
}
.collapsible.open .caret { color: var(--accent); }
.collapsible .collapsible-body { margin-top: 12px; }
.guest-notice {
  padding: 16px;
  color: var(--muted);
  font-style: italic;
  text-align: center;
  background: var(--card2);
  border: 1px dashed var(--border);
  border-radius: 6px;
}

/* ---- Users management ---- */
.users-form {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: end;
  margin-top: 14px;
  padding: 12px;
  background: var(--card2);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.users-form label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  color: var(--muted);
  flex: 1 1 160px;
}
.users-form input, .users-form select {
  background: var(--card);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 7px 9px;
  font-size: 14px;
  font-family: inherit;
}
.users-form input:focus, .users-form select:focus {
  outline: 2px solid var(--accent-dim);
}
.users-form-title {
  flex-basis: 100%;
  font-weight: 600;
  color: var(--text);
  font-size: 14px;
}
.users-form .actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}
.user-row { background: var(--card2); }
.user-row .item-meta .role-badge {
  display: inline-block;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  border-radius: 4px;
  margin-right: 6px;
  text-transform: uppercase;
}
.role-badge.role-ADMIN { background: var(--accent); color: var(--accent-fg); }
.role-badge.role-USER  { background: var(--card); color: var(--muted); border: 1px solid var(--border); }
.role-badge.role-BETA_TESTER { background: #ffb300; color: #1b1b1b; }

/* ---- Audit log ---- */
.audit-row { background: var(--card2); }
.audit-badge {
  display: inline-block;
  padding: 1px 7px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  border-radius: 4px;
  margin-right: 6px;
  text-transform: uppercase;
}
.audit-badge.audit-ok     { background: var(--ok);  color: #fff; }
.audit-badge.audit-fail   { background: var(--err); color: #fff; }
.audit-badge.audit-locked { background: var(--warn); color: #fff; }
.audit-ua {
  margin-top: 4px;
  font-size: 11px;
  color: var(--muted);
  word-break: break-all;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* ---- Login page ---- */
.login-page {
  min-height: 100vh;
  display: grid;
  place-items: center;
  margin: 0;
  padding: 20px;
}
.login-card {
  width: min(360px, 100%);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.login-card form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.login-card h1 {
  font-size: 22px;
  text-align: center;
  margin: 0 0 6px;
}
.login-tagline {
  text-align: center;
  color: var(--muted);
  font-size: 13px;
  font-weight: 400;
  margin: -8px 0 4px;
  line-height: 1.35;
}
.login-card label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
  color: var(--muted);
}
.login-card input {
  background: var(--card2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 9px 11px;
  font-size: 15px;
  font-family: inherit;
}
.login-card input:focus { outline: 2px solid var(--accent-dim); }
.error { color: var(--err); font-size: 13px; }

/* ---- Signup-request flow on login page ---- */
.signup-cta {
  font-size: 15px;
  text-align: center;
  background: transparent;
  border: none;
  color: var(--text);
  cursor: pointer;
  padding: 10px 4px 0;
  margin-top: 4px;
  border-top: 1px solid var(--border);
  font-weight: 500;
}
.signup-cta:hover { text-decoration: none; }
.signup-cta-action {
  color: var(--ok);
  text-decoration: underline;
  margin-left: 2px;
}
.signup-cta:hover .signup-cta-action { filter: brightness(1.15); }

/* "Продолжить как гость" — вторичный CTA под кнопкой «Войти». Сделан
   outlined-аксентным, чтобы было видно «вход не обязателен», но не
   конкурировал по визуальному весу с самой кнопкой логина. */
.guest-cta {
  display: block;
  text-align: center;
  padding: 10px 12px;
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  color: var(--accent);
  text-decoration: none;
  font-weight: 600;
  transition: background 0.15s;
}
.guest-cta:hover {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  text-decoration: none;
}
.guest-cta-meta {
  display: block;
  font-size: 12px;
  font-weight: 400;
  color: var(--muted);
  margin-top: 2px;
}

.signup-form { display: flex; flex-direction: column; gap: 12px; }
.signup-actions { justify-content: flex-end; }
.signup-success { text-align: center; padding: 6px 0; }

/* ---- Logout button in header ---- */
header .header-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
button.link-btn {
  background: transparent;
  color: var(--muted);
  border: none;
  cursor: pointer;
  font-size: 12px;
  padding: 4px 6px;
}
button.link-btn:hover { color: var(--text); text-decoration: underline; }

.btn-login {
  display: inline-block;
  padding: 6px 14px;
  background: var(--accent);
  color: #fff;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  line-height: 1.4;
  transition: filter 0.12s;
}
.btn-login:hover { filter: brightness(1.1); text-decoration: none; }

.me-avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--border);
  vertical-align: middle;
}

/* Login page: Yandex SSO button + "or password" divider */
.ya-button-wrap {
  margin: 6px 0 14px;
  min-height: 40px;
  display: flex;
  justify-content: center;
}
.login-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 6px 0 14px;
  color: var(--muted);
  font-size: 12px;
  text-transform: lowercase;
}
.login-divider::before,
.login-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* Small avatar in admin users list */
.user-avatar {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--border);
  vertical-align: middle;
  margin-right: 6px;
}

.badge-yandex {
  display: inline-block;
  padding: 1px 6px;
  margin-left: 6px;
  border-radius: 4px;
  background: #ffcc00;
  color: #1a1d24;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.3px;
  vertical-align: middle;
}

/* ---- Breadcrumbs (catch.html / future inner pages) ---- */
.breadcrumbs {
  font-size: 13px;
  color: var(--muted);
  margin: 0 0 12px;
}
.breadcrumbs ol {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.breadcrumbs li + li::before {
  content: "›";
  margin-right: 6px;
  color: var(--border);
}
.breadcrumbs a { color: var(--muted); text-decoration: none; }
.breadcrumbs a:hover { color: var(--accent); }
.breadcrumbs [aria-current="page"] { color: var(--text); }

/* ---- Catch SEO landing ---- */
.catch-page {
  max-width: 900px;
  margin: 0 auto;
}
.catch-page .page-title {
  margin: 0 0 12px;
  font-size: 22px;
  line-height: 1.25;
  color: var(--text);
}
.catch-page h2 {
  margin-top: 18px;
  font-size: 17px;
}
.catch-page h3 {
  margin: 14px 0 4px;
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
}
.catch-page p { margin: 6px 0 10px; }
@media (max-width: 600px) {
  .catch-page .page-title { font-size: 19px; }
  .catch-page h2 { font-size: 16px; }
}

/* Carve out a bit of breathing room above the "Активные брони" block
   inside /account - by default it sits flush against the абонементы list
   above and the section title gets visually swallowed. */
#account-active-card { margin-top: 18px; }

/* ---- FAQ collapsible questions ---- */
.faq-list { display: flex; flex-direction: column; gap: 4px; }
.faq-item { padding: 8px 0; border-bottom: 1px solid var(--border); }
.faq-item:last-child { border-bottom: 0; }
.faq-q { font-size: 15px; }
.faq-item .collapsible-body { margin-top: 4px; padding-left: calc(1em + 8px); }
.faq-item .collapsible-body p:first-child { margin-top: 0; }
.faq-item .collapsible-body p:last-child { margin-bottom: 0; }

/* ---- Theme toggle ---- */
.theme-toggle {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
  width: 32px;
  height: 32px;
  padding: 0;
  border-radius: 8px;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
}
.theme-toggle:hover { background: var(--card2); border-color: var(--accent); }
.theme-toggle:active { transform: scale(0.94); }
.theme-toggle .icon-sun { display: none; }
.theme-toggle .icon-moon { display: inline; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: inline; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }

/* Floating variant for login page */
.theme-toggle.floating {
  position: fixed;
  top: 14px;
  right: 14px;
  background: var(--card);
  z-index: 10;
}

/* ---- Welcome collapse (mobile) ---- */
.welcome-expand-btn { display: none; }
@media (max-width: 900px) {
  .welcome-collapse { display: none; }
  .welcome-collapse.expanded { display: block; }
  .welcome-expand-btn { display: inline; margin: 4px 0 2px; }
}

/* ---- Modal popup ---- */
.modal-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.45);
  display: flex; align-items: center; justify-content: center;
  z-index: 200;
}
.modal-overlay[hidden] { display: none; }
.modal {
  background: var(--card);
  border-radius: 10px;
  width: min(540px, 94vw);
  max-height: 80vh;
  display: flex; flex-direction: column;
  box-shadow: 0 8px 32px rgba(0,0,0,.25);
}
.modal-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px 10px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.modal-header h3 { margin: 0; font-size: 16px; }
.modal-body {
  overflow-y: auto;
  padding: 12px 18px 18px;
  flex: 1;
}
.tg-icon {
  width: 18px;
  height: 18px;
  fill: currentColor;
  vertical-align: -3px;
  flex-shrink: 0;
}
.tg-icon path { fill: currentColor; }

.tg-msg {
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.tg-msg:last-child { border-bottom: none; }
.tg-msg-time { color: var(--muted); font-size: 11px; margin-bottom: 2px; }
.tg-msg-text { white-space: pre-wrap; word-break: break-word; }

/* ---- Confirm / Alert dialog ---- */
.dialog-modal { width: min(360px, 92vw); max-height: none; }
.dialog-body { padding: 22px 20px 18px; }
/* pre-line: сообщения с \n (например список слотов, которые не удалось
   забронировать из корзины) рендерятся построчно. */
.dialog-message { margin: 0 0 20px; font-size: 15px; line-height: 1.5; white-space: pre-line; }
.dialog-actions { display: flex; justify-content: flex-end; gap: 8px; }
.dialog-actions button {
  padding: 7px 18px; border-radius: 6px; font-size: 14px; cursor: pointer;
  border: 1px solid var(--border); background: var(--card); color: var(--text);
  transition: background .15s;
}
.dialog-actions button:hover { background: var(--hover-bg, #f0f0f0); }
[data-theme="dark"] .dialog-actions button:hover { background: var(--hover-bg, #2a2a2a); }
.dialog-actions button.dialog-ok-danger {
  background: #e53e3e; color: #fff; border-color: #c53030;
}
.dialog-actions button.dialog-ok-danger:hover { background: #c53030; }
.dialog-actions button.dialog-ok-primary {
  background: var(--accent, #3b82f6); color: #fff; border-color: var(--accent, #3b82f6);
}
.dialog-actions button.dialog-ok-primary:hover { opacity: .88; }

/* ---- Park account linkage ---- */
.park-tabs {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 14px 0 12px;
}
.park-tab {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--card2); border: 1px solid var(--border); border-radius: 999px;
  padding: 6px 14px; cursor: pointer; color: var(--muted); font-size: 14px;
  white-space: nowrap;
}
.park-tab:hover { color: var(--text); }
.park-tab.active {
  color: #fff; background: var(--accent, #3b82f6); border-color: var(--accent, #3b82f6);
}
.park-tab.connected { border-color: #10b981; }
.park-tab.connected:not(.active) { color: var(--text); }
.park-tab-check {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; flex-shrink: 0;
  background: #10b981; color: #fff; border-radius: 50%;
  font-weight: 700; font-size: 10px; line-height: 1;
}
.park-tab.active .park-tab-check { background: #fff; color: var(--accent, #3b82f6); }
.account-status { margin: 12px 0; }
.account-card {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 10px 12px;
  background: var(--card2); border: 1px solid var(--border); border-radius: 8px;
}
.account-tabs { display: flex; gap: 4px; margin: 12px 0 10px; border-bottom: 1px solid var(--border); }
.account-tab {
  background: transparent; border: 0; border-bottom: 2px solid transparent;
  padding: 8px 12px; cursor: pointer; color: var(--muted); font-size: 14px;
}
.account-tab.active { color: var(--text); border-bottom-color: var(--accent, #3b82f6); }
.account-form { display: flex; flex-direction: column; gap: 10px; max-width: 420px; }
.account-form label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: var(--muted); }
.account-form input {
  padding: 8px 10px; border: 1px solid var(--border); border-radius: 6px;
  background: var(--bg); color: var(--text); font-size: 14px;
}
.account-snippet {
  background: var(--card2); border: 1px solid var(--border); border-radius: 6px;
  padding: 8px 10px; font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 13px; margin: 4px 0;
}
.account-form-msg { font-size: 13px; color: var(--muted); }
.account-form-msg.error { color: var(--err); }

#account-bookings-card { margin-top: 18px; }
.booking-row { gap: 8px; }
.booking-badge {
  display: inline-block; margin-left: 6px; padding: 1px 7px;
  font-size: 11px; font-weight: 600; border-radius: 10px;
  vertical-align: middle;
}
.booking-badge-ok     { background: #d1fae5; color: #065f46; }
.booking-badge-paid   { background: #dbeafe; color: #1e40af; }
.booking-badge-done   { background: #e5e7eb; color: #374151; }
.booking-badge-cancel { background: #fee2e2; color: #991b1b; }
.booking-badge-muted  { background: var(--card2); color: var(--muted); border: 1px solid var(--border); }
.booking-cancel { opacity: 0.7; }
[data-theme="dark"] .booking-badge-ok     { background: #064e3b; color: #6ee7b7; }
[data-theme="dark"] .booking-badge-paid   { background: #1e3a8a; color: #93c5fd; }
[data-theme="dark"] .booking-badge-done   { background: #1f2937; color: #d1d5db; }
[data-theme="dark"] .booking-badge-cancel { background: #4c1d1d; color: #fca5a5; }

/* My booking overlay on the calendar grid. The bar keeps the line's own
   palette color (var(--c) inherited from inline style on .grid-svc) but
   loses the faded-busy opacity. The cell border/star use var(--my-color)
   set by JS to the same palette color, so visually "my booking" tracks
   the line it was made on. */
.grid-svc.my-booking {
  opacity: 1 !important;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.35);
}
/* Admin with linked cabinet: hint that my-booking badges are clickable to
   cancel. The `has-autobook` class is set on the parent grid view when
   the same gating (admin + connected) is on. */
#grid-view.has-autobook .grid-svc.my-booking {
  cursor: pointer;
}
.grid-cell.has-mine {
  position: relative;
  border: 2px solid var(--my-color, #f59e0b);
  background: color-mix(in srgb, var(--my-color, #f59e0b) 12%, transparent);
}
.grid-cell.has-mine .grid-time {
  color: var(--my-color, var(--text));
  font-weight: 600;
  opacity: 1;
  /* Counter the palette colours being light-on-light by darkening for the
     time label specifically. */
  filter: brightness(0.75) saturate(1.4);
}
.grid-cell.has-mine::after {
  content: "★";
  position: absolute;
  top: -1px;
  left: 3px;
  font-size: 10px;
  line-height: 1;
  color: var(--my-color, currentColor);
  filter: brightness(0.85) saturate(1.4);
  pointer-events: none;
}
[data-theme="dark"] .grid-cell.has-mine .grid-time,
[data-theme="dark"] .grid-cell.has-mine::after {
  filter: brightness(1.15) saturate(1.1);
}

/* Legend entry for "my booking": neutral outlined-star swatch so it doesn't
   pretend to be any particular palette colour. */
.legend-item.legend-static,
.legend-item.legend-mine,
.legend-item.legend-autobook { cursor: default; }
.legend-item.legend-mine .legend-swatch {
  background: transparent;
  border: 2px solid currentColor;
  position: relative;
  box-sizing: border-box;
}
.legend-item.legend-mine .legend-swatch::after {
  content: "★";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 9px;
  color: currentColor;
  line-height: 1;
}
.legend-mine-link {
  color: var(--muted);
  font-size: 12px;
  text-decoration: underline;
  cursor: pointer;
}
.legend-mine-link:hover { color: var(--text); }

/* Auto-book legend entry: outlined swatch with the clock icon inside,
   matching the cell-corner mark. The icon is mask-painted with
   currentColor (same trick as `.legend-mine` uses for ★) and shrunk a
   couple of pixels so it doesn't kiss the swatch border. */
.legend-item.legend-autobook .legend-swatch {
  background: transparent;
  border: 2px solid currentColor;
  position: relative;
  box-sizing: border-box;
}
.legend-item.legend-autobook .legend-swatch::after {
  content: "";
  position: absolute;
  inset: 2px;
  background-color: currentColor;
  -webkit-mask-image: var(--clock-mask);
          mask-image: var(--clock-mask);
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-position: center;
          mask-position: center;
}

/* ---- Auto-book clock icon on busy slots ---- */
/*
 * Visible only when:
 *   - the calendar is rendered with `.has-autobook` on #grid-view
 *     (script sets this when current user is admin AND the current park
 *      has a connected rubitime cabinet);
 *   - the .grid-svc is .busy or .my-booking (we don't show on free slots,
 *     since those are already bookable manually).
 * The clock sits in the upper-right corner of the bar. Its colour comes
 * from a CSS variable so JS can switch states (idle vs scheduled) without
 * swapping the markup.
 */
/* For autobookable busy badges we replace the cascading `opacity: 0.08`
   (which would fade the icon too) with an alpha-blended background so the
   bar still reads as "faded busy" but the clock pseudo-element renders at
   full opacity. The SVG carries its own filled disc background so the
   icon stays crisp regardless of the bar's palette colour. */
.grid-svc.autobookable {
  position: relative;
  cursor: pointer;
  pointer-events: auto;
  opacity: 1 !important;
  background: color-mix(in srgb, var(--c, var(--muted)) 30%, transparent);
}
.grid-svc.autobookable::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--clock-icon-grey);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 9px 9px;
  pointer-events: none;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.45));
}
.grid-svc.autobookable:hover {
  background: color-mix(in srgb, var(--c, var(--muted)) 55%, transparent);
}
/* When an auto-book is set, the badge looks just like .my-booking and the
   cell gets the full booked-looking border (see .grid-cell.has-autobook
   below). The inner clock icon is suppressed - the cell-level corner
   clock takes over so the two don't compete visually. */
/* Badge stays faded (matches regular .busy) so it doesn't pretend to be
   booked; the cell-level border + corner clock carry the auto-book
   signal. Inner clock is suppressed for the same reason. Opacity matches
   .grid-svc.busy so the two states look identical at the plaque level. */
.grid-svc.autobookable.has-autobook {
  opacity: 0.10 !important;
  filter: grayscale(0.7);
  background: var(--c, var(--muted));
  box-shadow: none;
}
.grid-svc.autobookable.has-autobook::after { display: none; }

/* Vilamipovode-style trainer overlay: один значок-силуэт на каждого тренера,
   свободного на этом слоте, окрашенный в его цвет (--c из JS = trainer.color).
   Сами значки рисуем через mask-image — так фон элемента (= цвет тренера)
   виден через силуэт без всяких filter-хаков (раньше grayscale обесцвечивал
   и фон, из-за чего в легенде все значки выглядели одинаково серыми).
   Значки лежат в левом верхнем углу ячейки (не привязаны к линиям). Клик
   по плашке свободной линии по-прежнему открывает popover «без тренера / с X»;
   нужная per-line привязка хранится в .grid-svc[data-trainer-ids]. */
.trainer-mark {
  display: inline-block;
  width: 10px;
  height: 10px;
  background-color: var(--c, #888);
  -webkit-mask-image: var(--trainer-mask);
          mask-image: var(--trainer-mask);
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
  pointer-events: none;
  vertical-align: middle;
}
/* Значки тренеров стоят столбиком у левого края ровно туда, где живёт ★
   моей брони (top:0, left:3) - так они не залезают на центрированное время.
   Когда в этом углу уже сидит ★ (has-mine) или часы (has-autobook), приоритет
   у них, иконки тренера прячем целиком - но это чисто визуально, на фильтрацию
   слотов не влияет (cell.dataset.cellTrainerIds выставляется всегда). */
.grid-cell.has-trainer > .trainer-mark {
  position: absolute;
  left: 3px;
  width: 8px;
  height: 8px;
  z-index: 2;
  /* top выставляется инлайном в applyTrainerOverlayDecorations (0/9/18 по
     индексу). nth-of-type здесь не работает: в ячейке первый <span> -
     это .grid-time, и `:nth-of-type(1)` приклеился бы к нему, а не к марке. */
}
.grid-cell.has-mine > .trainer-mark,
.grid-cell.has-autobook > .trainer-mark { display: none; }

.legend-trainer-mark {
  margin-right: 4px;
  width: 12px;
  height: 12px;
}
/* Разрыв строки внутри flex-легенды: пустой элемент с flex-basis:100%
   принудительно загоняет последующие пункты на следующую строку.
   Используется для отделения тренерских чекбоксов от линий услуг. */
.legend-break {
  flex-basis: 100%;
  height: 0;
  margin: 0;
}
/* Лейбл-подсказка перед чекбоксами тренеров: «Только с:» */
.legend-trainer-label {
  color: var(--muted);
  font-size: 13px;
  cursor: default;
  user-select: none;
}

/* Vertical action stack for the booking popover when there are multiple
   options (без тренера / с X / с Y). The default `.ab-actions` is row
   flex; we override for that specific variant only. */
.autobook-popover .ab-actions.ab-actions-vert {
  flex-direction: column;
  align-items: stretch;
}
.autobook-popover .ab-actions.ab-actions-vert > button {
  width: 100%;
}

/* Cell-level "has-autobook" mirrors .has-mine: outer border + tinted
   background using --my-color set by applyAutoBookDecorations. The
   corner mark is a clock (vs. ★ for has-mine) so the two states stay
   distinguishable when scanning the calendar. */
.grid-cell.has-autobook {
  position: relative;
  border: 2px solid var(--my-color, #f59e0b);
  background: color-mix(in srgb, var(--my-color, #f59e0b) 12%, transparent);
}
.grid-cell.has-autobook .grid-time {
  color: var(--my-color, var(--text));
  font-weight: 600;
  opacity: 1;
  filter: brightness(0.75) saturate(1.4);
}
/* Stroked SVG masked over var(--my-color) so the clock picks up the line
   colour - mirrors how .has-mine renders ★ via `color: var(--my-color)`.
   Star fits in its glyph box with built-in padding; the clock SVG is
   drawn edge-to-edge, so we offset it ~2px from the cell's top + left
   to give it the same visual breathing room as the star. Time text gets
   matching extra top padding so the corner mark doesn't crowd it. */
.grid-cell.has-autobook::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 3px;
  width: 10px;
  height: 10px;
  background-color: var(--my-color, currentColor);
  -webkit-mask-image: var(--clock-mask);
          mask-image: var(--clock-mask);
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-size: contain;
          mask-size: contain;
  filter: brightness(0.85) saturate(1.4);
  pointer-events: none;
}
/* Extra top padding does two jobs: shifts the time text down a pixel
   so the clock has clean air above it, and grows the cell itself by
   the same pixel (cell height comes from children) so everything else
   below the time gets a touch more room. */
.grid-cell.has-autobook .grid-time { padding-top: 7px; }
[data-theme="dark"] .grid-cell.has-autobook .grid-time,
[data-theme="dark"] .grid-cell.has-autobook::after {
  filter: brightness(1.15) saturate(1.1);
}
/* Two clock-icon assets:
   --clock-icon-grey / --clock-icon-active are filled SVGs used as
   `background-image` on the inner badge (where the bar colour shows
   through and we need a high-contrast disc).
   --clock-mask is a stroked SVG meant for `mask-image`: the icon takes
   whatever background-color the element gets. We use it for the cell
   corner and the legend swatch so the clock can pick up the line colour
   via `--my-color`, identical to how the star does. */
:root {
  --clock-icon-grey:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23ffffff' stroke='%23202020' stroke-width='2'/><polyline points='12 6 12 12 17 14' fill='none' stroke='%23202020' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --clock-icon-active:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23f59e0b' stroke='%23202020' stroke-width='2'/><polyline points='12 6 12 12 17 14' fill='none' stroke='%23202020' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --clock-mask:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='9' fill='none' stroke='black' stroke-width='2.5'/><polyline points='12 7 12 12 16 14' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  /* Силуэт человечка для значков тренеров; красится через background-color. */
  --trainer-mask:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='8' r='4'/><path d='M4 22c0-4.418 3.582-8 8-8s8 3.582 8 8z'/></svg>");
  /* Галка «слот в корзине» - тот же стиль диска, что и у clock-icon'ов. */
  --cart-check-icon:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23ffffff' stroke='%23202020' stroke-width='2'/><polyline points='7 12.5 10.5 16 17 9' fill='none' stroke='%23202020' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}
[data-theme="dark"] {
  --clock-icon-grey:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%231a1d24' stroke='%23e6e8eb' stroke-width='2'/><polyline points='12 6 12 12 17 14' fill='none' stroke='%23e6e8eb' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --clock-icon-active:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23ffb94e' stroke='%231a1d24' stroke-width='2'/><polyline points='12 6 12 12 17 14' fill='none' stroke='%231a1d24' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --cart-check-icon:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%231a1d24' stroke='%23e6e8eb' stroke-width='2'/><polyline points='7 12.5 10.5 16 17 9' fill='none' stroke='%23e6e8eb' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}

/* Popover that opens under the clicked busy badge. Absolute-positioned by
   JS (top/left set inline based on bounding rect). Stays attached to the
   document so it doesn't get clipped by the grid scroll container. */
.autobook-popover {
  position: absolute;
  z-index: 100;
  background: var(--card);
  border: 1px solid var(--border);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
  border-radius: 8px;
  padding: 10px 12px;
  min-width: 220px;
  font-size: 13px;
  color: var(--text);
}
.autobook-popover .ab-title { font-weight: 600; margin-bottom: 4px; }
.autobook-popover .ab-meta {
  color: var(--muted);
  font-size: 12px;
  margin-bottom: 8px;
}
.autobook-popover .ab-error {
  color: var(--err);
  font-size: 12px;
  margin-top: 6px;
  word-wrap: break-word;
}
.autobook-popover .ab-actions {
  display: flex;
  gap: 6px;
  justify-content: flex-end;
}
.autobook-popover button,
#book-cart-bar button {
  padding: 5px 10px;
  font-size: 13px;
  border-radius: 5px;
  cursor: pointer;
  border: 1px solid var(--border);
  background: var(--card2);
  color: var(--text);
}
.autobook-popover button.ab-primary,
#book-cart-bar button.ab-primary {
  background: #f59e0b;
  border-color: #f59e0b;
  color: #1a1d24;
}
.autobook-popover button.ab-danger {
  background: var(--err);
  border-color: var(--err);
  color: #fff;
}
.autobook-popover button:disabled,
#book-cart-bar button:disabled { opacity: 0.6; cursor: progress; }

/* ---- Booking cart ------------------------------------------------------
   Мульти-выбор свободных слотов на основном календаре: клик кладёт слот в
   корзину, ячейка получает пунктирную рамку в цвет линии, плашка - галку.
   Бар #book-cart-bar создаётся/удаляется JS'ом (renderBookCartBar). */
.grid-cell.has-cart {
  position: relative;
  border: 2px dashed var(--cart-color, #f59e0b);
  background: color-mix(in srgb, var(--cart-color, #f59e0b) 12%, transparent);
}
.grid-svc.in-cart {
  position: relative;
  opacity: 1 !important;
}
.grid-svc.in-cart::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--cart-check-icon);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 10px 10px;
}
#book-cart-bar {
  position: fixed;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  z-index: 900;  /* под toast-стеком (1000), поверх сетки и попапов */
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: min(94vw, 680px);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
  padding: 10px 14px;
  font-size: 14px;
  color: var(--text);
}
#book-cart-bar .cart-head { white-space: nowrap; }
#book-cart-bar .cart-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  max-height: 72px;
  overflow-y: auto;
}
#book-cart-bar .cart-chip {
  background: var(--card2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 12px;
  white-space: nowrap;
}
#book-cart-bar .cart-actions {
  display: flex;
  gap: 6px;
  margin-left: auto;
}
@media (max-width: 600px) {
  #book-cart-bar {
    left: 8px;
    right: 8px;
    transform: none;
    max-width: none;
    flex-wrap: wrap;
    gap: 8px;
  }
}

/* ---- Toast notifications ---------------------------------------------
   Lightweight stacking toaster anchored to the bottom center of the
   viewport. Driven by JS via `showToast()`; each .toast slides up, sits
   for ~3s, then fades out and is removed. Multiple toasts stack with a
   small gap. Click anywhere on a toast dismisses it immediately. */
.toast-stack {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
  pointer-events: none;  /* let the dismissable .toast claim its own events */
}
.toast {
  pointer-events: auto;
  background: var(--card);
  color: var(--text);
  border: 1px solid var(--border);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.22);
  border-radius: 10px;
  padding: 10px 16px;
  font-size: 14px;
  max-width: 90vw;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 180ms ease, transform 180ms ease;
}
.toast.show { opacity: 1; transform: translateY(0); }
.toast.toast-ok { border-color: color-mix(in srgb, var(--ok) 60%, var(--border)); }
.toast.toast-ok::before {
  content: "✓ ";
  color: var(--ok);
  font-weight: 700;
}
.toast.toast-err { border-color: color-mix(in srgb, var(--err) 60%, var(--border)); }
.toast.toast-err::before {
  content: "! ";
  color: var(--err);
  font-weight: 700;
}

/* /account "Активные брони" reuses the main calendar markup; no extra CSS
   needed beyond what .grid-day / .grid-cell / .grid-svc already provide. */

/* Generic collapsible card section: clickable header + body that hides
   when the wrapper has the .collapsed class. Used on /account so the
   "Активные брони" block doesn't claim viewport on page load. */
/* The collapsible header is a <button> so it's keyboard-focusable, but
   we strip the button look (background/border/padding) and restore the
   typography defaults that the original <h3> got for free from the UA
   stylesheet. Without these resets the title rendered in system UI font
   at normal weight instead of inheriting bold from the heading element. */
.collapsible-head {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  cursor: pointer;
  color: var(--text);
  font-family: inherit;
  font-size: inherit;
  font-weight: bold;
}
.collapsible-chevron {
  display: inline-block;
  width: 1em;
  transition: transform 120ms ease;
}
.collapsible:not(.collapsed) .collapsible-chevron { transform: rotate(90deg); }
.collapsible.collapsed .collapsible-body { display: none; }
.collapsible-count { font-size: 12px; font-weight: 400; }

/* Согласие на делегирование доступа к кабинету парка (см. /privacy §6). */
.account-consent {
  display: flex; gap: 8px; align-items: flex-start;
  margin: 10px 0 14px;
  font-size: 13px; line-height: 1.4;
  color: var(--muted, #666);
}
.account-consent input[type="checkbox"] {
  margin-top: 3px; flex-shrink: 0;
}
.account-consent a { color: var(--accent, #4ea1ff); }

/* Disclaimer-строка в попаперах брони ("Let's Wake действует
   по вашему поручению по правилам парка"). */
.ab-disclaimer {
  font-size: 11px; color: var(--muted, #888);
  line-height: 1.35;
  margin: 6px 0 2px;
}

/* ---------- Mini-app chrome (Max + Telegram) ----------------------------
   Both /max[ /account ] and /tg[ /account ] templates render under
   <body class="mini-app …">. Hides global header / footer, replaces
   them with a slim logo + greeting + nav strip rendered by the
   _mini_chrome.html partial. */

body.mini-app { padding: 8px 10px; }
body.mini-app .mini-brand {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 0 6px;
}
body.mini-app .mini-brand img { height: 22px; }
body.mini-app .mini-brand-link { display: inline-flex; align-items: center; color: inherit; text-decoration: none; }
body.mini-app .mini-hello { font-size: 14px; font-weight: 500; }
body.mini-app .mini-status {
  font-size: 12px; color: var(--muted, #888);
  margin-left: auto;
}
body.mini-app main { padding: 0; }
body.mini-app .calendar-card { padding: 8px 10px; }
/* «Моя бронь» в легенде показываем подсветкой, но CTA-ссылку на /account
   прячем — внутри мини-апа есть свой пункт меню. */
body.mini-app .legend-mine-link { display: none; }

/* Slim nav with two tabs: Главная (#mini-nav-main) и Мои споты
   (#mini-nav-account). Active state matches header tab style. */
body.mini-app .mini-nav {
  display: flex; gap: 16px;
  padding: 4px 0 10px;
  border-bottom: 1px solid var(--border, #e3e3e3);
  margin-bottom: 10px;
}
body.mini-app .mini-nav-link {
  text-decoration: none;
  color: var(--muted, #888);
  font-weight: 500; font-size: 14px;
  padding: 4px 2px;
  border-bottom: 2px solid transparent;
}
body.mini-app .mini-nav-link.active {
  color: var(--text, #222);
  border-bottom-color: var(--accent, #4ea1ff);
}

/* Redirect-to-site card on /max/account и /tg/account, когда парк не
   привязан. Привязка — единственная фича, которую мы вынесли только в
   браузерный /account (форма пароля, цена ошибок в webview велика). */
body.mini-app .account-redirect {
  padding: 12px 0;
  font-size: 14px; line-height: 1.45;
}
body.mini-app .account-redirect p {
  margin: 0 0 12px;
  color: var(--muted, #666);
}
body.mini-app .account-redirect-btn {
  display: inline-block;
  padding: 10px 16px;
  border-radius: 8px;
  background: var(--accent, #4ea1ff);
  color: #fff !important;
  text-decoration: none;
  font-weight: 500;
}
body.mini-app .account-redirect-btn:hover { opacity: 0.92; }


/* ---------- Голосование с призом (/golosovanie) ------------------------- */
.contest-form { display: flex; flex-direction: column; gap: 12px; }
.contest-row {
  /* .contest-row это <label> внутри <form>, а глобальное `form label`
     навязывает flex-direction:column + gap:4px — поэтому направление и
     выравнивание задаём явно, иначе имя и дропдаун встают друг под другом. */
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}
/* Фиксированная колонка имени: имена выстраиваются столбиком слева, а
   дропдауны — ровным столбцом сразу справа от них. */
.contest-name {
  flex: 0 0 200px;
  min-width: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--text);
}
.contest-select {
  background: var(--card2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  font-size: 15px;
  font-family: inherit;
  font-weight: 600;
  /* глобальное `form select` ставит width:100% — сужаем до содержимого,
     чтобы дропдаун был компактным, а не во всю строку. */
  width: auto;
  max-width: none;
  min-width: 72px;
}
.contest-select:focus { outline: 2px solid var(--accent-dim); }
.contest-note { margin-top: 10px; font-size: 13px; }
#contest-login-gate {
  margin: 4px 0 2px;
  padding: 12px;
  border: 1px dashed var(--border);
  border-radius: 8px;
  background: var(--card2);
}
.contest-login-hint { margin: 0 0 8px; }
#contest-submit:disabled { opacity: 0.5; cursor: not-allowed; }
.contest-picks { display: flex; flex-direction: column; gap: 8px; }
.contest-picks-row { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 4px; }
.contest-pick { font-size: 14px; }
.contest-pick strong { color: var(--accent); }

@media (max-width: 600px) {
  .contest-name { flex-basis: 150px; font-size: 15px; }
}
