/* Shared Stoneware page anatomy, panels, lists and reusable page states. */
.fs-general-report__filters {
  background: var(--fs-color-panel-filter);
}

.fs-page {
  display: grid;
  align-content: start;
  gap: var(--fs-page-gap);
  width: 100%;
  min-width: 0;
}

/* Work-page headings stay quiet: identity already lives in the application shell. */
/*
 * A record's internal number: a quiet chip before its name — tabular figures, the muted tone, no frame of a
 * badge. It is read and said aloud («тендер 418»), never clicked; the name beside it is the link.
 */
.fs-record-number {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  min-height: 20px;
  padding: 0 6px;
  color: var(--fs-color-text-secondary);
  background: var(--fs-color-surface-subtle);
  border-radius: var(--fs-radius-pill);
  font-size: var(--fs-text-xs);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

/* The number and the name share one line; a long name wraps under itself, not under the number. */
.fs-record-title-line {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}

.fs-record-title-line > :last-child {
  min-width: 0;
}

.fs-page-heading-card {
  position: sticky;
  z-index: 20;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 54px;
  padding: 10px 16px;
  background-color: var(--fs-color-surface);
  border: 1px solid var(--fs-color-border-subtle);
  border-radius: var(--fs-radius-lg);
  box-shadow: var(--fs-shadow-sm);
}

/* Client-owned feature pages use this lighter header wrapper around the same
   canonical heading fragment. It participates in the same pinned page layer. */
.fs-page-header {
  position: sticky;
  z-index: 20;
  top: 0;
  background: var(--fs-color-content-canvas);
}

/*
 * One family for the whole interface. The serif was tried here and read as a
 * different product bolted on: the title sat in another voice from every number
 * under it. Rank comes from size and tracking instead — 26px against 14px body,
 * tightened, which outranks the section eyebrows without changing typeface.
 */
.fs-page-heading {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  color: var(--fs-color-text);
  font-size: 26px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.025em;
}

/*
 * The feature pictogram is the page's one identifying mark, so it is read at a
 * glance rather than squinted at. It grows only into room the header already
 * has: the title's own line box is 31px on desktop and 28px on mobile, so a
 * 26px glyph never becomes the tallest thing in the row and the header keeps
 * its 54px. Anything above that would start pushing the bar taller.
 */
.fs-page-heading img {
  width: 26px;
  height: 26px;
  flex: 0 0 26px;
  object-fit: contain;
}

/*
 * Шапка віддає висоту, щойно її притиснуло до верху.
 *
 * У спокої вона тримає документовані 54px: це висота, на якій назва сторінки та
 * її піктограма читаються саме як заголовок. Але шапка є sticky і лишається на
 * екрані весь візит, а назву читають один раз — далі та сама смуга просто стоїть
 * над даними, заради яких сторінку відкрили. Прилипнувши, вона стискається до
 * 44px і бере тінь: заголовок лишається на місці й лишається читабельним, але
 * перестає коштувати екрана. Клас ставить `page-header.js`; сама геометрія — тут.
 */
.fs-page-heading-card.is-stuck {
  min-height: 44px;
  padding-block: 4px;
  box-shadow: var(--fs-shadow-md, var(--fs-shadow-sm));
}

.fs-page-heading-card.is-stuck .fs-page-heading {
  font-size: 20px;
}

.fs-page-heading-card.is-stuck .fs-page-heading img {
  width: 20px;
  height: 20px;
  flex-basis: 20px;
}

/*
 * Рух тут пояснює, що сталося з блоком, а не прикрашає його, тому він короткий
 * і його немає для тих, хто просив системно менше руху.
 */
@media (prefers-reduced-motion: no-preference) {
  .fs-page-heading-card {
    transition:
      min-height 0.16s ease,
      padding 0.16s ease,
      box-shadow 0.16s ease;
  }

  .fs-page-heading {
    transition: font-size 0.16s ease;
  }

  /* Лише піктограма змінює власні розміри, тому лише вона їх анімує. */
  .fs-page-heading img {
    transition:
      width 0.16s ease,
      height 0.16s ease,
      flex-basis 0.16s ease;
  }
}

.fs-page-heading-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: var(--fs-space-2);
}


/*
 * Довідка сторінки. Обгортка існує лише заради `data-dialog-open`: спільна
 * кнопка має сталий набір параметрів, і додавати їй п'ятнадцятий заради одного
 * атрибута означало б переписати кожне з її звернень. `contents` лишає в смузі
 * дій саму кнопку, тому вона стоїть у тому самому ритмі, що й сусідні.
 */
.fs-page-help {
  display: contents;
}

/*
 * Глиф довідки більший за звичайні 16px: у цій кнопці він єдиний носій
 * значення, і зменшений до розміру глифа поруч із підписом він переставав
 * читатися здалеку. Форму кнопки задає набір дій шапки, а не вона сама.
 */
.fs-page-help__trigger .action-button__icon {
  width: 21px;
  height: 21px;
}

/*
 * Panel label. Per the brand book: a bordered strip at the top of a card that
 * names the block and optionally carries its metadata on the right. Panels are
 * all one white surface, so this strip — not a fill — is what tells query from
 * summary from search.
 */
.fs-section-label {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fs-space-3);
  min-height: 40px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--fs-color-border-subtle);
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.fs-section-label__title {
  display: flex;
  align-items: center;
  gap: var(--fs-space-2);
}

/*
 * The same label inside an opened record or a nested section. It names a part of
 * one record, not a panel of the page, so it keeps the strip's typography and
 * drops the strip's geometry: the surface around it already sets the left edge,
 * and 40px of bordered strip per section made three short sections taller than
 * the data underneath them.
 */
.fs-section-label--inline {
  min-height: 0;
  padding: 0;
  border-bottom: 0;
}

/* Metadata beside the name is not a heading: it keeps sentence case. */
.fs-section-label__meta {
  display: flex;
  align-items: center;
  gap: var(--fs-space-2);
  color: var(--fs-color-text-muted);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}

/* A card that opens with a label owns no padding; each part sets its own. */
.fs-panel {
  display: block;
  padding: 0;
  overflow: hidden;
}

.fs-panel__body {
  padding: var(--fs-space-4);
}

/*
 * A regular form panel clips its content so the card corners stay clean. Opt in
 * when a control popup must cross the panel boundary.
 */
.fs-panel--overlay-visible {
  position: relative;
  z-index: 1;
  overflow: visible;
}

.fs-panel--overlay-visible > .fs-section-label {
  border-radius: var(--fs-radius-lg) var(--fs-radius-lg) 0 0;
}

/*
 * Canonical feature-page blocks. Templates compose these through page-blocks.html;
 * feature CSS may change only the inner layout, never the panel surface or rhythm.
 */
.fs-page-block {
  min-width: 0;
}

.fs-page-block--query,
.fs-page-block--filters,
.fs-page-block--content {
  background: var(--fs-color-surface);
}

/*
 * A workflow with several page-level commands moves them out of the heading and
 * into one quiet panel. Groups keep navigation/utility actions apart from
 * business commands on desktop without inventing a feature-owned toolbar.
 */
.fs-page-actions {
  overflow: hidden;
  padding: 0;
  background: var(--fs-color-surface);
}

.fs-page-actions__body {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--fs-space-3);
  padding: var(--fs-space-3) var(--fs-space-4);
}

.fs-page-actions--compact .fs-page-actions__body {
  gap: var(--fs-space-1);
  padding: var(--fs-space-1);
}

.fs-page-actions--inline .fs-page-actions__body {
  display: flex;
  flex-wrap: wrap;
}

.fs-page-actions--inline .fs-page-actions__group {
  display: flex;
  width: auto;
}

.fs-page-actions--inline .fs-page-actions__group--primary {
  margin-left: auto;
}

.fs-page-actions--inline .fs-page-actions__group > .action-button,
.fs-page-actions--inline .fs-page-actions__group > form,
.fs-page-actions--inline .fs-page-actions__group > form > .action-button {
  width: auto;
}

.fs-page-actions__content {
  display: contents;
}

.fs-page-actions__group {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--fs-space-2);
  min-width: 0;
}

.fs-page-actions__group--primary {
  justify-content: flex-end;
  margin-left: auto;
}

.fs-page-actions__note {
  margin: 0;
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-sm);
}

/*
 * Query and filters host controls that open over the page — user pickers, selects,
 * date popovers. `.fs-panel` clips to its own box, which cut every one of those off
 * at the bottom edge of the panel, so these two blocks stay unclipped and instead
 * outrank the blocks below them. Query sits above filters because its dropdown
 * opens downward across it; both sit above content, which is not positioned.
 */
.fs-page-block--query,
.fs-page-block--filters {
  position: relative;
  overflow: visible;
}

.fs-page-block--query {
  z-index: 6;
}

.fs-page-block--filters {
  z-index: 5;
}

/*
 * Without the panel clip the label owns the top corners of the card itself,
 * otherwise its hover fill squares them off.
 */
.fs-page-block--query > .fs-page-block__disclosure > .fs-section-label,
.fs-page-block--filters > .fs-page-block__disclosure > .fs-section-label {
  border-radius: var(--fs-radius-lg) var(--fs-radius-lg) 0 0;
}

.fs-page-block--summary {
  display: block;
}

.fs-page-block__disclosure {
  display: block;
}

.fs-page-block__disclosure > .fs-section-label {
  padding-right: 44px;
  cursor: pointer;
  list-style: none;
}

.fs-page-block__disclosure > .fs-section-label::-webkit-details-marker {
  display: none;
}

.fs-page-block__chevron {
  position: absolute;
  top: 50%;
  right: 18px;
  width: 8px;
  height: 8px;
  margin-top: -6px;
  border-right: 1.5px solid var(--fs-color-text-muted);
  border-bottom: 1.5px solid var(--fs-color-text-muted);
  transform: rotate(45deg);
  transition: transform 0.16s ease;
}

/*
 * Скільки умов зараз діє. Стоїть у рядку згорнутої панелі, бо саме там його
 * видно, коли панель закрита; праве поле лишає місце шеврону, який висить
 * абсолютно. Це не другий бейдж стану — тон нейтральний, а саме число є
 * посиланням на те, що всередині.
 */
.fs-page-block__filters-count {
  margin-right: 18px;
  margin-left: auto;
  color: var(--fs-color-text-muted);
  font-size: var(--fs-text-xs);
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  white-space: nowrap;
}

.fs-page-block__filters-count[hidden] {
  display: none;
}

.fs-page-block__disclosure[open] .fs-page-block__chevron {
  margin-top: -2px;
  transform: rotate(225deg);
}

.fs-page-block__disclosure:not([open]) > .fs-section-label {
  border-bottom: 0;
}

@media (hover: hover) {
  .fs-page-block__disclosure > .fs-section-label:hover {
    background: var(--fs-color-surface-hover);
  }
}

/*
 * Any panel can collapse: write it as <details class="fs-panel fs-panel--collapsible">
 * with the label as its <summary>. This is panel behaviour, not one page's feature —
 * query, summary and search all fold the same way, and the chevron is the only
 * affordance added, so a collapsed panel still reads as the same block.
 */
