:root {
  color-scheme: light dark;
  --bg: #0f1117;
  --fg: #e8eaed;
  --muted: #9aa0ac;
  --card-bg: #1a1d27;
  --card-border: #2a2e3a;
  --accent: #5b8cff;
  /* Verdict + severity palette (shared: env-panel state pill, .ai* messages,
     SCA report severities, ambient status node). */
  --go: #2ea043;
  --nogo: #e5484d;
  --crit: #e5484d;
  --high: #f0883e;
  --med: #d9a441;
  --low: #6b7a8d;
  --series-1: #3987e5; /* Trivy */
  --series-2: #d95926; /* Semgrep */
  --series-3: #199e70; /* Claude summary */
}

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--fg);
  font: 16px/1.5 system-ui, -apple-system, sans-serif;
}

.hero {
  text-align: center;
  margin-bottom: 0.5rem;
}

.hero h1 {
  margin: 0 0 0.4rem;
  font-size: 1.8rem;
  letter-spacing: -0.01em;
}

.subtitle {
  margin: 0;
  color: var(--muted);
}

/* Fixed bottom-right bar wrapping the tenant badge (injected/relocated into it
   by tenant.js). */
.tenant-bar {
  position: fixed;
  bottom: 12px;
  right: 12px;
  z-index: 1000;
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: 90vw;
}

.tenant-badge {
  opacity: 0.28;
  padding: 6px 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 12px/1.4 ui-monospace, monospace;
  color: var(--fg);
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 999px;
}


.demo-content {
  padding: 1rem 2rem 3rem;
  /* Flex column so a panel can flex to fill the remaining viewport height
     (see #progress-panel). The grid row stretches demo-content to >=100vh. */
  display: flex;
  flex-direction: column;
}
.demo-content .hero { text-align: left; }

/* --fill: cap the content column at the viewport and let an inner panel scroll
   (desktop only — on mobile the page scrolls normally). Shared by the demos
   whose single panel should fill the screen (workstations, ambient, database,
   ai-agent-sandbox, agentic-analytics). */
@media (min-width: 901px) {
  .demo-content--fill { height: 100vh; overflow: hidden; }
}

.panel {
  max-width: none;
  margin: 0 0 2rem;
  padding: 1.5rem;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 14px;
}

.panel__title {
  margin: 0 0 0.35rem;
  font-size: 1.15rem;
}

/* Shared utilities (used across demos). */
.is-hidden { display: none !important; }
.muted { color: var(--muted); }
.count { color: var(--muted); font-weight: 400; font-size: 0.8rem; }

/* Panel header: title on the left, controls on the right. Used by every demo's
   env panel + the SCA report sections. */
.report-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
}

/* Action-button row beside the state pill (shared by the single-VM demos). */
.vm-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.vm-quota {
  font: 0.85rem ui-monospace, monospace;
  color: var(--muted);
}

/* Env panel header: title + controls on one row, vertically centered. The panel
   only holds this single row, so trim its vertical padding (the shared .panel
   default is 1.5rem all round) to keep the provision bar compact. */
#env-panel { padding: 0.9rem 1.5rem; }
#env-panel .report-head { align-items: center; }
#env-panel .panel__title { margin: 0; }

/* The MicroVM state pill (shared across every demo's env panel; the `[data-state]`
   variants colour it by lifecycle state). Only `.vm-card__state` survives from the
   old workstation card UI — the rest of `.vm-card*` is demo-specific (dev-workstation). */
.vm-card__state {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  color: var(--muted);
  background: rgba(255, 255, 255, 0.06);
}
.vm-card__state[data-state="RUNNING"] { color: var(--go); background: rgba(46, 160, 67, 0.14); }
.vm-card__state[data-state="SUSPENDED"] { color: var(--med); background: rgba(217, 164, 65, 0.14); }
.vm-card__state[data-state="PENDING"],
.vm-card__state[data-state="SUSPENDING"],
.vm-card__state[data-state="TERMINATING"] { color: var(--accent); background: rgba(91, 140, 255, 0.14); }
.vm-card__state[data-state="ERROR"] { color: var(--nogo); background: rgba(229, 72, 77, 0.14); }

/* Match the state pill's height to the action buttons beside it. */
#env-panel .vm-card__state {
  align-self: stretch;
  display: inline-flex;
  align-items: center;
}

