/* Appointments analytics.
   Chart colours are the two validated categorical slots: warning-600 for no-show and
   primary-500 for cancelled. That pair clears the lightness band, chroma floor, CVD
   separation and 3:1 contrast against a white surface — re-run the palette validator
   before substituting either. Volume is deliberately neutral: it is the context, and the
   outcome rates are the story, so they own the colour. */
.analytics--filters {
  margin-bottom: var(--rem-16);
}

/* The select carries the shared filter styling; only its width needs restating here,
   because the global `select { width: 100% }` would otherwise stretch it across the page.
   Sized to hold the longest option, "Last 12 months", without truncating. */
.analytics--filters .appointments-filters--select-wrapper {
  width: 12rem;
}

.analytics--tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--rem-12);
  margin-bottom: var(--rem-16);
}

/* The surface is the shared card's; only the stacking of label, value and note is here. */
.analytics--tile {
  display: flex;
  flex-direction: column;
  gap: var(--rem-4);
}

.analytics--tile-label {
  font-size: var(--rem-13);
  color: var(--text-information);
}

/* The hero figure: when the data is one number, typography is the chart. */
.analytics--tile-value {
  font-size: var(--rem-32);
  font-weight: var(--text-semibold);
  line-height: 1.1;
  color: var(--text-heading);
}

.analytics--tile-unit {
  font-size: var(--rem-16);
  font-weight: var(--text-medium);
  color: var(--text-information);
  margin-left: var(--rem-2);
}

.analytics--tile-note {
  font-size: var(--rem-12);
  color: var(--text-information);
}

.analytics--charts {
  display: flex;
  flex-direction: column;
  gap: var(--rem-16);
  margin-bottom: var(--rem-16);
}

.analytics--chart-mount {
  width: 100%;
}

/* frappe-charts injects its own stylesheet at runtime, AFTER this file has loaded, so an
   equal-specificity rule loses the cascade and silently does nothing. Everything below is
   therefore scoped under the mount to outrank it.

   Only the values that differ from the library's are restated — its hardcoded greys become
   our tokens. Series colours are not here at all: those are resolved from tokens by name in
   frappe_chart_controller.js, so each one has a single definition. */
.analytics--chart-mount .chart-container {
  font-family: inherit;
}

.analytics--chart-mount .chart-container .axis,
.analytics--chart-mount .chart-container .chart-label {
  fill: var(--text-information);
}

/* Recessive chrome: hairlines one shade off the surface. */
.analytics--chart-mount .chart-container .axis line,
.analytics--chart-mount .chart-container .chart-label line {
  stroke: var(--border-secondary);
}

/* A surface ring keeps the two markers apart where the lines cross. */
.analytics--chart-mount .chart-container .dataset-units circle {
  stroke: var(--surface-primary);
}

/* Identity is never colour alone: the legend is always present for two or more series. */
.analytics--chart-mount .chart-container .legend-dataset-text {
  fill: var(--text-information);
  font-weight: var(--text-semibold);
}

.analytics--chart-mount .graph-svg-tip {
  font-size: var(--rem-12);
  background: var(--neutral-900);
  border-radius: var(--radius-xs);
}

/* Set on each child rather than inherited from the tooltip. The library's own rule only
   colours the container and `strong`, so the date and the series names fall through to
   whatever the page inherits — which on a dark tooltip lands as near-black on near-black. */
.analytics--chart-mount .graph-svg-tip,
.analytics--chart-mount .graph-svg-tip .title,
.analytics--chart-mount .graph-svg-tip li {
  color: var(--neutral-300);
}

/* The values are the point of the tooltip, so they get the contrast. */
.analytics--chart-mount .graph-svg-tip strong {
  color: var(--surface-primary);
}

.analytics--chart-mount .graph-svg-tip .svg-pointer {
  border-top-color: var(--neutral-900);
}

.analytics--chart-note {
  margin-top: var(--rem-8);
  font-size: var(--rem-12);
  color: var(--text-information);
}

/* 26rem and not less: a breakdown is five columns wide, and below this the label column and
   the numbers start colliding rather than the table getting narrower. Two per row on a laptop,
   three on a wide monitor. */
.analytics--tables {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(26rem, 1fr));
  gap: var(--rem-12);
}

/* `fixed` and not the default `auto`: left to itself the browser sizes the label column to
   its longest practice name and lets the count columns run off the edge of the card, which
   is how "10 (15.2%)" ends up rendered as "10 (15.2…". Fixed widths make the label column
   the one that gives. */
