/* Krater styles. Hand-written, no framework, no inline styles (the CSP allows only this file).

   The Patchwork palette (Ink, Grape, Deep Purple, Lavender, Quilt) with the same role tokens as Quilt's
   stylesheet, so the two apps read as one family. Components use the role tokens (--surface, --text,
   --accent ...), never the palette directly, so dark mode only redefines the roles. Geist is the only
   typeface (fonts.css). The theme switch is ../js/theme.js: it always sets data-theme on <html>, and the
   OS preference block below covers the moment before it runs.

   Sections: tokens, base, layout, components, pages, small screens. */

/* ── Tokens ── */

:root {
  color-scheme: light;

  /* The Patchwork palette. */
  --ink: #2a2050;
  --grape: #6c3ec1;
  --deep-purple: #4b006e;
  --lavender: #c7b7e2;
  --quilt: #f7f5fb;

  /* Roles. Text pairs are at least 4.5:1 (WCAG AA). */
  --bg: var(--quilt);
  --surface: #ffffff;
  --surface-sunken: #f3f0f9;
  --surface-hover: #faf8fd;
  --border: #e6dff1;
  --border-strong: #d3c7e8;
  --text: var(--ink);
  --text-muted: #5d5580;
  --heading: var(--ink);
  --accent: var(--grape);
  --accent-hover: var(--deep-purple);
  --accent-soft: #efe9fa;
  --on-accent: #ffffff;
  --link: var(--grape);
  --link-hover: var(--deep-purple);
  --focus: var(--grape);
  --header-bg: rgb(255 255 255 / 0.88);
  --quilt-1: var(--grape);
  --quilt-2: var(--lavender);
  --quilt-3: var(--deep-purple);
  --quilt-4: #9b7ad9;

  --good: #1d6b47;
  --good-soft: #e3f4ea;
  --info: #1f5a96;
  --info-soft: #e5effa;
  --warn: #8a4b00;
  --warn-soft: #fdf0dc;
  --bad: #a3243f;
  --bad-soft: #fce8ec;
  --neutral: #575170;
  --neutral-soft: #efedf3;

  --shadow-sm: 0 1px 2px rgb(42 32 80 / 0.06);
  --shadow-md: 0 1px 2px rgb(42 32 80 / 0.06), 0 6px 18px rgb(42 32 80 / 0.07);

  --font-sans: "Geist", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.375rem;
  --text-2xl: 1.75rem;
  --text-3xl: 2.25rem;

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --radius-sm: 6px;
  --radius: 10px;
  --radius-lg: 14px;
  --radius-pill: 999px;
  --content-width: 72rem;
  --gutter: 1rem;
}

/* Dark mode. The set appears twice, once for the toggle's explicit choice and once for the OS preference
   before theme.js has run; keep them identical. */
[data-theme="dark"] {
  color-scheme: dark;

  --bg: #131020;
  --surface: #1c1729;
  --surface-sunken: #171324;
  --surface-hover: #221c33;
  --border: #2f2745;
  --border-strong: #42385f;
  --text: #ece8f6;
  --text-muted: #a8a0c4;
  --heading: #f4f1fb;
  --accent: #7d52d6;
  --accent-hover: #6c3ec1;
  --accent-soft: #2a2145;
  --on-accent: #ffffff;
  --link: #b79cf2;
  --link-hover: #d4c4f7;
  --focus: #b79cf2;
  --header-bg: rgb(28 23 41 / 0.88);
  --quilt-1: #7d52d6;
  --quilt-2: #c7b7e2;
  --quilt-3: #9b7ad9;
  --quilt-4: #4b2a8a;

  --good: #7fd6a6;
  --good-soft: #15301f;
  --info: #8ec0f2;
  --info-soft: #142740;
  --warn: #f2bd6d;
  --warn-soft: #36260d;
  --bad: #f39aae;
  --bad-soft: #3a1621;
  --neutral: #bdb6d4;
  --neutral-soft: #29233a;

  --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.3);
  --shadow-md: 0 1px 2px rgb(0 0 0 / 0.3), 0 6px 18px rgb(0 0 0 / 0.25);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --bg: #131020;
    --surface: #1c1729;
    --surface-sunken: #171324;
    --surface-hover: #221c33;
    --border: #2f2745;
    --border-strong: #42385f;
    --text: #ece8f6;
    --text-muted: #a8a0c4;
    --heading: #f4f1fb;
    --accent: #7d52d6;
    --accent-hover: #6c3ec1;
    --accent-soft: #2a2145;
    --on-accent: #ffffff;
    --link: #b79cf2;
    --link-hover: #d4c4f7;
    --focus: #b79cf2;
    --header-bg: rgb(28 23 41 / 0.88);
    --quilt-1: #7d52d6;
    --quilt-2: #c7b7e2;
    --quilt-3: #9b7ad9;
    --quilt-4: #4b2a8a;

    --good: #7fd6a6;
    --good-soft: #15301f;
    --info: #8ec0f2;
    --info-soft: #142740;
    --warn: #f2bd6d;
    --warn-soft: #36260d;
    --bad: #f39aae;
    --bad-soft: #3a1621;
    --neutral: #bdb6d4;
    --neutral-soft: #29233a;

    --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.3);
    --shadow-md: 0 1px 2px rgb(0 0 0 / 0.3), 0 6px 18px rgb(0 0 0 / 0.25);
  }
}

