/* ===========================================================================
   MSF 3D printing customizer -- house style
   ---------------------------------------------------------------------------
   Médecins Sans Frontières brand basics: one red, white surfaces, black type.
   The masthead is white with a red rule, never a black bar. Red is reserved
   for the logo, primary actions and errors, so it keeps its meaning.

   Self-contained: no CDN stylesheet, no web font download, no icon font. The
   content security policy in customizer/web.py allows styles from 'self'
   only, so there are no inline styles or <style> blocks in the templates.
   ======================================================================== */

:root {
  --msf-red: #ee0000;
  --msf-red-dark: #c00000;
  --msf-red-tint: #fdecec;

  --ink: #000000;
  --ink-muted: #55565a;
  --ink-faint: #7c7d82;

  --surface: #ffffff;
  --surface-sunken: #f5f5f5;
  --surface-raised: #fafafa;

  --line: #d8d8d8;
  --line-strong: #b4b4b4;

  --ok: #157347;
  --ok-tint: #e8f5ee;
  --warn: #8a6100;
  --warn-tint: #fdf4e3;

  --radius: 4px;
  --radius-lg: 6px;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
  --shadow-lifted: 0 4px 14px rgba(0, 0, 0, 0.10);

  --font: "Helvetica Neue", Helvetica, Arial, "Segoe UI", system-ui, sans-serif;
  --font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;

  --page-max: 1240px;
  --gap: 24px;
}

/* --------------------------------------------------------------- reset -- */

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

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

body {
  margin: 0;
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--surface-sunken);
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

h1, h2, h3, h4 { margin: 0 0 0.5em; line-height: 1.2; font-weight: 700; }
h1 { font-size: 2rem; }
h2 { font-size: 1.4rem; }
h3 { font-size: 1.1rem; }
p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

a { color: var(--msf-red); text-decoration: underline; text-underline-offset: 2px; }
a:hover { color: var(--msf-red-dark); }

code, pre, kbd { font-family: var(--font-mono); font-size: 0.875em; }
code { background: var(--surface-sunken); padding: 1px 5px; border-radius: var(--radius); }

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

/* Inline icons scale with the text they sit in. Without an explicit size an
   SVG with only a viewBox falls back to the browser's 300x150 default, which
   swamps a heading. Rules for buttons and the viewer override this. */
.icon {
  width: 1em;
  height: 1em;
  fill: currentColor;
  flex: none;
  vertical-align: -0.125em;
}

