/* =========================================================================
   Dashboards: Dashbord A (butikk, region) and B (kjeden) in the daily,
   weekly and monthly views. The composition follows HYROX Minimalistic in
   training-health: one column of full-width panels with 24 px of air inside
   and between them, large Outfit figures, mono capitals for labels and
   filters, hairlines instead of boxes and colour only in data and in the
   7 px status squares. Type, radius and colours are the Ligo and
   Pizzabakeren tokens, so every theme in config/reporting.php works.

   Loaded on every page through resources/views/shell/head.blade.php, before
   the chart kit and report.css. Every rule is scoped to a dashboard class.
   Tokens only, no hex values. The components live in
   resources/views/components/dashboard, see Dashbord in
   docs/design-system.md.
   ========================================================================= */

/* ---------- Rhythm ---------- */

/* A dashboard page is one column: the toolbar, then the sections, each a
   heading over full-width panels. */
.dashboard {
  --dashboard-pad: 24px;
  --dashboard-gap: 24px;
  --dashboard-section-gap: 48px;

  display: grid;
  min-width: 0;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--dashboard-section-gap);
}

/* Panels from the template keep their anatomy and take the dashboard air. */
.dashboard .report-card .card-heading {
  padding: var(--dashboard-pad) var(--dashboard-pad) 12px;
}

.dashboard .report-card-body {
  padding: 0 var(--dashboard-pad) var(--dashboard-pad);
}

/* Two charts in one panel stand one under the other, set apart by air and
   one hairline. */
.dashboard .report-card-body > .report-chart + .report-chart {
  margin-top: 8px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
}

/* Status badges outside a panel are their square and mono text, as they
   are inside one. The square sits on the first line when the text wraps. */
:is(.dashboard, .dashboard-kpis) .status-badge {
  min-height: 0;
  align-items: baseline;
  padding: 0;
  border-color: transparent;
}

/* A provisional definition is quieter than a status: muted text and an
   outlined square. */
.status-badge.dashboard-provisional {
  color: var(--muted);
}

.status-badge.dashboard-provisional::before {
  border: 1px solid var(--status-color);
  background: transparent;
}

/* ---------- Explanations (x-dashboard.info) ---------- */

/* The page holds the figures; what they mean opens from a small (i) or
   from a status badge. The root holds the button and its popover. The (i)
   is muted, amber for a provisional figure, and ink under the pointer, the
   keyboard or while it is open. */
.info {
  display: inline-flex;
  min-width: 0;
  max-width: 100%;
  align-items: center;
  vertical-align: middle;
}

.info-trigger {
  position: relative;
  display: inline-grid;
  width: 18px;
  height: 18px;
  flex: none;
  place-items: center;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  color: var(--muted);
  background: transparent;
  cursor: pointer;
}

/* A provisional figure keeps an amber mark of its own: the (i) in amber
   over a faint amber disc, apart from the muted (i) of a plain figure. */
.info-trigger.is-amber {
  color: var(--amber);
}

.info-trigger.is-amber circle {
  fill: color-mix(in srgb, var(--amber) 18%, transparent);
}

.info-trigger:is(:hover, :focus-visible),
.info-trigger:has(+ .info-popover:popover-open) {
  color: var(--ink);
}

.info-trigger svg,
.info-badge .info-icon,
.info-close svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* A finger gets a larger target than the 18 px it sees. */
@media (pointer: coarse) {
  .info-trigger::after {
    position: absolute;
    inset: -12px;
    content: "";
  }
}

/* A badge that opens its explanation: what the slot holds, usually a
   status badge, then a small muted (i). The button itself has no frame. */
.info-badge {
  display: inline-flex;
  min-width: 0;
  max-width: 100%;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 0;
  border: 0;
  color: inherit;
  background: transparent;
  font: inherit;
  letter-spacing: inherit;
  text-align: left;
  text-transform: inherit;
  cursor: pointer;
}

.info-badge .info-icon {
  width: 13px;
  height: 13px;
  flex: none;
  color: var(--muted);
}

.info-badge:is(:hover, :focus-visible) .info-icon,
.info-badge:has(+ .info-popover:popover-open) .info-icon {
  color: var(--ink);
}

.info-badge:is(:hover, :focus-visible) .status-badge {
  color: var(--ink);
}

/* A trigger that is a word, such as Om signalene, reads like the quiet
   links: mono capitals, muted until the pointer reaches it. */
