/*
  Chart Paper component styles.

  Function-named classes only — never named after what they look like.
  Every color / font-family / border / radius value below is a
  var(--token) reference into tokens.css; no hex codes here.

  Ported from the approved mock (artik-v3-chartpaper.html). The mock's
  look-based names are mapped to the function names later tasks bind
  against:
    .stamp            -> .status-chip  (.attn -> .attend, .ok -> .normal, .watch -> .watch)
    .ledgerhead        -> .ledger-head
    table/th/td (ledger)-> .ledger-table
    .card              -> .unit-card
    .big               -> .reading
    .docline           -> .doc-title
    .nav               -> .site-nav
    .form              -> .entry-form
    .btn / .btn.ghost  -> .btn / .btn-ghost
*/

* {
  box-sizing: border-box;
}

/* The browser hides [hidden] with `display: none`, but that comes from the UA stylesheet, so any
   author rule setting display wins over it — .btn's own `display: inline-block` was enough to keep
   a hidden button on screen. Restating it here, at author level, makes `hidden` mean hidden for
   every component in this file rather than only the ones that happen not to set display. */
[hidden] {
  display: none !important;
}

/* The ground the design system is named for: recorder-chart paper. A faint
   millimeter grid — minor line every 8px, major every 40px — painted on the
   page itself and nowhere else. Panels and cards are opaque, so tables and
   forms sit on clean surfaces and the grid reads only in the margins, the
   way chart paper does under a mounted instrument. Fixed attachment keeps
   the grid still while content scrolls over it — the paper doesn't move,
   the pen does. */
body {
  margin: 0;
  background:
    linear-gradient(var(--chart-major) 1px, transparent 1px) 0 0 / 100% 40px,
    linear-gradient(90deg, var(--chart-major) 1px, transparent 1px) 0 0 / 40px 100%,
    linear-gradient(var(--chart-minor) 1px, transparent 1px) 0 0 / 100% 8px,
    linear-gradient(90deg, var(--chart-minor) 1px, transparent 1px) 0 0 / 8px 100%,
    var(--paper);
  background-attachment: fixed;
  color: var(--ink);
  font: var(--fs-body)/1.5 var(--font-body);
}

/* The header sits ON the paper, not under the grid — an opaque strip keeps the
   wordmark and nav crisp. Same for the ledger strips injected by ledger-tools. */
.site-header {
  background: var(--paper);
}

a {
  color: var(--pen-blue);
}

/* ---------------------------------------------------------------------
   Brand
--------------------------------------------------------------------- */

.brand {
  font-family: var(--font-display);
  font-size: var(--fs-title);
  font-weight: 700;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
}

.brand span {
  color: var(--pen-red);
}

/* ---------------------------------------------------------------------
   Site header / nav / user info
--------------------------------------------------------------------- */

.site-header {
  display: flex;
  align-items: baseline;
  gap: 26px;
  padding: 16px 24px 12px;
  border-bottom: var(--border-heavy) solid var(--ink);
  background: var(--paper);
  flex-wrap: wrap;
}

.site-nav {
  display: flex;
  gap: 22px;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  letter-spacing: 1px;
  text-transform: uppercase;
}

.site-nav a {
  color: var(--faint);
  text-decoration: none;
  cursor: pointer;
  padding-bottom: 2px;
  border-bottom: var(--border-heavy) solid transparent;
}

.site-nav a.active {
  color: var(--ink);
  font-weight: 600;
  border-bottom-color: var(--pen-red);
}

.user-info {
  margin-left: auto;
  display: flex;
  align-items: baseline;
  gap: 14px;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--faint);
}

.user-info a {
  color: var(--pen-blue);
}

/* The admin area's own tab strip, under the site header. Same voice as .site-nav
   (mono, uppercase, red underline on the active tab) but subordinate to it: a thin
   rule instead of the header's heavy one, so the hierarchy reads at a glance. */
.admin-nav {
  display: flex;
  gap: 22px;
  margin-bottom: 20px;
  padding-bottom: 8px;
  border-bottom: var(--border-thin) solid var(--rule);
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  letter-spacing: 1px;
  text-transform: uppercase;
}

