/*
  The corpus is instrument data, so the page is built like an instrument's readout rather
  than like a brochure: one neutral ground, one ink, and one accent that means "this is the
  thing you selected" and is never spent on decoration.

  The accent is the recorder's own highlight, so a stroke picked out here is the colour it
  is picked out in the application that recorded it.
*/
:root {
  --paper: #f7f7f5;
  --card: #ffffff;
  --ink: #1d1d1b;
  --quiet: #6b6b66;
  --faint: #9a9a94;
  --rule: #dfdfd9;
  --accent: #b4541e;
  --accent-soft: #f4e6dd;
  --good: #2f6b46;
  --warn: #8a6d1f;
  --bad: #9b3b32;
  --hover: #1b66d6;

  --mono: "Cascadia Mono", "SF Mono", Consolas, "Liberation Mono", monospace;
  --text: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #16161a;
    --card: #1e1e23;
    --ink: #e8e8e4;
    --quiet: #a0a09a;
    --faint: #6e6e69;
    --rule: #33333a;
    --accent: #e0793f;
    --accent-soft: #3a2519;
    --good: #6fbf8e;
    --warn: #d4ab4a;
    --bad: #e08078;
    --hover: #6aa9ff;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--text);
  font-size: 15px;
  line-height: 1.55;
}

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

.wrap { max-width: 1180px; margin: 0 auto; padding: 0 20px; }

/* The stroke page, which has three columns to lay out and wants the room. */
.wrap.wide { max-width: 1800px; }

header.top {
  border-bottom: 1px solid var(--rule);
  background: var(--card);
}

header.top .wrap { padding-block: 22px 18px; }

header.top h1 {
  margin: 0;
  font-size: 23px;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

header.top h1 a { color: inherit; text-decoration: none; }

header.top p {
  margin: 6px 0 0;
  color: var(--quiet);
  max-width: 68ch;
}

.crumb {
  font-size: 13px;
  color: var(--quiet);
  margin: 0 0 4px;
}

.crumb a { text-decoration: none; }
.crumb a:hover { text-decoration: underline; }

main { padding-block: 24px 60px; }

/* Numbers that a reader compares down a column line up. */
.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* ---- the totals strip ------------------------------------------------ */

.totals {
  display: flex;
  flex-wrap: wrap;
  gap: 26px;
  padding: 14px 18px;
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: var(--card);
  margin-bottom: 22px;
}

.totals div { min-width: 96px; }
.totals dt { font-size: 12px; color: var(--quiet); text-transform: uppercase; letter-spacing: 0.06em; }
.totals dd { margin: 2px 0 0; font-family: var(--mono); font-size: 19px; font-variant-numeric: tabular-nums; }

/* ---- tags ------------------------------------------------------------- */

.tag {
  display: inline-block;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.03em;
  padding: 2px 7px;
  border-radius: 3px;
  border: 1px solid currentColor;
  white-space: nowrap;
}

.tag.complete { color: var(--good); }
.tag.hover-suspect { color: var(--warn); }
.tag.single-clock, .tag.early, .tag.partial { color: var(--quiet); }
.tag.raw { color: var(--faint); }
.tag.rerecord { color: var(--bad); }

/* A share of something, drawn as a bar beside the number that says it. */
.meter {
  display: inline-block;
  height: 8px;
  min-width: 1px;
  border-radius: 2px;
  background: var(--accent);
  vertical-align: middle;
}

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

.scroll { overflow-x: auto; }

table { border-collapse: collapse; width: 100%; font-size: 14px; }

th, td {
  text-align: left;
  padding: 7px 10px;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
}

th {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--quiet);
  font-weight: 600;
  white-space: nowrap;
  position: sticky;
  top: 0;
  background: var(--paper);
}

td.n, th.n { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; }

tbody tr:hover { background: var(--accent-soft); }
tbody tr.picked { background: var(--accent-soft); }

td a { text-decoration: none; font-weight: 600; }
td a:hover { text-decoration: underline; }

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

.controls {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-bottom: 14px;
}

.controls label { font-size: 13px; color: var(--quiet); }

select, input[type="search"], button {
  font: inherit;
  font-size: 14px;
  padding: 5px 9px;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--card);
  color: var(--ink);
}

button { cursor: pointer; }
button:hover { border-color: var(--accent); }
button[disabled] { opacity: 0.45; cursor: default; }
button.on { border-color: var(--accent); color: var(--accent); }

/* ---- panels ----------------------------------------------------------- */

.panel {
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: var(--card);
  padding: 16px 18px;
  margin-bottom: 18px;
}

.panel h2 { margin: 0 0 10px; font-size: 15px; letter-spacing: 0.01em; }
.panel h2 .sub { font-weight: 400; color: var(--quiet); }

/*
  A definition list laid out in pairs.

  Written first as one auto-fit grid with dt and dd as its items, which put a label in one
  column and its value in the next -- so "recorded" sat above "tablet" and its date sat
  beside it under "driver". A four-column track pairs them, because dt, dd, dt, dd is
  exactly one row of it.
*/
.facts {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr) max-content minmax(0, 1fr);
  gap: 0 16px;
  margin: 0;
  align-items: baseline;
}

.facts dt {
  font-size: 12px;
  color: var(--quiet);
  padding: 4px 0;
  border-top: 1px solid var(--rule);
  white-space: nowrap;
}

.facts dd {
  margin: 0;
  padding: 4px 0;
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.45;
  word-break: break-word;
}

/* The first row of each column pair has the panel's heading above it already. */
.facts dt:first-of-type, .facts dt:first-of-type + dd,
.facts dt:nth-of-type(2), .facts dt:nth-of-type(2) + dd { border-top: 0; }

