/* Fonts are loaded via <link rel="stylesheet"> in each page <head> (see spec §2.6).
   The former @import here serialised the font fetch behind the CSS fetch. */

:root {
  color-scheme: dark;
  scrollbar-color: var(--color-rule-heavy) transparent;

  /* ---- ground planes: one hue (~152°), four levels + a deep wash ---- */
  --color-bg:              #121F19;  /* hsl(153,26%,9.5%)  canvas, body   */
  --color-bg-deep:         #0D1712;  /* masthead + footer wash            */
  --color-surface:         #16231E;  /* L1 resting containers  1.15:1     */
  --color-surface-raised:  #1D2E26;  /* L2 inset controls/wells 1.31:1    */
  --color-surface-overlay: #293B32;  /* L3 hover lift, team cards 1.57:1  */

  /* ---- ink: warm ivory primary, green-grey secondaries ---- */
  --color-text:            #EFEDE7;
  --color-text-secondary:  #AFB8B1;
  --color-text-muted:      #99A69E;

  /* ---- accent: champagne gold, pushed to 47° so it never muddies on green ---- */
  --color-accent:          #DAC473;  /* hsl(47.2,58%,65%) */
  --color-accent-hover:    #F0DEA6;
  --color-accent-contrast: #121F19;  /* text/glyph colour ON a gold fill */
  --color-accent-light:    rgba(240, 235, 220, 0.08);  /* NEUTRAL LIFT — see §1.2 */
  --color-focus-ring:      rgba(218, 196, 115, 0.55);

  /* ---- lines: three weights, three jobs ---- */
  --color-rule:            #26382F;  /* decorative hairlines            1.51:1 */
  --color-rule-heavy:      #3F564B;  /* structural rules, L3 borders    2.36:1 */
  --color-border-control:  #6E877A;  /* FORM CONTROLS ONLY  >=3:1 on all planes */

  /* ---- chart chrome ---- */
  --chart-track:           #1B2A22;  /* the 100% bar-shell track */

  /* ---- semantic tones ---- */
  --tone-positive:        #7FD4A4;
  --tone-positive-bg:     rgba(127, 212, 164, 0.14);
  --tone-positive-border: rgba(127, 212, 164, 0.38);
  --tone-caution:         #E68B40;
  --tone-caution-bg:      rgba(230, 139,  64, 0.14);
  --tone-caution-border:  rgba(230, 139,  64, 0.38);
  --tone-info:            #9CB8EC;
  --tone-info-bg:         rgba(156, 184, 236, 0.14);
  --tone-info-border:     rgba(156, 184, 236, 0.38);
  --tone-teal:            #5FC2D2;
  --tone-teal-bg:         rgba( 95, 194, 210, 0.14);
  --tone-teal-border:     rgba( 95, 194, 210, 0.38);
  --tone-clay:            #E28C88;
  --tone-clay-bg:         rgba(226, 140, 136, 0.14);
  --tone-clay-border:     rgba(226, 140, 136, 0.38);
  --tone-neutral:         #607769;  /* the "no write-up yet" segment */

  /* ---- shape ---- */
  --radius-xs:   4px;
  --radius-sm:   8px;
  --radius-md:  12px;
  --radius-lg:  16px;
  --radius-pill: 999px;

  /* ---- space (4px grid) ---- */
  --space-1: 0.25rem;  --space-2: 0.5rem;   --space-3: 0.75rem;
  --space-4: 1rem;     --space-5: 1.5rem;   --space-6: 2rem;
  --space-8: 3rem;     --space-10: 4.5rem;

  /* ---- elevation (shadow alone is invisible at this darkness — always pair
          a shadow with the inset top highlight) ---- */
  --hairline-top: inset 0 1px 0 rgba(240, 250, 242, 0.045);
  --ring-inset:   inset 0 0 0 1px rgba(240, 250, 242, 0.05);
  --shadow-1: 0 1px 2px rgba(2, 7, 5, 0.45);
  --shadow-2: 0 8px 24px -10px rgba(2, 7, 5, 0.75), 0 2px 6px rgba(2, 7, 5, 0.35);
  --focus-shadow: 0 0 0 2px var(--color-bg), 0 0 0 4px var(--color-accent);

  /* ---- motion ---- */
  --t-fast: 0.15s ease;
  --t-med:  0.22s ease;

  --font-display: 'Libre Baskerville', Georgia, serif;
  --font-body: 'Source Serif 4', 'Charter', Georgia, serif;
  --font-mono: 'JetBrains Mono', 'Consolas', monospace;
  /* Width of the page shell: header, main, footer. */
  --content-width: 1120px;
  /* Long-form prose (problem background, statement, quotes) is capped a little
     narrower so proofs stay at a readable measure inside the wider shell. */
  --reading-width: 92ch;
}

* {
  box-sizing: border-box;
}

/* ---------- Foundation (spec §2) ---------- */

/* [hidden] must beat every author display rule. Fixes the live bug where
   .problem-detail-item{display:flex} defeats <div id="problem-type-item" hidden>
   and paints an empty "TYPE" label in the metadata row. Also guards
   .problem-sequence-nav{display:flex} and lets us delete .upload-panel[hidden]. */
[hidden] { display: none !important; }

::selection      { background: var(--color-accent); color: var(--color-accent-contrast); }
::-moz-selection { background: var(--color-accent); color: var(--color-accent-contrast); }

/* :where() keeps specificity at 0 so component rules still win */
:where(a, button, select, input, textarea, summary, [tabindex]):focus-visible {
  outline: none;
  box-shadow: var(--focus-shadow);
  border-radius: var(--radius-xs);
}
:focus:not(:focus-visible) { outline: none; }

:where(a, button, summary, .problem-card, .journal-tab, .area-pill,
       .suitability-pill, .problem-seq-btn, .bar-row, .kpi, .team-card) {
  transition: color var(--t-fast), background-color var(--t-fast),
              border-color var(--t-fast), box-shadow var(--t-fast),
              transform var(--t-fast), opacity var(--t-fast);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

.skip-link {
  position: fixed; left: -9999px; z-index: 100;
  background: var(--color-accent); color: var(--color-accent-contrast);
  padding: 0.6rem 1rem; border-radius: var(--radius-sm);
  font-family: var(--font-mono); font-size: 0.78rem; text-decoration: none;
}
.skip-link:focus { left: 1rem; top: 1rem; }

/* The masthead is position: sticky (~78px). Without this, following the skip
   link (or any in-page anchor) parks the target underneath it. */
#main, :target { scroll-margin-top: calc(78px + var(--space-4)); }

/* One soft green falloff behind everything: the cheapest "modern" move
   available on a ground this dark. Costs nothing in legibility. */
body::before {
  content: ""; position: fixed; inset: 0 0 auto 0; height: 520px;
  z-index: -1; pointer-events: none;
  background: radial-gradient(120% 70% at 50% -10%,
              rgba(127, 212, 164, 0.055), transparent 72%);
}

/* Skeletons (used by index, problem, summary, upload) */
.skeleton, .skeleton-bar {
  background: linear-gradient(100deg,
    var(--color-surface) 28%, var(--color-surface-raised) 50%, var(--color-surface) 72%);
  background-size: 220% 100%;
  border-radius: var(--radius-sm);
  animation: opor-shimmer 1.4s ease-in-out infinite;
}
@keyframes opor-shimmer { to { background-position: -220% 0; } }
@keyframes opor-spin    { to { transform: rotate(360deg); } }

body {
  margin: 0;
  padding: 0;
  font-family: var(--font-body);
  font-size: 17px;
  color: var(--color-text);
  background: var(--color-bg);
  line-height: 1.7;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--color-accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
a:hover {
  color: var(--color-accent-hover);
}

/* ---------- Masthead (spec §3.1) ---------- */

.site-header-shell {
  position: sticky; top: 0; z-index: 20;
  background: color-mix(in oklab, var(--color-bg-deep) 86%, transparent);
  backdrop-filter: blur(14px) saturate(130%);
  -webkit-backdrop-filter: blur(14px) saturate(130%);
  border-bottom: 1px solid var(--color-rule);
}

.site-header {
  padding: 1.4rem 2rem;
  max-width: var(--content-width);
  margin: 0 auto;
  width: 100%;
  border-bottom: none;
}

.site-header-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1.25rem;
  flex-wrap: wrap;
}

.site-title {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 700;
  margin: 0;
  color: var(--color-text);
  letter-spacing: -0.01em;
  line-height: 1.3;
  flex: 1 1 14rem;
}

.site-title a {
  color: inherit;
  text-decoration: none;
}
.site-title a:hover {
  color: var(--color-accent);
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 0.35rem 0.4rem;
  flex-wrap: wrap;
}

.site-nav-link {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--color-text-secondary);
  border-bottom: none;
  padding: 0.35rem 0.7rem;
  border-radius: var(--radius-pill);
}

