rama 0.3.0

modular service framework
Documentation
body {
  font-family: system-ui, sans-serif;
  max-width: 42rem;
  margin: 0 auto;
  padding: 3rem 1rem 2rem;
}

.banner {
  position: fixed;
  top: 1rem;
  left: 50%;
  transform: translateX(-50%);
  padding: 0.4rem 1rem;
  background: #fff3a8;
  border: 1px solid #c9b400;
  border-radius: 999px;
  font-size: 0.9em;
  z-index: 100;
  transition: opacity 0.25s ease-out;
}

.lede { color: #555; }

.panel {
  background: #f6f7f9;
  border-radius: 8px;
  padding: 1rem;
  margin: 1rem 0;
  min-height: 4rem;
}

.spinner {
  display: flex;
  align-items: center;
  gap: 0.5em;
  color: #888;
}
.spinner .llama {
  display: inline-block;
  font-size: 1.6em;
  animation: spin 1.5s linear infinite;
}
@keyframes spin {
  from { transform: rotate(0); }
  to   { transform: rotate(360deg); }
}

.metric { font-family: monospace; font-weight: bold; }
.ok { color: #096; }

/* The spinner sits between `<?start>` and `<?end>`, so the range swap
   removes it when the fragment arrives — no CSS needed to hide it. The
   banner clears once no spinner remains. */
body:not(:has(.spinner)) .banner {
  opacity: 0;
  pointer-events: none;
}