.admin-nav a {
  color: var(--faint);
  text-decoration: none;
  padding-bottom: 2px;
  border-bottom: var(--border-heavy) solid transparent;
}

.admin-nav a.active {
  color: var(--ink);
  font-weight: 600;
  border-bottom-color: var(--pen-red);
}

.admin-nav a:hover {
  color: var(--pen-blue);
}

/* Identifier-shaped table cells — MAC addresses, ZigBee ids, Modbus addresses.
   Mono so eyes can diff two of them; never applied to prose. */
.ledger-table td.mono {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
}

/* The savings window picker, sitting inside a panel title. Sized to the text it
   holds rather than the form-field default, so the heading still reads as a
   heading with a control in it, not a form with a label. */
.panel-title .range-select {
  margin-left: 10px;
  padding: 2px 6px;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--muted);
  background: var(--input-bg);
  border: var(--border-thin) solid var(--rule);
  width: auto;
}

/* Light/dark switch. Styled like the nav labels rather than as a prominent control: it is a
   display preference, not a place anyone needs to be sent. Its text is written by site.js. */
.theme-toggle {
  padding: 2px 0;
  background: none;
  border: none;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--faint);
}

.theme-toggle:hover {
  color: var(--pen-blue);
}

.theme-toggle:focus-visible {
  outline: var(--border-thick) solid var(--pen-blue);
  outline-offset: 3px;
}

/* On the login page the toggle stands alone under the card with nothing to
   align to — frame it like a small stamp so it reads as a control, not a
   stray label. (In the header it stays the quiet nav-voice element above.) */
.auth-shell .theme-toggle {
  margin-top: 14px;
  padding: 4px 12px;
  border: var(--border-thin) solid var(--rule);
  border-radius: var(--radius-sm);
}

/* The header's user menu is a <details>/<summary> disclosure, so "is it open" is element state
   rather than a class this stylesheet has to coordinate with JavaScript. The caret is drawn with
   borders instead of a glyph so it doesn't depend on the display font shipping U+25BE; its size is
   geometry (like the paddings in this file), its color comes from a token. */

.user-menu {
  position: relative;
}

.user-menu > summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 2px 0;
  color: var(--ink);
}

.user-menu > summary::-webkit-details-marker {
  display: none;
}

.user-menu > summary:hover {
  color: var(--pen-blue);
}

.user-menu > summary:focus-visible {
  outline: var(--border-thick) solid var(--pen-blue);
  outline-offset: 3px;
}

.user-menu .caret {
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid var(--faint);
}

.user-menu[open] > summary {
  color: var(--pen-blue);
}

.user-menu[open] .caret {
  transform: rotate(180deg);
}

.user-menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 9px);
  z-index: 30;
  min-width: 172px;
  display: flex;
  flex-direction: column;
  padding: 5px 0;
  background: var(--panel);
  border: var(--border-thin) solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
}

.user-menu-panel form {
  margin: 0;
}

.user-info .user-menu-panel a,
.user-menu-panel button {
  display: block;
  width: 100%;
  padding: 7px 14px;
  background: none;
  border: none;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  font: inherit;
  color: var(--ink);
}

.user-info .user-menu-panel a:hover,
.user-menu-panel button:hover {
  background: var(--hover);
  color: var(--pen-blue);
}

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

.page {
  padding: 24px;
  max-width: 1200px;
  margin: 0 auto;
}

.back-link {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--pen-blue);
  cursor: pointer;
  display: inline-block;
  margin-bottom: 10px;
  text-decoration: none;
}

/* ---------------------------------------------------------------------
   Page heading block (doc-title) + status chip + subtitle line
--------------------------------------------------------------------- */

.doc-title {
  display: flex;
  align-items: baseline;
  gap: 16px;
  margin-bottom: 4px;
  flex-wrap: wrap;
}

.doc-title h2 {
  font-family: var(--font-display);
  font-size: var(--fs-display);
  font-weight: 600;
  margin: 0;
  letter-spacing: 0.3px;
}

.status-chip {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  white-space: nowrap; /* a rubber stamp never wraps mid-word */
  border: var(--border-thick) solid;
  border-radius: var(--radius-sm);
  padding: 2px 9px;
  transform: rotate(-1.2deg);
  display: inline-block;
}

