/* ============================================================================
   MERITS API client — service sheet
   ----------------------------------------------------------------------------
   Loads after hitrail-ds.css and only adds what this service needs on top of
   the design system. No token is redefined here: if a value is wrong for every
   Hit Rail service it belongs in hitrail-ds.css, not in this file.
   ========================================================================== */

/* ---------------------------------------------------------------- shell ---- */

.skip-link {
  position: absolute;
  left: -9999px;
  top: var(--sp-4);
  z-index: var(--z-toast);
  padding: var(--sp-4) var(--sp-6);
  border-radius: var(--r-md);
  background: var(--surface-0);
  border: 1px solid var(--border);
}
.skip-link:focus { left: var(--sp-4); }

.sidebar__brand {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-6) var(--sp-6) var(--sp-5);
  border-bottom: 1px solid var(--border-soft);
}
.sidebar__brand-mark {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex-shrink: 0;
  border-radius: var(--r-md);
  background: var(--ht-olive-700);
  color: var(--ht-gold-400);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-caps);
}
.sidebar__brand-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caps);
}
.sidebar__brand-sub {
  font-size: var(--fs-micro);
  font-weight: var(--fw-medium);
  color: var(--text-muted);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
}

.sidebar__foot {
  padding: var(--sp-5) var(--sp-6) var(--sp-6);
  border-top: 1px solid var(--border-soft);
}
.sidebar__user {
  margin-bottom: var(--sp-4);
  font-size: var(--fs-sm);
  color: var(--text-dim);
  overflow-wrap: anywhere;
}
.sidebar__user b { display: block; color: var(--text); font-weight: var(--fw-semibold); }

.topbar__burger { display: none; }

/* A link out of this service, not a view in it — dimmer, and it keeps the
   arrow glyph rather than taking the active rail. */
/* The service switcher in the topbar. One Keycloak session covers every Hit
   Rail service, so this is a plain list of links — the only cleverness is that
   it shows what the signed-in person's roles actually reach. */
/* A date field you can empty again. The button sits inside the input's box,
   left of the native calendar glyph, and only appears once there is something
   to clear. */
.date-field { position: relative; display: block; flex: 1; min-width: 0; }
.date-clear {
  position: absolute;
  top: 50%;
  right: 30px;
  transform: translateY(-50%);
  width: 18px;
  height: 18px;
  padding: 0;
  border: 0;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-dim);
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
}
.date-clear:hover { background: var(--ht-gold-100); color: var(--ht-olive-800); }

.svc { position: relative; }
.svc__btn {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-5);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-0);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caps);
  cursor: pointer;
}
.svc__btn:hover { border-color: var(--ht-gold-400); }
.svc .menu { top: calc(100% + var(--sp-3)); left: 0; min-width: 260px; }
.svc__item {
  display: flex;
  align-items: baseline;
  gap: var(--sp-4);
  width: 100%;
  padding: var(--sp-4) var(--sp-5);
  border-radius: var(--r-md);
  color: var(--text);
  text-decoration: none;
}
.svc__item:hover { background: var(--surface-2); }
.svc__item .hint { margin-left: auto; font-size: var(--fs-micro); color: var(--text-muted); }
.svc__item.is-here { color: var(--text-muted); pointer-events: none; }
.svc__item.is-here .hint { color: var(--ht-gold-600); }

/* The view host is the 1fr row of .main, and a grid item's min-height defaults
   to auto — so without this it grows to its content, .view grows with it and
   .view__body never overflows. The page then looks as though scrolling is
   broken, which is exactly the failure the design system warns about; it is
   worth a rule of its own rather than a comment in the markup. */
#view {
  min-height: 0;
  overflow: hidden;
}

/* A single value — a UIC code, a service id, a RICS code, a day bitmap — that
   can be lifted out on its own. The whole point of this client is handing one
   of these to somebody else, and selecting it by hand inside a dense table is
   exactly where people give up. */
.copyval {
  cursor: pointer;
  border-radius: var(--r-sm);
  border-bottom: 1px dotted var(--border-strong);
  transition: background var(--dur-fast) var(--ease);
}
.copyval:hover { background: var(--ht-gold-50); border-bottom-color: var(--ht-gold-500); }
.copyval:focus-visible { outline: 2px solid var(--ht-gold-400); outline-offset: 1px; }
.copyval.is-copied {
  background: var(--ok-bg);
  border-bottom-color: var(--ok);
}
.copyval.is-copied::after,
.copyval.is-manual::after {
  content: " copied";
  font-family: var(--font-sans);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  color: var(--ok-dark);
}
.copyval.is-manual {
  background: var(--warn-bg);
  border-bottom-color: var(--warn);
}
.copyval.is-manual::after { content: " selected — ⌘C"; color: var(--warn-dark); }

/* --------------------------------------------------------------- layout ---- */

/* Search on top, results underneath — not side by side.
   A 380px column cannot hold a form of ten fields without cutting the inputs,
   and it leaves the results fighting for the rest of the width. Stacked, the
   form spreads into as many columns as fit (.field-grid is auto-fit 200px) and
   a wide table gets the whole viewport. */