.info-label {
  color: var(--muted);
  font: 400 var(--fs-label)/1.5 var(--font-mono);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.info-badge:is(:hover, :focus-visible) .info-label {
  color: var(--ink);
}

/* The popover floats over the page with a stronger hairline and no
   shadow, as nothing on a dashboard has one. It inherits nothing from the
   label or the cell it sits in. Without public/js/info.js it stands in the
   middle of the window. */
.info-popover {
  position: fixed;
  inset: 0;
  width: max-content;
  max-width: min(340px, calc(100vw - 16px));
  height: fit-content;
  margin: auto;
  padding: 12px 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  color: var(--ink);
  background: var(--surface);
  font: 400 var(--fs-ui-small)/1.5 var(--font-sans);
  letter-spacing: 0;
  text-align: left;
  text-transform: none;
  white-space: normal;
  overflow-wrap: break-word;
}

.info-popover.is-placed {
  inset: auto;
  margin: 0;
}

/* Scoped twice, since .control-main section p in ligo-shell.css sets the
   top margin of every paragraph in a section. */
.info .info-popover > * {
  margin: 0;
}

.info .info-popover > * + * {
  margin-top: 8px;
}

.info-popover-link {
  font-size: var(--fs-ui-small);
}

.info-popover-title {
  display: block;
  font-weight: 500;
}

.info-popover a {
  color: var(--ink);
  text-decoration: underline 1px;
  text-decoration-color: var(--border-strong);
  text-underline-offset: 3px;
}

.info-popover a:is(:hover, :focus-visible) {
  text-decoration-color: currentColor;
}

.info-popover .info-muted {
  color: var(--muted);
}

.info-popover ul {
  padding-left: 18px;
}

/* A longer explanation is a dialog in the middle of the window, over a
   veil of the page, with a close button. */
.info-popover.is-modal {
  display: none;
  width: min(680px, calc(100vw - 32px));
  max-width: none;
  max-height: min(820px, calc(100dvh - 48px));
  padding: 0;
  border-radius: var(--radius-lg);
}

.info-popover.is-modal:popover-open {
  display: flex;
  flex-direction: column;
}

.info .info-popover.is-modal > * + * {
  margin-top: 0;
}

.info-popover.is-modal::backdrop {
  background: color-mix(in srgb, var(--bg) 72%, transparent);
}

.info-popover-head {
  display: flex;
  flex-shrink: 0;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border);
}

.info-popover-head h2 {
  margin: 0;
  color: var(--ink);
  font: 500 calc(var(--fs-label) + 8px)/1.25 var(--font-sans);
}

.info-close {
  display: grid;
  width: 32px;
  height: 32px;
  flex: none;
  place-items: center;
  margin: -6px -8px 0 0;
  padding: 0;
  border: 0;
  border-radius: var(--radius-md);
  color: var(--muted);
  background: transparent;
  cursor: pointer;
}

.info-close:is(:hover, :focus-visible) {
  color: var(--ink);
}

