/* ════════════════════════════════════════════════════════════════════════
   playground.css - SHARED visual system for the interactive playgrounds
   ════════════════════════════════════════════════════════════════════════
   Loaded by BOTH:
     • /blog/node-lv-playground/  (Lotka-Volterra NODE - uses .lv-* classes)
     • /blog/kinns-playground/    (KINNs - widget scoped under #kinn-embed .ke-*)

   The two playgrounds were built from two independent CSS sets and drifted
   apart. This file is the single source of truth for the chrome they share:
   design tokens, panels, plot containers, controls, the floating FAB, and the
   prose/hero typography.

   APPROACH - shared-selector rules (NOT class migration).
   The KINNs widget is deeply em-scoped: every child size is an `em` relative
   to `#kinn-embed { font-size: clamp(13px,1.4vw,15px) }`, so renaming markup to
   shared classes would silently rescale hundreds of values. Instead this sheet
   keeps the existing `.lv-*` and `.ke-*` markup and defines the SAME rules for
   BOTH families (often via a shared selector list), so the computed values
   converge while each widget's internal em cascade stays intact.

   It is a thin convergence layer: it only sets properties that genuinely
   diverged. Each page's inline <style> still owns layout-specific geometry.
   Because this sheet loads AFTER the page <style> on both pages, its values win
   for the properties it sets (it is intentionally authoritative for those).
   ════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Accent palette ── */
  --pg-accent:        #1a73e8;  /* primary blue accent (links, play btn, focus) */
  --pg-accent-soft:   #e8f0fe;  /* tinted accent fill (hover backgrounds)       */
  --pg-purple:        #7c3aed;  /* secondary accent                              */
  --pg-danger:        #d93025;  /* running / stop red                            */
  --pg-warm:          #f0e5d6;  /* warm epoch-counter accent                     */

  /* ── Surfaces ── */
  --pg-panel-bg:      #f8f9fa;  /* card / panel background           */
  --pg-plot-bg:       #fff;     /* plot container background         */
  --pg-border:        #e8eaed;  /* hairline border on cards / panels */
  --pg-border-soft:   #dadce0;  /* slightly darker hairline          */

  /* ── Text ── */
  --pg-text:          #202124;  /* headings / strong text   */
  --pg-text-body:     #333;     /* body prose               */
  --pg-text-muted:    #5f6368;  /* labels / secondary text  */

  /* ── Dark FAB surface ── */
  --pg-fab-bg:        #222;     /* FAB bar + settings panel background */
  --pg-fab-text:      #e0e0e0;

  /* ── Geometry ── */
  --pg-radius:        8px;      /* unified card / panel / button radius */
  --pg-radius-sm:     6px;      /* small chips / inputs                 */
  --pg-radius-plot:   8px;      /* plot containers                      */

  /* ── Typography ── */
  --pg-font-sans:     'Open Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --pg-font-display:  'Inter', -apple-system, sans-serif;
  --pg-font-mono:     'Roboto Mono', monospace;
}

/* ════════════════════════════════════════════════════════════════════════
   1 · PROSE + HERO  (shared by both pages, identical markup .blog-*)
   ──────────────────────────────────────────────────────────────────────
   The two pages were already ~99% aligned here. The one real divergence was
   the prose base size (NODE 1.05em vs KINNs 1.0em) and the content-column
   max-width (NODE 820 vs KINNs 800). Unify on the KINNs values (1em base,
   800px column) and justify prose on desktop on BOTH (NODE already did; KINNs
   already did) - left-aligned on mobile to avoid ugly gaps.
   These selectors are NOT scoped to a page, so they only take effect where the
   .blog-* markup exists (the two playground pages).
   ════════════════════════════════════════════════════════════════════════ */

.blog-hero h1 {
  font-size: 1.5em;
  font-weight: 500;
  color: var(--pg-text);
  margin: 0 0 6px;
  line-height: 1.3;
  letter-spacing: -0.02em;
  font-family: var(--pg-font-display);
}
.blog-hero .blog-subtitle {
  font-size: 0.92em;
  color: var(--pg-text-muted);
  line-height: 1.55;
  font-family: var(--pg-font-sans);
}

.blog-prose {
  line-height: 1.6;
  font-size: 1em;            /* unified base (was NODE 1.05em / KINNs 1em) */
  color: var(--pg-text-body);
  font-family: var(--pg-font-sans);
}
.blog-prose p {
  font-size: 1em;
  color: var(--pg-text-body);
  margin: 0 0 16px;
  text-align: justify;       /* desktop: justified on BOTH */
}
.blog-prose h2 {
  font-size: 1.3em;
  font-weight: 600;
  color: var(--pg-text);
  margin: 32px 0 12px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--pg-border);
  font-family: var(--pg-font-display);
}
.blog-prose h3 {
  font-size: 1.1em;
  font-weight: 600;
  color: var(--pg-text);
  margin: 24px 0 10px;
  font-family: var(--pg-font-display);
}
.blog-prose a { color: var(--pg-accent); text-decoration: none; }
.blog-prose a:hover { text-decoration: underline; }
.blog-prose code {
  background: var(--pg-panel-bg);
  border: 1px solid var(--pg-border);
  border-radius: 4px;
  padding: 1px 5px;
  font-family: var(--pg-font-mono);
  font-size: 0.9em;
  color: #d93025;
}
/* Normalize KaTeX to surrounding text size on both pages */
.blog-prose .katex { font-size: 1em; }

