/*
 * fugue-viz.css — styling for the Fugue Explorables shared infrastructure.
 *
 * Defines the semantic color algebra (blue x yellow = green) as CSS custom
 * properties, theme-switched via mdbook's <html> theme class:
 *   light family  -> html.light, html.rust
 *   dark family   -> html.coal, html.navy, html.ayu, html.dark, and ALSO the
 *                    default (no theme class), since the book default is dark.
 * The dark palette is the :root default so the absent-class case is dark.
 */

:root {
  --fv-prior: #58a6ff;
  --fv-data: #f2cc60;
  --fv-post: #56d364;
  --fv-hot: #ff7b72;
  --fv-flow: #bc8cff;
  --fv-ink: rgba(230, 237, 243, 0.9);
  --fv-grid: rgba(230, 237, 243, 0.08);
  --fv-panel: rgba(110, 118, 129, 0.08);
}

/* Light theme families */
html.light,
html.rust {
  --fv-prior: #0969da;
  --fv-data: #9a6700;
  --fv-post: #1a7f37;
  --fv-hot: #cf222e;
  --fv-flow: #8250df;
  --fv-ink: rgba(31, 35, 40, 0.9);
  --fv-grid: rgba(31, 35, 40, 0.08);
  --fv-panel: rgba(175, 184, 193, 0.12);
}

/* Explicit dark families (redundant with :root default, but future-proof) */
html.coal,
html.navy,
html.ayu,
html.dark {
  --fv-prior: #58a6ff;
  --fv-data: #f2cc60;
  --fv-post: #56d364;
  --fv-hot: #ff7b72;
  --fv-flow: #bc8cff;
  --fv-ink: rgba(230, 237, 243, 0.9);
  --fv-grid: rgba(230, 237, 243, 0.08);
  --fv-panel: rgba(110, 118, 129, 0.08);
}

/* ---- The widget panel (full-width) ---------------------------------------- */

.fugue-explorable {
  border: 1px solid var(--fv-grid);
  border-radius: 8px;
  background: var(--fv-panel);
  padding: 12px 14px;
  margin: 1.4rem 0;
  font-size: 0.8rem;
}

.fv-canvas {
  display: block;
  width: 100%;
  border-radius: 6px;
  /* Default: allow the page to scroll when a thumb swipes the canvas. Ambient
     micros keep this so they never eat scroll. A widget that owns the whole
     canvas for interaction opts into full gesture capture via .fv-touch-none
     (added automatically by FugueViz.drag with its default fullCapture). */
  touch-action: pan-y;
}

/* Belt-and-braces: any canvas inside an explorable defaults to pan-y even if a
   widget forgot the .fv-canvas class. */
.fugue-explorable canvas {
  touch-action: pan-y;
}

/* Full-capture opt-in: the whole canvas is interactive, so no gesture scrolls
   the page (FugueViz.drag adds/removes this class around a fullCapture drag). */
.fv-canvas.fv-touch-none,
.fugue-explorable canvas.fv-touch-none {
  touch-action: none;
}

/* Cursor while a FugueViz.drag grab is active (paired with an on-canvas halo). */
.fv-canvas.fv-grabbing,
.fugue-explorable canvas.fv-grabbing {
  cursor: grabbing;
}

/* ---- Controls row --------------------------------------------------------- */

.fv-controls {
  display: flex;
  flex-flow: row wrap;
  gap: 10px;
  align-items: flex-end;
  margin-bottom: 10px;
}

.fv-control {
  display: inline-flex;
  flex-direction: column;
  gap: 3px;
  font-size: 0.8rem;
}

.fv-control-label {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  opacity: 0.65;
  font-size: 0.68rem;
}

.fv-control-value {
  font-family: var(--mono-font, "Source Code Pro", monospace);
  font-variant-numeric: tabular-nums;
  opacity: 0.9;
}

/* Custom slider: hairline track, solid accent thumb with a hover halo.
   (Firefox additionally fills the elapsed side via ::-moz-range-progress.) */
.fv-range {
  -webkit-appearance: none;
  appearance: none;
  width: 140px;
  height: 26px;
  background: transparent;
  cursor: pointer;
}

.fv-range::-webkit-slider-runnable-track {
  height: 3px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--fv-ink) 18%, transparent);
}
.fv-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 14px;
  height: 14px;
  margin-top: -5.5px;
  border: none;
  border-radius: 50%;
  background: var(--fv-prior);
  transition: box-shadow 120ms ease;
}
.fv-range:hover::-webkit-slider-thumb,
.fv-range:active::-webkit-slider-thumb {
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--fv-prior) 22%, transparent);
}

.fv-range::-moz-range-track {
  height: 3px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--fv-ink) 18%, transparent);
}
.fv-range::-moz-range-progress {
  height: 3px;
  border-radius: 999px;
  background: var(--fv-prior);
}
.fv-range::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border: none;
  border-radius: 50%;
  background: var(--fv-prior);
  transition: box-shadow 120ms ease;
}
.fv-range:hover::-moz-range-thumb,
.fv-range:active::-moz-range-thumb {
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--fv-prior) 22%, transparent);
}

