/* ============================================================
   HMI DESIGN SYSTEM — COMPONENTS v1.0

   Ready-made component classes so every application gets the
   same button, card, table, and alarm banner without anyone
   re-deriving them.

   Load AFTER hmi-tokens.css:
     <link rel="stylesheet" href="/css/hmi-tokens.css">
     <link rel="stylesheet" href="/css/hmi-components.css">

   Every value here resolves through a token. There is not one
   literal color in this file, which is why it themes for free.
   ============================================================ */

/* ---------- LAYOUT ---------- */
.hmi-page {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: var(--space-7);
}
.hmi-stack { display: grid; gap: var(--space-6); }
.hmi-row   { display: flex; gap: var(--space-4); flex-wrap: wrap; align-items: center; }
.hmi-spacer{ flex: 1; }
.hmi-grid  { display: grid; gap: var(--space-6); }
.hmi-grid-auto { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.hmi-prose { max-width: var(--measure); line-height: var(--leading-prose); }

/* ---------- TYPE ---------- */
.hmi-h1 { font-size: var(--size-h1); font-weight: var(--weight-semibold); line-height: var(--leading-tight); margin: 0; }
.hmi-h2 { font-size: var(--size-h2); font-weight: var(--weight-semibold); line-height: var(--leading-heading); margin: 0; }
.hmi-h3 { font-size: var(--size-h3); font-weight: var(--weight-semibold); line-height: var(--leading-heading); margin: 0; }
.hmi-label   { font-size: var(--size-label); font-weight: var(--weight-medium); }
.hmi-caption { font-size: var(--size-caption); color: var(--text-secondary); }
.hmi-secondary { color: var(--text-secondary); }
.hmi-eyebrow {
  font-size: var(--size-micro);
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  color: var(--text-secondary);
}
.hmi-mono { font-family: var(--font-mono); }
.hmi-num  { font-variant-numeric: tabular-nums; }

/* ---------- CARD ---------- */
.hmi-card {
  background: var(--surface-raised);
  border: var(--border-width) solid var(--border-subtle);
  border-radius: var(--radius-card);
  padding: var(--card-padding);
  box-shadow: var(--shadow-card);
}
.hmi-card--flush { padding: 0; overflow: hidden; }
.hmi-card__header {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-4) var(--space-5);
  border-bottom: var(--border-width) solid var(--border-subtle);
}
.hmi-card__body { padding: var(--space-5); }

/* ---------- BUTTONS ----------
   The primary action is the highest-contrast NEUTRAL.
   Destructive is the only colored button in the system. */
.hmi-btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--space-3);
  font-family: inherit;
  font-size: var(--size-body);
  font-weight: var(--weight-medium);
  line-height: 1;
  height: var(--control-height);
  min-width: var(--touch-min);
  padding: 0 var(--space-5);
  border: var(--border-width) solid transparent;
  border-radius: var(--radius-control);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--duration-fast) var(--ease),
              border-color var(--duration-fast) var(--ease),
              opacity var(--duration-fast) var(--ease);
}
.hmi-btn--primary     { background: var(--fill-primary); color: var(--on-primary); }
.hmi-btn--primary:hover:not(:disabled) { opacity: .88; }

.hmi-btn--secondary   { background: transparent; border-color: var(--border-interactive); color: var(--text-primary); }
.hmi-btn--secondary:hover:not(:disabled) { background: var(--surface-sunken); }

.hmi-btn--tertiary    { background: transparent; color: var(--text-secondary); padding: 0 var(--space-3); }
.hmi-btn--tertiary:hover:not(:disabled) { color: var(--text-primary); text-decoration: underline; }

.hmi-btn--destructive { background: var(--signal-critical); color: var(--on-critical); }
.hmi-btn--destructive:hover:not(:disabled) { opacity: .88; }

