/*
 * RU: Вкладка «Услуги и запись» кабинета организации (ДО7, 26.09.2026, public/js/biz-services.js). Здесь только то, чего
 *     нет в общем словаре `.bc-*` (biz-commerce.css): сетка календаря дня по мастерам, неделя карточками, карточки
 *     записей по статусам, аватары мастеров, таблица графика, сетка фото портфолио и пары «до/после». Карточки, поля,
 *     кнопки, плашки и таблицы — из `.bc-*`, чтобы вкладка выглядела частью кабинета.
 *
 *     Только токены `--k-*` из kartivi.css: литерал цвета не перекрасился бы ни палитрой, ни ночным тоном (храповик
 *     `node scripts/check-theme.mjs`). Цели нажатия не ниже `--k-tap-min`. Сетка календаря шире 375 px и листается внутри
 *     своей обёртки (вбок и вниз), шапка с именами и колонка часов при этом прилипают; страница вбок не едет.
 *
 *     Положение карточки записи задаёт разметка переменными: --bs-from/--bs-to (часы сетки, минуты), --bs-px (пикселей на
 *     минуту, одно число с CAL_PX_PER_MIN в JS), --bs-start/--bs-len (начало и длина события), --bs-lane/--bs-lanes
 *     (дорожка при пересечении). Так вся арифметика раскладки живёт в проверяемом JS, а CSS только переводит её в пиксели.
 *
 * EN: The "Services and booking" tab of the organisation cabinet (DO7, 2026-09-26, public/js/biz-services.js). Only what the
 *     shared `.bc-*` vocabulary (biz-commerce.css) lacks lives here: the per-staff day calendar grid, the week as cards,
 *     booking cards by status, staff avatars, the schedule table, the portfolio photo grid and before/after pairs. Cards,
 *     fields, buttons, chips and tables come from `.bc-*` so the tab looks like part of the cabinet.
 *
 *     Only `--k-*` tokens from kartivi.css: a colour literal would be repainted by neither palette nor night tone (the
 *     `node scripts/check-theme.mjs` ratchet). Tap targets are at least `--k-tap-min`. The calendar grid is wider than
 *     375 px and scrolls inside its own wrapper (sideways and down) while the name header and hours column stick; the page
 *     never shifts sideways.
 *
 *     The markup positions a booking card through variables: --bs-from/--bs-to (grid hours, minutes), --bs-px (pixels per
 *     minute, the same number as CAL_PX_PER_MIN in JS), --bs-start/--bs-len (event start and length), --bs-lane/--bs-lanes
 *     (the lane on overlap). All layout arithmetic thus lives in testable JS, and CSS only turns it into pixels.
 */

.bs {
  min-width: 0;
}

/* RU: Атрибут hidden проигрывает любому display у класса (.bc-grid — grid, .bc-form — flex): без этого правила скрытые
       части форм оставались бы видны.
   EN: The hidden attribute loses to any class display (.bc-grid is grid, .bc-form is flex): without this rule hidden form
       parts would stay visible. */
.bs [hidden] {
  display: none !important;
}

.bs-sec {
  min-width: 0;
}

.bs-lead {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--k-s-2);
  margin: 0 0 var(--k-s-3);
}

.bs-lead p {
  margin: 0;
}

.bs-center {
  justify-content: center;
}

.bc-empty p {
  margin: 0 0 var(--k-s-2);
}

/* RU: Форма, раскрытая внутри карточки или списка: своя рамка отделяет её от соседних записей.
   EN: A form unfolded inside a card or list: its own frame separates it from neighbouring entries. */
.bs-subform {
  margin: var(--k-s-3) 0;
  padding: var(--k-s-3);
  border: 1px solid var(--k-border);
  border-radius: var(--k-r-2);
  background: var(--k-surface);
  min-width: 0;
}

.bs-subform h5 {
  margin: 0 0 var(--k-s-2);
  font-size: var(--k-fs-3);
  line-height: var(--k-lh-base);
  font-weight: 700;
}

/* ——— Прайс / Price list ——— */

.bs-group-title {
  margin: var(--k-s-4) 0 var(--k-s-2);
  font-size: var(--k-fs-3);
  line-height: var(--k-lh-base);
  font-weight: 700;
}

/* RU: Колонка «Услуга» не сжимается в столбик по слову: таблица и так листается вбок в своей обёртке.
   EN: The "Услуга" column does not squeeze into a word-per-line column: the table scrolls sideways in its wrapper anyway. */
.bs-price-table td:first-child {
  min-width: 12rem;
}

.bs-cell-item {
  display: flex;
  align-items: flex-start;
  gap: var(--k-s-2);
}

.bs-nowrap {
  flex-wrap: nowrap;
}

/* ——— Мастера / Staff ——— */

.bs-person {
  display: flex;
  align-items: center;
  gap: var(--k-s-3);
  min-width: 0;
}

.bs-avatar {
  flex: 0 0 auto;
  display: inline-grid;
  place-items: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--k-brand-soft);
  color: var(--k-brand-ink);
  font-weight: 700;
  object-fit: cover;
}

