/* ontologydriven's look, as one override layer on top of Bootstrap 5.3.
 *
 * ## Why a theme layer and not a theme build
 *
 * Bootstrap is normally retheme'd by editing Sass variables and recompiling.
 * This project cannot do that without acquiring an asset pipeline, and
 * `utils/assets.py` already records why it does not have one: it deploys by
 * uploading the source tree, so there is no build step to hang a Sass compile
 * on. Bootstrap 5.3 makes the pipeline unnecessary -- surfaces, borders, links,
 * radii, typography and the whole dark theme are CSS custom properties now, so
 * retheming is one `:root` block that ships as a plain file and gets
 * fingerprinted by `asset()` like everything else.
 *
 * What 5.3 still bakes in at Sass-compile time is the *variant* colours:
 * `.btn-primary`, `.badge.text-bg-*` and friends resolve their background to a
 * literal hex in the compiled file. Those are written out by hand below, under
 * "what variables cannot reach". It is about forty lines, which is the entire
 * price of not having a build.
 *
 * ## Two colour families, kept apart
 *
 * `--brand` is petrol: it means *you can act on this*. The `--st-*` tokens are
 * semantic: they say what a verdict or a finding **means**. A screen where
 * "add" and "Continue" are the same colour is a screen where neither reads as
 * information, so the two families never share a hue.
 *
 * ## Load order
 *
 * fonts.css, then bootstrap.min.css, then this file. Every rule here is
 * expected to win, so nothing needs `!important`.
 */

/* ---------------------------------------------------------------- tokens -- */

:root {
  /* Surfaces run warm and low-contrast; the ink does the work. A pure #fff
     page under a table of monospace identifiers reads as a spreadsheet. */
  --bs-body-bg: #f7f6f2;
  --surface: #ffffff;
  --surface-2: #fbfaf7;

  --bs-body-color: #16191d;
  --ink-2: #4a5159;          /* running prose, table values                 */
  --muted: #5f666d;          /* labels and asides -- 5.3:1 on --bs-body-bg  */

  --bs-border-color: #e2dfd8;
  --line-strong: #cfcbc1;    /* an edge that has to be seen: inputs, buttons */

  --brand: #0f4c4a;
  --brand-ink: #0a3230;      /* hover, and text on --brand-soft              */
  --brand-soft: #e6efee;
  --brand-line: #cfe0de;

  /* The second accent. Used for provenance, residue and anything the model
     could not express -- never for an action. */
  --clay: #b4532a;
  --clay-ink: #8a4a24;
  --clay-soft: #f6eee6;

  /* Bootstrap resolves links and several derived colours through the `-rgb`
     triplets, not the hex variables -- `a` is literally
     `rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1))`. Setting only
     the hex ones leaves every link Bootstrap blue while the rest of the theme
     looks correct, which is exactly as confusing as it sounds. */
  --bs-body-color-rgb: 22, 25, 29;
  --bs-body-bg-rgb: 247, 246, 242;
  --bs-emphasis-color-rgb: 22, 25, 29;
  --bs-link-color-rgb: 15, 76, 74;
  --bs-link-hover-color-rgb: 10, 50, 48;

  --bs-link-color: var(--brand);
  --bs-link-hover-color: var(--brand-ink);
  --bs-emphasis-color: var(--bs-body-color);
  --bs-secondary-color: var(--muted);
  --bs-tertiary-bg: var(--surface-2);

  --bs-body-font-family: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --bs-font-monospace: "IBM Plex Mono", ui-monospace, "Cascadia Code", Consolas, monospace;
  --font-display: Newsreader, Georgia, "Times New Roman", serif;
  --bs-body-font-size: 0.9375rem;   /* 15px */
  --bs-body-line-height: 1.6;

  --bs-border-radius: 0.375rem;
  --bs-border-radius-lg: 0.625rem;

  --rail-width: 15rem;

  /* Semantic verdicts and findings. Retuned to sit in the new palette, but
     deliberately still the five the import screens already use -- widening
     them to the six the merge proposal actually distinguishes belongs with
     the rewrite of those templates, not with a stylesheet swap. */
  --st-new:   #1f4e8c;   /* something arrives      */
  --st-map:   #55407a;   /* an alignment, no row   */
  --st-warn:  #8a5a08;   /* worth knowing          */
  --st-block: #a02b1f;   /* stops the import       */
  --st-skip:  var(--muted);
  --st-new-bg:   #e7eef7;
  --st-map-bg:   #edeaf3;
  --st-warn-bg:  #f6efe0;
  --st-block-bg: #f7ecea;
  --st-ok-bg:    #e7f1eb;

  --error: var(--st-block);
  /* Kept so anything still reaching for the old names renders. */
  --bg: var(--bs-body-bg);
  --card: var(--surface);
  --ink: var(--bs-body-color);
  --line: var(--bs-border-color);
  --accent: var(--brand);
}

