/* SkillGraph component styles. Scoped under .skill-graph; all colors come from
   --sg-* custom properties, which the component sets at runtime from the same
   palette that drives the Cytoscape stylesheet (src/palette.js). A host page
   may override the variables after creation to re-skin the chrome. */

.skill-graph {
  position: relative;
  display: flex;
  overflow: hidden;
  background: var(--sg-surface);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  color: var(--sg-ink);
}

.skill-graph .sg-canvas {
  position: relative;
  flex: 1;
  min-width: 0;
}

/* ── side panel ─────────────────────────────────────────────────────────── */

.skill-graph .sg-panel {
  /* own stacking rung: the panel must cover the screen-centered legend node
     (z 4) while staying under the canvas buttons (10) */
  position: relative;
  z-index: 5;
  display: flex;
  flex-direction: column;
  width: 232px;
  flex: none;
  border-left: 1px solid var(--sg-hairline);
  background: var(--sg-panel);
  font-size: 12.5px;
}

.skill-graph.sg-panel-collapsed .sg-panel {
  display: none;
}

.skill-graph .sg-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  border-bottom: 1px solid var(--sg-hairline);
}

.skill-graph .sg-panel-title {
  font-weight: 600;
}

.skill-graph .sg-panel-headright {
  display: flex;
  align-items: center;
  gap: 6px;
}

.skill-graph .sg-lang {
  font: inherit;
  font-size: 11.5px;
  color: var(--sg-ink-secondary);
  background: var(--sg-surface);
  border: 1px solid var(--sg-hairline);
  border-radius: 6px;
  padding: 1px 4px;
}

.skill-graph .sg-panel-collapse {
  border: none;
  background: none;
  color: var(--sg-ink-secondary);
  font-size: 16px;
  line-height: 1;
  padding: 2px 6px;
  cursor: pointer;
  border-radius: 6px;
}

.skill-graph .sg-panel-collapse:hover {
  color: var(--sg-ink);
  background: var(--sg-hairline);
}

.skill-graph .sg-panel-body {
  flex: 1;
  overflow-y: auto;
  padding: 6px 12px 10px;
}

/* ── search ── */
.skill-graph .sg-search {
  position: relative;
  padding: 8px 12px 2px;
}

.skill-graph .sg-search input {
  width: 100%;
  box-sizing: border-box;
  font: inherit;
  font-size: 12.5px;
  color: var(--sg-ink);
  background: var(--sg-surface);
  border: 1px solid var(--sg-hairline);
  border-radius: 7px;
  padding: 4px 8px;
}

.skill-graph .sg-search input:focus-visible {
  outline: 2px solid var(--sg-accent);
  outline-offset: -1px;
}

/* FIXED, with all coordinates (and the up/down flip) set inline by
   search-box.js — the mobile bottom sheet is a scroll container that would
   clip an absolutely-positioned list opening upwards. horizontal stays
   clipped (rounds the corners). */
.skill-graph .sg-search-results {
  display: none;
  position: fixed;
  z-index: 20;
  background: var(--sg-panel);
  border: 1px solid var(--sg-hairline);
  border-radius: 8px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
  overflow: hidden auto;
}

.skill-graph .sg-search-results.sg-open {
  display: block;
}

.skill-graph .sg-search-row {
  display: flex;
  align-items: baseline;
  gap: 6px;
  width: 100%;
  border: none;
  background: none;
  color: var(--sg-ink);
  font: inherit;
  font-size: 12.5px;
  text-align: left;
  padding: 5px 10px;
  cursor: pointer;
}

.skill-graph .sg-search-row:hover {
  background: var(--sg-hairline);
}

.skill-graph .sg-search-sub {
  color: var(--sg-ink-muted);
  font-size: 11px;
}

.skill-graph .sg-search-hidden {
  margin-left: auto;
  color: var(--sg-ink-muted);
  font-size: 10px;
  font-style: italic;
}

.skill-graph .sg-search-more {
  padding: 5px 10px;
  color: var(--sg-ink-muted);
  font-size: 11px;
  font-style: italic;
  border-top: 1px solid var(--sg-hairline);
}

/* ── detail view ── */
.skill-graph .sg-detail-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 6px;
}

.skill-graph .sg-detail-kind {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--sg-ink-muted);
  border: 1px solid var(--sg-hairline);
  border-radius: 999px;
  padding: 1px 8px;
}

.skill-graph .sg-detail-close {
  border: none;
  background: none;
  color: var(--sg-ink-secondary);
  font-size: 13px;
  padding: 2px 6px;
  cursor: pointer;
  border-radius: 6px;
}

.skill-graph .sg-detail-close:hover {
  color: var(--sg-ink);
  background: var(--sg-hairline);
}

.skill-graph .sg-detail-name {
  font-size: 16px;
  font-weight: 650;
  margin: 6px 0 0;
}

.skill-graph .sg-detail-other {
  color: var(--sg-ink-secondary);
  font-size: 12.5px;
  margin-top: 1px;
}

.skill-graph .sg-detail-sub {
  color: var(--sg-ink-secondary);
  font-size: 12px;
  margin-top: 6px;
}

.skill-graph .sg-detail-stats {
  margin-top: 10px;
}

.skill-graph .sg-stat-row {
  display: flex;
  /* wide value rows (e.g. the commonness enum) wrap below their label instead
     of clipping at the panel edge — provisional until the Phase G UI rework */
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  padding: 1.5px 0;
}

.skill-graph .sg-stat-label {
  color: var(--sg-ink-secondary);
  font-size: 12px;
}

/* read-only value beside the label — the detail rows outside authoring (P4a) */
.skill-graph .sg-stat-value {
  font-size: 12px;
}

/* editable value rows (Phase F 1a): one compact button per value + unset */
.skill-graph .sg-editvals {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 2px;
}

.skill-graph .sg-val {
  min-width: 18px;
  padding: 1px 3px;
  border: 1px solid var(--sg-hairline);
  border-radius: 5px;
  background: none;
  color: var(--sg-ink-secondary);
  font: inherit;
  font-size: 10.5px;
  line-height: 1.3;
  cursor: pointer;
}

.skill-graph .sg-val:hover {
  border-color: var(--sg-ink-muted);
}

.skill-graph .sg-val.sg-val-active {
  color: var(--sg-ink);
  border-color: var(--sg-accent);
  background: color-mix(in srgb, var(--sg-accent) 12%, var(--sg-surface));
}

.skill-graph .sg-detail-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 8px;
}

.skill-graph .sg-tag {
  font-size: 10.5px;
  color: var(--sg-ink-secondary);
  border: 1px solid var(--sg-hairline);
  border-radius: 999px;
  padding: 1px 7px;
}

.skill-graph .sg-link-row {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  border: none;
  background: none;
  color: var(--sg-ink);
  font: inherit;
  font-size: 12.5px;
  text-align: left;
  padding: 2.5px 0;
  cursor: pointer;
  border-radius: 5px;
}

.skill-graph .sg-link-row:hover .sg-link-label {
  text-decoration: underline;
  text-decoration-color: var(--sg-ink-muted);
}

.skill-graph .sg-link-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.skill-graph .sg-detail-note {
  color: var(--sg-ink-muted);
  font-size: 11px;
}

.skill-graph .sg-detail-action {
  margin-top: 8px;
  padding: 4px 10px;
  flex: none;
}

.skill-graph .sg-panel-h {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 12px 0 5px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--sg-ink-muted);
}