.fv-range:focus-visible {
  outline: 2px solid var(--fv-prior);
  outline-offset: 2px;
}

/* Toggle */
.fv-toggle {
  flex-direction: row;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}

/* Custom checkbox: hairline rounded square, filled posterior-green when
   checked (ink check on the light green of dark themes, white check on the
   dark green of light themes). */
.fv-checkbox {
  -webkit-appearance: none;
  appearance: none;
  width: 15px;
  height: 15px;
  margin: 0;
  border: 1px solid color-mix(in srgb, var(--fv-ink) 35%, transparent);
  border-radius: 4px;
  background: transparent;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}
.fv-checkbox:hover {
  border-color: var(--fv-post);
}
.fv-checkbox:checked {
  background: var(--fv-post) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 8'%3E%3Cpath d='M1 4l2.8 2.8L9 1.4' fill='none' stroke='%23081018' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 9px no-repeat;
  border-color: var(--fv-post);
}
html.light .fv-checkbox:checked,
html.rust .fv-checkbox:checked {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 8'%3E%3Cpath d='M1 4l2.8 2.8L9 1.4' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.fv-checkbox:focus-visible {
  outline: 2px solid var(--fv-post);
  outline-offset: 2px;
}

/* Buttons */
.fv-buttons {
  display: inline-flex;
  gap: 6px;
  align-items: center;
}

.fv-btn {
  font-size: 0.75rem;
  padding: 4px 10px;
  border-radius: 6px;
  border: 1px solid var(--fv-grid);
  background: transparent;
  color: var(--fv-ink);
  cursor: pointer;
  font-family: inherit;
  line-height: 1.4;
  transition: border-color 120ms ease, background-color 120ms ease;
}

.fv-btn:hover {
  border-color: var(--fv-prior);
  background-color: color-mix(in srgb, var(--fv-prior) 10%, transparent);
}

.fv-btn:focus-visible {
  outline: 2px solid var(--fv-prior);
  outline-offset: 2px;
}

.fv-btn.fv-primary {
  background: var(--fv-prior);
  border-color: var(--fv-prior);
  color: #0d1117;
  font-weight: 600;
}

html.light .fv-btn.fv-primary,
html.rust .fv-btn.fv-primary {
  color: #ffffff;
}

/* ---- Readouts row --------------------------------------------------------- */

.fv-readouts {
  display: flex;
  flex-flow: row wrap;
  gap: 16px;
  margin-top: 10px;
  align-items: baseline;
}

.fv-readout {
  display: inline-flex;
  flex-direction: column;
  gap: 1px;
}

.fv-readout-label {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  opacity: 0.65;
  font-size: 0.66rem;
}

.fv-readout-value {
  font-family: var(--mono-font, "Source Code Pro", monospace);
  font-variant-numeric: tabular-nums;
  font-size: 0.95rem;
}

/* ---- The Victor scrub number (in prose) ----------------------------------- */

.fv-scrub {
  border-bottom: 1px dashed var(--fv-prior);
  cursor: ew-resize;
  font-family: var(--mono-font, "Source Code Pro", monospace);
  font-variant-numeric: tabular-nums;
  color: var(--fv-prior);
  user-select: none;
  -webkit-user-select: none;
  padding: 0 1px;
  white-space: nowrap;
  /* A horizontal thumb-drag scrubs the number; never let it scroll the page. */
  touch-action: none;
}

.fv-scrub:focus-visible {
  outline: 2px solid var(--fv-prior);
  outline-offset: 2px;
}

.fv-scrub-active {
  color: var(--fv-hot);
  border-bottom-color: var(--fv-hot);
}

/* ---- Inline prose color classes (the color algebra in text) --------------- */

.fv-c-prior { color: var(--fv-prior); }
.fv-c-data { color: var(--fv-data); }
.fv-c-post { color: var(--fv-post); }
.fv-c-hot { color: var(--fv-hot); }
.fv-c-flow { color: var(--fv-flow); }

/* ---- The "try this" hint -------------------------------------------------- */

.fv-hint {
  font-style: italic;
  opacity: 0.7;
  font-size: 0.78rem;
  margin-top: 8px;
}

.fv-hint::before {
  content: "try: ";
  font-style: normal;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  opacity: 0.7;
  font-size: 0.66rem;
}

/* Canvas instruction line (drag/paint affordances) */
.fv-instruction {
  font-size: 0.72rem;
  opacity: 0.6;
  margin-top: 4px;
  text-align: center;
}

/* ---- Reduced motion ------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .fugue-explorable * {
    transition: none !important;
    animation: none !important;
  }
}

/* ---- The micro-widget family (docs/viz/inline.js) ------------------------- */
/* Ambient inline figures embeddable on any page. Tighter chrome than the
   full-width hero explorables; a single pause/play glyph; an optional caption. */

.fv-inline {
  position: relative; /* anchor the pause/play glyph */
  padding: 8px 10px;
  border-radius: 6px;
  margin: 1.1rem 0;
}