/* ── Base ── */

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* Components below set `display`, which would otherwise beat the UA's `[hidden] { display: none }`
   (e.g. the estimator's "Use this estimate" button showed before any estimate existed). */
[hidden] {
  display: none !important;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--text);
  font: var(--text-base) / 1.55 var(--font-sans);
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
  margin: 0;
  color: var(--heading);
  line-height: 1.25;
  letter-spacing: -0.015em;
}

h1 {
  font-size: var(--text-2xl);
  font-weight: 700;
}

h2 {
  font-size: var(--text-lg);
  font-weight: 650;
}

h3 {
  font-size: var(--text-base);
  font-weight: 650;
}

p {
  margin: 0 0 var(--space-3);
}

a {
  color: var(--link);
  text-underline-offset: 0.2em;
  text-decoration-thickness: 1px;
}

a:hover {
  color: var(--link-hover);
}

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

code {
  font-family: var(--font-mono);
  font-size: 0.875em;
  overflow-wrap: anywhere;
}

img {
  max-width: 100%;
}

.muted {
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ── Header ── */

/* The staging marker (KRATER_STAGING): a yellow and black hazard-stripe frame around the viewport and a STAGING tab.
   The same look as Weave and Quilt, so its colors are fixed, not role tokens, and do not change in dark mode. Both
   are fixed, ignore the pointer, take no space and do not animate. */
.staging-frame {
  position: fixed;
  inset: 0;
  z-index: 60;
  box-sizing: border-box;
  padding: 8px;
  pointer-events: none;
  background: repeating-linear-gradient(45deg, #facc15 0 12px, #111 12px 24px);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}

.staging-tab {
  position: fixed;
  top: 0;
  left: 50%;
  z-index: 61;
  transform: translateX(-50%);
  pointer-events: none;
  user-select: none;
  padding: 2px 16px 4px;
  border: 2px solid #111;
  border-top: 0;
  border-radius: 0 0 8px 8px;
  background: #facc15;
  color: #000;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.skip-link {
  position: absolute;
  left: var(--space-4);
  top: -4rem;
  z-index: 30;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 600;
}

.skip-link:focus {
  top: var(--space-2);
  color: var(--on-accent);
}

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  border-top: 3px solid var(--accent);
  border-bottom: 1px solid var(--border);
  background: var(--header-bg);
  backdrop-filter: saturate(1.4) blur(10px);
  -webkit-backdrop-filter: saturate(1.4) blur(10px);
}

.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-5);
  max-width: var(--content-width);
  margin: 0 auto;
  padding: var(--space-3) var(--gutter);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--heading);
  font-size: var(--text-lg);
  font-weight: 750;
  letter-spacing: -0.02em;
  text-decoration: none;
}

.brand:hover {
  color: var(--heading);
}

.brand-mark {
  display: block;
  flex: none;
  width: 28px;
  height: 28px;
}

.brand-mark .q1 {
  fill: var(--quilt-1);
}
.brand-mark .q2 {
  fill: var(--quilt-2);
}
.brand-mark .q3 {
  fill: var(--quilt-3);
}
.brand-mark .q4 {
  fill: var(--quilt-4);
}

