/* ============================================================================
   CentriX.AI.FISReporter - project stylesheet
   ----------------------------------------------------------------------------
   WHY THIS FILE EXISTS
   `styles.css` is a PRE-COMPILED Tailwind v4 bundle copied from
   CentriX.Web.Inside. There is no Tailwind build step in this project, so any
   utility class not already inside that bundle produces NO css at all.
   (Verified stale: `py-6`, `mt-auto`, `bg-accent`, `sm:inline`,
   `hover:shadow-md` are used by the CentriX razor views yet absent here.)

   Therefore: layout/structure is expressed with the explicit `fis-*` classes
   below, and visuals reuse the `kt-*` component layer from styles.css.
   Everything here is plain CSS driven by the theme tokens that styles.css
   defines on `:root` and `.dark`, so light/dark mode works with no extra work.
   ========================================================================== */

/* ---------- app shell ---------------------------------------------------- */

:root {
  --fis-header-height: 60px;
  --fis-gutter: 1.25rem;
  --fis-maxw: 1600px;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  background-color: var(--muted);
  color: var(--foreground);
  font-family: Inter, ui-sans-serif, system-ui, "Segoe UI", Roboto, sans-serif;
  font-size: 0.875rem;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.fis-shell {
  display: flex;
  min-height: 100%;
  flex-direction: column;
}

.fis-container {
  width: 100%;
  max-width: var(--fis-maxw);
  margin-inline: auto;
  padding-inline: var(--fis-gutter);
}

.fis-header {
  position: sticky;
  top: 0;
  z-index: 30;
  height: var(--fis-header-height);
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  background-color: var(--muted);
  border-bottom: 1px solid var(--border);
}

.fis-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.fis-brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  text-decoration: none;
  color: var(--mono);
}

.fis-brand img {
  min-height: 24px;
  height: 24px;
}

.fis-brand__name {
  font-weight: 600;
  color: var(--mono);
}

.fis-brand__env {
  font-size: 0.6875rem;
  line-height: 1;
  padding: 0.1875rem 0.375rem;
  border-radius: 0.25rem;
  background-color: var(--accent);
  color: var(--accent-foreground);
}

.fis-main {
  flex: 1 1 auto;
  padding-block: 1.5rem;
}

.fis-footer {
  flex: 0 0 auto;
  padding-block: 0.75rem;
  border-top: 1px solid var(--border);
  color: var(--secondary-foreground);
  font-size: 0.8125rem;
}

.fis-footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

/* ---------- generic layout primitives ----------------------------------- */

.fis-stack {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.fis-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.625rem;
}

.fis-row--between {
  justify-content: space-between;
}

.fis-spacer {
  flex: 1 1 auto;
}

.fis-grid {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: repeat(1, minmax(0, 1fr));
}

@media (width >= 640px) {
  .fis-grid--2,
  .fis-grid--4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (width >= 1024px) {
  .fis-grid--3 {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .fis-grid--4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.fis-muted {
  color: var(--secondary-foreground);
}

.fis-strong {
  color: var(--mono);
  font-weight: 600;
}

.fis-hidden {
  display: none !important;
}

.fis-num {
  font-variant-numeric: tabular-nums;
  text-align: end;
  white-space: nowrap;
}

.fis-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 22rem;
}

/* ---------- tabs -------------------------------------------------------- */

.fis-tabbar {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  flex-wrap: wrap;
  border-bottom: 1px solid var(--border);
  margin-bottom: 1.25rem;
}

.fis-tab {
  appearance: none;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: 0.625rem 0.875rem;
  margin-bottom: -1px;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--secondary-foreground);
  cursor: pointer;
  border-radius: 0.375rem 0.375rem 0 0;
}

.fis-tab:hover {
  color: var(--mono);
  background-color: var(--accent);
}

.fis-tab.active {
  color: var(--primary);
  border-bottom-color: var(--primary);
  background-color: transparent;
}

.fis-tab:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: -2px;
}

.fis-panel[hidden] {
  display: none;
}