/* Dark is a real theme, not an inversion: the ground stays slightly warm, the
   brand lightens far enough to stay a link at 4.5:1, and the semantic hues are
   re-picked rather than lightened, because a lightened red goes pink. */
[data-bs-theme="dark"] {
  --bs-body-bg: #0f1214;
  --surface: #171b1d;
  --surface-2: #1b2022;

  --bs-body-color: #eceae4;
  --ink-2: #c8cdd1;
  --muted: #98a0a6;

  --bs-border-color: #2a3033;
  --line-strong: #3a4245;

  --brand: #6fcfb8;
  --brand-ink: #9be2d0;
  --brand-soft: #14302c;
  --brand-line: #2f5a53;

  --clay: #e08b5f;
  --clay-ink: #eda87f;
  --clay-soft: #201a17;

  --bs-body-color-rgb: 236, 234, 228;
  --bs-body-bg-rgb: 15, 18, 20;
  --bs-emphasis-color-rgb: 236, 234, 228;
  --bs-link-color-rgb: 111, 207, 184;
  --bs-link-hover-color-rgb: 155, 226, 208;

  --st-new:   #8ab4e8;
  --st-map:   #b3a5dd;
  --st-warn:  #dbaa4e;
  --st-block: #e8887c;
  --st-new-bg:   #17222f;
  --st-map-bg:   #1f1b2b;
  --st-warn-bg:  #251f12;
  --st-block-bg: #2b1a18;
  --st-ok-bg:    #132420;

  color-scheme: dark;
}

/* ------------------------------------------------------------ typography -- */

body {
  font-feature-settings: "cv02", "cv03", "cv04";  /* Plex's single-storey a/g */
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { color: var(--bs-body-color); }

/* The display face is for the page's own title and for figures -- the things a
   reader looks at rather than reads. Everything structural stays in Plex. */
h1, .display-face {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.875rem;
  letter-spacing: -0.015em;
  line-height: 1.12;
}

/* A page whose subject is a name out of the model puts that name in the title,
   so the title is set in mono -- the same rule as everywhere else, applied to
   the largest type on the page rather than excepted from it. */
h1.mono { font-family: var(--bs-font-monospace); font-weight: 500; font-size: 1.75rem; }

h2 { font-size: 1.125rem; font-weight: 600; letter-spacing: -0.005em; }
h3 { font-size: 1rem; font-weight: 600; }

/* A name that came out of the model -- a class, a property, a relation, an IRI,
   a row id -- is always set in mono. That is how a reader tells what they can
   search for apart from what we wrote about it. */
code, .ent, .mono { font-family: var(--bs-font-monospace); }
code, .ent { font-size: 0.86em; color: inherit; }

.muted { color: var(--muted); }
.error { color: var(--st-block); }
.empty { color: var(--muted); font-style: italic; }
.why { font-size: 0.8rem; color: var(--muted); line-height: 1.45; }

/* A small all-caps label above a value or a group. Letter-spaced because Plex
   at 10px with no tracking sets too tight to scan. */
.eyebrow {
  font-family: var(--bs-font-monospace);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

a { text-decoration: none; }
a:hover { text-decoration: underline; }

/* -------------------------------------------------------------- the shell -- */

/*
 * One grid for the whole window: the top bar spans it, the rail and the content
 * share the second row. The rail's column is `auto`, so a page that renders no
 * chrome at all -- every authentication page overrides that block -- collapses
 * it to nothing and the content simply occupies the window. That is why there
 * is one block to override rather than two.
 */
body {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto 1fr;
  min-height: 100vh;
  margin: 0;
}

.topbar {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 1.25rem;
  height: 3.5rem;
  padding: 0 1.25rem;
  background: var(--surface);
  border-bottom: 1px solid var(--bs-border-color);
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--bs-body-color);
}
.brand:hover { text-decoration: none; color: var(--bs-body-color); }
.brand b { color: var(--brand); font-weight: 600; }
.brand svg { display: block; }

.topbar-actions { display: flex; align-items: center; gap: 0.75rem; margin-left: auto; }
.topbar-actions a { font-size: 0.875rem; color: var(--ink-2); }
.topbar-actions a:hover { color: var(--bs-body-color); }

/* An icon-only control. 2rem is below the 44px touch target, which is why the
   rail -- the navigation you actually use on a phone -- gets full-height rows
   instead, and these stay pointer-sized affordances beside them. */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius);
  background: var(--surface);
  color: var(--ink-2);
  cursor: pointer;
}
.icon-btn:hover { background: var(--surface-2); color: var(--bs-body-color); }
.icon-btn svg { display: block; }

