/* Panels, KPIs, tables, buttons and status pills. */

/* ---- Panel ---- */

.hx-panel {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  background: var(--hx-surface);
  border: 1px solid var(--hx-line);
  border-radius: var(--hx-radius);
  overflow: hidden;
}

.hx-panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--hx-space-3);
  padding: var(--hx-space-3) var(--hx-space-4);
  border-bottom: 1px solid var(--hx-line-faint);
  flex: none;
}

/* Quiet secondary text beside a panel title (a fixed description of what the panel shows, never a
   value): the title's size but sentence case, untracked and dimmer, so it reads as subordinate; it is
   clipped before the title if the panel is narrow. */
.hx-panel__meta {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--hx-fs-micro);
  color: var(--hx-text-dim);
}

/* Workspace contract: a panel is bounded by the operator's chosen GridStack geometry, never by its
   content (grid.js). Horizontal overflow always clips, never scrolls (no horizontal scrollbar exists
   anywhere in a panel); vertical overflow scrolls inside the panel instead of growing it. */
.hx-panel__body {
  flex: 1 1 auto;
  min-height: 0;
  padding: var(--hx-space-4);
  overflow-y: auto;
  overflow-x: hidden;
}

.hx-panel__body--flush {
  padding: 0;
}

/* Table/list panels: the body itself does not scroll. It is a plain (non-scrolling) flex column so
   fixed chrome (a title is already outside it, in .hx-panel__head; a future controls/filter row would
   be a flex:none child here) stays above the row viewport. Only .hx-panel__scroll scrolls, and only
   vertically: the column headings (a sticky <thead>) stay visible while the rows beneath them scroll. */
.hx-panel__body--list {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.hx-panel__scroll {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

/* Opaque, not --hx-surface: a sticky header must fully occlude rows scrolling underneath it, which a
   translucent surface does not (found in testing the sticky header). */
.hx-panel__scroll thead th {
  position: sticky;
  top: 0;
  background: var(--hx-surface-opaque);
  z-index: 1;
}

/* Used only while measuring a tile's natural content height (see grid.js): the panel takes the height
   of its content instead of filling the grid cell. This feeds only the INITIAL/default and Reset Layout
   size; it is never an ongoing minimum (see grid.js's workspace-contract comment). */
.hx-panel--natural {
  height: auto;
}

.hx-panel--natural > .hx-panel__body {
  flex: none;
  overflow: hidden;
}

.hx-panel--natural .hx-panel__scroll {
  flex: none;
  overflow: hidden;
}

/* ---- Honest empty / unavailable states ---- */

.hx-na {
  color: var(--hx-text-muted);
}

.hx-empty {
  padding: var(--hx-space-5) var(--hx-space-4);
  text-align: center;
  color: var(--hx-text-muted);
}

.hx-empty__title {
  display: block;
  font-weight: 600;
  color: var(--hx-text);
  margin-bottom: var(--hx-space-1);
}

.hx-note {
  color: var(--hx-text-muted);
  font-size: var(--hx-fs-small);
}

/* ---- Label / value rows ---- */

.hx-rows {
  margin: 0;
  display: grid;
  gap: var(--hx-space-3);
}

.hx-rows > div {
  display: grid;
  gap: 2px;
}

.hx-rows dt {
  font-size: var(--hx-fs-small);
  color: var(--hx-text-muted);
}

.hx-rows dt .hx-note {
  display: block;
}

.hx-rows dd {
  margin: 0;
  min-width: 0;
  font-weight: 600;
}

.hx-rows--inline > div {
  grid-template-columns: minmax(7.5rem, 1fr) auto;
  align-items: center;
  gap: var(--hx-space-3);
  padding-bottom: var(--hx-space-3);
  border-bottom: 1px solid var(--hx-line-faint);
}

.hx-rows--inline > div:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

/* ---- Collection panel ---- */

.hx-collection {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--hx-space-5);
  height: 100%;
}

.hx-collection__state {
  display: flex;
  align-items: center;
  gap: var(--hx-space-4);
  flex: 1 1 18rem;
}

.hx-collection__badge {
  display: grid;
  place-items: center;
  width: 84px;
  height: 84px;
  flex: none;
  border-radius: 50%;
  border: 2px dashed var(--hx-line-strong);
  color: var(--hx-text-muted);
}

.hx-collection__badge .hx-icon {
  width: 38px;
  height: 38px;
  stroke-width: 1.4;
}

.hx-collection__title {
  font-size: var(--hx-fs-hero);
  font-weight: 600;
  line-height: 1.1;
}

/* The badge summarizes requested state + observed runtime with a glyph and the same border-style
   language as the header pills (solid = settled, double = failure, dotted = in transition, dashed =
   unknown), so it never depends on colour. */
.hx-collection__badge[data-state="ok"] {
  border-style: solid;
  color: var(--hx-ok);
}

.hx-collection__badge[data-state="warn"] {
  border-style: solid;
  color: var(--hx-warn);
}

.hx-collection__badge[data-state="error"] {
  border-style: double;
  border-width: 4px;
  color: var(--hx-error);
}

.hx-collection__badge[data-state="paused"] {
  border-style: solid;
  color: var(--hx-neutral);
}

.hx-collection__badge[data-state="checking"] {
  border-style: dotted;
  color: var(--hx-neutral);
}

.hx-collection__label {
  color: var(--hx-text-dim);
}

.hx-collection__runtime {
  display: flex;
  align-items: center;
  gap: var(--hx-space-2);
  margin-top: var(--hx-space-2);
}

.hx-collection__glyph,
.hx-collection__btnglyph {
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 16px;
  flex: none;
}

.hx-collection__glyph .hx-icon,
.hx-collection__btnglyph .hx-icon {
  width: 16px;
  height: 16px;
}

.hx-btn[aria-busy="true"] {
  cursor: progress;
}

.hx-collection__info {
  flex: 1 1 18rem;
  padding-left: var(--hx-space-5);
  border-left: 1px solid var(--hx-line-faint);
}

/* Label above value here: the per-device values need the width. */
.hx-collection__info > div {
  grid-template-columns: minmax(0, 1fr);
  gap: var(--hx-space-2);
}

.hx-collection__info .hx-devlist {
  justify-content: start;
}

.hx-collection__control {
  flex: 0 1 18rem;
  display: grid;
  gap: var(--hx-space-2);
  justify-items: stretch;
  text-align: center;
}

/* ---- KPI ---- */

.hx-kpi {
  display: flex;
  align-items: center;
  gap: var(--hx-space-4);
  height: 100%;
}

.hx-kpi > div {
  min-width: 0;
}

.hx-kpi__icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  flex: none;
  border-radius: var(--hx-radius-sm);
  border: 1px solid var(--hx-line-strong);
  color: var(--hx-text-muted);
}

