/* Nostia Console — desktop-first.
   Light and dark are both first-class: a finance screen read at 11pm should not be a flashbang. */

:root {
  /* Drives how the BROWSER paints native widgets — dropdown popups, scrollbars,
     date pickers, the caret. index.html carries a <meta name="color-scheme">,
     which is a document-level hint and does NOT reach widget painting; this
     property does.

     Without it the organisation switcher opened a WHITE popup in dark mode while
     its <option> children inherited the select's near-white --text, so every
     unselected organisation was white-on-white and effectively invisible. Only
     the row under the OS highlight could be read. */
  color-scheme: light dark;

  --accent: #2E7D32;
  --accent-soft: #E8F3E9;
  /* Text/icon colour that sits ON an accent fill. Split out from --text because
     the accent is dark in light mode and bright in dark mode — one fixed value
     is unreadable in whichever mode it was not chosen for. */
  --accent-ink: #FFFFFF;
  --warning: #B45309;
  --danger: #B3261E;
  --info: #1D4ED8;

  --canvas: #F4F6F8;
  --card: #FFFFFF;
  --card-2: #FAFBFC;
  --stroke: #E3E8ED;
  --text: #111827;
  --text-2: #4B5563;
  --text-3: #8A94A0;
  --shadow: rgba(30, 50, 70, .09);

  --radius: 14px;
  --radius-sm: 10px;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    /* Was #4CAF50 carrying white text: ~2.3:1, far under the 4.5:1 floor and the
       exact flashbang the header above warns about. The fill stays bright but
       now carries near-black ink (~12:1). Same treatment as the emerald button
       on the marketing site, so the two surfaces read as one product. */
    --accent: #34D399;
    --accent-ink: #08120C;
    --accent-soft: #16301A;
    --warning: #F59E0B;
    --danger: #F2645A;
    --info: #60A5FA;
    --canvas: #0E1113;
    --card: #1A1E21;
    --card-2: #15191B;
    --stroke: #2A3034;
    --text: #F3F4F6;
    --text-2: #B6BDC4;
    --text-3: #78828C;
    --shadow: rgba(0, 0, 0, .45);
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--sans);
  background: var(--canvas);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
}

/* The stylesheet had NO anchor rule, so every link fell back to the browser
   defaults — #0000EE unvisited, #551A8B visited — against a near-black card.
   Unreadable, and the visited state made the same row change colour after a
   click for no reason the user could act on. */
a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 38%, transparent);
  transition: color .12s ease, border-color .12s ease;
}
a:hover { border-bottom-color: var(--accent); }
a:visited { color: var(--accent); }
a:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 3px; }

.noscript { padding: 2rem; font-size: 1rem; }

/* ---------- Layout ---------- */

.shell { display: grid; grid-template-columns: 264px 1fr; min-height: 100vh; }

.sidebar {
  border-right: 1px solid var(--stroke);
  background: var(--card);
  padding: 22px 18px;
  display: flex;
  flex-direction: column;
  gap: 22px;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.content { padding: 30px 38px 64px; max-width: 1180px; }

/* Below a laptop the sidebar stacks. The console is desktop-first — the phone has its own app —
   but a narrow window should degrade rather than break. */
@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; }
  .sidebar { position: static; height: auto; border-right: none; border-bottom: 1px solid var(--stroke); }
  .content { padding: 22px 18px 48px; }
}

.brand { font-family: var(--mono); font-weight: 800; letter-spacing: .22em; font-size: 15px; }
/* Reads as a product label beside the wordmark rather than an orphaned word
   under it — which is how "Orgs" looked once it replaced a longer subtitle. */
.brand span {
  display: inline-block; margin-top: 7px;
  font-family: var(--sans); font-size: 11px; font-weight: 700;
  letter-spacing: .10em; text-transform: uppercase;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 99px; padding: 3px 9px;
}