/* `hidden` loses against the explicit display above — same trap as
   .sg-sv-form-row. The quick-edit section hides outside authoring (P4a). */
.skill-graph .sg-panel-h[hidden],
.skill-graph .sg-panel-section[hidden] {
  display: none;
}

.skill-graph .sg-bulk {
  display: flex;
  gap: 4px;
}

.skill-graph .sg-mini {
  border: 1px solid var(--sg-hairline);
  background: none;
  color: var(--sg-ink-secondary);
  font-size: 10px;
  padding: 1px 6px;
  border-radius: 999px;
  cursor: pointer;
  text-transform: none;
  letter-spacing: normal;
}

.skill-graph .sg-mini:hover {
  color: var(--sg-ink);
  border-color: var(--sg-ink-muted);
}

/* group chips */
.skill-graph .sg-chiplist {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

/* group chips blocked by sport (2026-09-12): a small caption per block */
.skill-graph .sg-chipblock + .sg-chipblock {
  margin-top: 8px;
}

.skill-graph .sg-chipblock-cap {
  font-size: 11px;
  color: var(--sg-ink-secondary);
  margin-bottom: 3px;
}

.skill-graph .sg-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: 1px solid var(--sg-hairline);
  border-radius: 999px;
  background: var(--sg-surface);
  color: var(--sg-ink);
  font-size: 11.5px;
  padding: 2px 8px 2px 5px;
  cursor: pointer;
}

.skill-graph .sg-chip:hover {
  border-color: var(--sg-ink-muted);
}

.skill-graph .sg-chip-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 1.5px solid transparent;
  flex: none;
}

.skill-graph .sg-chip-off {
  opacity: 0.55;
}

.skill-graph .sg-chip-off .sg-chip-label {
  text-decoration: line-through;
  text-decoration-color: var(--sg-ink-muted);
}

.skill-graph .sg-chip-count {
  color: var(--sg-ink-muted);
  font-size: 10px;
}

/* sticky-highlight chips (3e/3h): active = accent ring, matching the halo */
.skill-graph .sg-chip-hl-on {
  border-color: var(--sg-accent);
  background: color-mix(in srgb, var(--sg-accent) 10%, var(--sg-surface));
}

/* checkbox rows */
.skill-graph .sg-check {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 3px 0;
  cursor: pointer;
  user-select: none;
}

.skill-graph .sg-check input {
  accent-color: var(--sg-accent);
  margin: 0;
}

.skill-graph .sg-check-label {
  flex: 1;
}

/* sub-toggle indent: a row refining the toggle above it (e.g. "Hide big
   families" under Skills) — aligns with the parent row's label text */
.skill-graph .sg-check.sg-check-indent {
  margin-left: 20px;
}

/* segmented controls (layout mode; direction sits indented as a sub-control) */
.skill-graph .sg-seg {
  display: flex;
  gap: 4px;
  margin: 3px 0 2px 22px;
}

/* section-level segment (not under a checkbox) — no sub-control indent */
.skill-graph .sg-seg.sg-seg-block {
  margin-left: 0;
}

/* value / edge picker in the direction row (shares the .sg-lang select look) */
.skill-graph .sg-layout-pick {
  flex: 1;
  min-width: 0;
}

.skill-graph .sg-seg.sg-seg-off {
  opacity: 0.4;
  pointer-events: none;
}

.skill-graph .sg-seg-btn {
  flex: 1;
  border: 1px solid var(--sg-hairline);
  border-radius: 6px;
  background: var(--sg-surface);
  color: var(--sg-ink-secondary);
  font: inherit;
  font-size: 11px;
  padding: 2px 4px;
  cursor: pointer;
}

.skill-graph .sg-seg-btn:hover {
  border-color: var(--sg-ink-muted);
}

.skill-graph .sg-seg-btn.sg-seg-active {
  color: var(--sg-ink);
  border-color: var(--sg-accent);
  background: color-mix(in srgb, var(--sg-accent) 12%, var(--sg-surface));
}

/* single-arrow direction buttons: compact, not half-width each */
.skill-graph .sg-seg-btn.sg-seg-arrow {
  flex: none;
  width: 30px;
  font-size: 14px;
  line-height: 1.1;
}

/* edge-type swatches: small line samples in the edge color/style */
.skill-graph .sg-swatch {
  width: 18px;
  border-top: 2px solid var(--sg-ink-muted);
  flex: none;
}

/* P3 ramp legend: one swatch per scale step + the grey "no value" step */
.skill-graph .sg-ramp {
  display: flex;
  gap: 3px;
  margin-top: 4px;
}

.skill-graph .sg-ramp-step {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  min-width: 0;
}

.skill-graph .sg-ramp-swatch {
  width: 100%;
  height: 10px;
  border-radius: 3px;
  border: 1px solid var(--sg-hairline);
}

.skill-graph .sg-ramp-num {
  font-size: 9px;
  color: var(--sg-ink-muted);
}

.skill-graph .sg-swatch-requires { border-top-color: var(--sg-edge-requires); }
.skill-graph .sg-swatch-base-move-is { border-top-color: var(--sg-edge-base-move-is); }
.skill-graph .sg-swatch-transfers-to { border-top-style: dotted; border-top-color: var(--sg-edge-transfers-to); }
.skill-graph .sg-swatch-applicable-at { border-top-color: var(--sg-edge-applicable-at); }
.skill-graph .sg-swatch-part-of { border-top-style: dashed; border-top-color: var(--sg-edge-part-of); }

.skill-graph .sg-panel-foot {
  border-top: 1px solid var(--sg-hairline);
  padding: 8px 12px;
}

.skill-graph .sg-panel-foot .sg-check {
  padding-top: 0;
}

/* footer mode row (reveal-on-select): label above its own segmented control */
.skill-graph .sg-foot-mode {
  margin: 2px 0 6px;
}

.skill-graph .sg-foot-mode-label {
  display: block;
  padding: 3px 0 1px;
  user-select: none;
}

.skill-graph .sg-panel-stats {
  color: var(--sg-ink-secondary);
  font-size: 11.5px;
  margin-bottom: 6px;
}

.skill-graph .sg-panel-actions {
  display: flex;
  gap: 6px;
}

.skill-graph .sg-action {
  flex: 1;
  border: 1px solid var(--sg-hairline);
  border-radius: 7px;
  background: var(--sg-surface);
  color: var(--sg-ink);
  font-size: 12px;
  padding: 4px 0;
  cursor: pointer;
}

.skill-graph .sg-action:hover {
  border-color: var(--sg-ink-muted);
}

/* a disabled checkbox row (e.g. Invert while Frei) dims like the dir row */
.skill-graph .sg-check:has(input:disabled) {
  opacity: 0.45;
}

/* ── saved views (presets, spec 8c) ─────────────────────────────────────── */

/* always-visible presets strip between the swapped bodies and the footer —
   reachable while a node's detail view is open (author 2026-07-16). Heading +
   save button stay put; only the LIST scrolls, capped so exactly
   --sg-preset-visible-rows rows show — more presets overflow into the scroll
   (author 2026-07-16: the strip must not keep growing with every preset). */
.skill-graph .sg-panel-presets {
  --sg-preset-row-h: 24px;      /* fixed row height — the scroll cap derives from it */
  --sg-preset-row-gap: 4px;
  --sg-preset-visible-rows: 3;
  flex: none;
  border-top: 1px solid var(--sg-hairline);
  padding: 2px 12px 8px;
}