.site-nav-link:hover {
  background: var(--color-accent-light);
  color: var(--color-accent);
}

.site-nav-link[aria-current="page"] {
  background: var(--color-accent-light);
  color: var(--color-accent);
}

main {
  flex: 1;
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 2rem 2rem 3rem;
  width: 100%;
}

/* ---------- Banner grammar (spec §4) ---------- */

.unverified-banner, .prompt-banner, .contact-result,
.upload-status-banner, .summary-error, .page-error {
  border: 1px solid var(--color-rule);
  border-left: 3px solid var(--color-rule-heavy);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  box-shadow: var(--hairline-top);
  color: var(--color-text-secondary);
  padding: 0.9rem 1.15rem;
  font-size: 0.94rem;
  line-height: 1.65;
  max-width: 78ch;
  margin: 0;
}
.unverified-banner      { border-left-color: var(--tone-info); }
.unverified-banner strong { color: var(--color-text); font-weight: 600; }
.unverified-banner a { color: var(--tone-info); font-weight: 600; }
.prompt-banner          { border-left-color: var(--color-accent); }
.prompt-banner a { color: var(--color-accent); font-weight: 600; }
.contact-result-success { border-left-color: var(--tone-positive); }
.contact-result-error,
.summary-error, .page-error { border-left-color: var(--tone-clay); }

/* Work-in-progress chip (spec §5.1a) — the eight !important declarations are gone. */
/* Site-status stamp. Deliberately steps OUTSIDE the semantic tone vocabulary:
   every --tone-* colour is already spoken for by the data pills (caution=partial
   progress, info=unverified, positive=solution, teal=direct proof, clay=error), so
   reusing one made this notice read as a per-problem status. It is distinguished
   from those pills on three axes at once — neutral ink instead of a tone, a squared
   silhouette instead of a pill, and a gold edge instead of a leading dot. */
.wip-warning {
  display: inline-flex; align-items: center; gap: 0.55rem;
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.12em;
  font-weight: 500;
  text-transform: uppercase;
  padding: 0.4rem 0.85rem 0.4rem 0.7rem;
  border-radius: var(--radius-xs);
  border: 1px solid var(--color-rule-heavy);
  border-left: 3px solid var(--color-accent);
  background: var(--color-surface-raised);
  color: var(--color-text-secondary);
  box-shadow: var(--hairline-top);
  margin: 0 0 var(--space-5);
}

.notice-stack { display: grid; gap: var(--space-2); margin-bottom: var(--space-6); }

/* ---------- Index hero (spec §5.1b) ---------- */

.list-hero { margin: 0 0 var(--space-6); }
.list-hero-title { font-family: var(--font-display);
  font-size: clamp(1.85rem, 1.2rem + 1.8vw, 2.4rem);
  line-height: 1.18; letter-spacing: -0.015em; margin: 0 0 var(--space-2); }
.list-hero-sub { margin: 0; font-size: 1.05rem;
  color: var(--color-text-secondary); max-width: 62ch; }

/* Problem list (home page) */
.problem-list {
  list-style: none;
  padding: 0;
  margin: 0;
  min-height: 60vh;        /* stops the footer jumping on filter change */
}

.problem-card {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-4) 0.9rem;
  margin-inline: -0.9rem;
  border-radius: var(--radius-md);
  border-bottom: 1px solid var(--color-rule);
}
/* :not(.problem-card-empty) — the empty state reuses .problem-card and its
   ::before carries the "∅" glyph, which must not inherit the hover bar. */
.problem-card:not(.problem-card-empty)::before {
  content: ""; position: absolute; left: 0; top: 0.6rem; bottom: 0.6rem;
  width: 2px; border-radius: 2px; background: var(--color-accent); opacity: 0;
  transition: opacity var(--t-fast);
}
.problem-card:hover { background: var(--color-surface); box-shadow: inset 0 0 0 1px var(--color-rule); }
.problem-card:not(.problem-card-empty):hover::before { opacity: 1; }
.problem-card:has(.problem-card-link:focus-visible) {
  background: var(--color-surface); box-shadow: 0 0 0 2px var(--color-accent); }
.problem-card-link:focus-visible { box-shadow: none; }
.problem-card:last-child {
  border-bottom: none;
}

.problem-card-skeleton { pointer-events: none; }
.skeleton-bar { display: block; height: 0.8rem; margin: 0.3rem 0; }

.problem-card-empty {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-3);
  padding: var(--space-8) var(--space-5); margin: var(--space-5) 0; text-align: center;
  font-style: normal; color: var(--color-text-secondary);
  background: var(--color-surface); border: 1px dashed var(--color-border-control);
  border-radius: var(--radius-lg);
}
.problem-card-empty::before { content: "∅"; font-family: var(--font-display);
  font-size: 1.75rem; line-height: 1; color: var(--color-text-muted); }

.problem-card-link {
  text-decoration: none;
  color: var(--color-text);
}

/* Stretched link: whole card is clickable, while pills/links above stay interactive. */
.problem-card-link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
}

.problem-card:hover .problem-card-title {
  color: var(--color-accent);
}

.problem-card-id {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--color-text-muted);
  flex-shrink: 0;
  width: 2.5rem;
  text-align: right;
  padding-top: 0;
  /* 1.12rem x 1.4 = the .problem-card-title line box, so the two baselines meet. */
  line-height: 1.568rem;
  font-variant-numeric: tabular-nums;
  align-self: flex-start;
}
.problem-card:hover .problem-card-id { color: var(--color-accent); }

.problem-card-body {
  flex: 1;
  min-width: 0;
}

.problem-card-title {
  font-family: var(--font-body);
  font-size: 1.12rem;
  font-weight: 600;
  margin: 0 0 0.35rem;
  /* line-height 1.4 is load-bearing: inline MathJax needs that line box. */
  line-height: 1.4;
  letter-spacing: -0.004em;
  transition: color var(--t-fast);
}

.problem-card-meta {
  font-size: 0.84rem;
  color: var(--color-text-muted);
  line-height: 1.5;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem 0.6rem;
}
.problem-card-meta > span:not(.meta-badges) {
  display: inline;
}
/* Kill the blanket separator: it printed a dot before every pill and stranded a
   leading "·" at the start of wrapped lines. */
.problem-card-meta > span + span::before {
  content: none;
}
.problem-card-meta a {
  color: var(--color-text-secondary);
  text-decoration: none;
  position: relative;
  z-index: 1;
}
.problem-card-meta a:hover {
  color: var(--color-accent);
  text-decoration: underline;
}

.meta-badges { display: inline-flex; gap: 0.35rem; flex-wrap: wrap; }
.meta-date { color: var(--color-text-muted); font-variant-numeric: tabular-nums; }

/* ---------- Badge families (spec §5.1e / §5.3e) ---------- */