/* ---------- kpi tiles --------------------------------------------------- */

.fis-kpi {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  padding: 1.125rem 1.25rem;
}

.fis-kpi__label {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--secondary-foreground);
}

.fis-kpi__value {
  font-size: 1.75rem;
  line-height: 1.15;
  font-weight: 600;
  color: var(--mono);
  font-variant-numeric: tabular-nums;
}

.fis-kpi__hint {
  font-size: 0.75rem;
  color: var(--secondary-foreground);
}

.fis-delta--up {
  color: var(--primary);
}

.fis-delta--down {
  color: var(--destructive);
}

/* ---------- table ------------------------------------------------------- */

.fis-tablewrap {
  width: 100%;
  overflow-x: auto;
}

.fis-tablewrap table {
  min-width: 100%;
}

.fis-th {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

.fis-th__sort {
  display: inline-block;
  width: 0.75rem;
  opacity: 0.45;
  font-size: 0.6875rem;
}

.fis-th.is-sorted .fis-th__sort {
  opacity: 1;
  color: var(--primary);
}

.fis-empty {
  padding: 2.5rem 1.25rem;
  text-align: center;
  color: var(--secondary-foreground);
}

.fis-empty__icon {
  font-size: 1.75rem;
  display: block;
  margin-bottom: 0.5rem;
  opacity: 0.55;
}

/* ---------- drop zone --------------------------------------------------- */

.fis-drop {
  border: 1px dashed var(--input);
  border-radius: var(--radius);
  padding: 1.5rem;
  text-align: center;
  color: var(--secondary-foreground);
  background-color: var(--background);
}

.fis-drop.is-over {
  border-color: var(--primary);
  background-color: var(--accent);
  color: var(--mono);
}

/* ---------- misc -------------------------------------------------------- */

@media print {
  .fis-header,
  .fis-footer,
  .fis-tabbar,
  .fis-noprint {
    display: none !important;
  }
  .fis-main {
    padding: 0;
  }
}

/* ============================================================================
   CRUD layer: settings dropdown, modal, form grid, tag editor, row actions.
   Added for the management pages (Trạng thái / Dự án / AI Agent) and the two
   report tabs. Plain CSS on theme tokens, same rules as above - no Tailwind
   utility may be assumed to exist.
   ========================================================================== */

/* ---------- page title --------------------------------------------------- */

.fis-pagetitle {
  margin: 0 0 0.875rem;
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--mono);
}

/* ---------- header dropdown --------------------------------------------- */

.fis-dropdown {
  position: relative;
}

.fis-dropdown__menu {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  z-index: 40;
  width: 17rem;
  max-height: 80vh;
  overflow-y: auto;
}

.fis-menu-label {
  padding: 0.375rem 0.625rem 0.25rem;
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--secondary-foreground);
}

.fis-menu-count {
  margin-inline-start: auto;
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
  color: var(--secondary-foreground);
}

.kt-dropdown-menu-link.fis-danger,
.kt-dropdown-menu-link.fis-danger i {
  color: var(--destructive);
}

/* ---------- breadcrumb chip for admin pages ----------------------------- */

.fis-tab--crumb {
  cursor: default;
  pointer-events: none;
}

.fis-tab--crumb:hover {
  background: none;
}

/* ---------- modal ------------------------------------------------------- */

/* CASCADE TRAP - do not rewrite this as a bare `.kt-modal { display: flex }`.
   styles.css hides the overlay with `.kt-modal:not(.open){display:none}` INSIDE
   `@layer components`. An unlayered rule beats a layered one no matter the
   specificity, so a bare `.kt-modal{display:flex}` here kept the overlay
   displayed forever: after the first dialog closed, an empty 100vw x 100vh
   fixed element sat at z-index 60 swallowing every click, and only F5 cleared
   it (the host is created lazily, so a fresh page had none yet).
   Scoping to `.open` means this rule simply does not match when closed. */
.kt-modal.open {
  z-index: 60;
  display: flex;
  align-items: flex-start;
  justify-content: center;
}