.hx-kpi__icon .hx-icon {
  width: 28px;
  height: 28px;
}

.hx-kpi__value {
  font-size: var(--hx-fs-kpi);
  font-weight: 600;
  line-height: 1.15;
}

.hx-kpi__value--na {
  font-size: 1.125rem;
  font-weight: 500;
  color: var(--hx-text-muted);
}

.hx-kpi__caption {
  font-size: var(--hx-fs-small);
  color: var(--hx-text-muted);
}

/* ---- Tables ---- */

.hx-table {
  width: 100%;
  font-size: var(--hx-fs-small);
  /* Collapsed borders (default 'separate' leaves gaps between cells): a sticky <thead> covers each
     <th> cell individually, so a gap between cells would let scrolled rows show through the seam. */
  border-collapse: collapse;
}

.hx-table th {
  padding: var(--hx-space-2) var(--hx-space-3);
  text-align: left;
  font-size: var(--hx-fs-micro);
  font-weight: 600;
  letter-spacing: var(--hx-track-micro);
  text-transform: uppercase;
  color: var(--hx-text-dim);
  border-bottom: 1px solid var(--hx-line);
}

.hx-table td {
  padding: var(--hx-space-2) var(--hx-space-3);
  border-bottom: 1px solid var(--hx-line-faint);
}

/* ---- Buttons ---- */

.hx-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--hx-space-2);
  padding: 10px var(--hx-space-4);
  color: var(--hx-text);
  background: rgba(120, 155, 245, 0.12);
  border: 1px solid var(--hx-line-strong);
  border-radius: var(--hx-radius-sm);
  cursor: pointer;
}

.hx-btn:hover:not(:disabled):not([aria-disabled="true"]) {
  background: rgba(120, 155, 245, 0.24);
}

/* Unavailable but discoverable: aria-disabled keeps the control focusable and announced as
   unavailable, while a dashed outline (not colour) shows it is not operational. */
.hx-btn:disabled,
.hx-btn[aria-disabled="true"] {
  color: var(--hx-text-muted);
  background: transparent;
  border-style: dashed;
  cursor: not-allowed;
}

.hx-btn--large {
  padding: 16px var(--hx-space-5);
  font-size: 1.125rem;
  font-weight: 600;
}

.hx-btn--quiet {
  padding: 6px var(--hx-space-3);
  font-size: var(--hx-fs-small);
}