.brand-mark .stitch {
  fill: none;
  stroke: var(--surface);
  stroke-dasharray: 2 2;
  stroke-width: 1;
}

.site-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
}

.site-nav__link {
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  color: var(--text-muted);
  font-size: var(--text-sm);
  font-weight: 550;
  text-decoration: none;
}

.site-nav__link:hover {
  background: var(--surface-sunken);
  color: var(--text);
}

.site-nav__link[aria-current] {
  background: var(--accent-soft);
  color: var(--link);
  font-weight: 650;
}

.site-account {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
  min-width: 0;
  font-size: var(--text-sm);
}

.site-account__name {
  min-width: 0;
  max-width: 14rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}

.site-account__logout {
  display: inline-flex;
  margin: 0;
}

.link-button {
  margin: 0;
  padding: var(--space-1) var(--space-2);
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-weight: 550;
  cursor: pointer;
}

.link-button:hover {
  background: var(--surface-sunken);
  color: var(--text);
}

/* The light/dark switch, in the header so it never covers page content. */
.theme-toggle {
  display: inline-flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
}

.theme-toggle:hover {
  color: var(--link);
  border-color: var(--border-strong);
}

.theme-toggle__sun {
  display: none;
}

[data-theme="dark"] .theme-toggle__sun {
  display: block;
}

[data-theme="dark"] .theme-toggle__moon {
  display: none;
}

/* ── Layout ── */

.content {
  flex: 1 0 auto;
  width: 100%;
  max-width: var(--content-width);
  margin: 0 auto;
  padding: var(--space-6) var(--gutter) var(--space-7);
}

/* `:not(:first-child)` rather than `* + *` so the gap beats a component's own `margin: 0`. */
.content > :not(:first-child) {
  margin-top: var(--space-5);
}

.site-footer {
  border-top: 1px solid var(--border);
  color: var(--text-muted);
  font-size: var(--text-xs);
}

.site-footer p {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: var(--space-4) var(--gutter);
}

/* The top of a page: its title, a line under it, and its main actions. */
.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-3) var(--space-4);
}

.page-head h1 {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  overflow-wrap: anywhere;
}

.page-head > div {
  min-width: 0;
}

.page-subtitle {
  margin: var(--space-1) 0 0;
  max-width: 48rem;
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

.page-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.eyebrow {
  margin: 0 0 var(--space-1);
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.back-link {
  display: inline-block;
  margin-bottom: var(--space-2);
  font-size: var(--text-sm);
  text-decoration: none;
}

.back-link:hover {
  text-decoration: underline;
}

.section-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-1) var(--space-3);
  margin-bottom: var(--space-3);
}

.section-head p {
  flex-basis: 100%;
  margin: 0;
  color: var(--text-muted);
  font-size: var(--text-sm);
  max-width: 60rem;
}

/* Main column plus a side column for actions (the project page). */
.layout-split {
  display: grid;
  gap: var(--space-5);
  align-items: start;
}

.layout-split > * {
  min-width: 0;
}

.stack > :not(:first-child) {
  margin-top: var(--space-5);
}

@media (min-width: 64rem) {
  .layout-split {
    grid-template-columns: minmax(0, 1fr) 22rem;
  }

  /* No side column when it has nothing in it. */
  .layout-split:has(> aside:not(:has(*))) {
    grid-template-columns: minmax(0, 1fr);
  }
}

.layout-split > aside:not(:has(*)) {
  display: none;
}

.narrow {
  max-width: 34rem;
  margin-left: auto;
  margin-right: auto;
}

/* ── Cards ── */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-5);
}

.card > :last-child {
  margin-bottom: 0;
}

.card > h2,
.card-head {
  margin-bottom: var(--space-3);
}

.card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-3);
}

.card h3 {
  margin: var(--space-4) 0 var(--space-2);
}

.card-head h2,
.card-head h3 {
  margin: 0;
}

.card--flush {
  padding: 0;
  overflow: hidden;
}

.form-card {
  max-width: 46rem;
}

/* ── Stat cards ── */

.stats {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr));
  margin: 0;
}