/* Shared: they are flex items now, not inline boxes — the vertical-align and
   top: -0.5px optical hacks are gone. */
.area-pill, .attempt-pill, .label-pill {
  letter-spacing: 0.02em;
  line-height: 1.35;
  position: static;
  top: auto;
  vertical-align: baseline;
}

.area-pill {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 400;
  padding: 0.1rem 0.6rem;
  border-radius: var(--radius-sm);
  background: transparent;
  border: 1px solid var(--color-rule-heavy);
  color: var(--color-text-secondary);
  margin-left: 0;
}

/* Clickable area pill on list cards (sits above the card stretched link). */
.area-pill-btn {
  z-index: 1;
  cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast), color var(--t-fast);
}
.area-pill-btn:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
  background: var(--color-accent-light);
}
.area-pill-btn.area-pill-active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-accent-contrast);
}

.attempt-pill {
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-pill);
  font-size: 0.7rem;
  padding: 0.14rem 0.6rem 0.14rem 0.5rem;
  gap: 0.35rem;
  font-family: var(--font-mono);
  font-weight: 500;
}
.attempt-pill::before { content: ""; width: 5px; height: 5px; border-radius: 50%;
                        background: currentColor; flex: none; }

.attempt-pill-solution {
  border: 1px solid var(--tone-positive-border);
  background: var(--tone-positive-bg);
  color: var(--tone-positive);
}

.attempt-pill-partial {
  border: 1px solid var(--tone-caution-border);
  background: var(--tone-caution-bg);
  color: var(--tone-caution);
}

.label-pill {
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-sm);
  font-size: 0.7rem;
  padding: 0.16rem 0.55rem;
  font-family: var(--font-mono);
  font-weight: 500;
}

.label-pill-quantitative {
  border: 1px solid var(--tone-info-border);
  background: var(--tone-info-bg);
  color: var(--tone-info);
}

.label-pill-direct-proof {
  border: 1px solid var(--tone-teal-border);
  background: var(--tone-teal-bg);
  color: var(--tone-teal);
}

.label-pill-counterexample {
  border: 1px solid var(--tone-clay-border);
  background: var(--tone-clay-bg);
  color: var(--tone-clay);
}

/* ---------- Journal tabs → segmented control (spec §5.1f) ---------- */
.journal-tabs {
  display: inline-flex;
  gap: 0.2rem;
  padding: 0.25rem;
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  margin: 0 0 var(--space-5);
  flex-wrap: wrap;
}

.journal-tab {
  appearance: none;
  border: none;
  background: transparent;
  border-radius: var(--radius-pill);
  padding: 0.45rem 1rem;
  font-family: var(--font-body);
  font-size: 0.88rem;
  line-height: 1.3;
  color: var(--color-text-secondary);
  cursor: pointer;
}

.journal-tab:hover { background: var(--color-surface-overlay); color: var(--color-text); }

.journal-tab-active {
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  font-weight: 600;
  border: none;
}

.journal-tab-count { opacity: 0.8; font-variant-numeric: tabular-nums; margin-left: 0.35rem; }

/* ---------- Global panels + controls (spec §5.0) ---------- */

/* Every resting container becomes a real plane. Shadow alone is invisible at
   this darkness — always pair it with the inset top highlight. */
.problem-definition-box, .raw-source-block, .lit-review-details,
.problem-seq-btn, .list-controls, .summary-details, .upload-panel,
.contact-form-col, .problem-detail-grid, .team-card {
  background: var(--color-surface);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-md);
  box-shadow: var(--hairline-top), var(--shadow-1);
}

.list-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: var(--space-3);
  padding: 0.9rem 1rem;
  margin-bottom: var(--space-4);
}

.control-field {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
  /* without a grow the wrapped row leaves ~190px dead to the right of Sort */
  flex: 1 1 12rem;
}
.control-field-search {
  flex: 1 1 240px;
}

.control-label {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 500;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

/* Form controls: sunken well + the 3:1 border + the modern ring focus */
.control-input,
.upload-field input[type="text"], .upload-field input[type="password"],
.upload-field input[type="email"], .contact-field textarea {
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border-control);
  border-radius: var(--radius-sm);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 0.95rem;
  line-height: 1.4;
  padding: 0.6rem 0.8rem;
  min-height: 42px;
  width: 100%;
  box-shadow: var(--hairline-top);
  transition: border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
}
.control-input::placeholder, .contact-field textarea::placeholder,
.upload-field input::placeholder { color: var(--color-text-muted); opacity: 1; }

.control-input:focus-visible,
.upload-field input:focus-visible, .contact-field textarea:focus-visible {
  outline: 2px solid transparent;   /* keeps a ring in forced-colors mode */
  outline-offset: 2px;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px var(--color-focus-ring);
}
.upload-field input:user-invalid, .contact-field textarea:user-invalid {
  border-color: var(--tone-clay);
}
input:-webkit-autofill, input:-webkit-autofill:hover,
input:-webkit-autofill:focus, textarea:-webkit-autofill {
  -webkit-text-fill-color: var(--color-text);
  caret-color: var(--color-accent);
  box-shadow: 0 0 0 1000px var(--color-surface-raised) inset;
  transition: background-color 9999s ease-out;
}
select.control-input {
  cursor: pointer;
  appearance: none; -webkit-appearance: none; padding-right: 2.1rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%2399A69E' stroke-width='1.6'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 0.7rem center; background-size: 11px;
  /* Narrow enough that search + three selects share one row in the wide shell;
     still comfortably fits the longest option label. */
  max-width: 13rem;
}

.control-search {
  width: 100%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%2399A69E' stroke-width='1.6' stroke-linecap='round'%3E%3Ccircle cx='6.9' cy='6.9' r='4.4'/%3E%3Cpath d='M10.2 10.2 14 14'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: left 0.7rem center;
  background-size: 14px;
  padding-left: 2.2rem;
}

.list-status {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-bottom: 1rem;
  font-size: 0.86rem;
  color: var(--color-text-muted);
}
.list-status-count strong {
  font-family: var(--font-mono);
  font-size: 1.05rem;
  font-variant-numeric: tabular-nums;
  color: var(--color-accent);
  font-weight: 500;
}

.active-filters {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--color-accent);
  background: var(--color-accent-light);
  border: 1px solid var(--color-rule-heavy);
  border-radius: var(--radius-pill);
  padding: 0.15rem 0.3rem 0.15rem 0.6rem;
}

.filter-chip-x {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.05rem;
  height: 1.05rem;
  padding: 0;
  font-size: 0.85rem;
  line-height: 1;
  color: inherit;
  background: transparent;
  border: none;
  border-radius: var(--radius-pill);
  cursor: pointer;
}
.filter-chip-x:hover {
  background: var(--color-accent);
  color: var(--color-accent-contrast);
}

/* ---------- Buttons (spec §5.0) ---------- */

.inline-action-btn, .copy-source-bibtex-btn, .copy-bibtex-btn, .list-clear-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono); font-size: 0.72rem;
  letter-spacing: 0.04em; text-transform: uppercase;
  padding: 0.5rem 0.9rem;
  margin: 0;
  border: 1px solid var(--color-border-control);
  border-radius: var(--radius-pill);
  background: var(--color-surface-raised);
  color: var(--color-text-secondary);
  box-shadow: var(--hairline-top); cursor: pointer;
}
.inline-action-btn:hover, .copy-source-bibtex-btn:hover,
.copy-bibtex-btn:hover, .list-clear-btn:hover {
  background: var(--color-accent-light); border-color: var(--color-accent);
  color: var(--color-accent); transform: translateY(-1px);
}
.inline-action-btn:active { transform: none; box-shadow: none; }
/* The :where() foundation ring is specificity (0,1,0) and loses to the box-shadow
   in the block above, so every one of these buttons must re-assert it. */