.nav { display: flex; flex-direction: column; gap: 3px; }
.nav button {
  all: unset;
  /* Same `all: unset` box-sizing trap as button.btn — and these stretch to full
     width inside a flex column, so content-box would overhang the sidebar. */
  box-sizing: border-box;
  cursor: pointer;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  font-size: 14px;
  color: var(--text-2);
  display: flex; align-items: center; gap: 9px;
}
.nav button:hover { background: var(--canvas); color: var(--text); }
.nav button[aria-current="page"] { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.nav button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.org-switch {
  border: 1px solid var(--stroke);
  border-radius: var(--radius-sm);
  padding: 10px 11px;
  background: var(--card-2);
}
.org-switch label { display: block; font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--text-3); margin-bottom: 6px; }
.org-switch select {
  /* Borderless inside its own bordered wrapper — but it still gets the chevron,
     so it does not read as a different KIND of control from the selects in the
     authoring form. */
  width: 100%; box-sizing: border-box; font: inherit; font-size: 14px; color: var(--text);
  background: transparent; border: none; cursor: pointer;
  appearance: none; -webkit-appearance: none;
  padding-right: 22px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%238A94A0' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right center;
}
.org-switch:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
.org-switch { transition: border-color .15s ease, box-shadow .15s ease; }
.org-switch select:focus-visible { outline: none; }

.sidebar-foot { margin-top: auto; font-size: 11px; color: var(--text-3); line-height: 1.5; }
.sidebar-foot code { font-family: var(--mono); font-size: 10px; word-break: break-all; }

/* ---------- Typography ---------- */

h1 { font-size: 24px; margin: 0 0 4px; letter-spacing: -.01em; }
h2 { font-size: 16px; margin: 0 0 12px; }
h3 { font-size: 14px; margin: 0 0 6px; }
p  { margin: 0 0 10px; color: var(--text-2); font-size: 14px; line-height: 1.55; }
.lede { color: var(--text-3); font-size: 13px; margin-bottom: 22px; }
.muted { color: var(--text-3); }
.small { font-size: 12px; }
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* ---------- Surfaces ---------- */

.card {
  background: var(--card);
  border: 1px solid var(--stroke);
  border-radius: var(--radius);
  padding: 18px;
  box-shadow: 0 4px 14px var(--shadow);
}
.card + .card { margin-top: 14px; }
.section { margin-bottom: 30px; }

.grid { display: grid; gap: 14px; }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }

.row { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.row + .row { margin-top: 9px; padding-top: 9px; border-top: 1px solid var(--stroke); }

/* ---------- Metric tiles ---------- */

.metric { background: var(--card); border: 1px solid var(--stroke); border-radius: var(--radius); padding: 16px; }
.metric .label { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--text-3); }
.metric .value { font-family: var(--mono); font-size: 30px; font-weight: 700; margin: 6px 0 2px; letter-spacing: -.02em; }
.metric .value.thin { color: var(--text-2); }
.metric .sub { font-size: 12px; color: var(--text-3); }
.metric .caption { font-size: 11px; color: var(--text-3); margin-top: 7px; line-height: 1.45; }
.metric.suppressed .value { font-size: 18px; color: var(--text-3); font-weight: 600; }

/* ---------- Funnel ---------- */

.funnel-row { padding: 13px 0; border-bottom: 1px solid var(--stroke); }
.funnel-row:last-child { border-bottom: none; }
.funnel-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }
.funnel-ord { font-family: var(--mono); font-size: 12px; color: var(--text-3); min-width: 18px; }
.funnel-title { font-size: 14px; font-weight: 600; flex: 1; }
.funnel-count { font-family: var(--mono); font-size: 13px; color: var(--text-2); }
.funnel-track { position: relative; height: 9px; border-radius: 99px; background: var(--stroke); overflow: hidden; }
.funnel-reached { position: absolute; inset: 0 auto 0 0; background: color-mix(in srgb, var(--accent) 28%, transparent); border-radius: 99px; }
.funnel-verified { position: absolute; inset: 0 auto 0 0; background: var(--accent); border-radius: 99px; }
.funnel-meta { display: flex; gap: 14px; margin-top: 8px; font-size: 11px; color: var(--text-3); flex-wrap: wrap; }
.funnel-meta .warn { color: var(--warning); font-weight: 600; }
.funnel-flag { margin-top: 8px; font-size: 12px; color: var(--warning); line-height: 1.45; }

/* ---------- Pills and notices ---------- */