.skill-graph .sg-preset-list {
  max-height: calc(var(--sg-preset-visible-rows) * (var(--sg-preset-row-h) + var(--sg-preset-row-gap)));
  overflow-y: auto;
}

/* the "+" save button in the section caption: mini-button look, but wide
   enough to be an easy tap target for the most-used preset action */
.skill-graph .sg-preset-add {
  font-size: 12px;
  line-height: 1;
  padding: 1px 10px;
}

.skill-graph .sg-preset-row {
  display: flex;
  align-items: center;
  gap: 4px;
  height: var(--sg-preset-row-h); /* fixed — the list's 3-row scroll cap depends on it */
  margin-bottom: var(--sg-preset-row-gap);
}

.skill-graph .sg-preset-load {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: left;
  padding: 3px 8px;
  border: 1px solid var(--sg-hairline);
  border-radius: 6px;
  background: none;
  color: var(--sg-ink);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}

.skill-graph .sg-preset-load:hover {
  border-color: var(--sg-ink-muted);
}

.skill-graph .sg-preset-empty {
  color: var(--sg-ink-muted);
  font-size: 12px;
}

/* ── floating in-canvas buttons ─────────────────────────────────────────── */

.skill-graph .sg-btn {
  position: absolute;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--sg-hairline);
  border-radius: 8px;
  background: var(--sg-panel);
  color: var(--sg-ink-secondary);
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease;
}

.skill-graph .sg-btn:not(:disabled):hover {
  color: var(--sg-ink);
  border-color: var(--sg-ink-muted);
}

.skill-graph .sg-btn:focus-visible {
  outline: 2px solid var(--sg-accent);
  outline-offset: 1px;
}

.skill-graph .sg-btn:disabled {
  opacity: 0.4;
  cursor: default;
}

.skill-graph .sg-btn.is-active {
  color: var(--sg-accent);
  border-color: var(--sg-accent);
}

.skill-graph .sg-btn-fit {
  left: 12px;
  bottom: 12px;
}

.skill-graph .sg-btn-recenter {
  left: 52px; /* right of the 32px-wide fit button (12 + 32 + 8 gap) */
  bottom: 12px;
}

.skill-graph .sg-btn-mute {
  left: 92px; /* right of recenter (52 + 32 + 8) */
  bottom: 12px;
}

.skill-graph .sg-btn-fs {
  left: 132px; /* right of mute (92 + 32 + 8) */
  bottom: 12px;
}

/* favorited-preset quick-switch buttons: their own SECOND ROW above the fixed
   buttons (left offset set per button in JS); label = first character */
.skill-graph .sg-btn-preset {
  bottom: 56px; /* fixed row bottom (12) + button height (32) + 12 gap */
  font-size: 13px;
  font-weight: 600;
}

/* shortcut feedback HUD: transient chip naming what a key just did */
.skill-graph .sg-hud {
  position: absolute;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 20;
  padding: 4px 12px;
  border: 1px solid var(--sg-hairline);
  border-radius: 999px;
  background: var(--sg-panel);
  color: var(--sg-ink);
  font-size: 12px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 250ms ease;
}

.skill-graph .sg-hud.sg-hud-show {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .skill-graph .sg-hud { transition: none; } /* appear/vanish instantly */
  .skill-graph .sg-panel { transition: none; } /* sheet snaps between sizes */
}

/* Legend Skill Node (§11.7): a non-interactable replica node at the top of the
   FV canvas naming every shown badge field. FV-only and full-state-only — the
   embed preview has no room for it (the SVG itself is drawn in legend-node.js;
   overflow stays visible so long field names are never clipped). It is
   centered on the whole COMPONENT, so opening or collapsing the side panel
   never shifts it; z-index 4 puts it above the cytoscape canvases but below
   every piece of chrome — the panel included, which is why .sg-panel carries
   its own rung (5) below the canvas buttons (10), hud/search (20) and
   modals (30). */
.skill-graph .sg-lsn {
  position: absolute;
  top: 6px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 4;
  pointer-events: none;
  overflow: visible;
}

/* Small screens (SMALL_SCREEN_QUERY in viewport.js): the legend is nearly as
   wide as the viewport, so it clears the top-left switcher row vertically
   instead of beside it. */
@media (max-width: 640px) {
  .skill-graph .sg-lsn { top: 52px; }
}

/* the legend explains FV's node+badge language — it has no business in the
   skilltree view (author 2026-08-09) */
.skill-graph.sg-preview .sg-lsn,
.skill-graph.sg-view-tree .sg-lsn {
  display: none;
}

/* quick-edit banner (Phase F 1b): persistent while the mode is armed — sits
   below the HUD's flash position so toggle feedback never covers it */
.skill-graph .sg-editbar {
  position: absolute;
  top: 48px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 19;
  display: none;
  padding: 4px 12px;
  border: 1px solid var(--sg-accent);
  border-radius: 999px;
  background: var(--sg-panel);
  color: var(--sg-ink);
  font-size: 12px;
  pointer-events: none;
}

.skill-graph.sg-quickedit-on .sg-editbar {
  display: block;
}

/* embedded PREVIEW (Phase E display modes; look-only since 2026-09-14): every
   panel (FV side panel, SV panel — both carry .sg-panel — and the Design
   View's) and the focus buttons disappear, only ⛶ (moved to the corner)
   remains */
.skill-graph.sg-preview .sg-panel,
.skill-graph.sg-preview.sg-view-tree .sg-sv-panel, /* out-specifies the tree-view show rule */
.skill-graph.sg-preview .sg-design-panel,
.skill-graph.sg-preview .sg-btn-panel-open,
.skill-graph.sg-preview .sg-btn-fit,
.skill-graph.sg-preview .sg-btn-recenter,
.skill-graph.sg-preview .sg-btn-mute,
.skill-graph.sg-preview .sg-btn-preset {
  display: none;
}

.skill-graph.sg-preview .sg-btn-fs {
  left: 12px;
}

/* the Design View hides every canvas button in the full state (its own
   panel has the controls) — the preview still needs its way in */
.skill-graph.sg-preview.sg-view-design .sg-btn.sg-btn-fs {
  display: flex;
}

/* Preview SHIELD (ui/preview-shield.js): a transparent layer over the whole
   component while in the preview state. z-index: above every canvas and
   in-canvas overlay (wheel, hints, legend: ≤ 4… 10 is the buttons' level,
   which stay ABOVE it so ⛶ keeps working), below buttons/HUD/modals. It
   deliberately keeps the browser's default touch-action: a finger on it
   scrolls the host page. */
.skill-graph .sg-shield {
  position: absolute;
  inset: 0;
  z-index: 9;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: rgba(0, 0, 0, 0);
  transition: background 200ms ease;
}

.skill-graph.sg-preview .sg-shield {
  display: flex;
}

.skill-graph .sg-shield-text {
  max-width: 28em;
  padding: 10px 16px;
  border-radius: 999px;
  background: var(--sg-panel);
  color: var(--sg-ink);
  font-size: 14px;
  text-align: center;
  opacity: 0;
  transition: opacity 200ms ease;
  pointer-events: none;
}

.skill-graph .sg-shield.sg-shield-on {
  background: rgba(0, 0, 0, 0.45);
}

.skill-graph .sg-shield.sg-shield-on .sg-shield-text {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .skill-graph .sg-shield,
  .skill-graph .sg-shield-text { transition: none; }
}

.skill-graph .sg-btn-panel-open {
  display: none;
  right: 12px;
  top: 12px;
  font-size: 14px;
}