.inline-action-btn:focus-visible, .copy-source-bibtex-btn:focus-visible,
.copy-bibtex-btn:focus-visible, .list-clear-btn:focus-visible {
  box-shadow: var(--focus-shadow);
}
.is-copied { color: var(--tone-positive); border-color: var(--tone-positive-border); }

.copy-source-bibtex-btn { margin-top: 0.65rem; }

.upload-btn {                    /* the one primary action, shared by contact + upload */
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-radius: var(--radius-sm); padding: 0.8rem 1.5rem;
  min-height: 2.9rem; font-weight: 500;
  background: var(--color-accent); color: var(--color-accent-contrast);
  border: 1px solid var(--color-accent); box-shadow: var(--shadow-1); cursor: pointer;
}
.upload-btn:hover { background: var(--color-accent-hover); border-color: var(--color-accent-hover);
                    transform: translateY(-1px); box-shadow: 0 6px 18px -8px rgba(218,196,115,0.5); }
.upload-btn:active:not(:disabled) { transform: translateY(0); box-shadow: none; }
/* was opacity:.45 on gold — murky olive with near-illegible text, shown exactly
   while the user is waiting. Now a readable neutral. */
.upload-btn:disabled {
  opacity: 1; background: var(--color-surface-raised);
  border-color: var(--color-border-control); color: var(--color-text-muted);
  transform: none; cursor: progress;
}
.upload-btn[aria-busy="true"]::after {
  content: ""; display: inline-block; margin-left: 0.6rem;
  width: 0.85em; height: 0.85em; vertical-align: -0.1em;
  border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%; animation: opor-spin 0.7s linear infinite;
}
.upload-btn-secondary { background: transparent; color: var(--color-text-secondary);
                        border-color: var(--color-border-control); padding: 0.45rem 0.85rem;
                        font-size: 0.72rem; min-height: 0; box-shadow: none; }
/* Deliberately loses its gold — "Sign out" should not be the most conspicuous
   thing on the page. */
.upload-btn-secondary:hover { background: var(--color-surface-overlay);
                              color: var(--color-text); border-color: var(--color-rule-heavy);
                              box-shadow: none; }
/* Declared last so it beats the base, :hover and -secondary box-shadows above. */
.upload-btn:focus-visible, .upload-btn-secondary:focus-visible {
  box-shadow: var(--focus-shadow);
}

/* Clickable area on problem detail page */
.problem-area-link {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px dotted currentColor;
}
.problem-area-link:hover {
  color: var(--color-accent);
}

.problem-area-sep {
  color: var(--color-text-muted);
  margin: 0 0.35rem;
}

/* Solution attempts */
.solution-attempts-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.solution-attempt-group {
  margin: 1rem 0 1.35rem;
}

.solution-attempt-group h3 {
  font-family: var(--font-display);
  font-size: 0.98rem;
  margin: 0 0 0.4rem;
  color: var(--color-text);
}

.solution-attempts-list li {
  padding: 0.35rem 0;
  border-bottom: 1px solid var(--color-rule);
}
.solution-attempts-list li:last-child {
  border-bottom: none;
}
.solution-attempt-meta {
  font-family: var(--font-mono);
  font-size: 0.66rem;
  color: var(--color-text-muted);
  margin-left: 0.5rem;
}

/* ---------- Literature-review disclosure (spec §5.3f) ---------- */
.lit-review-details {
  max-width: var(--reading-width);
  border-radius: var(--radius-md);
  padding: 0;
}
.lit-review-details > summary {
  list-style: none;
  padding: 0.85rem 1.1rem;
  border-radius: var(--radius-md);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--color-text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.lit-review-details > summary::-webkit-details-marker { display: none; }
.lit-review-details > summary::after { content: "\203A"; float: right;
  transition: transform var(--t-fast); }
.lit-review-details[open] > summary::after { transform: rotate(90deg); }
.lit-review-details > summary:hover { background: var(--color-accent-light); color: var(--color-accent); }
.lit-review-details[open] > summary { border-bottom: 1px solid var(--color-rule);
  border-radius: var(--radius-md) var(--radius-md) 0 0; }
.lit-review-details[open] > div { padding: 0 1.1rem 1.1rem; }

/* ---------- Pagination → segmented control (spec §5.1h) ---------- */
.pagination {
  display: flex;
  align-items: center;
  width: max-content;
  max-width: 100%;
  /* the bottom margin keeps the pill off the trailing prompt banner */
  margin: var(--space-8) auto;
  gap: 0.15rem;
  padding: 0.25rem;
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  flex-wrap: wrap;
}

.pagination a,
.pagination span {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.2rem; height: 2.2rem; padding: 0 0.6rem; border: none;
  border-radius: var(--radius-pill);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  text-decoration: none;
  color: var(--color-text-secondary);
}
.pagination a:hover { background: var(--color-surface-overlay); color: var(--color-text); }
.pagination .current {
  background: var(--color-accent);
  color: var(--color-accent-contrast);
  font-weight: 600;
  border-bottom: none;
}
.pagination .disabled {
  opacity: 0.55;
  cursor: default;
  pointer-events: none;
}
.pagination-gap { color: var(--color-text-muted); }

/* ---------- Problem detail page (spec §5.3) ---------- */

/* Page shell matches the Problems listing (--content-width). Prose and math
   inside sections still use --reading-width so line length stays readable. */

main.is-loading .problem-section,
main.is-loading .problem-source-block,
main.has-error .problem-section,
main.has-error .problem-source-block,
main.has-error .problem-detail-grid { visibility: hidden; }

/* §4 banners carry margin: 0 and rely on a wrapper for spacing; problem.html has
   no .notice-stack around this one, so it sat flush against the header. */
body.page-problem #unverified-banner:not([hidden]) { margin-bottom: var(--space-5); }

.back-link {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  color: var(--color-text-muted);
  text-decoration: none;
  margin-bottom: 1.5rem;
}
.back-link:hover {
  color: var(--color-accent);
}

.problem-header {
  margin-bottom: var(--space-10);
  padding-bottom: var(--space-5);
  /* No border-bottom: the metadata card already closes the header with an edge,
     and the 4.5rem margin does the separating. Two hairlines 25px apart read as
     a rendering error. */
}

.problem-topline {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.5rem;
}

.problem-number-badge {
  display: inline-flex; align-items: center;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.2rem 0.6rem;
  border-radius: var(--radius-pill);
  background: var(--color-accent-light);
  border: 1px solid var(--color-accent);
  color: var(--color-accent);
}
.problem-number-badge:empty {
  display: none;
}

.problem-id {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  color: var(--color-text-muted);
  letter-spacing: 0.03em;
  margin-left: auto;
}

.problem-title {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 1.15rem + 1.7vw, 2.35rem);
  font-weight: 700;
  line-height: 1.22;
  letter-spacing: -0.015em;
  margin: 0 0 1.4rem;
  text-wrap: balance;
}

.problem-source-block {
  margin-bottom: 1.2rem;
}

.problem-source-paper {
  font-size: 0.92rem;
  line-height: 1.5;
  color: var(--color-text-secondary);
}
.problem-source-paper a {
  color: var(--color-accent);
}

.problem-source-authors {
  font-size: 0.84rem;
  color: var(--color-text-secondary);
  margin-top: 0.15rem;
  line-height: 1.5;
}

.solved-notice-block {
  margin: 0.8rem 0 0;
}
.solved-notice-label {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--color-text);
  margin-bottom: 0.35rem;
}

/* Metadata row → a real grid in a card (panel base from §5.0) */
.problem-detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr));
  gap: 1.1rem 1.5rem;
  /* No border-top override — it is a four-sided panel now (§5.0), and killing the
     top edge left the rounded top corners unstroked. */
  padding: 1.15rem 1.25rem;
  font-size: 0.84rem;
}

.problem-detail-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.25rem;
}

