:root {
  --bg: #fbfcfd;
  --panel: #ffffff;
  --panel-2: #fdfdfe;
  --text: #2b3038;
  --muted: #7b8494;
  --border: #eaedf2;
  --accent: #3b6ee6;
  --accent-soft: #eff4fe;
  --pass: #1e9a6c;
  --pass-bg: #ecf9f3;
  --fail: #d4483f;
  --fail-bg: #fef2f1;
  --na: #8b7cba;
  --na-bg: #f5f2fc;
  --todo: #aeb6c2;
  --l1: #2a91a4;
  --l2: #b07f1c;
  --l3: #9d55bb;
  --shadow: 0 1px 2px rgba(16, 24, 40, .04), 0 1px 3px rgba(16, 24, 40, .03);
  --radius: 10px;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

[data-theme="dark"] {
  --bg: #14171c;
  --panel: #1b1f26;
  --panel-2: #21262f;
  --text: #e6e9ef;
  --muted: #98a2b3;
  --border: #2d333d;
  --accent: #6f97ff;
  --accent-soft: #1f2a40;
  --pass: #4fd1a1;
  --pass-bg: #16302a;
  --fail: #ff8b82;
  --fail-bg: #3a1f1e;
  --na: #b9a6ec;
  --na-bg: #2a2340;
  --todo: #6b7480;
  --l1: #5fc6d8;
  --l2: #e0b455;
  --l3: #cf95e8;
  --shadow: 0 1px 2px rgba(0, 0, 0, .4);
}

* { box-sizing: border-box; }

/* Single content width shared by every full-bleed bar and the main column. */
:root { --maxw: 1400px; }

.bar-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  width: 100%;
}

[hidden] { display: none !important; }

html { scroll-padding-top: 12px; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  /* Column layout so <main> can absorb the leftover height and keep the footer
     at the bottom of short pages, such as while the standard is loading. */
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

a { color: var(--accent); }

/* ---------- top bar ---------- */
.topbar {
  padding: 14px 20px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}
.topbar .bar-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
}

.brand h1 { margin: 0; font-size: 20px; letter-spacing: -.2px; }
.brand .ver { color: var(--muted); font-weight: 600; }
.brand .sub { margin: 2px 0 0; font-size: 12.5px; color: var(--muted); }

/* Attribution chip beside the title. Sized off the heading rather than
   inheriting it, so it reads as a badge and not part of the title. */
.made-by {
  display: inline-block;
  vertical-align: middle;
  margin-left: 8px;
  padding: 2px 8px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--panel-2);
  font-size: 11px;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: 0;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
}
.made-by:hover { border-color: var(--accent); color: var(--accent); }

/* Sits beside the brand while everything fits on one row. Once it wraps, it
   takes a full row and aligns left, so the groups line up with the brand
   above rather than stacking against the right edge. */
.topbar-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 18px;
  flex: 1 1 auto;
  justify-content: flex-end;
}

/* The brand plus both groups need roughly 1280px to share a row. Below that
   the toolbar wraps, so align it left with the brand instead of the right edge. */
@media (max-width: 1300px) {
  .topbar-actions { justify-content: flex-start; }
}

/* Each group wraps as a unit, so the toolbar breaks between the assessment
   controls and the data actions rather than mid-group. The groups do not
   shrink, so the toolbar drops to its own row instead of being squeezed. */
.btn-group {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}

.btn {
  font: inherit;
  font-size: 13px;
  padding: 6px 11px;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text);
  border-radius: 7px;
  cursor: pointer;
}
.btn:hover { background: var(--accent-soft); border-color: var(--accent); }
.btn.small { padding: 4px 9px; font-size: 12.5px; }
.btn.icon {
  width: 31px;
  height: 31px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.btn.icon svg { display: block; width: 18px; height: 18px; }
.btn.danger:hover { background: var(--fail-bg); border-color: var(--fail); color: var(--fail); }
.file-btn { display: inline-flex; align-items: center; }

select#project-select {
  font: inherit;
  font-size: 13px;
  padding: 6px 9px;
  /* Fixed rather than content-sized: the options are filled in by JS after
     first paint, which would otherwise shift every button to its right. */
  width: 200px;
  flex: none;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--panel-2);
  color: var(--text);
}

/* ---------- guide modal ---------- */
.guide-backdrop {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: rgba(10, 12, 16, .5);
  opacity: 0;
  transition: opacity .15s ease;
}
.guide-backdrop.show { opacity: 1; }

.guide {
  position: fixed;
  z-index: 91;
  top: 6vh;
  left: 50%;
  width: min(var(--maxw), 92vw);
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .3);
  transform: translate(-50%, -8px);
  opacity: 0;
  transition: opacity .15s ease, transform .15s ease;
}
.guide.show { opacity: 1; transform: translate(-50%, 0); }