/* Unified content column width (was NODE 820 / KINNs 800) */
#main-content.col-md-9,
.container > .row > .col-md-9 { max-width: 800px; }
@media (max-width: 999px) {
  #main-content.col-md-9, .col-md-9 { max-width: 100%; }
}

@media (max-width: 720px) {
  .blog-prose { font-size: 0.95em; }
  .blog-prose p { text-align: left; }   /* mobile: left-align on BOTH */
  .blog-hero h1 { font-size: 1.25em; }
  .blog-hero .blog-subtitle { font-size: 0.85em; }
  .blog-prose h2 { font-size: 1.15em; word-wrap: break-word; }
}

/* ════════════════════════════════════════════════════════════════════════
   2 · PANELS  (card chrome)
   ──────────────────────────────────────────────────────────────────────
   NODE .lv-panel : #f8f9fa bg, #e8eaed border, 6px radius, 9px 12px pad.
   KINNs .ke-panel: #fff bg, no border, no radius, 8px 10px pad - while the
   rest of the KINNs cards (.ke-data-setup, .ke-nn-header, .ke-layer-row, …)
   already use #f8f9fa / #e8eaed / 8px. Converge every panel onto the same
   recipe: panel-bg fill, hairline border, 8px radius. Layout-specific
   display/grid/flex stays in each page's own <style>.
   ════════════════════════════════════════════════════════════════════════ */
.lv-panel,
#kinn-embed .ke-panel {
  background: var(--pg-panel-bg);
  border: 1px solid var(--pg-border);
  border-radius: var(--pg-radius);
}
.lv-panel { padding: 9px 12px; margin-bottom: 10px; }

/* Other KINNs card surfaces - pin radius + border to the shared tokens so the
   8px family is uniform with NODE's cards. */
#kinn-embed .ke-data-setup,
#kinn-embed .ke-nn-header,
#kinn-embed .ke-nn-body,
#kinn-embed .ke-layer-row,
#kinn-embed .ke-eigen-inline,
#kinn-embed .ke-fisher-body {
  border-radius: var(--pg-radius);
  border-color: var(--pg-border);
}

/* NODE secondary cards onto the same tokens (these used 6px) */
.lv-arch-card,
.lv-eqn-box,
.lv-note,
.lv-deepdive {
  border-color: var(--pg-border);
}
.lv-note, .lv-deepdive { border-radius: var(--pg-radius); }

/* ════════════════════════════════════════════════════════════════════════
   3 · PLOT CONTAINERS
   ──────────────────────────────────────────────────────────────────────
   NODE .lv-plot: #fff bg, #e8eaed border, 6px radius. KINNs charts sit inside
   .ke-panel / .ke-center with no per-plot frame. Give the KINNs concentration
   and loss plot hosts the same framed white container so a "plot" reads the
   same on both pages, and pin NODE's to the shared tokens (8px radius).
   ════════════════════════════════════════════════════════════════════════ */
.lv-plot {
  background: var(--pg-plot-bg);
  border: 1px solid var(--pg-border);
  border-radius: var(--pg-radius-plot);
}
#kinn-embed .ke-plot-conc,
#kinn-embed .ke-plot-loss {
  background: var(--pg-plot-bg);
  border: 1px solid var(--pg-border);
  border-radius: var(--pg-radius-plot);
  padding: 4px 6px;
}

/* ════════════════════════════════════════════════════════════════════════
   4 · CONTROLS  (selects, range sliders, info "i" chips)
   ──────────────────────────────────────────────────────────────────────
   Light-context selects on both pages converge on white bg, hairline border,
   small radius, mono text. (FAB-panel dark selects are handled in §5.)
   ════════════════════════════════════════════════════════════════════════ */
#kinn-embed .ke-rxn-bar select,
#kinn-embed .ke-layer-row select {
  border-radius: var(--pg-radius-sm);
  border-color: var(--pg-border);
  font-family: var(--pg-font-mono);
}

/* Range-slider thumb - same blue, same 12px disc with white ring, on both. */
.lv-playground input[type="range"]::-webkit-slider-thumb,
#kinn-embed input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--pg-accent);
  border: 2px solid #fff;
  cursor: pointer;
}
.lv-playground input[type="range"]::-moz-range-thumb,
#kinn-embed input[type="range"]::-moz-range-thumb {
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--pg-accent);
  border: 2px solid #fff;
  cursor: pointer;
}
/* Vertical swipe scrolls the page; horizontal drag still moves the thumb. */
.lv-playground input[type="range"],
#kinn-embed input[type="range"] { touch-action: pan-y; }