.stat {
  min-width: 0;
  padding: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

.stat dt,
.stat__label {
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.stat dd,
.stat__value {
  display: block;
  margin: var(--space-1) 0 0;
  font-size: var(--text-xl);
  font-weight: 650;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
  overflow-wrap: anywhere;
}

/* Many small counts (the admin page). */
.stats--compact {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
}

@media (min-width: 48rem) {
  .stats--compact {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.stats--compact .stat {
  padding: var(--space-3);
}

.stats--compact dd {
  font-size: var(--text-lg);
}

.stat--accent {
  border-color: var(--border-strong);
  background: linear-gradient(180deg, var(--accent-soft), var(--surface));
}

.stat--bad dd {
  color: var(--bad);
}

/* A stat that is also a link (the home page shortcuts). */
a.stat {
  color: var(--text);
  text-decoration: none;
}

a.stat:hover {
  border-color: var(--border-strong);
  background: var(--surface-hover);
}

a.stat .stat__value {
  color: var(--link);
}

/* ── Notes and banners ── */

.policy-note,
.compute-hint,
.budget-banner,
.guardian-banner,
.demographics-banner,
.residency-line,
.notice {
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-left: 4px solid var(--info);
  border-radius: var(--radius);
  background: var(--info-soft);
  color: var(--text);
  font-size: var(--text-sm);
}

.compute-hint {
  border-left-color: var(--accent);
  background: var(--surface-sunken);
}

.compute-hint code {
  padding: 0 0.3rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
}

.budget-banner {
  border-color: var(--bad-soft);
  border-left-color: var(--bad);
  background: var(--bad-soft);
  font-weight: 600;
}

.budget-banner--warn {
  border-color: var(--warn-soft);
  border-left-color: var(--warn);
  background: var(--warn-soft);
}

/* A team member under 18 needs a guardian verification before Krater grants budget. The submitter must answer
   Weave's demographics form before Krater submits a grant application. */
.guardian-banner,
.demographics-banner {
  border-color: var(--warn-soft);
  border-left-color: var(--warn);
  background: var(--warn-soft);
}

.guardian-banner ul,
.residency-line ul {
  margin: var(--space-2) 0 0;
  padding-left: var(--space-5);
}

/* Whether a project's whole team is verified US residents in Weave, for picking OSPool projects. */
.residency-line p {
  margin: 0;
}

.queue-filter {
  margin: 0 0 var(--space-4);
  font-size: var(--text-sm);
}

/* ── Flash messages ── */

.flash-list {
  display: grid;
  gap: var(--space-2);
}

.flash {
  margin: 0;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--info-soft);
  border-left: 4px solid var(--info);
  border-radius: var(--radius);
  background: var(--info-soft);
  color: var(--text);
  font-weight: 500;
}

.flash--success {
  border-color: var(--good-soft);
  border-left-color: var(--good);
  background: var(--good-soft);
}

.flash--error {
  border-color: var(--bad-soft);
  border-left-color: var(--bad);
  background: var(--bad-soft);
}

/* ── Buttons ── */

/* Secondary by default; `--primary` is the one main action of a form or page. */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 2.5rem;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition:
    background-color 120ms ease,
    border-color 120ms ease;
}

.button:hover {
  background: var(--surface-sunken);
  color: var(--text);
}

.button--primary {
  border-color: transparent;
  background: var(--accent);
  color: var(--on-accent);
}

.button--primary:hover {
  background: var(--accent-hover);
  color: var(--on-accent);
}

.button--danger {
  border-color: var(--bad);
  color: var(--bad);
}

.button--danger:hover {
  background: var(--bad-soft);
  color: var(--bad);
}

.button--small {
  min-height: 2rem;
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-xs);
}

.button:disabled,
.button[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
}

.action-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-4);
}

.action-row:last-child {
  margin-bottom: 0;
}

/* ── Forms ── */

form {
  margin: 0;
}

.form {
  display: grid;
  gap: var(--space-4);
}

.form > .button,
.form .action-row {
  justify-self: start;
  margin: 0;
}

.form--inline {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
}

.field {
  display: grid;
  gap: var(--space-1);
  min-width: 0;
}

.field label {
  font-size: var(--text-sm);
  font-weight: 600;
}

