/* The portal's stylesheet.
 *
 * The colour tokens are copied from the box frontend's src/index.css on
 * purpose, so the fleet page and the plant you click into read as one
 * product. Copied rather than shared because the two applications ship
 * separately - the portal must not need a node build, and a box must not need
 * the portal to exist.
 *
 * The palette discipline is the box's and is load-bearing here too:
 *
 *   quality-*  the freshness dot. A stale plant is a DATA-TRUST problem, not
 *              a plant alarm, and must not be mistakable for one across a
 *              room. This is the amber that means "I am not sure this number
 *              is current".
 *   alarm-*    the alarm badge, and nothing else. Red is reserved for an
 *              unacknowledged critical - an acknowledged one is amber,
 *              because red means "nobody has looked at this yet".
 */

:root {
  --color-bg: #f5f6f8;
  --color-surface: #ffffff;
  --color-surface-hover: #eef0f3;
  --color-border: #d9dde3;
  --color-text: #1c2128;
  --color-text-muted: #5b6472;
  --color-accent: #2563eb;
  --color-accent-hover: #1d4ed8;
  --color-danger: #dc2626;

  --alarm-critical: #b91c1c;
  --alarm-critical-bg: #fee2e2;
  --alarm-critical-border: #f5a3a3;
  --alarm-warning: #a15c07;
  --alarm-warning-bg: #fef3c7;
  --alarm-warning-border: #f0d78c;

  --quality-ok: #22c55e;
  --quality-warn: #b45309;
  --quality-warn-bg: #fdf3e3;
  --quality-warn-border: #e6cba0;
  --quality-idle: var(--color-text-muted);

  color-scheme: light;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
}

h1, h2, h3 { margin: 0 0 0.5rem; }

.muted { color: var(--color-text-muted); font-size: 0.85rem; }
code { background: var(--color-surface-hover); padding: 0.1rem 0.3rem; border-radius: 4px; }

button, .button-link {
  font: inherit;
  cursor: pointer;
  border-radius: 6px;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text);
  padding: 0.4rem 0.85rem;
  text-decoration: none;
  display: inline-block;
}
button:hover, .button-link:hover { background: var(--color-surface-hover); }

button.primary {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}
button.primary:hover { background: var(--color-accent-hover); }

label {
  display: block;
  font-weight: 600;
  font-size: 0.85rem;
  margin: 0.75rem 0 0.25rem;
  color: var(--color-text-muted);
}

input[type="email"], input[type="password"] {
  font: inherit;
  width: 100%;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--color-border);
  border-radius: 6px;
  background: var(--color-surface);
  color: var(--color-text);
}

.banner-error {
  background: var(--alarm-critical-bg);
  border: 1px solid var(--alarm-critical-border);
  color: var(--alarm-critical);
  border-radius: 6px;
  padding: 0.5rem 0.7rem;
  font-size: 0.9rem;
  margin-bottom: 0.5rem;
}

/* --- login ------------------------------------------------------------- */

.gate {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 1rem;
}

.gate-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 10px;
  padding: 1.5rem;
  width: min(24rem, 100%);
}

.gate-card button { width: 100%; margin-top: 1rem; }
.hint { color: var(--color-text-muted); font-size: 0.78rem; margin: 1rem 0 0; line-height: 1.5; }

/* --- fleet ------------------------------------------------------------- */

.topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.7rem 1.2rem;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}
.topbar-left, .topbar-right { display: flex; align-items: center; gap: 0.9rem; }
.topbar form { margin: 0; }

.fleet {
  padding: 1.2rem;
  display: grid;
  gap: 0.9rem;
  grid-template-columns: repeat(auto-fill, minmax(22rem, 1fr));
  align-items: start;
}

.empty {
  grid-column: 1 / -1;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 10px;
  padding: 1.5rem;
}

.plant-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 10px;
  padding: 0.9rem 1rem;
}

.plant-head { display: flex; align-items: flex-start; gap: 0.65rem; }
.plant-title { flex: 1 1 auto; min-width: 0; }
.plant-title h2 { font-size: 1.05rem; margin: 0; }
.plant-badges { display: flex; align-items: center; gap: 0.5rem; flex-shrink: 0; }

/* At rest the page stays gray - the dot is the one small spot of positive
 * colour, never a filled region (ISA-101, same as the box's Overview). */
.dot {
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  margin-top: 0.35rem;
  flex-shrink: 0;
  background: var(--quality-idle);
}
.dot-ok { background: var(--quality-ok); }
.dot-warn { background: var(--quality-warn); }
.dot-idle { background: var(--quality-idle); }