/* Info "i" chip - NODE has .lv-info; KINNs has .ke-help-btn. Same disc:
   neutral fill, muted glyph, blue on hover/open. */
.lv-info,
#kinn-embed .ke-help-btn {
  background: var(--pg-border);
  color: var(--pg-text-muted);
  border-radius: 50%;
}
@media (hover: hover) {
  .lv-info:hover,
  #kinn-embed .ke-help-btn:hover { background: var(--pg-accent); color: #fff; }
}

/* ════════════════════════════════════════════════════════════════════════
   5 · THE FAB  (floating Train / Pause / Reset / gear)
   ──────────────────────────────────────────────────────────────────────
   NODE .lv-fab-* and KINNs #kinn-embed .ke-fab-* were already close. Pin the
   shared values so the bar height, padding, colors, button styles, position,
   hover behavior and touch-action are byte-for-byte the same on both:
     • dark #222 bar + panel, 12px panel radius, 280px panel
     • position bottom:20px/right:20px desktop;
       bottom: calc(24px + env(safe-area-inset-bottom)) on mobile
     • blue play button → red when running, 8px radius
     • mini-bar min-height 40px (preserves the recent KINNs fix)
     • @media (hover:hover) hovers only; touch-action: manipulation on buttons
   ════════════════════════════════════════════════════════════════════════ */

/* Wrapper position - identical anchor on both. */
.lv-fab-wrapper,
#kinn-embed .ke-fab-wrapper {
  position: fixed;
  bottom: 20px;
  right: 20px;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  pointer-events: none;
}
.lv-fab-wrapper > *,
#kinn-embed .ke-fab-wrapper > * { pointer-events: auto; }

/* Settings panel - dark, 12px radius, 280px, slides up from bottom-right. */
.lv-fab-panel,
#kinn-embed .ke-fab-panel {
  background: var(--pg-fab-bg);
  color: var(--pg-fab-text);
  border-radius: 12px;
  width: 280px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.28), 0 2px 8px rgba(0,0,0,0.15);
}

/* Mini bar - always-visible pill. min-height 40px keeps the recent KINNs fix
   and gives NODE the same bar height. */
.lv-fab-mini,
#kinn-embed .ke-fab-mini {
  background: var(--pg-fab-bg);
  color: var(--pg-fab-text);
  border-radius: 28px;
  min-height: 40px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.25), 0 2px 6px rgba(0,0,0,0.12);
}

/* Play / Train button - blue, → red running, 8px radius. */
.lv-btn-play,
#kinn-embed .ke-btn-play {
  background: var(--pg-accent);
  color: #fff;
  border-radius: var(--pg-radius);
  font-weight: 600;
  min-width: 64px;
  touch-action: manipulation;
}
.lv-btn-play.running,
#kinn-embed .ke-btn-play.running { background: var(--pg-danger); }

/* Reset / Step - translucent light on the dark bar, 8px radius. */
.lv-btn-reset,
#kinn-embed .ke-btn-reset,
#kinn-embed .ke-btn-step {
  background: rgba(255,255,255,0.12);
  color: #fff;
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: var(--pg-radius);
  font-weight: 600;
  touch-action: manipulation;
}

/* Gear toggle - 32px disc, blue + rotate when open. */
.lv-fab-gear,
#kinn-embed .ke-fab-gear {
  width: 32px; height: 32px;
  border-radius: 50%;
  border: none;
  background: rgba(255,255,255,0.1);
  color: #94a3b8;
  padding: 0;
  cursor: pointer;
  touch-action: manipulation;
}
.lv-fab-gear.open,
#kinn-embed .ke-fab-gear.open {
  background: var(--pg-accent);
  color: #fff;
  transform: rotate(60deg);
}

/* Epoch counter - warm mono on both. */
.lv-epoch,
#kinn-embed .ke-epoch-display {
  font-family: var(--pg-font-mono);
  color: var(--pg-warm);
  font-weight: 600;
}

/* Dark FAB-panel selects + range sliders - same translucent input chrome. */
.lv-fab-section select,
#kinn-embed .ke-fab-panel select {
  background: rgba(255,255,255,0.1);
  color: var(--pg-fab-text);
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: 4px;
  font-family: var(--pg-font-mono);
  cursor: pointer;
}

/* Hover behaviors only where a real pointer exists (no sticky :hover on touch). */
@media (hover: hover) {
  .lv-fab-gear:hover,
  #kinn-embed .ke-fab-gear:hover { background: rgba(255,255,255,0.18); color: var(--pg-fab-text); }
}

/* Position on mobile - identical safe-area-aware anchor on both. */
@media (max-width: 900px) {
  .lv-fab-wrapper,
  #kinn-embed .ke-fab-wrapper {
    bottom: calc(24px + env(safe-area-inset-bottom));
    right: 12px;
  }
}

@media print {
  .lv-fab-wrapper,
  #kinn-embed .ke-fab-wrapper { display: none !important; }
}