@media (prefers-reduced-motion: reduce) {
  .guide, .guide-backdrop { transition: none; }
}

.guide-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
  flex: none;
}

.guide-title { margin: 0; font-size: 16px; }

.guide-close {
  margin-left: auto;
  width: 30px;
  height: 30px;
  font-size: 18px;
  line-height: 1;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text);
  border-radius: 7px;
  cursor: pointer;
}
.guide-close:hover { background: var(--fail-bg); border-color: var(--fail); color: var(--fail); }
.guide-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.guide-inner {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 26px;
  padding: 18px 20px;
  overflow-y: auto;
}

.guide-foot {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding: 14px 20px;
  border-top: 1px solid var(--border);
  flex: none;
}
.guide-dismiss {
  font-weight: 650;
  padding: 8px 16px;
  border-color: var(--accent);
  color: var(--accent);
}
.guide-reopen { font-size: 12.5px; color: var(--muted); }

@media (max-width: 640px) {
  .guide { top: 3vh; max-height: 94vh; }
}

.guide-col { min-width: 0; }

.guide h2 {
  margin: 0 0 8px;
  font-size: 15px;
  letter-spacing: -.1px;
  padding-bottom: 6px;
  border-bottom: 2px solid var(--accent);
  display: inline-block;
}

.guide h3 {
  margin: 16px 0 5px;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--muted);
}

.guide p { margin: 0 0 9px; font-size: 13.5px; }
.guide code {
  font-family: var(--mono);
  font-size: 12.5px;
  background: var(--accent-soft);
  padding: 1px 5px;
  border-radius: 4px;
}

.guide ul.tight { margin: 0 0 9px; padding-left: 18px; font-size: 13.5px; }
.guide ul.tight li { margin-bottom: 5px; }

.note-box {
  padding: 8px 11px;
  background: var(--accent-soft);
  border-left: 3px solid var(--accent);
  border-radius: 0 6px 6px 0;
  font-size: 13px !important;
}

/* level cards */
.lvl-card {
  margin: 10px 0;
  padding: 10px 12px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-left-width: 4px;
  border-radius: 0 8px 8px 0;
}
.lvl-card.l1 { border-left-color: var(--l1); }
.lvl-card.l2 { border-left-color: var(--l2); }
.lvl-card.l3 { border-left-color: var(--l3); }

.lvl-card h3 {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 5px;
  font-size: 13.5px;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text);
  font-weight: 650;
}
.lvl-card p { margin: 0 0 5px; font-size: 13px; }
.lvl-card .eg { color: var(--muted); font-style: italic; font-size: 12.5px; margin: 0; }

/* status legend */
dl.statuses {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 6px 12px;
  margin: 0 0 9px;
  align-items: baseline;
  font-size: 13px;
}
dl.statuses dt {
  font-weight: 650;
  font-size: 12px;
  padding: 2px 9px;
  border-radius: 99px;
  border: 1px solid currentColor;
  justify-self: start;
  white-space: nowrap;
}
dl.statuses dt.s-pass { color: var(--pass); background: var(--pass-bg); }
dl.statuses dt.s-fail { color: var(--fail); background: var(--fail-bg); }
dl.statuses dt.s-na   { color: var(--na);   background: var(--na-bg); }
dl.statuses dt.s-todo { color: var(--todo); }
dl.statuses dd { margin: 0; color: var(--muted); }

/* ---------- dashboard ---------- */
.dashboard {
  padding: 14px 20px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
}
.dashboard .bar-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 22px;
  align-items: center;
}

.stats { display: flex; gap: 18px; flex-wrap: wrap; }
.stat { display: flex; flex-direction: column; min-width: 62px; }
.stat-num { font-size: 21px; font-weight: 680; font-variant-numeric: tabular-nums; line-height: 1.1; }
.stat-lbl { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .5px; }
.stat.pass .stat-num { color: var(--pass); }
.stat.fail .stat-num { color: var(--fail); }
.stat.na .stat-num { color: var(--na); }
.stat.todo .stat-num { color: var(--todo); }

.progress-wrap { flex: 1; min-width: 240px; }
.progress {
  display: flex;
  height: 10px;
  border-radius: 99px;
  overflow: hidden;
  background: var(--border);
}
.seg { height: 100%; transition: width .25s ease; }
.seg.pass { background: var(--pass); }
.seg.fail { background: var(--fail); }
.seg.na { background: var(--na); }
.progress-meta {
  display: flex;
  justify-content: space-between;
  margin-top: 6px;
  font-size: 12px;
  color: var(--muted);
}