.fs-panel--collapsible > .fs-section-label {
  padding-right: 44px;
  cursor: pointer;
  list-style: none;
}

.fs-panel--collapsible > .fs-section-label::-webkit-details-marker {
  display: none;
}

@media (hover: hover) {
  .fs-panel--collapsible > .fs-section-label:hover {
    background: var(--fs-color-surface-hover);
  }
}

.fs-panel--collapsible > .fs-section-label::after {
  position: absolute;
  top: 50%;
  right: 18px;
  width: 8px;
  height: 8px;
  margin-top: -6px;
  border-right: 1.5px solid var(--fs-color-text-muted);
  border-bottom: 1.5px solid var(--fs-color-text-muted);
  content: "";
  transform: rotate(45deg);
  transition: transform 0.16s ease;
}

.fs-panel--collapsible[open] > .fs-section-label::after {
  margin-top: -2px;
  transform: rotate(225deg);
}

/* A closed panel is a single strip: the label keeps no divider under it. */
.fs-panel--collapsible:not([open]) > .fs-section-label {
  border-bottom: 0;
}

/*
 * Record list. One panel, a header row, then rows flush against each other — the
 * shape every "list of things" page needs. Only the column track differs per
 * page, so a feature sets `grid-template-columns` on the head and row and takes
 * everything else from here.
 *
 * Rows do not float apart with gaps and shadows: separated rows read as separate
 * cards and stop the eye from running down a column, which is the one thing a
 * table is for.
 */
.fs-datalist {
  display: block;
  padding: 0;
  overflow: hidden;
}

.fs-datalist__head,
.fs-datalist__row {
  display: grid;
  gap: 0;
  align-items: center;
}

.fs-datalist__head {
  min-height: 34px;
  padding: 8px 16px;
  color: var(--fs-color-text-secondary);
  background: var(--fs-color-table-header);
  border-bottom: 1px solid var(--fs-color-border);
  font-size: var(--fs-text-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.fs-datalist__row {
  min-height: 58px;
  padding: 9px 16px;
  background: var(--fs-color-panel-content);
  border-bottom: 1px solid var(--fs-color-border-subtle);
  transition: background-color 0.14s ease;
}

.fs-datalist__row:last-child {
  border-bottom: 0;
}

@media (hover: hover) {
  .fs-datalist__row:hover {
    background: var(--fs-color-surface-hover);
  }
}

/*
 * A divider between runs of records — the day a batch of notes was written, the
 * partner a run of documents belongs to.
 *
 * Between two lines of values a hairline is a sufficient break. Between two
 * paragraphs it is not: a list of prose records reads as one heap, and finding
 * where one day ends means reading the timestamp of every record. The strip
 * names the run once and states its size, so the eye gets a landmark instead of
 * a wall.
 *
 * It is a landmark, not a column header: warm neutral surface and sentence case.
 * `fs-datalist__head` is uppercase because it labels columns, and a date set in
 * uppercase would claim to be labelling something. The strip carries only its
 * bottom hairline — the row above it brings its own, and two lines in contact
 * read as a border twice as thick as every other break in the list.
 */
.fs-datalist__divider {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--fs-space-3);
  padding: 9px 16px;
  background: var(--fs-color-surface-subtle);
  border-bottom: 1px solid var(--fs-color-border);
}

.fs-datalist__divider-label {
  min-width: 0;
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-sm);
  font-weight: 600;
}

.fs-datalist__divider-meta {
  flex: 0 0 auto;
  color: var(--fs-color-text-muted);
  font-size: var(--fs-text-xs);
  font-variant-numeric: tabular-nums;
}

/*
 * A header cell that carries an icon. The glyph is grey and sits before the
 * name, so a wide result can be scanned by column shape instead of by reading
 * six uppercase words. Numeric columns align their whole cell to the right —
 * `text-align` cannot do that once the cell is a flex row.
 */
.fs-datalist__col {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}

.fs-datalist__col--numeric {
  justify-content: flex-end;
}

.fs-datalist__col-icon {
  display: block;
  width: 14px;
  height: 14px;
  flex: 0 0 14px;
  background: currentcolor;
  mask-image: var(--fs-col-icon, none);
  mask-position: center;
  mask-repeat: no-repeat;
  mask-size: 14px 14px;
  -webkit-mask-image: var(--fs-col-icon, none);
  -webkit-mask-position: center;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-size: 14px 14px;
}

/*
 * Money in a result row is data, not decoration. It keeps tabular figures so a
 * column of amounts lines up digit under digit, and it takes a semantic tone
 * only where the number states a confirmed business fact: a realised sale is
 * money earned, an overdue debt is money late. A plain count never takes one —
 * colouring every number turns the palette into striping.
 */
.fs-datalist__amount {
  color: var(--fs-amount-tone, var(--fs-color-text));
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.fs-datalist__amount--success {
  --fs-amount-tone: var(--fs-color-success-text);
}

/*
 * Гроші — завжди `--fs-color-money` (brand book «Гроші»). Модифікатор називає вид числа, а не стан: `--success`
 * лишається за успіхом (відсоток виконання), `--muted` — за планом чи нормою поруч із фактом.
 */
.fs-datalist__amount--money {
  --fs-amount-tone: var(--fs-color-money);
}

/* Сума поза списком — у KPI, картці, рядку деталей. */
.fs-money {
  color: var(--fs-color-money);
  font-variant-numeric: tabular-nums;
}

.fs-datalist__amount--warning {
  --fs-amount-tone: var(--fs-color-warning-text);
}

.fs-datalist__amount--danger {
  --fs-amount-tone: var(--fs-color-danger-text);
}

.fs-datalist__amount--muted {
  --fs-amount-tone: var(--fs-color-text-secondary);
}

/*
 * An expandable record: <details class="fs-datalist__group"> with the row as
 * its <summary> and the detail below it. Every list that opens a row needs the
 * same four things — a pointer, a chevron, an opened tint and a recessed body —
 * and each feature used to redraw all four, which is why one list opened blue
 * and the next one warm grey. Opened is the product's one selection state.
 */
.fs-datalist__group > summary {
  cursor: pointer;
  list-style: none;
}

.fs-datalist__group > summary::-webkit-details-marker {
  display: none;
}

.fs-datalist__group[open] > summary {
  color: var(--fs-color-selected-text);
  background: var(--fs-color-selected);
}

/* Points right when closed and down when open, like every other disclosure. */
.fs-datalist__chevron {
  width: 8px;
  height: 8px;
  justify-self: end;
  border-right: 1.5px solid currentcolor;
  border-bottom: 1.5px solid currentcolor;
  transform: rotate(45deg);
  transition: transform 0.16s ease;
}

/*
 * The glyph turns in the summary of its own open disclosure. The direct-summary
 * boundary matters: an open parent must not also turn the glyphs of closed
 * disclosures nested in its body.
 */
details[open] > summary .fs-datalist__chevron {
  transform: rotate(225deg);
}

/*
 * The opened body. It is recessed, not another card: a child list floating on
 * white reads as a second record rather than as the inside of this one.
 */
.fs-datalist__nested {
  padding: var(--fs-space-3) var(--fs-space-4);
  background: var(--fs-color-selected-subtle);
  border-bottom: 1px solid var(--fs-color-border-subtle);
}

/*
 * Record state as a surface. A list of statuses is read by scanning, and a word
 * in a badge is found only after the eye has already stopped on the row. The
 * tone is therefore said twice on purpose — once in the badge, once as a rail
 * and a wash — but it stays a wash: the tint is mixed far enough into the
 * surface that the figures on top keep their contrast, and the saturated part
 * is three pixels wide at the edge.
 *
 * The rail is an inset shadow, not a border, so a toned row keeps exactly the
 * geometry of an untoned one and columns never shift by three pixels between
 * two records. Opening the record deepens its own tone instead of replacing it
 * with the neutral selection colour: an opened record is still that record.
 */
.fs-datalist__group[data-tone] {
  --fs-row-tone-line: var(--fs-color-border);
  --fs-row-tone-surface: var(--fs-color-surface-subtle);
  --fs-row-tone-open: var(--fs-color-surface-hover);
  --fs-row-tone-nested: var(--fs-color-surface-subtle);
}

.fs-datalist__group[data-tone="primary"] {
  --fs-row-tone-line: var(--fs-color-primary);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-primary-subtle) 55%, var(--fs-color-surface));
  --fs-row-tone-open: color-mix(in srgb, var(--fs-color-primary-subtle) 88%, var(--fs-color-surface));
  --fs-row-tone-nested: color-mix(in srgb, var(--fs-color-primary-subtle) 42%, var(--fs-color-surface));
}

.fs-datalist__group[data-tone="success"] {
  --fs-row-tone-line: var(--fs-color-success);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-success-subtle) 55%, var(--fs-color-surface));
  --fs-row-tone-open: color-mix(in srgb, var(--fs-color-success-subtle) 88%, var(--fs-color-surface));
  --fs-row-tone-nested: color-mix(in srgb, var(--fs-color-success-subtle) 42%, var(--fs-color-surface));
}

.fs-datalist__group[data-tone="warning"] {
  --fs-row-tone-line: var(--fs-color-warning);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-warning-subtle) 55%, var(--fs-color-surface));
  --fs-row-tone-open: color-mix(in srgb, var(--fs-color-warning-subtle) 88%, var(--fs-color-surface));
  --fs-row-tone-nested: color-mix(in srgb, var(--fs-color-warning-subtle) 42%, var(--fs-color-surface));
}

.fs-datalist__group[data-tone="danger"] {
  --fs-row-tone-line: var(--fs-color-danger);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-danger-subtle) 55%, var(--fs-color-surface));
  --fs-row-tone-open: color-mix(in srgb, var(--fs-color-danger-subtle) 88%, var(--fs-color-surface));
  --fs-row-tone-nested: color-mix(in srgb, var(--fs-color-danger-subtle) 42%, var(--fs-color-surface));
}

/*
 * Категорійні родини несуть смугу рядка нарівні з семантичними. Без них стан,
 * названий `sage` або `sand`, падав у типовий `[data-tone]` — сіру рейку й
 * майже білу заливку, тобто виглядав як рядок узагалі без стану. `sand` бере
 * більшу частку, ніж інші: `tan` сам собою блідіший за решту subtle-поверхонь,
 * і на спільних 55% його смуга не читалася б.
 */
.fs-datalist__group[data-tone="sage"] {
  --fs-row-tone-line: var(--fs-color-sage-text);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-sage-subtle) 55%, var(--fs-color-surface));
  --fs-row-tone-open: color-mix(in srgb, var(--fs-color-sage-subtle) 88%, var(--fs-color-surface));
  --fs-row-tone-nested: color-mix(in srgb, var(--fs-color-sage-subtle) 42%, var(--fs-color-surface));
}

.fs-datalist__group[data-tone="sand"] {
  --fs-row-tone-line: var(--fs-color-rust);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-tan) 70%, var(--fs-color-surface));
  --fs-row-tone-open: var(--fs-color-tan);
  --fs-row-tone-nested: color-mix(in srgb, var(--fs-color-tan) 52%, var(--fs-color-surface));
}

