/* Meridian — Fractal Deps View styles (v0.7.12.2c)
   Scoped under #dvFractalRoot so nothing leaks into the flat app. De-neoned
   (v0.7.12.2c): the prototype's warm `C` palette is retired — the --fr-* vars are
   now thin aliases onto the app's canonical :root tokens (styles/main.css), and
   raw chrome hex is replaced by those tokens, so the fractal reads in the same
   palette as Project/Trench. */

#dvFractalRoot {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;          /* [toolbar] above [main row] (v0.7.12.2a) */
  overflow: hidden;
  background: var(--bg);
  color: var(--text-sec);
  font-family: 'DM Mono', ui-monospace, monospace;
  /* --fr-* vars are now canonical aliases (de-neon, v0.7.12.2c) — redefining them
     here cascades to every var(--fr-*) consumer below. */
  --fr-border: var(--border);
  --fr-border-light: var(--border2);
  --fr-mute: var(--text-dim);
  --fr-mute2: var(--text-muted);
  --fr-gold: var(--accent);
  --fr-critical: var(--critical);
  --seam: #aeb9c6;   /* neutral tie between force-expanded parent and its revealed children (v0.7.12.2g) */
  --reveal: #E8943A;   /* right-click dependency reveal spotlight — amber-orange, distinct from muted gold chrome + red crit; survives the purple-band case violet failed (v0.7.12.2h) */
}

/* ── Controls toolbar (v0.7.12.2a): zoom slider, presets, altitude chip, Today ─
   Lives at the top of the fractal view container (NOT the global app header).
   flex:none so it keeps its height; .fr-main below it takes the rest. */
#dvFractalRoot .fractal-controls-toolbar {
  flex: none; display: flex; align-items: center; gap: 10px;
  padding: 6px 12px; box-sizing: border-box;
  background: var(--surface); border-bottom: 1px solid var(--fr-border-light);
}
#dvFractalRoot .fractal-zoom-slider {
  /* override the app-global `input[type=range]{flex:1}` (main.css) so the slider
     keeps a fixed width instead of stretching across the whole toolbar. The
     global rule still supplies the track/thumb styling, which we inherit. */
  flex: none; width: 220px; cursor: ew-resize;
}
#dvFractalRoot .fractal-preset-btn {
  font-family: inherit; font-size: 10px; letter-spacing: 0.08em;
  color: var(--fr-mute2); background: var(--surface2);
  border: 1px solid var(--fr-border-light); border-radius: 10px;
  padding: 3px 9px; cursor: pointer; transition: color .12s, border-color .12s;
}
#dvFractalRoot .fractal-preset-btn:hover { color: var(--fr-gold); border-color: var(--fr-gold); }
#dvFractalRoot .fractal-altitude-chip {
  font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--fr-gold); background: var(--accent-dim);
  border: 1px solid var(--fr-mute); border-radius: 3px;
  padding: 2px 8px; min-width: 56px; text-align: center;
}
#dvFractalRoot .fractal-today-btn {
  margin-left: auto;                /* pin Today to the right edge of the bar */
  font-family: inherit; font-size: 10px; letter-spacing: 0.08em;
  color: var(--fr-mute2); background: var(--surface2);
  border: 1px solid var(--fr-border-light); border-radius: 3px;
  padding: 3px 11px; cursor: pointer; transition: color .12s, border-color .12s;
}
#dvFractalRoot .fractal-today-btn:hover { color: var(--fr-gold); border-color: var(--fr-gold); }

/* ── Category dep-visibility toggles (v0.7.12.2c) — sit left of Today ──────────
   Active = lit (accent, full opacity); inactive = dimmed — the lit/dim state
   communicates the persisted on/off class filter at a glance. */
#dvFractalRoot .fractal-cat-btn {
  font-family: inherit; font-size: 10px; letter-spacing: 0.06em;
  color: var(--fr-mute2); background: var(--surface2);
  border: 1px solid var(--fr-border-light); border-radius: 3px;
  padding: 3px 9px; cursor: pointer; opacity: 0.5;
  transition: color .12s, border-color .12s, opacity .12s;
}
#dvFractalRoot .fractal-cat-btn:hover { color: var(--fr-gold); border-color: var(--fr-gold); }
#dvFractalRoot .fractal-cat-btn.active { color: var(--fr-gold); border-color: var(--fr-mute); opacity: 1; }

/* Main row: pinned sidebar | timeline. Fills the height below the toolbar. */
#dvFractalRoot .fr-main { display: flex; flex: 1 1 auto; min-height: 0; width: 100%; overflow: hidden; }