.badge {
  font-size: 0.78rem;
  font-weight: 600;
  border-radius: 999px;
  padding: 0.15rem 0.6rem;
  border: 1px solid var(--color-border);
  color: var(--color-text-muted);
  white-space: nowrap;
}
.badge-critical {
  background: var(--alarm-critical-bg);
  border-color: var(--alarm-critical-border);
  color: var(--alarm-critical);
}
.badge-warning {
  background: var(--alarm-warning-bg);
  border-color: var(--alarm-warning-border);
  color: var(--alarm-warning);
}
.badge-quiet { background: transparent; }

.plant-body { margin-top: 0.7rem; padding-left: 1.35rem; }

.machines { list-style: none; margin: 0 0 0.6rem; padding: 0; }
.machines li {
  display: flex;
  gap: 0.5rem;
  align-items: baseline;
  padding: 0.15rem 0;
  border-top: 1px solid var(--color-border);
}
.machines li:first-child { border-top: none; }
.machine-name { font-size: 0.9rem; font-weight: 600; }

.plant-meta { font-size: 0.8rem; color: var(--color-text-muted); display: grid; gap: 0.2rem; }

.quality-warn {
  color: var(--quality-warn);
  background: var(--quality-warn-bg);
  border: 1px solid var(--quality-warn-border);
  border-radius: 6px;
  padding: 0.2rem 0.45rem;
}

/* --- P1: nav, banners, controls, groups, admin -------------------------- */

.nav { display: flex; gap: 0.75rem; align-items: center; }
.nav a {
  color: var(--color-text-muted);
  text-decoration: none;
  font-size: 0.9rem;
  padding: 0.2rem 0;
  border-bottom: 2px solid transparent;
}
.nav a:hover { color: var(--color-text); }
.nav a.here { color: var(--color-text); border-bottom-color: var(--color-accent); font-weight: 600; }

/* The success banner is deliberately quiet: it confirms, it does not
 * celebrate, and it must never compete with the alarm palette. */
.banner-ok {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--quality-ok);
  border-radius: 6px;
  padding: 0.5rem 0.7rem;
  font-size: 0.9rem;
  margin: 0.7rem 1.2rem 0;
}
.banner-error { margin: 0.7rem 1.2rem 0; }
.gate-card .banner-error, .panel .banner-error { margin: 0 0 0.7rem; }

input[type="text"], input[type="number"], select {
  font: inherit;
  padding: 0.4rem 0.55rem;
  border: 1px solid var(--color-border);
  border-radius: 6px;
  background: var(--color-surface);
  color: var(--color-text);
}
input[type="checkbox"] { margin-right: 0.4rem; }
button.danger { color: var(--color-danger); border-color: var(--color-danger); }
button.danger:hover { background: var(--alarm-critical-bg); }
button[disabled] { opacity: 0.45; cursor: not-allowed; }
form.inline { display: inline-flex; gap: 0.4rem; align-items: center; margin: 0; }
form.inline label { margin: 0; display: inline-flex; gap: 0.35rem; align-items: center; }

/* --- fleet controls ----------------------------------------------------- */

.controls {
  padding: 0.8rem 1.2rem 0;
  display: grid;
  gap: 0.5rem;
}
.control-row { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: flex-end; margin: 0; }
.control-label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-text-muted);
  align-self: center;
}
.control-gap { flex: 0 0 1.5rem; }
.control-field { margin: 0; display: grid; gap: 0.2rem; }
.control-note { font-size: 0.82rem; color: var(--color-text-muted); }

.chip {
  font-size: 0.82rem;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 0.25rem 0.7rem;
  background: var(--color-surface);
  color: var(--color-text-muted);
  text-decoration: none;
}
.chip:hover { background: var(--color-surface-hover); }
.chip-on { border-color: var(--color-accent); color: var(--color-accent); font-weight: 600; }

/* --- site groups -------------------------------------------------------- */

.site-group {
  grid-column: 1 / -1;
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: 10px;
  padding: 0.5rem 0.7rem;
  background: var(--color-surface);
}
.site-group > summary {
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.95rem;
}
.site-group > summary .dot { margin-top: 0; }
.site-name { font-weight: 700; }
.site-plants {
  margin-top: 0.7rem;
  display: grid;
  gap: 0.9rem;
  grid-template-columns: repeat(auto-fill, minmax(22rem, 1fr));
  align-items: start;
}