/* A record that does not expand carries the same tone tokens on the row itself. */
.fs-datalist__row[data-tone] {
  --fs-row-tone-line: var(--fs-color-border);
  --fs-row-tone-surface: var(--fs-color-surface-subtle);
}

.fs-datalist__row[data-tone="primary"] {
  --fs-row-tone-line: var(--fs-color-primary);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-primary-subtle) 55%, var(--fs-color-surface));
}

.fs-datalist__row[data-tone="success"] {
  --fs-row-tone-line: var(--fs-color-success);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-success-subtle) 55%, var(--fs-color-surface));
}

.fs-datalist__row[data-tone="warning"] {
  --fs-row-tone-line: var(--fs-color-warning);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-warning-subtle) 55%, var(--fs-color-surface));
}

.fs-datalist__row[data-tone="danger"] {
  --fs-row-tone-line: var(--fs-color-danger);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-danger-subtle) 55%, var(--fs-color-surface));
}

.fs-datalist__row[data-tone="sage"] {
  --fs-row-tone-line: var(--fs-color-sage-text);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-sage-subtle) 55%, var(--fs-color-surface));
}

.fs-datalist__row[data-tone="sand"] {
  --fs-row-tone-line: var(--fs-color-rust);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-tan) 70%, var(--fs-color-surface));
}

.fs-datalist__group[data-tone] > summary,
.fs-datalist__row[data-tone] {
  background: var(--fs-row-tone-surface);
  box-shadow: inset 3px 0 0 var(--fs-row-tone-line);
}

@media (hover: hover) {
  .fs-datalist__group[data-tone] > summary:hover {
    background: color-mix(in srgb, var(--fs-row-tone-open) 70%, var(--fs-color-surface-hover));
  }
}

.fs-datalist__group[data-tone][open] > summary {
  color: var(--fs-color-text);
  background: var(--fs-row-tone-open);
}

.fs-datalist__group[data-tone] > .fs-datalist__nested {
  background: var(--fs-row-tone-nested);
  box-shadow: inset 3px 0 0 var(--fs-row-tone-line);
}

/*
 * Row actions. One place decides where a record's actions sit, so the same
 * pencil is in the same corner on every list: last column on desktop, and on a
 * card the bottom-right, where the thumb already is. The column title names it
 * on desktop; inside the card the icon names itself and a repeated "Дії" label
 * above a single button is a word per record that reports nothing.
 */
.fs-datalist__row-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--fs-space-2);
  min-width: 0;
}

/*
 * Nested list. Compact by design — it repeats the parent's anatomy one level
 * down and must not compete with it for weight.
 */
.fs-nested-list {
  overflow: hidden;
  background: var(--fs-color-surface);
  border: 1px solid var(--fs-color-border-subtle);
  border-radius: var(--fs-radius-md);
}

.fs-nested-list__head,
.fs-nested-list__row {
  display: grid;
  gap: var(--fs-space-3);
  align-items: center;
  padding: var(--fs-space-2) var(--fs-space-3);
}

.fs-nested-list__head {
  color: var(--fs-color-text-secondary);
  background: var(--fs-color-table-header);
  font-size: var(--fs-text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.fs-nested-list__row + .fs-nested-list__row {
  border-top: 1px solid var(--fs-color-border-subtle);
}

/*
 * A nested row states its business state the same way a list row does: the rail
 * at the edge and a wash of the same family. Without it a finished child looked
 * exactly like an unfinished one until its badge was read, which is the problem
 * `data-tone` was introduced on the parent list to solve.
 */
.fs-nested-list__row[data-tone] {
  --fs-row-tone-line: var(--fs-color-border);
  --fs-row-tone-surface: var(--fs-color-surface-subtle);

  background: var(--fs-row-tone-surface);
  box-shadow: inset 3px 0 0 var(--fs-row-tone-line);
}

.fs-nested-list__row[data-tone="primary"] {
  --fs-row-tone-line: var(--fs-color-primary);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-primary-subtle) 45%, var(--fs-color-surface));
}

.fs-nested-list__row[data-tone="success"] {
  --fs-row-tone-line: var(--fs-color-success);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-success-subtle) 45%, var(--fs-color-surface));
}

.fs-nested-list__row[data-tone="warning"] {
  --fs-row-tone-line: var(--fs-color-warning);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-warning-subtle) 45%, var(--fs-color-surface));
}

.fs-nested-list__row[data-tone="danger"] {
  --fs-row-tone-line: var(--fs-color-danger);
  --fs-row-tone-surface: color-mix(in srgb, var(--fs-color-danger-subtle) 45%, var(--fs-color-surface));
}

/* Shared status marker. A feature chooses only the semantic tone; Stoneware owns the palette and shape. */
.fs-badge {
  display: inline-flex;
  align-items: center;
  width: max-content;
  max-width: 100%;
  min-height: 24px;
  padding: 3px 9px;
  color: var(--fs-badge-text, var(--fs-color-text-secondary));
  background: var(--fs-badge-surface, var(--fs-color-surface-subtle));
  border: 1px solid var(--fs-badge-line, var(--fs-color-border-subtle));
  border-radius: var(--fs-radius-pill);
  font-size: var(--fs-text-xs);
  font-weight: 600;
  line-height: 1.2;
}

.fs-badge--compact {
  min-height: 20px;
  padding: 2px 7px;
  font-size: 10px;
}

.fs-badge[data-tone="primary"] {
  --fs-badge-text: var(--fs-color-primary-text);
  --fs-badge-surface: var(--fs-color-primary-subtle);
  --fs-badge-line: var(--fs-color-primary-line);
}

.fs-badge[data-tone="success"] {
  --fs-badge-text: var(--fs-color-success-text);
  --fs-badge-surface: var(--fs-color-success-subtle);
  --fs-badge-line: var(--fs-color-success-line);
}

.fs-badge[data-tone="warning"] {
  --fs-badge-text: var(--fs-color-warning-text);
  --fs-badge-surface: var(--fs-color-warning-subtle);
  --fs-badge-line: var(--fs-color-warning-line);
}

.fs-badge[data-tone="danger"] {
  --fs-badge-text: var(--fs-color-danger-text);
  --fs-badge-surface: var(--fs-color-danger-subtle);
  --fs-badge-line: var(--fs-color-danger-line);
}

/*
 * Дві категорійні родини бренду. Вони існували для metric-карток підсумку, але
 * не для бейджа, тож стан, який словник фічі називає `sand` або `sage`, на
 * бейджі мовчки падав у нейтральний — і два різні стани ставали одним сірим.
 * Це не семантика «добре/погано», а позиція в шкалі: бліда родина означає стан
 * на шляху до свого насиченого відповідника.
 */
.fs-badge[data-tone="sand"] {
  --fs-badge-text: var(--fs-color-rust);
  --fs-badge-surface: var(--fs-color-tan);
  --fs-badge-line: var(--fs-color-tan-line);
}

.fs-badge[data-tone="sage"] {
  --fs-badge-text: var(--fs-color-sage-text);
  --fs-badge-surface: var(--fs-color-sage-subtle);
  --fs-badge-line: var(--fs-color-sage-line);
}

/*
 * Категорійний чип.
 *
 * `fs-badge` називає стан і має рівно п'ять тонів. Категорія — інша річ: це елемент клієнтського
 * довідника з власним порядком (у 1С у теми є номер), і вона нічого не стверджує про запис. Тому
 * чип бере не семантичну родину, а позицію шкали через `data-category`: одна й та сама тема
 * завжди має той самий колір, а сусідні теми відрізняються з першого погляду.
 *
 * Форма — обведений pill, а не заливка: кольорових категорій у списку буває багато, і стіна
 * суцільних плиток переважила б дані, заради яких список відкривають. Колір ніколи не є єдиним
 * носієм значення — назва категорії стоїть у самому чипі словом.
 */
.fs-category-chip {
  --fs-category: var(--fs-color-border);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  width: max-content;
  max-width: 100%;
  min-height: 22px;
  padding: 2px 10px;
  color: color-mix(in srgb, var(--fs-category) 72%, black);
  background: color-mix(in srgb, var(--fs-category) 14%, var(--fs-color-surface));
  border: 1px solid color-mix(in srgb, var(--fs-category) 52%, var(--fs-color-surface));
  border-radius: var(--fs-radius-pill);
  font-size: var(--fs-text-xs);
  font-weight: 600;
  line-height: 1.25;
}

/*
 * Крапка попереду — той самий колір у насиченому вигляді. Обведення тихе за призначенням, тому
 * на світлих позиціях шкали (пісок, шавлія) сама рамка ще не називає категорію; крапка називає.
 */
.fs-category-chip::before {
  width: 7px;
  height: 7px;
  flex: 0 0 7px;
  background: color-mix(in srgb, var(--fs-category) 78%, black);
  border-radius: var(--fs-radius-pill);
  content: "";
}

.fs-category-chip[data-category="1"] { --fs-category: var(--fs-category-1); }
.fs-category-chip[data-category="2"] { --fs-category: var(--fs-category-2); }
.fs-category-chip[data-category="3"] { --fs-category: var(--fs-category-3); }
.fs-category-chip[data-category="4"] { --fs-category: var(--fs-category-4); }
.fs-category-chip[data-category="5"] { --fs-category: var(--fs-category-5); }
.fs-category-chip[data-category="6"] { --fs-category: var(--fs-category-6); }
.fs-category-chip[data-category="7"] { --fs-category: var(--fs-category-7); }

/*
 * Progress of one record. The bar measures, it does not judge, so its fill is
 * primary at every value: a green bar at 4% would report a confirmed positive
 * state nobody claimed. The state of the record is said by its badge, and the
 * percentage always stands as text beside the track — colour alone never
 * carries the figure.
 */
.fs-progress {
  display: grid;
  gap: 4px;
  min-width: 0;
}

.fs-progress__head {
  display: flex;
  justify-content: space-between;
  gap: var(--fs-space-2);
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-xs);
  font-weight: 600;
  line-height: 1.2;
}

.fs-progress__head strong {
  color: var(--fs-color-text);
  font-size: var(--fs-text-sm);
  font-variant-numeric: tabular-nums;
}

.fs-progress__track {
  display: block;
  width: 100%;
  height: 7px;
  padding: 0;
  overflow: hidden;
  background: var(--fs-color-border-subtle);
  border: 1px solid var(--fs-color-primary-line);
  border-radius: var(--fs-radius-pill);
  appearance: none;
  -webkit-appearance: none;
}

.fs-progress__track::-webkit-progress-bar {
  background: var(--fs-color-border-subtle);
  border-radius: inherit;
}

.fs-progress__track::-webkit-progress-value {
  background: var(--fs-color-primary);
  border-radius: inherit;
}

.fs-progress__track::-moz-progress-bar {
  background: var(--fs-color-primary);
  border-radius: inherit;
}

/*
 * Compact comparison for a measured value and its share of a total. The fill
 * gives the visual proportion while the amount and percentage remain readable
 * inside the same control, so the bar never becomes an unlabeled decoration.
 */