.hx-btn .hx-icon {
  width: 18px;
  height: 18px;
}

/* ---- Status pills -------------------------------------------------------------------------
   Every state carries a GLYPH and TEXT; the border style differs as well, and colour only
   reinforces. Read in grayscale, ok/warn/error/paused/unknown/checking are all distinguishable
   without colour. */

.hx-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--hx-space-2);
  padding: 6px 12px;
  border: 1px solid var(--hx-line-strong);
  border-radius: var(--hx-radius-pill);
  background: var(--hx-surface-sunken);
  font-size: var(--hx-fs-micro);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--hx-text);
}

.hx-pill__glyph {
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 16px;
}

.hx-pill__glyph .hx-icon {
  width: 16px;
  height: 16px;
  stroke-width: 2.2;
}

.hx-pill__label {
  color: var(--hx-text-muted);
}

.hx-pill[data-state="ok"] {
  border-style: solid;
  color: var(--hx-ok);
}

.hx-pill[data-state="warn"] {
  border-style: solid;
  border-width: 2px;
  color: var(--hx-warn);
}

.hx-pill[data-state="error"] {
  border-style: double;
  border-width: 3px;
  color: var(--hx-error);
}

.hx-pill[data-state="paused"] {
  border-style: solid;
  border-width: 2px;
  color: var(--hx-neutral);
}

.hx-pill[data-state="unknown"] {
  border-style: dashed;
  color: var(--hx-neutral);
}

.hx-pill[data-state="checking"] {
  border-style: dotted;
  border-width: 2px;
  color: var(--hx-neutral);
}

.hx-pill[data-state="checking"] .hx-pill__glyph {
  animation: hx-blink 1.6s ease-in-out infinite;
}

@keyframes hx-blink {
  50% {
    opacity: 0.35;
  }
}

/* Header pills shrink in two stages so status is never pushed off-screen (the tagline is dropped first,
   in shell.css). Below 1240px the service NAME is visually hidden (its icon, the state glyph and the state
   text remain; the name stays for screen readers and in the tooltip). Below 1040px only the icon and glyph
   remain visually; the name and state text stay for screen readers and in the tooltip. */
@media (max-width: 1239px) {
  .hx-header .hx-pill__label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }
}

@media (max-width: 1039px) {
  .hx-header .hx-pill {
    padding: 8px;
  }

  .hx-header .hx-pill__text {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }
}

@media (max-width: 520px) {
  .hx-clock__date {
    display: none;
  }
}

/* Windows high-contrast and increased-contrast preferences keep every border visible. */
@media (forced-colors: active) {
  .hx-panel,
  .hx-pill,
  .hx-btn,
  .hx-kpi__icon,
  .hx-collection__badge,
  .hx-panel__scroll thead th {
    border-color: CanvasText;
  }
}

@media (prefers-contrast: more) {
  :root {
    --hx-line: rgba(200, 215, 255, 0.55);
    --hx-line-strong: rgba(220, 230, 255, 0.8);
    --hx-text-dim: #b6c2e0;
  }
}

.hx-pill__service {
  display: inline-grid;
  place-items: center;
  width: 18px;
  height: 18px;
  color: var(--hx-text-muted);
}

.hx-pill__service .hx-icon {
  width: 18px;
  height: 18px;
  stroke-width: 1.7;
}

/* ---- Per-device values, page notice, as-of line and definitions (Overview state instruments) ---- */

.hx-devlist {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: max-content max-content; /* device labels share one column */
  justify-content: end;
  gap: var(--hx-space-2) var(--hx-space-3);
}

.hx-devlist__row {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: 1 / -1;
  align-items: baseline;
}

.hx-devlist__id {
  font-size: var(--hx-fs-micro);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--hx-text-muted);
}

.hx-devlist__instant,
.hx-devlist__text {
  font-variant-numeric: tabular-nums;
}

.hx-devlist__age {
  margin-left: var(--hx-space-2);
  font-size: var(--hx-fs-small);
  font-weight: 400;
  color: var(--hx-text-muted);
}

/* In a KPI tile the room is narrow: one column, each row wraps instead of being clipped. */
.hx-devlist--kpi {
  grid-template-columns: minmax(0, 1fr);
  justify-content: start;
}

.hx-devlist--kpi .hx-devlist__row {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--hx-space-3);
  overflow-wrap: anywhere;
}

.hx-devlist--kpi .hx-devlist__instant,
.hx-devlist--kpi .hx-devlist__text {
  font-size: 1rem;
  font-weight: 600;
}