.plant-card[draggable="true"] { cursor: grab; }
.plant-card.dragging { opacity: 0.45; }
.reorder { display: inline-flex; gap: 0.15rem; margin: 0; }
.reorder button { padding: 0.1rem 0.4rem; line-height: 1.1; }

/* --- admin pages -------------------------------------------------------- */

.admin { padding: 1.2rem; display: grid; gap: 1rem; max-width: 70rem; }

.panel {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 10px;
  padding: 1rem 1.1rem;
}
.panel > p:first-of-type { margin-top: 0; }

.stack { display: grid; gap: 0.6rem; }
.field-row { display: flex; flex-wrap: wrap; gap: 0.8rem; align-items: flex-end; }
.field-row label { margin: 0; display: grid; gap: 0.2rem; }
.field-row label.wide { flex: 1 1 22rem; }

.person {
  border-top: 1px solid var(--color-border);
  padding: 0.5rem 0;
}
.person > summary {
  cursor: pointer;
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  align-items: baseline;
}
.person-removed > summary strong { text-decoration: line-through; }
.person-body { padding: 0.6rem 0 0.2rem 1.2rem; display: grid; gap: 0.8rem; }
.person-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; }
.person-actions form { margin: 0; }

.state {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  border-radius: 999px;
  padding: 0.1rem 0.5rem;
  border: 1px solid var(--color-border);
  color: var(--color-text-muted);
}
.state-active { border-color: var(--quality-ok); color: #15803d; }
.state-invited { border-color: var(--quality-warn-border); color: var(--quality-warn); }
.state-removed { border-color: var(--color-border); }

.plant-access {
  border: 1px solid var(--color-border);
  border-radius: 8px;
  padding: 0.6rem 0.8rem;
}
.plant-access legend { font-size: 0.8rem; font-weight: 600; color: var(--color-text-muted); padding: 0 0.3rem; }
.plant-access label { display: block; font-weight: 400; color: var(--color-text); margin: 0.2rem 0; }
.all-plants { border-bottom: 1px solid var(--color-border); padding-bottom: 0.4rem; margin-bottom: 0.4rem; }
.plant-checks { display: grid; grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr)); gap: 0.1rem; }

.role-row { border-top: 1px solid var(--color-border); padding: 0.7rem 0 0.2rem; display: grid; gap: 0.5rem; }
.role-delete { margin: 0 0 0.5rem; }
.role-count { align-self: center; }
.caps { display: grid; grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); gap: 0.4rem; }
.cap {
  margin: 0;
  font-weight: 400;
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-radius: 6px;
  padding: 0.4rem 0.5rem;
  display: grid;
  gap: 0.15rem;
}
/* An inert capability looks like what it is: a real choice that does nothing
 * yet. Greyed out would say "broken"; unmarked would say "this works". */
.cap-inert { border-style: dashed; }
.cap-help { font-size: 0.75rem; line-height: 1.35; }
.tag {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  border: 1px solid var(--quality-warn-border);
  background: var(--quality-warn-bg);
  color: var(--quality-warn);
  border-radius: 999px;
  padding: 0 0.4rem;
  margin-left: 0.3rem;
}

.plant-edit { border-top: 1px solid var(--color-border); padding-top: 0.7rem; }
.site-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: center;
  border-top: 1px solid var(--color-border);
  padding: 0.5rem 0;
}

/* ---------------------------------------------------------------------------
 * P2: graphs, shared graphs, and the claim code
 *
 * Same palette discipline as everything above. Note what is NOT here: no red
 * on a graph. A chart that could not be drawn is a data-trust problem - "this
 * plant did not answer" - so it wears the quality amber, never the alarm red,
 * which stays reserved for an unacknowledged critical on a real plant.
 * ------------------------------------------------------------------------ */

.graphs-page { padding: 1.2rem; display: grid; gap: 1rem; max-width: 74rem; }
.graphs-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
.graphs-head p { margin: 0.2rem 0 0; }

#graph-list { display: grid; gap: 1rem; }

.graph-card { margin: 0; }
.graph-card[draggable="true"] { cursor: grab; }
.graph-card.dragging { opacity: 0.45; }
.graph-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.8rem; }
.graph-title { min-width: 0; }
.graph-title h3 { font-size: 1rem; margin: 0; }
.graph-actions { display: flex; align-items: flex-start; gap: 0.4rem; flex-shrink: 0; flex-wrap: wrap; }
.graph-actions form { margin: 0; }