/* Shared editor/output chrome — authored by the REPL demo, reused by the
   database SQL console (its own styles.css only adds .db__* on top). */
.repl__toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  margin-bottom: 0.6rem;
  min-height: 2.5rem;
  flex-shrink: 0;
}
.repl__code {
  width: 100%;
  flex: 1 1 auto;
  min-height: 200px;
  resize: none;
  padding: 0.9rem;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--card-border);
  border-radius: 10px;
  font: 0.85rem/1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
  tab-size: 4;
}
.repl__code:focus { outline: none; border-color: var(--accent); }
.repl__output-title { font-size: 0.85rem; font-weight: 600; color: var(--muted); }
.repl__meta { font: 0.75rem ui-monospace, monospace; color: var(--muted); }
/* Live code-length counter overlaid in the code box's bottom-right corner. */
.repl__charcount {
  position: absolute;
  right: 0.75rem;
  bottom: 0.6rem;
  pointer-events: none;
  padding: 0.1rem 0.4rem;
  border-radius: 6px;
  background: var(--bg);
  border: 1px solid var(--card-border);
  font: 0.72rem ui-monospace, monospace;
  color: var(--muted);
  z-index: 5;
}
.repl__charcount.is-over { color: var(--danger, #f5564a); border-color: var(--danger, #f5564a); font-weight: 600; }

/* Live status appended inline after a section title, e.g.
   "Database environment (Ready · …)". Reusable across scenarios. */
.panel__title-status {
  margin-left: 0.4rem;
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--muted);
}
.panel__title-status:empty {
  margin-left: 0;
}
.panel__title-status.is-error {
  color: #ff6b6b;
}

.panel__hint {
  margin: 0 0 1.25rem;
  color: var(--muted);
  font-size: 0.9rem;
}
/* No trailing gap when the hint is the last thing in its panel. */
.panel__hint:last-child { margin-bottom: 0; }

/* Reusable information callout — an accent-tinted box with a leading icon, used
   to surface things the reader should notice (e.g. the MicroVM lifecycle). Shape:
   <div class="info-box">
     <span class="info-box__icon" aria-hidden="true">ℹ️</span>
     <div class="info-box__body">…text, may contain <strong>…</strong>…</div>
   </div> */
.info-box {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  margin: 0 0 1.25rem;
  padding: 0.75rem 0.9rem;
  background: rgba(91, 140, 255, 0.09); /* --accent at low opacity */
  border: 1px solid var(--card-border);
  border-left: 3px solid var(--accent);
  border-radius: 10px;
  color: var(--fg);
  font-size: 0.9rem;
  line-height: 1.5;
}
.info-box__icon { flex: 0 0 auto; font-size: 1.05rem; line-height: 1.45; }
.info-box__body { min-width: 0; }
.info-box__body strong { color: var(--fg); font-weight: 600; }

.panel code {
  padding: 0.1rem 0.35rem;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.07);
  font: 0.85em ui-monospace, monospace;
}

.upload {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  align-items: flex-start;
}

.dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 2rem 1rem;
  text-align: center;
  cursor: pointer;
  border: 1px dashed var(--card-border);
  border-radius: 12px;
  transition: border-color 0.12s ease, background 0.12s ease;
}

.dropzone:hover,
.dropzone.is-dragover {
  border-color: var(--accent);
  background: rgba(91, 140, 255, 0.08);
}

.dropzone.is-busy { opacity: 0.6; pointer-events: none; }

.dropzone__icon { font-size: 2rem; line-height: 1; }
.dropzone__text { color: var(--muted); font-size: 0.9rem; }
.dropzone__file { font: 0.85rem ui-monospace, monospace; color: var(--fg); }

.btn {
  display: inline-block;
  padding: 0.6rem 1.1rem;
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  color: #fff;
  text-decoration: none;
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 10px;
  cursor: pointer;
  transition: opacity 0.12s ease, transform 0.12s ease;
}

.btn:hover { transform: translateY(-1px); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none; }

.btn--secondary {
  color: var(--fg);
  background: transparent;
  border-color: var(--card-border);
}

.btn--secondary:hover { border-color: var(--accent); }

.btn--danger {
  color: #ff6b6b;
  background: transparent;
  border-color: #ff6b6b;
}