.fis-modal {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 34rem;
  margin: 2.5rem auto;
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 5rem);
  background-color: var(--background);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 24px 48px -12px rgba(0, 0, 0, 0.35);
}

.fis-modal--lg {
  max-width: 56rem;
}

.fis-modal--sm {
  max-width: 26rem;
}

.kt-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--border);
}

.kt-modal-title {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
  color: var(--mono);
}

.kt-modal-body {
  padding: 1.25rem;
  overflow-y: auto;
  flex: 1 1 auto;
}

.kt-modal-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.875rem 1.25rem;
  border-top: 1px solid var(--border);
}

.kt-modal-footer .kt-alert {
  flex: 1 1 auto;
  margin: 0;
}

/* ---------- form grid --------------------------------------------------- */

.fis-formgrid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(1, minmax(0, 1fr));
}

@media (width >= 640px) {
  .fis-formgrid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.fis-formitem {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  min-width: 0;
}

.fis-formitem--full {
  grid-column: 1 / -1;
}

.fis-formitem .kt-form-label {
  display: flex;
  align-items: baseline;
  gap: 0.125rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--mono);
}

.fis-req {
  color: var(--destructive);
  font-weight: 600;
}

.fis-formitem .kt-form-message {
  font-size: 0.75rem;
  color: var(--destructive);
}

.fis-invalid,
.fis-invalid:focus-visible {
  border-color: var(--destructive) !important;
}

input[readonly].kt-input,
textarea[readonly].kt-textarea {
  background-color: var(--muted);
  color: var(--secondary-foreground);
  cursor: not-allowed;
}

/* ---------- tag editor (Nhân sự tham gia) -------------------------------- */

.fis-tags {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.fis-tags__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
  min-height: 1.75rem;
  align-items: center;
}

.fis-tags__chips .kt-badge {
  gap: 0.25rem;
}

.fis-tags__x {
  appearance: none;
  background: none;
  border: 0;
  padding: 0 0 0 0.125rem;
  margin: 0;
  cursor: pointer;
  color: inherit;
  font-size: 1rem;
  line-height: 1;
  opacity: 0.6;
}

.fis-tags__x:hover {
  opacity: 1;
  color: var(--destructive);
}

.fis-tags__input {
  max-width: 16rem;
}

/* ---------- row actions -------------------------------------------------- */

/* The iHRP table is 19 columns wide, so the row actions would sit far off the
   right edge behind a horizontal scroll. Pinning the column keeps edit/delete
   reachable at any scroll position; it needs an opaque background of its own
   because the cells underneath scroll past it. */
.fis-actions-col {
  width: 1%;
  white-space: nowrap;
  text-align: end;
  position: sticky;
  right: 0;
  z-index: 2;
  background-color: var(--background);
  border-inline-start: 1px solid var(--border);
}

thead .fis-actions-col {
  z-index: 3;
  background-color: var(--muted);
}

.fis-actions {
  display: inline-flex;
  gap: 0.125rem;
  justify-content: flex-end;
}

/* ---------- progress cell ----------------------------------------------- */

.fis-progress {
  display: inline-block;
  vertical-align: middle;
  width: 3.5rem;
  height: 0.375rem;
  border-radius: 999px;
  background-color: var(--muted);
  overflow: hidden;
  margin-inline-end: 0.5rem;
}

.fis-progress__bar {
  height: 100%;
  background-color: var(--primary);
  border-radius: 999px;
}

.fis-progress__label {
  font-variant-numeric: tabular-nums;
}

/* ---------- wrapped cells (long Vietnamese text) ------------------------ */

.fis-wrap {
  white-space: pre-line;
  min-width: 16rem;
  max-width: 28rem;
}

/* ============================================================================
   Breakdown panel: compact filter bar + statistics table.
   ========================================================================== */

/* ---------- filter bar --------------------------------------------------- */

/* The card header is min-height 3.5rem and shrink-to-fit; let it breathe when
   the filter wraps under the title on a narrow viewport. */