.graph-canvas { margin-top: 0.6rem; min-height: 3rem; }
.graph-canvas svg { display: block; width: 100%; height: auto; }
.graph-message { margin: 0.4rem 0; font-size: 0.85rem; color: var(--color-text-muted); }
.graph-message-bad {
  color: var(--quality-warn);
  background: var(--quality-warn-bg);
  border: 1px solid var(--quality-warn-border);
  border-radius: 6px;
  padding: 0.5rem 0.7rem;
}

.graph-legend {
  display: flex; flex-wrap: wrap; gap: 0.2rem 1rem;
  margin-top: 0.4rem; font-size: 0.78rem; color: var(--color-text-muted);
}
.graph-legend-item { display: inline-flex; align-items: center; gap: 0.35rem; }
.graph-swatch { width: 0.7rem; height: 0.2rem; border-radius: 1px; display: inline-block; }
.graph-legend-note { font-style: italic; }
.graph-legend-warn { color: var(--quality-warn); font-style: normal; }

/* The share popover on a graph card, and the picker's parameter table. */
.share > summary { cursor: pointer; font-size: 0.85rem; }
.share-form { padding: 0.5rem 0 0.2rem; max-width: 26rem; }
.share-target { display: block; font-weight: 400; margin: 0.15rem 0; }

.picker { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.picker th, .picker td { text-align: left; padding: 0.28rem 0.5rem; border-bottom: 1px solid var(--color-border); }
.picker th { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--color-text-muted); }

/* The dashboard's "shared with you" section and the shares page share these. */
.share-inbox { margin: 0.9rem 1.2rem 0; }
.share-offer {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem;
  border-top: 1px solid var(--color-border); padding: 0.6rem 0;
}
.share-offer:first-of-type { border-top: none; }
.share-offer-what { min-width: 0; }
.share-offer-actions { display: flex; gap: 0.4rem; flex-shrink: 0; }
.share-offer-actions form { margin: 0; }

/* A claim code is read off the screen and typed at a box. Big, spaced, and
 * in a monospace face so O/0 and 5/S cannot be confused - the alphabet in
 * portal/claim.py already leaves the worst offenders out, and this is the
 * other half of the same care. */
.claim-code-box {
  border: 1px solid var(--color-accent);
  border-radius: 8px;
  padding: 0.8rem 1rem;
  margin-bottom: 1rem;
  background: var(--color-surface);
}
.claim-code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  margin: 0.4rem 0;
}
.claim-code-box p { margin: 0; }
.claim-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem;
  padding: 0 0 0.9rem; margin-top: -0.3rem;
  border-bottom: 1px solid var(--color-border);
}
.claim-row form { margin: 0; }

/* Deleting a plant. Folded away behind a summary rather than sat next to
   "Unbind box": everything else on this row is undone with a new claim code
   and this one is not, so it should take a deliberate click to even see. */
.plant-danger {
  padding: 0 0 0.9rem;
  border-bottom: 1px solid var(--color-border);
}
.plant-danger > summary {
  cursor: pointer;
  font-size: 0.85rem;
  padding: 0.2rem 0;
}
.plant-danger[open] > summary { color: var(--color-danger); }
.plant-danger form { margin: 0.4rem 0 0; }

/* --- incidents page: the disturbance-capture archive --- */
.table-scroll { overflow-x: auto; }
.incidents-table { width: 100%; border-collapse: collapse; }
.incidents-table td, .incidents-table th { vertical-align: top; text-align: left; }
.verified-pill {
  display: inline-block;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--quality-ok);
  border: 1px solid var(--quality-ok);
  white-space: nowrap;
}
.incident-actions { white-space: nowrap; }
.incident-delete { display: inline-flex; gap: 0.3rem; align-items: center; margin-left: 0.4rem; }
.incident-delete input { width: 6.5rem; padding: 0.2rem 0.4rem; border: 1px solid var(--color-border); border-radius: 4px; }

/* ------------------------------------------------------------------ */
/* FleetLink - the second-source card group on the fleet page          */
/* ------------------------------------------------------------------ */

/* Outside the .fleet grid (it is a distinct group, not more plant
   cards), so it carries the page margin itself - same as .share-inbox,
   plus a bottom margin because it is the last thing on the page. */
.fleetlink { margin: 0 1.2rem 1.2rem; }
.fleetlink > h2 { margin-top: 0; }
.fleetlink .plant-card { margin-top: 0.9rem; }
.fleetlink .inline select { max-width: 14rem; }
