/* Reset & base */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
/* Warm-dark palette, matched to the lesson pages (the default lesson theme).
   Token NAMES are unchanged so the views.js / app.js d3 + dagre code keeps working;
   only the VALUES move to the warm, low-glare, WCAG-AA set used on the lesson pages.
   --accent is now the lesson teal, so links/active states read the same everywhere. */
:root {
  /* Colors live in tokens.css (the theme source of truth). The dashboard color names
     are aliased there to the active theme tokens, so one data-theme switch reswatches the
     whole dashboard. Do not redefine the color names here. */
  --radius: 6px;
  --panel-w: 340px;
  /* Type tokens shared with the lesson pages (render_lessons.py _CSS), so the app
     and the lessons read as one product: a display face for titles, a mono face for
     labels and numbers. Body UI stays on the system sans (the app is dense chrome,
     not long-form prose, where the lessons' serif belongs). */
  --font-display: "Space Grotesk", system-ui, sans-serif;
  --font-body: "Source Serif 4", "Iowan Old Style", Palatino, Georgia, serif;
  --font-mono: "JetBrains Mono", ui-monospace, monospace;
}
html, body { height: 100%; background: var(--bg); color: var(--text); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; font-size: 14px; overflow: hidden; }
#app { display: flex; flex-direction: column; height: 100vh; }
#topbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 8px 16px; background: var(--bg2); border-bottom: 1px solid var(--border); flex-shrink: 0; z-index: 10; }
#topbar .topbar-title { font-family: var(--font-display); font-size: 16px; font-weight: 600; color: var(--accent); white-space: nowrap; letter-spacing: -0.01em; }
#topbar .topbar-title a { color: inherit; text-decoration: none; }
#topbar .topbar-title a:hover { text-decoration: underline; }
#search { background: var(--bg3); border: 1px solid var(--border); border-radius: var(--radius); color: var(--text); padding: 4px 8px; font-size: 13px; width: 200px; }
#search:focus { border-color: var(--accent); }
/* Keyboard focus is always visible across the desktop shell. :focus-visible only matches
   keyboard / assistive-tech focus, so pointer users never see the ring. Restores the rings the
   accessibility review found missing on search, the chapter select, and other controls that had
   a bare outline:none. */
#search:focus-visible,
button:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
#tabs { display: flex; gap: 4px; margin-left: auto; }
.tab-btn { background: none; border: 1px solid var(--border); border-radius: var(--radius); color: var(--text-dim); padding: 4px 12px; cursor: pointer; font-size: 13px; }
.tab-btn.active { background: var(--accent); color: var(--bg); border-color: var(--accent); }
#filters { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 6px 16px; background: var(--bg2); border-bottom: 1px solid var(--border); flex-shrink: 0; font-size: 12px; }
.chip { padding: 2px 10px; border-radius: 12px; cursor: pointer; border: 1px solid var(--border); background: var(--bg3); color: var(--text-dim); font-size: 12px; }
.chip.active { color: var(--bg); border-color: transparent; }
#chapter-select { background: var(--bg3); border: 1px solid var(--border); border-radius: var(--radius); color: var(--text); padding: 3px 6px; font-size: 12px; }
#chapter-select:focus { border-color: var(--accent); }
#hud { display: flex; align-items: center; gap: 16px; padding: 4px 16px; background: var(--bg); border-bottom: 1px solid var(--border); flex-shrink: 0; font-size: 12px; color: var(--text-dim); flex-wrap: wrap; }
.hud-bar-wrap { display: flex; align-items: center; gap: 4px; }
.hud-bar { height: 6px; width: 60px; background: var(--bg3); border-radius: 3px; overflow: hidden; }
.hud-bar-fill { height: 100%; border-radius: 3px; transition: width 0.3s; }
#views { flex: 1; position: relative; overflow: hidden; }
.view { position: absolute; inset: 0; display: none; }
.view.active { display: block; }
.svg-wrapper { width: 100%; height: 100%; overflow: hidden; }
.svg-wrapper svg { display: block; }
/* Node cards */
.node-card text { font-size: 11px; fill: var(--text); pointer-events: none; }
.node-card.locked rect.card-bg    { fill: var(--bg); stroke-width: 1; opacity: 0.7; }
.node-card.unlockable rect.card-bg { fill: var(--bg); stroke: var(--accent); stroke-width: 1.5; }
.node-card.learned rect.card-bg   { fill: var(--green); fill-opacity: 0.14; stroke: var(--green); stroke-width: 1.5; }
.node-card.dimmed { opacity: 0.12; }
.node-card.highlighted rect.card-bg { stroke-width: 2.5; }
.pulse-ring { fill: none; stroke: var(--accent); stroke-width: 1.5; opacity: 0; }
.node-card.unlockable .pulse-ring { animation: pulse 2s ease-in-out infinite; }
@keyframes pulse { 0%,100%{opacity:0} 50%{opacity:0.5} }
/* Graph nodes */
.graph-node circle { stroke-width: 1.5; cursor: pointer; }
.graph-node.locked   circle { opacity: 0.5; }
.graph-node.unlockable circle { stroke: var(--accent); }
.graph-node.learned  circle { stroke: var(--green); }
/* Graph labels: a halo (paint-order stroke in the canvas color) keeps the name legible
   over edges and circles in every theme. Shown progressively by node degree (see views.js). */