.problem-detail-label {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 500;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  white-space: nowrap;
}

.problem-detail-value {
  font-weight: 500;
  color: var(--color-text);
}

/* Sections */
.problem-section > p,
.problem-section > ul,
.problem-section > ol,
.problem-section .math-content,
.problem-section .section-note {
  max-width: var(--reading-width);
}

.problem-section {
  margin: var(--space-8) 0;
}

.problem-section h2 {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--color-text);
}

.problem-section p {
  margin: 0 0 1rem;
}

.section-note {
  margin: 0 0 0.8rem;
  color: var(--color-text-muted);
  font-size: 0.9rem;
  border-left: 2px solid var(--color-rule-heavy);
  padding-left: 0.6rem;
}

/* The statement callout: the 4px gold slab is gone; the eyebrow carries the
   emphasis it was carrying. */
.problem-definition-box {
  border: none;
  border-left: none;
  border-radius: var(--radius-md);
  background: var(--color-surface-raised);
  box-shadow: var(--ring-inset), var(--hairline-top);
  padding: 1.5rem 1.75rem;
}

.box-eyebrow {
  display: block; font-family: var(--font-mono); font-size: 0.62rem;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--color-text-muted);
  margin-bottom: 0.75rem;
}

/* ADDITIVE ONLY — improves long mathematical prose, never hurts it. */
mjx-container[display="true"] {
  margin: 1.35rem 0 !important;
  overflow-x: auto; overflow-y: hidden;
  padding: 0.2rem 0 0.35rem; scrollbar-width: thin;
}
mjx-container { color: var(--color-text); }

/* Computational suitability pills */
.suitability-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 2rem;
  margin: 0.4rem 0 0;
  padding: 0;
}

.suitability-row {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin: 0;
}

.suitability-label {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 500;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
}

.suitability-value {
  margin: 0;
}

.suitability-pill {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 0.2rem 0.6rem;
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  line-height: 1.2;
}

.suitability-pill.high {
  background: var(--tone-positive-bg);
  border-color: var(--tone-positive-border);
  color: var(--tone-positive);
}

.suitability-pill.medium {
  background: var(--tone-caution-bg);
  border-color: var(--tone-caution-border);
  color: var(--tone-caution);
}

/* .low was a dead grey lozenge that read as disabled. high/medium/low now form
   one visible three-step ramp: mint / amber / blue. */
.suitability-pill.low {
  background: var(--tone-info-bg);
  border-color: var(--tone-info-border);
  color: var(--tone-info);
}

.suitability-pill.unknown {
  background: transparent;
  border-color: var(--color-rule);
  color: var(--color-text-secondary);
}

.source-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: var(--space-4);
}

.raw-source-block {
  margin: 0 0 1rem;
  padding: 1rem;
  white-space: pre-wrap;
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 0.82rem;
  line-height: 1.6;
}

#problem-latex {
  overflow-x: auto;
  overflow-y: visible;
  width: 100%;
  padding: 0.5rem 0;
  white-space: pre-wrap;
}

.problem-section ul {
  margin: 0.5rem 0 1rem;
  padding-left: 1.5rem;
}

/* Literature review cards */
.lit-source-card {
  padding: 1.2rem 0;
  border-bottom: 1px solid var(--color-rule);
}
.lit-source-card:last-child {
  border-bottom: none;
}
.lit-source-heading {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: 0.5rem;
}

/* Problem detail: previous / next */
.problem-sequence-nav {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: 1rem;
  margin-top: var(--space-10);
  padding-top: var(--space-5);
  border-top: 1px solid var(--color-rule);
}

.problem-seq-slot {
  flex: 1 1 0;
  min-width: 0;
}

.problem-seq-slot:last-child {
  text-align: right;
}

.problem-seq-counter {
  flex: 0 0 auto;
  align-self: center;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--color-text-muted);
  letter-spacing: 0.04em;
  white-space: nowrap;
}

.problem-seq-btn {
  display: inline-flex;
  flex-direction: column;
  gap: 0.22rem;
  text-decoration: none;
  border: none;
  border-radius: var(--radius-md);
  background: var(--color-surface);
  box-shadow: var(--ring-inset), var(--hairline-top);
  padding: 0.95rem 1.2rem;
  cursor: default;
  max-width: 100%;
}

a.problem-seq-btn {
  cursor: pointer;
}

a.problem-seq-btn:hover {
  background: var(--color-surface-overlay);
  box-shadow: var(--ring-inset), var(--shadow-2);
  transform: translateY(-1px);
}

a.problem-seq-btn:hover .problem-seq-btn-label {
  color: var(--color-accent-hover);
}

/* Same cascade collision as the buttons: the panel shadow above out-ranks the
   :where() foundation ring, so re-assert it here. */
a.problem-seq-btn:focus-visible {
  box-shadow: var(--focus-shadow);
}

.problem-seq-btn-direction {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  font-weight: 500;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.problem-seq-btn-label {
  font-family: var(--font-body);
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--color-text-secondary);
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: color var(--t-fast);
}

/* was opacity:.38 — a ghost box */
.problem-seq-btn.disabled {
  display: none;
}

@media (max-width: 640px) {
  .problem-sequence-nav {
    flex-direction: column;
    gap: 0.75rem;
  }
  .problem-seq-slot:last-child {
    text-align: left;
  }
  .problem-seq-counter {
    align-self: flex-start;
    order: -1;
  }
  .problem-seq-btn {
    width: 100%;
  }
  .problem-seq-btn-label {
    white-space: normal;
  }
}

/* ---------- Footer (spec §3.4) ---------- */
.site-footer {
  border-top: 1px solid var(--color-rule);
  background: var(--color-bg-deep);
  padding: var(--space-6) 2rem;
  margin-top: auto;
}

.footer-content {
  /* main is --content-width WITH 2rem of its own padding, so the footer column
     has to lose the same 4rem or it breaks alignment by 32px on each edge. */
  max-width: calc(var(--content-width) - 4rem);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;
  gap: 0.35rem 2rem;
  text-align: left;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.footer-maintainers {
  font-weight: 600;
  color: var(--color-text);
}

/* The funding acknowledgement carries an institutional obligation and was the
   least legible text on the site. */
.footer-content > div:last-child {
  grid-column: 1 / -1;
  max-width: 68ch;
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-rule);
  color: var(--color-text-secondary);
}

@media (max-width: 640px) {
  .footer-content { grid-template-columns: 1fr; }
}

/* MathJax */
.math-content {
  overflow-x: auto;
  overflow-wrap: break-word;
  word-break: break-word;
}

/* —— Shared page furniture (summary, contact, upload, team) —— */

.page-header {
  margin-bottom: clamp(2rem, 4vw, 3rem);
  padding-bottom: var(--space-5);
  border-bottom: 1px solid var(--color-rule);
}

.page-title {
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.35rem + 2.1vw, 2.6rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.02em;
  margin: 0 0 0.6rem;
}

.page-lede {
  margin: 0;
  color: var(--color-text-secondary);
  font-size: 1.08rem;
  line-height: 1.65;
  max-width: 68ch;
}

/* Everything below the header on upload.html is centred at 46rem/30rem (§5.5a),
   so the full-shell page header read as a second, unrelated grid. */
body.page-upload .page-header { max-width: 46rem; margin-inline: auto; }

.label-optional {
  font-size: 0.9em; letter-spacing: 0.04em; color: var(--color-text-muted);
  text-transform: none; font-style: italic;
}

/* —— Summary of Results —— */

.summary-section {
  margin: 2.5rem 0;
}

/* Shared section heading: a fixed-width tick above, replacing the ragged
   variable-width gold underline. */