.btn--danger:hover { color: #fff; background: #e5484d; border-color: #e5484d; }

.upload__status { margin: 0; font-size: 0.85rem; color: var(--muted); }
.upload__status.is-error { color: #ff6b6b; }

.ref-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
}

@media (max-width: 560px) {
  .ref-grid { grid-template-columns: 1fr; }
}

.ref-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.5rem;
  padding: 1.25rem;
  background: var(--bg);
  border: 1px solid var(--card-border);
  border-radius: 12px;
}

.ref-card__badge {
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.ref-card__badge--bad { color: #ff6b6b; background: rgba(255, 107, 107, 0.12); }
.ref-card__badge--good { color: #4ade80; background: rgba(74, 222, 128, 0.12); }

.ref-card__title { margin: 0.25rem 0 0; font-size: 1rem; }
.ref-card__desc { margin: 0 0 0.5rem; color: var(--muted); font-size: 0.85rem; }
.ref-card__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: center;
  margin-top: auto;
}


/* --- Shared "MicroVM node" box ------------------------------------------ */
/* A Lambda-logo card that sits in the middle column between two panes, with a
   static accent arrow in each side gap. Used by the chat-rooms demo (arrows
   point inward — both panes ↔ one VM) and the REPL demo (arrows point left→right
   — code in → VM → output). Both hosts are `1fr auto 1fr` grids with this box in
   the middle. Compose an arrow from a placement (--before = left gap, --after =
   right gap) and a direction (--point-right / --point-left). */
.vm-node {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 0.25rem;
}
.vm-node__card {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.45rem;
  padding: 0.9rem 1rem;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 12px;
  box-shadow: 0 4px 18px rgb(0 0 0 / 35%);
}
.vm-node__logo { width: 46px; height: auto; display: block; }
/* Two logos side by side (e.g. the database node: Lambda + MySQL). */
.vm-node__logos { display: flex; align-items: center; gap: 0.7rem; }
.vm-node__logo--mysql { width: 54px; }
.vm-node__label { font-size: 0.8rem; font-weight: 600; white-space: nowrap; }
.vm-node__id {
  max-width: 12ch;
  overflow: hidden;
  text-overflow: ellipsis;
  font: 0.68rem ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--muted);
}
.vm-node__arrow {
  position: absolute;
  top: 50%;
  width: 2.75rem;
  height: 50px;
  transform: translateY(-50%);
  background: var(--accent);
  opacity: 0.9;
  z-index: 2;
}
.vm-node__arrow--before { right: 100%; margin-right: 0.15rem; }
.vm-node__arrow--after { left: 100%; margin-left: 0.15rem; }
.vm-node__arrow--point-right {
  clip-path: polygon(0 32%, 55% 32%, 55% 8%, 100% 50%, 55% 92%, 55% 68%, 0 68%);
}
.vm-node__arrow--point-left {
  clip-path: polygon(100% 32%, 45% 32%, 45% 8%, 0 50%, 45% 92%, 45% 68%, 100% 68%);
}
/* Panes stack vertically on narrow screens, so the horizontal arrows don't apply. */
@media (max-width: 860px) {
  .vm-node__arrow { display: none; }
}

/* --- AI Agent Sandbox: streaming chat + shortcut prompts ---------------- */
/* Once the sandbox VM is RUNNING, #ai-panel is a two-column layout: the chat
   (log + composer) on the left, a column of clickable prompt shortcuts on the
   right. The panel flex-fills the page so the log gets real height to scroll. */
.ai {
  display: grid;
  grid-template-columns: 1fr 260px;
  /* Cap the single row to the grid's own (flex-bounded) height with minmax(0,1fr).
     Without this the row auto-sizes to its tallest column — the shortcuts list —
     and the panel grows past the viewport (grid items default to min-height:auto).
     Each column then scrolls internally instead. */
  grid-template-rows: minmax(0, 1fr);
  gap: 1rem;
  flex: 1 1 auto;
  min-height: 0;
  margin-bottom: 0;
}

@media (max-width: 860px) {
  .ai { grid-template-columns: 1fr; }
}

.ai__chat {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  gap: 0.7rem;
}

.ai__log {
  flex: 1 1 auto;
  min-height: 140px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 0.9rem;
  background: var(--bg);
  border: 1px solid var(--card-border);
  border-radius: 10px;
}

.ai-msg {
  max-width: 85%;
  padding: 0.6rem 0.85rem;
  border-radius: 12px;
  font-size: 0.9rem;
  line-height: 1.55;
  white-space: pre-wrap;
  word-break: break-word;
}

.ai-msg--user {
  align-self: flex-end;
  color: #fff;
  background: var(--accent);
  border-bottom-right-radius: 4px;
}

.ai-msg--agent {
  align-self: flex-start;
  color: var(--fg);
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-bottom-left-radius: 4px;
  /* Agent replies are rendered as markdown HTML, so block spacing is handled by
     the child elements — not the preserved whitespace used by user/system bubbles. */
  white-space: normal;
}

.ai-msg--system {
  align-self: center;
  max-width: 100%;
  color: var(--muted);
  font-size: 0.82rem;
  text-align: center;
  background: transparent;
}

.ai-msg--muted { color: var(--muted); }
.ai-msg--error { color: var(--nogo); border-color: var(--nogo); }

/* Live "what the agent is doing right now" chip, streamed in between text. */
.ai-msg__tool {
  display: block;
  margin: 0.35rem 0;
  color: var(--muted);
  font-size: 0.82rem;
  font-style: italic;
}
.ai-msg__tool:first-child { margin-top: 0; }

/* Rendered markdown inside an agent reply. Scoped so it can't leak elsewhere. */
.ai-msg__text > :first-child { margin-top: 0; }
.ai-msg__text > :last-child { margin-bottom: 0; }
.ai-msg__text p { margin: 0.5rem 0; }
.ai-msg__text ul, .ai-msg__text ol { margin: 0.5rem 0; padding-left: 1.4rem; }
.ai-msg__text li { margin: 0.2rem 0; }
.ai-msg__text li > p { margin: 0; }
.ai-msg__text h1, .ai-msg__text h2, .ai-msg__text h3,
.ai-msg__text h4, .ai-msg__text h5, .ai-msg__text h6 {
  margin: 0.7rem 0 0.4rem;
  line-height: 1.3;
}
.ai-msg__text h1 { font-size: 1.15rem; }
.ai-msg__text h2 { font-size: 1.08rem; }
.ai-msg__text h3 { font-size: 1rem; }
.ai-msg__text h4, .ai-msg__text h5, .ai-msg__text h6 { font-size: 0.92rem; }
.ai-msg__text a { color: var(--accent); }
.ai-msg__text strong { font-weight: 600; }
.ai-msg__text code {
  font: 0.85em ui-monospace, SFMono-Regular, monospace;
  background: var(--bg);
  padding: 0.1rem 0.3rem;
  border-radius: 4px;
}
.ai-msg__text pre {
  margin: 0.5rem 0;
  padding: 0.7rem 0.85rem;
  background: var(--bg);
  border: 1px solid var(--card-border);
  border-radius: 8px;
  overflow-x: auto;
}
.ai-msg__text pre code { padding: 0; background: none; font-size: 0.82rem; }
.ai-msg__text blockquote {
  margin: 0.5rem 0;
  padding-left: 0.8rem;
  border-left: 3px solid var(--card-border);
  color: var(--muted);
}
.ai-msg__text table { border-collapse: collapse; margin: 0.5rem 0; font-size: 0.85rem; }
.ai-msg__text th, .ai-msg__text td { border: 1px solid var(--card-border); padding: 0.3rem 0.5rem; }
.ai-msg__text th { background: var(--bg); }

/* Blinking caret shown while the agent reply streams in. */
.ai-typing {
  display: inline-block;
  margin-left: 1px;
  color: var(--accent);
  animation: ai-blink 1s step-start infinite;
}
@keyframes ai-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .ai-typing { animation: none; } }

