/* Demo container: tab row + fixed-height panel body.
   Loaded conditionally from single.html when a page uses the demo shortcode.
   Uses site variables only; height per instance via --demo-height. */

.demo {
  margin: 1.6rem 0;
}

/* typography.css's generic `.content div { margin-bottom: 1.333rem }`
   outranks single-class selectors (extra element selector wins the
   specificity tie), so zero out every div inside the component and let
   demo rules opt back in. */
.demo div {
  margin-bottom: 0;
}

/* Header row: the tab row, centered over the card. */
.demo .demo-header {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 2rem;
}

/* Tab row: pill tabs matching the audio-comparison figure in the
   interaction-models post (blog-post.css .audio-comparison-tab /
   .token-timeline-control): padded pill buttons, quiet gray fill on the
   active one, and — when JS is live — one sliding indicator pill that
   glides between tabs instead of each button painting its own background. */
.demo-tabs {
  /* Sliding indicator geometry, set by demo-tabs.js. */
  --demo-tab-indicator-opacity: 0;
  --demo-tab-width: 0px;
  --demo-tab-height: 0px;
  --demo-tab-x: 0px;
  --demo-tab-y: 0px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;  /* like the reference: wrap rather than scroll on narrow screens */
  gap: 0.45rem;
  position: relative;
  isolation: isolate;
}

/* The sliding pill. Positioned in the row's content coordinates (the active
   tab's offsetLeft/offsetTop), so it scrolls with the tabs. */
.demo-tabs::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  width: var(--demo-tab-width);
  height: var(--demo-tab-height);
  border-radius: 999px;
  background: color-mix(in srgb, var(--fg) 10%, var(--bg) 90%);
  opacity: var(--demo-tab-indicator-opacity);
  transform: translate3d(var(--demo-tab-x), var(--demo-tab-y), 0);
  transition:
    transform 280ms cubic-bezier(0.22, 1, 0.36, 1),
    width 240ms cubic-bezier(0.22, 1, 0.36, 1),
    height 240ms cubic-bezier(0.22, 1, 0.36, 1),
    opacity 120ms ease;
  pointer-events: none;
}

.demo-tab {
  appearance: none;
  border: 0;
  background: transparent;
  border-radius: 999px;
  padding: 0.62rem 0.9rem;
  position: relative;
  z-index: 1;
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 400;
  line-height: 1;
  color: var(--fg);
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.16s ease, color 0.16s ease;
}

.demo-tab:hover,
.demo-tab:focus-visible {
  background: color-mix(in srgb, var(--fg) 7%, var(--bg) 93%);
}

/* Static active fill: the no-JS / pre-enhancement state. */
.demo-tab[aria-selected="true"] {
  background: color-mix(in srgb, var(--fg) 10%, var(--bg) 90%);
}

/* Once JS marks the row enhanced, the sliding indicator owns the active
   background (a static fill would double up under the glide). */
.demo-tabs.demo-tabs-enhanced .demo-tab[aria-selected="true"],
.demo-tabs.demo-tabs-enhanced .demo-tab[aria-selected="true"]:hover,
.demo-tabs.demo-tabs-enhanced .demo-tab[aria-selected="true"]:focus-visible {
  background: transparent;
}

/* Body */
.demo-body {
  position: relative;
  height: var(--demo-height, 520px);
  max-height: 70vh;
  border: 1px solid color-mix(in srgb, var(--fg4) 18%, var(--bg) 82%);
  border-radius: 12px;
  background: var(--bg);
  overflow: hidden;
}

.demo-panel {
  height: 100%;
  overflow: auto;
  box-sizing: border-box;
  scrollbar-width: none;  /* scrolling still works; bar is just hidden */
}

.demo-panel::-webkit-scrollbar {
  display: none;
}

.demo-panel[hidden] {
  display: none !important;
}

/* Panels are focusable (tabindex=0, ARIA tabs pattern) but shouldn't draw
   a focus ring on mouse/touch interaction — only for keyboard focus. */