.summary-section-title, .problem-section h2 {
  display: block;
  border-bottom: none;
  padding-bottom: 0;
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--color-text);
  font-size: 1.35rem;
  letter-spacing: -0.015em;
  margin: 0 0 var(--space-4);
}
.summary-section-title::before, .problem-section h2::before {
  content: ""; display: block; width: 2.25rem; height: 2px;
  background: var(--color-accent); border-radius: 2px; margin-bottom: 0.85rem;
}

.summary-note {
  margin: 0 0 1.1rem;
  color: var(--color-text-muted);
  font-size: 0.88rem;
  max-width: 78ch;
}

.summary-error {
  font-family: var(--font-mono);
  font-size: 0.8rem;
}

.summary-divider {
  border: none;
  border-top: 1px solid var(--color-rule);
  margin: 3rem 0 0;
}

/* Charts get a real plane; the section title, note and footnote stay outside
   the panel, on the ground at full measure. */
#outcome-bar, #solution-type-bar, .bar-chart, .col-chart-wrap {
  background: var(--color-surface);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-lg);
  padding: 1.4rem 1.5rem;
  box-shadow: var(--hairline-top), var(--shadow-1);
}

/* Accordions — the native ▶ marker is replaced by a chevron. */
.summary-details {
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-md);
  background: var(--color-surface);
  padding: 0;
  margin-bottom: 0.75rem;
}

.summary-details > summary {
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1.25rem;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
  border-radius: var(--radius-md);
  cursor: pointer;
}
.summary-details > summary::-webkit-details-marker { display: none; }
.summary-details > summary::after {
  content: ""; width: 0.5rem; height: 0.5rem;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg); transition: transform var(--t-med);
}
.summary-details[open] > summary::after { transform: rotate(225deg); }
.summary-details > summary:hover { background: var(--color-surface-raised); color: var(--color-accent); }

.summary-details[open] > summary {
  color: var(--color-text);
  border-radius: var(--radius-md) var(--radius-md) 0 0;
}

/* The accordion is already a panel. Its children carried their own 1px rule and
   a mismatched radius, so every open accordion showed two parallel hairlines. */
.summary-details .bar-chart,
.summary-details .col-chart-wrap,
.summary-details .table-scroll {
  border: none;
  box-shadow: none;
  background: transparent;
  border-radius: 0 0 var(--radius-md) var(--radius-md);
}

/* Headline figures */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
  margin: 0;
  padding: 0;
}
@media (max-width: 900px) { .kpi-grid { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 560px) { .kpi-grid { grid-template-columns: 1fr; } }

.kpi {
  background: var(--color-surface);
  border: 1px solid var(--color-rule);
  border-top: 1px solid var(--color-rule);   /* kills the 2014 coloured top strip */
  border-radius: var(--radius-md);
  padding: 1.35rem 1.4rem;
}
.kpi:hover { border-color: var(--color-rule-heavy); transform: translateY(-1px); }

.kpi-positive { box-shadow: inset 3px 0 0 var(--tone-positive); }
.kpi-caution  { box-shadow: inset 3px 0 0 var(--tone-caution); }

.kpi-value {
  font-family: var(--font-display);
  font-size: 2.4rem;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  color: var(--color-text);
  margin: 0;
}

.kpi-positive .kpi-value {
  color: var(--tone-positive);
}

.kpi-caution .kpi-value {
  color: var(--tone-caution);
}

.kpi-meta {
  margin: 0.35rem 0 0;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.kpi-label {
  font-size: 0.92rem;
  color: var(--color-text);
  line-height: 1.4;
}

.kpi-note {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
}

/* Chart tones: each class only carries the colour, applied by the shapes below. */
.tone-positive { --tone: var(--tone-positive); }
.tone-caution { --tone: var(--tone-caution); }
.tone-neutral { --tone: var(--tone-neutral); }
.tone-teal { --tone: var(--tone-teal); }
.tone-clay { --tone: var(--tone-clay); }
.tone-accent { --tone: var(--color-accent); }

.bar-seg,
.chart-swatch,
.col-bar {
  background: var(--tone, var(--tone-neutral));
}

.chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.75rem;
  margin-bottom: var(--space-4);
}

.chart-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-body);
  font-size: 0.88rem;
  letter-spacing: 0;
  color: var(--color-text-secondary);
}

.chart-legend-value {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  color: var(--color-text);
}

.chart-swatch {
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  flex-shrink: 0;
}

.bar-wide {
  margin-bottom: 0.75rem;
}

.bar-wide .bar-track {
  height: 1.5rem;
  border-radius: var(--radius-pill);
}

.bar-rows {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

.bar-row {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.35rem 0.5rem;
  margin: 0 -0.5rem;
  border-radius: var(--radius-sm);
}
.bar-row:hover { background: var(--color-surface-raised); }

.bar-label {
  flex: 0 0 14.5rem;
  font-size: 0.8rem;
  line-height: 1.35;
  color: var(--color-text-secondary);
}

/* Descriptive labels are far too long for the fixed column the short category
   labels sit in, so they take their own line above the bar. The label-to-bar
   gap must be several times smaller than the row-to-row gap. */
.bar-rows-wide-labels { gap: 1.5rem; }

.bar-rows-wide-labels .bar-row {
  flex-wrap: wrap;
  gap: 0.3rem 0.85rem;
}

.bar-rows-wide-labels .bar-label {
  flex: 1 1 100%;
}

.bar-shell {
  flex: 1 1 auto;
  min-width: 0;
  background: var(--chart-track);
  border-radius: var(--radius-pill);
}

.bar-inner {
  min-width: 2px;
}

.bar-track {
  display: flex;
  height: 0.72rem;
  border-radius: var(--radius-pill);
  overflow: hidden;
  gap: 2px;
}

.bar-seg {
  min-width: 3px;
  transition: filter var(--t-fast);
}
/* MANDATORY — see §1.4. Makes adjacent-segment contrast non-load-bearing. */
.bar-seg + .bar-seg { box-shadow: -1px 0 0 var(--color-bg); }
.bar-track:hover .bar-seg { filter: saturate(0.6) opacity(0.55); }
.bar-seg:hover { filter: none; }

.bar-seg-empty {
  width: 100%;
  background: var(--color-surface-raised);
}

.bar-total {
  flex: 0 0 3rem;
  text-align: right;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-secondary);
}

.chart-footnote {
  margin: 0.9rem 0 0;
  max-width: 78ch;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  line-height: 1.6;
  letter-spacing: 0.03em;
  color: var(--color-text-muted);
}

/* Vertical histogram (publication years) — one continuous axis rule, not a row
   of disconnected dashes. */
.col-chart {
  display: flex;
  align-items: flex-end;
  gap: 0.5rem;
  height: 13rem;
  padding-bottom: 0;
  border-bottom: 1px solid var(--color-rule);
}

.col-item {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  height: 100%;
  min-width: 0;
}

.col-bar-wrap {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 0.25rem;
}

.col-bar {
  width: 100%;
  /* cap the BAR, not the column, so the axis spacing in §5.2h is untouched */
  max-width: 4.5rem;
  margin-inline: auto;
  border-radius: 6px 6px 0 0;
  min-height: 2px;
}

.col-value {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-secondary);
  text-align: center;
}

.col-label {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--color-text-muted);
  text-align: center;
  padding-top: 0.5rem;
  border-top: none;
  margin-top: 0;
}

/* Category table */
.table-scroll {
  overflow-x: auto;
  /* gives `.summary-table thead th { position: sticky }` a scrollport to stick in */
  max-height: 70vh;
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-md);
}

.summary-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.summary-table th,
.summary-table td {
  padding: 0.7rem 0.9rem;
  border-bottom: 1px solid var(--color-rule);
  text-align: left;
}

.summary-table thead th {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  white-space: nowrap;
  background: var(--color-surface);
  position: sticky;
  top: 0;
}