.rail {
  grid-row: 2;
  width: var(--rail-width);
  padding: 1rem 0.75rem;
  background: var(--surface);
  border-right: 1px solid var(--bs-border-color);
}

.rail-group {
  padding: 0.25rem 0.625rem 0.375rem;
  margin-top: 1rem;
}
.rail-group:first-child { margin-top: 0; }

.rail a {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  min-height: 2.25rem;
  padding: 0 0.625rem;
  border-radius: var(--bs-border-radius);
  color: var(--ink-2);
  font-size: 0.875rem;
}
.rail a:hover { background: var(--surface-2); color: var(--bs-body-color); text-decoration: none; }
.rail a[aria-current="page"] {
  background: var(--brand-soft);
  color: var(--brand-ink);
  font-weight: 600;
}
.rail a svg { flex: none; }
.rail .count {
  margin-left: auto;
  font-family: var(--bs-font-monospace);
  font-size: 0.6875rem;
  font-weight: 400;
  color: var(--muted);
}
.rail a[aria-current="page"] .count { color: var(--brand-ink); }

.content {
  grid-row: 2;
  grid-column: 2;
  min-width: 0;          /* or a wide table stretches the whole grid */
  padding: 1.75rem 2rem 4rem;
}
.page { max-width: 72rem; }

/* Below this the rail cannot stay a column without taking half the window, so
   it becomes a scrollable strip under the bar. No JavaScript, no offcanvas to
   wire up, and the links keep working with the same markup. */
@media (max-width: 54rem) {
  body { grid-template-columns: 1fr; }
  .rail {
    grid-row: auto;
    grid-column: 1 / -1;
    width: auto;
    display: flex;
    gap: 0.25rem;
    overflow-x: auto;
    /* Without this the rail's min-content width -- the sum of its
       non-wrapping links -- becomes the grid column's minimum, and the whole
       page ends up wider than the phone it is being read on. `overflow-x`
       alone does not do it: a grid item's default `min-width: auto` wins. */
    min-width: 0;
    padding: 0.5rem 0.75rem;
    border-right: 0;
    border-bottom: 1px solid var(--bs-border-color);
  }
  .rail-group { display: none; }
  .rail a { white-space: nowrap; }
  .rail .count { margin-left: 0.375rem; }
  /* The base rule pins the content to row 2, which is where the rail now
     auto-places itself; leaving it would stack the two in one cell. */
  .content { grid-row: auto; grid-column: 1 / -1; padding: 1.25rem 1rem 3rem; }
}

/* ----------------------------------------------------- page-level furniture -- */

.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin: 0 0 0.625rem;
  font-size: 0.8125rem;
  color: var(--muted);
}
.crumbs a { color: var(--muted); }
.crumbs a:hover { color: var(--bs-body-color); }
.crumbs .sep { color: var(--line-strong); }

.page-head { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0.75rem; }
.page-head h1 { margin: 0; }
/* The lede is a sibling of `.page-head`, not a child of it, and deliberately.
   Inside the flex row it cannot be made to wrap onto its own line: a flex
   basis of 100% is clamped by `max-width` *before* lines are broken, so a
   measure-limited paragraph always fits beside the buttons and sits there. */