h1 .icon, h2 .icon, h3 .icon,
.card__header .icon,
.notice .icon {
  /* Slightly under the cap height so the icon reads as a marker, not a title. */
  width: 0.85em;
  height: 0.85em;
  margin-right: 0.15em;
  opacity: 0.75;
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: 8px; top: -60px; z-index: 100;
  background: var(--msf-red); color: #fff; padding: 10px 16px;
  border-radius: var(--radius); text-decoration: none; transition: top 0.15s;
}
.skip-link:focus { top: 8px; color: #fff; }

/* -------------------------------------------------------------- layout -- */

.page {
  flex: 1;
  width: 100%;
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 32px 20px 56px;
}

.stack > * + * { margin-top: var(--gap); }

/* ------------------------------------------------------------ masthead -- */

.masthead {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.masthead__rule { height: 6px; background: var(--msf-red); }

.masthead__inner {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 14px 20px;
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  color: var(--ink);
  margin-right: auto;
}
.brand:hover { color: var(--ink); }

/* Full MSF lockup, mark and wordmark. Served at 455x200 so it stays sharp on
   high-density screens; the height below drives the displayed size. */
.brand__logo {
  height: 52px;
  width: auto;
  flex: none;
  display: block;
}

.brand__title {
  font-weight: 700;
  font-size: 1.2rem;
  letter-spacing: -0.01em;
  padding-left: 16px;
  border-left: 1px solid var(--line);
  line-height: 1.2;
}

@media (max-width: 620px) {
  .brand__logo { height: 40px; }
  .brand__title { font-size: 1rem; padding-left: 12px; }
}

@media (max-width: 420px) {
  .brand { gap: 8px; }
  .brand__logo { height: 34px; }
  .brand__title { font-size: 0.95rem; padding-left: 10px; }
}

.masthead__nav { display: flex; align-items: center; gap: 6px; }
.masthead__nav form { margin: 0; }

.nav-link {
  display: inline-block;
  padding: 8px 12px;
  color: var(--ink);
  text-decoration: none;
  border-radius: var(--radius);
  font-weight: 500;
  font-size: 0.95rem;
}
.nav-link:hover { background: var(--surface-sunken); color: var(--msf-red); }
.nav-link[aria-current="page"] { color: var(--msf-red); box-shadow: inset 0 -2px 0 var(--msf-red); border-radius: 0; }

/* -------------------------------------------------------------- footer -- */

.site-footer {
  background: var(--surface);
  border-top: 1px solid var(--line);
  padding: 20px;
  font-size: 0.85rem;
  color: var(--ink-muted);
}
.site-footer__inner {
  max-width: var(--page-max);
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
  justify-content: space-between;
}

/* --------------------------------------------------------------- cards -- */

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

.card__header {
  padding: 14px 20px;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.card__header h2, .card__header h3 { margin: 0; font-size: 1.05rem; }

.card__body { padding: 20px; }
.card__footer {
  padding: 14px 20px;
  border-top: 1px solid var(--line);
  background: var(--surface-raised);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* --------------------------------------------------------------- intro -- */

.intro {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 6px solid var(--msf-red);
  border-radius: var(--radius-lg);
  padding: 28px 32px;
  margin-bottom: 32px;
}
.intro h1 { margin-bottom: 12px; }
.intro p { max-width: 68ch; color: var(--ink-muted); margin-bottom: 0; }

/* The one thing on the page nobody may skim past: a downloaded STL is not a
   validated part. Weighted heavier than the paragraph above it. */
.intro__disclaimer {
  margin-top: 14px;
  font-weight: 600;
  color: var(--ink) !important;
}

/* ------------------------------------------------------------ catalogue -- */

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}
.section-head h2 { margin: 0; }
.section-head p { margin: 0; color: var(--ink-muted); font-size: 0.9rem; }

/* ------------------------------------------------- search, tabs, paging -- */

.browse {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-bottom: 16px;
}

.browse__search {
  position: relative;
  flex: 1 1 320px;
  display: flex;
  align-items: center;
}
.browse__search .icon {
  position: absolute;
  left: 12px;
  width: 16px;
  height: 16px;
  fill: var(--ink-faint);
  pointer-events: none;
}
/* The attribute selector is load-bearing: the shared field rule below is
   `input[type="search"]`, which has the same specificity as `.browse__search
   input` and comes later, so its shorthand `padding` would reset the left
   padding and run the text under the magnifier. */
.browse__search input[type="search"] {
  padding-left: 38px;
  /* Safari draws its own clear button and inner shadow on search inputs. */
  -webkit-appearance: none;
  appearance: none;
}

/* The category menu. Sized so the longest category name is readable without
   the control stretching across the toolbar. */
.browse__category {
  flex: 0 1 240px;
  width: auto;
  min-width: 0;
}
.browse__category--compact { flex: 0 1 200px; padding-top: 7px; padding-bottom: 7px; }

.tag--link { text-decoration: none; }
.tag--link:hover { border-color: var(--ink); color: var(--ink); }

.pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 28px;
}
.pager__pages { display: flex; align-items: center; gap: 4px; }
.pager__page {
  min-width: 36px;
  padding: 7px 10px;
  text-align: center;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 600;
}
.pager__page:hover { border-color: var(--ink); }
.pager__page.is-current {
  background: var(--msf-red);
  border-color: var(--msf-red);
  color: #fff;
}
.pager__gap { color: var(--ink-faint); padding: 0 2px; }

.catalogue {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
  gap: var(--gap);
  list-style: none;
  margin: 0;
  padding: 0;
}

.item-card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s;
}
.item-card:hover {
  border-color: var(--line-strong);
  box-shadow: var(--shadow-lifted);
  transform: translateY(-2px);
}

.item-card__media {
  aspect-ratio: 16 / 10;
  background: var(--surface-sunken);
  display: grid;
  place-items: center;
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}
.item-card__media img { width: 100%; height: 100%; object-fit: contain; }
.item-card__media svg { width: 56px; height: 56px; fill: var(--line-strong); }

.item-card__body { padding: 18px 20px; flex: 1; display: flex; flex-direction: column; gap: 10px; }
.item-card__body h3 { margin: 0; }
.item-card__body p { color: var(--ink-muted); font-size: 0.92rem; margin: 0; flex: 1; }
.item-card__foot { padding: 0 20px 20px; }

.meta-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }

.tag {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  color: var(--ink-muted);
  background: var(--surface);
}
.tag--python { border-color: #9aa7c7; color: #3b4a6b; background: #eef1f8; }
.tag--openscad { border-color: #c7a99a; color: #6b4a3b; background: #f8f1ee; }
.tag--unavailable { border-color: var(--msf-red); color: var(--msf-red); background: var(--msf-red-tint); }
.tag--hidden { border-color: var(--warn); color: var(--warn); background: var(--warn-tint); }

/* ------------------------------------------------------------- buttons -- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font: inherit;
  font-weight: 600;
  padding: 10px 18px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  background: var(--surface);
  color: var(--ink);
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.btn svg { width: 17px; height: 17px; fill: currentColor; flex: none; }

.btn--primary { background: var(--msf-red); border-color: var(--msf-red); color: #fff; }
.btn--primary:hover:not(:disabled) { background: var(--msf-red-dark); border-color: var(--msf-red-dark); color: #fff; }

.btn--secondary { background: var(--surface); border-color: var(--ink); color: var(--ink); }
.btn--secondary:hover:not(:disabled) { background: var(--ink); color: #fff; }

.btn--quiet { background: transparent; border-color: var(--line-strong); color: var(--ink-muted); }
.btn--quiet:hover:not(:disabled) { border-color: var(--ink); color: var(--ink); }

.btn--block { width: 100%; }
.btn--small { padding: 6px 12px; font-size: 0.85rem; }

.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.btn.is-busy { position: relative; color: transparent; }
.btn.is-busy::after {
  content: "";
  position: absolute;
  width: 16px; height: 16px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
  color: #fff;
}
.btn--secondary.is-busy::after, .btn--quiet.is-busy::after { color: var(--ink); }

@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .btn.is-busy::after { animation-duration: 2s; }
  .item-card { transition: none; }
}

/* --------------------------------------------------------------- forms -- */

.field { margin-bottom: 20px; }
.field:last-child { margin-bottom: 0; }

.field__label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-weight: 600;
  margin-bottom: 6px;
}
.field__unit { font-weight: 400; color: var(--ink-faint); font-size: 0.85rem; }

.field__help { font-size: 0.85rem; color: var(--ink-muted); margin-top: 6px; }
.field__error { font-size: 0.85rem; color: var(--msf-red); margin-top: 6px; font-weight: 600; }
.field__error:empty { display: none; }

/* type="search" belongs here with the rest: left out, the search boxes fall
   back to the browser's own control and look nothing like the other fields. */
input[type="text"], input[type="password"], input[type="number"],
input[type="search"], select, textarea {
  width: 100%;
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  padding: 9px 12px;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--msf-red);
  outline: 2px solid var(--msf-red-tint);
  outline-offset: 0;
}
.field.is-invalid input, .field.is-invalid select { border-color: var(--msf-red); }

.field__row { display: flex; gap: 12px; align-items: center; }
.field__row input[type="range"] { flex: 1; accent-color: var(--msf-red); min-width: 0; }
.field__row input[type="number"] { width: 7.5rem; flex: none; }

.checkbox { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; }
.checkbox input { width: 18px; height: 18px; margin: 3px 0 0; accent-color: var(--msf-red); flex: none; }
.checkbox span { font-weight: 600; }

/* Collapsible control groups. */
.field-group {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  margin-bottom: 10px;
  background: var(--surface);
}
.field-group:last-of-type { margin-bottom: 0; }
.field-group[open] { border-color: var(--line-strong); }