.status-chip.attend {
  color: var(--pen-red);
  border-color: var(--pen-red);
}

.status-chip.normal {
  color: var(--ok);
  border-color: var(--ok);
}

/* For states that are information, not alerts — "this week", "monitor". Same
   stamp, uninked: the row reads as settled rather than shouting. */
.status-chip.quiet {
  color: var(--faint);
  border-color: var(--rule);
}

.status-chip.watch {
  color: var(--warn);
  border-color: var(--warn);
}

.sub {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--faint);
  margin-bottom: 16px;
}

/* ---------------------------------------------------------------------
   Ledger head (stat strip) + ledger table
--------------------------------------------------------------------- */

.ledger-head {
  display: flex;
  gap: 26px;
  border-top: var(--border-thin) solid var(--rule);
  border-bottom: var(--border-thin) solid var(--rule);
  padding: 8px 0;
  margin-bottom: 14px;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--muted);
  flex-wrap: wrap;
}

.ledger-head b {
  color: var(--ink);
  font-size: var(--fs-body);
  font-weight: 600;
}

/* A control that belongs to the statistic beside it ("Inactive 3  show"), not another statistic.
   Set back from the number so the pair reads as one item in the strip's rhythm. */
.ledger-head a:not(.csv-link) {
  margin-left: 7px;
}

/* A strip of ACTIONS (preview links, a test-send button) rather than statistics:
   csv-link's right-alignment margin would distribute multiple actions across the
   whole strip, so here they cluster left in reading order. */
.ledger-head.actions {
  align-items: center;
}
.ledger-head.actions .csv-link {
  margin-left: 0;
}

.ledger-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-body);
}

.ledger-table th {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--faint);
  text-align: left;
  padding: 6px 10px;
  border-bottom: var(--border-thick) solid var(--ink);
}

.ledger-table th.num {
  text-align: right;
}

.ledger-table td {
  padding: 8px 10px;
  border-bottom: var(--border-thin) solid var(--grid);
  font-variant-numeric: tabular-nums;
}

.ledger-table tr.row-link {
  cursor: pointer;
}

.ledger-table tr.row-link:hover td {
  background: var(--hover);
}

/* The "Show inactive" filter, sitting between the stat strip and the table it filters. Set in the
   label voice — mono, uppercase, tracked — because that is what this system uses for a form label,
   but at reading size rather than micro: it is a control someone reaches for, not a column head.
   The checkbox keeps its native rendering; a hand-drawn one would cost the platform's own focus,
   keyboard and forced-colours behaviour to gain nothing this design asks for. */
.show-inactive {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: -6px 0 14px;
}

.show-inactive label {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  letter-spacing: 1px;
  text-transform: uppercase;
  color: var(--muted);
}

.show-inactive label:hover {
  color: var(--pen-blue);
}

.show-inactive input[type="checkbox"] {
  accent-color: var(--pen-blue);
  cursor: pointer;
  margin: 0;
}

.show-inactive input[type="checkbox"]:focus-visible {
  outline: var(--border-thick) solid var(--pen-blue);
  outline-offset: 3px;
}

/* The no-script fallback submit: present in the markup, removed by site.js. */
.show-inactive .btn {
  margin-top: 0;
}

/* A retired unit card. The card keeps its shape — it is still a real controller with a last known
   reading — but the reading drops from Pen Blue to Muted, because that colour is the system's way
   of saying "this is the current value" and on a deactivated unit it is not current, it is the last
   thing seen before someone switched it off. The Inactive stamp in the corner carries the state. */
.unit-card.unit-card-inactive .reading {
  color: var(--muted);
}

.unit-card.unit-card-inactive h3 {
  color: var(--muted);
}

/* A deactivated row: still a record, no longer a place you can go. It reads back one tone (Muted
   rather than Ink) and takes no hover or pointer, because there is nothing to click — the site's
   own page does not exist while it is inactive. The "Inactive" stamp carries the meaning; this is
   only the supporting weight, so the row never looks like a disabled control someone should retry. */
.ledger-table tr.row-inactive td {
  color: var(--muted);
}

.ledger-table tr.row-inactive td .why a {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
}