.field input[type="text"],
.field input[type="url"],
.field input[type="number"],
.field select,
.field textarea,
.compact-form input[type="text"] {
  display: block;
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: var(--text-base);
}

.field input[type="number"] {
  font-variant-numeric: tabular-nums;
}

.field input::placeholder,
.field textarea::placeholder {
  color: var(--text-muted);
  opacity: 0.8;
}

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible,
.compact-form input:focus-visible {
  border-color: var(--accent);
  outline-offset: 0;
}

.field [aria-invalid="true"] {
  border-color: var(--bad);
}

.field textarea {
  resize: vertical;
  min-height: 5rem;
}

.field-hint {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.field-error {
  margin: 0;
  color: var(--bad);
  font-size: var(--text-sm);
  font-weight: 600;
}

.field-error:empty {
  display: none;
}

.field input[type="file"] {
  max-width: 100%;
  font: inherit;
  font-size: var(--text-sm);
}

.field input[type="file"]::file-selector-button {
  margin-right: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

.field input[type="file"]::file-selector-button:hover {
  background: var(--surface-sunken);
}

.form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
}

.form-actions p {
  margin: 0;
}

/* Budget estimator (proposal and amendment draft form). */
.estimator {
  display: grid;
  gap: var(--space-4);
  min-width: 0;
  margin: 0;
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-sunken);
}

.estimator legend {
  padding: 0 var(--space-1);
  font-size: var(--text-sm);
  font-weight: 650;
}

.estimator .policy-note {
  margin: 0;
}

.estimator__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
  gap: var(--space-4);
}

/* A form in a table cell: label, input and button in a small stack. */
.compact-form {
  display: grid;
  gap: var(--space-1);
  min-width: 13rem;
}

.compact-form + .compact-form {
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px dashed var(--border-strong);
}

.compact-form label {
  font-size: var(--text-xs);
  font-weight: 600;
}

.compact-form input[type="text"] {
  padding: var(--space-1) var(--space-2);
  font-size: var(--text-sm);
}

.compact-form .button {
  justify-self: start;
}

/* One self-contained admin action (its heading, fields and button) among several on a card. */
.admin-action + .admin-action {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
}

.admin-action h3 {
  margin: 0 0 var(--space-2);
}

.admin-action .muted {
  margin-bottom: var(--space-3);
}

/* Parts of the draft editor outside the main save form. */
.edit-section {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
}

/* ── Badges and tags ── */

/* Status pills. Neutral for drafts and anything closed, info while a reviewer has to act, good for
   approved and completed, warn when sent back, bad for a rejection. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.05rem 0.6rem;
  border-radius: var(--radius-pill);
  background: var(--neutral-soft);
  color: var(--neutral);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0;
  line-height: 1.7;
  white-space: nowrap;
  vertical-align: middle;
}

.badge::before {
  content: "";
  flex: none;
  width: 0.45em;
  height: 0.45em;
  border-radius: 50%;
  background: currentColor;
}

.badge--good {
  background: var(--good-soft);
  color: var(--good);
}

.badge--info {
  background: var(--info-soft);
  color: var(--info);
}

.badge--bad {
  background: var(--bad-soft);
  color: var(--bad);
}

.badge--draft {
  background: var(--accent-soft);
  color: var(--link);
}

.badge--pending_review,
.badge--pending_completion_review,
.badge--outcome-pending {
  background: var(--info-soft);
  color: var(--info);
}

.badge--approved,
.badge--completed,
.badge--decision-approve,
.badge--outcome-approved {
  background: var(--good-soft);
  color: var(--good);
}

.badge--changes_requested,
.badge--completion_changes_requested {
  background: var(--warn-soft);
  color: var(--warn);
}

.badge--decision-reject,
.badge--outcome-rejected {
  background: var(--bad-soft);
  color: var(--bad);
}

.badge--withdrawn,
.badge--outcome-superseded {
  background: var(--neutral-soft);
  color: var(--neutral);
}

h1 .badge {
  font-size: var(--text-sm);
}

.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin: 0 0 var(--space-3);
}

.tag {
  padding: 0 0.55rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.7;
}

/* ── Lists ── */

.link-list,
.review-list,
.stub-user-list,
.project-list,
.gallery-list,
.feature-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.link-list {
  display: grid;
  gap: var(--space-1);
}