.fs-value-gauge {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--fs-space-2);
  min-width: 0;
  min-height: 28px;
  padding: 4px var(--fs-space-3);
  border: 1px solid var(--fs-color-border-subtle);
  border-radius: var(--fs-radius-pill);
  background: linear-gradient(
    to right,
    var(--fs-color-primary-subtle) 0 var(--fs-value-gauge, 0%),
    var(--fs-color-surface) var(--fs-value-gauge, 0%)
  );
  font-variant-numeric: tabular-nums;
}

.fs-value-gauge__value {
  margin-right: auto;
  color: var(--fs-color-text);
  font-size: var(--fs-text-sm);
  font-weight: 600;
  white-space: nowrap;
}

.fs-value-gauge__percent {
  margin-left: auto;
  color: var(--fs-color-text);
  font-size: var(--fs-text-sm);
  font-weight: 600;
  white-space: nowrap;
}

.fs-datalist__empty {
  padding: var(--fs-space-4);
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-sm);
  text-align: center;
}

/*
 * What a form says about itself: a parameter that is missing, a request that
 * came back refused. It stays inside the form it belongs to — a toast reports
 * the outcome of an action after the fact, and cannot point at the field.
 */
.fs-form-message {
  margin: 0;
  color: var(--fs-color-danger-text);
  font-size: var(--fs-text-sm);
}

/* Search/filter composition shared by every result page. */
.fs-filters-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--fs-space-3);
}

/*
 * Групи фільтрів.
 *
 * Дев'ять полів однією сіткою читалися як випадковий набір: пошук за назвою стояв поруч із сортуванням, а
 * автор — поруч із брендом. Група збирає поля за тим, що людина робить: знаходить запис, відбирає за
 * людьми й станом, упорядковує. На desktop назва групи — колонка ліворуч, поля всіх груп стоять в одних
 * колонках, тож очі йдуть рівно вниз; між групами волосяна лінія. На телефоні назва стає над полями.
 */
.fs-filters-groups {
  display: grid;
}

.fs-filters-group {
  display: grid;
  grid-template-columns: 132px repeat(4, minmax(0, 1fr));
  align-items: end;
  gap: var(--fs-space-3);
  min-width: 0;
  margin: 0;
  padding: var(--fs-space-3) 0;
  border: 0;
  border-top: 1px solid var(--fs-color-border-subtle);
}

.fs-filters-group:first-child {
  padding-top: 0;
  border-top: 0;
}

.fs-filters-group__title {
  align-self: center;
  float: none;
  width: auto;
  padding: 0;
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* На desktop поле групи займає одну колонку спільної сітки; `--wide` розтягує його лише на телефоні. */
.fs-filters-group > .fs-field--wide {
  grid-column: auto;
}

/* Дії смуги стоять у рядку останньої групи, при правому краї, а не окремим поверхом під нею. */
.fs-filters-group > .fs-filters-actions {
  grid-column: -3 / -1;
  margin-top: 0;
}

@media (max-width: 900px) {
  .fs-filters-group {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .fs-filters-group__title {
    grid-column: 1 / -1;
  }

  .fs-filters-group > .fs-field--wide,
  .fs-filters-group > .fs-filters-actions {
    grid-column: 1 / -1;
  }
}

.fs-filters-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--fs-space-2);
  margin-top: var(--fs-space-3);
}

/*
 * The «⋯» of a page header (`page-menu.html`): a round trigger the size of an icon action, a panel of items
 * under it, each item a row with a glyph. Boards drew this first; records with long names took it over.
 */
.fs-page-menu {
  position: relative;
}

.fs-page-menu__trigger {
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  color: var(--fs-color-primary-text);
  border-radius: var(--fs-radius-pill);
  list-style: none;
  cursor: pointer;
}

.fs-page-menu__trigger::-webkit-details-marker {
  display: none;
}

.fs-page-menu__dots {
  width: 22px;
  height: 22px;
  background: currentcolor;
  mask: url("/stoneware/icons/more.svg") center / 22px 22px no-repeat;
  -webkit-mask: url("/stoneware/icons/more.svg") center / 22px 22px no-repeat;
}

@media (hover: hover) {
  .fs-page-menu__trigger:hover {
    background: var(--fs-color-primary-subtle);
  }
}

.fs-page-menu[open] .fs-page-menu__trigger {
  background: var(--fs-color-primary-subtle);
}

.fs-page-menu__panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 40;
  display: grid;
  min-width: 230px;
  padding: 6px;
  background: var(--fs-color-surface);
  border: 1px solid var(--fs-color-border-subtle);
  border-radius: var(--fs-radius-card);
  box-shadow: var(--fs-shadow-md);
}

.fs-page-menu__panel form {
  display: contents;
}

.fs-page-menu__item {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 36px;
  padding: 6px 10px;
  color: var(--fs-color-text);
  background: transparent;
  border: 0;
  border-radius: var(--fs-radius-control);
  font: inherit;
  font-size: var(--fs-text-sm);
  font-weight: 500;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

/* An item may be a form's button — a removal that posts — and then wears the row's look, not the button's. */
button.fs-page-menu__item {
  width: 100%;
  background: none;
  border: 0;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.fs-page-menu__item--danger {
  color: var(--fs-color-danger);
}


.fs-page-menu__item:hover {
  background: var(--fs-color-surface-hover);
}

.fs-page-menu__glyph {
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
  background: var(--fs-color-primary);
  mask: var(--fs-page-menu-icon, none) center / 16px 16px no-repeat;
  -webkit-mask: var(--fs-page-menu-icon, none) center / 16px 16px no-repeat;
}

/* A long record name keeps the header to two lines; the whole name is in the heading's title. */
.fs-page-heading-card > .fs-page-heading > span {
  display: -webkit-box;
  overflow: hidden;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}

/*
 * «Лише основне для експорту» stands right before the export button it shapes: a quiet checkbox and its words,
 * the height of a small button, so the row of filter actions keeps one line.
 */
.fs-export-brief {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  margin-right: auto;
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-sm);
  cursor: pointer;
  user-select: none;
}

.fs-export-brief input {
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--fs-color-primary);
}

.fs-filters-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--fs-space-2);
  min-width: 0;
}

/*
 * Активні фільтри стоять окремим рядком **під** панеллю «Пошук і фільтри», на полотні сторінки.
 *
 * **Рішення 2026-08-31 (замінює «чипи в рядку дій»).** Чип є контролом фільтра, але він росте, а
 * кнопки — ні: з двома-трьома умовами набір чипів витісняв «Скинути» й «Завантажити Excel», і
 * панель міняла висоту від того, скільки фільтрів увімкнено. Усередині панелі він до того ж
 * ховається разом із нею, а згорнута панель не має ховати причину короткого результату.
 *
 * Рядок не має власної поверхні: чипи вже є pills зі своєю заливкою, а обведена смуга між двома
 * картками читалася б як третій блок сторінки.
 */
.fs-filters-chips--applied {
  padding: var(--fs-space-2) var(--fs-space-1);
}

.fs-filters-chips[hidden] {
  display: none;
}

.fs-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 28px;
  padding: 4px 9px;
  color: var(--fs-color-primary-text);
  background: var(--fs-color-primary-subtle);
  border: 1px solid var(--fs-color-primary-line);
  border-radius: var(--fs-radius-pill);
  font: inherit;
  font-size: var(--fs-text-xs);
  font-weight: 600;
}

/* A chip that drops its own filter is a link when the page is server-rendered and a button
   when a script owns the filter state. Both remove one condition, so both look the same. */
button.fs-filter-chip,
a.fs-filter-chip {
  cursor: pointer;
  text-decoration: none;
}

button.fs-filter-chip::after,
a.fs-filter-chip::after {
  color: currentcolor;
  content: "×";
  font-size: var(--fs-text-sm);
  line-height: 1;
}

button.fs-filter-chip:focus-visible,
a.fs-filter-chip:focus-visible {
  outline: none;
  box-shadow: var(--fs-focus-ring);
}

.fs-result-pagination {
  display: flex;
  align-items: center;
  gap: var(--fs-space-2);
}

.fs-result-pagination:empty {
  display: none;
}

/*
 * Pagination at the foot of a data list.
 *
 * It belongs to Content, not to a block of its own: it governs the very set above it. One copy,
 * at the end, where the reader arrives after finishing the page — a second copy on top would be
 * the same control in two places that can drift apart.
 *
 * The position readout and the jump field were copied into four client stylesheets before they
 * were defined here, which is exactly the kind of rule that has to live in the shared layer.
 */
.fs-datalist__pagination {
  flex-wrap: wrap;
  justify-content: flex-end;
  padding: var(--fs-space-3) var(--fs-space-4);
  border-top: 1px solid var(--fs-color-border);
}

/*
 * The readout says which records are on screen and the controls change them, so they are
 * the two ends of the row rather than one clump against the right edge: pushed together,
 * the sentence was read as a label on the first arrow.
 */
.fs-datalist__pagination > .fs-pagination__position:first-child {
  margin-right: auto;
}

.fs-pagination__position {
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-sm);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/*
 * Jump to a page. A plain GET form, so a thousand pages stay reachable with the keyboard and
 * without a script: the arrows alone only ever reach the neighbouring page.
 */
.fs-pagination__jump {
  display: flex;
  align-items: center;
  gap: var(--fs-space-2);
}

.fs-pagination__jump input[type="number"] {
  width: 4.75rem;
  min-height: 32px;
  padding: 4px 6px;
  color: var(--fs-color-text);
  background: var(--fs-color-field);
  border: 1px solid var(--fs-color-border);
  border-radius: var(--fs-radius-sm);
  font: inherit;
  font-size: var(--fs-text-sm);
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.fs-pagination__jump input[type="number"]:focus {
  outline: none;
  border-color: var(--fs-color-primary);
  box-shadow: var(--fs-focus-ring);
}

/*
 * On a phone the row of five controls no longer fits, and wrapping it puts one lonely arrow on a
 * second line. First and last go instead: the jump field already reaches either end of the range,
 * and it does so in one step rather than two.
 */
@media (max-width: 560px) {
  /*
   * Scoped to the block, not to the class alone: the edge is an action button, and
   * `.action-button { display: inline-flex }` is loaded after this file, so a bare
   * `.fs-pagination__edge` lost the cascade and both edges stayed on the phone.
   */
  .fs-datalist__pagination .fs-pagination__edge {
    display: none;
  }

  /*
   * Two rows rather than a wrap. Six items of unequal width flowed into a ragged pair of
   * columns with an arrow stranded beside the readout; here the sentence takes a line of
   * its own and the three surviving controls sit centred under it as one group.
   */
  .fs-datalist__pagination {
    justify-content: center;
    row-gap: var(--fs-space-3);
  }

  .fs-datalist__pagination > .fs-pagination__position:first-child {
    flex: 1 0 100%;
    margin-right: 0;
    text-align: center;
  }
}

/*
 * Summary strip. Every page that reports counts uses this one component: the users
 * page and the tasks page each grew their own before, which is why one had icons
 * and room and the other had neither.
 *
 * A KPI is the first thing read on a page, so it gets height. The number carries
 * the strip; the icon only names the metric, so it is a quiet grey outline, the
 * same weight as the label beside it. Solid coloured tiles put four saturated
 * blocks above the data and made the markers louder than the figures they mark.
 * Where a metric really has a state, it is said in the row below — a badge, a
 * progress track, an amount tone — not in a swatch next to its name.
 */
.fs-summary {
  display: grid;
  padding: 0;
  overflow: hidden;
  background: var(--fs-color-panel-summary);
}

/* Like a section label: the block names itself on the left, its metadata — how
   fresh the figures are — sits on the right instead of trailing the name. */
.fs-summary__head {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--fs-space-3);
  min-height: 42px;
  padding: 10px 18px;
  border-bottom: 1px solid var(--fs-color-border-subtle);
}