/* site.js makes these rows a real tab stop; this is what arriving on one looks like. The row tints
   like a hover so the whole row reads as the target, and the ring says which one has focus. */
.ledger-table tr.row-link:focus-visible {
  outline: var(--border-thick) solid var(--pen-blue);
  outline-offset: -2px;
}

.ledger-table tr.row-link:focus-visible td {
  background: var(--hover);
}

.ledger-table td.num {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  text-align: right;
}

.ledger-table td .why {
  color: var(--muted);
  font-size: var(--fs-small);
}

.ledger-table td.checkbox-cell {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  text-align: center;
}

/* ---------------------------------------------------------------------
   Unit cards
--------------------------------------------------------------------- */

.unit-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-bottom: 18px;
}

.unit-card {
  background: var(--panel);
  border: var(--border-thin) solid var(--rule);
  border-radius: var(--radius);
  padding: 14px 16px;
  position: relative;
}

.unit-card h3 {
  font-family: var(--font-display);
  font-size: var(--fs-title);
  font-weight: 600;
  margin: 0 0 2px;
}

.unit-card .tag {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 1.2px;
  color: var(--faint);
  text-transform: uppercase;
}

.unit-card .reading {
  font-family: var(--font-mono);
  font-size: var(--fs-display);
  font-weight: 600;
  margin: 8px 0 2px;
  color: var(--pen-blue);
}

.unit-card.attend .reading {
  color: var(--pen-red);
}

.unit-card .reading small {
  font-size: var(--fs-body);
  color: var(--muted);
  font-weight: 500;
}

.unit-card .stats {
  display: flex;
  gap: 16px;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--muted);
  margin-top: 8px;
  flex-wrap: wrap;
  /* .settings-link is pinned to the card's bottom-right corner and is out of flow, so this row has
     to keep clear of it or the two collide — which is exactly what happened when the type ramp made
     this row wider. Reserved in `ch` against this row's own mono font: "Settings" is 8 characters,
     plus the link's 12px inset and a gap. Because ch tracks --fs-small, the reservation resizes
     with the ramp instead of going stale the next time a step moves. */
  padding-right: calc(8ch + 26px);
}

.unit-card .stats b {
  color: var(--ink);
  font-weight: 600;
}

.unit-card .status-chip {
  position: absolute;
  top: 12px;
  right: 12px;
}

.unit-card .settings-link {
  position: absolute;
  bottom: 12px;
  right: 12px;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--pen-blue);
  cursor: pointer;
  text-decoration: none;
  border-bottom: var(--border-thin) solid var(--pen-blue);
}

/* ---------------------------------------------------------------------
   Chart / info panels
--------------------------------------------------------------------- */

.chart-panel,
.panel-box {
  background: var(--panel);
  border: var(--border-thin) solid var(--rule);
  border-radius: var(--radius);
  padding: 14px 16px;
}

.chart-panel h4,
.panel-box h4 {
  margin: 0 0 2px;
  font-family: var(--font-display);
  font-size: var(--fs-title);
  font-weight: 600;
}

.chart-panel .sub,
.panel-box .sub {
  margin-bottom: 8px;
}

/* Named for the one thing it styles, not for a container. This started as a bare `svg` rule, which
   also caught Leaflet's internal marker and attribution SVGs on the map — Leaflet sizes those with
   width/height attributes, so stretching them to 100% broke its coordinate mapping and made every
   status marker invisible. Map.cshtml carried a counter-override for that.

   Scoping it to `.chart-panel svg` did not help: #fleet-map lives inside a .chart-panel too, so the
   rule still reached Leaflet — verified by the markers disappearing again. The container is not the
   distinguishing fact; being a hand-drawn strip chart is. Hence a class on the element itself, and
   no override needed anywhere. */
.strip-chart {
  display: block;
  width: 100%;
  height: auto;
}

/* ---------------------------------------------------------------------
   Entry forms
--------------------------------------------------------------------- */

.entry-form {
  background: var(--panel);
  border: var(--border-thin) solid var(--rule);
  border-radius: var(--radius);
  padding: 18px 20px;
  /* 560px squeezed two-column fields to ~250px — too narrow for an address or
     an email. 680px keeps the form a column, not a sheet, and gives each field
     of the pair a usable ~305px. */
  max-width: 680px;
}