/* Rows in a flush card: a title and its meta on the left, a badge on the right. */
.project-list__item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-1) var(--space-3);
  padding: var(--space-3) var(--space-5);
}

.project-list__item + .project-list__item {
  border-top: 1px solid var(--border);
}

.project-list__item:hover {
  background: var(--surface-hover);
}

.project-list__main {
  display: grid;
  min-width: 0;
}

.project-list__title {
  font-weight: 600;
  text-decoration: none;
  overflow-wrap: anywhere;
}

.project-list__title:hover {
  text-decoration: underline;
}

.project-list__meta {
  color: var(--text-muted);
  font-size: var(--text-sm);
}

.review-list {
  display: grid;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.review-list li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-2);
  font-size: var(--text-sm);
}

.stub-user-list {
  display: grid;
  gap: var(--space-2);
}

.stub-user-list li {
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.stub-user-list li:hover {
  background: var(--surface-hover);
}

.stub-user-list a {
  font-weight: 600;
}

/* Gallery: a grid of project cards; the title link covers the whole card. */
.gallery-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr));
  gap: var(--space-4);
}

.gallery-list__item {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition:
    box-shadow 150ms ease,
    border-color 150ms ease;
}

.gallery-list__item:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
}

.gallery-list__item:focus-within {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

.gallery-list__body {
  display: grid;
  gap: var(--space-2);
  padding: var(--space-4);
}

.gallery-list__body h2 {
  font-size: var(--text-base);
}

.gallery-list__body h2 a {
  color: var(--heading);
  text-decoration: none;
}

.gallery-list__body h2 a:focus-visible {
  outline: none;
}

.gallery-list__body h2 a::after {
  content: "";
  position: absolute;
  inset: 0;
}

.gallery-list__body .tag-list,
.gallery-list__body p {
  margin: 0;
}

.gallery-list__thumb {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
  object-fit: cover;
  border-bottom: 1px solid var(--border);
  background: var(--surface-sunken);
}

.gallery-list__thumb--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--link);
  font-size: var(--text-3xl);
  font-weight: 700;
  background: linear-gradient(135deg, var(--accent-soft), var(--surface-sunken));
}

/* ── Project page ── */

.write-up {
  margin: 0;
  line-height: 1.65;
  overflow-wrap: anywhere;
}

.project-link {
  overflow-wrap: anywhere;
}

.revision + .revision {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
}

.revision__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-1) var(--space-3);
  margin-bottom: var(--space-1);
}

.revision__head h3 {
  margin: 0;
}

.revision p {
  margin: var(--space-1) 0 0;
}

/* ── Screenshots ── */

.screenshot-list {
  list-style: none;
  margin: 0 0 var(--space-3);
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.screenshot-list__item {
  display: grid;
  justify-items: start;
  gap: var(--space-2);
  width: 9rem;
}

.screenshot-list__thumb {
  width: 100%;
  height: 6rem;
  object-fit: cover;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
}

.gallery-screenshots {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr));
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.gallery-screenshots img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-sunken);
}

/* ── Tables ── */

/* The wrapper scrolls on small screens, never the page. */
.table-scroll {
  /* Positioned, so a visually hidden header label stays inside the scrolling box instead of widening the page. */
  position: relative;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.card .table-scroll {
  box-shadow: none;
  border-radius: var(--radius);
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}

.table th,
.table td {
  padding: var(--space-2) var(--space-3);
  text-align: left;
  vertical-align: top;
}

.table th:first-child,
.table td:first-child {
  padding-left: var(--space-4);
}

.table th:last-child,
.table td:last-child {
  padding-right: var(--space-4);
}

.table thead th {
  background: var(--surface-sunken);
  border-bottom: 1px solid var(--border);
  color: var(--text-muted);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
}

.table tbody tr + tr td {
  border-top: 1px solid var(--border);
}

.table tbody tr:hover td {
  background: var(--surface-hover);
}

/* Numbers and money: right-aligned in fixed-width digits so columns line up. */
.num,
.table .num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.nowrap {
  white-space: nowrap;
}

.table td.cell-title {
  min-width: 12rem;
  font-weight: 600;
}

.cell-sub {
  display: block;
  margin-top: 0.15rem;
  color: var(--text-muted);
  font-size: var(--text-xs);
}

.table td code {
  overflow-wrap: normal;
  white-space: nowrap;
}

/* A note row under a pricing row; keep the two visually together. */
.table .table__note {
  padding-top: 0;
  color: var(--warn);
  font-size: var(--text-xs);
}

.table tbody tr + tr:has(.table__note) td {
  border-top: none;
}

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.filter-bar .field {
  min-width: min(100%, 12rem);
}

/* Events Quilt refused (the admin page): one block per event, with its two forms side by side. */
.event-list {
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.event-list > li {
  min-width: 0;
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-left: 4px solid var(--bad);
  border-radius: var(--radius);
}

.event-list__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-1) var(--space-3);
  font-weight: 600;
}