/* ── Column layout: pinned sidebar | timeline (axis + scroller) ───────────────
   Matches the prototype's separate .sidebar / .timeline columns. The sidebar is
   NOT inside the scroller, so it stays pinned during horizontal scroll. Vertical
   sync is translateY on .fr-sidebar-rows; horizontal axis sync is translateX on
   .fr-axis-inner — both set by the .fr-body scroll handler (render-only). */
#dvFractalRoot .fr-sidebar-col {
  position: relative; flex: none; z-index: 2; overflow: hidden;
  background: var(--surface); border-right: 1px solid var(--fr-border-light);
}
#dvFractalRoot .fr-corner {
  position: relative; z-index: 1;
  display: flex; align-items: flex-end; padding: 0 0 6px 16px;
  border-bottom: 1px solid var(--fr-border-light); background: var(--surface);
  font-size: 9px; letter-spacing: 0.18em; color: var(--fr-mute2);
}
#dvFractalRoot .fr-sidebar-body { position: absolute; left: 0; right: 0; bottom: 0; overflow: hidden; }
#dvFractalRoot .fr-sidebar-rows { position: absolute; top: 0; left: 0; will-change: transform; }

#dvFractalRoot .fr-timeline-col { position: relative; flex: 1 1 auto; min-width: 0; overflow: hidden; }
#dvFractalRoot .fr-axis {
  position: absolute; top: 0; left: 0; right: 0; z-index: 2; overflow: hidden;
  background: var(--surface); border-bottom: 1px solid var(--fr-border-light);
}
#dvFractalRoot .fr-axis-inner { position: absolute; top: 0; left: 0; height: 100%; will-change: transform; }
#dvFractalRoot .fr-body { position: absolute; left: 0; right: 0; bottom: 0; overflow: auto; }
#dvFractalRoot .fr-axis-month {
  position: absolute; top: 6px; height: 16px;
  border-left: 1px solid var(--fr-border-light);
  padding-left: 5px;
  font-size: 10px; letter-spacing: 0.08em; color: var(--fr-gold);
  white-space: nowrap; overflow: hidden;
}
#dvFractalRoot .fr-axis-week {
  position: absolute; bottom: 4px; height: 14px;
  border-left: 1px solid var(--fr-border);
  padding-left: 3px;
  font-size: 9px; color: var(--fr-mute2);
  white-space: nowrap; overflow: hidden;
}

/* ── Sidebar rows (PROGRAM tree) ───────────────────────────────────────────── */
#dvFractalRoot .fr-side-ws,
#dvFractalRoot .fr-side-track,
#dvFractalRoot .fr-side-task { position: absolute; left: 0; right: 0; display: flex; align-items: center; overflow: hidden; }
#dvFractalRoot .fr-side-ws { padding-left: 12px; gap: 8px; border-bottom: 1px solid var(--fr-border); }
#dvFractalRoot .fr-side-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
#dvFractalRoot .fr-side-ws-name { font-size: 11px; letter-spacing: 0.1em; color: var(--text); }
#dvFractalRoot .fr-side-track { padding-left: 28px; font-size: 10px; color: var(--fr-mute2); }
#dvFractalRoot .fr-side-task { gap: 5px; font-size: 10px; color: var(--text-sec); }
#dvFractalRoot .fr-side-arrow { color: var(--fr-mute); flex: none; }
#dvFractalRoot .fr-side-task-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ── Canvas ────────────────────────────────────────────────────────────────── */
#dvFractalRoot .fr-canvas { position: relative; z-index: 1; }
#dvFractalRoot .fr-band { position: absolute; left: 0; pointer-events: none; }
#dvFractalRoot .fr-ws-strip { position: absolute; left: 0; pointer-events: none; }
#dvFractalRoot .fr-track-strip {
  position: absolute; left: 0; pointer-events: none;
  border-bottom: 1px solid var(--fr-border);
  background: rgba(255,255,255,0.012);
}
#dvFractalRoot .fr-today {
  position: absolute; top: 0; width: 0;
  border-left: 1px dashed var(--fr-gold); opacity: 0.5; pointer-events: none; z-index: 2;
}

/* ── Pills / atoms ─────────────────────────────────────────────────────────── */
/* overflow was `hidden` until v0.7.12.5, purely to clip a long .fr-task-label out of
   a narrow pill. It is now `visible` so the .fr-dep-dot can STRADDLE the right edge
   (uniform with the atom's dot, and with the flat view's .dv-dep-dot). The label
   clipping it used to provide is preserved by `min-width: 0` on .fr-task-label below,
   which lets the flex item shrink so its OWN overflow:hidden + ellipsis take over. */