.pill {
  display: inline-block; font-size: 10px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; padding: 4px 9px; border-radius: 99px;
  background: color-mix(in srgb, var(--text-3) 16%, transparent); color: var(--text-2);
}
.pill.ok { background: var(--accent); color: var(--accent-ink); }
.pill.info { background: color-mix(in srgb, var(--info) 16%, transparent); color: var(--info); }
.pill.warn { background: color-mix(in srgb, var(--warning) 18%, transparent); color: var(--warning); }
.pill.bad { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }

.notice {
  border-radius: var(--radius-sm);
  padding: 13px 15px;
  font-size: 13px;
  line-height: 1.55;
  border: 1px solid;
  margin-bottom: 16px;
}
.notice h3 { margin: 0 0 4px; font-size: 13px; }
.notice p { margin: 0; font-size: 13px; color: inherit; opacity: .88; }
.notice.info { border-color: color-mix(in srgb, var(--info) 34%, transparent); background: color-mix(in srgb, var(--info) 9%, transparent); color: var(--text); }
.notice.warn { border-color: color-mix(in srgb, var(--warning) 38%, transparent); background: color-mix(in srgb, var(--warning) 10%, transparent); color: var(--text); }
.notice.bad  { border-color: color-mix(in srgb, var(--danger) 34%, transparent); background: color-mix(in srgb, var(--danger) 9%, transparent); color: var(--text); }
.notice.ok   { border-color: color-mix(in srgb, var(--accent) 34%, transparent); background: color-mix(in srgb, var(--accent) 9%, transparent); color: var(--text); }

/* ---------- Controls ---------- */

button.btn {
  all: unset; cursor: pointer; text-align: center;
  /* MUST come after `all: unset`. That resets box-sizing to its initial
     content-box, overriding the global `* { box-sizing: border-box }`, so any
     .btn given width:100% rendered 34px wider than its container — the padding
     was added on top of the full width. The sign-in button visibly overhung the
     card edge. Restoring border-box here fixes every .btn, not just that one. */
  box-sizing: border-box;
  padding: 10px 17px; border-radius: var(--radius-sm);
  font-size: 14px; font-weight: 600;
  background: var(--accent); color: var(--accent-ink);
}
button.btn:hover { filter: brightness(1.06); }
button.btn:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }
button.btn[disabled] { opacity: .45; cursor: not-allowed; }
button.btn.ghost { background: transparent; color: var(--text); border: 1px solid var(--stroke); }
button.btn.link { background: transparent; color: var(--accent); padding: 4px 0; font-weight: 600; }

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

   Styled by ELEMENT, not by wrapper. These rules used to be scoped under .field,
   which meant a control only looked designed if someone remembered to wrap it —
   and two did not. The "New adventure title" box and the "Stop title" box sit
   inline next to their buttons rather than in a labelled field, so both rendered
   as raw OS widgets on the authoring screen, directly beside a styled button.
   That is the first screen an admin meets and the one they spend an hour in.

   Scoping to a wrapper makes correct styling something you can forget. Scoping to
   the element makes it the default and the next control added is covered for
   free. .field is now layout only: label, spacing, full width.

   Two deliberate exceptions, both winning on specificity rather than order:
   .org-switch select is borderless inside its own bordered shell, and
   input[type="file"] carries the dashed drop-zone treatment. */

.field { display: block; margin-bottom: 16px; }
.field > span {
  display: block;
  font-size: 12px; font-weight: 500; letter-spacing: .01em;
  color: var(--text-2); margin-bottom: 6px;
}

input:not([type="file"]),
select,
textarea {
  /* One shared box so a text input and the textarea under it line up exactly. */
  width: 100%; box-sizing: border-box;
  font: inherit; font-size: 14px; line-height: 1.45;
  padding: 10px 12px;
  color: var(--text);
  background: var(--card);
  border: 1px solid var(--stroke);
  border-radius: var(--radius-sm);
  /* Colour and shadow only — never a transition on layout properties, which is
     what makes a focus state feel like a jump rather than a highlight. */
  transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
}

input::placeholder,
textarea::placeholder { color: var(--text-3); }

input:not([type="file"]):hover:not(:disabled),
select:hover:not(:disabled),
textarea:hover:not(:disabled) { border-color: var(--text-3); }