.lede {
  margin: 0.5rem 0 0;
  max-width: 68ch;
  color: var(--ink-2);
}
.page-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-left: auto; }

.section { margin-top: 2rem; }
.section > h2 {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin-bottom: 0.625rem;
}
.section > h2 .count {
  font-family: var(--bs-font-monospace);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--muted);
  margin-left: 0.4rem;
}
details.section > summary { cursor: pointer; margin-bottom: 0.5rem; }

/* The two-column reading layout: the document, and a column of things about the
   document. The aside drops below on a narrow window rather than squeezing,
   because at 14rem it stops being scannable and starts being a second column of
   wrapped text. */
.doc { display: flex; align-items: flex-start; gap: 2rem; }
.doc > article { flex: 1 1 auto; min-width: 0; }
.doc > aside { flex: 0 0 15.25rem; width: 15.25rem; position: sticky; top: 1.75rem; }
@media (max-width: 68rem) {
  .doc { display: block; }
  .doc > aside { width: auto; position: static; margin-top: 2rem; }
}

/* An index of the page's own sections. The stripe is the position indicator, so
   it stays visible with colour removed. */
.toc { display: flex; flex-direction: column; gap: 0.125rem; }
.toc a {
  padding: 0.25rem 0 0.25rem 0.625rem;
  border-left: 2px solid var(--bs-border-color);
  font-size: 0.8125rem;
  color: var(--ink-2);
}
.toc a:hover { color: var(--bs-body-color); text-decoration: none; border-left-color: var(--line-strong); }

/* --------------------------------------------------------------- surfaces -- */

/* `.card` exists in Bootstrap too. Everything it sets that we do not want --
   the flex column in particular -- is overridden here rather than by renaming
   it in eighteen templates. */
.card {
  display: block;
  background: var(--surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius-lg);
  padding: 1.25rem 1.5rem;
  margin: 1rem 0;
}
.auth-card { max-width: 22rem; margin: 5rem auto; }
.auth-card h1 { font-size: 1.375rem; margin-bottom: 0.25rem; }

/* Same story: Bootstrap's `.row` is a grid row with negative margins and
   full-width children. One template uses `.row` to mean "a few things side by
   side", and it predates Bootstrap being here. */
.row {
  --bs-gutter-x: 0;
  --bs-gutter-y: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 1.6rem;
  margin: 0;
}
.row > * { flex: 0 0 auto; width: auto; max-width: none; padding: 0; margin-top: 0; }

.notice {
  background: var(--st-warn-bg);
  border: 1px solid var(--st-warn);
  color: var(--st-warn);
  border-radius: var(--bs-border-radius);
  padding: 0.75rem 1rem;
  margin: 0.75rem 0;
}
.notice-ok { background: var(--st-ok-bg); border-color: var(--brand); color: var(--brand-ink); }

/* A block whose point is that it came from somewhere else, or could not be
   expressed. The clay stripe marks provenance and residue, never an action. */
.aside-note {
  background: var(--surface);
  border: 1px solid var(--bs-border-color);
  border-left: 3px solid var(--clay);
  border-radius: var(--bs-border-radius-lg);
  padding: 0.875rem 1rem;
}

.secret {
  background: #0f1720;
  color: #d6e2ff;
  padding: 0.9rem;
  border-radius: var(--bs-border-radius);
  white-space: pre-wrap;
  word-break: break-all;
  font-family: var(--bs-font-monospace);
}

/* ----------------------------------------------------------------- facts -- */

/* A strip of counts. These are the model's own numbers, so they are set in the
   display face at a size that says "read me" -- they are the page's headline
   as much as the title is. */