/* A form whose body is a TABLE (the recipients editor) needs the width of a
   ledger, not of a field column — capped at 680 its own email/name floors
   forced a horizontal scrollbar that hid the Add button on a desktop. */
.entry-form.entry-form-wide {
  max-width: 980px;
}

.entry-form h4 {
  margin: 0 0 12px;
  font-family: var(--font-display);
  font-size: var(--fs-title);
  font-weight: 600;
}

.entry-form .field {
  margin-bottom: 12px;
}

.entry-form .field-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.entry-form label,
label,
.field-key {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 1.4px;
  text-transform: uppercase;
  color: var(--faint);
  margin-bottom: 4px;
}

.field-input {
  width: 100%;
  background: var(--input-bg);
  border: none;
  border-bottom: var(--border-thick) solid var(--rule);
  color: var(--ink);
  font: var(--fs-body) var(--font-mono);
  padding: 6px 2px;
  font-variant-numeric: tabular-nums;
}

.field-input:focus {
  outline: none;
  border-bottom-color: var(--pen-blue);
}

/* Every ledger table sits in one of these. On a desktop it does nothing; in a
   narrow window or on a phone the TABLE keeps its native layout — every column,
   correct row heights — and scrolls inside this box, so the page itself never
   scrolls sideways. (Setting display:block on the table instead was tried and
   ballooned any row holding a long finding paragraph.) */
.ledger-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* A field inside a ledger cell (the recipients editor, any inline-edit row) is
   sized by the column, and columns size to their longest TEXT — an empty input
   collapses to nothing. Floors keep an email or a name legible while typing;
   the email floor fits a realistic address, not just user@x.io. */
.ledger-table td .field-input {
  min-width: 11rem;
}
.ledger-table td input[type="email"].field-input {
  min-width: 20rem;
}

.form-error {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--pen-red);
  margin: 0 0 12px;
}

/* Confirmation of something that just happened — the counterpart to .form-error. */
.form-note {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--ok);
  margin: 0 0 14px;
}

/* A value the form shows but does not let this user edit: the same slot as .field-input, without
   the affordances of one. The dashed, lighter rule under it is what says "not a field you can type
   in" — a solid rule of the same weight reads as an input someone should be able to click into. */
.field-static {
  margin: 0;
  padding: 6px 2px;
  font: var(--fs-body) var(--font-mono);
  color: var(--muted);
  border-bottom: var(--border-thick) dashed var(--grid);
}

/* A lowercase word stored in the database (usertype_name is "general user") shown as a label. */
.field-static.db-term {
  text-transform: capitalize;
}

/* A second form panel stacked under the first. */
.form-stack {
  margin-top: 18px;
}

/* A "Download CSV" link. Sized like the stat strip it usually sits in, and pushed to the far end
   of it, so it reads as an action on that table rather than another statistic. */
.csv-link {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  letter-spacing: 0.6px;
  color: var(--pen-blue);
  text-decoration: none;
  white-space: nowrap;
}

.csv-link:hover {
  text-decoration: underline;
}

/* ---------------------------------------------------------------------
   Ledger tools (search / status filter / page size) + pager strip.
   Both strips are injected by ledger-tools.js on tables marked data-tools;
   with scripting off neither exists and the full table simply renders.
--------------------------------------------------------------------- */

.ledger-tools {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--muted);
  flex-wrap: wrap;
}

.ledger-tools .ledger-search {
  flex: 0 1 280px;
  padding: 4px 8px;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--ink);
  background: var(--input-bg);
  border: var(--border-thin) solid var(--rule);
}

.ledger-tools .ledger-search:focus {
  outline: none;
  border-color: var(--pen-blue);
}

.ledger-tools select {
  padding: 3px 6px;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--muted);
  background: var(--input-bg);
  border: var(--border-thin) solid var(--rule);
  width: auto;
}

/* Page size sits opposite the filters: it belongs to the pager below, not the search. */
.ledger-tools .pg-size {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}

.ledger-foot {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 0;
  margin-bottom: 18px;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--muted);
}

.ledger-foot button {
  padding: 2px 10px;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  color: var(--muted);
  background: none;
  border: var(--border-thin) solid var(--rule);
  cursor: pointer;
}