.fis-cardhead {
  padding-block: 0.625rem;
  row-gap: 0.625rem;
}

.fis-filter {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.fis-filter__field {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  min-width: 0;
}

.fis-filter__label {
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--secondary-foreground);
  white-space: nowrap;
}

/* Vendor `.kt-select` is width:100%, which is what made two of these stack and
   overflow the header. Inside a filter they size to content instead. */
.fis-filter .kt-select {
  width: auto;
  min-width: 8.5rem;
  /* "Trung binh: % Hoan thanh" is the longest measure label; a <select> clips
     rather than ellipsises, so it needs room or it collides with its caret. */
  max-width: 16rem;
  flex: 0 1 auto;
}

@media (width < 640px) {
  .fis-filter {
    width: 100%;
    justify-content: stretch;
  }
  .fis-filter__field {
    flex: 1 1 100%;
  }
  .fis-filter .kt-select {
    width: 100%;
    max-width: none;
  }
}

/* ---------- statistics table -------------------------------------------- */

.fis-breakdown-table {
  margin-top: 1rem;
  width: 100%;
  overflow-x: auto;
  /* Many buckets should scroll inside the card rather than stretch the page. */
  max-height: 22rem;
  overflow-y: auto;
}

.fis-bdtable {
  width: 100%;
}

.fis-bdtable thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background-color: var(--muted);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--secondary-foreground);
  white-space: nowrap;
}

.fis-bdtable tbody tr:hover {
  background-color: var(--accent);
}

/* The vendor styles `:is(.kt-table tbody) td` and `:is(.kt-table tfoot) th`,
   but NOT `tfoot td` - so the total row (which uses td) inherited zero
   horizontal padding and its label sat 16px left of the rows above it.
   Set both axes explicitly for every cell instead of relying on the vendor. */
.fis-bdtable td,
.fis-bdtable th {
  padding-inline: 1rem;
  padding-block: 0.4375rem;
}

.fis-col-rank {
  width: 2.5rem;
  text-align: end;
  font-variant-numeric: tabular-nums;
  padding-inline-end: 0.75rem !important;
}

.fis-col-num {
  width: 7rem;
  text-align: end;
  white-space: nowrap;
}

.fis-col-share {
  width: 34%;
  min-width: 6rem;
}

.fis-bd-label {
  display: inline-block;
  max-width: 26rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  vertical-align: bottom;
}

.fis-share {
  height: 0.5rem;
  border-radius: 999px;
  background-color: var(--muted);
  overflow: hidden;
}

.fis-share__bar {
  height: 100%;
  border-radius: 999px;
  background-color: var(--primary);
  min-width: 2px;
}

.fis-bdtable tfoot td {
  position: sticky;
  bottom: 0;
  background-color: var(--background);
  border-top: 1px solid var(--border);
  font-weight: 600;
  color: var(--mono);
}

/* ---------- live field hint (Do kho band label) -------------------------- */

.fis-hint {
  font-size: 0.75rem;
  font-weight: 500;
  line-height: 1.35;
}

.fis-hint--muted { color: var(--secondary-foreground); font-weight: 400; }
.fis-hint--success { color: var(--primary); }
.fis-hint--primary { color: var(--primary); }
.fis-hint--warning { color: var(--mono); }
.fis-hint--destructive { color: var(--destructive); }
.fis-hint--error { color: var(--destructive); }

/* ============================================================================
   Reporting period picker, change-history dialog, 12-column form grid and the
   one-row table toolbar. Same rules as everything above: plain CSS on the
   theme tokens, no Tailwind utility assumed to exist.
   ========================================================================== */

/* ---------- small text utilities ---------------------------------------- */

/* STT is a row counter, not a measurement - see buildCell() in ui/crud.js. */
.fis-center {
  text-align: center;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.fis-nowrap {
  white-space: nowrap;
}

/* Read-only status pill (the "filtering by week 34" note above each table). */
.fis-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding: 0.1875rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.75rem;
  color: var(--secondary-foreground);
  background-color: var(--background);
  white-space: nowrap;
}