.stats {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  margin: 1.25rem 0;
  background: var(--surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius-lg);
  overflow: hidden;
}
.stat {
  flex: 1 1 8rem;
  padding: 0.75rem 1rem;
  border-right: 1px solid var(--bs-border-color);
}
.stat:last-child { border-right: 0; }
.stat .n {
  display: block;
  font-family: var(--font-display);
  font-size: 1.625rem;
  font-weight: 600;
  line-height: 1.1;
}
.stat .k {
  display: block;
  margin-top: 0.125rem;
  font-family: var(--bs-font-monospace);
  font-size: 0.625rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---------------------------------------------------------------- tables -- */

table.grid {
  width: 100%;
  border-collapse: collapse;
  margin: 0;
  background: var(--surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius-lg);
  overflow: hidden;
}
table.grid th,
table.grid td {
  text-align: left;
  padding: 0.6rem 0.9rem;
  border-bottom: 1px solid var(--bs-border-color);
  vertical-align: top;
}
table.grid thead th {
  font-family: var(--bs-font-monospace);
  font-size: 0.625rem;
  font-weight: 400;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--surface-2);
  white-space: nowrap;
}
table.grid tbody tr:last-child td { border-bottom: 0; }
table.grid tbody tr:hover { background: var(--surface-2); }
/* A row's first cell is nearly always the thing the row is about. */
table.grid tbody td:first-child { font-family: var(--bs-font-monospace); font-size: 0.8125rem; }
table.grid tbody td { color: var(--ink-2); }
table.grid tbody td a { font-weight: 500; }
.label-cell { width: 9.5rem; vertical-align: top; }
table.proposal td { vertical-align: top; }
table.proposal tr[hidden] { display: none; }

/* A table that has to scroll rather than squeeze. Wrapping it is the only way
   to keep a wide table from stretching the grid it sits in. */
.scroll-x { overflow-x: auto; }

/* ----------------------------------------------------------- annotations -- */

.tag {
  display: inline-block;
  padding: 0.05rem 0.45rem;
  border-radius: 0.25rem;
  font-size: 0.6875rem;
  border: 1px solid var(--bs-border-color);
  color: var(--muted);
  background: var(--surface);
  white-space: nowrap;
  vertical-align: 1px;
}
.tag-accent {
  border-color: var(--brand-line);
  background: var(--brand-soft);
  color: var(--brand-ink);
  font-weight: 500;
}
/* A relation type that states only cardinality, never meaning -- R2 finding A.
   Dashed rather than merely grey, so the model's central gap survives being
   printed, and survives a reader who cannot separate the two greens. */
.tag-cardinality { border-style: dashed; }
/* A relation name, as opposed to a fact about it. Mono, because it is a name
   out of the model. */
.tag-rel { font-family: var(--bs-font-monospace); }

.chips { display: flex; flex-wrap: wrap; gap: 0.4rem; margin: 0.5rem 0; }
a.tag:hover { text-decoration: none; border-color: var(--line-strong); color: var(--bs-body-color); }

/* Verdict and status pills. Filled rather than outlined so a row's state is
   legible while scanning a column of two hundred, which is how the proposal
   table is actually read. */
.pill {
  display: inline-block;
  padding: 0.08rem 0.5rem;
  border-radius: 999px;
  font-size: 0.6875rem;
  font-weight: 600;
  white-space: nowrap;
}
.pill-new, .pill-parsed          { color: var(--st-new);   background: var(--st-new-bg); }
.pill-equivalent, .pill-proposed { color: var(--st-map);   background: var(--st-map-bg); }
.pill-ambiguous, .pill-warn, .pill-unresolved
                                 { color: var(--st-warn);  background: var(--st-warn-bg); }
.pill-conflict, .pill-block, .pill-failed
                                 { color: var(--st-block); background: var(--st-block-bg); }
.pill-identical, .pill-reverted, .pill-discarded
                                 { color: var(--st-skip);  background: var(--bs-body-bg);
                                   border: 1px solid var(--bs-border-color); }
.pill-applied { color: var(--brand-ink); background: var(--st-ok-bg); }

.st-new   { color: var(--st-new); }
.st-map   { color: var(--st-map); }
.st-warn  { color: var(--st-warn); }
.st-block { color: var(--st-block); }
.st-skip  { color: var(--st-skip); }

.act { font-size: 0.8rem; font-weight: 600; }
.act-add  { color: var(--st-new); }
.act-map  { color: var(--st-map); }
.act-skip { color: var(--muted); font-weight: 400; }

/* ---------------------------------------------------------------- controls -- */

/* What variables cannot reach: Bootstrap compiles these backgrounds to literal
   hexes, so they are restated here. Bare `button` is restyled too, because the
   templates that predate Bootstrap use elements, not classes. */