.hx-asof {
  margin-top: var(--hx-space-1);
  font-size: var(--hx-fs-small);
  color: var(--hx-text-muted);
  font-variant-numeric: tabular-nums;
}

.hx-asof[hidden],
.hx-notice[hidden] {
  display: none;
}

/* The notice carries a glyph, text and a dashed border: never colour alone. */
.hx-notice {
  display: flex;
  align-items: center;
  gap: var(--hx-space-3);
  margin-top: var(--hx-space-2);
  padding: var(--hx-space-2) var(--hx-space-3);
  border: 2px dashed var(--hx-line-strong);
  border-radius: var(--hx-radius-sm);
}

.hx-defs {
  margin-top: var(--hx-space-5);
  padding: var(--hx-space-3) var(--hx-space-4);
  border: 1px solid var(--hx-line-faint);
  border-radius: var(--hx-radius);
}

.hx-defs summary {
  cursor: pointer;
  font-size: var(--hx-fs-micro);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.hx-defs dl {
  display: grid;
  gap: var(--hx-space-3);
  margin: var(--hx-space-3) 0 0;
}

.hx-defs dt {
  font-weight: 600;
}

.hx-defs dd {
  margin: 0;
  color: var(--hx-text-muted);
  max-width: 70ch;
}

/* ---- Recent runs table ---- */

.hx-runs__time,
.hx-runs__facts {
  font-variant-numeric: tabular-nums;
}

.hx-runs__kind {
  white-space: nowrap;
}

.hx-runs__type {
  display: block;
  font-size: var(--hx-fs-small);
  color: var(--hx-text-muted);
}

/* The status carries a glyph AND text (and never colour alone). */
.hx-runs__glyph {
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 16px;
  margin-right: var(--hx-space-2);
  vertical-align: text-bottom;
}

.hx-runs__glyph .hx-icon {
  width: 16px;
  height: 16px;
}

/* The identifying row and its facts line read as one entry: no rule between them. */
.hx-runs__main > td {
  border-bottom: 0;
  padding-bottom: var(--hx-space-1);
}

.hx-runs__factsrow > td {
  padding-top: 0;
}

.hx-runs__facts {
  color: var(--hx-text-muted);
  font-size: var(--hx-fs-small);
}

.hx-runs__factslabel {
  margin-right: var(--hx-space-2);
  font-size: var(--hx-fs-micro);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* ---- Recent observations table ---- */

/* A Location's heading row: the name, then the timezone its times are shown in (as text, not colour). */
.hx-obs__loc > th {
  padding-top: var(--hx-space-3);
  font-size: var(--hx-fs-small);
  letter-spacing: 0;
  text-transform: none;
  color: var(--hx-text);
}

.hx-obs__zone {
  margin-left: var(--hx-space-3);
  font-weight: 400;
  color: var(--hx-text-muted);
}

.hx-obs__time,
.hx-obs__num {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.hx-obs__device {
  white-space: nowrap;
  color: var(--hx-text-muted);
}

.hx-obs__sub {
  display: block;
  font-size: var(--hx-fs-micro);
  color: var(--hx-text-muted);
}

.hx-obs__missing {
  color: var(--hx-text-dim);
}

/* ---- Sign-in page (ADR-0011): the Hundchen panel language, one compact column, no script ---- */

.hx-login-page {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: var(--hx-space-4);
}

.hx-login {
  width: min(100%, 24rem);
  display: grid;
  gap: var(--hx-space-4);
}

.hx-login__brand {
  text-align: center;
}

.hx-login__name {
  font-size: 1.375rem;
  font-weight: 600;
  letter-spacing: 0.32em;
}

.hx-login__sub {
  font-size: var(--hx-fs-micro);
  letter-spacing: 0.3em;
  color: var(--hx-text-muted);
}

.hx-login__form {
  display: grid;
  gap: var(--hx-space-4);
  padding: var(--hx-space-4);
}

.hx-login__field {
  display: grid;
  gap: var(--hx-space-2);
  font-size: var(--hx-fs-small);
  color: var(--hx-text-muted);
}

.hx-login__field input {
  padding: 10px var(--hx-space-3);
  font: inherit;
  font-size: 1rem;
  color: var(--hx-text);
  background: var(--hx-surface-opaque);
  border: 1px solid var(--hx-line-strong);
  border-radius: var(--hx-radius-sm);
}

/* The failure notice: a glyph-free sentence in a dashed border (never colour alone). */
.hx-login__error {
  padding: var(--hx-space-3);
  border: 2px dashed var(--hx-line-strong);
  border-radius: var(--hx-radius-sm);
}

.hx-login__error[hidden] {
  display: none;
}