.fs-summary__head > span {
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Metadata is not a heading: it keeps sentence case, exactly as in a panel label. */
.fs-summary__head > .fs-summary__meta {
  color: var(--fs-color-text-muted);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}

.fs-summary__header-meta {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: var(--fs-space-2);
  min-width: 0;
  color: var(--fs-color-text-muted);
  font-size: var(--fs-text-xs);
  font-weight: 400;
}

.fs-summary__header-side {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--fs-space-2);
  min-width: 0;
}

.fs-summary__breakdown-toggle {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  min-height: 40px;
  padding: 10px 44px 10px 18px;
  color: var(--fs-color-text-secondary);
  background: transparent;
  border: 0;
  border-top: 1px solid var(--fs-color-border-subtle);
  font: inherit;
  font-size: var(--fs-text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-align: left;
  text-transform: uppercase;
  cursor: pointer;
}

.fs-summary__breakdown-toggle .fs-page-block__chevron {
  right: 18px;
}

.fs-summary__breakdown-toggle[aria-expanded="true"] .fs-page-block__chevron {
  margin-top: -2px;
  transform: rotate(225deg);
}

@media (hover: hover) {
  .fs-summary__breakdown-toggle:hover {
    background: var(--fs-color-surface-hover);
  }
}

.fs-summary__breakdown-toggle:focus-visible {
  outline: 0;
  box-shadow: inset var(--fs-focus-ring);
}

/*
 * Metadata is one quiet line of separate facts. The caller usually hands the
 * fragment a single wrapper holding them, so the separator is placed between
 * siblings at either level — otherwise a wrapped group renders as one run-on
 * sentence: "20 запитів показано 4 дані станом на …".
 */
.fs-summary__header-meta > * + *::before,
.fs-summary__header-meta > :only-child > * + *::before {
  margin-right: var(--fs-space-2);
  color: var(--fs-color-border);
  content: "·";
}

.fs-summary__header-meta > :only-child {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: var(--fs-space-2);
  min-width: 0;
}

.fs-summary__body {
  display: grid;
}

/*
 * Controls that scope the figures stand above them as a quiet strip, not as a
 * sunken form: a filled box here turned the block for reading into a second
 * panel for typing.
 */
.fs-summary__scope {
  padding: 10px 18px;
  border-bottom: 1px solid var(--fs-color-border-subtle);
}

/*
 * A scope strip placed after the metrics is the last thing in the panel, so its
 * hairline divides it from the figures above rather than drawing a line along
 * the bottom edge of the card.
 */
.fs-summary__scope--after-metrics {
  border-top: 1px solid var(--fs-color-border-subtle);
  border-bottom: 0;
}

/*
 * The metrics are one strip on the panel's own surface, divided by hairlines.
 * Boxed tiles made the block read as four cards stacked inside a fifth: the
 * frame around each figure weighed more than the figure, and a summary is
 * there to be read, not to be counted.
 */
.fs-summary__row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--fs-space-2);
  padding: var(--fs-space-3);
}

/*
 * Compact strip: четверта дозволена форма смуги показників.
 *
 * Плитка існує заради порівняння: чотири однакові прямокутники ставлять свої
 * числа в один ряд, і око бачить, яке з них більше. Один-два показники
 * порівнювати нема з чим — там плитка коштує 84px висоти, щоб сказати одне
 * слово й одне число, і на телефоні з'їдає перший екран у списку, заради якого
 * сторінку й відкрили. Тут показник лишається рядком: `іконка → підпис →
 * число`, все на одній лінії, без власної поверхні й рамки. Плити немає, тому
 * підпис не мусить бути uppercase-міткою — він читається як звичайне слово, а
 * виділяється число.
 *
 * Форму беруть на один-три показники без tone. Там, де показників чотири або
 * де хоч один констатує бізнес-стан кольором, лишаються канонічні плитки.
 */
.fs-summary--compact .fs-summary__row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px var(--fs-space-5);
  padding: 11px 18px;
}

.fs-summary--compact .fs-summary__item {
  display: flex;
  align-items: baseline;
  gap: var(--fs-space-2);
  min-height: 0;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
}

/*
 * Плити немає — отже, немає й заливки тону: у рядку тон лишається на самому
 * числі, як і каже правило «колір належить показнику, а не контейнеру».
 */
.fs-summary--compact .fs-summary__item[data-tone] {
  background: none;
  border-color: transparent;
}

.fs-summary--compact .fs-summary__label {
  align-items: baseline;
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-sm);
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
}

/* Іконка стоїть на лінії тексту, а не на лінії числа поруч із ним. */
.fs-summary--compact .fs-summary__icon {
  align-self: center;
  width: 15px;
  height: 15px;
  flex-basis: 15px;
  mask-size: 15px 15px;
  -webkit-mask-size: 15px 15px;
}

.fs-summary--compact .fs-summary__value {
  font-size: 19px;
  letter-spacing: -0.01em;
}

/*
 * Composition strip: an alternative body for the metrics row.
 *
 * Чотири рівні плитки рахували, скільки записів у якому стані, і не казали
 * нічого про форму роботи — «3 прострочені» стає рішенням аж тоді, коли видно,
 * з яких двадцяти вони. Композиція каже ціле один раз, малює поділ однією
 * смугою і називає кожен стан його числом. Сторінка обирає одне з двох:
 * `fs-summary--composition` віддає смугу metrics під композицію, канонічні
 * `summaryMetric` лишаються значенням за замовчуванням.
 *
 * Колір тут позначає сегмент даних, а не контейнер. Жодного факту смуга не
 * повідомляє самим лише кольором: кожен сегмент названо словом і числом у
 * легенді під нею.
 */
.fs-summary--composition .fs-summary__row {
  display: block;
  padding: var(--fs-space-3) 18px;
}

.fs-summary-composition {
  display: grid;
  gap: 10px;
  min-width: 0;
}

/*
 * Кількість ліворуч, необов'язкова друга величина при правому краї — на одному
 * рядку, бо це дві міри того самого цілого. Коли другої немає, рядок нічим не
 * відрізняється від попереднього одинарного.
 */
/*
 * Дві величини одного цілого лишаються в одному рядку й на пів екрана: вони
 * переносяться самі, коли не вміщаються, а стос за замовчуванням витрачав рядок
 * навіть на «5 запитів» і «0 грн», які стоять поруч без жодної тісноти.
 */
.fs-summary-composition__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 6px var(--fs-space-4);
  min-width: 0;
}

/* Ціле, з якого береться поділ. Воно стоїть один раз і великим, бо кожне число
   в легенді читається у відношенні саме до нього. */
.fs-summary-composition__total {
  display: flex;
  align-items: baseline;
  gap: var(--fs-space-2);
  min-width: 0;
  margin: 0;
}

.fs-summary-composition__total strong {
  color: var(--fs-color-text);
  font-size: 30px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: -0.02em;
}

.fs-summary-composition__total span {
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-sm);
}

/*
 * Друга величина читається як підпис і число, а не як друга плитка: рамки й
 * заливки вона не має, вагу їй дає сам розмір цифри. Підпис іде першим — без
 * нього сума лишалась би числом, про яке невідомо, чого воно стосується.
 */
.fs-summary-composition__aside {
  display: flex;
  align-items: baseline;
  gap: var(--fs-space-2);
  min-width: 0;
  margin: 0;
}

.fs-summary-composition__asides {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: var(--fs-space-2) var(--fs-space-5);
  min-width: 0;
}

.fs-summary-composition__asides .fs-summary-composition__aside {
  flex-wrap: wrap;
}

.fs-summary-composition__aside-label {
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-xs);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.fs-summary-composition__aside-value {
  color: var(--fs-color-text);
  font-size: 20px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}

/* Тон бере лише число — рівно як тон у рядку результату, і рівно з тієї самої
   причини: він констатує стан цієї суми, а не фарбує блок. */
.fs-summary-composition__aside[data-tone="success"] .fs-summary-composition__aside-value {
  color: var(--fs-color-success-text);
}

.fs-summary-composition__aside[data-tone="warning"] .fs-summary-composition__aside-value {
  color: var(--fs-color-warning-text);
}

.fs-summary-composition__aside[data-tone="danger"] .fs-summary-composition__aside-value {
  color: var(--fs-color-danger-text);
}

/* Доріжка видніється у проміжках між сегментами, тому смуга лишається смугою
   навіть тоді, коли один стан забрав майже все. */
.fs-summary-composition__bar {
  display: flex;
  gap: 2px;
  height: 10px;
  overflow: hidden;
  background: var(--fs-color-border-subtle);
  border-radius: var(--fs-radius-pill);
}

/* Ширина сегмента задається скриптом як flex-grow, тож базис нульовий, а
   min-width лишає видимим стан, у якому є один запис із чотирьохсот. */
.fs-summary-composition__segment {
  flex-basis: 0;
  min-width: 3px;
}

.fs-summary-composition__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px var(--fs-space-4);
  min-width: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

.fs-summary-composition__legend-item {
  display: flex;
  align-items: center;
  gap: var(--fs-space-2);
  min-width: 0;
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-sm);
}

/*
 * Коли сегмент легенди відбирає свій стан, він лишається тим самим написом: смуга під шапкою не має
 * ставати рядом кнопок. Натиснутий стан каже себе кольором і підкресленням, а не заливкою — інакше
 * легенда почала б сперечатися за увагу з самим списком.
 */
button.fs-summary-composition__legend-item {
  padding: 0;
  color: inherit;
  background: none;
  border: 0;
  border-radius: var(--fs-radius-sm);
  font: inherit;
  cursor: pointer;
}

@media (hover: hover) {
  button.fs-summary-composition__legend-item:hover {
    color: var(--fs-color-text);
    text-decoration: underline;
    text-underline-offset: 3px;
  }
}

button.fs-summary-composition__legend-item:focus-visible {
  outline: 0;
  box-shadow: var(--fs-focus-ring);
}