.ledger-foot button:hover:not(:disabled) {
  color: var(--ink);
  border-color: var(--ink);
}

.ledger-foot button:disabled {
  color: var(--faint);
  cursor: default;
}

.ledger-foot .pg-range {
  margin-left: auto;
}

/* Rows paged or filtered out of view. Only ever set by ledger-tools.js. */
.ledger-table tr.pg-hide {
  display: none;
}

.ledger-table tr.pg-empty td {
  color: var(--faint);
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  padding: 14px 10px;
}

/* A panel's title line when something (the CSV link) sits opposite the heading. */
.panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
}

.panel-head h4 {
  margin-bottom: 0;
}

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

.btn {
  background: var(--ink);
  color: var(--on-ink);
  border: none;
  border-radius: var(--radius);
  font: 600 var(--fs-body) var(--font-body);
  padding: 8px 18px;
  margin-top: 16px;
  cursor: pointer;
  display: inline-block;
  text-decoration: none;
}

.btn-ghost {
  background: transparent;
  color: var(--muted);
  border: var(--border-thin) solid var(--rule);
  margin-left: 8px;
}

/* The two buttons were the only interactive things in the system with no response to hover or
   keyboard focus — every other one (nav, menu summary, theme toggle) already shifts to
   --pen-blue on hover and takes a pen-blue ring on :focus-visible. These follow that same
   language rather than inventing a second one, so the buttons stop being the exception.
   :active nudges by 1px: a flat, workmanlike system can still acknowledge a press. */
.btn:hover {
  background: var(--pen-blue);
}

.btn-ghost:hover {
  color: var(--pen-blue);
  border-color: var(--pen-blue);
  background: transparent;
}

.btn:active,
.btn-ghost:active {
  transform: translateY(1px);
}

.btn:focus-visible,
.btn-ghost:focus-visible {
  outline: var(--border-thick) solid var(--pen-blue);
  outline-offset: 3px;
}

/* Links carry the browser's default ring, which changes shape and color between browsers and
   ignores the palette. One treatment for every focusable thing is easier to recognise than four. */
a:focus-visible {
  outline: var(--border-thick) solid var(--pen-blue);
  outline-offset: 3px;
}

/* ---------------------------------------------------------------------
   Standalone auth / error pages (login, forbidden, not-found)
--------------------------------------------------------------------- */

.auth-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  /* transparent on purpose: body's chart-paper ground is the login page's
     whole scenery — an opaque paper here blanked it out */
  padding: 24px;
}

.auth-card {
  background: var(--panel);
  border: var(--border-thin) solid var(--rule);
  border-radius: var(--radius);
  padding: 20px 24px;
  max-width: 420px;
  width: 100%;
}

.auth-card .doc-title {
  margin-bottom: 4px;
}

.auth-card .sub {
  margin-bottom: 16px;
}

/* ---------------------------------------------------------------------
   Responsive
--------------------------------------------------------------------- */

@media (max-width: 760px) {
  .unit-cards {
    grid-template-columns: 1fr;
  }
  .entry-form .field-grid {
    grid-template-columns: 1fr;
  }
  .site-nav {
    gap: 12px;
  }

  /* ---- Phone layer -------------------------------------------------------
     The rule everywhere below: the PAGE never scrolls sideways; anything wide
     scrolls inside its own box. A ledger keeps every column — an admin on a
     phone is usually hunting one row, and losing columns loses the row. */
  .page {
    padding: 14px 12px;
  }
  .site-header {
    padding: 12px 14px 10px;
    gap: 12px 18px;
    align-items: center;
  }
  .user-info {
    flex-basis: 100%;
    justify-content: flex-end;
  }
  .site-nav,
  .admin-nav {
    flex-wrap: wrap;
    gap: 8px 16px;
  }
  .ledger-head,
  .doc-title {
    flex-wrap: wrap;
    row-gap: 4px;
  }
  /* Comfortable thumbs: the pager and toolbar controls grow to tappable size
     only where a finger is the pointer. */
  .btn,
  .btn-ghost,
  .ledger-foot button {
    padding-top: 8px;
    padding-bottom: 8px;
  }
  .ledger-tools {
    flex-wrap: wrap;
    row-gap: 8px;
  }
  .ledger-tools .ledger-search {
    flex: 1 1 100%;
  }
  .pg-size {
    margin-left: 0;
  }
  .entry-form {
    padding: 14px;
  }
}