button,
.btn-primary,
a.btn:not(.secondary) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: 2.25rem;
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--brand);
  border-radius: var(--bs-border-radius);
  background: var(--brand);
  color: #fff;
  font: inherit;
  font-weight: 500;
  line-height: 1.2;
  cursor: pointer;
  text-decoration: none;
}
button:hover,
.btn-primary:hover,
a.btn:not(.secondary):hover {
  background: var(--brand-ink);
  border-color: var(--brand-ink);
  color: #fff;
  text-decoration: none;
}
[data-bs-theme="dark"] button,
[data-bs-theme="dark"] .btn-primary,
[data-bs-theme="dark"] a.btn:not(.secondary) { color: #0f1214; }
[data-bs-theme="dark"] button:hover,
[data-bs-theme="dark"] a.btn:not(.secondary):hover { color: #0f1214; }

button:disabled, button[disabled] {
  background: var(--line-strong);
  border-color: var(--line-strong);
  color: var(--surface);
  cursor: not-allowed;
}

button.secondary,
a.btn.secondary,
.btn-outline-primary {
  background: var(--surface);
  color: var(--bs-body-color);
  border: 1px solid var(--line-strong);
}
button.secondary:hover,
a.btn.secondary:hover,
.btn-outline-primary:hover {
  background: var(--surface-2);
  color: var(--bs-body-color);
  border-color: var(--line-strong);
}

.btn-mini { min-height: 0; padding: 0.22rem 0.55rem; font-size: 0.8rem; }

/* An action that belongs in running text but must POST -- the sign-in page's
   "send the confirmation link again" -- where an <a href> would be the wrong
   element. It must not inherit any of the button styling above. */
.linklike {
  display: inline;
  min-height: 0;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-weight: inherit;
  cursor: pointer;
  color: var(--brand);
}
.linklike:hover { background: none; color: var(--brand-ink); text-decoration: underline; }
.linklike:disabled { background: none; color: var(--muted); cursor: default; text-decoration: none; }

/* Focus is drawn once, here, for everything. A keyboard reader on the class
   page walks forty links; an outline that only some of them have is worse than
   none. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 3px;
}

form label { display: block; margin: 0.5rem 0; font-size: 0.875rem; color: var(--muted); }
form input,
.choice select,
.choice input[type="text"],
.indent input[type="text"] {
  display: block;
  width: 100%;
  margin-top: 0.25rem;
  padding: 0.45rem 0.65rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--bs-border-radius);
  background: var(--surface);
  color: var(--bs-body-color);
  font: inherit;
}
form input::placeholder { color: var(--muted); }

.inline-form { display: flex; flex-wrap: wrap; gap: 1rem; align-items: end; }
.inline-form label { margin: 0; }
.inline-form input { width: auto; }

.filters { display: flex; gap: 0.4rem; flex-wrap: wrap; align-items: center; margin: 1rem 0 0.75rem; }
.filters .tag {
  cursor: pointer;
  font-family: inherit;
  min-height: 1.875rem;
  display: inline-flex;
  align-items: center;
  padding: 0 0.6rem;
  border-radius: 999px;
  background: var(--surface);
}
.tag-on { border-color: var(--brand); background: var(--brand-soft); color: var(--brand-ink); font-weight: 500; }
.filter-search {
  margin-left: auto;
  width: auto;
  max-width: 12rem;
  padding: 0.35rem 0.6rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--bs-border-radius);
  background: var(--surface);
  color: var(--bs-body-color);
  font: inherit;
  font-size: 0.85rem;
}

.code-input {
  display: block;
  width: 100%;
  margin: 0.6rem 0;
  font: 0.8125rem/1.5 var(--bs-font-monospace);
  padding: 0.6rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--bs-border-radius);
  background: var(--surface);
  color: var(--bs-body-color);
  resize: vertical;
}

.drop {
  background: var(--surface);
  border: 1.5px dashed var(--line-strong);
  border-radius: var(--bs-border-radius-lg);
  padding: 2rem 1.25rem;
  text-align: center;
  transition: border-color 0.12s, background 0.12s;
}
.drop-over { border-color: var(--brand); background: var(--st-ok-bg); }

.choices { display: grid; gap: 1rem; margin-top: 1rem; }
@media (min-width: 39rem) { .choices { grid-template-columns: 1fr 1fr; } }
.choice {
  display: block;
  background: var(--surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius-lg);
  padding: 1rem 1.15rem;
  cursor: pointer;
}
.choice h3 { font-size: 0.95rem; margin: 0 0 0.7rem; }
.choice-current { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand); }
.opt { display: block; margin: 0.3rem 0; font-size: 0.9rem; color: var(--bs-body-color); }
.indent { margin: 0.7rem 0 0 1.4rem; }
.lbl { display: block; font-size: 0.82rem; color: var(--muted); margin-bottom: 0.2rem; }

/* --------------------------------------------------- sign-in page details -- */

.or-divider {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 1.1rem 0;
  color: var(--muted);
  font-size: 0.8rem;
}
.or-divider::before, .or-divider::after { content: ""; flex: 1; height: 1px; background: var(--bs-border-color); }

.google-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 2.25rem;
  width: 100%;
  padding: 0.55rem 0.75rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--bs-border-radius);
  background: var(--surface);
  color: var(--bs-body-color);
  font-weight: 500;
}
.google-btn:hover { background: var(--surface-2); text-decoration: none; }