.hmi-btn:disabled {
  background: var(--fill-disabled); color: var(--text-disabled);
  border-color: transparent; cursor: not-allowed;
}
.hmi-btn--sm { height: 32px; padding: 0 var(--space-4); font-size: var(--size-label); }

/* ---------- STATUS ----------
   Always a dot AND a word. Normal states are gray.
   Hollow carries acknowledgment so it survives colorblind viewing. */
.hmi-status { display: inline-flex; align-items: center; gap: var(--space-3); font-size: var(--size-label); }
.hmi-dot {
  width: 8px; height: 8px; flex: none;
  border-radius: var(--radius-pill);
  background: var(--gray-500);
}
.hmi-dot--hollow  { background: transparent; border: 2px solid currentColor; box-sizing: border-box; }
.hmi-dot--idle    { background: var(--gray-400); }
.hmi-dot--nodata  { background: var(--gray-300); }
.hmi-dot--warning { background: var(--signal-warning); }
.hmi-dot--alarm   { background: var(--signal-critical); }

.hmi-status--warning { color: var(--signal-warning); font-weight: var(--weight-medium); }
.hmi-status--alarm   { color: var(--signal-critical); font-weight: var(--weight-medium); }

/* ---------- BANNER / ALARM ----------
   Severity carried three ways: rule color, icon shape, severity word. */
.hmi-banner {
  display: flex; align-items: flex-start; gap: var(--space-4);
  background: var(--surface-raised);
  border: var(--border-width) solid var(--border-subtle);
  border-left-width: 3px;
  border-radius: var(--radius-card);
  padding: var(--space-4) var(--space-5);
}
.hmi-banner__icon { flex: none; margin-top: 1px; }
.hmi-banner__body { flex: 1; min-width: 0; }
.hmi-banner__severity {
  display: block;
  font-size: var(--size-micro);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-micro);
  margin-bottom: 2px;
}
.hmi-banner__message { font-size: var(--size-body); }
.hmi-banner__time {
  flex: none;
  font-family: var(--font-mono);
  font-size: var(--size-caption);
  color: var(--text-secondary);
}
.hmi-banner--critical { border-left-color: var(--signal-critical); }
.hmi-banner--critical .hmi-banner__severity,
.hmi-banner--critical .hmi-banner__icon { color: var(--signal-critical); }

.hmi-banner--warning { border-left-color: var(--signal-warning); }
.hmi-banner--warning .hmi-banner__severity,
.hmi-banner--warning .hmi-banner__icon { color: var(--signal-warning); }

.hmi-banner--info { border-left-color: var(--signal-info); }
.hmi-banner--info .hmi-banner__severity,
.hmi-banner--info .hmi-banner__icon { color: var(--signal-info); }

/* Only an unacknowledged critical alarm animates. Nothing else. */
.hmi-pulse { animation: hmi-pulse 1s ease-in-out infinite; }
@keyframes hmi-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

/* ---------- KPI ----------
   Colored only when the value itself is out of bounds. */
.hmi-kpi__label {
  font-size: var(--size-label); font-weight: var(--weight-medium);
  color: var(--text-secondary); margin-bottom: var(--space-3);
}
.hmi-kpi__value {
  font-size: var(--size-value-lg); font-weight: var(--weight-medium);
  line-height: var(--leading-value); font-variant-numeric: tabular-nums;
}
.hmi-kpi__unit {
  font-size: var(--size-label); font-weight: var(--weight-regular);
  color: var(--text-secondary); margin-left: var(--space-2);
}
.hmi-kpi__meta { font-size: var(--size-caption); color: var(--text-secondary); margin-top: var(--space-3); }
.hmi-kpi--alarm   .hmi-kpi__value { color: var(--signal-critical); }
.hmi-kpi--warning .hmi-kpi__value { color: var(--signal-warning); }

/* ---------- TABLE ----------
   No zebra striping. Hairline row rules scan better. */