button.fs-summary-composition__legend-item[aria-pressed="true"] {
  color: var(--fs-color-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.fs-summary-composition__swatch {
  width: 8px;
  height: 8px;
  flex: 0 0 8px;
  border-radius: 2px;
}

.fs-summary-composition__legend-value {
  color: var(--fs-color-text);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* Обидва мають власний display, тож без цього порожній результат показав би
   доріжку без сегментів і порожній список замість нічого. */
.fs-summary-composition__bar[hidden],
.fs-summary-composition__legend[hidden] {
  display: none;
}

/*
 * Один тон — один рядок для сегмента і його зразка в легенді: доти, доки вони
 * фарбуються разом, зразок не може розійтися із власною ділянкою смуги.
 * Нейтральний узятий muted, а не border: на доріжці кольору border він
 * практично не видно, а «формується» і «скасоване» — це стани, а не пусте
 * місце. `sage` лишається категорійним тоном і стоїть за проміжний стан, який
 * ще не є результатом.
 */
.fs-summary-composition__segment[data-tone="primary"],
.fs-summary-composition__swatch[data-tone="primary"] {
  background: var(--fs-color-primary);
}

.fs-summary-composition__segment[data-tone="success"],
.fs-summary-composition__swatch[data-tone="success"] {
  background: var(--fs-color-success-text);
}

.fs-summary-composition__segment[data-tone="warning"],
.fs-summary-composition__swatch[data-tone="warning"] {
  background: var(--fs-color-warning-text);
}

.fs-summary-composition__segment[data-tone="sage"],
.fs-summary-composition__swatch[data-tone="sage"] {
  background: var(--fs-color-sage);
}

.fs-summary-composition__segment[data-tone="sand"],
.fs-summary-composition__swatch[data-tone="sand"] {
  background: var(--fs-color-tan-line);
}

.fs-summary-composition__segment[data-tone="danger"],
.fs-summary-composition__swatch[data-tone="danger"] {
  background: var(--fs-color-danger-text);
}

.fs-summary-composition__segment[data-tone="neutral"],
.fs-summary-composition__swatch[data-tone="neutral"] {
  background: var(--fs-color-text-muted);
}

/*
 * Stages strip: a third body for the metrics row.
 *
 * Composition ділить одне ціле на частки. Тут ціле саме є станом, а не сумою
 * усього, що коли-небудь сталося: черга — це те, що зараз відкрите, і рахувати
 * разом із нею накопичений за роки результат означає щодня показувати смугу, у
 * якій одна частка росте, а решта тане. Тому стадії стоять потоком, а
 * підсумкові за весь час числа — тихим рядком під ними.
 *
 * Сторінка вмикає форму класом `fs-summary--stages` і віддає їй смугу metrics
 * цілком: три власні смуги блока розділені hairline на всю ширину панелі, як і
 * будь-які інші смуги підсумку.
 */
.fs-summary--stages .fs-summary__row {
  display: block;
  padding: 0;
}

.fs-summary-stages {
  display: grid;
  min-width: 0;
}

.fs-summary-stages__body {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px var(--fs-space-4);
  min-width: 0;
  padding: var(--fs-space-3) 18px;
}

/* Ціле, до якого читається кожна стадія. Воно стоїть один раз і великим — так
   само, як число над смугою композиції. */
.fs-summary-stages__total {
  display: flex;
  align-items: baseline;
  gap: var(--fs-space-2);
  min-width: 0;
  margin: 0;
}

.fs-summary-stages__total strong {
  color: var(--fs-color-text);
  font-size: 30px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: -0.02em;
}

.fs-summary-stages__total span {
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-sm);
}

.fs-summary-stages__flow {
  display: flex;
  align-items: stretch;
  flex: 1 1 320px;
  gap: var(--fs-space-2);
  min-width: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

.fs-summary-stages__flow[hidden],
.fs-summary-stages__signals[hidden],
.fs-summary-stages__facts[hidden],
.fs-summary-stages__foot[hidden] {
  display: none;
}

.fs-summary-stages__step {
  display: flex;
  align-items: center;
  flex: 1 1 0;
  gap: var(--fs-space-2);
  min-width: 0;
}

/* Порядок стадій є фактом, а не оформленням: між ними стоїть напрямок, тому
   сусідні числа не читаються як два незалежні показники. */
.fs-summary-stages__step + .fs-summary-stages__step::before {
  width: 6px;
  height: 6px;
  flex: 0 0 6px;
  border-right: 1.5px solid var(--fs-color-border);
  border-bottom: 1.5px solid var(--fs-color-border);
  transform: rotate(-45deg);
  content: "";
}

.fs-summary-stages__stage {
  display: grid;
  align-content: center;
  flex: 1 1 0;
  gap: 5px;
  min-width: 0;
  min-height: 58px;
  padding: 9px 12px;
  color: inherit;
  background: var(--fs-color-surface-subtle);
  border: 1px solid var(--fs-color-border-subtle);
  border-radius: var(--fs-radius-md);
  font: inherit;
  text-align: left;
}

.fs-summary-stages__stage .fs-summary__value {
  font-size: 22px;
}

button.fs-summary-stages__stage,
button.fs-summary-stages__signal,
button.fs-summary-stages__fact {
  cursor: pointer;
}

/* Тон плитки лишається на місці: підсвітити її сірим на hover означало б на
   час наведення сказати інший стан, ніж вона має. */
@media (hover: hover) {
  button.fs-summary-stages__stage:hover {
    border-color: var(--fs-summary-tone, var(--fs-color-primary));
  }

  button.fs-summary-stages__signal:hover,
  button.fs-summary-stages__fact:hover {
    border-color: currentcolor;
    text-decoration: underline;
    text-underline-offset: 3px;
  }
}

button.fs-summary-stages__stage:focus-visible,
button.fs-summary-stages__signal:focus-visible,
button.fs-summary-stages__fact:focus-visible {
  outline: 0;
  box-shadow: var(--fs-focus-ring);
}

/*
 * Увімкнений фільтр видно на самій стадії, а не лише в чипах під панеллю:
 * підсумок, у якому натиснута плитка виглядає як ненатиснута, змушує шукати
 * причину короткого списку деінде.
 */
.fs-summary-stages__stage[aria-pressed="true"] {
  border-color: var(--fs-summary-tone, var(--fs-color-primary));
  box-shadow: inset 0 0 0 1px var(--fs-summary-tone, var(--fs-color-primary));
}

/*
 * Нижня смуга: ліворуч — те, що вимагає уваги сьогодні, при правому краї —
 * величини за весь час. Обидві групи стоять поруч у один рядок, бо жодна з них
 * не є станом черги і жодна не заслуговує власного блока.
 */
.fs-summary-stages__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--fs-space-2) var(--fs-space-4);
  min-width: 0;
  padding: 9px 18px;
  border-top: 1px solid var(--fs-color-border-subtle);
}

.fs-summary-stages__signals {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--fs-space-2);
  min-width: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

.fs-summary-stages__signal-item {
  display: flex;
  min-width: 0;
}

.fs-summary-stages__signal {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 26px;
  padding: 2px 10px;
  color: var(--fs-color-text-secondary);
  background: var(--fs-color-surface-subtle);
  border: 1px solid var(--fs-color-border-subtle);
  border-radius: var(--fs-radius-pill);
  font: inherit;
  font-size: var(--fs-text-sm);
}

/* Сигнал — рядок тексту, а не плитка, тому підпис не стає uppercase-міткою і
   число не виростає до розміру показника. */
.fs-summary-stages__signal .fs-summary__label {
  gap: 6px;
  font-size: var(--fs-text-sm);
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
}

.fs-summary-stages__signal .fs-summary__value {
  font-size: var(--fs-text-sm);
  font-weight: 600;
}

.fs-summary-stages__signal[data-tone="danger"] {
  color: var(--fs-color-danger-text);
  background: var(--fs-color-danger-subtle);
  border-color: var(--fs-color-danger-line);
}

.fs-summary-stages__signal[data-tone="warning"] {
  color: var(--fs-color-warning-text);
  background: var(--fs-color-warning-subtle);
  border-color: var(--fs-color-warning-line);
}

.fs-summary-stages__signal[data-tone] .fs-summary__icon,
.fs-summary-stages__signal[data-tone] .fs-summary__value {
  color: inherit;
}

.fs-summary-stages__signal[aria-pressed="true"] {
  box-shadow: inset 0 0 0 1px currentcolor;
}

.fs-summary-stages__facts {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--fs-space-1) var(--fs-space-5);
  min-width: 0;
  margin: 0 0 0 auto;
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-sm);
}

.fs-summary-stages__fact {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 0;
  color: inherit;
  background: none;
  border: 0;
  font: inherit;
  font-size: var(--fs-text-sm);
}

.fs-summary-stages__fact strong {
  color: var(--fs-color-text);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* Факт не має власної поверхні, тому увімкнений фільтр каже себе кольором і
   підкресленням: рамка тут повернула б у нижню смугу ще одну плитку. */
.fs-summary-stages__fact[aria-pressed="true"] {
  color: var(--fs-color-primary-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.fs-summary-stages__fact[aria-pressed="true"] strong {
  color: var(--fs-color-primary-text);
}

.fs-summary__head--with-tools {
  align-items: flex-end;
}

.fs-summary__tools {
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  gap: var(--fs-space-2);
  min-width: 0;
}

.fs-summary__item {
  display: grid;
  align-content: center;
  gap: 7px;
  min-height: 72px;
  padding: 10px 18px;
  background: var(--fs-color-surface-subtle);
  border: 1px solid var(--fs-color-border-subtle);
  border-radius: var(--fs-radius-md);
}

.fs-summary__item[data-tone],
.fs-summary-stages__stage[data-tone] {
  --fs-summary-tone-line: var(--fs-color-primary-line);
  --fs-summary-tone-surface: var(--fs-color-primary-subtle);
  background: var(--fs-summary-tone-surface);
  border-color: var(--fs-summary-tone-line);
}

.fs-summary__item[data-tone="primary"],
.fs-summary-stages__stage[data-tone="primary"] {
  --fs-summary-tone: var(--fs-color-primary-text);
  --fs-summary-tone-line: var(--fs-color-primary-line);
  --fs-summary-tone-surface: var(--fs-color-primary-subtle);
}

.fs-summary__item[data-tone="success"],
.fs-summary-stages__stage[data-tone="success"] {
  --fs-summary-tone: var(--fs-color-success-text);
  --fs-summary-tone-line: var(--fs-color-success-line);
  --fs-summary-tone-surface: var(--fs-color-success-subtle);
}

.fs-summary__item[data-tone="warning"],
.fs-summary-stages__stage[data-tone="warning"] {
  --fs-summary-tone: var(--fs-color-warning-text);
  --fs-summary-tone-line: var(--fs-color-warning-line);
  --fs-summary-tone-surface: var(--fs-color-warning-subtle);
}

.fs-summary__item[data-tone="danger"],
.fs-summary-stages__stage[data-tone="danger"] {
  --fs-summary-tone: var(--fs-color-danger-text);
  --fs-summary-tone-line: var(--fs-color-danger-line);
  --fs-summary-tone-surface: var(--fs-color-danger-subtle);
}

.fs-summary__item[data-tone="sand"],
.fs-summary-stages__stage[data-tone="sand"] {
  --fs-summary-tone: var(--fs-color-rust);
  --fs-summary-tone-line: var(--fs-color-tan-line);
  --fs-summary-tone-surface: var(--fs-color-tan);
}

.fs-summary__item[data-tone="sage"],
.fs-summary-stages__stage[data-tone="sage"] {
  --fs-summary-tone: var(--fs-color-text);
  --fs-summary-tone-line: var(--fs-color-sage-line);
  --fs-summary-tone-surface: color-mix(in srgb, var(--fs-color-sage) 38%, var(--fs-color-surface));
}

/*
 * The name of a metric has no state, so its glyph stays the grey of the label.
 * The tone belongs to the figure, and only where the figure states a confirmed
 * business fact — money earned, work overdue — exactly as an amount in a result
 * row. Four tinted plates above a table made the markers louder than the data.
 */
.fs-summary__item[data-tone] .fs-summary__icon,
.fs-summary-stages__stage[data-tone] .fs-summary__icon {
  color: var(--fs-color-text-secondary);
}

.fs-summary__item[data-tone] .fs-summary__value,
.fs-summary-stages__stage[data-tone] .fs-summary__value {
  color: var(--fs-summary-tone, var(--fs-color-text));
}

/* One aggregate may lead the strip. It leads by the size of its figure, not by
   a frame around it: a border would bring the plate back for a single metric. */
.fs-summary__item--emphasis .fs-summary__value {
  font-size: 28px;
}

.fs-summary__label {
  display: flex;
  align-items: center;
  gap: var(--fs-space-2);
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-xs);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/*
 * Masked, not <img>: the icon files carry their own stroke colour, so the same
 * strip would come out part black, part blue, part dark red. The metric's name
 * has one colour, and its glyph takes that colour.
 */
.fs-summary__icon {
  display: block;
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
  background: currentcolor;
  mask-image: var(--fs-summary-icon, none);
  mask-position: center;
  mask-repeat: no-repeat;
  mask-size: 16px 16px;
  -webkit-mask-image: var(--fs-summary-icon, none);
  -webkit-mask-position: center;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-size: 16px 16px;
}

/* A KPI slot can also hold a name, not only a number, so it breaks rather than
   overflows the item beside it. */
.fs-summary__value {
  color: var(--fs-color-text);
  font-size: 24px;
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
  overflow-wrap: anywhere;
}

/* The unit is not part of the number: it stays quiet and does not set the size. */
.fs-summary__value small {
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-sm);
  font-weight: 500;
  letter-spacing: 0;
}

/*
 * The breakdown continues the strip one step quieter: same surface, same
 * rhythm, a hairline above it. A bordered box here made a second panel inside
 * the summary, and the caller may wrap its rows in a slot element, so that
 * wrapper dissolves instead of becoming a layout of its own.
 */
.fs-summary__breakdown {
  display: flex;
  flex-wrap: wrap;
  border-top: 1px solid var(--fs-color-border-subtle);
}

.fs-summary__breakdown > div:not([class]) {
  display: contents;
}

.fs-summary__breakdown[hidden] {
  display: none;
}

.fs-summary__breakdown-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--fs-space-3);
  min-height: 44px;
  padding: 10px 18px;
  flex: 1 1 210px;
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-sm);
}