.summary-table td.num,
.summary-table th.num {
  text-align: right;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.col-value, .summary-table td.num, .summary-table th.num { font-variant-numeric: tabular-nums; }

.summary-table tbody tr:hover {
  background: var(--color-surface-raised);   /* was 1.07:1 — invisible */
}

.summary-table tfoot th,
.summary-table tfoot td {
  border-top: 2px solid var(--color-rule-heavy);
  border-bottom: none;
  font-weight: 600;
  color: var(--color-text);
}

/* Loading state: three JSON fetches resolve before replaceChildren(). */
#kpi-grid:empty { min-height: 15rem; }
.bar-chart:empty, #outcome-bar:empty, #solution-type-bar:empty { min-height: 9rem; }
#kpi-grid:empty, .bar-chart:empty, #outcome-bar:empty, #solution-type-bar:empty {
  border-radius: var(--radius-lg);
  background: linear-gradient(100deg, var(--color-surface) 30%,
              var(--color-surface-raised) 50%, var(--color-surface) 70%);
  background-size: 200% 100%; animation: opor-shimmer 1.4s ease-in-out infinite;
}
/* boot() adds .is-failed to <main> when a fetch rejects: stop pretending data is
   still on its way underneath the error banner. */
main.is-failed :is(#kpi-grid, .bar-chart, #outcome-bar, #solution-type-bar):empty {
  animation: none; background: none; min-height: 0; border: none;
}

@media (max-width: 640px) {
  .bar-row {
    flex-wrap: wrap;
    gap: 0.3rem 0.6rem;
  }
  .bar-label {
    flex: 1 1 100%;
  }
  .bar-shell {
    flex: 1 1 auto;
  }
}

/* —— Contact —— */

.contact-layout {
  display: grid;
  max-width: none;
  grid-template-columns: minmax(0, 1.35fr) minmax(19rem, 0.85fr);
  gap: clamp(1.5rem, 3vw, 3.25rem);
  align-items: start;
}
@media (max-width: 860px) { .contact-layout { grid-template-columns: 1fr; gap: 2rem; } }

.contact-form-col {
  min-width: 0;
  padding: clamp(1.5rem, 3vw, 2.25rem);
}
/* Scope the 26rem release so upload.html keeps its narrow form. */
.contact-form-col .upload-form { max-width: none; gap: var(--space-5); }

.contact-aside {
  min-width: 0;
  position: sticky;
  top: 6rem;
}

.contact-aside-title {
  font-family: var(--font-display);
  font-size: 0.95rem;
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0;
  color: var(--color-text);
  margin: 1.75rem 0 0.5rem;
}
.contact-aside-title:first-child { margin-top: 0; }

.contact-aside p {
  margin: 0 0 1rem;
  font-size: 0.95rem;
  color: var(--color-text-secondary);
  line-height: 1.65;
  /* the aside collapses under the form at <=860px while main still carries its
     2rem desktop padding, which let this prose run to a ~100-character measure */
  max-width: 62ch;
}
.contact-aside-title { max-width: 62ch; }

#contact-direct-emails {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 0.4rem; margin: 0 0 1.25rem;
}
#contact-direct-emails a {
  font-family: var(--font-mono); font-size: 0.78rem;
  text-decoration: none; color: var(--color-text-secondary);
  padding: 0.4rem 0.7rem; border: 1px solid var(--color-rule);
  border-radius: var(--radius-pill); background: var(--color-surface);
  max-width: 100%; overflow-wrap: anywhere;
}
#contact-direct-emails a:hover { color: var(--color-accent);
  border-color: var(--color-accent); background: var(--color-accent-light); }

.field-hint {
  margin: var(--space-2) 0 0;
  font-size: 0.8rem;
  line-height: 1.5;
  max-width: 52ch;
  color: var(--color-text-muted);
}

.contact-field textarea {
  resize: vertical;
  min-height: 11rem;
  line-height: 1.6;
}

#contact-form { caret-color: var(--color-accent); }

.contact-result {
  margin: var(--space-5) 0 0;
  max-width: 44rem;
}

@media (prefers-reduced-motion: no-preference) {
  .contact-result:not([hidden]) { animation: result-in 0.22s ease-out both; }
  @keyframes result-in { from { opacity: 0; transform: translateY(-4px); } }
}

/* —— Upload page (login-protected PDF intake scaffold) —— */

.upload-status-banner {
  font-family: var(--font-mono);
  letter-spacing: 0.02em;
  max-width: 46rem;
  margin-inline: auto;
  margin-bottom: var(--space-5);
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.8rem;
}
/* It painted an empty 40px bar before JS ran. */
.upload-status-banner:empty { display: none; }
.upload-status-banner::before { content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: var(--tone-info); flex: 0 0 auto; }
.upload-status-banner.is-connected { border-left-color: var(--tone-positive); }
.upload-status-banner.is-connected::before { background: var(--tone-positive); }
.upload-status-banner.is-scaffold  { border-left-color: var(--tone-caution); }
.upload-status-banner.is-scaffold::before { background: var(--tone-caution); }

.upload-panel {
  border: 1px solid var(--color-rule);
  border-top: 1px solid var(--color-rule);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  padding: 1.75rem;
  margin: 0 0 var(--space-5);
  box-shadow: var(--hairline-top), var(--shadow-1);
}
#login-panel  { max-width: 30rem; margin-inline: auto; }
#login-panel .upload-form { max-width: none; }
#upload-panel { max-width: 46rem; margin-inline: auto; }
.upload-panel > * + .upload-panel-title { margin-top: 2.25rem; }

.upload-panel-title {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
  margin: 0 0 var(--space-4);
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--color-rule);
  display: flex;
  align-items: center;
  gap: 0.55rem;
}
.upload-panel-title::before { content: ""; width: 3px; height: 0.8em;
  background: var(--color-accent); border-radius: 2px; }

.upload-form {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  max-width: 26rem;
}

.upload-field label {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
  margin-bottom: var(--space-1);
}

.upload-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: var(--space-4);
}

/* Errors must not render in the brand gold — "Only PDF files are accepted."
   read as a highlight. */
.upload-form-error {
  font-family: var(--font-mono);
  margin: 0.7rem 0 0;
  min-height: 0;
  font-size: 0.8rem;
  color: var(--tone-clay);
  scroll-margin: 6rem;
}
.upload-form-error:not(:empty) {
  display: flex; align-items: flex-start; gap: 0.5rem;
  padding: 0.6rem 0.85rem; background: var(--tone-clay-bg);
  border: 1px solid var(--tone-clay-border); border-left: 3px solid var(--tone-clay);
  border-radius: var(--radius-sm);
}
/* Empty live region: it contributes no height but still takes flex gaps, which
   opened a ~54px void between Password and Sign in. Setting textContent brings
   it straight back, and role="alert" still fires. */
.upload-form-error:empty { display: none; }
.upload-form-error:not(:empty)::before { content: "!"; font-family: var(--font-mono); font-weight: 500; }

.upload-session-bar {
  max-width: 46rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  padding: 0.7rem 0.9rem;
  margin: 0 0 var(--space-5);
  background: var(--color-surface-raised);
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-md);
  font-size: 0.88rem;
  color: var(--color-text-secondary);
}

#session-label {
  font-family: var(--font-mono); font-size: 0.78rem; letter-spacing: 0.03em;
  color: var(--color-text-secondary); display: inline-flex; align-items: center; gap: 0.5rem;
}
#session-label::before { content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--tone-positive); }

.upload-dropzone {
  position: relative;
  max-width: 46rem;
  border: 1px dashed var(--color-border-control);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  padding: 2.5rem 1.5rem;
  overflow: hidden;
  text-align: center;
  cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast);
}
.upload-dropzone::before { content: "⇪"; display: block; font-family: var(--font-mono);
  font-size: 1.4rem; color: var(--color-text-muted); margin-bottom: 0.6rem; }