.info-popover-body {
  display: grid;
  gap: 14px;
  padding: 16px 20px 20px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.info-popover-body > * {
  margin: 0;
}

/* A screen reader reads it, nobody sees it. */
.dashboard-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  border: 0;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- Toolbar: period and comparison ---------- */

/* The controls stand in one row under the page title: the period on the
   left, the comparison after its short «Mot» on the right. */
.dashboard-toolbar {
  display: flex;
  min-width: 0;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 48px;
}

.dashboard-control {
  display: flex;
  min-width: 0;
  max-width: 100%;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 14px;
}

.dashboard-control-label {
  color: var(--muted);
  font: 400 var(--fs-label)/1.5 var(--font-mono);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

.dashboard-control-row {
  display: flex;
  min-width: 0;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 24px;
}

/* Options are mono capitals without a box. The chosen one is ink with a
   1 px underline, the others muted until hover or focus. */
.dashboard-switch {
  display: flex;
  min-width: 0;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 20px;
}

.dashboard-switch a {
  display: inline-flex;
  min-width: 0;
  min-height: 34px;
  align-items: center;
  color: var(--muted);
  font: 400 var(--fs-label)/1.4 var(--font-mono);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.dashboard-switch a:is(:hover, :focus-visible) {
  color: var(--ink);
}

.dashboard-switch a[aria-current] {
  color: var(--ink);
  text-decoration: underline 1px;
  text-underline-offset: 4px;
}

/* The period stepper is the one control with a ring at rest: a hairline,
   no fill, the period in ink and muted arrows that turn ink. */
.dashboard-stepper {
  display: inline-flex;
  min-width: 0;
  max-width: 100%;
  min-height: 34px;
  align-items: center;
  gap: 4px;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--ink);
  font: 400 var(--fs-label)/1.4 var(--font-mono);
  font-variant-numeric: tabular-nums;
}

.dashboard-stepper-label {
  min-width: 0;
  padding: 4px 6px;
  text-align: center;
  overflow-wrap: anywhere;
}

.dashboard-step {
  display: grid;
  width: 28px;
  height: 28px;
  flex: none;
  place-items: center;
  border-radius: var(--radius-md);
  color: var(--muted);
}

a.dashboard-step:is(:hover, :focus-visible) {
  color: var(--ink);
}

.dashboard-step.is-disabled {
  opacity: 0.35;
}

.dashboard-step svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---------- Scope trail ---------- */

.dashboard-trail ol {
  display: flex;
  min-width: 0;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 0;
  margin: 0;
  padding: 0;
  list-style: none;
  font: 400 var(--fs-label)/1.5 var(--font-mono);
}

.dashboard-trail li {
  min-width: 0;
  overflow-wrap: anywhere;
}

.dashboard-trail li + li::before {
  margin: 0 10px;
  color: var(--muted);
  content: "›" / "";
}

.dashboard-trail a {
  color: var(--muted);
}

.dashboard-trail a:is(:hover, :focus-visible) {
  color: var(--ink);
  text-decoration: underline 1px;
  text-underline-offset: 4px;
}

.dashboard-trail [aria-current] {
  color: var(--ink);
}

/* ---------- Sections ---------- */

/* A section is its name over its panels. Size and air set it apart, so the
   panel line under it is the only rule. */
.dashboard-section {
  display: grid;
  min-width: 0;
  grid-template-columns: minmax(0, 1fr);
  gap: 14px;
  scroll-margin-top: 20px;
}

/* The heading is the name, then its marks: a provisional definition, a
   note on the figures, or the status of a section that only waits. */
.dashboard-section-heading {
  display: flex;
  min-width: 0;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 20px;
}

.dashboard-section-heading h2 {
  min-width: 0;
  margin: 0;
  color: var(--ink);
  font: 500 calc(var(--fs-label) + 8px)/1.25 var(--font-sans);
  letter-spacing: -0.01em;
  overflow-wrap: break-word;
}

.dashboard-section-meta {
  display: flex;
  min-width: 0;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 16px;
  color: var(--muted);
  font: 400 var(--fs-label)/1.5 var(--font-mono);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}

/* Sections that only wait follow each other closer, as one short list. */
.dashboard > .dashboard-section.is-waiting + .dashboard-section.is-waiting {
  margin-top: calc(20px - var(--dashboard-section-gap));
}

.dashboard-section-body {
  display: grid;
  min-width: 0;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--dashboard-gap);
}

/* ---------- Key figures ---------- */

/* One panel holds the figures of a section: the hero on top, the others in
   columns under it, each set apart by one hairline over it, like the small
   multiples of the chart kit. No figure has a box of its own. */
.dashboard-kpis {
  display: grid;
  min-width: 0;
  grid-template-columns: minmax(0, 1fr);
  gap: 36px;
  padding: var(--dashboard-pad, 24px);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  container-type: inline-size;
}

.dashboard-kpi-grid {
  display: grid;
  min-width: 0;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 184px), 1fr));
  column-gap: 32px;
  margin-bottom: -28px;
}

.dashboard-kpi {
  display: grid;
  min-width: 0;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  margin: 0;
}

.dashboard-kpi > * {
  min-width: 0;
  margin: 0;
}

/* In the grid every figure shares the rows of its neighbours, so values
   and changes line up even when one label wraps. */
.dashboard-kpi-grid > .dashboard-kpi {
  grid-row: span 4;
  grid-template-rows: subgrid;
  row-gap: 0;
  padding: 14px 0 28px;
  border-top: 1px solid var(--border);
}