.hmi-table { width: 100%; border-collapse: collapse; font-size: var(--size-label); }
.hmi-table th {
  text-align: left;
  font-size: var(--size-label);
  font-weight: var(--weight-medium);
  color: var(--text-secondary);
  padding: var(--space-3) var(--space-5);
  border-bottom: var(--border-width) solid var(--border-default);
  white-space: nowrap;
  position: sticky; top: 0;
  background: var(--surface-raised);
}
.hmi-table td {
  padding: 0 var(--space-5);
  height: var(--row-height);
  border-bottom: var(--border-width) solid var(--border-subtle);
}
.hmi-table tbody tr:last-child td { border-bottom: none; }
.hmi-table tbody tr:hover { background: var(--surface-sunken); }
.hmi-table tr[aria-selected="true"] {
  background: var(--surface-sunken);
  box-shadow: inset 2px 0 0 var(--signal-info);
}
.hmi-table th.hmi-num,
.hmi-table td.hmi-num { text-align: right; font-variant-numeric: tabular-nums; }
/* Color the value, never the cell background. */
.hmi-table td.hmi-cell--alarm   { color: var(--signal-critical); font-weight: var(--weight-medium); }
.hmi-table td.hmi-cell--warning { color: var(--signal-warning);  font-weight: var(--weight-medium); }

/* ---------- FORM ---------- */
.hmi-field { margin-bottom: var(--space-6); }
.hmi-field label {
  display: block;
  font-size: var(--size-label);
  font-weight: var(--weight-medium);
  margin-bottom: var(--space-3);
}
.hmi-field input,
.hmi-field select,
.hmi-field textarea {
  width: 100%;
  min-height: var(--control-height);
  padding: 0 var(--space-4);
  font-family: inherit;
  font-size: var(--size-body);
  color: var(--text-primary);
  background: var(--surface-default);
  border: var(--border-width) solid var(--border-interactive);
  border-radius: var(--radius-control);
}
.hmi-field textarea { padding: var(--space-3) var(--space-4); line-height: var(--leading-body); resize: vertical; }
/* Helper text is always present so the layout never jumps on error. */
.hmi-field__help {
  display: block;
  font-size: var(--size-caption);
  color: var(--text-secondary);
  margin-top: var(--space-3);
}
.hmi-field--error input,
.hmi-field--error select,
.hmi-field--error textarea { border-color: var(--signal-critical); }
.hmi-field--error .hmi-field__help { color: var(--signal-critical); }

/* ---------- DIVIDER ---------- */
.hmi-divider { height: var(--border-width); background: var(--border-subtle); border: 0; margin: var(--space-6) 0; }

/* ---------- SKIP LINK ---------- */
.hmi-skip {
  position: absolute; left: -9999px;
  padding: var(--space-3) var(--space-5);
  background: var(--surface-raised); color: var(--text-primary);
  border: var(--border-width) solid var(--border-interactive);
  border-radius: var(--radius-control);
}
.hmi-skip:focus { left: var(--space-5); top: var(--space-5); z-index: 100; }

/* ---------- TIER CELLS ----------
   Categorical threshold encoding for scoreboards and comparison grids.
   NOT for control screens — see the header in hmi-tokens.css.

   <div data-viewing="far">            <!-- omit for desk viewing -->
     <div class="hmi-tier hmi-tier--poor">
       <span class="hmi-tier__key">18:00</span>
       <span class="hmi-tier__val">47%</span>
     </div>
   </div>                                                             */
.hmi-tier {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-control);
  border: 2px solid transparent;
  background: var(--tier-none-bg);
}
.hmi-tier__key { font-family: var(--font-mono); font-size: var(--size-caption); color: var(--text-secondary); }
.hmi-tier__val { font-family: var(--font-mono); font-weight: var(--weight-medium);
                 font-variant-numeric: tabular-nums; }