.analytics--table {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
  font-size: var(--rem-13);

  th:first-child {
    width: 30%;
  }

  th:nth-child(2) {
    width: 12%;
  }

  th:nth-child(3) {
    width: 14%;
  }

  /* The two widest cells on the page are the outcome columns, which carry a count and its
     rate — "10 (76.9%)" — and clip to an ellipsis a character short if given any less. */
  th:nth-child(4),
  th:nth-child(5) {
    width: 22%;
  }

  th, td {
    padding: var(--rem-6) var(--rem-8);
    text-align: left;
    border-bottom: 1px solid var(--border-subtle);
  }

  thead th {
    font-weight: var(--text-medium);
    color: var(--text-information);
  }

  tbody th {
    font-weight: var(--text-medium);
    color: var(--text-body);
  }
}

/* Referring practices arrive with names like "Golden State Orthopedics and Spine / West Coast
   Sports Institute". The label column is the one that gives: it wraps — opting out of the
   global `th, td { text-wrap: nowrap }`, which would otherwise run it straight through the
   counts — while a count and its rate stay on one line, because "11 (16.7%)" broken across
   two is unreadable. */
.analytics--table tbody th {
  text-wrap: wrap;
  overflow-wrap: anywhere;
}

.analytics--table-number {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.analytics--table-rate {
  color: var(--text-information);
}

/* Sits with the table it qualifies, not at the foot of the page: a payer or condition row
   read without its derivation is a different claim from the one the data supports. */
.analytics--table-note {
  margin-top: var(--rem-8);
  font-size: var(--rem-12);
  color: var(--text-information);
}

/* Groups the tables by what they slice on — the clinic's own shape, who the patient is, how
   the booking was made — so a long column of tables stays navigable.

   Larger than the 1rem card titles underneath it, and not the other way round: a heading the
   same size as the things it heads reads as a caption on the first card rather than a label
   for the group. The extra space above does as much of that work as the type size. */
.analytics--section-title {
  margin-top: var(--rem-28);
  margin-bottom: var(--rem-12);
  font-size: var(--rem-20);
  font-weight: var(--text-semibold);
  color: var(--text-heading);
}

.analytics--footnote {
  margin-top: var(--rem-16);
  font-size: var(--rem-12);
  color: var(--text-information);
}

/* Sortable column headers.
   The button carries the click and keyboard affordance; the th carries the sort state, so
   `aria-sort` sits on the cell where assistive technology expects to find it. */
/* tables.css insets the first and last column with `td:first-of-type` / `td:last-of-type`.
   `:first-of-type` counts by ELEMENT TYPE, and the first cell in these rows is a
   `th scope="row"` carrying the row's name — so the inset lands on the second column
   instead, putting each value 16px right of the header above it. Reset it, then inset by
   position so the rule cannot care what element a cell happens to be. */
.analytics--table > tbody > tr > td:first-of-type {
  padding-left: var(--rem-8);
}

.analytics--table > tbody > tr > td:last-of-type {
  padding-right: var(--rem-8);
}

.analytics--table > thead > tr > *:first-child,
.analytics--table > tbody > tr > *:first-child {
  padding-left: var(--rem-16);
}

.analytics--table > thead > tr > *:last-child,
.analytics--table > tbody > tr > *:last-child {
  padding-right: var(--rem-16);
}

.analytics--table-sort {
  /* Fills its cell so the label sits at the column's left edge and the whole header is a
     click target. Safe here only because the table is `table-layout: fixed` with declared
     column widths — under auto layout a full-width button stops the browser counting the
     header when it sizes the column, and the label overflows into its neighbour. */
  display: flex;
  box-sizing: border-box;
  width: 100%;
  align-items: center;
  gap: var(--rem-4);
  /* No padding of its own. The cell is padded by the same rule that pads the body's, which
     is the only way a column's header and its values are guaranteed to start on the same
     pixel — every attempt to add the head's inset here drifted from the body by the amount
     of whichever rule fired last. */
  padding: 0;
  white-space: nowrap;
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-align: inherit;

  &:hover {
    color: var(--text-heading);
  }

  &:focus-visible {
    outline: 2px solid var(--border-focus);
    outline-offset: -2px;
    border-radius: var(--radius-xs);
  }
}

/* Font Awesome glyphs rather than an icon component: the indicator is one character that
   swaps with the sort state, and a component per header would render 45 of them a page. */
.analytics--table-sort-icon::before {
  font-family: "Font Awesome 7 Pro";
  font-weight: 900;
  font-size: var(--rem-10);
  content: "\f0dc"; /* fa-sort */
  color: var(--neutral-400);
}

/* Only the sorted column shows a direction; the rest keep the neutral both-ways glyph so
   the header reads as sortable before it is clicked. */
.analytics--table th[data-sorted="ascending"] .analytics--table-sort-icon::before {
  content: "\f0de"; /* fa-sort-up */
  color: var(--text-heading);
}

.analytics--table th[data-sorted="descending"] .analytics--table-sort-icon::before {
  content: "\f0dd"; /* fa-sort-down */
  color: var(--text-heading);
}

/* Names the sort for a screen reader without repeating it on screen. */
.analytics--table-sort-hint {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