.skill-graph.sg-panel-collapsed .sg-btn-panel-open {
  display: flex;
}

/* ── slim hover tooltip (tippy theme "sg") ──────────────────────────────── */

.tippy-box[data-theme~='sg'] {
  background: var(--sg-panel);
  color: var(--sg-ink);
  border: 1px solid var(--sg-hairline);
  border-radius: 8px;
  font-size: 12px;
  line-height: 1.35;
  padding: 2px 4px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.14);
}

.tippy-box[data-theme~='sg'] .tippy-arrow {
  color: var(--sg-panel);
}

.tippy-box[data-theme~='sg'] .sg-tip-name {
  font-weight: 600;
}

.tippy-box[data-theme~='sg'] .sg-tip-de {
  color: var(--sg-ink-secondary);
}

.tippy-box[data-theme~='sg'] .sg-tip-dots {
  color: var(--sg-ink-muted);
  font-size: 10px;
  letter-spacing: 1px;
  margin-left: 4px;
}

/* ── app views (Skilltree stage 1) ──────────────────────────────────────────
   sg-view-tree swaps the FV chrome for the SV scaffold; SV-specific DOM comes
   from src/skilltree-view.js. The FV/SV switcher stays visible in both views
   (hidden only in the embed preview, like the other controls). */

.skill-graph .sg-viewswitch {
  position: absolute;
  z-index: 10;
  top: 12px;
  left: 12px;
  display: flex;
  border: 1px solid var(--sg-hairline);
  border-radius: 8px;
  background: var(--sg-panel);
  overflow: hidden;
}

.skill-graph .sg-viewswitch-btn {
  border: none;
  background: none;
  color: var(--sg-ink-secondary);
  font: inherit;
  font-size: 12px;
  padding: 5px 10px;
  cursor: pointer;
}

.skill-graph .sg-viewswitch-btn:hover {
  color: var(--sg-ink);
}

.skill-graph .sg-viewswitch-btn[aria-pressed='true'] {
  color: var(--sg-ink);
  background: var(--sg-hairline);
  font-weight: 600;
}

.skill-graph .sg-viewswitch-btn:focus-visible {
  outline: 2px solid var(--sg-accent);
  outline-offset: -2px;
}

.skill-graph.sg-preview .sg-viewswitch {
  display: none;
}

/* SV stage + panel exist in the DOM always, shown only in the tree view */
.skill-graph .sg-sv,
.skill-graph .sg-sv-panel {
  display: none;
}

/* Activation invite (§11.3 / N5): the bar that asks for the first root
   charge. It sits above the canvas buttons and never takes pointer events —
   the gesture it describes happens on the canvas behind it. */
/* Hint card (B3, 2026-08-20 — generalizes the old activation invite): a tiny
   text card beside a target node, optionally with an arrow toward it. The
   root sits AT the anchor point; the per-side transform shifts the card off
   the node, the inner .sg-sv-hint-jump carries the motion. */
.skill-graph .sg-sv-hint {
  position: absolute;
  z-index: 10;
  pointer-events: none;
  /* it FADES in (author 2026-08-09) — the class arrives one frame after the
     element is unhidden */
  opacity: 0;
  transition: opacity 260ms ease;
}

.skill-graph .sg-sv-hint[data-side='top'] { transform: translate(-50%, -100%); }
.skill-graph .sg-sv-hint[data-side='bottom'] { transform: translate(-50%, 0); }
.skill-graph .sg-sv-hint[data-side='left'] { transform: translate(-100%, -50%); }
.skill-graph .sg-sv-hint[data-side='right'] { transform: translate(0, -50%); }

.skill-graph .sg-sv-hint-in {
  opacity: 1;
}

.skill-graph .sg-sv-hint[hidden] {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .skill-graph .sg-sv-hint { transition: none; }
}

.skill-graph .sg-sv-hint-jump {
  display: flex;
  align-items: center;
}

.skill-graph .sg-sv-hint[data-side='top'] .sg-sv-hint-jump { flex-direction: column; }
.skill-graph .sg-sv-hint[data-side='bottom'] .sg-sv-hint-jump { flex-direction: column-reverse; }
.skill-graph .sg-sv-hint[data-side='left'] .sg-sv-hint-jump { flex-direction: row; }
.skill-graph .sg-sv-hint[data-side='right'] .sg-sv-hint-jump { flex-direction: row-reverse; }

.skill-graph .sg-sv-hint-card {
  max-width: min(70vw, 460px);
  white-space: nowrap;
  text-align: center;
  padding: 7px 14px;
  border: 1px solid var(--sg-hairline);
  border-radius: 999px;
  background: var(--sg-panel);
  color: var(--sg-ink-secondary);
  font-size: 12.5px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.14);
}

/* the arrow toward the target: a plain border triangle on the node-facing
   side of the card (default ON, author 2026-08-20) */
.skill-graph .sg-sv-hint-arrow {
  width: 0;
  height: 0;
  border: 6px solid transparent;
}

.skill-graph .sg-sv-hint[data-side='top'] .sg-sv-hint-arrow {
  border-top-color: var(--sg-hairline);
  border-bottom-width: 0;
}

.skill-graph .sg-sv-hint[data-side='bottom'] .sg-sv-hint-arrow {
  border-bottom-color: var(--sg-hairline);
  border-top-width: 0;
}

.skill-graph .sg-sv-hint[data-side='left'] .sg-sv-hint-arrow {
  border-left-color: var(--sg-hairline);
  border-right-width: 0;
}

.skill-graph .sg-sv-hint[data-side='right'] .sg-sv-hint-arrow {
  border-right-color: var(--sg-hairline);
  border-left-width: 0;
}

/* The two motions (author 2026-08-20: default = bounce, both built for the
   Design View eyeball). Bounce = a ball on the floor: NO squash or stretch,
   leaves the ground fast, hangs at the top. Eased = one smooth up-down.
   Reduced motion never adds the classes; the guard below is a second belt
   for the OS preference. Height/duration ride in on CSS vars. */
@keyframes sg-sv-hint-bounce {
  0%   { transform: translateY(0); animation-timing-function: ease-out; }
  50%  { transform: translateY(calc(-1 * var(--sg-hint-jump, 16px))); animation-timing-function: ease-in; }
  100% { transform: translateY(0); }
}

@keyframes sg-sv-hint-eased {
  0%   { transform: translateY(0); animation-timing-function: ease-in-out; }
  50%  { transform: translateY(calc(-1 * var(--sg-hint-jump, 16px))); animation-timing-function: ease-in-out; }
  100% { transform: translateY(0); }
}

.skill-graph .sg-sv-hint-bounce {
  animation: sg-sv-hint-bounce var(--sg-hint-period, 1200ms) infinite;
}

.skill-graph .sg-sv-hint-eased {
  animation: sg-sv-hint-eased var(--sg-hint-period, 1200ms) infinite;
}

@media (prefers-reduced-motion: reduce) {
  .skill-graph .sg-sv-hint-jump { animation: none; }
}

/* the view switch is gone INSIDE a skilltree (author 2026-08-09): SV leaves
   through the root donut's switcher list and its manage modal (B1) —
   EXCEPT in authoring (author 2026-08-22), where it returns top-left */
.skill-graph.sg-view-tree .sg-viewswitch {
  display: none;
}

.skill-graph.sg-view-tree.sg-authoring-on .sg-viewswitch {
  display: flex;
}

.skill-graph.sg-view-tree .sg-sv {
  display: block;
  flex: 1;
  min-width: 0;
}