.upload-dropzone:hover { border-color: var(--color-rule-heavy); background: var(--color-surface-raised); }
.upload-dropzone.is-dragover { border-color: var(--color-accent); border-style: solid;
  background: var(--color-surface-raised);
  box-shadow: inset 0 0 0 1px var(--color-accent), 0 0 0 3px var(--color-accent-light); }
.upload-dropzone.is-uploading,
.upload-dropzone.is-disabled { cursor: progress; border-style: solid; }
.upload-dropzone.is-uploading::after,
.upload-dropzone.is-disabled::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0;
  height: 2px; background: linear-gradient(90deg, transparent, var(--color-accent), transparent);
  animation: opor-sweep 1.1s linear infinite; }
@keyframes opor-sweep { from { transform: translateX(-100%);} to { transform: translateX(100%);} }

.upload-dropzone-title {
  font-family: var(--font-display);
  font-size: 1.05rem;
  margin: 0 0 0.35rem;
}

.upload-dropzone-hint {
  margin: 0;
  font-size: 0.9rem;
  color: var(--color-text-muted);
}

.upload-file-input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}

.upload-list {
  list-style: none;
  margin: 1.25rem 0 0;
  padding: 0;
  max-width: 46rem;
  border-top: none;
}

.upload-list-item {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  align-items: center;
  gap: 0.9rem;
  padding: 0.8rem 0.75rem;
  border-bottom: 1px solid var(--color-rule);
  border-radius: var(--radius-sm);
  font-size: 0.95rem;
}
.upload-list-item:hover { background: var(--color-surface-raised); }
.upload-list-item:last-child { border-bottom: none; }

.upload-list-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  justify-content: flex-end;
}
.upload-list-actions .upload-btn {
  padding: 0.35rem 0.7rem;
  font-size: 0.78rem;
}

.upload-list-meta {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--color-text-muted);
}

.upload-status-pill {
  display: inline-flex; align-items: center; border-radius: var(--radius-pill);
  padding: 0.14rem 0.6rem; font-family: var(--font-mono); font-size: 0.66rem; font-weight: 500;
  border: 1px solid var(--tone-info-border); background: var(--tone-info-bg); color: var(--tone-info);
}
.upload-status-pill.is-reviewed { border-color: var(--tone-positive-border);
  background: var(--tone-positive-bg); color: var(--tone-positive); }
.upload-status-pill.is-pending  { border-color: var(--tone-caution-border);
  background: var(--tone-caution-bg); color: var(--tone-caution); }

.upload-empty {
  max-width: 46rem;
  margin: var(--space-4) 0 0;
  padding: 1.75rem 1.25rem;
  text-align: center;
  border: 1px dashed var(--color-rule);
  border-radius: var(--radius-md);
  color: var(--color-text-muted);
  font-size: 0.9rem;
}
.upload-empty::after { content: "Uploads you submit will appear here after review.";
  display: block; margin-top: 0.4rem; font-family: var(--font-mono); font-size: 0.7rem; }

/* ---------- Our Team (spec §6.2 + roster) ---------- */

.team-grid {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13.5rem, 1fr));
  gap: var(--space-5);
  max-width: 68rem;
}
/* Five members: 5-up once the shell is at full width, then 4-up, 3-up on
   laptops, 2-up on tablets, 1-up on phones. */
@media (min-width: 1120px) { .team-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--space-4); } }
/* 4-up step: without it the roster jumped 3-up (336px cards) straight to 5-up
   (198px cards) at exactly 1120px. */
@media (min-width: 1000px) and (max-width: 1119px) { .team-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-4); } }
@media (max-width: 999px)  { .team-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 820px)  { .team-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .team-grid { grid-template-columns: 1fr; gap: var(--space-4); } }

.team-card {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: var(--space-6) var(--space-4) var(--space-5);
  /* L3 overlay: photographic skin tones need a plane between them and the ground */
  background: var(--color-surface-overlay);
  border: 1px solid var(--color-rule-heavy);   /* NOT --color-rule: only 1.05:1 on L3 */
  border-radius: var(--radius-lg);
  box-shadow: var(--hairline-top), var(--shadow-1);
}
.team-card:hover {
  transform: translateY(-2px);
  border-color: var(--color-border-control);
  box-shadow: var(--hairline-top), var(--shadow-2);
}

/* The photo and the initials monogram share one circular footprint and one ring,
   so a row mixing the two stays even. team.html uses `.team-avatar` (the bare
   <img>) and `.team-avatar-fallback` — there is deliberately only one naming
   system here, so the wrong class cannot be reached for later. */
.team-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 8.5rem; height: 8.5rem; flex: 0 0 auto;
  border-radius: 50%;
  overflow: hidden;
  object-fit: cover;
  object-position: 50% 25%;       /* headshots: bias the crop toward the eyeline */
  background: var(--color-surface-raised);
  /* gilt hairline: 3.19:1 against the card, and it conceals any mismatch between
     a JPEG's baked-in backdrop and the green ground at the circle's edge */
  box-shadow: 0 0 0 1px var(--color-surface-overlay),
              0 0 0 3px var(--color-focus-ring);
  margin-bottom: var(--space-4);
  text-decoration: none;
}

/* Initials fallback: the same footprint and ring as a real photo, so it reads as
   deliberate rather than broken. */
.team-avatar-fallback {
  background: var(--color-surface-overlay);
  box-shadow: var(--ring-inset),
              0 0 0 1px var(--color-surface-overlay),
              0 0 0 3px var(--color-focus-ring);
  font-family: var(--font-mono);
  font-size: 1.9rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  line-height: 1;
  color: var(--color-text-secondary);
}

.team-name {
  font-family: var(--font-display); font-size: 1.1rem; font-weight: 700;
  line-height: 1.3; margin: 0 0 0.35rem; color: var(--color-text);   /* 10.16:1 */
}
.team-name a { color: inherit; text-decoration: none; }
.team-name a:hover { color: var(--color-accent); text-decoration: underline; }
.team-role {
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.09em;
  text-transform: uppercase; margin: 0 0 0.55rem;
  color: var(--color-accent);                                        /* 6.87:1 */
  line-height: 1.5;
}
.team-affiliation {
  font-size: 0.86rem; line-height: 1.5; margin: 0; max-width: 22ch;
  color: var(--color-text-secondary);                                /* 5.84:1 */
  /* the card is a flex column: this drops every affiliation to a common baseline
     however many lines the role above it wraps to */
  margin-top: auto;
}
/* Scoped OFF .team-name: a blanket `.team-card a` sits after `.team-name a
   { color: inherit }` at equal specificity and turned every linked name gold. */
.team-role a, .team-affiliation a { color: var(--color-accent); }    /* 6.87:1 */

/* ---------- Narrow viewports ---------- */

@media (max-width: 640px) {
  .site-header {
    padding: 1rem 1.2rem;
  }
  .site-title {
    font-size: 1.05rem;
    /* .site-title carries `flex: 1 1 14rem` for the row-direction header. Once
       .site-header-row flips to column below, that basis sizes the MAIN axis =
       height, forcing the h1 to 224px and the sticky masthead to ~340px. */
    flex: 0 0 auto;
  }
  .site-header-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.85rem;
  }
  main {
    padding: 1.5rem 1.2rem 2rem;
  }
  .site-footer {
    padding: var(--space-6) 1.2rem;
  }
  .problem-title {
    font-size: 1.6rem;
  }
  .problem-detail-grid {
    grid-template-columns: 1fr;
    gap: 0.9rem;
  }
  .list-controls {
    flex-direction: column;
    align-items: stretch;
    gap: 0.7rem;
  }
  .control-field,
  .control-field-search {
    flex: 1 1 auto;
    width: 100%;
  }
  select.control-input {
    max-width: none;
  }
  .upload-list-item {
    grid-template-columns: 1fr;
    gap: 0.35rem;
    justify-items: start;
  }
}