.event-list .details {
  margin: var(--space-2) 0 var(--space-3);
}

.event-list__forms {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr));
}

.event-list__forms .compact-form {
  min-width: 0;
}

.event-list__forms .compact-form + .compact-form {
  margin: 0;
  padding: 0;
  border: 0;
}

/* Label and value pairs. */
.details {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--space-1) var(--space-4);
  font-size: var(--text-sm);
}

.details dt {
  color: var(--text-muted);
}

.details dd {
  margin: 0;
  min-width: 0;
  overflow-wrap: anywhere;
}

/* ── Empty states ── */

.empty-state {
  padding: var(--space-6) var(--space-4);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  color: var(--text-muted);
  text-align: center;
}

.empty-state p {
  margin: 0 0 var(--space-2);
}

.empty-state p:last-child {
  margin-bottom: 0;
}

.empty-state__title {
  color: var(--text);
  font-weight: 600;
}

.card--flush .empty-state {
  margin: var(--space-4);
}

/* ── Pages ── */

/* Signed-out home. */
.hero {
  padding: var(--space-7) var(--space-6);
  background:
    radial-gradient(circle at 100% 0%, var(--accent-soft), transparent 55%),
    var(--surface);
}

.hero .brand-mark {
  width: 48px;
  height: 48px;
  margin-bottom: var(--space-4);
}

.hero h1 {
  font-size: var(--text-3xl);
  letter-spacing: -0.03em;
}

.hero__lead {
  max-width: 38rem;
  margin: var(--space-3) 0 var(--space-5);
  color: var(--text-muted);
  font-size: var(--text-lg);
}

.feature-list {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
}

.feature-list li {
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.feature-list h2 {
  font-size: var(--text-base);
  margin-bottom: var(--space-1);
}

.feature-list p {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--text-sm);
}

/* Error pages and the sign-in pages: one centred card. */
.message-card {
  margin-top: var(--space-6);
  text-align: center;
}

.message-card h1 {
  margin-bottom: var(--space-3);
}

.message-card .action-row {
  justify-content: center;
  margin-top: var(--space-5);
}

/* ── Motion ── */

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
  }
}

/* ── Small screens ── */

@media (max-width: 40rem) {
  .content {
    padding-top: var(--space-5);
  }

  h1 {
    font-size: var(--text-xl);
  }

  .site-header {
    position: static;
  }

  .site-header__inner {
    gap: var(--space-2) var(--space-3);
  }

  .site-nav {
    order: 3;
    width: 100%;
  }

  .site-account__name {
    max-width: 8rem;
  }

  .card {
    padding: var(--space-4);
  }

  .card--flush {
    padding: 0;
  }

  .project-list__item {
    padding: var(--space-3) var(--space-4);
  }

  .hero {
    padding: var(--space-6) var(--space-4);
  }

  .hero h1 {
    font-size: var(--text-2xl);
  }

  .hero__lead {
    font-size: var(--text-base);
  }

  .page-actions,
  .page-actions .button {
    width: 100%;
  }
}

/* ── Krater Compute ── */

/* A job's state, in the same tones as a project's. */
.badge--compute-queued,
.badge--compute-starting {
  background: var(--info-soft);
  color: var(--info);
}

.badge--compute-running,
.badge--compute-succeeded {
  background: var(--good-soft);
  color: var(--good);
}

.badge--compute-paused {
  background: var(--warn-soft);
  color: var(--warn);
}