/* A soft ring instead of the old 2px outline. `outline` is drawn outside the
   border box and cannot be rounded to match the corner radius, so on a 10px
   radius it rendered as a square bracket around a rounded field. A box-shadow
   ring follows the radius exactly. The outline is kept as a transparent
   fallback for forced-colours mode, where box-shadow is discarded. */
input:not([type="file"]):focus-visible,
select:focus-visible,
textarea:focus-visible {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
  outline: 2px solid transparent; outline-offset: 1px;
}

input:disabled,
select:disabled,
textarea:disabled {
  background: var(--card-2);
  color: var(--text-3);
  cursor: not-allowed;
}

/* A published adventure is immutable, so most of the authoring form is disabled
   rather than hidden. It has to read as "locked", not as "broken". */
input:disabled::placeholder,
textarea:disabled::placeholder { color: transparent; }

textarea {
  /* Horizontal drag would let a stop description escape its card. */
  resize: vertical;
  min-height: 72px;
}

/* Native select arrow replaced so the control matches the inputs beside it.
   The chevron is a fixed mid-grey rather than currentColor: a data-URI cannot
   read a CSS variable, and this grey clears 3:1 against both the light card and
   the dark one. */
select {
  appearance: none; -webkit-appearance: none;
  padding-right: 34px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%238A94A0' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  cursor: pointer;
}
select:disabled { cursor: not-allowed; opacity: .7; }

/* The dropdown popup is drawn by the OS, not by this stylesheet, and it does not
   inherit the select's background — only its COLOUR. That asymmetry is the whole
   bug: light text arrives over a background the page never set. Paint both here,
   explicitly, so the pair can never drift apart again.

   Firefox and Chrome on Windows and Linux honour this. Safari and Chrome on
   macOS ignore option colours entirely and render a system popup — which is why
   color-scheme above is the primary fix and this is the backstop. */
option {
  background-color: var(--card);
  color: var(--text);
}
option:checked,
option:hover { background-color: var(--accent-soft); color: var(--text); }

/* Same treatment inside the switcher, whose select is deliberately transparent —
   a transparent select must not hand a transparent popup to the compositor. */
.org-switch option { background-color: var(--card); color: var(--text); }

/* Spinners removed. These fields carry a latitude and a dwell in seconds — both
   are typed or pasted, never nudged one step at a time, and the arrows only
   narrow the text area and invite a mis-click that silently moves a geofence. */
input[type="number"] { appearance: textfield; -moz-appearance: textfield; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* The file picker is the worst default on the page — an unstyled OS button
   whose label is set by the browser. The wrapper keeps our border; the button
   inside it is restyled to match .btn.ghost. */
input[type="file"] {
  width: 100%; box-sizing: border-box;
  font: inherit; font-size: 13px;
  padding: 8px 10px;
  color: var(--text-2);
  background: var(--card);
  border: 1px dashed var(--stroke);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: border-color .15s ease, background-color .15s ease;
}
input[type="file"]:hover:not(:disabled) { border-color: var(--accent); background: var(--card-2); }
/* ::-webkit-file-upload-button is the alias Safari used before 14.1. Listed as a
   separate rule, not a selector list: a browser that does not know one of the two
   discards the WHOLE list, which would drop the styling on both. */
input[type="file"]::-webkit-file-upload-button {
  font: inherit; font-size: 13px; font-weight: 600;
  margin-right: 12px; padding: 6px 12px;
  color: var(--text);
  background: transparent;
  border: 1px solid var(--stroke);
  border-radius: 8px;
  cursor: pointer;
}
input[type="file"]::file-selector-button {
  font: inherit; font-size: 13px; font-weight: 600;
  margin-right: 12px; padding: 6px 12px;
  color: var(--text);
  background: transparent;
  border: 1px solid var(--stroke);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease;
}
input[type="file"]::file-selector-button:hover { border-color: var(--accent); color: var(--accent); }
input[type="file"]:focus-visible {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
  outline: 2px solid transparent;
}

/* An input sharing a .row with its button — "New adventure title", "Stop title".
   Both controls now carry width:100%, and inside a flex row that makes them
   fight: the input claims the whole line and the button gets squeezed to its
   text. Let the input take the slack and hold the button at its natural size. */
.row > input,
.row > select { flex: 1 1 auto; min-width: 0; width: auto; }
.row > .btn { flex: 0 0 auto; }

.tabs { display: flex; gap: 6px; margin-bottom: 18px; flex-wrap: wrap; }
.tabs button {
  /* Auto-width today, so nothing overflows — box-sizing set anyway so this does
     not become the third instance of the same bug. */
  all: unset; box-sizing: border-box; cursor: pointer; padding: 6px 13px; border-radius: 99px;
  font-size: 13px; color: var(--text-2); border: 1px solid var(--stroke); background: var(--card);
}
.tabs button[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink); border-color: transparent; font-weight: 600; }