.split {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-7);
  align-items: start;
}
.stack { display: grid; gap: var(--sp-7); }
.row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-5);
}
.row--end { justify-content: flex-end; }
.grow { flex: 1; min-width: 0; }

.kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--sp-6);
}
.kpi__label {
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--text-muted);
  font-weight: var(--fw-semibold);
}
.kpi__value {
  font-family: var(--font-mono);
  font-size: var(--fs-kpi);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-display);
  font-variant-numeric: tabular-nums;
}
.kpi__hint { font-size: var(--fs-sm); color: var(--text-dim); }

/* ------------------------------------------------------------- payloads ---- */

/* Request and response bodies. Every one of them gets a copy button, because
   the whole point of this client is handing evidence to somebody else. */
.payload { position: relative; }
.payload pre {
  margin: 0;
  padding: var(--sp-6);
  overflow: auto;
  max-height: 460px;
  border: 1px solid var(--border-soft);
  border-radius: var(--r-md);
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  line-height: var(--lh-relaxed);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.payload__copy {
  position: absolute;
  top: var(--sp-4);
  right: var(--sp-4);
  opacity: 0.35;
}
.payload:hover .payload__copy,
.payload__copy:focus-visible { opacity: 1; }

/* JSON colouring, done without a library. */
.tok-key { color: var(--ht-olive-600); }
.tok-str { color: var(--ok); }
.tok-num { color: var(--info); }

/* --------------------------------------------------------------- tables ---- */

.table th.is-sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.table th.is-sortable:hover { color: var(--ht-gold-600); }
.table th .sort-arrow { margin-left: var(--sp-2); font-size: var(--fs-micro); color: var(--ht-gold-600); }
.table tr.is-diff > td { background: var(--warn-bg, #fcefd6); }
.table td.is-missing { color: var(--text-muted); font-style: italic; }
.table tbody tr.is-picked > td { background: var(--ht-gold-50); }

.idbtn {
  padding: 2px var(--sp-4);
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: var(--ht-olive-50);
  color: var(--ht-olive-700);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}
.idbtn:hover { border-color: var(--ht-gold-400); background: var(--ht-gold-50); }

/* The shortcut hint that rides along inside the primary button. Dim enough to
   read as a hint rather than as part of the label. */
.kbd {
  margin-left: var(--sp-4);
  padding: 1px 5px;
  border-radius: var(--r-sm);
  background: rgba(31, 34, 26, 0.14);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  line-height: 1.5;
  opacity: 0.8;
}
.btn[disabled] .kbd { opacity: 0.4; }

@media (max-width: 767px) {
  .kbd { display: none; }      /* no modifier key worth advertising on a phone */
}

.pager {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-4);
  font-weight: var(--fw-regular);
  text-transform: none;
  letter-spacing: 0;
}

/* ------------------------------------------------------------- calendar ---- */

/* The operating-day bitmap. POP carries one character per day counting from
   the period's first day, so day k is validFrom + k. Days outside the period
   are drawn blank: the bitmap says nothing about them either way. */
.cal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5) var(--sp-7);
  padding: var(--sp-6);
}
.cal__month { width: 162px; }
.cal__month h4 {
  margin: 0 0 var(--sp-4);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--text-dim);
}
.cal__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.cal__dow {
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  color: var(--text-muted);
  text-align: center;
  line-height: 15px;
}
.cal__day {
  height: 19px;
  line-height: 19px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.cal__day--on {
  background: var(--ok-bg);
  color: var(--ok-dark);
  font-weight: var(--fw-semibold);
  box-shadow: inset 0 0 0 1px var(--ok);
}
/* In the period and not running. Filled and struck through, so it reads as a
   deliberate "no" rather than as a gap. */
.cal__day--off {
  background: var(--surface-3);
  color: var(--text-dim);
  text-decoration: line-through;
}
.cal__day--diff {
  background: var(--warn-bg);
  color: var(--warn-dark);
  font-weight: var(--fw-semibold);
  box-shadow: inset 0 0 0 1px var(--warn);
}
.cal__day--partial { background: var(--info-bg); color: var(--info-dark); }
/* Outside the period. The date still shows, faintly and without a fill: the
   bitmap says nothing about these days, and a calendar with half its dates
   invisible reads as broken rather than as empty. */
.cal__day--out {
  background: transparent;
  color: var(--text-muted);
  opacity: 0.55;
}
/* Grid lead-in before the first of the month — not a day at all. */
.cal__day--pad { background: transparent; color: transparent; pointer-events: none; }

/* Comparison: the date with one stripe per compared run underneath. A filled
   stripe means that run operates that day, so overlaps and hand-overs between
   sub-periods can be read straight off the grid. */
.cal__day--multi {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: space-between;
  height: 26px;
  padding-bottom: 2px;
  background: transparent;
  color: var(--text-muted);
}
.cal__day--multi.is-all { background: var(--ok-bg); color: var(--ok-dark); font-weight: var(--fw-semibold); }
.cal__day--multi.is-none { color: var(--text-muted); opacity: 0.55; }
.cal__n { line-height: 16px; }
.cal__bars { display: flex; gap: 1px; padding: 0 2px; }
.cal__bars i {
  flex: 1;
  height: 4px;
  border-radius: 1px;
  background: var(--surface-3);   /* not running — the track stays visible */
}
.cal__legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-6);
  width: 100%;
  font-size: var(--fs-sm);
  color: var(--text-dim);
}
.cal__swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
  margin-right: var(--sp-3);
  border-radius: 3px;
  vertical-align: -2px;
}