@media (max-width: 760px) {
  .facts { grid-template-columns: max-content minmax(0, 1fr); }
  .facts dt:nth-of-type(2), .facts dt:nth-of-type(2) + dd { border-top: 1px solid var(--rule); }
}

/* Prose in a value, rather than a measurement, wants the reading face. */
.facts dd.says { font-family: var(--text); font-size: 13.5px; }

.note { color: var(--quiet); font-size: 13.5px; margin: 8px 0 0; }

.warnings { list-style: none; padding: 0; margin: 10px 0 0; }
.warnings li {
  border-left: 3px solid var(--bad);
  padding: 4px 0 4px 11px;
  margin-bottom: 7px;
  font-size: 13.5px;
  color: var(--quiet);
}

/* ---- the stroke gallery ----------------------------------------------- */

.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(148px, 1fr)); gap: 12px; }

.gallery a {
  display: block;
  border: 1px solid var(--rule);
  border-radius: 5px;
  padding: 8px;
  text-decoration: none;
  color: inherit;
  background: var(--card);
}

.gallery a:hover { border-color: var(--accent); }
.gallery canvas { display: block; width: 100%; height: auto; }
.gallery .cap { font-size: 11.5px; color: var(--quiet); margin-top: 6px; font-family: var(--mono); }

/* ---- the analyser ----------------------------------------------------- */

/*
  Three columns: the stroke, the reading under the playhead, and all the readings. The
  channels sit under the stroke, in the first column.

  The third is held to the height of the stroke panel. They share the first row, so its panel
  stretches to whatever height the stroke sets, and its contents are taken out of flow so that
  a long table cannot make the row taller -- it scrolls inside the panel instead. Without that
  the page was as tall as the table, and the playhead's row scrolled the whole page rather
  than just the list.
*/
.analyser {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 280px 400px;
  grid-template-areas:
    "stroke reading every"
    "across .       .";
  gap: 0 18px;
  align-items: start;
}

.analyser > .stroke { grid-area: stroke; }
.analyser > .across { grid-area: across; }
.analyser > .reading { grid-area: reading; }

/*
  Seventy percent of the row the stroke sets, not all of it, so it is 30% shorter than it was when
  it filled the row. A percentage height on a grid item is taken from its grid area, which includes
  the panel's 18px bottom margin, so the margin comes off first: 70% of the area itself would be
  3% too tall. This follows the stroke panel as it resizes. The table scrolls inside, and the floor
  keeps a short stroke from squashing it to nothing.
*/
.analyser > .every {
  grid-area: every;
  align-self: start;
  height: calc((100% - 18px) * 0.7);
  position: relative;
  padding: 0;
  min-height: 240px;
}

.every .inside {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  padding: 16px 18px 6px;
}

.every .rows { flex: 1 1 0; min-height: 0; max-height: none; }

/*
  One label and one value to a row, at a fixed label width, and a value that never wraps.
  The pairs-across layout the other pages use sizes its columns to their contents, so as the
  playhead moved the columns changed width and the panel changed height with every step.
*/
.analyser .facts { grid-template-columns: 6.5em minmax(0, 1fr); gap: 0 12px; }
.analyser .facts dt:nth-of-type(2), .analyser .facts dt:nth-of-type(2) + dd {
  border-top: 1px solid var(--rule);
}
.analyser .facts dd {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-variant-numeric: tabular-nums;
}

/* Two columns: the table goes under the reading and takes its own height again. */
@media (max-width: 1100px) {
  .analyser {
    grid-template-columns: minmax(0, 1fr) 300px;
    grid-template-areas:
      "stroke reading"
      "stroke every"
      "across every";
  }

  .analyser > .every { align-self: start; height: auto; position: static; padding: 16px 18px 6px; min-height: 0; }
  .every .inside { position: static; display: block; padding: 0; }
  .every .rows { flex: none; max-height: 305px; }
}

@media (max-width: 900px) {
  .analyser {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "stroke" "across" "reading" "every";
  }
}

canvas.closely, canvas.channel { display: block; width: 100%; height: auto; background: transparent; }

.rows { max-height: 305px; overflow: auto; }
.rows table { font-size: 12.5px; }
.rows th { font-size: 11px; }
.rows td { padding: 3px 8px; }

/* The stroke picture can be zoomed: a hand to say it can be dragged once it has been. */
canvas.closely.zoomed { cursor: grab; touch-action: none; }
canvas.closely.zoomed.dragging { cursor: grabbing; }

.transport.zoombar { margin: 8px 0 0; }
.zoombar button { min-width: 2.2em; }
.zoombar .at { min-width: 3.2em; }
.zoombar .follow { margin-left: auto; font-size: 13px; color: var(--quiet); white-space: nowrap; }

.transport { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-top: 10px; }
.transport input[type="range"] { flex: 1 1 200px; min-width: 140px; accent-color: var(--accent); }
.transport .at { font-family: var(--mono); font-size: 13px; color: var(--quiet); white-space: nowrap; }

footer {
  border-top: 1px solid var(--rule);
  color: var(--quiet);
  font-size: 13px;
  padding-block: 18px 34px;
}

footer a { color: var(--quiet); }

/* The menu that appears when a reading is right-clicked on the stroke page. */
.ctxmenu {
  position: fixed;
  z-index: 50;
  min-width: 13rem;
  padding: 4px;
  background: var(--card);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 6px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.2);
}

.ctxmenu[hidden] { display: none; }

.ctxmenu button {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  font-size: 13px;
  padding: 6px 10px;
  border: 0;
  border-radius: 4px;
  background: transparent;
  color: inherit;
  cursor: pointer;
}

.ctxmenu button:hover,
.ctxmenu button:focus-visible { background: var(--accent-soft); outline: none; }

.ctxmenu button:disabled { color: var(--quiet); background: transparent; cursor: default; }