/* ---------- reporting period picker (header) ---------------------------- */

.fis-range {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  padding-inline: 0.5rem;
  border-inline-start: 1px solid var(--border);
}

.fis-range__icon {
  color: var(--secondary-foreground);
  font-size: 0.875rem;
}

/* Vendor `.kt-select` is width:100%, which in the flex header row collapses to
   nothing. Size both selects to their content instead, and cap the week one -
   its labels carry the Monday..Sunday span and would otherwise stretch the
   whole header. */
.fis-range .kt-select {
  width: auto;
  flex: 0 0 auto;
}

#fis-range-year {
  min-width: 6rem;
}

#fis-range-week {
  min-width: 9rem;
  max-width: 15rem;
}

.fis-range__span {
  font-size: 0.75rem;
  color: var(--secondary-foreground);
  white-space: nowrap;
}

/* Below ~1100px the header cannot hold subtitle + period + 3 buttons. The
   subtitle is the expendable one: the period is a control, the subtitle is
   decoration. */
@media (width < 1100px) {
  #fis-subtitle {
    display: none;
  }
  .fis-range__span {
    display: none;
  }
}

@media (width < 800px) {
  #fis-range-week {
    min-width: 6.5rem;
  }
  .fis-range {
    padding-inline: 0.25rem;
  }
}

/* ---------- table toolbar (one row) ------------------------------------- */

.fis-toolbar {
  row-gap: 0.5rem;
}

.fis-toolbar__group {
  gap: 0.5rem;
  flex-wrap: nowrap;
  min-width: 0;
}

/* Column picker first, then the box it narrows. Both shrink-to-fit so the
   count and page size stay on the same line. */
.fis-toolbar__col {
  width: auto;
  min-width: 9rem;
  max-width: 13rem;
  flex: 0 1 auto;
}

.fis-toolbar__search {
  width: 100%;
  min-width: 9rem;
  max-width: 18rem;
  flex: 1 1 12rem;
}

@media (width < 640px) {
  .fis-toolbar__group {
    flex-wrap: wrap;
  }
}

/* ---------- form grid: 12 columns + section headings -------------------- */

/* Overrides the 1-then-2 column grid defined earlier in this file: 12 columns
   is what makes quarter/third/twothirds widths land on a shared baseline, so
   a row of four number inputs reads as one group. */
@media (width >= 640px) {
  .fis-formgrid {
    grid-template-columns: repeat(12, minmax(0, 1fr));
  }

  .fis-formitem--full { grid-column: span 12; }
  .fis-formitem--twothirds { grid-column: span 8; }
  .fis-formitem--half { grid-column: span 6; }
  .fis-formitem--third { grid-column: span 4; }
  .fis-formitem--quarter { grid-column: span 3; }
}

/* Narrow viewport: everything is full width, sections still separate. */
@media (width < 640px) {
  .fis-formitem--full,
  .fis-formitem--twothirds,
  .fis-formitem--half,
  .fis-formitem--third,
  .fis-formitem--quarter {
    grid-column: 1 / -1;
  }
}

.fis-formsection {
  grid-column: 1 / -1;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.375rem;
  padding-bottom: 0.375rem;
  border-bottom: 1px solid var(--border);
}

/* No top margin on the first heading - the modal body already has padding. */
.fis-formgrid > .fis-formsection:first-child {
  margin-top: 0;
}

.fis-formsection__title {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--mono);
}

.fis-formsection__hint {
  font-size: 0.75rem;
  color: var(--secondary-foreground);
}

/* ---------- change-history dialog --------------------------------------- */

.fis-modal--xl {
  max-width: 72rem;
}

.fis-logs__device {
  padding: 0.875rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background-color: var(--muted);
}

.fis-logs__device .kt-input {
  width: auto;
  min-width: 10rem;
  flex: 0 1 auto;
}

/* Many entries scroll inside the dialog rather than growing it past the
   viewport; the header stays put so the columns remain identifiable. */