.graph-node text, .graph-label {
  fill: var(--text); font-family: var(--font-display); font-size: 11px; font-weight: 600;
  letter-spacing: -0.01em; pointer-events: none;
  paint-order: stroke; stroke: var(--bg); stroke-width: 3.5px; stroke-linejoin: round;
}
.graph-node.locked text, .graph-label.locked { fill: var(--muted); }
/* Edges */
.edge { fill: none; }
.edge.strong   { stroke: var(--accent); stroke-width: 1.5; opacity: 0.85; }
.edge.moderate { stroke: var(--accent); stroke-width: 1; opacity: 0.8; }
.edge.helpful  { stroke: var(--cX); stroke-width: 1; stroke-dasharray: 5 3; opacity: 0.7; }
.edge.weak     { stroke: var(--cX); stroke-width: 0.8; stroke-dasharray: 2 4; opacity: 0.5; }
.edge.unlock   { stroke: var(--cX); stroke-width: 0.8; stroke-dasharray: 2 4; opacity: 0.5; }
.edge.soft     { stroke: var(--purple); stroke-width: 1; stroke-dasharray: 4 3; opacity: 0.6; }
.edge.dimmed   { opacity: 0.05 !important; }
.edge.ancestor   { stroke: var(--gold); stroke-width: 2; opacity: 0.9; }
.edge.descendant { stroke: var(--green); stroke-width: 2; opacity: 0.9; }
/* Panel */
#panel { position: fixed; right: 0; top: 0; bottom: 0; width: var(--panel-w); background: var(--bg2); border-left: 1px solid var(--border); transform: translateX(100%); transition: transform 0.2s; z-index: 20; overflow-y: auto; padding: 16px; }
#panel.open { transform: none; }
/* Tap-outside-to-dismiss scrim behind the detail panel (sits just under #panel, z-index 20). */
#panel-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.45); z-index: 19; opacity: 0; transition: opacity 0.2s; }
#panel-backdrop:not([hidden]) { opacity: 1; }
#panel-close { float: right; background: none; border: none; color: var(--text-dim); cursor: pointer; font-size: 18px; line-height: 1; padding: 0; }
#panel-title { font-size: 15px; font-weight: 600; margin-bottom: 4px; padding-right: 24px; display: block; }
.panel-meta { font-size: 12px; color: var(--text-dim); margin-bottom: 12px; display: flex; flex-wrap: wrap; gap: 6px; }
.badge { padding: 2px 7px; border-radius: 10px; font-size: 11px; font-weight: 500; background: var(--bg3); }
.badge-course { background: var(--bg3); }
.badge-diff-foundational { background: var(--bg3); color: var(--green); }
.badge-diff-beginner     { background: var(--bg3); color: var(--accent); }
.badge-diff-intermediate { background: var(--bg3); color: var(--orange); }
.badge-diff-advanced     { background: var(--bg3); color: var(--red); }
.badge-type-strong   { background: var(--bg3); color: var(--accent); }
.badge-type-moderate { background: var(--bg3); color: var(--accent); }
.badge-type-helpful  { background: var(--bg3); color: var(--text-dim); }
.badge-type-weak     { background: var(--bg3); color: var(--text-dim); }
.badge-type-unlock   { background: var(--bg3); color: var(--text-dim); }
.panel-section-hd { font-size: 11px; font-weight: 600; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.05em; margin: 14px 0 6px; }
.prereq-item { margin-bottom: 8px; }
.prereq-link { cursor: pointer; color: var(--accent); font-weight: 500; background: none; border: none; padding: 0; font-size: 14px; }
.prereq-link:hover { text-decoration: underline; }
.stars { color: var(--gold); font-size: 12px; margin-left: 4px; }
.prereq-reason { font-size: 11px; color: var(--text-dim); margin-top: 2px; }
.unlock-link { cursor: pointer; color: var(--green); background: none; border: none; padding: 0; font-size: 14px; }
.unlock-link:hover { text-decoration: underline; }
.lesson-links { margin-top: 12px; }
.lesson-link { display: inline-block; margin: 3px 4px 3px 0; padding: 4px 10px; background: var(--bg3); border: 1px solid var(--border); border-radius: var(--radius); color: var(--accent); font-size: 12px; text-decoration: none; }
.lesson-link:hover { background: var(--accent); color: var(--bg); }
#mark-btn { margin-top: 14px; width: 100%; padding: 7px; border: none; border-radius: var(--radius); cursor: pointer; font-size: 13px; font-weight: 600; }
.mark-unlearn { background: var(--bg3); color: var(--red); border: 1px solid var(--border) !important; }
.mark-learn   { background: var(--green); color: var(--bg); }
#skip-warning { display: none; margin-top: 6px; padding: 6px 8px; background: var(--amber-soft); border-radius: var(--radius); font-size: 11px; color: var(--orange); }
/* Legend */
#legend { position: absolute; bottom: 12px; left: 12px; background: var(--chrome-bg); -webkit-backdrop-filter: var(--chrome-blur); backdrop-filter: var(--chrome-blur); border: 1px solid var(--chrome-border); border-radius: var(--radius); padding: 10px 14px; font-size: 11px; color: var(--text); box-shadow: var(--chrome-shadow); z-index: 5; max-width: 220px; }
#legend h4 { font-size: 11px; color: var(--text-dim); margin-bottom: 6px; }
.legend-row { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.legend-node { width: 18px; height: 12px; border-radius: 2px; border: 1.5px solid; }
.legend-node.locked     { border-color: var(--border); background: var(--bg); opacity: 0.7; }
.legend-node.unlockable { border-color: var(--accent); background: var(--bg); }
.legend-node.learned    { border-color: var(--green); background: var(--bg3); }
.legend-line { width: 24px; height: 2px; }
.legend-strong  { background: var(--accent); }
.legend-helpful { background: repeating-linear-gradient(90deg,var(--cX) 0,var(--cX) 4px,transparent 4px,transparent 7px); }
.era-label { fill: var(--text-dim); font-size: 13px; font-weight: 600; }
.era-sub   { fill: var(--cX); font-size: 9px; }
.era-sep   { stroke: var(--border); stroke-width: 1; }
.era-sep-chapter { stroke: var(--text-dim); stroke-width: 2; opacity: 0.7; }
#tt-controls { position: absolute; top: 12px; right: 12px; display: flex; gap: 6px; z-index: 5; }
#tt-controls button { background: var(--chrome-bg); -webkit-backdrop-filter: var(--chrome-blur); backdrop-filter: var(--chrome-blur); border: 1px solid var(--chrome-border); color: var(--text); border-radius: var(--radius); padding: 5px 11px; font-size: 12px; font-family: var(--font-mono); cursor: pointer; box-shadow: var(--chrome-shadow); transition: border-color .15s, color .15s; }
#tt-controls button:hover { border-color: var(--accent); color: var(--accent); }
.legend-soft    { background: repeating-linear-gradient(90deg,var(--purple) 0,var(--purple) 3px,transparent 3px,transparent 6px); }
/* Atlas */
.pack-leaf { cursor: pointer; }
.atlas-label { font-family: var(--font-display); pointer-events: none;
  paint-order: stroke; stroke: var(--bg); stroke-width: 3px; stroke-linejoin: round; }
.atlas-group-label { fill: var(--text); font-weight: 600; }
.atlas-leaf-label  { fill: var(--muted); font-weight: 500; }
/* Search highlight */
.search-match rect.card-bg { stroke: var(--gold) !important; stroke-width: 2 !important; }
.search-match circle { stroke: var(--gold) !important; stroke-width: 2 !important; }
/* Tooltip */
#tooltip { position: fixed; pointer-events: none; background: var(--bg2); border: 1px solid var(--border); border-radius: var(--radius); padding: 6px 10px; font-size: 12px; z-index: 100; display: none; max-width: 220px; }

/* ── Discipline hub lens ── */
.node-card.lens-dim { opacity: 0.24; transition: opacity .15s; }
.node-card.lens-dim:hover { opacity: 0.55; }
.hubchip { background: transparent; border: 1px solid var(--border); color: var(--text-dim);
  border-radius: 999px; padding: 3px 11px; font-size: 12px; cursor: pointer;
  font-family: var(--font-mono); line-height: 1.4; }
.hubchip:hover { color: var(--text); border-color: var(--accent); }
.hubchip.active { color: var(--text); border-color: var(--accent); background: var(--bg2); }