.hmi-tier--good { background: var(--tier-good-bg); }
.hmi-tier--good .hmi-tier__val { color: var(--tier-good-fg); }
.hmi-tier--fair { background: var(--tier-fair-bg); }
.hmi-tier--fair .hmi-tier__val { color: var(--tier-fair-fg); }
.hmi-tier--poor { background: var(--tier-poor-bg); }
.hmi-tier--poor .hmi-tier__val { color: var(--tier-poor-fg); }
.hmi-tier--none .hmi-tier__val,
.hmi-tier--none .hmi-tier__key { color: var(--tier-none-fg); }

/* The current period. A neutral outline, never another colour — the fill
   already carries the tier, and a second hue would collide with it. */
.hmi-tier--current { border-color: var(--text-primary); }

/* At distance the key label shrinks and the value grows: position already
   tells the reader which period they are looking at. */
[data-viewing="far"] .hmi-tier { padding: var(--space-3) var(--space-5); }
[data-viewing="far"] .hmi-tier__key { font-size: var(--size-label); }
[data-viewing="far"] .hmi-tier__val { font-size: var(--size-value-md); font-weight: var(--weight-semibold); }

/* Tier legend — always label the bands. A tinted grid with no key is a puzzle. */
.hmi-tier-legend { display: flex; gap: var(--space-5); flex-wrap: wrap;
                   font-size: var(--size-caption); color: var(--text-secondary); }
.hmi-tier-legend i { font-style: normal; display: inline-flex; align-items: center; gap: var(--space-2); }
.hmi-tier-legend .chip { width: 16px; height: 16px; border-radius: 3px;
                         display: inline-block; border: 1px solid var(--border-default); }


/* ============================================================
   HIGH CONTRAST / FORCED COLORS
   Windows High Contrast Mode replaces every author color with a
   system palette. The failure mode is not "wrong colors" — it is
   elements that were distinguished ONLY by background disappearing
   into a single flat surface.

   The system survives this better than most because state always
   carries a word, never just a color. These rules cover the rest.
   ============================================================ */
@media (forced-colors: active) {

  /* Keep panel edges visible; backgrounds are flattened by the OS. */
  .hmi-card,
  .hmi-banner,
  .hmi-field input,
  .hmi-field select,
  .hmi-field textarea,
  .hmi-table th,
  .hmi-table td {
    border-color: CanvasText;
  }

  /* Buttons lose their fill distinction, so give every variant a
     visible edge and let the primary read as the default action. */
  .hmi-btn { border: 1px solid ButtonText; }
  .hmi-btn--primary { border-width: 2px; }
  .hmi-btn--destructive { border-width: 2px; border-style: double; }
  .hmi-btn:disabled { color: GrayText; border-color: GrayText; }

  /* Status dots become one flat color. Fill vs hollow is the only
     channel left, so protect it. */
  .hmi-dot { forced-color-adjust: none; background: CanvasText; }
  .hmi-dot--hollow { background: Canvas; border-color: CanvasText; }
  .hmi-dot--nodata,
  .hmi-dot--idle { background: GrayText; }

  /* The severity rule on a banner is structural, not decorative. */
  .hmi-banner { border-left-width: 5px; border-left-color: CanvasText; }
  .hmi-banner--critical { border-left-style: double; }
  .hmi-banner--warning  { border-left-style: dashed; }
  .hmi-banner--info     { border-left-style: solid; }

  /* Selected rows keep their marker. */
  .hmi-table tr[aria-selected="true"] {
    outline: 2px solid Highlight;
    outline-offset: -2px;
  }

  /* Focus must track the system highlight, not our Info token. */
  :focus-visible { outline-color: Highlight; }
}

/* ============================================================
   PREFERS-CONTRAST: MORE
   The user asked for more separation without going all the way to
   forced colors. Lift borders one step; leave type alone.
   ============================================================ */
@media (prefers-contrast: more) {
  :root, [data-theme="light"], [data-theme="dark"] {
    --border-subtle: var(--border-default);
    --border-default: var(--border-interactive);
  }
  .hmi-card, .hmi-banner { border-width: 2px; }
  :focus-visible { outline-width: 3px; }
}
