/*
 * One page, one stylesheet.
 *
 * The same vocabulary as the two benches next door -- the same tokens, the same
 * three scales, the same rule about the face. Sizes, dims and gaps are scales:
 * pick a step, never write a fresh number. The one rule that carries meaning is
 * the face -- a machine-produced fact is set in the mono one, and an ICCID, an
 * address and an IMEI are all machine-produced facts.
 *
 * This file is downloaded by whoever opens the page, comments included.
 */

:root {
  --ink: #17191c;
  --ink-quiet: #4a4f57;
  --ink-faint: #767c86;
  --page: #f7f8fa;
  --card: #ffffff;
  --edge: #dfe3e8;
  --accent: #1a5fb4;
  --bad: #b3261e;
  --good: #1c7c48;
  --waiting: #8a5a00;

  --text-caption: 0.75rem;
  --text-small: 0.85rem;
  --text-body: 0.95rem;
  --text-lead: 1.1rem;
  --text-title: 1.5rem;

  /* One height for everything on a form row. Saying it once is what stops a
     button drifting away from the fields beside it. */
  --control: 34px;

  --gap-xs: 4px;
  --gap-s: 8px;
  --gap-m: 12px;
  --gap-l: 20px;
  --gap-xl: 32px;

  --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --font: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  padding: var(--gap-xl) var(--gap-l);
  background: var(--page);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--text-body);
  line-height: 1.5;
}

/*
 * **This bench is wider than the two next door, on purpose.**
 *
 * They cap at 1400px because what they show is prose and a few columns, and a
 * long line of prose is hard to read. This shows an account: as many columns as
 * the provider sends, which was twelve on the first real one. Capping it would
 * push half of them behind a sideways scroll on a screen with room for them.
 *
 * The reading width still applies to the prose: `.lede` keeps its own 70ch.
 */
main, .masthead { max-width: none; margin: 0 auto; }
.masthead { padding: 0 calc(var(--gap-l) + 1px); }
.masthead h1 { font-size: var(--text-title); margin: 0 0 var(--gap-xs); font-weight: 600; }
.lede { margin: 0 0 var(--gap-l); color: var(--ink-quiet); max-width: 70ch; }

.panel {
  background: var(--card);
  border: 1px solid var(--edge);
  border-radius: 8px;
  padding: var(--gap-l);
  margin-bottom: var(--gap-l);
}

.field { display: block; margin-bottom: var(--gap-m); }
.label { display: block; font-size: var(--text-small); color: var(--ink-quiet); margin-bottom: var(--gap-xs); }
.hint { color: var(--ink-faint); font-weight: 400; }

input[type=text], input[type=password], input[type=search], select {
  width: 100%;
  font-family: var(--font-mono);
  font-size: var(--text-small);
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--edge);
  border-radius: 6px;
  padding: var(--gap-s) var(--gap-m);
  height: var(--control);
}
select { font-family: var(--font); cursor: pointer; }

input:focus-visible, select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: var(--accent);
}

.row { display: flex; gap: var(--gap-m); align-items: flex-end; flex-wrap: wrap; }
.row .field { margin-bottom: 0; }
.narrow { width: 200px; }
.grow { flex: 1 1 240px; }

button {
  font: inherit;
  font-size: var(--text-small);
  padding: 0 var(--gap-l);
  height: var(--control);
  border: 1px solid transparent;
  border-radius: 6px;
  background: var(--accent);
  color: #fff;
  cursor: pointer;
}
button:hover { filter: brightness(1.08); }
button[disabled] { opacity: 0.6; cursor: default; }
button[disabled]:hover { filter: none; }
button.quiet {
  background: var(--card);
  color: var(--accent);
  border-color: var(--edge);
}
button.quiet:hover { filter: none; border-color: var(--accent); }
button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.privacy {
  margin: var(--gap-m) 0 0;
  font-size: var(--text-caption);
  color: var(--ink-faint);
  max-width: 70ch;
}

/*
 * The sign-in, which is the one narrow thing on a page that is otherwise as
 * wide as the screen.
 *
 * **Two fields and a button do not want the width of an account.** Stretched
 * across a large screen they sit a hand's width apart with nothing between
 * them, and the eye has to travel the whole page to fill two boxes. So this
 * column is sized by what is in it -- a field, then a field, then the button
 * -- and centred, while the table next door still gets everything.
 *
 * The heading and the lede join it, because a left-aligned title over a
 * centred card reads as a mistake. They go back to the full width the moment
 * somebody signs in, which is what `body.signed-in` says.
 */