.ai__composer {
  display: flex;
  gap: 0.6rem;
  align-items: stretch; /* Send button matches the textarea's height */
  flex-shrink: 0;
}

/* Fixed width sized to the longest label ("Send your next prompt in N seconds…")
   so the button never resizes as its text swaps between "Send" and the countdown.
   flex: none stops the composer flex row from stretching/shrinking it; the
   textarea (flex 1 1 auto) absorbs the remaining space. Shared by the two
   .ai__composer chat demos (ai-agent-sandbox + agentic-analytics); the
   agentic-app-builder Build button gets the same treatment in its own styles.css. */
#ai-send,
#aa-send {
  flex: none;
  width: 10rem;
  /* Fixed height sized to fit the two-line countdown (2 lines @ line-height 1.3
     + the .btn vertical padding), so the composer row doesn't grow/shift when the
     label swaps between "Send" and the wrapped countdown. An explicit height on
     this flex: none item overrides the composer's align-items: stretch. */
  height: 3.5rem;
  box-sizing: border-box;
  /* Center the label; let the longer countdown wrap onto two lines inside the
     fixed width rather than overflow. */
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  line-height: 1.3;
}

/* During the post-turn cooldown the Send button is disabled but shows the live
   countdown — override the dim .btn:disabled opacity so it stays readable.
   (agentic-app-builder's #aab-build.is-cooling mirrors this in its own styles.css.) */