.badge--compute-failed {
  background: var(--bad-soft);
  color: var(--bad);
}

/* What a job printed, on its page: the end of its log, scrolling inside its own box. */
.log {
  max-height: 32rem;
  margin: 0;
  overflow: auto;
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* Price history (/pricing/history): a line for the median and a band for the 10th to 50th percentile. */
.chart-figure {
  margin: 0;
}

.chart-wrap {
  position: relative;
}

.chart {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.chart__grid {
  stroke: var(--border);
  stroke-width: 1;
}

.chart__tick {
  fill: var(--text-muted);
  font-family: var(--font-sans);
  font-size: 11px;
}

.chart__band {
  fill: var(--accent-soft);
  stroke: none;
}

.chart__line {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.chart__end {
  fill: var(--accent);
  stroke: var(--surface);
  stroke-width: 2;
}

.chart__crosshair {
  stroke: var(--border-strong);
  stroke-width: 1;
}

.chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  margin: 0 0 var(--space-2);
  padding: 0;
  color: var(--text-muted);
  font-size: var(--text-sm);
  list-style: none;
}

.chart-legend li {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.chart-key {
  display: inline-block;
  width: 1.25rem;
}

.chart-key--line {
  height: 2px;
  border-radius: 1px;
  background: var(--accent);
}

.chart-key--band {
  height: 0.75rem;
  border-radius: 2px;
  background: var(--accent-soft);
}

.chart-tooltip {
  position: absolute;
  top: 0;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  box-shadow: var(--shadow-md);
  color: var(--text);
  font-size: var(--text-sm);
  white-space: nowrap;
  pointer-events: none;
}

.chart-tooltip__title {
  margin-bottom: 0.15rem;
  color: var(--text-muted);
}

/* The new-job form: its parts as fieldsets, short fields side by side, and groups of checkboxes or radios. */
.form-fieldset {
  display: grid;
  gap: var(--space-4);
  min-width: 0;
  margin: 0;
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.form-fieldset legend {
  padding: 0 var(--space-1);
  font-size: var(--text-sm);
  font-weight: 650;
}

.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  gap: var(--space-4);
}

.field-label {
  font-size: var(--text-sm);
  font-weight: 600;
}

.choice-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
}

.choice-list--stacked {
  flex-direction: column;
}

.field .choice-list label,
.field label.choice {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 400;
}

/* A secret's value: typed like any text field, never shown. */
.field input[type="password"] {
  display: block;
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: var(--text-base);
}

.field input[type="password"]:focus-visible {
  border-color: var(--accent);
  outline-offset: 0;
}

/* ----------------------------------------------------------------------------------------------------------
   Project teams: the Team card on a project page and team invitations on the home page
   ---------------------------------------------------------------------------------------------------------- */

.team-list,
.invitation-list {
  list-style: none;
  margin: 0 0 var(--space-4);
  padding: 0;
}

.team-list__item,
.invitation {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-3);
  padding: var(--space-2) 0;
}

.team-list__item + .team-list__item,
.invitation + .invitation {
  border-top: 1px solid var(--border);
}

.team-list__name,
.invitation__text {
  display: grid;
  min-width: 0;
  overflow-wrap: anywhere;
}

.invitation__actions {
  display: flex;
  gap: var(--space-2);
}

.invitation-list:last-child {
  margin-bottom: 0;
}

/* ----------------------------------------------------------------------------------------------------------
   The application form (projects/_application.html)
   ---------------------------------------------------------------------------------------------------------- */

fieldset.choice-list {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

fieldset.choice-list legend {
  width: 100%;
  margin-bottom: var(--space-2);
  padding: 0;
}

.word-count {
  margin-top: var(--space-1);
}

.word-count--over {
  color: var(--bad);
  font-weight: 600;
}

.estimator__more summary {
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: 600;
}

.estimator__more[open] summary {
  margin-bottom: var(--space-3);
}

/* The application as reviewers read it on the project page. */
.answers {
  display: grid;
  gap: var(--space-4);
}

.answers h3 {
  margin: 0 0 var(--space-1);
  font-size: var(--text-sm);
  font-weight: 650;
}

.answers p {
  margin: 0;
}

.answer-summary {
  font-size: var(--text-lg);
  font-weight: 500;
}