/* ---------- controls ---------- */
.controls {
  position: sticky;
  top: 0;
  z-index: 20;
  padding: 10px 20px;
  background: var(--panel-2);
  border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow);
}
.controls .bar-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

#search {
  font: inherit;
  font-size: 13.5px;
  flex: 1;
  min-width: 220px;
  padding: 7px 11px;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--panel);
  color: var(--text);
}
#search:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

.filter-group { display: flex; align-items: center; gap: 5px; }
.fg-label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .5px; }

.chip { cursor: pointer; user-select: none; }
.chip input { position: absolute; opacity: 0; pointer-events: none; }
.chip span {
  display: inline-block;
  font-size: 12.5px;
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 99px;
  background: var(--panel);
  color: var(--muted);
}
.chip input:checked + span {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}
.chip input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- layout ---------- */
/* Padding lives on the outer wrapper, matching how .bar-inner is centered inside
   the full-bleed bars above, so content edges line up at every viewport width.
   It also grows into the height body leaves over, so the loading message can
   fill the page and the footer stays at the bottom on short pages. */
.layout-wrap {
  padding: 20px 20px 0;
  flex: 1;
  display: flex;
  flex-direction: column;
  /* .layout caps itself at --maxw; centre it on the cross axis, since the
     margin:0 auto that would do so in normal flow does not apply here. */
  align-items: center;
}
/* Grow to fill the wrapper's height, and take its full width up to --maxw. */
.layout-wrap > .layout { flex: 1; width: 100%; }

.layout {
  display: grid;
  grid-template-columns: 232px minmax(0, 1fr);
  gap: 22px;
  max-width: var(--maxw);
  margin: 0 auto;
  align-items: start;
}

/* While the standard loads the sidebar is empty: hide it so its panel and
   border do not show as a bare box, and collapse the grid to one column so
   the loading message centres on the page rather than in the second track. */
.toc:empty { display: none; }
.layout:has(.toc:empty) { grid-template-columns: minmax(0, 1fr); }
/* The grid is normally top-aligned; while loading, let the column stretch so
   the message can fill the page height and centre itself in it. */
.layout:has(.loading-msg) { align-items: stretch; }
.chapters:has(.loading-msg) { display: flex; flex-direction: column; }