/* placed after the sg-panel-collapsed rule on purpose: a collapsed FV panel
   must never hide the SV panel (equal specificity — order decides) */
.skill-graph.sg-view-tree .sg-sv-panel {
  display: flex;
}

/* SV panel collapse (§10.1 Phase 3 A1): its OWN toggle, deliberately
   decoupled from the FV `sg-panel-collapsed`. Must follow the rule above —
   equal specificity, order decides. Collapsed state is never persisted. */
.skill-graph.sg-view-tree.sg-sv-collapsed .sg-sv-panel {
  display: none;
}

/* SV's fullscreen button. On-canvas buttons live BOTTOM-LEFT in both views
   (author 2026-08-02); the ☰ panel-opener is gone (author 2026-08-22 —
   authoring keeps the panel open instead, end users use the root's details
   donut). The selector must out-specify the "FV chrome off in tree view"
   rule that hides every .sg-btn there. */
.skill-graph.sg-view-tree .sg-btn.sg-btn-sv-fs {
  display: flex;
  left: 12px;
  bottom: 12px;
}

.skill-graph .sg-btn.sg-btn-sv-fs[hidden] {
  display: none;
}

/* authoring ⇒ the panel is open (author 2026-08-22): both views' ✕ would be
   a dead control (setCollapsed refuses every close), so it hides */
.skill-graph.sg-authoring-on .sg-panel-collapse {
  display: none;
}

/* Portrait phones (SMALL_SCREEN_QUERY in viewport.js): EVERY side panel
   becomes a bottom sheet (author 2026-08-09 — the general rule, not just the
   SV details panel). Absolute, so the stage keeps the full width behind it,
   and above the canvas buttons: the sheet covers the fullscreen button, not
   the other way round.
   Three pull sizes — bottom-sheet.js owns both the class and the pixel
   height (big ≈ 2/3 · medium ≈ 2/5 of the viewport · small = head + search). */
@media (max-width: 640px) {
  .skill-graph .sg-panel {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    top: auto;
    width: auto;
    border-left: none;
    border-top: 1px solid var(--sg-hairline);
    z-index: 11; /* over the canvas buttons (10) */
  }

  /* the head is the pull handle — never let a drag select its text */
  .skill-graph .sg-panel-head {
    touch-action: none;
    user-select: none;
  }

  /* ONE scroll container: the presets strip and the footer are pinned in the
     desktop side panel, but in a sheet they would eat most of its height —
     here they scroll with the content (author 2026-08-09). Only the head and
     whatever sits above the body stay put. */
  .skill-graph .sg-panel {
    overflow-y: auto;
    /* keep boundary drags with the sheet: without this the browser may claim
       an at-the-edge drag for overscroll/chaining and cancel the pull */
    overscroll-behavior: contain;
  }

  .skill-graph .sg-panel-body {
    flex: none;
    overflow: visible;
  }

  .skill-graph .sg-panel-head,
  .skill-graph .sg-panel > .sg-search {
    position: sticky;
    z-index: 2;
    background: var(--sg-panel);
  }

  .skill-graph .sg-panel-head { top: 0; }
  /* the search box sticks directly under the head — HEAD height only, or it
     would be pushed down by its own height as well */
  .skill-graph .sg-panel > .sg-search { top: var(--sg-sheet-head-h, 0); }

  /* the exact height is set inline by bottom-sheet.js — the size cap AND the
     content decide it, so every change (pull or content) eases the same way */
  .skill-graph .sg-panel {
    transition: height 220ms ease-out;
  }


}

/* SV context wheel (§10.1 Phase 4): DOM buttons placed on a circle around the
   tapped node, inside the stage so they scroll/pan away with it. */
.skill-graph .sg-sv-wheel {
  position: absolute;
  inset: 0;
  /* above the cytoscape canvases (they paint later in the DOM) */
  z-index: 4;
  pointer-events: none;
}

/* the ring itself: one svg per open wheel, absolutely placed on the node */
.skill-graph .sg-sv-wheel-ring {
  position: absolute;
  overflow: visible;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.22));
}

.skill-graph .sg-sv-wheel-seg {
  pointer-events: auto;
  cursor: pointer;
  color: var(--sg-ink);
}

.skill-graph .sg-sv-wheel-seg > path {
  fill: var(--sg-panel);
  /* see-through enough that the node's own label stays legible underneath,
     opaque enough that the icons read cleanly on top (author 2026-08-02) */
  fill-opacity: 0.62;
  /* the segment boundary must be clearly visible — never faint */
  stroke: var(--sg-ink-secondary);
  stroke-width: 1.25;
}

.skill-graph .sg-sv-wheel-seg:hover > path {
  fill: var(--sg-accent);
  fill-opacity: 0.3;
  stroke: var(--sg-accent);
}

.skill-graph .sg-sv-wheel-seg:hover {
  color: var(--sg-accent);
}

.skill-graph .sg-sv-wheel-seg-off {
  cursor: default;
  color: var(--sg-ink-muted);
}

.skill-graph .sg-sv-wheel-seg-off > path {
  fill-opacity: 0.35;
}

.skill-graph .sg-sv-wheel-seg-off:hover > path {
  fill: var(--sg-panel);
  fill-opacity: 0.35;
  stroke: var(--sg-ink-secondary);
}

.skill-graph .sg-sv-wheel-seg-off:hover {
  color: var(--sg-ink-muted);
}

/* Button list beside a node (B1, 2026-08-20): the skilltree switcher today,
   the learned-enum picker later. Equal-width buttons: the grid stretches
   every button to the widest label. */
.skill-graph .sg-sv-buttonlist {
  position: absolute;
  z-index: 4; /* above the cytoscape canvases, like the wheel */
  display: grid;
  grid-auto-rows: min-content;
  gap: 4px;
  /* a long list scrolls instead of outgrowing the screen (the JS caps
     max-height to the stage and clamps the top) */
  overflow-y: auto;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.22));
}

.skill-graph .sg-sv-buttonlist[hidden] {
  display: none;
}

.skill-graph .sg-sv-buttonlist-btn {
  appearance: none;
  cursor: pointer;
  text-align: left;
  white-space: nowrap;
  padding: 7px 14px;
  border: 1px solid var(--sg-ink-secondary);
  border-radius: 8px;
  background: var(--sg-panel);
  color: var(--sg-ink);
  font: inherit;
  font-size: 13px;
}

.skill-graph .sg-sv-buttonlist-btn:hover {
  border-color: var(--sg-accent);
  color: var(--sg-accent);
}

/* the current choice (the active skilltree) */
.skill-graph .sg-sv-buttonlist-active {
  border-color: var(--sg-accent);
  box-shadow: inset 3px 0 0 var(--sg-accent);
  font-weight: 600;
}

/* the visually set-off trailing action ("Verwalten…") */
.skill-graph .sg-sv-buttonlist-distinct {
  margin-top: 6px;
  border-style: dashed;
  color: var(--sg-ink-secondary);
}

/* SV placeholder modal (mocap wheel action) */
.skill-graph .sg-sv-modal {
  position: absolute;
  inset: 0;
  /* above ALL chrome (buttons 10, hud/search 20): while the modal is open the
     canvas buttons must be dimmed and inert — a click on them hits the
     backdrop and closes it (author 2026-08-02) */
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.45);
}

.skill-graph .sg-sv-modal[hidden] {
  display: none;
}

/* A SMALL modal: one short decision, not a form. Narrower than the default on
   purpose — these open ON TOP of a full-size modal (the language picker over
   the edit form), and matching widths would read as the same surface. */