#ai-send.is-cooling,
#aa-send.is-cooling {
  opacity: 0.85;
}

.ai__input {
  flex: 1 1 auto;
  resize: none;
  padding: 0.7rem 0.85rem;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--card-border);
  border-radius: 10px;
  font: inherit;
  font-size: 0.9rem;
  line-height: 1.5;
}
.ai__input:focus { outline: none; border-color: var(--accent); }
.ai__input:disabled { opacity: 0.6; }

.ai__shortcuts {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  min-width: 0;
  /* Scroll the shortcut list within the capped grid row instead of letting it
     stretch the whole .ai panel past the viewport. */
  min-height: 0;
  overflow-y: auto;
}

.ai__shortcuts-title {
  margin: 0 0 0.2rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--muted);
}

/* Cooldown countdown shown above the prompt buttons while the per-turn rate-limit
   window is open (empty otherwise, so it collapses). */
.ai__shortcuts-note {
  margin: 0;
  min-height: 1em;
  font-size: 0.78rem;
  color: var(--accent);
}

.ai-shortcut {
  text-align: left;
  padding: 0.6rem 0.75rem;
  color: var(--fg);
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 10px;
  font: inherit;
  font-size: 0.82rem;
  line-height: 1.4;
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease;
}
.ai-shortcut:hover:not(:disabled) { border-color: var(--accent); background: var(--bg); }
.ai-shortcut:disabled { opacity: 0.5; cursor: default; }

/* Workstation demos (developer / data-scientist): once RUNNING, #<prefix>-panel
   embeds the workstation (code-server / JupyterLab) in one iframe via /proxy/<id>/,
   with an "open in a new tab" link in a bar above it. The panel flex-fills the page
   so the iframe gets real height to fill. */
.workstation-frame {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  /* Tighten the top padding so the "open" link bar doesn't eat screen space. */
  padding-top: 0.6rem;
}
.workstation-frame__bar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 1rem;
  flex-wrap: wrap;
}
.workstation-frame__bar .panel__hint { margin: 0; flex: 1 1 auto; min-width: 0; }
/* Small text link in the top-right corner of the frame panel (not a button). */
.workstation-frame__open {
  flex: 0 0 auto;
  white-space: nowrap;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--accent);
  text-decoration: none;
}
.workstation-frame__open:hover { text-decoration: underline; }
.workstation-frame__wrap {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 360px;
  margin-top: 0.5rem;
  overflow: hidden;
  background: #1e1e1e;
  border: 1px solid var(--card-border);
  border-radius: 12px;
}
.workstation-frame__iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

/* On the capped (≥901px) fill layout, let the workstation iframe run all the way
   to the bottom edge — drop the frame panel's bottom margin and the container's
   bottom padding. Scoped to workstation pages via :has() so the other --fill
   demos (AI sandbox, ambient inbox) keep their normal bottom spacing. The fixed
   tenant badge (position: fixed, z-index 1000) hovers over the bottom-right. */
@media (min-width: 901px) {
  .demo-content--fill:has(.workstation-frame) { padding-bottom: 0.75rem; }
  .demo-content--fill:has(.workstation-frame) .workstation-frame { margin-bottom: 0; }
}

/* --- "About this demo" help widget (help.js, every demo page) ------------ */
/* A pulsating "?" button fixed to the top-right corner; clicking it opens a
   modal explaining the scenario. Injected + wired by /help.js from a per-demo
   /demos/<slug>/help.json. */
