@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&family=Space+Grotesk:wght@400;500;600;700;800;900&display=swap");

:root {
  --font-body: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-display: "Space Grotesk", "IBM Plex Sans", sans-serif;
  --font-mono: "JetBrains Mono", Consolas, "Courier New", monospace;
  --text: #f8fafb;
  --muted: #c3ccd3;
}

body { font-family: var(--font-body); color: var(--text); line-height: 1.6; }
:is(button, input, select, textarea) { font-family: var(--font-body); }
:is(h1, h2, h3, h4, h5, h6) { font-family: var(--font-display); }
:is(code, pre, kbd, samp) { font-family: var(--font-mono) !important; }

.theme-toggle {
  position: fixed;
  z-index: 100;
  top: 15px;
  right: max(20px, calc((100vw - 1440px) / 2));
  min-width: 88px;
  min-height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 0 12px;
  border: 1px solid var(--line, #2a323b);
  border-radius: 10px;
  color: var(--text, #f2f5f7);
  background: var(--panel-raised, var(--raised, #171c22));
  box-shadow: 0 8px 24px rgb(0 0 0 / 14%);
  font: 800 11px var(--font-body);
  cursor: pointer;
}

/* Closing note appended by /site-footer.js, ported from the published site's sim/footer.js.
   The contrast notes below are carried over from there: the site's theme toggle is
   independent of the OS, so colours are tinted rather than inverted. */
.site-footer {
  margin-top: 2rem;
  padding: 1.75rem 1.5rem 2rem;
  border-top: 1px solid color-mix(in srgb, currentColor 18%, transparent);
  background: color-mix(in srgb, currentColor 5%, transparent);
  text-align: center;
}

.site-footer-inner { max-width: 32rem; margin: 0 auto; }
.site-footer h2 { margin: 0 0 .5rem; font-size: clamp(1.15rem, 2.4vw, 1.4rem); font-weight: 700; line-height: 1.25; }
.site-footer p { margin: 0 0 1.1rem; font-size: .92rem; line-height: 1.55; opacity: .85; }
.site-footer .site-footer-warm { color: var(--cyan, #69d9ec); font-weight: 600; opacity: 1; }

/* Cyan sits at about 4.4:1 on the pale background, so it is nudged darker to clear the
   4.5:1 minimum without a visible shift in hue. */
html[data-theme="light"] .site-footer .site-footer-warm { color: color-mix(in srgb, var(--cyan, #087f93) 90%, #000); }

.site-footer-cta {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  padding: .65rem 1.35rem;
  border: 2px solid currentColor;
  border-radius: .6rem;
  color: inherit;
  font-size: 1rem;
  font-weight: 700;
  text-decoration: none;
}

.site-footer-cta:hover { background: color-mix(in srgb, currentColor 15%, transparent); }
.site-footer-cta span { font-weight: 600; opacity: .7; }

/* 0.6 would blend this small text to roughly 4.3:1 on the light theme; 0.7 keeps it
   visibly secondary while clearing the minimum. */
.site-footer-note { margin: 1rem 0 0; font-size: .82rem; opacity: .7; }
.site-footer-note a { color: inherit; text-decoration: underline; text-underline-offset: .2em; }

@media (max-width: 760px) {
  .site-footer { margin-top: 1.5rem; padding: 1.5rem 1.15rem 1.75rem; }
  .site-footer-cta { width: 100%; justify-content: center; }
}

/* Dismissible "browse without Docker" note, mounted by /browse-note.js. Both the note and its
   collapsed pull tab sit in normal document flow — the fixed corners are already taken by the
   theme toggle and the Kill all button. */
.browse-note {
  width: min(var(--page-max, 1320px), calc(100% - 40px));
  margin: 18px auto 0;
  border: 1px solid color-mix(in srgb, var(--cyan, #55d9e8) 34%, var(--line, #2a323b));
  border-radius: 12px;
  background: color-mix(in srgb, var(--panel-raised, #171c22) 84%, var(--cyan, #55d9e8));
}

.browse-note-inner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px 16px;
  padding: 12px 16px;
}

.browse-note-text { flex: 1 1 320px; color: var(--text, #f2f5f7); font-size: 13px; line-height: 1.55; }
.browse-note-text strong { color: var(--cyan, #55d9e8); }

.browse-note-link {
  flex: 0 0 auto;
  padding: 7px 13px;
  border: 1px solid color-mix(in srgb, var(--cyan, #55d9e8) 45%, var(--line, #2a323b));
  border-radius: 8px;
  color: var(--cyan, #55d9e8);
  font-size: 12px;
  font-weight: 800;
  text-decoration: none;
  white-space: nowrap;
}

.browse-note-link:hover { color: var(--text, #f2f5f7); background: color-mix(in srgb, var(--cyan, #55d9e8) 16%, transparent); }

.browse-note-hide {
  flex: 0 0 auto;
  min-height: 30px;
  padding: 0 11px;
  border: 1px solid var(--line, #2a323b);
  border-radius: 8px;
  color: var(--muted, #8e99a5);
  background: transparent;
  font: 800 11px var(--font-body);
  cursor: pointer;
}

.browse-note-hide:hover { color: var(--text, #f2f5f7); border-color: var(--muted, #8e99a5); }

/* Collapsed state: a small tab tucked under the header, squared off at the top so it reads as
   something pulled down rather than a free-floating button. */
.browse-note-tab {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-left: max(20px, calc((100% - var(--page-max, 1320px)) / 2));
  padding: 5px 13px 6px;
  border: 1px solid color-mix(in srgb, var(--cyan, #55d9e8) 30%, var(--line, #2a323b));
  border-top: 0;
  border-radius: 0 0 10px 10px;
  color: var(--muted, #8e99a5);
  background: color-mix(in srgb, var(--panel-raised, #171c22) 88%, var(--cyan, #55d9e8));
  font: 800 10px var(--font-body);
  letter-spacing: .04em;
  cursor: pointer;
}

.browse-note-tab:hover { color: var(--cyan, #55d9e8); }
.browse-note-tab:focus-visible { outline: 2px solid var(--cyan, #55d9e8); outline-offset: 2px; }
.browse-note[hidden],
.browse-note-tab[hidden] { display: none !important; }

html[data-theme="light"] .browse-note { background: #eef8fa; }
html[data-theme="light"] .browse-note-tab { color: #29434d; background: #eef8fa; }
html[data-theme="light"] .browse-note-hide { color: #53636d; }

/* Global progress indicator, mounted by /progress.js wherever containers can be started.
   The bar is indeterminate on purpose: Docker reports no completion percentage, so a
   filling bar would be a made-up number. The badge carries the honest signal instead —
   what is running and how long it has been going. */
.op-progress-bar {
  position: fixed;
  z-index: 200;
  top: 0;
  right: 0;
  left: 0;
  height: 3px;
  overflow: hidden;
  background: color-mix(in srgb, var(--cyan, #55d9e8) 18%, transparent);
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s ease;
}

.op-progress-bar.visible { opacity: 1; }
.op-progress-bar i {
  position: absolute;
  inset: 0 auto 0 0;
  width: 34%;
  background: linear-gradient(90deg, transparent, var(--cyan, #55d9e8), transparent);
}
.op-progress-bar.visible i { animation: op-progress-sweep 1.15s ease-in-out infinite; }

.op-progress-badge {
  position: fixed;
  z-index: 200;
  top: 14px;
  left: 50%;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 8px 14px;
  border: 1px solid color-mix(in srgb, var(--cyan, #55d9e8) 38%, var(--line, #2a323b));
  border-radius: 999px;
  color: var(--text, #f2f5f7);
  background: var(--panel-raised, #171c22);
  box-shadow: 0 10px 30px rgb(0 0 0 / 30%);
  font: 800 11px var(--font-body);
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, -8px);
  transition: opacity .18s ease, transform .18s ease;
}

.op-progress-badge.visible { opacity: 1; transform: translate(-50%, 0); }
.op-progress-spinner {
  width: 12px;
  height: 12px;
  flex: 0 0 auto;
  border: 2px solid color-mix(in srgb, var(--cyan, #55d9e8) 30%, transparent);
  border-top-color: var(--cyan, #55d9e8);
  border-radius: 50%;
  animation: op-progress-spin .7s linear infinite;
}

@keyframes op-progress-sweep {
  0% { left: -34%; }
  100% { left: 100%; }
}

@keyframes op-progress-spin {
  to { transform: rotate(360deg); }
}

html[data-theme="light"] .op-progress-badge { color: var(--text); background: #fff; box-shadow: 0 10px 30px rgb(25 42 50 / 16%); }

@media (prefers-reduced-motion: reduce) {
  .op-progress-bar.visible i { left: 0; width: 100%; animation: none; }
  .op-progress-spinner { animation-duration: 2.4s; }
}

/* Global cleanup control, mounted by /kill-all.js on the home page and every lesson.
   Bottom-left so it never collides with the fixed theme toggle (top-right) or with any
   page's toast region (bottom-right). */
.kill-all-button {
  position: fixed;
  z-index: 100;
  bottom: 20px;
  left: 20px;
  min-height: 38px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0 14px;
  border: 1px solid color-mix(in srgb, #ff6b78 42%, var(--line, #2a323b));
  border-radius: 10px;
  color: #ffd7dc;
  background: color-mix(in srgb, var(--panel-raised, #171c22) 84%, #ff6b78);
  box-shadow: 0 8px 24px rgb(0 0 0 / 20%);
  font: 800 11px var(--font-body);
  cursor: pointer;
}

.kill-all-button:hover:not(:disabled) { border-color: #ff6b78; background: color-mix(in srgb, var(--panel-raised, #171c22) 68%, #ff6b78); }
.kill-all-button:focus-visible { outline: 2px solid #ff6b78; outline-offset: 2px; }
.kill-all-button:disabled { cursor: not-allowed; opacity: .65; }
.kill-all-dot { width: 7px; height: 7px; flex: 0 0 auto; border-radius: 50%; background: #ff6b78; }

.kill-all-toasts { position: fixed; z-index: 101; bottom: 68px; left: 20px; display: grid; gap: 8px; }
.kill-all-toast {
  max-width: 320px;
  padding: 10px 13px;
  border: 1px solid rgb(255 107 120 / 38%);
  border-radius: 9px;
  color: var(--text, #f2f5f7);
  background: var(--panel-raised, #171c22);
  box-shadow: 0 12px 32px rgb(0 0 0 / 30%);
  font-size: 12px;
  line-height: 1.5;
}
.kill-all-toast.error { border-color: rgb(255 107 120 / 60%); color: #ffd7dc; }

html[data-theme="light"] .kill-all-button { color: #8e2333; background: #fff0f2; }
html[data-theme="light"] .kill-all-button:hover:not(:disabled) { background: #ffe3e7; }
html[data-theme="light"] .kill-all-toast { color: var(--text); background: #fff; box-shadow: 0 12px 32px rgb(25 42 50 / 16%); }
html[data-theme="light"] .kill-all-toast.error { color: #8e2333; background: #fff0f2; }

.theme-toggle:hover { border-color: var(--cyan, #55d9e8); }
.theme-toggle:focus-visible { outline: 2px solid var(--cyan, #55d9e8); outline-offset: 2px; }

.topbar-inner > :last-child,
body > .topbar > :last-child:not(.topbar-inner),
body > .site-header > :last-child { margin-right: 108px; }

html[data-theme="light"] {
  color-scheme: light;
  --canvas: #f4f7f8;
  --bg: #f4f7f8;
  --panel: #ffffff;
  --panel-raised: #eef3f5;
  --raised: #eef3f5;
  --line: #cbd5da;
  --text: #10181e;
  --muted: #465761;
  --cyan: #087f93;
  --lime: #76a929;
  --lime-ink: #172205;
  --amber: #9b6a08;
  --danger: #c33d50;
  --shadow: 0 18px 48px rgb(25 42 50 / 12%);
}

html[data-theme="light"] body {
  color: var(--text);
  background:
    radial-gradient(circle at 14% 4%, rgb(8 127 147 / 9%), transparent 30rem),
    linear-gradient(rgb(23 32 39 / 3%) 1px, transparent 1px),
    linear-gradient(90deg, rgb(23 32 39 / 3%) 1px, transparent 1px),
    var(--bg);
  background-size: auto, 32px 32px, 32px 32px, auto;
}

html[data-theme="light"] :is(.topbar, .site-header) {
  border-color: var(--line);
  background: rgb(255 255 255 / 88%);
}

html[data-theme="light"] :is(
  .service-card, .instance-card, .lesson-card, .layer-card, .client-card, .proxy-card,
  .trace, .flow, .replica-pool, .replica-card, .response-cache, .empty-state,
  .service-lab-card, .scale-preview, .fleet-summary, .service-mini-card, .service-workbench, .workbench-capacity,
  lesson-client-card, lesson-service-card, lesson-proxy-card, lesson-load-balancer-card,
  lesson-api-gateway-card, lesson-service-compact, lesson-node-lite, lesson-service-lite
) {
  color: var(--text);
  background-color: #ffffff !important;
  background-image: linear-gradient(145deg, color-mix(in srgb, var(--lesson-node-accent, var(--cyan)) 7%, white), white 72%) !important;
  box-shadow: 0 15px 38px rgb(25 42 50 / 10%);
}

html[data-theme="light"] :is(
  pre, .code-block, .client-route, .url, .formula, .lb-route, .lb-details,
  .replica-summary, .cache-result, .route-buttons button, .client-tooling,
  .lesson-service-compact-heading code, .lesson-response-code, .lesson-served-by,
  .count-control, .intro code, .request-body, .instance-option
) {
  border-color: var(--line);
  color: #29434d;
  background: #f6f9fa;
}

html[data-theme="light"] .intro-copy code {
  border-color: #9abf5d;
  color: #365d05;
  background: #e8f4d0;
}

html[data-theme="light"] .count-control :is(button, input) {
  color: var(--text);
  background: transparent;
}

html[data-theme="light"] .endpoint-list {
  border-color: var(--line);
  background: #f6f9fa !important;
}

html[data-theme="light"] .response-tabs {
  border-color: var(--line);
  background: #f6f9fa;
}

html[data-theme="light"] .skeleton {
  border-color: var(--line);
  background: linear-gradient(90deg, #edf2f4 25%, #f8fafb 38%, #edf2f4 58%);
}

html[data-theme="light"] :is(.intro > p:not(.eyebrow), .intro span, .explain p, .explanation > p, .lesson-note > p, .policy-note) {
  color: #53636d;
}

html[data-theme="light"] .lesson-overview .lesson-overview-copy p {
  color: var(--text);
}

html[data-theme="light"] :is(.button, .controls button, .theme-toggle) {
  color: var(--text);
  background: var(--panel-raised);
}

html[data-theme="light"] :is(.button.primary, .controls .primary, .send, .request-button) {
  color: #172205;
  background: #a9d85c;
}

html[data-theme="light"] .button.danger {
  border-color: rgb(195 61 80 / 28%);
  color: #a32639;
  background: #fff0f2;
}

html[data-theme="light"] .lesson-number {
  border-color: color-mix(in srgb, var(--cyan) 38%, var(--line));
  color: var(--cyan);
  background: color-mix(in srgb, var(--cyan) 12%, white);
}

html[data-theme="light"] .lesson-topology {
  border-color: var(--line);
  color: #236b78;
  background: #f6f9fa;
}

html[data-theme="light"] .lesson-tags span,
html[data-theme="light"] .service-pills span,
html[data-theme="light"] :is(.preview-step, .preview-replicas span) {
  color: var(--text);
  background: var(--panel-raised);
}

html[data-theme="light"] :is(.selected-endpoint, .lesson-topology) {
  border-color: var(--line);
  color: var(--text);
  background: #f6f9fa;
}

html[data-theme="light"] .lesson-configuration-dialog {
  color: var(--text);
  background: #ffffff;
}

@media (max-width: 700px) {
  .theme-toggle { right: 12px; min-width: 40px; width: 40px; padding: 0; }
  .theme-toggle span:last-child { display: none; }
  .kill-all-button { bottom: 12px; left: 12px; padding: 0 11px; font-size: 10px; }
  .browse-note { width: calc(100% - 24px); margin-top: 12px; }
  .browse-note-inner { padding: 11px 13px; }
  .browse-note-tab { margin-left: 12px; }
  /* Full-width on small screens, so the slide-in transform is dropped for both states
     rather than overridden per state. Only opacity animates here. */
  .op-progress-badge,
  .op-progress-badge.visible { right: 12px; left: 12px; justify-content: center; text-align: center; transform: none; }
  .kill-all-toasts { right: 12px; bottom: 58px; left: 12px; }
  .kill-all-toast { max-width: none; }
  .topbar-inner > :last-child,
  body > .topbar > :last-child:not(.topbar-inner),
  body > .site-header > :last-child { margin-right: 48px; }
}