.skill-graph .sg-sv-modal-small .sg-sv-modal-card {
  width: min(360px, 82%);
}

.skill-graph .sg-sv-modal-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(560px, 86%);
  max-height: 82%;
  padding: 12px;
  background: var(--sg-panel);
  border: 1px solid var(--sg-hairline);
  border-radius: 10px;
}

.skill-graph .sg-sv-modal-head {
  display: flex;
  align-items: center;
  gap: 8px;
}

.skill-graph .sg-sv-modal-title {
  font-weight: 600;
}

/* the shared look of every button in a modal head */
.skill-graph .sg-sv-modal-headbtn,
.skill-graph .sg-sv-modal-close {
  font: inherit;
  color: var(--sg-ink);
  background: none;
  border: none;
  cursor: pointer;
}

/* …but ONLY the ✕ is pushed to the far right. Head buttons sit directly after
   the title, because they belong to it — which is also why they must not
   borrow the ✕'s class for their styling (author 2026-08-20). */
.skill-graph .sg-sv-modal-close {
  margin-left: auto;
}

.skill-graph .sg-sv-modal-frame {
  width: 100%;
  height: 260px;
  background: var(--sg-surface);
  border: 1px dashed var(--sg-hairline);
  border-radius: 8px;
}

.skill-graph .sg-sv-confirm .sg-sv-modal-card {
  width: min(360px, 82%);
  gap: 14px;
}

.skill-graph .sg-sv-confirm-actions {
  display: flex;
  gap: 8px;
}

.skill-graph .sg-sv-confirm-actions .sg-sv-export {
  margin-top: 0;
}

.skill-graph .sg-sv-confirm-ok,
.skill-graph .sg-sv-create-ok {
  border-color: var(--sg-accent);
  color: var(--sg-accent);
}

.skill-graph .sg-sv-modal-note {
  color: var(--sg-ink-secondary);
  font-size: 12px;
}

/* create-skill modal (node authoring 2026-08-03) */
.skill-graph .sg-sv-create .sg-sv-modal-card {
  overflow-y: auto;
}

.skill-graph .sg-sv-form {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.skill-graph .sg-sv-form-row {
  display: grid;
  grid-template-columns: 140px 1fr;
  align-items: center;
  gap: 8px;
  font-size: 13px;
}

.skill-graph .sg-sv-form-row-top {
  align-items: start;
}

/* the row's own display:grid would override the hidden attribute — the same
   trap as .sg-sv-form-link below. Language rows are hidden this way whenever
   the author excludes a language from the form. */
.skill-graph .sg-sv-form-row[hidden] {
  display: none;
}

.skill-graph .sg-sv-form-label {
  color: var(--sg-ink-secondary);
}

.skill-graph .sg-sv-form input[type="text"],
.skill-graph .sg-sv-form select {
  font: inherit;
  font-size: 13px;
  color: var(--sg-ink);
  background: var(--sg-surface);
  border: 1px solid var(--sg-hairline);
  border-radius: 6px;
  padding: 4px 6px;
  min-width: 0;
}

.skill-graph .sg-sv-form input[type="text"]:focus-visible,
.skill-graph .sg-sv-form select:focus-visible {
  outline: none;
  border-color: var(--sg-accent);
}

.skill-graph .sg-sv-form-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 12px;
}

/* the id row: a fixed `<folder>:` prefix owned by the folder dropdown (D2) */
.skill-graph .sg-sv-form-idwrap {
  display: flex;
  align-items: center;
  gap: 4px;
  min-width: 0;
}

.skill-graph .sg-sv-form-idwrap .sg-sv-form-id {
  flex: 1 1 auto;
}

.skill-graph .sg-sv-form-idprefix {
  color: var(--sg-ink-secondary);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  white-space: nowrap;
}