#dvFractalRoot .fr-task {
  position: absolute; z-index: 3;
  border-radius: 5px;
  overflow: visible; cursor: default;
  display: flex; align-items: center;
}
#dvFractalRoot .fr-task-expanded { border-radius: 5px 5px 0 0; }
/* Force-expand containment (v0.7.12.2g) — keyed on expandedPillIds, NOT altitude.
   Co-occurs with .fr-task-expanded: that shorthand sets top=5/bottom=0; these
   longhands come later in the cascade and set bottom=0 (redundant) leaving top=5. ✓ */
#dvFractalRoot .fr-task--force-expanded {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
  box-shadow: 0 2px 0 var(--seam);
  z-index: 5;   /* scoped bump above .fr-deps (z:4) so seam shadow is not painted over */
}
#dvFractalRoot .fr-task--nested {
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}
#dvFractalRoot .fr-task-label {
  padding: 0 8px; font-size: 11px; font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; pointer-events: none;
  min-width: 0;   /* v0.7.12.5: flex items default to min-width:auto and refuse to
                     shrink below their text — without this the label would spill out
                     of a narrow pill now that .fr-task is overflow:visible. */
}
#dvFractalRoot .fr-task-expanded .fr-task-label { font-size: 10.5px; letter-spacing: 0.06em; }
#dvFractalRoot .fr-atom {
  position: absolute; z-index: 3; border-radius: 2px; cursor: default;
}
/* Crit outline (v0.7.12.2c) — replaces the old partial-critical strips. A whole-
   element outline marks a rendered pill/atom that is critical OR the rendered
   ancestor of a critical node (set built in fractalRender.computeCritOutlineSet).
   `outline` (not border) so it never perturbs the box model or the inline hue
   border. --fr-critical is now the canonical --critical token (de-neon). */
#dvFractalRoot .fr-crit-outline {
  outline: 1.5px solid var(--fr-critical);
  outline-offset: 1px;
}

/* Reveal spotlight (v0.7.12.2h) — a DISTINCT channel from the crit outline. The
   reveal is a box-shadow GLOW (not an outline), so a revealed+critical pill reads
   as BOTH at once (red outline + violet glow) without competing for the same
   property. Endpoint pills/atoms of a right-click-revealed task's deps get this
   class via a post-pass in buildFractalMain (the glow set is derived from the
   drawn dep lines, so it matches them exactly). */
#dvFractalRoot .fr-task--revealed,
#dvFractalRoot .fr-atom.fr-task--revealed {
  box-shadow: 0 0 0 2px var(--reveal), 0 0 8px 1px var(--reveal);
}

/* ── Dep curves ────────────────────────────────────────────────────────────── */
#dvFractalRoot .fr-deps { position: absolute; top: 0; left: 0; pointer-events: none; z-index: 4; overflow: visible; }
#dvFractalRoot .fr-dep-path { fill: none; stroke: var(--text-muted); stroke-width: 1.2; stroke-dasharray: 4 3; opacity: 0.55; }
/* Lit dep line (v0.7.12.2h) — a dep curve incident to a right-click-revealed task.
   Violet + brighter + slightly thicker so it reads as "lifted" above the muted
   dashed field; keeps the dash so it stays a dependency curve, not a new species. */
#dvFractalRoot .fr-dep-path--revealed { stroke: var(--reveal); stroke-width: 1.6; opacity: 0.95; }

/* item 6 — pending approval: a DASH-DOT pattern instead of the approved plain dash (4 3),
   matching the Project and Trench views. A shape change, not just a sparser version of the
   same dash, so it reads as its own state at a glance. Deliberately not a colour change;
   --reveal amber and --critical red are both already load-bearing here. Round linecap so
   the short "dot" segment reads as a dot rather than a barely-visible sliver. Placed after
   --revealed so a revealed pending edge keeps its amber stroke and only inherits the dash. */
#dvFractalRoot .fr-dep-path--pending { stroke-dasharray: 5 3 1 3; stroke-linecap: round; }

/* Invisible hit overlay (v0.7.12.5) — a 9px transparent stroke twinned to every
   .fr-dep-path, the flat view's exact idiom (depsView.js:361-368). Its parent
   .fr-deps is pointer-events:none; `pointer-events` is an inherited property, so a
   descendant that names its own value is hit-testable again while the rest of the
   SVG layer stays transparent to the mouse. `stroke` (not `all`) confines the target
   to the curve itself, so the layer never swallows clicks aimed at the pills below.
   Disarmed mid-drag: drop resolution uses elementFromPoint(...).closest('[data-task-id]'),
   which a hit path sitting over the target pill would otherwise defeat. */