/* ---------------------------------------------------------- station pick --- */

.pick-list { margin-top: var(--sp-5); max-height: 320px; overflow-y: auto; }
.pick-list button {
  display: flex;
  align-items: baseline;
  gap: var(--sp-5);
  width: 100%;
  padding: var(--sp-4) var(--sp-5);
  border: 0;
  border-bottom: 1px solid var(--border-soft);
  background: none;
  text-align: left;
  cursor: pointer;
}
.pick-list button:hover { background: var(--surface-2); }
.pick-list .u {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.pick-list .n { flex: 1; font-weight: var(--fw-medium); }
.pick-list .m { font-size: var(--fs-sm); color: var(--text-muted); }

/* ------------------------------------------------------------- compare ----- */

.cmpbar {
  position: fixed;
  left: 50%;
  bottom: var(--sp-7);
  z-index: var(--z-toast);
  display: none;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-5) var(--sp-6);
  transform: translateX(-50%);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface-0);
  box-shadow: var(--shadow-lg);
}
.cmpbar.is-on { display: flex; }

/* ------------------------------------------------------------ utilities ---- */

/* Small, named spacing and layout helpers. They exist because our own CSP is
   `style-src 'self'` with no 'unsafe-inline', so a style="" attribute is
   silently dropped by the browser — a class is the only thing that actually
   applies. That is also what the design system asks for. */
.mt-5 { margin-top: var(--sp-5); }
.mt-6 { margin-top: var(--sp-6); }
.mt-7 { margin-top: var(--sp-7); }
.mb-5 { margin-bottom: var(--sp-5); }
.my-6-5 { margin: var(--sp-6) 0 var(--sp-5); }
.ml-4 { margin-left: var(--sp-4); }
.p-4 { padding: var(--sp-4); }
.stack--tight { gap: var(--sp-3); }
.wrap-anywhere { word-break: break-all; }
.is-dim { opacity: 0.55; }
.col-check { width: 34px; }
.col-wide { min-width: 16rem; }
.btn--start { justify-content: flex-start; gap: var(--sp-4); }

/* One colour per compared run, applied by class rather than inline. */
.cal__bars i.is-run-0 { background: var(--ok); }
.cal__bars i.is-run-1 { background: var(--info); }
.cal__bars i.is-run-2 { background: var(--ht-gold-500); }
.cal__swatch--run-0 { background: var(--ok); }
.cal__swatch--run-1 { background: var(--info); }
.cal__swatch--run-2 { background: var(--ht-gold-500); }
.cal__swatch--on   { background: var(--ok-bg); box-shadow: inset 0 0 0 1px var(--ok); }
.cal__swatch--diff { background: var(--warn-bg); box-shadow: inset 0 0 0 1px var(--warn); }
.cal__swatch--off  { background: var(--surface-3); }
.cal__swatch--out  { background: transparent; box-shadow: inset 0 0 0 1px var(--border); }

/* --------------------------------------------------------------- misc ------ */

.meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5);
  align-items: center;
  font-size: var(--fs-sm);
  color: var(--text-dim);
}
.eyebrow {
  margin: 0 0 var(--sp-4);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--text-muted);
}
.prose { max-width: 74ch; font-size: var(--fs-base); line-height: var(--lh-relaxed); }
.prose p { margin: 0 0 var(--sp-5); }
.prose code {
  padding: 1px 5px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: 0.92em;
}

/* --------------------------------------------------------------- mobile ---- */

@media (max-width: 767px) {
  .app { grid-template-columns: 1fr; }
  .sidebar {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: var(--z-drawer);
    width: var(--sidebar-w-mobile);
    transform: translateX(-100%);
    transition: transform var(--dur-base) var(--ease);
  }
  .app.is-drawer-open .sidebar { transform: none; }
  .app.is-drawer-open::after {
    content: "";
    position: fixed;
    inset: 0;
    z-index: var(--z-drawer-backdrop);
    background: rgba(31, 34, 26, 0.45);
  }
  .topbar { position: sticky; top: 0; z-index: var(--z-topbar-mobile); }
  .topbar__burger { display: grid; }
}

@media print {
  .sidebar, .topbar, .cmpbar, .payload__copy, .btn { display: none !important; }
  .app { display: block; height: auto; overflow: visible; }
  .view, .view__body { overflow: visible; height: auto; }
}