#signin, #signin-error { max-width: 24rem; margin-left: auto; margin-right: auto; }
#signin .field:last-of-type { margin-bottom: var(--gap-l); }
button.wide { width: 100%; }

body:not(.signed-in) .masthead {
  max-width: 24rem;
  margin: 0 auto;
  padding: 0;
}

.refusal {
  background: var(--card);
  border: 1px solid var(--bad);
  border-left-width: 4px;
  border-radius: 6px;
  padding: var(--gap-m) var(--gap-l);
  margin: 0 0 var(--gap-l);
  color: var(--bad);
}

.empty { color: var(--ink-faint); font-size: var(--text-small); margin: var(--gap-m) 0 0; }

/* ------------------------------------------------------------- the account */

.summary {
  display: flex;
  gap: var(--gap-xl);
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: var(--gap-l);
  padding: var(--gap-m) var(--gap-l);
  background: var(--card);
  border: 1px solid var(--edge);
  border-radius: 8px;
}

.fact { display: flex; flex-direction: column; }
.fact .name { font-size: var(--text-caption); color: var(--ink-faint); text-transform: uppercase; letter-spacing: 0.04em; }
.fact .value { font-family: var(--font-mono); font-size: var(--text-lead); }

.heading { font-size: var(--text-lead); font-weight: 600; margin: var(--gap-xl) 0 var(--gap-m); }
.panel .heading { margin-top: 0; }

/*
 * The account, as many columns wide as the provider sends.
 *
 * The box scrolls rather than the page, and the head stays put while it does: a
 * label is the widest thing here and the ICCID beside it is the column a reader
 * loses first.
 */
.sheet {
  background: var(--card);
  border: 1px solid var(--edge);
  border-radius: 8px;
  overflow: auto;
  max-height: 70vh;
}

.rows {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-small);
}
.rows th, .rows td {
  text-align: left;
  padding: var(--gap-s) var(--gap-m);
  border-bottom: 1px solid var(--edge);
  white-space: nowrap;
}
.rows th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--card);
  font-size: var(--text-caption);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
  font-weight: 600;
  cursor: pointer;
  user-select: none;
}
.rows th:hover { color: var(--accent); }
.rows th .arrow { color: var(--accent); }
.rows tbody tr:last-child td { border-bottom: none; }
.rows tbody tr { cursor: pointer; }
.rows tbody tr:hover { background: var(--page); }

/* A machine-produced fact in the mono face; a label is prose somebody typed,
   and it is the one column allowed to wrap. */
.rows td.mono { font-family: var(--font-mono); }
.rows td.label-cell { white-space: normal; min-width: 22rem; }
.rows td.blank { color: var(--ink-faint); }

/* 1NCE's own three words for what a SIM has left. The one that means somebody
   has to act is the one that is coloured. */
.rows td.is-exceeded, .is-exceeded { color: var(--bad); }
.rows td.is-low, .is-low { color: var(--waiting); }
.rows td.is-disabled { color: var(--ink-faint); }

.pager { display: flex; gap: var(--gap-m); align-items: center; margin-top: var(--gap-m); }
.pager span { color: var(--ink-quiet); font-size: var(--text-small); }

/* ------------------------------------------------------------------ one SIM */

/* The heading takes the room and the way back sits at the right edge, where it
   is out of the way of the thing somebody came to read.
 *
 * **The same inset as the masthead**, so the SIM's name starts under the page's
 * own title rather than a panel's width to the left of it. The number is the
 * masthead's own: a panel's padding plus its border, which is what puts `SIM
 * bench` over the text inside a card. */
.detail-head {
  margin-bottom: var(--gap-l);
  padding: 0 calc(var(--gap-l) + 1px);
  align-items: center;
  flex-wrap: nowrap;
}
/* Sized to the name, so the pencil sits against it. The spacer after them is
   what pushes the two buttons to the right edge. */
.detail-head h2 { font-size: var(--text-lead); font-weight: 600; margin: 0; flex: 0 1 auto; min-width: 0; }
.detail-head button { flex: 0 0 auto; }