.field-group__summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  cursor: pointer;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-muted);
  user-select: none;
  /* Hide the native disclosure triangle; a chevron is drawn below. */
  list-style: none;
}
.field-group__summary::-webkit-details-marker { display: none; }
.field-group__summary:hover { color: var(--ink); }
.field-group__summary:focus-visible { outline: 3px solid var(--msf-red); outline-offset: -3px; }

.field-group__summary::before {
  content: "";
  width: 6px;
  height: 6px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
  flex: none;
  margin: 0 2px 2px 0;
}
.field-group[open] > .field-group__summary::before { transform: rotate(45deg); }

.field-group__name { flex: 1; }

.field-group__count {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--ink-faint);
  background: var(--surface-sunken);
  border-radius: 999px;
  padding: 1px 9px;
}

.field-group__body {
  padding: 16px 14px;
  border-top: 1px solid var(--line);
}

@media (prefers-reduced-motion: reduce) {
  .field-group__summary::before { transition: none; }
}

/* -------------------------------------------------------------- notices -- */

.notice {
  border: 1px solid var(--line);
  border-left: 4px solid var(--ink-faint);
  border-radius: var(--radius);
  padding: 12px 16px;
  background: var(--surface);
  font-size: 0.92rem;
  /* Whatever follows a notice -- a toolbar of buttons, a table -- must not sit
     flush against it. Hidden notices are display:none, so they add nothing. */
  margin-bottom: 16px;
}
.notice--error { border-left-color: var(--msf-red); background: var(--msf-red-tint); color: #7a1010; }
.notice--success { border-left-color: var(--ok); background: var(--ok-tint); color: #0d4a2c; }
.notice--warn { border-left-color: var(--warn); background: var(--warn-tint); color: #6b4b00; }
.notice--info { border-left-color: var(--ink-faint); background: var(--surface-raised); }
.notice__title { font-weight: 700; display: block; margin-bottom: 3px; }
.notice ul { margin: 6px 0 0; padding-left: 20px; }
.notice[hidden] { display: none; }

/* -------------------------------------------------------- customiser -- */

.customiser {
  display: grid;
  grid-template-columns: minmax(0, 380px) minmax(0, 1fr);
  gap: var(--gap);
  align-items: start;
}
@media (max-width: 900px) {
  .customiser { grid-template-columns: minmax(0, 1fr); }
}

.customiser__panel { position: sticky; top: 20px; }
@media (max-width: 900px) { .customiser__panel { position: static; } }

.page-head { margin-bottom: 24px; }
.page-head h1 { margin-bottom: 6px; }
.page-head p { color: var(--ink-muted); max-width: 70ch; }
.attribution {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 20px;
  margin-top: 10px;
  font-size: 0.85rem;
  color: var(--ink-faint);
}
.attribution span { display: inline-flex; align-items: center; }
.attribution .icon { width: 0.9em; height: 0.9em; margin-right: 0.35em; opacity: 0.7; }

.breadcrumb { font-size: 0.88rem; margin-bottom: 10px; color: var(--ink-muted); }
.breadcrumb a { color: var(--ink-muted); }
.breadcrumb a:hover { color: var(--msf-red); }

/* --------------------------------------------------------------- viewer -- */

.viewer {
  position: relative;
  background: var(--surface-sunken);
  border-radius: var(--radius-lg);
  overflow: hidden;
  min-height: 420px;
  height: clamp(420px, 58vh, 680px);
}
.viewer--tall { height: clamp(420px, 66vh, 760px); }

.viewer-canvas { display: block; width: 100%; height: 100%; cursor: grab; touch-action: none; }
.viewer-canvas.is-grabbing { cursor: grabbing; }

.viewer__overlay {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(245, 245, 245, 0.88);
  text-align: center;
  padding: 24px;
  color: var(--ink-muted);
  pointer-events: none;
}
.viewer__overlay[hidden] { display: none; }
.viewer__overlay svg { width: 48px; height: 48px; fill: var(--line-strong); margin-bottom: 10px; }
.viewer__overlay strong { display: block; color: var(--ink); }

.viewer__spinner {
  width: 28px; height: 28px; margin: 0 auto 12px;
  border: 3px solid var(--line-strong);
  border-top-color: var(--msf-red);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

.viewer__toolbar {
  position: absolute;
  top: 12px; right: 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: stretch;
}
.viewer__toolbar-row { display: flex; gap: 6px; }

.viewer-btn {
  background: rgba(255, 255, 255, 0.94);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  color: var(--ink);
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 6px 9px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-width: 34px;
  justify-content: center;
}
.viewer-btn:hover { border-color: var(--ink); }
.viewer-btn[aria-pressed="true"] { background: var(--msf-red); border-color: var(--msf-red); color: #fff; }
.viewer-btn svg { width: 14px; height: 14px; fill: currentColor; }

.viewer__hint {
  position: absolute;
  left: 12px; bottom: 12px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 5px 10px;
  font-size: 0.75rem;
  color: var(--ink-muted);
}

.viewer__stats {
  position: absolute;
  right: 12px; bottom: 12px;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 5px 10px;
  font-size: 0.75rem;
  font-family: var(--font-mono);
  color: var(--ink-muted);
}
.viewer__stats[hidden] { display: none; }

/* --------------------------------------------------------------- editor -- */

.editor-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--gap);
  align-items: start;
}
@media (max-width: 1100px) { .editor-layout { grid-template-columns: minmax(0, 1fr); } }

.editor-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-bottom: var(--gap);
  padding: 14px 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}

.field__label--inline { margin: 0; display: inline-flex; }

/* The shared field rule sets width:100%, which in this flex row would push the
   buttons onto their own line. */
.editor-toolbar__category { flex: 0 1 220px; width: auto; min-width: 0; }

.input-with-suffix { display: flex; align-items: stretch; }
.input-with-suffix input {
  width: 16rem;
  border-radius: var(--radius) 0 0 var(--radius);
  font-family: var(--font-mono);
}
.input-suffix {
  display: flex;
  align-items: center;
  padding: 0 12px;
  border: 1px solid var(--line-strong);
  border-left: 0;
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--surface-sunken);
  color: var(--ink-muted);
  font-family: var(--font-mono);
  font-size: 0.85rem;
}
.select--compact { width: auto; padding: 6px 10px; font-size: 0.9rem; }

/* Highlighted <pre> painted directly beneath a transparent <textarea>.
   Both layers must share font, padding, border and wrapping exactly, or the
   caret drifts away from the text. */
.code-surface {
  position: relative;
  height: clamp(420px, 62vh, 780px);
  background: #fcfcfc;
  overflow: hidden;
}

/* The caret belongs to the textarea, the colours to the <pre> underneath it.
   Every property that can move a glyph sideways must therefore be identical
   in both layers, and must stay identical for every token: the textarea can
   only render one weight and one style, so the painted layer must not use a
   second one. See the .tok-* rules below. */
.code-surface__highlight,
.code-surface__input {
  margin: 0;
  padding: 16px;
  border: 0;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 400;
  font-style: normal;
  /* Whole pixels, never a ratio. 13px x 1.6 is 20.8px, and a <pre> and a
     <textarea> round that to different line-box heights; the error is a
     fifth of a pixel per line, so after a hundred lines the caret sits a
     whole line away from the text. */
  line-height: 21px;
  letter-spacing: 0;
  word-spacing: 0;
  tab-size: 4;
  white-space: pre;
  overflow-wrap: normal;
  word-break: normal;
  text-rendering: auto;
  /* Ligatures would collapse "!=" or "->" into one glyph in the painted layer
     only, putting the caret out by a character for the rest of the line. */
  font-variant-ligatures: none;
  font-feature-settings: normal;
  font-kerning: none;
  overflow: auto;
  width: 100%;
  height: 100%;
}

.code-surface__highlight {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  color: var(--ink);
}

.code-surface__input {
  position: relative;
  background: transparent;
  color: transparent;
  caret-color: var(--msf-red);
  resize: none;
}
.code-surface__input::selection { background: rgba(238, 0, 0, 0.18); }
.code-surface__input:focus { outline: 2px solid var(--msf-red); outline-offset: -2px; }

/* The default: highlighting off, plain text in the textarea itself. Nothing is
   overlaid, so the caret cannot be out of step with the text whatever the
   platform does with fonts. Colouring is opt-in via the Colour button, because
   keeping the two layers in step proved unreliable across browsers and a caret
   that lands on the wrong line makes the editor unusable. */
.code-surface--plain .code-surface__highlight { display: none; }
.code-surface--plain .code-surface__input { color: var(--ink); }
.code-surface--plain .code-surface__input::selection {
  background: rgba(238, 0, 0, 0.25);
  color: var(--ink);
}

/* Syntax colours only.
   Never add font-weight, font-style, letter-spacing or a different family
   here. The textarea on top draws the caret and the selection in a single
   uniform style, so a bold keyword or an italic comment widens the painted
   text without widening the text the caret is measured against, and the two
   drift apart by a character for every styled token on the line.
   Colours are chosen to stay distinguishable when printed in greyscale. */
.tok-comment    { color: #5c7a3f; }
.tok-annotation { color: #0a6e91; }
.tok-group      { color: #9b0097; }
.tok-keyword    { color: #b30000; }
.tok-builtin    { color: #0b4fa8; }
.tok-string     { color: #067d17; }
.tok-number     { color: #8a4b00; }
.tok-special    { color: #7a3e9d; }
.tok-operator   { color: #555; }

/* ---------------------------------------------------------- data table -- */

.data-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.data-table th, .data-table td {
  padding: 12px 16px;
  text-align: left;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.data-table th {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-faint);
  background: var(--surface-raised);
}
.data-table tr:last-child td { border-bottom: 0; }
.data-table tr:hover td { background: var(--surface-raised); }
.data-table__sub { display: block; font-size: 0.85rem; color: var(--ink-muted); margin-top: 2px; }
.data-table__sub--warn { color: var(--warn); }
.data-table__check { width: 36px; }
.data-table__check input { width: 17px; height: 17px; accent-color: var(--msf-red); }
.data-table tr[hidden] { display: none; }

.browse__search--compact { flex: 0 1 260px; }
.browse__search--compact input[type="search"] { padding-top: 7px; padding-bottom: 7px; }

.data-table__actions { white-space: nowrap; text-align: right; }
.data-table__actions .btn { margin-left: 4px; }

.btn--danger { color: var(--msf-red); border-color: var(--line-strong); }
.btn--danger:hover:not(:disabled) { background: var(--msf-red); border-color: var(--msf-red); color: #fff; }

.mb-gap { margin-bottom: var(--gap); }

kbd {
  display: inline-block;
  padding: 1px 6px;
  border: 1px solid var(--line-strong);
  border-bottom-width: 2px;
  border-radius: 4px;
  background: var(--surface-raised);
  font-size: 0.8em;
}

@media (max-width: 700px) {
  .data-table thead { display: none; }
  .data-table, .data-table tbody, .data-table tr, .data-table td { display: block; width: 100%; }
  .data-table tr { border-bottom: 1px solid var(--line); padding: 8px 0; }
  .data-table td { border: 0; padding: 4px 16px; }
  .data-table__actions { text-align: left; padding-top: 10px; }
  .data-table__actions .btn { margin: 0 4px 0 0; }
}

.console {
  margin: 0;
  padding: 12px 16px;
  height: 180px;
  overflow-y: auto;
  background: #f7f7f7;
  border-top: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 0.78rem;
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--ink-muted);
}
.console__line--error { color: var(--msf-red); font-weight: 600; }
.console__line--ok { color: var(--ok); }

.toolbar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.toolbar__spacer { flex: 1; }

/* ---------------------------------------------------------------- misc -- */

.definition-list {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 6px 16px;
  margin: 0;
  font-size: 0.9rem;
}
.definition-list dt { color: var(--ink-muted); }
.definition-list dd { margin: 0; font-weight: 600; }

.auth-layout { max-width: 420px; margin: 40px auto; }

.empty-state {
  text-align: center;
  padding: 56px 24px;
  color: var(--ink-muted);
  background: var(--surface);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-lg);
}

.error-page { text-align: center; padding: 80px 20px; }
.error-page__code { font-size: 4rem; font-weight: 700; color: var(--msf-red); line-height: 1; }

.download-panel[hidden] { display: none; }
.download-panel { display: grid; gap: 12px; }