.demo-panel:focus:not(:focus-visible) {
  outline: none;
}

/* While the visible panel is text (prompt/code), the card sizes to the
   content — no fixed height and no cap, like a native blog code block
   (whose full text is always visible). The border also drops so the filled
   pre reads exactly like one. Same :has technique as the video rule below. */
.demo .demo-body:has(> .demo-panel-text:not([hidden])) {
  height: auto;
  max-height: none;
  border-color: transparent;
}

/* Text panels: the pre fills the panel and keeps the site's code-block look
   (typography.css: --bg_code background, 13px mono, lang chip) — the card
   just provides the rounded clip, so only the standalone-block geometry
   (margins, radius, own padding scale) is neutralized. */
.demo-panel-text pre,
#main.post article.content .demo-panel-text pre {
  height: 100%;
  margin: 0;
  /* The blog's code-block padding (with-lang-chip variant: 2rem top). */
  padding: 2rem 2rem 1rem 1rem;
  border-radius: 0;
  box-sizing: border-box;
  /* Wrap long lines so prompt/code read without horizontal scrolling. */
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

/* typography.css re-pins the inner <code> to `white-space: pre`; it must
   wrap too or the pre's wrapping never takes effect. */
.demo-panel-text pre code,
#main.post article.content .demo-panel-text pre code {
  white-space: pre-wrap;
  overflow-wrap: break-word;
}

#main.post article.content .demo-panel-text .code-block-wrapper,
.demo-panel-text .code-block-wrapper {
  height: 100%;
  margin: 0;
  padding: 0;
}

#main.post article.content .demo-panel-text .code-block-wrapper > .copy-button {
  top: 0.5rem;
}

.demo-panel-text .highlight {
  height: 100%;
}

.demo-panel-text .highlight > pre {
  height: 100%;
}

/* Image panels: letterbox within the fixed height; zoom covers detail. */
.demo-panel-image {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 1rem;
}

.demo-panel-image img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  margin: 0;
}

/* Video panels: native controls handle the rest; works without JS, so no
   fallback machinery needed. */
.demo-panel-video {
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.demo-panel-video video {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  margin: 0;
}

/* While the visible panel is a video, size the card to the clip's aspect
   ratio instead of letterboxing it inside the fixed-height box. */
.demo .demo-body:has(> .demo-panel-video:not([hidden])) {
  height: auto;
}

.demo .demo-body:has(> .demo-panel-video:not([hidden])) .demo-panel-video video {
  width: 100%;
  max-height: 70vh;  /* mirror the body's usual cap */
}

/* Run panels: the iframe fills the body edge to edge. */
.demo-panel-run {
  position: relative;
  overflow: hidden;
}

.demo-panel-run iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  background: var(--bg);
}

/* Lazy frames (run + pdf) are empty shells until demo-tabs.js copies
   data-src to src; hide them until then so nothing flashes pre-mount and
   the noscript fallback isn't accompanied by a dead box. */
.demo iframe[data-src]:not([src]) {
  display: none;
}


/* PDF panels: native viewer fills the body; a small persistent link covers
   viewers that can't page embedded PDFs (e.g. iOS Safari). */
.demo-panel-pdf {
  position: relative;
  overflow: hidden;
}

.demo-panel-pdf iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

.demo-panel-pdf .demo-pdf-open {
  position: absolute;
  right: 0.75rem;
  bottom: 0.75rem;
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(4px);
  font-family: var(--font-sans);
  font-size: 0.78rem;
  color: var(--fg2);
  text-decoration: none;
  border: 1px solid color-mix(in srgb, var(--fg4) 22%, var(--bg) 78%);
}

.demo-panel-pdf .demo-pdf-open:hover {
  color: var(--fg);
  background: var(--bg);
}

.demo-run-fallback {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 1rem;
  font-family: var(--font-sans);
  font-size: 0.85rem;
  color: var(--fg4);
  text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  .demo-tab,
  .demo-tabs::before {
    transition: none;
  }
}