/* The add-recipient row on the report page: five cells across is wider than a
   phone, and the one that fell off the edge was the Add button — the row's
   whole point. Under 640px the row stacks; the .cell-label spans (hidden on
   desktop, where the column headers do this job) caption the two edition
   checkboxes so they aren't bare boxes. */
.cell-label {
  display: none;
}

@media (max-width: 640px) {
  #add {
    display: block;
    border-top: var(--border-thin) solid var(--rule);
    padding-top: 8px;
  }
  #add td {
    display: block;
    border: none;
    padding: 4px 0;
    text-align: left; /* stacked cells read as a form; checkbox-cell centering doesn't */
  }
  #add .field-input,
  .ledger-table td #add input[type="email"].field-input {
    min-width: 0;
    width: 100%;
  }
  .cell-label {
    display: inline;
    font-family: var(--font-mono);
    font-size: var(--fs-label);
    letter-spacing: 1.4px;
    text-transform: uppercase;
    color: var(--faint);
    margin-left: 6px;
  }
}

/* ---------------------------------------------------------------------------
   Energy panels — savings and cooler/freezer performance on the company page.

   Two instruments and a ledger, not three pie charts. See the comment in
   Companies/Detail.cshtml for why the ring is spent on the energy split rather
   than on the per-site comparisons.

   Every ink here is a token. The three split colours reuse the existing pen and
   status inks rather than introducing a fourth and fifth: fan is the recorder
   pen, compressor the target-line green, defrost the amber that already marks a
   defrost band on the strip chart. That last one is not a coincidence — it is
   the same event in a different view, and it should be the same colour.
   --------------------------------------------------------------------------- */

.energy {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 16px;
  margin: 16px 0 24px;
}

.energy-panel {
  background: var(--panel);
  border: var(--border-thin) solid var(--rule);
  border-radius: var(--radius);
  padding: 14px 16px 12px;
}

.panel-title {
  font-family: var(--font-display);
  font-size: var(--fs-title);
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 12px;
  padding-bottom: 6px;
  border-bottom: var(--border-heavy) solid var(--ink);
}

.energy-headline {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
}

.ring-wrap { flex: 0 0 auto; }

.split-ring {
  width: 104px;
  height: 104px;
  display: block;
}

/* Butt caps, not round: a rounded cap overlaps its neighbour and makes a small
   slice look larger than it is. */
.ring-track,
.ring-arc {
  fill: none;
  stroke-width: 13;
  stroke-linecap: butt;
}

.ring-track { stroke: var(--grid); }
.ring-fan { stroke: var(--pen-blue); }
.ring-compressor { stroke: var(--ok); }
.ring-defrost { stroke: var(--warn); }

.energy-total { flex: 1 1 12rem; min-width: 0; }

.energy-total .reading { margin: 2px 0 0; }

.energy-total .sub { margin: 2px 0 10px; }

.split-key {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.split-item {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  font-variant-numeric: tabular-nums;
}

/* The key's swatch is a rule, not a dot — it is a length of the same pen that
   drew the arc. */
.split-item dt {
  position: relative;
  padding-left: 20px;
  color: var(--muted);
  flex: 1 1 auto;
}

.split-item dt::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 13px;
  border-top: var(--border-heavy) solid currentColor;
}

.split-fan dt { color: var(--pen-blue); }
.split-compressor dt { color: var(--ok); }
.split-defrost dt { color: var(--warn); }

.split-item dd {
  margin: 0;
  color: var(--ink);
  white-space: nowrap;
}

/* --- ranked savings ------------------------------------------------------ */