/* the secondary groups: one collapsible block per sport / collection (7c) */
.skill-graph .sg-sv-form-groupblocks {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.skill-graph .sg-sv-form-groupblock {
  border: 1px solid var(--sg-hairline);
  border-radius: 6px;
  padding: 2px 6px;
  margin-bottom: 4px;
  width: 100%;
}

.skill-graph .sg-sv-form-groupblock-head {
  cursor: pointer;
  display: flex;
  gap: 8px;
  align-items: baseline;
  padding: 2px 0;
  color: var(--sg-ink-secondary);
  user-select: none;
}

.skill-graph .sg-sv-form-groupblock[open] > .sg-sv-form-groupblock-head {
  color: var(--sg-ink);
  margin-bottom: 2px;
}

.skill-graph .sg-sv-form-groupblock-count:not(:empty) {
  font-size: 11px;
  padding: 0 6px;
  border-radius: 8px;
  background: var(--sg-accent);
  color: var(--sg-surface);
}

.skill-graph .sg-sv-form-link {
  margin: 2px 0;
}

/* .sg-check's display:flex would override the hidden attribute — without
   this the checkbox showed with no label when no source was armed */
.skill-graph .sg-sv-form-link[hidden] {
  display: none;
}

/* color editor (D25, P3): hex text + the system-picker swatch beside it */
.skill-graph .sg-colorinput {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.skill-graph .sg-colorinput-hex {
  width: 7.5em;
}
.skill-graph .sg-colorinput-invalid .sg-colorinput-hex {
  border-color: #d33;
  outline-color: #d33;
}
.skill-graph .sg-colorinput-pick {
  width: 34px;
  height: 26px;
  padding: 2px;
  border: 1px solid var(--sg-hairline);
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
}

/* list-field editors (P1.3/P1.4, 2026-08-20): a wrapping chip row over an add
   field. The tag picker adds a Manage toggle that swaps each chip's toggle for
   rename/delete — the vocabulary-wide edits are deliberately behind that
   switch, so the frequent action (picking) stays a single click. */
.skill-graph .sg-chipinput {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.skill-graph .sg-chipinput-list {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.skill-graph .sg-chipinput-list:empty {
  display: none;
}

.skill-graph .sg-taginput-row {
  display: flex;
  gap: 6px;
  align-items: center;
}

.skill-graph .sg-taginput-row .sg-chipinput-add {
  flex: 1 1 auto;
}

.skill-graph .sg-chip-val {
  padding: 2px 4px 2px 8px;
  cursor: default;
}

/* in picking mode the whole chip is the button, so the count and the padding
   are click targets too (author 2026-08-20) */
.skill-graph .sg-chip-toggle {
  font: inherit;
  cursor: pointer;
}

.skill-graph .sg-chip-x,
.skill-graph .sg-chip-act {
  font: inherit;
  font-size: 12px;
  line-height: 1;
  color: var(--sg-ink-muted);
  background: none;
  border: none;
  padding: 0 2px;
  cursor: pointer;
}

.skill-graph .sg-chip-x:hover,
.skill-graph .sg-chip-act:hover {
  color: var(--sg-ink);
}

/* MANAGE mode is a deliberate, destructive mode — its chips carry full-contrast
   text and fully legible action glyphs, not the muted picking-mode styling
   (author 2026-08-20: the ✎/× were barely visible). The off-state strike-out
   still marks which tags this node does not carry. */
.skill-graph .sg-taginput-managing .sg-chip-val,
.skill-graph .sg-taginput-managing .sg-chip-label {
  color: var(--sg-ink);
}

.skill-graph .sg-taginput-managing .sg-chip-val {
  opacity: 1;
}

.skill-graph .sg-taginput-managing .sg-chip-x,
.skill-graph .sg-taginput-managing .sg-chip-act {
  color: var(--sg-ink);
  font-size: 13px;
  padding: 0 3px;
}

/* the row NAME reverts that row to its value when the modal opened — only in
   EDIT mode, so it only looks clickable there */
.skill-graph .sg-sv-form-resettable .sg-sv-form-label-reset {
  cursor: pointer;
}

.skill-graph .sg-sv-form-resettable .sg-sv-form-label-reset:hover {
  color: var(--sg-ink);
  text-decoration: underline;
}

/* data-language picker (2026-08-20) */
.skill-graph .sg-sv-langs-note {
  color: var(--sg-ink-secondary);
}

.skill-graph .sg-sv-langs-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.skill-graph .sg-sv-langs-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: 6px;
}

.skill-graph .sg-sv-langs-row .sg-chip-act {
  color: var(--sg-ink);
  font-size: 13px;
}

.skill-graph .sg-sv-langs-row .sg-chip-act:disabled {
  opacity: 0.3;
  cursor: default;
}

.skill-graph .sg-sv-langs-open,
.skill-graph .sg-sv-scopes-open {
  font-size: 15px;
}

.skill-graph .sg-chip-rename {
  min-width: 7em;
}

.skill-graph .sg-chipinput-add:disabled {
  opacity: 0.5;
}

/* the value pickers reuse the FV detail-row buttons; left-aligned here (the
   FV rows right-align against their label) */
.skill-graph .sg-sv-form .sg-editvals {
  justify-content: flex-start;
}

.skill-graph .sg-sv-form-note {
  color: #d97e00; /* warning orange — author eyeball */
  font-size: 12px;
}

.skill-graph .sg-sv-form-error {
  color: #d03030; /* matches the SV cycle-guard reject flash */
  font-size: 12px;
}

.skill-graph .sg-sv-create-ok:disabled {
  opacity: 0.5;
  cursor: default;
}

/* time-travel modal (§11.8): a time window, the filter tree, a live count */
.skill-graph .sg-sv-timetravel .sg-sv-modal-card {
  overflow-y: auto;
}

.skill-graph .sg-sv-tt-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.skill-graph .sg-sv-tt-summary {
  color: var(--sg-ink-secondary);
  font-size: 12px;
}

.skill-graph .sg-sv-tt-window {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* one window edge: date picker, its stop slider, the stop caption */
.skill-graph .sg-sv-tt-edge {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* the date field takes only the width a date needs — the row does not
   stretch it across the card (author 2026-08-09) */
.skill-graph .sg-sv-tt-time {
  display: flex;
  align-items: center;
  gap: 6px;
}

.skill-graph .sg-sv-tt-time > span {
  width: 44px;
  flex: none;
}

.skill-graph .sg-sv-tt-time input[type="date"] {
  flex: none;
  width: auto;
}

.skill-graph .sg-sv-tt-clear {
  flex: none;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 1px solid var(--sg-hairline);
  border-radius: 6px;
  background: var(--sg-panel);
  color: var(--sg-ink-secondary);
  cursor: pointer;
  line-height: 1;
}

.skill-graph .sg-sv-tt-slider {
  width: 100%;
  margin: 0;
}

.skill-graph .sg-sv-tt-stop {
  font-size: 12px;
}

.skill-graph .sg-sv-tt-cnt {
  margin-left: auto;
  font-size: 11px;
  color: var(--sg-ink-secondary);
}

.skill-graph .sg-sv-tt-filters {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.skill-graph .sg-sv-tt-master {
  font-weight: 600;
}

/* leaf toggles are indented under their category master */
.skill-graph .sg-sv-tt-leaf {
  padding-left: 16px;
}

/* an opt-in category (id renames) explains itself right under its master */
.skill-graph .sg-sv-tt-warn,
.skill-graph .sg-sv-tt-note {
  padding-left: 16px;
  font-size: 12px;
  line-height: 1.4;
}

.skill-graph .sg-sv-tt-warn {
  color: var(--sg-accent);
}

.skill-graph .sg-sv-tt-note {
  color: var(--sg-ink-secondary);
}

.skill-graph .sg-sv-tt-count {
  color: var(--sg-ink-secondary);
}

.skill-graph .sg-sv-tt-delete {
  border-color: var(--sg-accent);
  color: var(--sg-accent);
}

.skill-graph .sg-sv-tt-delete:disabled {
  opacity: 0.5;
  cursor: default;
}

/* skilltree details block (§11.1 / N2): the head of what is now the details
   panel — tree name, its size, and the learned count */
.skill-graph .sg-sv-details {
  margin-bottom: 12px;
}

.skill-graph .sg-sv-details-name {
  font-size: 15px;
  font-weight: 600;
}

.skill-graph .sg-sv-details-meta,
/* the standing answer to "which mode am I in" (N3) — the donut slot only
   names what tapping DOES */
.skill-graph .sg-sv-details-mode,
/* …and which profile it belongs to (N6) */
.skill-graph .sg-sv-details-profile {
  color: var(--sg-ink-secondary);
}

/* SV progress line (learned count, no total — §8b) */
.skill-graph .sg-sv-progress {
  margin: 10px 0 12px;
  color: var(--sg-ink-secondary);
}

/* shared settings block (bottom of BOTH panels): label size + animations */
.skill-graph .sg-settings {
  margin-top: 12px;
  padding-top: 8px;
  border-top: 1px solid var(--sg-hairline);
}

/* the authoring block's own slider row shares the settings row's look, but
   NOT its class: `.sg-sv-panel .sg-setting-row` is how the settings block is
   addressed (tests included), and the authoring rows must stay out of that */
.skill-graph .sg-setting-row,
.skill-graph .sg-sv-slider-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 6px;
}

/* the label doubles as the reset control (author 2026-08-02) */
.skill-graph .sg-setting-label {
  cursor: pointer;
}

.skill-graph .sg-setting-label:hover {
  color: var(--sg-ink);
  text-decoration: underline;
  text-decoration-style: dotted;
}

.skill-graph .sg-setting-row input[type='range'],
.skill-graph .sg-sv-slider-row input[type='range'] {
  width: 110px;
  accent-color: var(--sg-accent);
}

.skill-graph .sg-setting-row select {
  font: inherit;
  font-size: 12px;
  color: var(--sg-ink);
  background: var(--sg-surface);
  border: 1px solid var(--sg-hairline);
  border-radius: 6px;
  padding: 2px 4px;
}

/* FV chrome off while the tree view is active (canvas keeps its size via
   cy.resize() on the way back) */
.skill-graph.sg-view-tree .sg-canvas,
.skill-graph.sg-view-tree .sg-panel:not(.sg-sv-panel),
.skill-graph.sg-view-tree .sg-btn,
/* …and while the Design View is showing (§11.6 / N8; the view switch stays) */
.skill-graph.sg-view-design .sg-canvas,
.skill-graph.sg-view-design .sg-panel,
.skill-graph.sg-view-design .sg-btn {
  display: none;
}

/* Design View (§11.6 / N8): control panel left, specimen stage right */
.skill-graph .sg-design {
  display: none;
}

.skill-graph.sg-view-design .sg-design {
  display: flex;
  position: absolute;
  inset: 0;
}

.skill-graph .sg-design-panel {
  width: 240px;
  flex: none;
  overflow-y: auto;
  padding: 52px 12px 12px; /* clear of the view switch */
  border-right: 1px solid var(--sg-hairline);
  background: var(--sg-panel);
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.skill-graph .sg-design-stage {
  flex: 1;
  min-width: 0;
  position: relative;
}

.skill-graph .sg-design-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.skill-graph .sg-design-cap {
  flex: 1;
  font-size: 12px;
  color: var(--sg-ink-secondary);
}

.skill-graph .sg-design-btn {
  border: 1px solid var(--sg-hairline);
  border-radius: 6px;
  background: var(--sg-surface);
  color: var(--sg-ink);
  font: inherit;
  font-size: 12px;
  padding: 3px 8px;
  cursor: pointer;
}

.skill-graph .sg-design-btn:hover {
  border-color: var(--sg-accent);
}

.skill-graph .sg-design-reset {
  margin-top: 10px;
}

.skill-graph .sg-design-row input[type='color'] {
  width: 34px;
  height: 24px;
  padding: 0;
  border: 1px solid var(--sg-hairline);
  border-radius: 6px;
  background: none;
}

/* the effects overlay (sv-effects.js): above the cytoscape canvases (0–2),
   below the DOM chrome (wheel/invite at 10+); never takes pointer events */
.skill-graph .sg-fx-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 3;
  pointer-events: none;
}

.skill-graph .sg-sv-note {
  color: var(--sg-ink-secondary);
}

/* SV stage (stage 3): the SV cytoscape instance mounts here */
.skill-graph .sg-sv {
  position: relative;
}

.skill-graph .sg-sv-stage {
  position: absolute;
  inset: 0;
}

/* SV authoring block (TSPE, stage 3.5): path-type toggles + export */
.skill-graph .sg-sv-authoring {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--sg-hairline);
}

.skill-graph .sg-sv-export {
  margin-top: 8px;
  width: 100%;
  font: inherit;
  font-size: 12px;
  color: var(--sg-ink);
  background: var(--sg-surface);
  border: 1px solid var(--sg-hairline);
  border-radius: 7px;
  padding: 5px 9px;
  cursor: pointer;
}

.skill-graph .sg-sv-export:hover {
  border-color: var(--sg-ink-muted);
}

/* ── Profiles (§11.1 tap-DB right / N6, 2026-08-09) ──
   The management MODAL: one row per profile, the active one marked. Sizes and
   colours are FIRST GUESSES — author eyeball pending. */
.skill-graph .sg-sv-profiles-modal .sg-sv-modal-card {
  width: min(420px, 92vw);
}

/* Only the LIST scrolls (author 2026-08-09: at ~11 profiles on a phone the
   card outgrew the screen and the buttons below it were pushed out of view).
   The head, the hint and the two buttons stay put; `min-height: 0` is what
   lets a flex child shrink below its content in the first place. */
.skill-graph .sg-sv-profiles {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.skill-graph .sg-sv-profile-list {
  min-height: 0;
  overflow-y: auto;
}

.skill-graph .sg-sv-profiles-hint {
  color: var(--sg-ink-secondary);
  font-size: 12px;
  margin: 2px 0 10px;
}

.skill-graph .sg-sv-profile-row {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 2px 0;
}

.skill-graph .sg-sv-profile-pick {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  padding: 5px 6px;
  border: 1px solid transparent;
  border-radius: 7px;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.skill-graph .sg-sv-profile-pick:hover {
  background: var(--sg-hover);
}

.skill-graph .sg-sv-profile-active .sg-sv-profile-pick {
  border-color: var(--sg-accent);
  background: var(--sg-hover);
}

.skill-graph .sg-sv-profile-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* the initials disc — its colour comes from the profile id (sv-profiles.js) */
.skill-graph .sg-sv-profile-dot {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 600;
  color: #1a1a1a;
}

.skill-graph .sg-sv-profile-name-input {
  flex: 1;
  min-width: 0;
  margin-left: 8px;
  padding: 5px 6px;
  border: 1px solid var(--sg-accent);
  border-radius: 7px;
  background: var(--sg-panel);
  color: var(--sg-ink);
  font: inherit;
}

/* reorder arrows: two tiny buttons stacked in one control's width, so the
   row keeps room for the name on a phone */
.skill-graph .sg-sv-profile-move {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* deliberately not smaller: two stacked arrows still have to be hittable with
   a thumb — 22×14 is the compromise between "tiny" and a usable touch target */
.skill-graph .sg-sv-profile-moveb {
  width: 22px;
  height: 14px;
  padding: 0;
  border: 1px solid var(--sg-hairline);
  border-radius: 4px;
  background: none;
  color: var(--sg-ink-secondary);
  font-size: 8px;
  line-height: 1;
  cursor: pointer;
}

.skill-graph .sg-sv-profile-moveb:hover:not(:disabled) {
  background: var(--sg-hover);
}

.skill-graph .sg-sv-profile-moveb:disabled {
  opacity: 0.35;
  cursor: default;
}

.skill-graph .sg-sv-profile-edit,
.skill-graph .sg-sv-profile-del {
  flex: none;
  width: 26px;
  height: 26px;
  border: 1px solid var(--sg-hairline);
  border-radius: 7px;
  background: none;
  color: var(--sg-ink-secondary);
  cursor: pointer;
}

.skill-graph .sg-sv-profile-edit:hover,
.skill-graph .sg-sv-profile-del:hover:not(:disabled) {
  background: var(--sg-hover);
}

.skill-graph .sg-sv-profile-del:disabled {
  opacity: 0.4;
  cursor: default;
}

.skill-graph .sg-sv-profile-new,
.skill-graph .sg-sv-profile-quick {
  display: block;
  width: 100%;
  margin-top: 8px;
  padding: 7px 10px;
  border: 1px solid var(--sg-hairline);
  border-radius: 8px;
  background: none;
  color: var(--sg-ink);
  font: inherit;
  cursor: pointer;
}

.skill-graph .sg-sv-profile-new:hover,
.skill-graph .sg-sv-profile-quick:hover {
  background: var(--sg-hover);
}

/* The QUICK-SWITCH overlay: profiles as circles down the RIGHT edge, starting
   at the top, for a coach updating several students while teaching. It lives
   in the SV STAGE — a flex sibling of the side panel — so the panel pushes it
   left rather than covering it; on a phone the bottom sheet simply overlaps
   its lower end (author 2026-08-09: the strip must not dodge upwards). */
.skill-graph .sg-sv-quick {
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 4;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 10px 8px;
  pointer-events: none; /* only the circles themselves take input */
}

.skill-graph .sg-sv-quick-right {
  right: 0;
}

.skill-graph .sg-sv-quick[hidden] {
  display: none;
}

/* more profiles than fit — especially on a small screen — scroll rather than
   run off the bottom */
.skill-graph .sg-sv-quick-strip {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: none;
  pointer-events: auto;
}

.skill-graph .sg-sv-quick-dot,
.skill-graph .sg-sv-quick-tool {
  flex: none;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 2px solid transparent;
  font-size: 14px;
  font-weight: 600;
  color: #1a1a1a;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
}

.skill-graph .sg-sv-quick-current {
  border-color: var(--sg-ink);
}

/* the grey tool circles (collapse toggle at the top, ✕ at the bottom): the
   profile dots' geometry (shared rule above), told apart by colour alone */
.skill-graph .sg-sv-quick-tool {
  border-color: var(--sg-hairline);
  background: var(--sg-panel);
  color: var(--sg-ink-secondary);
  font-size: 18px;
  /* the strip's scroll box clips shadows — and grey circles wear them badly
     anyway (author 2026-08-16) */
  box-shadow: none;
}