/* ---------- Lists ---------- */

.list-item {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 16px; background: var(--card); border: 1px solid var(--stroke);
  border-radius: var(--radius); cursor: pointer; width: 100%; text-align: left;
  font: inherit; color: inherit;
}
.list-item:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--stroke)); }
.list-item + .list-item { margin-top: 10px; }
.list-item:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.list-item .title { font-weight: 600; font-size: 15px; }
.list-item .meta { font-size: 12px; color: var(--text-3); margin-top: 3px; display: flex; gap: 9px; align-items: center; }
.list-item .figure { font-family: var(--mono); font-size: 19px; font-weight: 700; text-align: right; }
.list-item .figure small { display: block; font-family: var(--sans); font-size: 10px; font-weight: 400; color: var(--text-3); }

/* ---------- States ---------- */

.state { text-align: center; padding: 54px 22px; color: var(--text-3); }
.state h2 { color: var(--text); margin-bottom: 6px; }
.state p { max-width: 44ch; margin: 0 auto 12px; }

.spinner {
  width: 22px; height: 22px; margin: 0 auto 12px;
  border: 2px solid var(--stroke); border-top-color: var(--accent);
  border-radius: 50%; animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2.4s; } }

/* ---------- Sign in ---------- */

.signin { min-height: 100vh; display: grid; place-items: center; padding: 24px; }
.signin .card { width: min(400px, 100%); padding: 22px; }

/* The sign-in card stacks brand, blurb, form, a notice and a link row. .notice
   only carries margin-BOTTOM, which does nothing for the two blocks that sit
   AFTER the submit button — they ended up flush against it. */
.signin .notice { margin: 18px 0 0; }
/* :not() so this does not out-specify the .signin-links rule below — a bare
   `.signin .card > p` (0,2,1) beats `.signin .signin-links` (0,2,0) and would
   silently win the margin. */
.signin .card > p:not(.signin-links) { margin: 0 0 16px; color: var(--text-2); line-height: 1.5; }
.signin .signin-links { margin: 14px 0 0; font-size: 13px; line-height: 1.6; }
.signin .signin-links .sep { color: var(--text-3); margin: 0 6px; }

/* ---------- Tier table ---------- */

.tier { border: 1px solid var(--stroke); border-radius: var(--radius); padding: 16px; background: var(--card); }
.tier.current { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; }
.tier h3 { display: flex; align-items: center; justify-content: space-between; font-size: 15px; }
.tier ul { margin: 10px 0 0; padding-left: 17px; }
.tier li { font-size: 12px; color: var(--text-2); margin-bottom: 4px; line-height: 1.45; }

/* Wide content scrolls inside itself; the page body never scrolls sideways. */
.scroll-x { overflow-x: auto; }

/* ======================================================================
   School layer — clubs, campus events, attendance, students, outbox.
   ====================================================================== */

.grid-4 { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }

/* Chart series: slots 1–3 of the reference categorical palette (dataviz skill),
   which validate all-pairs in BOTH modes. Dark steps are selected for the dark
   surface, not flipped. Text never wears these — only marks do. */