#dvFractalRoot .fr-dep-hit {
  fill: none; stroke: transparent; stroke-width: 9;
  pointer-events: stroke; cursor: pointer;
}
#dvFractalRoot.fr-dragging .fr-dep-hit { pointer-events: none; }

/* ── Drag-to-draw (v0.7.12.5) ───────────────────────────────────────────────────
   Dep-dot handle: the fractal's port of .dv-dep-dot (styles/main.css:233). Hidden
   until its pill/atom is hovered, then straddles the RIGHT edge — the end an edge
   is drawn FROM (predecessor → successor). Pills and atoms share one treatment.
   The hover z-index bump is load-bearing: .fr-task/.fr-atom sit at z:3 and each
   creates a stacking context, so the dot (z:25 *within* that context) still paints
   below .fr-deps (z:4) and the hit strokes would steal its mousedown. Raising the
   hovered node to z:6 clears both .fr-deps (4) and .fr-task--force-expanded (5). */
#dvFractalRoot .fr-task:hover,
#dvFractalRoot .fr-atom:hover { z-index: 6; }
#dvFractalRoot .fr-dep-dot {
  position: absolute; right: -5px; top: 50%;
  transform: translateY(-50%) scale(.6);
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--fr-gold); border: 1.5px solid var(--bg);
  cursor: crosshair; z-index: 25; opacity: 0;
  transition: opacity .12s, transform .12s;
}
#dvFractalRoot .fr-task:hover .fr-dep-dot,
#dvFractalRoot .fr-atom:hover .fr-dep-dot { opacity: 1; transform: translateY(-50%) scale(1); }

/* Live drag preview. position:fixed + client coords so it needs no rebasing when the
   canvas scrolls or buildFractalMain rebuilds the layout underneath a live drag; it
   is a sibling of .fr-main (never inside the innerHTML wipe). pointer-events:none so
   it is invisible to the drop's elementFromPoint hit-test. */
#dvFractalRoot .fr-drag-preview {
  position: fixed; inset: 0; width: 100%; height: 100%;
  pointer-events: none; z-index: 60; overflow: visible;
}
#dvFractalRoot .fr-drag-preview-path {
  fill: none; stroke: var(--fr-gold); stroke-width: 1.5;
  stroke-dasharray: 5 4; opacity: 0.8;
}

/* ── Workstream collapse (v0.7.12.2a) ───────────────────────────────────────────
   The chevron lives in the sidebar's scroll-synced ws-header row. One glyph (▶),
   rotated 90° when expanded, with a transition so toggling animates. Collapsed
   bands render header-only (track/task rows omitted upstream) with a dimmed name. */
#dvFractalRoot .fractal-collapse-chevron {
  flex: none; cursor: pointer; user-select: none;
  font-size: 9px; line-height: 1; color: var(--fr-mute2);
  padding: 3px; margin: -3px -1px -3px -3px;   /* enlarge hit area, keep layout */
  display: inline-block; transition: transform .15s ease, color .12s;
}
#dvFractalRoot .fractal-collapse-chevron.expanded { transform: rotate(90deg); }
#dvFractalRoot .fractal-collapse-chevron:hover { color: var(--fr-gold); }
#dvFractalRoot .fr-side-ws-collapsed .fr-side-ws-name { color: var(--fr-mute2); }
#dvFractalRoot .fr-side-ws-collapsed .fr-side-dot { opacity: 0.5; }

/* ── Per-pill expand (v0.7.12.2f) ───────────────────────────────────────────────
   Disclosure chevron on a pill's LEFT edge (first flex child of .fr-task). Shown
   only when the pill has children currently suppressed by the global altitude
   threshold (fractalRender.childrenSuppressedAtCurrentPpd). One glyph (▶), rotated
   90° when the pill is force-expanded. pointer-events:auto because the sibling
   .fr-task-label sets pointer-events:none — the chevron must still receive its
   click (the delegated guard on `main` matches .fr-expand-chevron). De-neon: uses
   the canonical --text / --fr-gold tokens only, no raw hex. */