.help-fab-wrap {
  position: fixed;
  top: 1rem;
  right: 1rem;
  z-index: 1200;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* The one help control: an accent-filled, pulsating pill. */
.help-fab__label {
  padding: 0.5rem 1rem;
  color: #fff;
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: 0 0 0 0 rgba(91, 140, 255, 0.55);
  animation: help-pulse 2.4s ease-out infinite;
  transition: transform 0.12s ease;
}
.help-fab__label:hover { transform: scale(1.05); }
.help-fab__label:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

@keyframes help-pulse {
  0% { box-shadow: 0 0 0 0 rgba(91, 140, 255, 0.55); }
  70% { box-shadow: 0 0 0 12px rgba(91, 140, 255, 0); }
  100% { box-shadow: 0 0 0 0 rgba(91, 140, 255, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .help-fab__label { animation: none; }
}

.help-overlay {
  position: fixed;
  inset: 0;
  z-index: 1300;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(6, 8, 13, 0.72);
  backdrop-filter: blur(2px);
}
.help-overlay[hidden] { display: none; }

.help-modal {
  position: relative;
  width: 100%;
  max-width: 960px;
  max-height: 85vh;
  overflow-y: auto;
  padding: 1.75rem 1.9rem;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 16px;
  box-shadow: 0 20px 60px rgb(0 0 0 / 55%);
}
.help-modal__close {
  position: absolute;
  top: 0.9rem;
  right: 1rem;
  width: 2rem;
  height: 2rem;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--muted);
  background: transparent;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
}
.help-modal__close:hover { color: var(--fg); background: rgba(255, 255, 255, 0.06); }
.help-modal__title {
  margin: 0 2rem 1.25rem 0;
  font-size: 1.4rem;
  letter-spacing: -0.01em;
}

.help-section { margin-top: 1.4rem; }
.help-section:first-child { margin-top: 0; }
.help-section__heading {
  margin: 0 0 0.5rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent);
}
.help-section__body { color: var(--fg); font-size: 0.92rem; line-height: 1.6; }
.help-section__body > :first-child { margin-top: 0; }
.help-section__body > :last-child { margin-bottom: 0; }
.help-section__body p { margin: 0 0 0.7rem; }
.help-section__body strong { color: var(--fg); font-weight: 600; }
.help-section__body code {
  padding: 0.1rem 0.35rem;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.07);
  font: 0.85em ui-monospace, monospace;
}
.help-section__diagram {
  display: block;
  width: 100%;
  height: auto;
  margin-top: 0.85rem;
  background: var(--bg);
  border: 1px solid var(--card-border);
  border-radius: 10px;
  cursor: zoom-in;
  transition: border-color 0.12s ease;
}
.help-section__diagram:hover { border-color: var(--accent); }

/* Full-screen image viewer, opened by clicking a help diagram. Sits above the
   help modal (z 1300). */
.help-lightbox {
  position: fixed;
  inset: 0;
  z-index: 1400;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2.5rem;
  background: rgba(4, 6, 10, 0.92);
  cursor: zoom-out;
}
.help-lightbox__img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 8px;
  cursor: default;
}
.help-lightbox__close {
  position: fixed;
  top: 1rem;
  right: 1.25rem;
  width: 2.6rem;
  height: 2.6rem;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  line-height: 1;
  color: #fff;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 10px;
  cursor: pointer;
}
.help-lightbox__close:hover { background: rgba(255, 255, 255, 0.18); }

/* "Cost analysis" popup table — rendered inside a .help-modal by
   /demos/_shared/cost-analysis.js. Inherits the help modal palette. */
.cost-table {
  width: 100%;
  margin-top: 1.4rem;
  border-collapse: collapse;
  font-size: 0.92rem;
}
.cost-table th,
.cost-table td {
  padding: 0.55rem 0.5rem;
  text-align: left;
  border-bottom: 1px solid var(--card-border);
}
.cost-table thead th {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--accent);
  font-weight: 600;
}
.cost-table tbody tr:last-child td { border-bottom: 0; }
.cost-table__amount {
  text-align: right;
  font-family: ui-monospace, monospace;
  color: var(--fg);
  white-space: nowrap;
}
.cost-table__note {
  margin: 1rem 0 0;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--muted);
}
.cost-table__note a { color: var(--accent); }
.cost-table__note a:hover { text-decoration: underline; }