/* ------------------------------------------------- plans (onboarding) ----- */

.onboarding { max-width: 45rem; margin: 2rem auto; }
.plans { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: 1rem; }
.plan {
  flex: 1 1 11rem;
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius-lg);
  background: var(--surface);
  padding: 1rem 1.25rem;
  display: flex;
  flex-direction: column;
}
.plan h3 { margin: 0 0 0.5rem; }
.plan ul { list-style: none; padding: 0; margin: 0 0 1rem; flex: 1; }
.plan ul li { padding: 0.15rem 0; color: var(--ink-2); }
.plan-current { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand); }
.plan button, .plan .secondary { margin-top: auto; }
.plan-actions { margin-top: 0.75rem; }

/* ------------------------------------------------------- import findings -- */

.bar {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  background: var(--surface);
  border: 1px solid var(--bs-border-color);
  border-left: 3px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius);
  padding: 0.625rem 0.9rem;
  margin: 1rem 0;
  font-size: 0.9rem;
}
.bar-block { border-left-color: var(--st-block); }
.bar-ok    { border-left-color: var(--brand); }

/* A finding. The severity stripe is the only thing distinguishing the two
   kinds, because they explain themselves identically -- what differs is what
   they prevent, not how much a reader is owed. */
.finding {
  border-left: 3px solid var(--bs-border-color);
  padding: 0.1rem 0 0.1rem 0.85rem;
  margin: 0 0 1.3rem;
}
.finding-blocking { border-left-color: var(--st-block); }
.finding-warning  { border-left-color: var(--st-warn); }
.finding h3 { font-size: 0.95rem; margin: 0 0 0.3rem; }
.finding h3 .code {
  font: 600 0.72rem/1 var(--bs-font-monospace);
  color: var(--muted);
  border: 1px solid var(--bs-border-color);
  border-radius: 4px;
  padding: 0.12rem 0.3rem;
  margin-right: 0.4rem;
  vertical-align: 1px;
}
.finding p { font-size: 0.88rem; color: var(--muted); margin: 0 0 0.5rem; }

/* The justification: the minimal set of rows and axioms that produce the
   finding. Monospace and preformatted because it is evidence, and evidence that
   has been reflowed is evidence a reader has to reconstruct. */
.just {
  font: 0.78rem/1.6 var(--bs-font-monospace);
  background: var(--surface-2);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--bs-border-radius);
  padding: 0.5rem 0.7rem;
  margin: 0 0 0.6rem;
  overflow-x: auto;
  color: var(--bs-body-color);
}
.fixes { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.cands { margin-top: 0.2rem; font-size: 0.8rem; }

/* --------------------------------------------------------------- printing -- */

/* The class page is a reference document, and reference documents get printed.
   The chrome is navigation, which paper does not have. */
@media print {
  .topbar, .rail, .page-actions, .toc { display: none; }
  body { display: block; background: #fff; }
  .content { padding: 0; }
  .card, table.grid, .stats { border-color: #bbb; }
  a { color: inherit; text-decoration: none; }
}