#dvFractalRoot .fr-expand-chevron {
  flex: none; cursor: pointer; user-select: none; pointer-events: auto;
  font-size: 12px; font-weight: 700; line-height: 1; color: var(--text); opacity: 1;
  text-shadow: 0 1px 2px rgba(0,0,0,0.5);
  padding: 2px 3px; margin: 0 1px 0 2px;   /* enlarge hit area, keep at left edge */
  display: inline-block; transition: transform .15s ease, color .12s, opacity .12s;
}
#dvFractalRoot .fr-expand-chevron.expanded { transform: rotate(90deg); }
#dvFractalRoot .fr-expand-chevron:hover { color: var(--fr-gold); opacity: 1; }

/* ── Per-element interactivity (v0.7.12.2b) ─────────────────────────────────────
   Pills/atoms are now click/dblclick/right-click targets → pointer affordance. */
#dvFractalRoot .fr-task,
#dvFractalRoot .fr-atom { cursor: pointer; }

/* ── Read-only detail pane (v0.7.12.2b) ─────────────────────────────────────────
   Mounted on <body> (OUTSIDE #dvFractalRoot), so the --fr-* aliases (which live on
   the root) are out of scope — these rules reference the app's canonical :root
   tokens (styles/main.css) directly, which de-neons the pane in lockstep with the
   rest of the view. Right-side slide-in panel; exact treatment is a live-pass call. */
.fr-detail-pane {
  position: fixed; top: 0; right: 0; bottom: 0; width: 300px;
  transform: translateX(100%); transition: transform .18s ease;
  z-index: 1000; box-sizing: border-box;
  background: var(--surface); border-left: 1px solid var(--border2);
  color: var(--text-sec); font-family: 'DM Mono', ui-monospace, monospace;
  padding: 18px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 14px;
}
.fr-detail-pane.open { transform: translateX(0); }
.fr-detail-pane .fr-dp-breadcrumb { display: flex; align-items: center; gap: 7px; font-size: 10px; letter-spacing: 0.06em; color: var(--text-muted); }
.fr-detail-pane .fr-dp-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--text-muted); }
.fr-detail-pane .fr-dp-breadcrumb-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fr-detail-pane .fr-dp-title-row { display: flex; align-items: flex-start; gap: 8px; }
.fr-detail-pane .fr-dp-name { margin: 0; font-size: 14px; font-weight: 500; color: var(--text); line-height: 1.3; flex: 1 1 auto; }
.fr-detail-pane .fr-dp-crit-badge {
  flex: none; font-size: 8px; letter-spacing: 0.12em; color: var(--critical);
  border: 1px solid var(--critical); border-radius: 3px; padding: 2px 5px; margin-top: 2px;
}
.fr-detail-pane .fr-dp-meta { display: grid; grid-template-columns: 1fr 1fr; gap: 10px 12px; }
.fr-detail-pane .fr-dp-meta-label { font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); }
.fr-detail-pane .fr-dp-meta-value { font-size: 12px; color: var(--text-sec); margin-top: 2px; }
.fr-detail-pane .fr-dp-progress-label { font-size: 9px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 5px; }
.fr-detail-pane .fr-dp-progress-track { height: 5px; border-radius: 3px; background: var(--border); overflow: hidden; }
.fr-detail-pane .fr-dp-progress-fill { height: 100%; background: var(--accent); border-radius: 3px; }
.fr-detail-pane .fr-dp-section { border-top: 1px solid var(--border); padding-top: 12px; }
.fr-detail-pane .fr-dp-section-title { font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent); margin-bottom: 8px; }
.fr-detail-pane .fr-dp-empty { font-size: 11px; color: var(--text-dim); font-style: italic; }
.fr-detail-pane .fr-dp-dep-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; padding: 3px 0; }
.fr-detail-pane .fr-dp-dep-name { font-size: 11px; color: var(--text-sec); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fr-detail-pane .fr-dp-dep-meridian { flex: none; font-size: 9px; letter-spacing: 0.04em; color: var(--text-muted); }

/* ── Right-click dep-toggle panel (v0.7.12.2b, transient) ───────────────────────
   Mounted on <body> at the cursor; one toggle item; resets on reload. */
.fractal-dep-toggle-panel {
  position: fixed; z-index: 1001;
  background: var(--surface2); border: 1px solid var(--border2); border-radius: 4px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.5); padding: 3px;
  font-family: 'DM Mono', ui-monospace, monospace;
}
.fractal-dep-toggle-item {
  display: block; width: 100%; text-align: left;
  font-family: inherit; font-size: 11px; color: var(--text-sec);
  background: none; border: none; border-radius: 3px;
  padding: 6px 12px; cursor: pointer; white-space: nowrap;
}
.fractal-dep-toggle-item:hover { background: var(--accent-dim); color: var(--accent); }
