/* PV Fleet — the brand kit palette: navy ink, steel-blue accent, amber
   reserved for the measured line on charts. Status colours (good/warn/bad)
   are semantic, not brand, and stay as they are. */

:root {
  --bg: #f8fafc;
  --surface: #ffffff;
  --border: #e2e8f0;
  --text: #16263D;
  --muted: #64748b;
  --accent: #2F6FB0;
  --accent-dark: #245A91;
  --accent-soft: #E3EDF7;
  --warn: #b45309;
  --bad: #b91c1c;
  --radius: 12px;
  --shadow: 0 1px 2px rgba(15, 23, 42, .05), 0 4px 12px rgba(15, 23, 42, .04);
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--text);
  font: 15px/1.5 -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
a { color: var(--accent-dark); text-decoration: none; }
a:hover { text-decoration: underline; }
code { background: #f1f5f9; padding: 2px 6px; border-radius: 6px; font-size: 13px; }
hr { border: 0; border-top: 1px solid var(--border); margin: 20px 0; }

/* --- Top bar --- */
/* The bar itself spans the window (so the border and background do too), but
   its contents sit on the same 1400px centred column as .layout below. */
.topbar {
  background: var(--surface); border-bottom: 1px solid var(--border);
  height: 56px; position: sticky; top: 0; z-index: 20;
}
.topbar-inner {
  display: flex; align-items: center; gap: 24px; height: 100%;
  max-width: 1400px; margin: 0 auto; padding: 0 24px;
}
.brand { display: flex; align-items: center; gap: 9px; font-weight: 700; font-size: 17px; color: var(--text); }
.brand:hover { text-decoration: none; }
.topnav { display: flex; gap: 4px; }
.topnav a { padding: 6px 12px; border-radius: 8px; color: var(--muted); font-weight: 500; }
.topnav a:hover { background: var(--bg); text-decoration: none; }
.topnav a.active { color: var(--accent-dark); background: var(--accent-soft); }
.topuser { margin-left: auto; display: flex; align-items: center; gap: 12px; }
.topuser form { margin: 0; }

.content { max-width: 1200px; margin: 0 auto; padding: 28px 24px 64px; }
.footer { max-width: 1400px; margin: 0 auto; padding: 0 24px 32px; font-size: 12px; }

/* --- Layout with persistent sidebar (logged-in pages) --- */
.layout { display: flex; align-items: flex-start; gap: 22px; max-width: 1400px; margin: 0 auto; padding: 24px; }
.layout .content.in-layout { max-width: none; margin: 0; padding: 4px 0 64px; flex: 1; min-width: 0; }
.sidebar {
  width: 235px; flex-shrink: 0; position: sticky; top: 72px;
  max-height: calc(100vh - 90px); overflow-y: auto;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow); padding: 10px;
}
.side-org { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); margin: 14px 10px 4px; font-weight: 600; }
.side-item {
  display: flex; justify-content: space-between; align-items: center; gap: 8px;
  padding: 8px 10px; border-radius: 8px; color: var(--text); font-weight: 500; font-size: 14px;
}
.side-item:hover { background: var(--bg); text-decoration: none; }
.side-item.active { background: var(--accent-soft); color: var(--accent-dark); font-weight: 650; }
.side-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-pill { flex-shrink: 0; font-size: 11px; font-weight: 700; color: #fff; padding: 1px 8px; border-radius: 999px; }
.side-pill.good { background: #15803d; }
.side-pill.warn { background: #b45309; }
.side-pill.bad { background: #b91c1c; }

.page-title { font-size: 24px; font-weight: 700; margin: 0 0 4px; display: flex; align-items: center; gap: 10px; }
.section-title { font-size: 17px; font-weight: 650; margin: 28px 0 12px; }
.muted { color: var(--muted); }
.small { font-size: 13px; }
.hide-sm { display: inline; }

/* --- Cards --- */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow); padding: 18px 20px;
}
.cards { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(290px, 1fr)); margin: 16px 0; }
.info-cards { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
/* Sentence case, not caps: one heading convention across the app. */
.card h3 { margin: 0 0 10px; font-size: 14px; color: var(--muted); font-weight: 650; }
.card h4 { margin: 14px 0 6px; font-size: 13px; color: var(--muted); }
.card.empty { text-align: center; padding: 40px 20px; color: var(--muted); }

.sys-name { font-weight: 650; font-size: 16px; }

/* Overview table: whole row navigates (app.js), name stays a real link */
.row-links tbody tr { cursor: pointer; transition: background .1s; }
.row-links tbody tr:hover { background: #f8fafc; }
.row-links .sys-name { font-size: 14px; color: var(--text); margin-right: 6px; }
.pill { display: inline-block; min-width: 46px; text-align: center; padding: 3px 10px; border-radius: 6px; font-size: 12px; font-weight: 700; color: #fff; }
.pill.good { background: #15803d; }
.pill.warn { background: #b45309; }
.pill.bad { background: #b91c1c; }
.org-name { font-size: 14px; color: var(--muted); font-weight: 650; margin: 28px 0 0; }
.kpi-label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
.health-big.good { color: var(--accent-dark); }
.health-big.warn { color: var(--warn); }
.health-big.bad { color: var(--bad); }

/* Badges */
.badge { font-size: 11px; font-weight: 700; padding: 2px 9px; border-radius: 999px; text-transform: uppercase; letter-spacing: .04em; }
.badge.pro { background: var(--accent-soft); color: var(--accent-dark); }
.badge.free { background: #f1f5f9; color: var(--muted); }
.badge.bad { background: #fee2e2; color: var(--bad); }
.badge.beta { background: #ede9fe; color: #5b21b6; }
/* Tab-level Pro marker: small enough not to shout, clear enough to read. */
.subnav .tab-pro {
  margin-left: 6px; font-size: 9.5px; font-weight: 800; letter-spacing: .05em;
  text-transform: uppercase; padding: 1px 6px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent-dark); vertical-align: 1px;
}

/* --- Pro upsell panel (free accounts on a Pro tab) --- */
.pro-lock { text-align: center; padding: 40px 24px; }
/* Selector must out-specify `.card h3` (0,1,1), which uppercases every card
   heading. A bare `.pro-lock-title` (0,1,0) lost and the pitch rendered as a
   shouty uppercase label instead of a sentence. */
.pro-lock h3.pro-lock-title {
  margin: 12px 0 8px; font-size: 20px; font-weight: 700;
  text-transform: none; letter-spacing: 0; color: var(--text);
}
.pro-lock p { max-width: 56ch; margin: 0 auto 18px; }

/* --- System header + subnav --- */
.sys-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.health-tile { display: flex; flex-direction: column; align-items: center; padding: 10px 22px; }
.health-big { font-size: 34px; font-weight: 800; line-height: 1.1; }
.subnav {
  display: flex; gap: 2px; margin: 20px 0 8px; border-bottom: 1px solid var(--border);
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none;            /* swipeable on phones, but no visible scrollbar */
}
.subnav::-webkit-scrollbar { display: none; }
.subnav a {
  padding: 9px 16px; color: var(--muted); font-weight: 550; white-space: nowrap;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.subnav a:hover { color: var(--text); text-decoration: none; }
.subnav a.active { color: var(--accent-dark); border-bottom-color: var(--accent); }

/* --- Charts --- */
.chart-card { padding: 8px; margin: 14px 0; }
/* max-width + overflow guard: Plotly sizes its SVG from the container, and if
   anything upstream lets the container grow, the chart happily renders 9000px
   wide and takes the page with it. */
.chart { width: 100%; max-width: 100%; min-height: 420px; position: relative; overflow: hidden; }
.chart .plotly, .chart svg { max-width: 100%; }
.chart-loading {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: var(--muted); font-size: 14px;
  background: repeating-linear-gradient(90deg, #fafcff 0 40px, #f4f7fb 40px 80px);
  background-size: 200% 100%; animation: shimmer 1.4s linear infinite; border-radius: 8px;
}
@keyframes shimmer { to { background-position: -200% 0; } }
.chart-error { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: var(--muted); }
.upsell { margin-top: 18px; padding: 10px 14px; background: var(--accent-soft); border-radius: 8px; color: var(--accent-dark); }

/* --- Tables --- */
.table-card { padding: 6px 0; overflow-x: auto; }
table { border-collapse: collapse; width: 100%; }
th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); padding: 10px 16px; border-bottom: 1px solid var(--border); }
td { padding: 9px 16px; border-bottom: 1px solid #f1f5f9; font-size: 14px; }
tr:last-child td { border-bottom: 0; }
table.kv td { padding: 7px 4px; }
table.kv td:first-child { color: var(--muted); width: 45%; }

/* --- Forms --- */
label { display: block; margin: 10px 0; font-size: 14px; font-weight: 550; }
label.check { font-weight: 400; margin: 6px 0; }
input[type=text], input[type=email], input[type=password], input[type=number], input[type=date], select {
  display: block; width: 100%; margin-top: 4px; padding: 9px 12px; font: inherit;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface); color: var(--text);
}
label.check input { display: inline; width: auto; margin-right: 6px; }
input:focus, select:focus { outline: 2px solid var(--accent-soft); border-color: var(--accent); }
.inline-form { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.inline-form input, .inline-form select { display: inline-block; width: auto; margin: 0; }
.form-grid { display: grid; gap: 4px 18px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.form-card { margin-top: 16px; }

.btn {
  display: inline-block; padding: 8px 16px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text); font: inherit; font-weight: 600; cursor: pointer;
  white-space: nowrap;
}
.btn:hover { background: var(--bg); text-decoration: none; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; margin-top: 10px; }
.btn-primary:hover { background: var(--accent-dark); }
.btn-ghost { border: 0; background: transparent; color: var(--accent-dark); padding: 4px 8px; }
.btn-block { width: 100%; }

.alert { background: #fef2f2; color: var(--bad); border: 1px solid #fecaca; border-radius: 8px; padding: 10px 14px; margin: 12px 0; font-size: 14px; }
.alert.ok { background: var(--accent-soft); color: var(--accent-dark); border-color: #a7f3d0; }

/* --- Login --- */
.login-wrap { display: flex; justify-content: center; padding: 8vh 0; }
.login-card { width: 380px; max-width: 92vw; padding: 32px; }
.login-brand { text-align: center; margin-bottom: 18px; }
.login-brand h1 { margin: 10px 0 2px; font-size: 22px; }

/* --- Stat tiles (shading profile) --- */
.stat-tile { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.stat-big { font-size: 30px; font-weight: 800; color: var(--text); line-height: 1.15; }

/* --- Site photo (system overview) --- */
/* `contain`, not `cover`. These are aerial shots of the array itself and their
   aspect ratios run from 0.84 (a portrait house) to 2.78 (a long roof strip),
   so cover cropped away most of the panels — the whole point of the photo. A
   letterboxed neutral background is a much smaller price than showing a third
   of the array. */
.photo-card { padding-bottom: 14px; }
.photo-card img {
  display: block; width: 100%; height: 200px; object-fit: contain;
  border-radius: 8px; background: #eef2f7;
}

/* --- Health gauge (system overview) --- */
.gauge-card { display: flex; flex-direction: column; align-items: center; text-align: center; }
.gauge-card h3 { align-self: flex-start; }
/* In the Recent performance section the gauge is a full-width panel, so cap the
   dial and let the explanation sit beside it on a wide screen. */
.health-panel { margin: 16px 0; }
.health-panel .gauge { max-width: 200px; }
.gauge-note { max-width: 62ch; margin: 10px 0 0; }
@media (min-width: 700px) {
  .health-panel { display: grid; grid-template-columns: 200px 1fr; gap: 6px 24px; align-items: center; text-align: left; }
  .health-panel h3 { grid-column: 1 / -1; }
  .gauge-note { margin: 0; }
}
.gauge { width: 100%; max-width: 230px; }
.gauge svg { width: 100%; height: auto; display: block; }
.gauge-track, .gauge-value { fill: none; stroke-width: 15; stroke-linecap: round; }
.gauge-track { stroke: #eef2f7; }
.gauge-value { stroke: currentColor; transition: stroke-dasharray .6s ease; }
.gauge.good { color: #15803d; }
.gauge.warn { color: #b45309; }
.gauge.bad { color: #b91c1c; }
.gauge-num { font-size: 34px; font-weight: 800; fill: var(--text); }

/* Read by screen readers, invisible to everyone else. clip-path rather than
   display:none, which assistive tech skips entirely. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* --- Tooltips (data-tip) --- */
[data-tip] { position: relative; cursor: help; }
[data-tip]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
[data-tip]:hover::after, [data-tip]:focus-visible::after {
  content: attr(data-tip); position: absolute; left: 50%; bottom: calc(100% + 8px);
  transform: translateX(-50%); z-index: 50; width: max-content; max-width: 260px;
  background: var(--text); color: #fff; font-size: 12px; font-weight: 400; line-height: 1.4;
  padding: 8px 11px; border-radius: 8px; box-shadow: var(--shadow); pointer-events: none;
  white-space: normal; text-align: left;
}

/* --- Responsive --- */
@media (max-width: 900px) {
  /* Sidebar stays "always there" as a swipeable chip row above the content.
     align-items MUST return to stretch here: the desktop rule sets flex-start,
     which in a column flex container is the CROSS axis, so children sized to
     their widest content instead of the viewport. That let a wide chart drag
     the whole page sideways and pushed the subnav's Pro badges off-screen. */
  .layout { flex-direction: column; align-items: stretch; gap: 12px; padding: 16px 14px; }
  .layout .content.in-layout { width: 100%; min-width: 0; }
  .sidebar {
    position: static; width: 100%; max-height: none;
    display: flex; align-items: center; gap: 4px; padding: 8px;
    overflow-x: auto; scrollbar-width: none;
  }
  .sidebar::-webkit-scrollbar { display: none; }
  .side-org { display: none; }
  .side-item { flex-shrink: 0; }
}

@media (max-width: 760px) {
  /* Targets .topbar-inner, which is the flex container — the padding and gap
     moved there when the bar's contents were centred on the content column. */
  .topbar-inner { padding: 0 14px; gap: 10px; }
  .brand { font-size: 15px; gap: 6px; min-width: 0; }
  .brand span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .topnav a { padding: 6px 8px; }
  .hide-sm { display: none; }
  /* Wrap the tab bar rather than making it swipeable. Scrolling hid the last
     two tabs, which are exactly the ones carrying the Pro badge, so the upsell
     was invisible on a phone unless you happened to swipe. */
  .subnav { flex-wrap: wrap; overflow-x: visible; row-gap: 2px; }
  .subnav a { padding: 8px 12px; }
  /* Overview table: drop DC/AC/Installed (cols 3-5) so System, Site,
     Yesterday and Health fit a phone without scrolling. */
  .row-links th:nth-child(n+3):nth-child(-n+5),
  .row-links td:nth-child(n+3):nth-child(-n+5) { display: none; }
  .content { padding: 18px 14px 48px; }
  .cards { grid-template-columns: 1fr; }
  .chart { min-height: 340px; }
  .sys-head { flex-direction: column; }
  .health-tile { flex-direction: row; gap: 10px; align-items: baseline; padding: 8px 14px; }
  .health-big { font-size: 26px; }
  /* There is no hover on a touch screen, so the bubble is triggered by tap
     instead (app.js makes each tip focusable). Pinned to the left edge of its
     element rather than centred on it, so a 260px bubble cannot push a phone
     viewport sideways. */
  [data-tip]:hover::after, [data-tip]:focus-visible::after {
    left: 0; right: auto; transform: none;
    max-width: min(280px, calc(100vw - 32px));
  }
}

/* --- Degradation verdict --- */
.verdict-card { margin: 16px 0; }
.verdict-card p { margin: 0 0 10px; }
.verdict-card p:last-child { margin-bottom: 0; }
.stat-big.warn { color: var(--warn); }
.stat-big.bad { color: var(--bad); }

/* --- Degradation position bar --- */
.gauge-bar-card { margin: 16px 0; }
.gauge-bar { padding: 6px 10px 0; }
/* Named apart from .gauge-track, which is the SVG arc on System overview.
   Sharing the name meant both components matched both rulesets. */
.gauge-bar-track {
  position: relative; height: 16px; border-radius: 999px; overflow: visible;
  background: var(--border);
}
.gauge-bar-track .zone { position: absolute; top: 0; height: 100%; }
.gauge-bar-track .zone.good { background: #86efac; border-radius: 999px 0 0 999px; }
.gauge-bar-track .zone.warn { background: #fdba74; }
.gauge-bar-track .zone.bad  { background: #fca5a5; border-radius: 0 999px 999px 0; }

.gauge-bar-track .marker { position: absolute; top: -5px; transform: translateX(-50%); cursor: help; }
.gauge-bar-track .marker.yoy::after {
  content: ""; display: block; width: 4px; height: 26px; border-radius: 2px;
  background: var(--text); box-shadow: 0 0 0 2px #fff;
}
.marker-label {
  position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%);
  font-size: 12px; font-weight: 700; color: var(--text); white-space: nowrap;
}
.gauge-scale { position: relative; height: 20px; margin-top: 10px; font-size: 11px; color: var(--muted); }
.gauge-scale span { position: absolute; transform: translateX(-50%); white-space: nowrap; }
.gauge-scale span:first-child { transform: none; }
.gauge-scale span:last-child { transform: translateX(-100%); }
.gauge-key { margin: 22px 0 0; }
/* Same escape hatch as .pro-lock-title and .release-title: .card h3 uppercases
   every heading in a card, which a sentence cannot carry. */
.card h3.plain-title {
  text-transform: none; letter-spacing: normal; font-size: 15px; color: var(--text);
}

/* --- Alerts --- */
.tab-count {
  display: inline-block; min-width: 18px; margin-left: 6px; padding: 0 6px;
  border-radius: 999px; font-size: 11px; font-weight: 800; color: #fff;
  text-align: center; vertical-align: 1px;
}
.tab-count.warn { background: var(--warn); }
.tab-count.bad  { background: var(--bad); }

.alert-list { display: flex; flex-direction: column; gap: 12px; margin: 16px 0; }
/* Severity is carried by a coloured rail AND a written label — colour alone
   never states the severity, so it survives colour blindness and greyscale. */
.alert-row {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 18px; flex-wrap: wrap; border-left: 4px solid var(--border);
}
.alert-row.sev-critical { border-left-color: var(--bad); }
.alert-row.sev-warning  { border-left-color: var(--warn); }
.alert-row.sev-info     { border-left-color: #64748b; }
.alert-row.acted-archived { opacity: .62; }
.alert-main { flex: 1; min-width: 260px; }
.alert-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 4px; }
.sev-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--border); flex-shrink: 0; }
.sev-critical .sev-dot { background: var(--bad); }
.sev-warning .sev-dot  { background: var(--warn); }
.sev-info .sev-dot     { background: #64748b; }
.sev-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.alert-system { font-size: 13px; font-weight: 650; }
.alert-title { margin: 0 0 4px; font-size: 15px; font-weight: 550; }
.alert-meta { margin: 0; }
.alert-actions { display: flex; gap: 8px; flex-wrap: wrap; margin: 0; }
.btn-sm { padding: 5px 11px; font-size: 13px; font-weight: 550; }
.btn:disabled { opacity: .45; cursor: default; }
.btn:disabled:hover { background: var(--surface); }

@media (max-width: 620px) {
  .alert-row { flex-direction: column; }
  .alert-actions { width: 100%; }
  .alert-actions .btn { flex: 1; }
}

/* --- Admin reference pages (How it works, Changelog) --- */
.doc-toc { padding: 16px 20px; }
.doc-toc ul { margin: 8px 0 0; padding-left: 20px; columns: 2; column-gap: 32px; }
.doc-toc li { margin: 2px 0; }
.doc-toc a { color: var(--accent-dark); }
.release-list { list-style: none; margin: 16px 0 0; padding: 0; }
.release { margin: 0 0 16px; }
.release.current { border-left: 3px solid var(--accent); }
.release-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.release-version { font-size: 20px; font-weight: 800; color: var(--text); }
.release-date { margin-left: auto; }
/* Needs .release to outrank `.card h3`, which uppercases card headings. That
   suits a two-word label and not a sentence: these titles are long enough that
   all-caps costs real legibility. */
.release h3.release-title {
  margin: 6px 0 4px; text-transform: none; letter-spacing: 0;
  font-size: 16px; color: var(--text);
}
.release-notes { margin: 0; padding-left: 20px; }
.release-notes li { margin: 6px 0; line-height: 1.55; }
.app-version { margin-left: 8px; opacity: 0.75; }

/* --- Alert evidence (collapsed chart under each alert) --- */
/* The alert row is a flex line of text + buttons. The evidence is a third item
   and must not squeeze into a column beside them: it takes the full width on
   its own line, which is also the only way the chart gets room to be readable. */
.alert-evidence { flex: 0 0 100%; width: 100%; order: 10; margin: 12px 0 0; }
.alert-evidence > summary {
  cursor: pointer; font-size: 13px; font-weight: 600; color: var(--accent-dark);
  list-style: none; display: inline-flex; align-items: center; gap: 6px;
}
.alert-evidence > summary::-webkit-details-marker { display: none; }
.alert-evidence > summary::before { content: "▸"; font-size: 11px; }
.alert-evidence[open] > summary::before { content: "▾"; }
.alert-evidence > summary:hover { text-decoration: underline; }
.alert-evidence p { margin: 8px 0 0; max-width: 68ch; }
.alert-evidence .chart-card { margin-top: 8px; }

/* --- Wide charts scroll inside their own card, never the page --- */
/* The monthly grid is 12 labelled columns. Below about 680px the labels
   collide, so the card scrolls rather than the grid compressing. */
.chart-card.scroll-x { overflow-x: auto; }
.chart-card.scroll-x .chart { min-width: 680px; }

/* Admin usage: a bare-bones activity sparkline. Deliberately not a Plotly
   chart — it conveys shape, and the numbers are in the tooltip. */
.spark { display: flex; align-items: flex-end; gap: 2px; height: 90px; margin: 4px 0 10px; }
.spark-bar { flex: 1 1 0; min-width: 2px; min-height: 2px; background: var(--accent);
             border-radius: 2px 2px 0 0; }
.spark-bar.has-errors { background: var(--bad); }
.range-links { margin: -4px 0 16px; font-size: 13px; color: var(--muted); }

/* The logbook's type badge is a category label, not shouting. */
.badge.log-type { text-transform: none; letter-spacing: 0; }
/* The row whose entry is open in the edit form. */
.editing-row td { background: var(--accent-soft); }

/* Fleet freshness: how far behind each system's data is. Overnight gaps are
   normal (panels do not report at night), so amber only past a working day
   and red once a full day of daylight has been missed. */
.fresh-warn { color: var(--warn); font-weight: 650; }
.fresh-bad { color: var(--bad); font-weight: 650; }

textarea.contact-msg {
  width: 100%; margin-top: 4px; padding: 8px 10px; font: inherit;
  border: 1px solid var(--border); border-radius: 8px; resize: vertical;
}

.card p.numbers-note { margin-top: 10px; }

/* The brand lockups are images now (PVFleet Brand kit, the Trace mark). */
.brand-logo { height: 30px; width: auto; display: block; }
.login-logo { height: 96px; width: auto; margin: 0 auto 6px; display: block; }

/* --- Logbook --- */
/* Date, dropdown and notes on one row on a wide screen, stacked on a narrow
   one. The date and the type only need enough width for their content; the
   notes take whatever is left, because that is the field people actually
   write in. */
.log-fields {
  display: grid; gap: 14px; align-items: start;
  grid-template-columns: 210px 210px minmax(220px, 1fr);
}
.log-fields label {
  display: flex; flex-direction: column; gap: 5px;
  font-size: 12px; color: var(--muted);
}
/* One control style for all three, or the browser's default date chrome sits
   next to the app's select looking like it came from somewhere else. */
.log-fields input, .log-fields select, .log-fields textarea {
  width: 100%; padding: 8px 10px; font: inherit; font-size: 14px;
  color: var(--text); background: #fff;
  border: 1px solid var(--border); border-radius: 8px;
}
.log-fields input, .log-fields select { height: 38px; }
.log-fields textarea { min-height: 38px; resize: vertical; }
.log-fields input:focus-visible, .log-fields select:focus-visible,
.log-fields textarea:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 1px; border-color: var(--accent);
}
.log-actions { display: flex; gap: 8px; align-items: center; margin-top: 16px; }

@media (max-width: 860px) {
  .log-fields { grid-template-columns: 1fr; }
}
/* The delete form sits inside a table cell next to a link, so it must not
   claim a line of its own. */
.log-actions .inline-form, td .inline-form { display: inline; }
.nowrap { white-space: nowrap; }

/* The builder's resting state: same seat as the loading message, but it is a
   hint, not a load, so no shimmer. */
.chart-hint {
  display: flex; align-items: center; justify-content: center; height: 100%;
  min-height: 200px; color: var(--muted); font-size: 14px;
}

/* --- Custom range picker --- */
.custom-card { padding-bottom: 18px; }
.custom-controls { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; margin-bottom: 14px; }
.custom-controls label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--muted); }
.custom-controls input, .custom-controls select {
  padding: 7px 9px; font: inherit; font-size: 14px; color: var(--text);
  border: 1px solid var(--border); border-radius: 8px; background: #fff;
}
.custom-downloads { display: flex; gap: 8px; margin-left: auto; }
/* The button lines up with the 38px inputs beside it. */
.custom-controls .btn-primary { height: 38px; padding-top: 0; padding-bottom: 0; }
.btn.is-disabled { pointer-events: none; opacity: .45; }
.custom-error { margin: 0 0 12px; padding: 9px 12px; border-radius: 8px;
                background: #fef2f2; color: var(--bad); border: 1px solid #fecaca;
                font-size: 13px; }
@media (max-width: 760px) {
  .custom-downloads { margin-left: 0; width: 100%; }
  .custom-downloads .btn { flex: 1; }
}

/* --- Monthly reports --- */
.report-card { margin: 16px 0; }
.report-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 6px; }
.report-head h3 { margin: 0; }
.report-tldr { font-size: 16px; line-height: 1.55; margin: 6px 0 14px; }
.report-card h4 { margin: 16px 0 4px; font-size: 13px; color: var(--muted); }
.report-card p { margin: 0 0 8px; line-height: 1.6; }
.report-foot { margin-top: 18px; padding-top: 12px; border-top: 1px solid var(--border); }

/* --- Admin manual --- */
.steps { margin: 8px 0 0; padding-left: 22px; }
.steps li { margin-bottom: 8px; line-height: 1.55; }