.fis-logs__table {
  width: 100%;
  max-height: 26rem;
  overflow: auto;
}

.fis-logs__table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background-color: var(--muted);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--secondary-foreground);
  white-space: nowrap;
}

.fis-logs__table td {
  vertical-align: top;
  font-size: 0.8125rem;
}

.fis-logs__table .fis-wrap {
  min-width: 12rem;
  max-width: 24rem;
}

/* ---------- device panel in the change-history dialog ------------------- */

/* Read-only facts, not a form: the machine name / IP / user are detected, never
   typed (see app/js/core/audit.js). */
.fis-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem 2rem;
  margin-top: 0.5rem;
}

.fis-fact {
  display: flex;
  align-items: baseline;
  gap: 0.375rem;
  min-width: 0;
}

.fis-fact__label {
  font-size: 0.75rem;
  color: var(--secondary-foreground);
  white-space: nowrap;
}

.fis-fact__value {
  font-weight: 600;
  color: var(--mono);
  font-variant-numeric: tabular-nums;
  word-break: break-all;
}

/* ---------- collapsible Dashboard card ---------------------------------- */

/* The title doubles as the collapse trigger: a header that only responds on a
   small chevron reads as static. Reset the button chrome so it still looks
   exactly like the `h3` it wraps. */
.fis-cardhead__title {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  cursor: pointer;
  text-align: start;
  color: inherit;
  font: inherit;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}

.fis-cardhead__title:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
  border-radius: 0.25rem;
}

/* Collapsed: the header is the whole card, so drop the bottom border that was
   separating it from a body that is no longer there. */
.kt-card.is-collapsed .kt-card-header {
  border-bottom: 0;
}

/* ---------- locked key field -------------------------------------------- */

/* A key other records already point at. `inUse` guards delete; this guards
   rename, because there is no cascade update anywhere in this app. */
.fis-lockicon {
  margin-inline-start: 0.25rem;
  font-size: 0.75rem;
  color: var(--secondary-foreground);
}

.fis-formitem.is-locked .kt-input,
.fis-formitem.is-locked .kt-select,
.fis-formitem.is-locked .kt-textarea {
  background-color: var(--muted);
  color: var(--secondary-foreground);
  cursor: not-allowed;
}

/* ============================================================================
   Charts (ui/chart.js). Inline SVG, so every colour has to come from a CSS
   rule - a `var(--x)` inside a presentation attribute does not resolve.
   ========================================================================== */

/* Categorical palette. Defined here rather than reusing --primary eight times
   over: a doughnut needs slices that are actually distinguishable, and the
   vendor bundle ships no --success / --warning / --info tokens to borrow. */
:root {
  --fis-c1: #3b82f6;
  --fis-c2: #10b981;
  --fis-c3: #f59e0b;
  --fis-c4: #8b5cf6;
  --fis-c5: #ef4444;
  --fis-c6: #06b6d4;
  --fis-c7: #ec4899;
  --fis-c8: #84cc16;
  --fis-c-other: #94a3b8;
}

.dark {
  --fis-c1: #60a5fa;
  --fis-c2: #34d399;
  --fis-c3: #fbbf24;
  --fis-c4: #a78bfa;
  --fis-c5: #f87171;
  --fis-c6: #22d3ee;
  --fis-c7: #f472b6;
  --fis-c8: #a3e635;
  --fis-c-other: #64748b;
}

.fis-charthost {
  width: 100%;
  overflow-x: auto;
}

/* Height is fixed and the viewBox scales inside it, so the chart keeps its
   proportions instead of stretching with the card. */
.fis-chart {
  display: block;
  width: 100%;
  height: 300px;
  min-width: 34rem;
}

.fis-chart__grid {
  stroke: var(--border);
  stroke-width: 1;
  shape-rendering: crispEdges;
}

.fis-chart__axis {
  stroke: var(--secondary-foreground);
  stroke-width: 1;
  opacity: 0.7;
  shape-rendering: crispEdges;
}