.toc {
  position: sticky;
  /* Set from JS to the controls bar's real rendered height, so the sidebar sits
     flush under it instead of drifting by a few px whenever chips wrap or fonts render differently. */
  top: calc(var(--controls-h, 52px) + 20px);
  max-height: calc(100vh - var(--controls-h, 52px) - 40px);
  overflow-y: auto;
  /* Rows span the full width so the active marker sits flush against the left
     edge; the row's own padding supplies the text inset. No padding here, so
     rows tile edge to edge and the radius clips them cleanly. */
  padding: 0;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.toc a {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 11px;
  font-size: 12.8px;
  color: var(--text);
  text-decoration: none;
}
.toc a:hover { background: var(--accent-soft); }
.toc a.empty { opacity: .35; }

/* Chapter currently in view. Uses box-shadow rather than border-left, and no
   font-weight change, so nothing reflows as the highlight moves between rows. */
.toc a.active {
  background: var(--accent-soft);
  color: var(--accent);
}
.toc a.active .toc-id,
.toc a.active .toc-count { color: var(--accent); }
.toc .toc-id { color: var(--muted); font-family: var(--mono); font-size: 11.5px; }
.toc .toc-count { color: var(--muted); font-variant-numeric: tabular-nums; font-size: 11.5px; }

/* ---------- chapters ---------- */
.chapter {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 20px;
  overflow: hidden;
  box-shadow: var(--shadow);
}

.chapter-head {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 12px 15px;
  background: none;
  border: 0;
  border-bottom: 1px solid transparent;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
.chapter[open] .chapter-head { border-bottom-color: var(--border); }
.chapter-head:hover { background: var(--panel-2); }
.chapter-head .caret { color: var(--muted); transition: transform .15s; font-size: 11px; }
.chapter[open] .chapter-head .caret { transform: rotate(90deg); }
.chapter-head .cid {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--accent);
  background: var(--accent-soft);
  padding: 2px 7px;
  border-radius: 5px;
}
.chapter-head h2 { margin: 0; font-size: 15.5px; font-weight: 650; flex: 1; }
.chapter-head .mini {
  display: flex;
  gap: 6px;
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
}
.chapter-head .mini b { font-weight: 650; }
.chapter-head .mini .p { color: var(--pass); }
.chapter-head .mini .f { color: var(--fail); }
.chapter-head .mini .n { color: var(--na); }

.chapter-body { padding: 4px 0 8px; }

.section-title {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 12px 16px 6px;
  font-size: 12.5px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .6px;
  font-weight: 650;
}
.section-title .sid { font-family: var(--mono); text-transform: none; letter-spacing: 0; }

/* ---------- requirement rows ---------- */
.req {
  display: grid;
  grid-template-columns: 74px minmax(0, 1fr) auto;
  gap: 12px;
  align-items: start;
  padding: 10px 16px;
  border-top: 1px solid var(--border);
}
.req:hover { background: var(--panel-2); }
.req.s-pass { box-shadow: inset 3px 0 0 var(--pass); }
.req.s-fail { box-shadow: inset 3px 0 0 var(--fail); }
.req.s-na { box-shadow: inset 3px 0 0 var(--na); opacity: .72; }

.req-id {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
  padding-top: 2px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.req-id .lvl {
  align-self: start;
  font-size: 10px;
  font-weight: 700;
  padding: 1px 5px;
  border-radius: 4px;
  border: 1px solid currentColor;
}
.lvl.l1 { color: var(--l1); }
.lvl.l2 { color: var(--l2); }
.lvl.l3 { color: var(--l3); }

.req-main { min-width: 0; }
.req-text { margin: 0; font-size: 14px; }
.req-text mark { background: #ffe58a; color: #1a1d23; border-radius: 3px; padding: 0 1px; }

.note-row { margin-top: 7px; }
.note-toggle {
  font: inherit;
  font-size: 12px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  cursor: pointer;
}
.note-toggle:hover { text-decoration: underline; }
.note-toggle .dot { color: var(--fail); }
textarea.note {
  width: 100%;
  margin-top: 6px;
  min-height: 62px;
  padding: 8px 10px;
  font: inherit;
  font-size: 13px;
  color: var(--text);
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  resize: vertical;
}
textarea.note:focus { outline: 2px solid var(--accent); outline-offset: -1px; }

.status-group { display: flex; gap: 4px; }
.status-group button {
  font: inherit;
  font-size: 12px;
  padding: 4px 10px;
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--muted);
  cursor: pointer;
}
.status-group button:first-child { border-radius: 7px 0 0 7px; }
.status-group button:last-child { border-radius: 0 7px 7px 0; }
.status-group button + button { margin-left: -1px; }
.status-group button:hover { background: var(--panel-2); z-index: 1; }
.status-group button[aria-pressed="true"] { font-weight: 650; z-index: 2; }
.status-group button[data-s="pass"][aria-pressed="true"] { background: var(--pass-bg); border-color: var(--pass); color: var(--pass); }
.status-group button[data-s="fail"][aria-pressed="true"] { background: var(--fail-bg); border-color: var(--fail); color: var(--fail); }
.status-group button[data-s="na"][aria-pressed="true"] { background: var(--na-bg); border-color: var(--na); color: var(--na); }

.empty-msg { padding: 28px 16px; text-align: center; color: var(--muted); font-size: 14px; }

/* Centred in whatever height the page has left over: body is a flex column and
   <main> grows into the free space, so no viewport arithmetic is needed - the
   bars above and the footer below are accounted for by the layout itself. */
.loading-msg {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  flex: 1;
  min-height: 260px;
  margin: 0;
  padding: 0 16px;
  color: var(--muted);
  font-size: 14px;
}
.spinner {
  width: 15px;
  height: 15px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .spinner { animation: none; }
}

/* ---------- footer & toast ---------- */
.footer-wrap {
  padding: 0 20px;
  margin-top: 12px;
}

.footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 24px;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 16px 0 40px;
  border-top: 1px solid var(--border);
  font-size: 12px;
  line-height: 1.6;
  color: var(--muted);
}

.footer p { margin: 0; flex: 1; min-width: 320px; max-width: 78ch; }

.footer-repo {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  padding: 5px 11px;
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
}
.footer-repo:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.footer-repo svg { flex: none; }

/* Bottom-right, clear of the centred toast. */
.to-top {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 30;
  width: 40px;
  height: 40px;
  font-size: 17px;
  line-height: 1;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 50%;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .18);
  cursor: pointer;
}
.to-top:hover { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.to-top:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.toast {
  position: fixed;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%) translateY(20px);
  padding: 9px 16px;
  background: var(--text);
  color: var(--bg);
  border-radius: 8px;
  font-size: 13px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s, transform .2s;
  z-index: 100;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

@media (max-width: 900px) {
  .layout { grid-template-columns: minmax(0, 1fr); }
  .toc { position: static; max-height: none; }
  .req { grid-template-columns: minmax(0, 1fr); }
  .req-id { flex-direction: row; align-items: center; }
  .status-group { justify-self: start; }
}