.dashboard-kpi-label {
  display: flex;
  grid-row: 1;
  flex-wrap: wrap;
  align-items: center;
  align-self: start;
  gap: 2px 6px;
  color: var(--muted);
  font: 400 var(--fs-label)/1.5 var(--font-mono);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.dashboard-kpi-value {
  grid-row: 2;
  align-self: end;
  margin-top: 10px;
  color: var(--ink);
  font: 500 var(--fs-figure)/1.1 var(--font-display);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  overflow-wrap: anywhere;
}

/* Digit groups are held together by no-break spaces. Only a figure wider
   than its column breaks, so it never runs into the next one. */
.dashboard-kpi-value .figure-unit {
  margin-left: 2px;
}

.dashboard-figure.is-empty {
  color: var(--muted);
}

.dashboard-kpi-value.is-pending {
  font: inherit;
  letter-spacing: 0;
}

/* The change and «mot» the comparison share one line, and wrap under
   each other in a narrow column. */
.dashboard-kpi-delta {
  display: flex;
  grid-row: 3;
  min-width: 0;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  margin-top: 8px;
}

.dashboard-kpi-delta .viz-delta {
  justify-content: flex-start;
}

.dashboard-kpi-compare {
  min-width: 0;
  color: var(--muted);
  font-size: var(--fs-ui-small);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}

.dashboard-kpi-spark {
  grid-row: 4;
  align-self: end;
  margin-top: 14px;
}

/* A change that is neither good nor bad keeps its arrow in the muted
   colour. Good and bad come from the chart kit (--viz-good, --viz-bad). */
.viz-delta.is-neutral {
  color: var(--muted);
}

/* The hero is the answer of the section: a figure larger than the page
   title, its change and comparison, and the trend beside it. */
.dashboard-kpi.is-hero {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 48px;
}

.dashboard-kpi.is-hero > * {
  grid-column: 1;
}

.dashboard-kpi.is-hero .dashboard-kpi-value {
  margin-top: 12px;
  font-size: clamp(38px, 5cqi, 54px);
  line-height: 1.05;
  letter-spacing: -0.03em;
}

.dashboard-kpi.is-hero .dashboard-kpi-value .figure-unit {
  margin-left: 4px;
  font-size: calc(var(--fs-ui-small) + 3px);
}

.dashboard-kpi.is-hero .dashboard-kpi-delta {
  margin-top: 12px;
}

.dashboard-kpi.is-hero .dashboard-kpi-delta .viz-delta {
  font-size: calc(var(--fs-label) + 2px);
}

.dashboard-kpi.is-hero .dashboard-kpi-compare {
  font-size: var(--fs-ui-body);
}

.dashboard-kpi.is-hero .dashboard-kpi-spark {
  grid-column: 2;
  grid-row: 1 / 4;
  align-self: center;
  margin-top: 0;
}

.dashboard-kpi.is-hero .dashboard-trend {
  --trend-height: 72px;
}

/* ---------- Trend line ---------- */

/* A 1.5 px line in the series colour over a faint tint of it, the newest
   value as a 7 px point with the surface inside, as in the chart kit. */
.dashboard-trend {
  --trend-color: var(--viz-1);
  --trend-height: 28px;

  display: grid;
  min-width: 0;
  gap: 6px;
  margin: 0;
}

.dashboard-trend-body {
  display: grid;
  min-width: 0;
  grid-template-columns: minmax(0, 1fr);
}

.dashboard-trend-plot {
  position: relative;
  min-width: 0;
  height: var(--trend-height);
}

.dashboard-trend-plot svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.dashboard-trend-line {
  fill: none;
  stroke: var(--trend-color);
  stroke-width: var(--chart-line-width, 1.5);
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.dashboard-trend-area {
  fill: color-mix(in srgb, var(--trend-color) var(--chart-area, 5%), transparent);
  stroke: none;
}

.dashboard-trend-end {
  position: absolute;
  width: var(--chart-mark-size, 7px);
  height: var(--chart-mark-size, 7px);
  box-sizing: border-box;
  border: 1px solid var(--trend-color);
  border-radius: 50%;
  background: var(--surface);
  transform: translate(-50%, -50%);
}

/* ---------- Ranking ---------- */

/* A drilldown table: the name links to the next level, the figures are
   right aligned and the share carries an outlined bar. The text lines up
   with the panel heading. A table wider than its box is stacked by
   report-tables.js. */
.dashboard-ranking .control-table :is(th, td):first-child {
  padding-left: 0;
}

.dashboard-ranking .control-table :is(th, td):last-child {
  padding-right: 0;
}

/* A name is text, not a label: the UI face in ink, wrapping when long. */
.dashboard-ranking .control-table tbody th {
  color: var(--ink);
  font: 400 var(--fs-ui-small)/1.45 var(--font-sans);
  letter-spacing: 0;
  text-transform: none;
  white-space: normal;
  overflow-wrap: anywhere;
}

/* The link to the next level keeps a quiet hairline under it, ink under
   the pointer. */
.dashboard-ranking .control-table tbody th a {
  color: var(--ink);
  font: inherit;
  text-decoration: underline 1px;
  text-decoration-color: var(--border-strong);
  text-underline-offset: 4px;
}

.dashboard-ranking .control-table tbody th a:is(:hover, :focus-visible) {
  color: var(--ink);
  text-decoration-color: currentColor;
}

.dashboard-ranking .control-table tfoot :is(th, td) {
  padding-top: 12px;
  padding-bottom: 10px;
  border-top: 1px solid var(--border-strong);
  color: var(--ink);
  font-size: var(--fs-ui-small);
  font-weight: 500;
}

.dashboard-ranking .control-table tfoot th {
  font: 400 var(--fs-label)/1.4 var(--font-mono);
  letter-spacing: var(--tracking-label);
  text-align: left;
  text-transform: uppercase;
}

.dashboard-ranking .control-table td .viz-delta {
  justify-content: flex-end;
}

/* report-tables.js stacks the rows of the body; the total row follows them
   as one more block under a stronger hairline. */
.table-scroll.is-stacked.dashboard-ranking tfoot {
  display: block;
}

.table-scroll.is-stacked.dashboard-ranking tfoot tr {
  border-top: 1px solid var(--border-strong);
  border-bottom: 0;
}

.table-scroll.is-stacked.dashboard-ranking tfoot :is(th, td) {
  padding: 2px 0;
  border-top: 0;
}

.dashboard-rank {
  display: inline-block;
  min-width: 2ch;
  margin-right: 12px;
  color: var(--muted);
  font: 400 var(--fs-label)/1.45 var(--font-mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* A long ranking shows its first rows, and the toggle under it opens the
   rest without JavaScript. The toggle reads like Vis som tabell under a
   chart. */
.dashboard-ranking-group {
  display: grid;
  min-width: 0;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
}

.dashboard-ranking-group:has(.dashboard-ranking-more:not([open])) .dashboard-ranking-extra {
  display: none;
}

/* The toggle and what stands beside it, such as the link to Butikker. */
.dashboard-ranking-footer {
  display: flex;
  min-width: 0;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 24px;
}

/* A link to another page reads like the link to Datastatus: muted with a
   quiet underline, ink under the pointer. */
.dashboard-ranking-link {
  color: var(--muted);
  font: 400 var(--fs-label)/1.5 var(--font-mono);
  letter-spacing: var(--tracking-label);
  text-decoration: underline 1px;
  text-decoration-color: var(--border-strong);
  text-transform: uppercase;
  text-underline-offset: 4px;
}

.dashboard-ranking-link:is(:hover, :focus-visible) {
  color: var(--ink);
  text-decoration-color: currentColor;
}

.dashboard-ranking-more > summary {
  width: fit-content;
  color: var(--muted);
  font: 400 var(--fs-label)/1.5 var(--font-mono);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  cursor: pointer;
}

.dashboard-ranking-more > summary:is(:hover, :focus-visible) {
  color: var(--ink);
}

.dashboard-ranking-more[open] .dashboard-ranking-more-closed,
.dashboard-ranking-more:not([open]) .dashboard-ranking-more-open {
  display: none;
}

.dashboard-share {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
}

/* The share is an outlined bar on a hairline that stands for the whole. */
.dashboard-share-track {
  position: relative;
  width: 72px;
  height: 11px;
  flex: none;
  border-bottom: 1px solid var(--chart-axis, var(--border));
}

.dashboard-share-bar {
  position: absolute;
  top: 0;
  bottom: -1px;
  left: 0;
  width: var(--share);
  min-width: 2px;
  box-sizing: border-box;
  border: 1px solid var(--viz-1);
  background: color-mix(in srgb, var(--viz-1) var(--chart-tint, 10%), transparent);
}

/* ---------- Pending and empty states ---------- */

/* A state without figures is its status badge, and the reason opens from
   it. Only «Ikke tilgjengelig» keeps its line, since it is news and not a
   state. The page-wide state uses the template's empty panel. */
.dashboard-pending:not(.info) {
  display: grid;
  min-width: 0;
  justify-items: start;
  gap: 6px;
}

.dashboard-pending:not(.info) > p {
  max-width: 72ch;
  margin: 0;
  color: var(--muted);
  font-size: var(--fs-ui-body);
}

.empty-panel.dashboard-pending-panel {
  padding: var(--dashboard-pad, 24px);
}

/* A table or chart without rows is one muted line, as an empty chart in
   training-health. */
.dashboard-empty-line {
  margin: 0;
  color: var(--muted);
  font: 400 var(--fs-label)/1.5 var(--font-mono);
}

/* ---------- Lazy sections ---------- */

/* A section that loads after the page (App\Livewire\Dashboards) keeps the
   rhythm of the section body around its panels. */
.dashboard-lazy {
  display: grid;
  min-width: 0;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--dashboard-gap, 24px);
}

/* While it loads, the section holds the room it will take, so the page
   does not jump, and its status square breathes. */
.dashboard-loading {
  display: grid;
  min-height: var(--loading-height, 120px);
  align-content: center;
  justify-items: start;
}

.dashboard-loading .status-badge::before {
  animation: dashboard-loading 1.6s ease-in-out infinite;
}

@keyframes dashboard-loading {
  50% {
    opacity: 0.3;
  }
}

@media (prefers-reduced-motion: reduce) {
  .dashboard-loading .status-badge::before {
    animation: none;
  }
}

/* ---------- Page status ---------- */

/* The quiet line under the title and the trail: the data status line
   (data-status.css) on the dashboards, a count or a time on other pages.
   A block, since the data status has a notice that opens. It takes a row
   of its own in the meta row. */
.dashboard-status {
  flex: 1 1 100%;
  min-width: 0;
  margin: 0;
  color: var(--muted);
  font: 400 var(--fs-label)/1.5 var(--font-mono);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

/* ---------- Design reference ---------- */

/* Only on /designreferanse: the dashboard part under the template
   components, and the example page with its title as a heading. */
.reference-dashboard {
  display: grid;
  min-width: 0;
  grid-template-columns: minmax(0, 1fr);
  gap: 64px;
  margin-top: 64px;
}

.reference-part {
  display: grid;
  gap: 8px;
  padding-top: 24px;
  border-top: 1px solid var(--border);
}

.reference-part h2,
.reference-page-title {
  margin: 0;
  color: var(--ink);
  font: 500 var(--fs-title)/1.15 var(--font-display);
  letter-spacing: -0.025em;
  overflow-wrap: break-word;
}

.reference-part p {
  max-width: 72ch;
  margin: 0;
  color: var(--muted);
  font-size: var(--fs-ui-body);
}

.reference-variants {
  display: grid;
  min-width: 0;
  grid-template-columns: minmax(0, 1fr);
  gap: 32px;
}

.reference-variant {
  display: grid;
  min-width: 0;
  gap: 12px;
}

.reference-caption {
  color: var(--muted);
  font-size: var(--fs-ui-small);
}

.reference-example {
  display: grid;
  min-width: 0;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
}

/* ---------- Narrow screens ---------- */

/* In a narrow panel the trend goes under the hero figure. */
@container (max-width: 760px) {
  .dashboard-kpi.is-hero {
    grid-template-columns: minmax(0, 1fr);
  }

  .dashboard-kpi.is-hero .dashboard-kpi-spark {
    grid-column: 1;
    grid-row: 4;
    margin-top: 20px;
  }

  .dashboard-kpi.is-hero .dashboard-trend {
    --trend-height: 56px;
  }
}

@media (max-width: 620px) {
  .dashboard {
    --dashboard-pad: 16px;
    --dashboard-gap: 16px;
    --dashboard-section-gap: 40px;
  }

  .dashboard-toolbar {
    gap: 18px;
  }

  .dashboard-toolbar > .dashboard-control {
    flex: 1 1 100%;
  }

  .dashboard-stepper {
    display: flex;
    width: 100%;
    justify-content: space-between;
  }

  .dashboard-kpis {
    gap: 28px;
  }

  .dashboard-kpi-grid {
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 132px), 1fr));
    column-gap: 16px;
    margin-bottom: -22px;
  }

  .dashboard-kpi-grid > .dashboard-kpi {
    padding-bottom: 22px;
  }

  .reference-dashboard {
    gap: 48px;
    margin-top: 48px;
  }
}

/* Touch targets: the options and arrows keep 44 and 40 px without making
   the toolbar taller. */
@media (max-width: 720px), (pointer: coarse) {
  .dashboard-switch a {
    min-height: 44px;
  }

  .dashboard-step {
    width: 40px;
    height: 40px;
    margin-block: -4px;
  }
}