/*
 * Striping said "selected" in a product where a tinted row means exactly that.
 * Rows are told apart by the hairline between them, like every other list.
 */
.fs-summary__breakdown-row + .fs-summary__breakdown-row {
  border-left: 1px solid var(--fs-color-border-subtle);
}

.fs-summary__breakdown-value {
  color: var(--fs-color-text);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.fs-summary__breakdown-row[data-tone="success"] .fs-summary__breakdown-value {
  color: var(--fs-color-success-text);
}

.fs-summary__breakdown-row[data-tone="warning"] .fs-summary__breakdown-value {
  color: var(--fs-color-warning-text);
}

.fs-summary__breakdown-row[data-tone="danger"] .fs-summary__breakdown-value {
  color: var(--fs-color-danger-text);
}

@media (max-width: 760px) {
  .fs-summary--composition .fs-summary__row {
    padding: 11px 12px 12px;
  }

  /*
   * На пів екрана легенда в рядок переносила число на рядок під власним
   * підписом. Тут кожен стан — свій рядок, підпис ліворуч, число при правому
   * краї: рівно та сама анатомія, що й у рядках деталізації під ним.
   */
  .fs-summary-composition__legend {
    display: grid;
    gap: 7px;
  }

  .fs-summary-composition__legend-value {
    margin-left: auto;
  }

  .fs-summary-composition__total strong {
    font-size: 27px;
  }

  /*
   * Другі величини на телефоні (рішення 2026-10-27): рядки «підпис — сума» під цілим, а не великі зелені
   * числа праворуч. Дві суми по 20px поруч із «504 запити» рвали шапку на три рядки різної ваги; рядком
   * сума читається звичайним розміром, тон лишається лише в числі.
   */
  .fs-summary-composition__head {
    flex-direction: column;
    align-items: stretch;
  }

  .fs-summary-composition__asides {
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    padding-top: var(--fs-space-2);
    border-top: 1px solid var(--fs-color-border-subtle);
  }

  .fs-summary-composition__asides .fs-summary-composition__aside {
    flex-wrap: nowrap;
    justify-content: space-between;
  }

  .fs-summary-composition__aside-value {
    font-size: var(--fs-text-sm);
    font-weight: 600;
  }

  /*
   * Стадії лишаються рядком і на пів екрана: порядок «Створено → Прийнято → В
   * роботі» є самою суттю потоку, а стовпчик із трьох повноширинних смуг казав
   * його вертикаллю й коштував трьох екранних рядків замість одного. Разом із
   * рядком лишається й напрямок між стадіями: він і є тим, що відрізняє потік
   * від трьох сусідніх чисел, тому зникнути мав не він, а те, що з'їдало ширину
   * — іконка, яка повторює підпис, і uppercase-мітка. Плитка тут стиснена до
   * пари «число над підписом» по центру: на ширині близько `120px` число
   * читається першим, а підпис під ним переноситься.
   */
  .fs-summary-stages__body {
    display: grid;
    gap: 9px;
    padding: 10px 12px 11px;
  }

  .fs-summary-stages__total {
    gap: 7px;
  }

  .fs-summary-stages__total strong {
    font-size: 26px;
  }

  .fs-summary-stages__flow {
    gap: 4px;
  }

  .fs-summary-stages__step {
    gap: 4px;
  }

  .fs-summary-stages__step + .fs-summary-stages__step::before {
    width: 5px;
    height: 5px;
    flex-basis: 5px;
    border-width: 1.25px;
  }

  .fs-summary-stages__stage {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column-reverse;
    gap: 3px;
    min-height: 56px;
    padding: 7px 6px;
    text-align: center;
  }

  /* Іконка стадії тут не малюється: на трьох колонках вона забирає рядок у
     підпису, який вона ж і повторює. */
  .fs-summary-stages__stage .fs-summary__icon {
    display: none;
  }

  /* Підпис на трьох колонках лишається словом, а не uppercase-міткою: розрядка
     й великі літери коштують тут цілого рядка переносу. */
  .fs-summary-stages__stage .fs-summary__label {
    gap: 0;
    justify-content: center;
    flex-wrap: wrap;
    min-width: 0;
    color: var(--fs-color-text-secondary);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: normal;
    line-height: 1.15;
    text-transform: none;
    overflow-wrap: break-word;
  }

  .fs-summary-stages__stage .fs-summary__value {
    font-size: 21px;
    line-height: 1;
  }

  /*
   * Нижня смуга теж лишається рядком: сигнали ліворуч, факти за ними, з
   * переносом лише тоді, коли ширини справді бракує.
   */
  .fs-summary-stages__foot {
    display: flex;
    justify-content: flex-start;
    gap: 6px var(--fs-space-3);
    padding: 8px 12px 9px;
  }

  /* Палець влучає у сигнал так само, як у будь-яку іншу дію рядка. */
  .fs-summary-stages__signal {
    min-height: 40px;
    padding: 4px 12px;
  }

  .fs-summary-stages__facts {
    gap: 2px var(--fs-space-3);
    margin-left: 0;
  }

  button.fs-summary-stages__fact {
    min-height: 40px;
  }

  .fs-summary__head--with-tools {
    align-items: stretch;
    flex-direction: column;
  }

  .fs-summary__tools {
    display: block;
    width: 100%;
  }

  .fs-summary__row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-flow: row;
    gap: var(--fs-space-2);
    padding: var(--fs-space-3);
  }

  /* Compact-смуга на телефоні тримається того самого рядка й лише тісніше. */
  .fs-summary--compact .fs-summary__row {
    gap: 3px var(--fs-space-4);
    padding: 9px 12px 10px;
  }

  .fs-summary--compact .fs-summary__value {
    font-size: 18px;
  }

  /* Mobile summaries are compact decision tiles, not a desktop strip stacked vertically. */
  .fs-summary__item {
    align-content: start;
    gap: var(--fs-space-2);
    min-height: 84px;
    padding: 10px 12px;
  }

  .fs-summary__item:last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }

  /*
   * Metadata starts on the title's own line and, when it is longer than the
   * remaining width, keeps running underneath the title instead of moving to a
   * second block below it. Stacked, the header spent two full lines to say
   * "ПІДСУМОК" and one quiet sentence, and the sentence read as a heading of
   * its own. The title is floated for exactly that reason: text flows beside a
   * float on the first line and under it on the next, which is the behaviour
   * asked for and the one no flex or grid arrangement produces.
   */
  .fs-summary__head {
    display: block;
    padding-block: 8px;
  }

  .fs-summary__head::after {
    display: block;
    clear: both;
    content: "";
  }

  .fs-summary__head > span:first-child {
    float: left;
    margin-right: var(--fs-space-2);
    line-height: 18px;
  }

  .fs-summary__header-side,
  .fs-summary__header-meta,
  .fs-summary__header-meta > :only-child {
    display: block;
    width: auto;
    min-width: 0;
    line-height: 18px;
    text-align: left;
  }

  /* Inline flow has no gap, so the separator carries the space on both sides. */
  .fs-summary__header-meta > * + *::before,
  .fs-summary__header-meta > :only-child > * + *::before {
    margin-right: var(--fs-space-2);
    margin-left: var(--fs-space-2);
  }

  .fs-summary__scope {
    padding: 0;
  }

  .fs-summary__breakdown-row {
    flex: 1 1 100%;
  }

  .fs-summary__breakdown-row + .fs-summary__breakdown-row {
    border-top: 1px solid var(--fs-color-border-subtle);
    border-left: 0;
  }

  .fs-summary__value {
    font-size: 22px;
  }
}

.fs-scope-badge {
  display: inline-flex;
  align-items: center;
  width: max-content;
  padding: 4px 10px;
  color: var(--fs-color-primary-hover);
  background: color-mix(in srgb, var(--fs-color-primary) 8%, #fff);
  border: 1px solid color-mix(in srgb, var(--fs-color-primary) 25%, var(--fs-color-border));
  border-radius: var(--fs-radius-pill);
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}



.fs-section-head h2 {
  color: var(--fs-color-text);
  font-size: var(--fs-text-lg);
  font-weight: 700;
}

.fs-section-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}

.fs-section-head__main {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  min-width: 0;
}

.fs-section-head p {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 2px;
  color: var(--fs-color-text-secondary);
  font-size: var(--fs-text-sm);
  font-weight: 500;
}

.fs-checkbox-field {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  color: var(--fs-color-text-secondary);
  font-size: 12px;
}

.fs-checkbox-field {
  align-items: center;
  min-height: var(--fs-control-height);
}

.fs-form-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--fs-space-2);
}