.fv-inline .fv-canvas {
  border-radius: 5px;
}

/* The single unobtrusive pause/play glyph, top-right of the panel. */
.fv-glyph {
  position: absolute;
  top: 6px;
  right: 8px;
  z-index: 2;
  width: 20px;
  height: 20px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  color: var(--fv-ink);
  opacity: 0.35;
  cursor: pointer;
  font-size: 0.72rem;
  line-height: 1;
  font-family: inherit;
  transition: opacity 0.15s ease;
}

.fv-glyph:hover {
  opacity: 1;
}

.fv-glyph:focus-visible {
  opacity: 1;
  outline: 2px solid var(--fv-prior);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Caption rendered under a micro-widget's canvas (data-caption). */
.fv-caption {
  font-style: italic;
  opacity: 0.7;
  font-size: 0.76rem;
  margin-top: 6px;
  line-height: 1.4;
}

/* ---- Coarse-pointer (touch) sizing bumps ---------------------------------- */
/* On touch devices grow the tap targets without changing their layout on
   mouse/trackpad. Native range inputs get a taller hit box; buttons, checkbox,
   glyph and scrub all reach the ~44px comfortable-touch neighbourhood. */
@media (pointer: coarse) {
  .fv-range {
    height: 30px;
    width: 160px;
  }
  .fv-range::-webkit-slider-thumb {
    width: 18px;
    height: 18px;
    margin-top: -7.5px;
  }
  .fv-range::-moz-range-thumb {
    width: 18px;
    height: 18px;
  }
  .fv-select {
    padding: 7px 30px 7px 12px;
  }
  .fv-btn {
    padding: 8px 14px;
    font-size: 0.8rem;
    line-height: 1.5;
  }
  .fv-checkbox {
    width: 20px;
    height: 20px;
  }
  .fv-toggle {
    gap: 8px;
  }
  /* Enlarge the scrub's tap target vertically without shifting the text. */
  .fv-scrub {
    padding: 3px 4px;
  }
  .fv-glyph {
    width: 30px;
    height: 30px;
    opacity: 0.5;
    font-size: 0.85rem;
  }
}

/* ---- Phone-width layout (~390px and the 320px floor) ---------------------- */
/* Controls and readouts already wrap (flex-wrap); here we tighten padding and
   shrink the range width so nothing overflows the panel at narrow widths. */
@media (max-width: 420px) {
  .fugue-explorable {
    padding: 10px 10px;
  }
  .fv-controls {
    gap: 8px 12px;
  }
  .fv-readouts {
    gap: 10px 14px;
  }
  .fv-range {
    width: 130px;
  }
}

@media (max-width: 340px) {
  /* Last resort at the 320px floor: let a range take the full row so it never
     pushes the panel wider than the viewport. */
  .fv-control {
    flex: 1 1 100%;
  }
  .fv-range {
    width: 100%;
    min-width: 0;
  }
}

/* ==========================================================================
   Playground (viz/playground.js) — editor, feedback, notice
   ========================================================================== */
.fv-pg-editors {
  margin-bottom: 8px;
}
.fv-pg-editor {
  display: block;
  width: 100%;
  box-sizing: border-box;
  margin-top: 8px;
  padding: 10px 12px;
  font-family: var(--mono-font, monospace);
  font-size: 0.82em;
  line-height: 1.5;
  color: var(--fg);
  background: var(--quote-bg, rgba(128, 128, 128, 0.08));
  border: 1px solid var(--fv-grid, rgba(128, 128, 128, 0.35));
  border-radius: 6px;
  resize: vertical;
}
.fv-pg-editor:focus-visible {
  outline: 2px solid var(--fv-flow, #b18bf5);
  outline-offset: 1px;
}
.fv-pg-feedback {
  margin-top: 6px;
  font-family: var(--mono-font, monospace);
  font-size: 0.75em;
  min-height: 1.2em;
}
.fv-pg-feedback.fv-pg-ok { color: var(--fv-post, #56d364); opacity: 0.8; }
.fv-pg-feedback.fv-pg-err { color: var(--fv-hot, #ff7b72); }
.fv-pg-notice {
  padding: 14px 16px;
  border: 1px dashed var(--fv-grid, rgba(128, 128, 128, 0.4));
  border-radius: 8px;
  font-size: 0.9em;
  opacity: 0.85;
}
/* Custom select: no native chrome, mid-gray chevron (legible both themes). */
.fv-select {
  -webkit-appearance: none;
  appearance: none;
  font: inherit;
  font-size: 0.85em;
  color: var(--fg);
  background-color: var(--bg);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%238b96ad' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
  background-size: 10px 6px;
  border: 1px solid color-mix(in srgb, var(--fv-ink) 25%, transparent);
  border-radius: 7px;
  padding: 4px 28px 4px 10px;
  cursor: pointer;
  transition: border-color 120ms ease;
}
.fv-select:hover {
  border-color: var(--fv-prior);
}
.fv-select:focus-visible {
  outline: 2px solid var(--fv-prior);
  outline-offset: 2px;
}
.fv-pg-badge {
  margin-top: 6px;
}