.panels { display: flex; flex-wrap: wrap; gap: var(--gap-l); align-items: flex-start; }
.panels > .panel, .panels > .column { flex: 1 1 22rem; margin-bottom: 0; }
/* Data left, Network and the changes are each short. Stacked in one column
   they read as one side of the page rather than as three loose boxes. */
.column { display: flex; flex-direction: column; gap: var(--gap-l); }
.column .panel { margin-bottom: 0; }

/* The name takes the room; the spacer pushes the two buttons to the right
   edge, where the way back already was. */
.detail-head .spacer { flex: 1 1 auto; }

/* A pencil beside the name, sized to the text rather than to a button: it is
   an affordance on the heading and not a third control competing with the two
   at the other end. */
button.pencil {
  background: none;
  border: none;
  color: var(--ink-faint);
  height: auto;
  padding: 0 var(--gap-xs);
  font-size: var(--text-lead);
  line-height: 1;
}
button.pencil:hover { filter: none; color: var(--accent); }

dialog {
  border: 1px solid var(--edge);
  border-radius: 8px;
  padding: var(--gap-l);
  max-width: 34rem;
  width: calc(100% - 2 * var(--gap-l));
  color: var(--ink);
  background: var(--card);
}
dialog::backdrop { background: rgb(23 25 28 / 40%); }
dialog .heading { margin-top: 0; }
dialog .privacy { margin-top: 0; margin-bottom: var(--gap-m); }
dialog .field { margin-bottom: var(--gap-l); }
dialog .refusal { margin-bottom: var(--gap-m); }

/* The provider's own sentence under the number it belongs to. Quiet, because
   the number is the thing being read and this is what 1NCE calls it. */
dd.quiet-line {
  color: var(--ink-faint);
  font-family: var(--font);
  font-size: var(--text-caption);
  margin-top: calc(-1 * var(--gap-xs));
}
dd.quiet-line.is-exceeded { color: var(--bad); }
dd.quiet-line.is-low { color: var(--waiting); }

/* ----------------------------------------------------------------- traffic */

/* Three buttons that are one choice, so they read as a switch rather than as
   three things that might each do something. */
.choice { display: flex; }
.choice button {
  border-radius: 0;
  border: 1px solid var(--edge);
  background: var(--card);
  color: var(--accent);
  margin-left: -1px;
}
.choice button:first-child { border-radius: 6px 0 0 6px; margin-left: 0; }
.choice button:last-child { border-radius: 0 6px 6px 0; }
.choice button.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.choice button:hover { filter: none; }
.choice button:not(.on):hover { border-color: var(--accent); z-index: 1; }

/* The chart is one inline SVG this page draws itself: no bundler, no library,
   and nothing to keep in step. It scales to its box rather than being measured
   -- a chart drawn from a measurement is a chart that is empty whenever the box
   is hidden when it is drawn. */
#chart { margin-top: var(--gap-l); }
#chart svg { display: block; width: 100%; height: 220px; }
#chart .bar { fill: var(--accent); }
#chart .bar:hover { fill: var(--ink); }
#chart .axis { stroke: var(--edge); stroke-width: 1; }
#chart .tick { fill: var(--ink-faint); font-size: 10px; font-family: var(--font); }
#chart .nothing { fill: var(--ink-faint); font-size: 12px; font-family: var(--font); }

/* What a write came to, kept apart from a refusal: this is the provider
   agreeing, and it goes away on the next thing somebody does. */
.said {
  background: var(--card);
  border: 1px solid var(--good);
  border-left-width: 4px;
  border-radius: 6px;
  padding: var(--gap-m) var(--gap-l);
  margin: 0 0 var(--gap-l);
  color: var(--good);
}
.said.waiting { border-color: var(--waiting); color: var(--waiting); }

dl { margin: 0; }
dt { font-size: var(--text-caption); color: var(--ink-faint); text-transform: uppercase; letter-spacing: 0.04em; }
dd {
  margin: 0 0 var(--gap-m);
  font-family: var(--font-mono);
  font-size: var(--text-small);
  word-break: break-all;
}
dd:last-child { margin-bottom: 0; }
dd.blank { color: var(--ink-faint); font-family: var(--font); }

#events tbody tr { cursor: default; }
#events tbody tr:hover { background: none; }
#events td { white-space: normal; }
#events td:first-child { white-space: nowrap; font-family: var(--font-mono); }