.fis-chart__tick,
.fis-chart__cat,
.fis-chart__legendtext,
.fis-chart__legendvalue,
.fis-chart__axistitle,
.fis-chart__barvalue,
.fis-chart__centerlabel {
  fill: var(--secondary-foreground);
  font-size: 11px;
  font-family: inherit;
}

.fis-chart__tick--y { text-anchor: end; }
.fis-chart__tick--r { text-anchor: start; }

.fis-chart__cat { text-anchor: middle; }
.fis-chart__cat--rot { text-anchor: end; }

.fis-chart__axistitle {
  text-anchor: middle;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.fis-chart__barvalue {
  text-anchor: middle;
  font-size: 10.5px;
  fill: var(--mono);
  font-variant-numeric: tabular-nums;
}

.fis-chart__legendtext { text-anchor: start; }

.fis-chart__legendvalue {
  text-anchor: end;
  fill: var(--mono);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.fis-chart__legendpct {
  fill: var(--secondary-foreground);
  font-weight: 500;
}

/* ---------- bar + cumulative line -------------------------------------- */

.fis-chart__bar { fill: var(--fis-c1); }

.fis-chart__dot {
  fill: var(--background);
  stroke: var(--fis-c1);
  stroke-width: 2;
}

/* ---------- area -------------------------------------------------------- */

.fis-chart__area {
  fill: var(--fis-c1);
  fill-opacity: 0.18;
}

.fis-chart__arealine {
  fill: none;
  stroke: var(--fis-c1);
  stroke-width: 2.5;
  stroke-linejoin: round;
}

.fis-chart__dot--area {
  stroke: var(--fis-c1);
}

/* ---------- doughnut ---------------------------------------------------- */

.fis-chart__slice {
  stroke: var(--background);
  stroke-width: 1.5;
}

.fis-chart__center {
  text-anchor: middle;
  fill: var(--mono);
  font-size: 26px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.fis-chart__centerlabel {
  text-anchor: middle;
  font-size: 11px;
}

/* ---------- palette bindings ------------------------------------------- */

.fis-chart__c1 { fill: var(--fis-c1); }
.fis-chart__c2 { fill: var(--fis-c2); }
.fis-chart__c3 { fill: var(--fis-c3); }
.fis-chart__c4 { fill: var(--fis-c4); }
.fis-chart__c5 { fill: var(--fis-c5); }
.fis-chart__c6 { fill: var(--fis-c6); }
.fis-chart__c7 { fill: var(--fis-c7); }
.fis-chart__c8 { fill: var(--fis-c8); }
.fis-chart__c-other { fill: var(--fis-c-other); }

/* A 100% bucket is one closed ring path with fill-rule:evenodd, so it colours
   by `fill` like every other slice - see ringAll() in ui/chart.js for why a
   stroked circle with fill="none" cannot work here. */

.fis-chart__swatch--area { fill: var(--fis-c1); }

/* Three selects in the card toolbar: give them a smaller floor so the header
   still fits them on one row next to the collapse button. */
.fis-filter .kt-select {
  min-width: 7.5rem;
}

/* ---------- toasts must not sit on the header ---------------------------- */

/* Toasts used to land on top of the gear / logs / theme buttons and eat every
   click for the 3.5s they were visible - see the header comment in
   app/js/ui/toast.js for why that could not be fixed from CSS while KTToast
   owned the positioning. Now this app renders them, so this is the one place
   that decides where they go: clear of the header, and the container itself is
   never a click target - only the visible toasts inside it are. */
#fis-toasts {
  top: calc(var(--fis-header-height) + 0.5rem);
  inset-inline-end: 1rem;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.5rem;
  max-width: min(24rem, 90vw);
  pointer-events: none;
}

#fis-toasts > * {
  pointer-events: auto;
}

/* "Doughnut chart" is the widest option label in the toolbar; the shared
   7.5rem floor cropped it against the select's own arrow. */
.fis-filter [data-fis-role="chart-type"] {
  min-width: 9.75rem;
}