/*
 * A section of a form or of an opened record.
 *
 * Per the brand book a section is divided by its structural label, not by a
 * second surface: the page is already a card, and a bordered box for each
 * section inside it put a card in a card — and, where a section held a nested
 * list, a card in a card in a card. What separates two sections is the label
 * strip and its hairline, which is what the strip is for.
 */
.fs-form-section {
  display: grid;
  align-content: start;
  gap: var(--fs-space-3);
  min-width: 0;
}

/* The card's own padding sets the left edge; the label starts at it, not inside it. */
.fs-form-section > .fs-section-label {
  padding-inline: 0;
}

.fs-form-section__body {
  display: grid;
  gap: var(--fs-space-3);
}

/*
 * A section no longer clips, but a control that opens over the page still has to
 * outrank the sections below it, or its list disappears under the next label
 * strip and its hairline.
 */
.fs-form-section--overlay-visible {
  position: relative;
  z-index: 1;
  overflow: visible;
}

/*
 * Form grid. Two columns on desktop, never three: with three, the label and the
 * control stop reading as a pair and a row of short fields stretches wider than
 * the words naming it. A long value takes both columns through `--wide`.
 */
.fs-form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--fs-space-3);
  align-items: start;
}

.fs-field--wide {
  grid-column: 1 / -1;
}

/*
 * A section label may name itself with a glyph, like a query parameter does.
 * Masked rather than embedded: the icon files carry their own stroke colour, so
 * an <img> here would break the one grey the label row is written in.
 */
.fs-section-label__icon {
  display: block;
  width: 16px;
  height: 16px;
  flex: 0 0 16px;
  background: currentcolor;
  mask-image: var(--fs-section-icon, none);
  mask-position: center;
  mask-repeat: no-repeat;
  mask-size: 16px 16px;
  -webkit-mask-image: var(--fs-section-icon, none);
  -webkit-mask-position: center;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-size: 16px 16px;
}

/* A label that carries an action keeps the action out of the uppercase run. */
.fs-section-label__actions {
  display: flex;
  align-items: center;
  gap: var(--fs-space-2);
  flex: 0 0 auto;
}

/*
 * With an action on the right, the metadata belongs beside the name it qualifies. Left to
 * `space-between` it would drift to the middle of the row and read as a third, unrelated column.
 */
.fs-section-label:has(.fs-section-label__actions) .fs-section-label__meta {
  margin-right: auto;
}

@media (max-width: 760px) {
  /*
   * На телефоні шапка сторінки — плаваюча скляна панель, пара до нижньої.
   *
   * Розмір один і сталий. Стиснення на скролі коштувало стрибка контенту під
   * шапкою на кожному русі пальця, а назва потрібна однаково добре і на першому
   * екрані, і на двадцятому: якщо стиснена вона читається, то читається завжди.
   * Двох станів немає — немає ні переходу між ними, ні стрибка.
   *
   * Форму й ширину шапка бере з нижньої панелі: ті самі `10px` від кожного
   * краю екрана, та сама межа `560px`, той самий радіус `24px` і те саме скло.
   * Дві закріплені панелі на одному екрані мусять читатися як одна пара, а не
   * як бар зверху й острів знизу — інакше сторінка виглядає зібраною з двох
   * різних інтерфейсів. Ширину дає `calc(100% - 10px)`: сторінка вже тримає
   * власні `5px` полів, і ще `5px` тут дають рівно `10px` до краю екрана.
   *
   * Скло, а не плита: закріплена панель із непрозорою заливкою відрізає
   * сторінку рівною смугою й приховує, що під нею щось їде. Заливка тримає
   * лише світлість, аби заголовок не сідав на текст, який під нього заїжджає,
   * а тон бере canvas, бо біле скло над білою карткою не відрізнити від самої
   * картки.
   *
   * `is-stuck` тут лишається без наслідків навмисно: клас ставить спільний
   * `page-header.js`, і глушити його правилами дешевше, ніж заводити окрему
   * поведінку скрипта для однієї ширини екрана. Шапка report workspace
   * приходить до того самого вигляду у власному `report-page.css`: він
   * вантажиться після цього файла, тому її правило мусить стояти там, а не тут.
   */
  .fs-page-heading-card {
    position: sticky;
    z-index: 30;
    top: calc(10px + env(safe-area-inset-top));
    align-items: center;
    flex-wrap: wrap;
    gap: var(--fs-space-2);
    width: calc(100% - 10px);
    max-width: 560px;
    min-height: 60px;
    /* Плаваюча панель стоїть у своєму просвіті з усіх боків, тому знизу вона
       додає до `--fs-page-gap` рівно стільки, скільки тримає зверху. */
    margin: 0 auto 10px;
    padding: 8px var(--fs-space-4);
    background: color-mix(in srgb, var(--fs-color-canvas) 10%, transparent);
    border-color: color-mix(in srgb, var(--fs-color-primary) 12%, rgb(255 255 255 / 45%));
    border-radius: 24px;
    box-shadow:
      inset 0 1px 0 rgb(255 255 255 / 62%),
      0 4px 16px rgb(20 24 31 / 10%),
      0 14px 32px rgb(20 24 31 / 16%);
    backdrop-filter: blur(14px) saturate(190%) brightness(1.05);
  }

  .fs-page-heading-card.is-stuck {
    min-height: 60px;
    padding-block: 8px;
    box-shadow:
      inset 0 1px 0 rgb(255 255 255 / 62%),
      0 4px 16px rgb(20 24 31 / 10%),
      0 14px 32px rgb(20 24 31 / 16%);
  }

  /*
   * Без розмиття скла немає: слабка заливка лишила б заголовок просто на тексті,
   * який під нього заїжджає. Там, де `backdrop-filter` не працює, шапка
   * повертається до непрозорої поверхні.
   */
  @supports not (backdrop-filter: blur(1px)) {
    .fs-page-heading-card {
      background: rgb(255 255 255 / 96%);
    }
  }

  .fs-page-heading-card > .fs-page-heading {
    flex: 1 1 auto;
    min-width: 0;
  }

  /*
   * A long name — a tender's full subject — keeps the header to two lines and ends in an ellipsis; the whole
   * name is the heading's title and the record's own body (уточнено 2026-10-19).
   */
  .fs-page-heading-card > .fs-page-heading > span:last-child,
  .fs-page-heading-card > .fs-page-heading > :not(img):last-child {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
  }

  /*
   * Шапка на телефоні — один рядок: назва ліворуч, дії праворуч. Дія зі знаком лишається самим знаком
   * у колі `40px`, бо підпис не вміщався поруч із назвою і зсував усі дії на другий, а то й третій рядок —
   * шапка росла вдвічі (рішення 2026-10-17). Дія без знака лишає свій підпис.
   */
  .fs-page-heading-card {
    flex-wrap: nowrap;
  }

  .fs-page-heading-actions {
    flex: 0 0 auto;
    flex-wrap: nowrap;
  }

  .fs-page-heading-actions .action-button:has(.action-button__icon) {
    width: 40px;
    min-width: 40px;
    padding: 0;
    justify-content: center;
  }

  .fs-page-heading-actions .action-button:has(.action-button__icon) .action-button__label {
    display: none;
  }

  /*
   * Section tabs docked in the header (`header-tabs.js`): the second row of the same glass, its pills on the
   * glass itself. Scrolling down folds the row away; the header shrinks with it and comes back on the way up.
   */
  .fs-page-heading-card:has(> nav[data-header-tabs].is-docked) {
    flex-wrap: wrap;
    row-gap: 8px;
    padding-bottom: 10px;
  }

  .fs-page-heading-card > nav[data-header-tabs].is-docked {
    position: static;
    top: auto;
    z-index: auto;
    grid-column: 1 / -1;
    flex: 1 0 100%;
    order: 10;
    max-height: 48px;
    margin: 0 -6px;
    padding: 0 6px;
    overflow-x: auto;
    overflow-y: hidden;
    background: transparent;
    border: 0;
    box-shadow: none;
    transition: max-height 0.22s ease, opacity 0.18s ease, margin 0.22s ease;
  }

  .fs-page-heading-card > nav[data-header-tabs].is-docked::before {
    display: none;
  }

  .fs-page-heading-card.has-tabs-tucked {
    row-gap: 0;
    padding-bottom: 8px;
  }

  .fs-page-heading-card.has-tabs-tucked > nav[data-header-tabs].is-docked {
    max-height: 0;
    opacity: 0;
    pointer-events: none;
  }

  .fs-page-heading,
  .fs-page-heading-card.is-stuck .fs-page-heading {
    gap: var(--fs-space-2);
    font-size: var(--fs-text-xl);
    line-height: 1.2;
    letter-spacing: -0.015em;
  }

  /*
   * Знак сторінки — її identity, і на телефоні він єдине, що відрізняє одну
   * шапку від іншої з відстані витягнутої руки: назву там читають зблизька, а
   * піктограму впізнають. У розмірі підпису вона переставала бути знаком і
   * ставала другою літерою назви. Висоти це не додає: шапка тримає `60px` при
   * полях `8px`, тобто всередині лишається `44px`, і `36px` у них вкладаються
   * із запасом — найвищим у рядку стає знак, а не сам рядок.
   */
  .fs-page-heading img,
  .fs-page-heading-card.is-stuck .fs-page-heading img {
    width: 36px;
    height: 36px;
    flex-basis: 36px;
  }

  /*
   * Назва, метадані й дія не поміщаються в один рядок на телефоні. Вони переносяться, а не
   * стискаються: зрізана назва блока не пояснює нічого, а дія тут одна на весь блок.
   */
  .fs-section-label {
    flex-wrap: wrap;
  }

  .fs-page-actions__body {
    display: grid;
    padding: var(--fs-space-3);
  }

  .fs-page-actions__group {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    width: 100%;
  }

  .fs-page-actions__group--primary {
    margin-left: 0;
  }

  .fs-page-actions__group > .action-button,
  .fs-page-actions__group > form,
  .fs-page-actions__group > form > .action-button {
    width: 100%;
  }

  .fs-page-actions__group > .action-button,
  .fs-page-actions__group > form > .action-button {
    justify-content: center;
  }

  .fs-page-actions__group > :only-child {
    grid-column: 1 / -1;
  }

  .fs-page-actions__group > :last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }

  .fs-form-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  /*
   * The action row becomes a stack of full-width buttons at the end of the form.
   * It is still not pinned: a sticky bar would cover the field being typed into
   * for the whole visit instead of for the moment the user is ready to save.
   */
  .fs-form-actions {
    align-items: stretch;
    flex-direction: column;
    flex-wrap: nowrap;
  }

  .fs-form-actions > .action-button {
    width: 100%;
  }
}

.fs-empty-state {
  text-align: center;
}

.fs-empty-state h2 {
  font-size: 16px;
  font-weight: 700;
}

.fs-empty-state p {
  margin-top: 4px;
  color: var(--fs-color-text-secondary);
  font-size: 12px;
}

@media (max-width: 600px) {
  /* Геометрія шапки лежить у правилах mobile вище; тут — лише рядок її дій. */
  .fs-page-heading-actions {
    justify-content: flex-end;
    width: auto;
  }


  .fs-section-head {
    flex-direction: column;
  }

  .fs-scope-badge {
    white-space: normal;
  }
}