.bs-sched th[scope="row"] {
  white-space: nowrap;
}

.bs-sched td {
  vertical-align: middle;
}

.bs-sched .bc-check {
  justify-content: center;
}

.bs-sched .bc-inline-input:disabled {
  opacity: 0.5;
}

.bs-dayoff {
  padding: var(--k-s-1) 0;
  border-bottom: 1px solid var(--k-border-soft);
}

/* ——— Календарь: панель / Calendar: toolbar ——— */

.bs-cal-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--k-s-2) var(--k-s-3);
  margin: var(--k-s-2) 0 var(--k-s-3);
}

.bs-cal-bar .bc-seg {
  margin: 0;
}

.bs-cal-filter {
  flex: 1 1 12rem;
  max-width: 20rem;
}

/* ——— Календарь: день по мастерам / Calendar: day by master ——— */

/* RU: Обёртка ограничена по высоте, чтобы прокрутка шла внутри неё: тогда шапка с именами прилипает к её верху, а не
       уезжает вместе со страницей.
   EN: The wrapper is height-limited so scrolling happens inside it: then the name header sticks to its top rather than
       leaving with the page. */
.bs-cal-wrap {
  max-height: min(75vh, 46rem);
  overflow: auto;
}

.bs-cal {
  --bs-hours-w: 3.5rem;
  --bs-col-min: 9rem;
  display: grid;
  grid-template-columns: var(--bs-hours-w) repeat(var(--bs-cols, 1), minmax(var(--bs-col-min), 1fr));
  min-width: calc(var(--bs-hours-w) + var(--bs-cols, 1) * var(--bs-col-min));
}

.bs-cal-corner,
.bs-cal-staff {
  position: sticky;
  top: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  min-height: var(--k-tap-min);
  padding: var(--k-s-1) var(--k-s-2);
  border-bottom: 1px solid var(--k-border);
  background: var(--k-surface);
  font-size: var(--k-fs-2);
  line-height: var(--k-lh-sm);
  font-weight: 600;
}

.bs-cal-corner {
  left: 0;
  z-index: 4;
}

.bs-cal-staff {
  border-left: 1px solid var(--k-border-soft);
  overflow-wrap: anywhere;
}

.bs-cal-staff.is-muted {
  color: var(--k-text-muted);
}

.bs-cal-hours {
  position: sticky;
  left: 0;
  z-index: 2;
  height: calc((var(--bs-to) - var(--bs-from)) * var(--bs-px));
  background: var(--k-surface);
}

.bs-cal-hours span {
  position: absolute;
  top: calc((var(--bs-at) - var(--bs-from)) * var(--bs-px));
  right: var(--k-s-1);
  padding-top: 2px;
  color: var(--k-text-muted);
  font-size: var(--k-fs-1);
  line-height: var(--k-lh-cap);
  font-variant-numeric: tabular-nums;
}

/* RU: Линии часов — фоном колонки, шаг — 60 минут в тех же пикселях, что и события: линия и карточка на 10:00 совпадают.
   EN: Hour lines are the column background, one step per 60 minutes in the same pixels as events: the line and a 10:00
       card coincide. */
.bs-cal-col {
  position: relative;
  height: calc((var(--bs-to) - var(--bs-from)) * var(--bs-px));
  border-left: 1px solid var(--k-border-soft);
  background-image: repeating-linear-gradient(to bottom, var(--k-border-soft) 0 1px, transparent 1px calc(60 * var(--bs-px)));
}

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

/* RU: Высота — не меньше цели нажатия: короткая запись наезжает на следующую, поэтому раскладка по дорожкам в JS
       учитывает видимую, а не настоящую длину.
   EN: The height is at least the tap target: a short booking overlaps the next one, so the JS lane layout uses the visible
       rather than the real length. */
.bs-ev-slot {
  position: absolute;
  top: calc((var(--bs-start) - var(--bs-from)) * var(--bs-px));
  left: calc(var(--bs-lane, 0) * 100% / var(--bs-lanes, 1));
  width: calc(100% / var(--bs-lanes, 1));
  height: max(calc(var(--bs-len) * var(--bs-px)), var(--k-tap-min));
  padding: 1px 2px;
  box-sizing: border-box;
}

.bs-ev-slot:hover,
.bs-ev-slot:focus-within {
  z-index: 2;
}

.bs-ev,
.bs-ev-row {
  margin: 0;
  border: 1px solid var(--k-border);
  border-left: 3px solid var(--k-border-strong);
  border-radius: var(--k-r-1);
  background: var(--k-surface-2);
  color: var(--k-text);
  font: inherit;
  font-weight: 400;
  text-align: left;
  cursor: pointer;
}

.bs-ev {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: 100%;
  height: 100%;
  min-height: var(--k-tap-min);
  padding: var(--k-s-1) var(--k-s-2);
  overflow: hidden;
  font-size: var(--k-fs-1);
  line-height: var(--k-lh-cap);
}