:root { --series-1: #2a78d6; --series-2: #eb6834; --series-3: #1baf7a; }
@media (prefers-color-scheme: dark) {
  :root { --series-1: #3987e5; --series-2: #d95926; --series-3: #199e70; }
}

/* ---------- Tables ---------- */
table.data { width: 100%; border-collapse: collapse; font-size: 14px; background: var(--card);
  border: 1px solid var(--stroke); border-radius: var(--radius); overflow: hidden; }
table.data th { text-align: left; font-size: 12px; font-weight: 600; color: var(--text-3);
  padding: 10px 12px; border-bottom: 1px solid var(--stroke); background: var(--card-2); white-space: nowrap; }
table.data td { padding: 10px 12px; border-bottom: 1px solid var(--stroke); vertical-align: top; }
table.data tr:last-child td { border-bottom: 0; }
table.data .num { text-align: right; font-variant-numeric: tabular-nums; }
table.data tr.clickable { cursor: pointer; }
table.data tr.clickable:hover td { background: var(--card-2); }
table.data tr.clickable:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ---------- Charts ---------- */
.chart-wrap { margin: 0; background: var(--card); border: 1px solid var(--stroke); border-radius: var(--radius); padding: 14px 16px; }
.chart-wrap figcaption { margin-bottom: 6px; }
svg.chart { width: 100%; height: auto; display: block; overflow: visible; }
svg.chart .axis { stroke: var(--text-3); stroke-width: 1; }
svg.chart .grid, svg.chart .row-rule { stroke: var(--stroke); stroke-width: 1; }
svg.chart .tick { fill: var(--text-3); font-size: 11px; font-family: var(--sans); }
svg.chart .label { fill: var(--text-2); font-size: 12px; font-family: var(--sans); }
svg.chart .val { fill: var(--text-2); font-size: 12px; font-family: var(--mono); }
svg.chart .flag { fill: var(--warning); font-size: 12px; font-weight: 700; font-family: var(--sans); }
svg.chart .hit-target { fill: transparent; }
svg.chart .bar.s1 { fill: var(--series-1); }
svg.chart .hit:hover .bar { opacity: .85; }
svg.chart .range.s2 { stroke: var(--series-2); stroke-width: 6; stroke-linecap: round; opacity: .35; }
/* A 2px surface ring keeps overlapping markers separable. */
svg.chart .dot { stroke: var(--card); stroke-width: 2; }
svg.chart .dot.s1 { fill: var(--series-1); }
svg.chart .dot.s2 { fill: var(--series-2); }
svg.chart .dot.s3 { fill: var(--series-3); }
.legend { display: flex; flex-wrap: wrap; gap: 16px; font-size: 12px; color: var(--text-2); margin-bottom: 8px; }
.legend span { display: inline-flex; align-items: center; gap: 6px; }
.swatch { display: inline-block; width: 10px; height: 10px; }
.swatch.round { border-radius: 50%; }
.swatch.diamond { transform: rotate(45deg); width: 9px; height: 9px; }
.swatch.s1 { background: var(--series-1); }
.swatch.s2 { background: var(--series-2); }
.swatch.s3 { background: var(--series-3); }

/* ---------- Forms and bits ---------- */
label.check { display: flex; align-items: flex-start; gap: 8px; font-size: 14px; margin: 6px 0; cursor: pointer; }
label.check input { margin-top: 3px; flex: 0 0 auto; width: auto; }
label.check.option { padding: 8px 0; }
fieldset.plain { border: 0; padding: 0; margin: 12px 0; }
fieldset.plain legend { font-size: 13px; color: var(--text-2); margin-bottom: 4px; padding: 0; }
.chips { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 4px 0 8px 24px; align-items: center; }
.chips > select { width: auto; }
label.chip { margin: 0; }
.methods { margin-top: 8px; }
.survey-editor .question { padding: 12px; }
.survey-editor .question .row { gap: 8px; flex-wrap: wrap; }
.big-code { font-family: var(--mono); font-size: clamp(40px, 9vw, 72px); font-weight: 800;
  letter-spacing: .18em; text-align: center; padding: 18px 0; color: var(--text); }
blockquote.quote { margin: 8px 0; padding: 8px 12px; border-left: 3px solid var(--stroke); color: var(--text-2); }
.pre { white-space: pre-wrap; }
dl.answers { display: grid; grid-template-columns: minmax(140px, auto) 1fr; gap: 6px 16px; margin: 10px 0 0; font-size: 14px; }
dl.answers dt { color: var(--text-3); }
dl.answers dd { margin: 0; }
.owes { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; }
.owes .btn.link { padding: 0; font-size: 13px; text-align: left; }
.ok-text { color: var(--accent); }
.bad-text { color: var(--danger); }
.signin .sso { margin-top: 14px; }
.signin .divider { text-align: center; font-size: 12px; color: var(--text-3); margin: 0 0 12px; }