.bar-list {
  list-style: none;
  margin: 14px 0 0;
  padding: 12px 0 0;
  border-top: var(--border-thin) solid var(--grid);
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.bar-row {
  display: grid;
  grid-template-columns: minmax(6rem, 9rem) 1fr auto;
  align-items: center;
  gap: 10px;
}

.bar-name {
  font-size: var(--fs-small);
  color: var(--pen-blue);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bar-track {
  height: 9px;
  background: var(--paper);
  border: var(--border-thin) solid var(--grid);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.bar-fill {
  display: block;
  height: 100%;
  background: var(--pen-blue);
  min-width: 1px;
}

.bar-watch .bar-fill { background: var(--warn); }
.bar-attend .bar-fill { background: var(--pen-red); }

.bar-value {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  white-space: nowrap;
}

.bar-note {
  font-family: var(--font-body);
  font-size: var(--fs-small);
  color: var(--faint);
  margin: 10px 0 0;
}

/* --- performance scales --------------------------------------------------- */

.perf-averages {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
}

.perf-averages .reading { margin: 2px 0 0; }

.scale-list {
  list-style: none;
  margin: 14px 0 0;
  padding: 12px 0 0;
  border-top: var(--border-thin) solid var(--grid);
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.scale-row {
  display: grid;
  grid-template-columns: minmax(6rem, 9rem) 1fr;
  align-items: center;
  gap: 10px;
}

.scale-name {
  font-size: var(--fs-small);
  color: var(--pen-blue);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.scale-pair {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.scale-line {
  display: grid;
  grid-template-columns: 1.1rem 1fr 3.1rem;
  align-items: center;
  gap: 8px;
}

.scale-kind,
.scale-value {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-variant-numeric: tabular-nums;
  color: var(--faint);
  letter-spacing: 1.4px;
}

.scale-value {
  text-align: right;
  color: var(--ink);
  letter-spacing: normal;
}

/* The rule is the instrument: a 0-100 scale with a quarter tick, so a marker's
   position is readable without a second number beside it. */
.scale-rule {
  position: relative;
  height: 12px;
  border-bottom: var(--border-thin) solid var(--line);
  background-image: linear-gradient(to right, var(--grid) var(--border-thin), transparent var(--border-thin));
  background-size: 25% 100%;
  background-position: 0 0;
}

.scale-mark {
  position: absolute;
  bottom: -1px;
  width: 0;
  height: 9px;
  border-left: var(--border-thick) solid var(--pen-blue);
  transform: translateX(-50%);
}

.scale-line[data-kind="freezer"] .scale-mark { border-left-color: var(--ink); }

@media (max-width: 640px) {
  .bar-row,
  .scale-row { grid-template-columns: 1fr; gap: 4px; }
  .bar-value { justify-self: end; }
}

/* The rule's stated range, on the same grid as a scale row so the ticks land
   over the scale rather than near it. Three equal columns rather than
   space-between: the labels are different widths, and space-between would put
   the midpoint wherever the middle label happened to end. */
.scale-axis {
  display: grid;
  grid-template-columns: minmax(6rem, 9rem) 1fr;
  gap: 10px;
  margin: 12px 0 0;
}

.scale-axis-ticks {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  padding-left: calc(1.1rem + 8px);
  padding-right: calc(3.1rem + 8px);
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 1.4px;
  color: var(--faint);
}

.scale-axis-ticks > span:nth-child(2) { text-align: center; }
.scale-axis-ticks > span:nth-child(3) { text-align: right; }

/* The average, as a dashed reference — the same convention the strip chart uses
   for a target line, and the same ink. Without it the rule shows where a unit
   is but not whether that is good, which is the actual question. */
.scale-average {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 0;
  border-left: var(--border-thin) dashed var(--ok);
  transform: translateX(-50%);
}

/* The second way in. A ruled "or" rather than a plain gap: this is a fork in a
   form, and the rule says so without a heading. */
.alt-signin { margin-top: 18px; }

.alt-signin-rule {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 12px;
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 1.4px;
  color: var(--faint);
}

.alt-signin-rule::before,
.alt-signin-rule::after {
  content: "";
  flex: 1;
  border-top: var(--border-thin) solid var(--grid);
}

.alt-signin .btn-ghost { width: 100%; }

.passkeys { margin-top: 28px; }
.passkeys h3 {
  font-family: var(--font-display);
  font-size: var(--fs-title);
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 4px;
}
.passkeys .ledger-table { margin-top: 12px; }
.passkey-add { margin-top: 16px; max-width: 22rem; }
.passkey-add .btn { margin-top: 8px; }