.bs-ev-time {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.bs-ev .bs-ev-title,
.bs-ev .bs-ev-client {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bs-ev .bs-ev-client,
.bs-ev-row .bs-ev-client {
  color: var(--k-text-muted);
}

.bs-ev.is-new,
.bs-ev-row.is-new {
  border-left-color: var(--k-brand);
  background: var(--k-brand-soft);
}

.bs-ev.is-confirmed,
.bs-ev-row.is-confirmed {
  border-left-color: var(--k-ok);
  background: var(--k-ok-soft);
}

.bs-ev.is-done,
.bs-ev-row.is-done {
  border-left-color: var(--k-border-strong);
  background: var(--k-surface-3);
  color: var(--k-text-muted);
}

.bs-ev.is-no_show,
.bs-ev-row.is-no_show {
  border-left-color: var(--k-warn);
  background: var(--k-warn-soft);
}

.bs-ev.is-cancelled,
.bs-ev-row.is-cancelled {
  border-style: dashed;
  border-left-color: var(--k-danger);
  background: var(--k-surface);
  color: var(--k-text-muted);
  text-decoration: line-through;
}

/* RU: Закрытое время — штриховкой из двух оттенков поверхности: отличимо от записи и без цвета (для дальтоников).
   EN: Blocked time — hatching from two surface shades: distinguishable from a booking even without colour (for colour-blind
       users). */
.bs-ev.is-block,
.bs-ev-row.is-block {
  border-left-color: var(--k-text-subtle);
  background: repeating-linear-gradient(135deg, var(--k-surface-3) 0 6px, var(--k-surface-2) 6px 12px);
  color: var(--k-text-muted);
}

.bs-ev[aria-expanded="true"],
.bs-ev-row[aria-expanded="true"],
.bs-ev:focus-visible,
.bs-ev-row:focus-visible,
.bs-detail:focus-visible {
  outline: none;
  box-shadow: var(--k-focus);
}

.bs-cal-now {
  position: absolute;
  left: 0;
  right: 0;
  top: calc((var(--bs-at) - var(--bs-from)) * var(--bs-px));
  z-index: 1;
  border-top: 2px solid var(--k-danger);
  pointer-events: none;
}

/* ——— Календарь: неделя / Calendar: week ——— */

/* RU: auto-fit переносит дни: на широком экране неделя — в ряд, на телефоне — столбиком без прокрутки вбок.
   EN: auto-fit wraps the days: on a wide screen the week is a row, on a phone a column with no sideways scrolling. */
.bs-week {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 11rem), 1fr));
  gap: var(--k-s-2);
}

.bs-week-day {
  min-width: 0;
  padding: var(--k-s-2);
  border: 1px solid var(--k-border);
  border-radius: var(--k-r-2);
  background: var(--k-surface);
}

.bs-week-day.is-today {
  border-color: var(--k-brand);
}

.bs-week-title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--k-s-1);
  margin: 0 0 var(--k-s-2);
  font-size: var(--k-fs-3);
  line-height: var(--k-lh-base);
  font-weight: 700;
}

.bs-week-list {
  display: flex;
  flex-direction: column;
  gap: var(--k-s-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.bs-ev-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: var(--k-s-2);
  width: 100%;
  min-height: var(--k-tap-min);
  padding: var(--k-s-1) var(--k-s-2);
  font-size: var(--k-fs-2);
  line-height: var(--k-lh-sm);
}

.bs-ev-row .bs-ev-title {
  overflow-wrap: anywhere;
}

.bs-ev-row .bs-ev-client {
  grid-column: 2;
}

.bs-detail {
  margin-top: var(--k-s-3);
}

/* ——— Портфолио / Portfolio ——— */

.bs-photos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 9rem), 1fr));
  gap: var(--k-s-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.bs-photo {
  display: flex;
  flex-direction: column;
  gap: var(--k-s-1);
  min-width: 0;
}

/* RU: Пара «до/после» — во всю строку: две половины рядом читаются как сравнение, а разнесённые по сетке — как два фото.
   EN: A before/after pair takes a full row: two halves side by side read as a comparison, scattered across the grid — as
       two photos. */
.bs-photo.is-pair {
  grid-column: 1 / -1;
}

.bs-photo .bc-btn {
  align-self: flex-start;
}

.bs-pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--k-s-2);
  max-width: 24rem;
}

.bs-fig {
  display: flex;
  flex-direction: column;
  gap: var(--k-s-1);
  min-width: 0;
  margin: 0;
}

.bs-fig img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--k-r-2);
  background: var(--k-surface-3);
}

.bs-fig figcaption {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--k-s-1);
  font-size: var(--k-fs-1);
  line-height: var(--k-lh-cap);
}

.bs-fig-empty {
  display: grid;
  place-items: center;
  aspect-ratio: 1;
  padding: var(--k-s-2);
  border: 1px dashed var(--k-border);
  border-radius: var(--k-r-2);
  color: var(--k-text-muted);
  font-size: var(--k-fs-1);
  line-height: var(--k-lh-cap);
  text-align: center;
}

.bs-pair-label {
  font-weight: 700;
}

@media (max-width: 560px) {
  .bs-cal {
    --bs-hours-w: 3rem;
    --bs-col-min: 8rem;
  }

  .bs-cal-filter {
    max-width: none;
  }
}
