/* ===============================================================================================================
   STYLESHEET  --  what everything looks like
   ===============================================================================================================
   WHAT THIS FILE DOES (for beginners)
   CSS (Cascading Style Sheets) is the language that says how a web page LOOKS: colors, sizes, spacing, fonts,
   what sits where. index.html says WHAT is on the page; this file says how it looks; the scripts in js/ say what
   it DOES. Change a color here and the whole app changes, without touching any logic.
   HOW TO READ A RULE:  selector { property: value; }.  The selector says WHICH elements (#name = the element with
   that id, .name = every element with that class, header = every <header>, a space means "inside"). Each
   property: value line then changes one aspect, e.g. color: red;.
   WORDS YOU WILL MEET:  custom property (variable) = a name starting with two dashes, like --accent, defined once
   in chapter 1 and used everywhere as var(--accent).  media query = a rule that only applies on certain screens
   (@media (max-width: 700px) means phones).  flexbox = a way to line things up in a row or column.  z-index =
   which element lies on top of which.  px = pixels.  rem/em = sizes relative to the text size.  :hover = while
   the mouse is over it.  !important = "this one wins" (used sparingly).
   HOW THE PHONE LAYOUT WORKS: js/mobile.js puts the classes phone, tablet and touch on the page; the last chapter
   turns them into layout rules such as body.phone { ... }. Nothing here detects the device itself.
   ORIGINAL COMMENTS: each chapter keeps the original author's banner and notes below the chapter heading. Search
   for "CHAPTER" to see only the outline.
   
   TABLE OF CONTENTS  (search this file for "CHAPTER n" to jump to a chapter; line numbers are only a guide)
      1. COLOR PALETTE                                                                  line   61   - one color per node type
      2. BASE / RESET                                                                   line  101   - defaults for every element
      3. HEADER                                                                         line  123   - title, graph switcher, search box
      4. GRAPH CANVAS                                                                   line  176   - the map: nodes and links
      5. LEGEND                                                                         line  286   - the row at the bottom
      6. TUTORIAL / MANUAL CARD                                                         line  320   - the help card at the bottom left
      7. CAPTIONS AND EDGE LABELS                                                       line  347   - short texts on the map
      8. TOOLBAR, EDITOR PANEL, TOAST, EMPTY STATE                                      line  381   - buttons, node editor, messages
      9. GRAPH TABS                                                                     line  471   - one tab per graph
     10. DROP-DOWN MENUS                                                                line  484   - graph switcher, Edit, Learn
     11. STUDY LAYER                                                                    line  528   - notes panel, review, progress (js/study.js)
     12. EQUATIONS ATTACHED TO NODE LABELS                                              line  626   - formula blocks
     13. CLICKABLE EDGES                                                                line  653   - connection lines you can click
     14. ZOOM BUTTONS                                                                   line  723   - the + and - buttons
     15. LATER ADDITIONS: stacking order, figure editor, gap report, tutorial pictures  line  746   - added over time, each with its own note
     16. MODE SWITCH (Graph | Table) AND TABLE MODE                                     line  957   - the second view
     17. REVIEW CARD, QUICK ADD BAR, INBOX AND HISTORY ROWS                             line 1100   - small dialogs of js/study.js and js/extras.js
     18. PHONE AND TOUCH                                                                line 1140   - classes set by js/mobile.js
   =============================================================================================================== */

/* ===================================================================
   PHYSICS KNOWLEDGE GRAPH — STYLESHEET
   ===================================================================
   Pure presentation: colors, typography, and layout for the graph
   canvas, header, legend, manual card, and the node-detail side
   panel. No content lives here — that's all in the imported Excel data
   — and no behavior — that's js/app.js. This file just
   answers "what does it look like".

   The color palette follows a simple convention throughout the app:
   each node TYPE (root / field / subfield / principle / finding) has
   its own hue, defined once below as CSS custom properties and again
   as hex strings in the imported Excel data's TYPES object (SVG elements
   are colored via JS/D3, not CSS, so the two need to stay in sync if
   you ever change a color).
=================================================================== */


/* ===============================================================================================================
   CHAPTER 1 OF 18  --  COLOR PALETTE
   ===============================================================================================================
   The few colors the whole app uses, stored as variables (--bg for the background, --ink for text, --accent for
   the highlight, one hue per node type). Everything below says var(--name) instead of a color code, so changing a
   variable here recolors the entire page. The same hues are repeated in js/app.js (the TYPES table) because the
   SVG drawing is colored by the script; keep both in step.
=============================================================================================================== */

/* -----------------------------------------------------------------
   COLOR PALETTE (CSS custom properties)
   Dark, low-saturation "chalkboard" background with one accent hue
   per node type. "-dim" variants are the muted background used for
   small badges (e.g. the panel's type kicker) so text stays legible
   without the full-saturation color overpowering it.
----------------------------------------------------------------- */
:root{
  --bg:#0B1220;              /* page background */
  --bg-panel:#101A2C;        /* side panel / search dropdown background */
  --ink:#E7ECF3;             /* primary (brightest) text color */
  --ink-dim:#8FA0BC;         /* secondary / muted text color */
  --line:#2A3A54;            /* borders, dividers, link/edge color */

  --root:#7CA8E0;            /* "Physics" root node — blue */
  --root-dim:#233A56;
  --field:#4C9F82;           /* main field nodes — green */
  --field-dim:#274538;
  --subfield:#9B7FD4;        /* subfield nodes (e.g. Electrostatics) — purple */
  --subfield-dim:#332B52;
  --principle:#D9A63C;       /* principle / law nodes — amber */
  --principle-dim:#4A3C1C;
  --observable:#4AAFC4;      /* measurable observables (E-field, B-field, ...) — teal */
  --observable-dim:#1B3A45;
  --finding:#C0577A;         /* experimental finding nodes — rose */
  --finding-dim:#4A2732;

  --accent:#7CA8E0;          /* interactive highlight color (focus ring, links, etc.) */
}


/* ===============================================================================================================
   CHAPTER 2 OF 18  --  BASE / RESET
   ===============================================================================================================
   Removes the browser's built-in margins and sets the basic font, so the page looks the same in every browser.
=============================================================================================================== */

/* -----------------------------------------------------------------
   BASE / RESET
----------------------------------------------------------------- */
*{box-sizing:border-box;}
html,body{
  margin:0; padding:0; height:100%;
  background:var(--bg); color:var(--ink);
  font-family:'IBM Plex Sans', Arial, sans-serif;
  overflow:hidden; /* the graph is a full-viewport canvas app, not a scrolling page */
}
/* #app is the single full-screen container everything else is absolutely
   positioned within (header, canvas, legend, manual card, side panel). */
#app{ position:relative; width:100vw; height:100vh; }



/* ===============================================================================================================
   CHAPTER 3 OF 18  --  HEADER
   ===============================================================================================================
   The top strip: the graph's title and tagline, the graph switcher, the Graph / Table switch, the toolbar menus
   and the search box.
=============================================================================================================== */

/* -----------------------------------------------------------------
   HEADER (title + search box)
   Pinned to the top of the screen, floating over the canvas.
   pointer-events:none on the header itself lets clicks "pass through"
   to the graph beneath it in any empty space; the title block and
   search box opt back into receiving clicks individually.
----------------------------------------------------------------- */
header{
  position:absolute; top:0; left:0; right:0; z-index:5;
  display:flex; align-items:center; justify-content:flex-start; gap:14px; flex-wrap:wrap;
  padding:18px 28px 0 28px; pointer-events:none;
}
header > *{ align-self:center;

}
header .title-block{ pointer-events:auto; }
h1{
  font-family:'Fraunces', Georgia, serif; /* serif display face for the title, contrasting with the sans-serif UI */
  font-weight:600; font-size:22px; letter-spacing:0.2px; margin:0;
  color:var(--ink);
}
h1 .accent{ color:var(--accent); font-style:italic; }
.subtitle{ margin:4px 0 0 0; font-size:12.5px; color:var(--ink-dim); max-width:460px; }

/* Search input + its results dropdown (top-right of the header) */
#searchWrap{ pointer-events:auto; position:relative; }
#search{
  width:230px; background:var(--bg-panel); border:1px solid var(--line);
  color:var(--ink); font-family:'IBM Plex Mono', monospace; font-size:12.5px;
  padding:0 12px; border-radius:3px; outline:none;
}
#search:focus{ border-color:var(--accent); }
#search::placeholder{ color:var(--ink-dim); }
#searchResults{
  position:absolute; top:36px; right:0; width:230px; max-height:280px;
  overflow-y:auto; background:var(--bg-panel); border:1px solid var(--line);
  border-radius:3px; display:none; z-index:20; /* shown/hidden via JS, not :focus, so it can stay open on click */
}
#searchResults div{
  padding:8px 12px; font-size:12px; cursor:pointer; border-bottom:1px solid var(--line);
}
#searchResults div:last-child{border-bottom:none;}
#searchResults div:hover{ background:var(--field-dim); }



/* ===============================================================================================================
   CHAPTER 4 OF 18  --  GRAPH CANVAS
   ===============================================================================================================
   The big drawing area. Classes such as node, link and label are put on the SVG elements by js/app.js, and the
   rules here give them their look (sizes, transitions, what happens on hover and for the centred node).
=============================================================================================================== */

/* -----------------------------------------------------------------
   GRAPH CANVAS (SVG nodes + links)
   The actual force-directed diagram, drawn by js/app.js.
   These rules style the SVG elements it creates: <line> for edges,
   <g class="node"> wrapping a circle + label for each node.
----------------------------------------------------------------- */
svg{ display:block; width:100%; height:100%; cursor:grab; position:relative; z-index:1; } /* "grab" hints the canvas can be panned */
svg:active{ cursor:grabbing; }

.link{ stroke:var(--line); stroke-width:1.2px; fill:none; }
.link-arrowhead{ fill:var(--line); } /* the <marker> path used as marker-end on directed (derivation) links */

.node circle.core{ stroke-width:1.4px; cursor:pointer; }

/* A dashed ring drawn around every node but only made visible (via the
   .focus modifier below) on whichever node is currently focused —
   this is the "you are here" indicator at the center of the graph. */
.node .focusring{
  fill:none; stroke:var(--accent); stroke-width:1.4px;
  opacity:0; pointer-events:none;
}
.node.focus .focusring{ opacity:0.9; }

.node text{
  font-family:'IBM Plex Sans', sans-serif; font-size:12px; fill:var(--ink-dim);
  pointer-events:none; /* clicks should hit the circle beneath, not the text */
  paint-order:stroke; stroke:var(--bg); stroke-width:3px; /* dark outline so labels stay legible crossing over links/other nodes */
}
.node.focus text{ fill:var(--ink); font-weight:600; } /* focused node's label is brighter + bolder */

/* The on-canvas description box (built by updateDescOverlay() in
   js/app.js), shown below whichever node is currently
   focused — every node has one. For a focused PRINCIPLE, it also holds
   an equation card (see .eq-box below) underneath the description.
   Lives inside an SVG <foreignObject>, which is what lets this be a
   normal, word-wrapping HTML <div> instead of manually line-broken SVG
   <text>; the foreignObject's own height is set per-node in JS (taller
   when an equation card is present), so nothing here needs to clip. */
.node-desc{
  font-family:'IBM Plex Sans', sans-serif;
  color:#CBD5E6; background:rgba(16,26,44,0.98); border:1px solid var(--line);
  border-radius:8px; padding:10px 12px; box-sizing:border-box;
}
.node-desc-text{ font-size:11.5px; line-height:1.55; margin:0; }
.node-desc-list{ font-size:11.5px; line-height:1.55; margin:0; padding-left:18px; }
.node-desc-list li{ margin-bottom:3px; }
.node-desc-list li:last-child{ margin-bottom:0; }

/* Small illustrative diagram (see the FIGURES map in js/app.js)
   shown at the bottom of a node's description box when it has one, e.g.
   "field around a positive point charge" or the Lorentz-factor plot. */
/* A figure box has ONE border — the .node-desc frame around it. The inner
   .node-fig is just a layout row (no border/background of its own), whose
   height sets the size of the sketch: the sketch is fitted to that height. */
.node-desc.has-fig{ padding:12px 14px; }
.node-fig{
  --fig-h:130px;   /* ≈ 6 rows of text: the sketch is fitted to the height of the text beside it */
  margin:0; display:flex; align-items:center; gap:16px;
  border:0; padding:0; background:none;
  width:100%; height:var(--fig-h);
  box-sizing:border-box;
  /* Containing block for KaTeX's own internal absolutely-positioned parts. */
  position:relative; overflow:visible;
}
.fig-sketch{ flex:none; }
.fig-svg{ height:var(--fig-h,130px); width:calc(var(--fig-h,130px) * 1.5294); overflow:visible; display:block; }   /* 260:170 viewBox, fitted to the box height */
.fig-text{ position:relative; flex:1; min-width:0; display:flex; flex-direction:column; justify-content:center; gap:5px; text-align:left; }
.fig-title{ font-family:'IBM Plex Sans', sans-serif; font-weight:600; font-size:12.5px; line-height:1.3; color:var(--ink); }
.fig-line{ stroke:var(--observable); stroke-width:1.3px; fill:none; opacity:0.9; }
.fig-arrowed{ marker-end:url(#figArrowHead); }
.fig-svg marker path{ fill:var(--observable); }
.fig-wire{ stroke:var(--ink-dim); stroke-width:2px; fill:none; }
.fig-wire-dot{ fill:var(--ink); }
.fig-wire-cross line{ stroke:var(--ink); stroke-width:1.6px; }
.fig-charge-pos{ fill:var(--principle-dim); stroke:var(--principle); stroke-width:1.4px; }
.fig-charge-neg{ fill:var(--subfield-dim); stroke:var(--subfield); stroke-width:1.4px; }
.fig-charge-label{ font-family:'IBM Plex Mono', monospace; font-size:9px; fill:var(--ink); pointer-events:none; }
.fig-medium{ fill:var(--ink-dim); opacity:0.14; stroke:none; }   /* the shaded lower medium (medium 1) of the boundary-condition sketches */
.fig-label{ font-family:'IBM Plex Mono', monospace; font-size:10px; fill:var(--ink); pointer-events:none; }
.fig-dash{ stroke:var(--ink-dim); stroke-width:1px; stroke-dasharray:3 3; fill:none; }
.fig-thin{ stroke:var(--ink-dim); stroke-width:1px; fill:none; }
.fig-axis{ stroke:var(--ink-dim); stroke-width:1px; }
.fig-axis-label{ font-family:'IBM Plex Mono', monospace; font-size:9px; fill:var(--ink-dim); }

.fig-formula-katex{ position:relative; text-align:left; font-size:14px; color:var(--ink); margin-top:2px; }
.fig-formula-katex .katex{ position:relative; font-size:1em; }
.fig-formula-katex .katex-display{ position:relative; margin:0; text-align:left; }
.fig-caption-html{ font-family:'IBM Plex Sans', sans-serif; font-size:11px; color:var(--ink-dim); line-height:1.35; }

/* The highlighted "equation card" holding one or more KaTeX-rendered
   formulas, shown only when the focused node is a principle with an
   `eq` array in the imported Excel data. Styled like a highlighted
   blackboard excerpt: amber text on a near-black background with a
   colored left border. */
.eq-box{
  font-size:15px; color:#F0D998; background:#1B1508; border-left:3px solid var(--principle);
  padding:12px 16px; border-radius:2px; margin:10px 0 0 0;
}
.eq-box .eq-line{ margin:4px 0; overflow-x:auto; } /* one div per equation line; horizontal scroll as a fallback for very wide formulas */
.eq-box .eq-line .katex{ color:#F0D998; } /* KaTeX renders its own colored glyphs by default — force them to match the amber theme */



/* ===============================================================================================================
   CHAPTER 5 OF 18  --  LEGEND
   ===============================================================================================================
   The row of rounded buttons at the bottom of the map: Return to root, the field selector, Node types and the
   toggles added by js/study.js.
=============================================================================================================== */

/* -----------------------------------------------------------------
   LEGEND (type filter chips + "Reset view" button)
   Bottom-left row, floating over the canvas.
----------------------------------------------------------------- */
#legend{
  position:absolute; left:28px; right:88px; bottom:24px; z-index:5;   /* right:88px leaves room for the zoom buttons */
  display:flex; gap:8px; flex-wrap:wrap; align-items:center;
}
.chip{
  display:flex; align-items:center; gap:7px;
  padding:7px 12px; border-radius:20px; border:1px solid var(--line);
  background:rgba(16,26,44,0.85); font-size:12px; cursor:pointer; user-select:none;
  color:var(--ink-dim); transition:opacity .15s;
}
.chip.active{ color:var(--ink); border-color:currentColor; } /* "on" state: chip's own type color becomes its border */
.chip .dot{ width:8px; height:8px; border-radius:50%; }
.chip.off{ opacity:0.4; } /* "off" state: filtered out, dimmed rather than hidden so it's still clickable */

#resetBtn, #unpinBtn, #viewModeBtn{
  padding:7px 14px; border-radius:20px; border:1px solid var(--line);
  background:rgba(16,26,44,0.85); font-size:12px; cursor:pointer;
  color:var(--ink-dim); font-family:'IBM Plex Mono', monospace;
}
#resetBtn:hover, #unpinBtn:hover, #viewModeBtn:hover{ color:var(--ink); border-color:var(--accent); }



/* ===============================================================================================================
   CHAPTER 6 OF 18  --  TUTORIAL / MANUAL CARD
   ===============================================================================================================
   The card that opens from the Tutorial button, with chapters that scroll sideways page by page.
=============================================================================================================== */

/* -----------------------------------------------------------------
   MANUAL / "HOW TO USE THIS GRAPH" CARD
   A small always-visible instructions card, stacked directly above
   the legend row (bottom-left). pointer-events:none because it's
   purely informational — clicks should fall through to the canvas.
----------------------------------------------------------------- */
/* The two help cards sit side by side; the dock is lifted above the legend by JS (keepManualAboveLegend). */
#helpDock{ position:absolute; left:28px; bottom:84px; z-index:5; display:flex; align-items:flex-end; gap:12px; pointer-events:none; }
#helpDock > *{ pointer-events:auto; }


/* -----------------------------------------------------------------
   SIDE PANEL — removed. All node detail (description, and for
   principles, equations) now renders directly on the canvas beneath
   the focused node; see .node-desc and .eq-box above/below, and
   updateDescOverlay() in js/app.js.
----------------------------------------------------------------- */




/* ===============================================================================================================
   CHAPTER 7 OF 18  --  CAPTIONS AND EDGE LABELS
   ===============================================================================================================
   The two-line summaries under nodes and the sentences shown on connection lines.
=============================================================================================================== */

/* -----------------------------------------------------------------
   CAPTIONS + EDGE LABELS
   .caption: two-line summary under each non-focused node's name.
   .edge-label: one-line "why connected" text on each edge.
   Both are deliberately smaller and dimmer than node names so they
   read as secondary detail, and get the same dark outline for
   legibility over lines.
----------------------------------------------------------------- */
.node text.caption{
  font-size:9.5px; font-weight:400; fill:var(--ink-dim); opacity:0.85;
  stroke-width:2.5px;
}
.node.focus text.caption{ display:none; }
/* Hovering a non-focused node: its caption grows from 9.5px to 12px, the same
   size as the focused node's label. Scaling (rather than changing font-size)
   also scales the line spacing, so the wrapped lines don't collide. */
.node:not(.focus):hover text.caption{
  transform:scale(1.2632); transform-box:fill-box; transform-origin:0 0;
  fill:var(--ink); opacity:1;
  stroke-width:5px;   /* a thicker dark outline keeps the enlarged text legible over lines and nodes behind it */
}
.node.arc-left:not(.focus):hover text.caption{ transform-origin:100% 0; }   /* captions of left-arc nodes are right-aligned: grow leftwards */
.edge-label{ pointer-events:all; cursor:pointer; user-select:none; -webkit-user-select:none; }   /* click the card to close it */
.edge-label text{ font-size:10.5px; fill:#CBD5E6; }
.edge-label-bg{ fill:rgba(16,26,44,0.96); stroke:var(--accent); stroke-width:1px; }



/* ===============================================================================================================
   CHAPTER 8 OF 18  --  TOOLBAR, EDITOR PANEL, TOAST, EMPTY STATE
   ===============================================================================================================
   The toolbar buttons, the floating node editor, the small messages ("toasts") that fade away, and what you see
   before any graph is loaded.
=============================================================================================================== */

/* -----------------------------------------------------------------
   TOOLBAR, EDITOR PANEL, TOAST, EMPTY STATE
   Import/export + add/edit controls (top right, under the search box),
   the floating node editor, status messages, and the "no data yet" card.
----------------------------------------------------------------- */
#toolbar{
  position:static; margin-left:auto; pointer-events:auto;
  display:flex; gap:8px; align-items:center;
}
#toolbar button, #emptyState button, #editor button{
  font-family:'IBM Plex Mono', monospace; font-size:11.5px; color:var(--ink-dim);
  background:rgba(16,26,44,0.9); border:1px solid var(--line); border-radius:3px;
  padding:7px 11px; cursor:pointer;
}
#toolbar button:hover:not(:disabled), #emptyState button:hover, #editor button:hover{ color:var(--ink); border-color:var(--accent); }
#toolbar button:disabled{ opacity:0.35; cursor:default; }
#exportBtn.dirty{ color:var(--principle); border-color:var(--principle); } /* unsaved edits */

#editor{
  display:none; flex-direction:column;
  position:absolute; top:150px; right:28px; z-index:12; width:350px;
  max-height:calc(100vh - 175px);
  background:var(--bg-panel); border:1px solid var(--line); border-radius:8px;
  box-shadow:0 8px 30px rgba(0,0,0,0.5);
}
.ed-head{
  display:flex; justify-content:space-between; align-items:center;
  padding:11px 14px; border-bottom:1px solid var(--line);
  font-family:'IBM Plex Mono', monospace; font-size:12px; letter-spacing:0.4px;
  text-transform:uppercase; color:var(--ink);
}
.ed-head button{ padding:2px 8px !important; }
.ed-body{ padding:12px 14px; overflow-y:auto; flex:1; }
.ed-body label{ display:block; font-size:11px; color:var(--ink-dim); margin-bottom:10px; }
.ed-body input, .ed-body select, .ed-body textarea{
  display:block; width:100%; margin-top:4px; background:var(--bg); color:var(--ink);
  border:1px solid var(--line); border-radius:3px; padding:7px 9px;
  font-family:'IBM Plex Sans', sans-serif; font-size:12.5px; outline:none; resize:vertical;
}
.ed-body textarea#edEq{ font-family:'IBM Plex Mono', monospace; font-size:11.5px; }
.ed-body input:focus, .ed-body select:focus, .ed-body textarea:focus{ border-color:var(--accent); }
.ed-hint{ color:var(--ink-dim); font-size:10.5px; font-weight:400; }
.ed-section{
  margin:14px 0 8px; padding-top:10px; border-top:1px solid var(--line);
  font-family:'IBM Plex Mono', monospace; font-size:11px; letter-spacing:0.4px;
  text-transform:uppercase; color:var(--ink-dim);
}
.conn{ margin-bottom:10px; }
.conn-head{ display:flex; align-items:center; gap:7px; font-size:12px; color:var(--ink); margin-bottom:3px; }
.conn-head .dot{ width:8px; height:8px; border-radius:50%; flex-shrink:0; }
.conn-name{ flex:1; }
.conn-kind{ font-size:10px; color:var(--ink-dim); font-family:'IBM Plex Mono', monospace; }
.conn textarea{ margin-top:0; font-size:11.5px; }
.conn-rm{ padding:1px 7px !important; }
.conn-add select{ margin-top:2px; }
.ed-error{ color:#E58A9F; font-size:11.5px; min-height:0; margin-top:6px; }
.ed-foot{ display:flex; gap:8px; padding:11px 14px; border-top:1px solid var(--line); }
#editor button.primary{ color:var(--bg); background:var(--accent); border-color:var(--accent); font-weight:600; }
#editor button.primary:hover{ color:var(--bg); background:#9BBDE8; }
#editor button.danger{ margin-left:auto; color:#E58A9F; }
#editor button.danger:hover{ border-color:#E58A9F; color:#E58A9F; }

.toast{
  display:none; position:absolute; left:50%; bottom:28px; transform:translateX(-50%);
  z-index:30; max-width:560px; padding:11px 16px; border-radius:6px; cursor:pointer;
  background:var(--bg-panel); border:1px solid var(--line); color:var(--ink);
  font-size:12.5px; line-height:1.5; box-shadow:0 6px 24px rgba(0,0,0,0.5);
}
.toast.ok{ border-color:var(--field); }
.toast.warn{ border-color:var(--principle); }
.toast.error{ border-color:var(--finding); }
.toast-x{ margin-top:6px; font-size:10.5px; color:var(--ink-dim); }

#emptyState{
  position:absolute; inset:0; z-index:4; display:flex; flex-direction:column;
  align-items:center; justify-content:center; text-align:center; gap:4px;
}
#emptyState h2{ font-family:'Fraunces', Georgia, serif; font-weight:600; font-size:22px; margin:0 0 6px 0; }
#emptyState p{ margin:0 0 14px 0; color:var(--ink-dim); font-size:13px; max-width:380px; }
#emptyState button{ font-size:13px; padding:10px 18px; color:var(--ink); border-color:var(--accent); }



/* ===============================================================================================================
   CHAPTER 9 OF 18  --  GRAPH TABS
   ===============================================================================================================
   The tabs shown when a workbook contains several graphs.
=============================================================================================================== */

/* -----------------------------------------------------------------
   GRAPH TABS (one per graph in the imported workbook)
   Sits in the header between the title block and the search box.
----------------------------------------------------------------- */
#tabs{ display:none; pointer-events:auto; }


/* ===============================================================================================================
   CHAPTER 10 OF 18  --  DROP-DOWN MENUS
   ===============================================================================================================
   The menus that open under the Edit and Learn buttons and under the graph name.
=============================================================================================================== */

/* -----------------------------------------------------------------
   DROP-DOWN MENUS (graph switcher, Edit, Learn)
   .menu = wrapper; .menu-btn = the always-visible button; .menu-panel =
   the list, shown while the wrapper has .open (toggled in
   js/app.js; closes on outside click / Esc).
----------------------------------------------------------------- */
.menu{ position:relative; pointer-events:auto; }
#toolbar .menu-btn, #tabs .menu-btn, #search{
  height:38px; box-sizing:border-box;
}
#toolbar .menu-btn, #tabs .menu-btn{
  display:inline-flex; align-items:center; line-height:1;
  font-family:'IBM Plex Mono', monospace; font-size:12px; letter-spacing:0.3px;
  color:var(--ink-dim); background:rgba(16,26,44,0.9);
  border:1px solid var(--line); border-radius:3px; padding:0 14px;
  cursor:pointer; white-space:nowrap;
}
#tabs .menu-btn{ color:var(--ink); border-color:var(--accent); background:var(--bg-panel); }
#toolbar .menu-btn:hover, .menu.open > .menu-btn{ color:var(--ink); border-color:var(--accent); }
#editMenuBtn.dirty{ color:var(--principle) !important; border-color:var(--principle) !important; } /* unsaved edits */
.menu-panel{
  display:none; position:absolute; top:calc(100% + 4px); left:0; min-width:100%; z-index:30;
  flex-direction:column; background:var(--bg-panel); border:1px solid var(--line);
  border-radius:3px; padding:4px; box-shadow:0 6px 24px rgba(0,0,0,0.5);
}
#toolbar .menu-panel{ left:auto; right:0; }
.menu.open > .menu-panel{ display:flex; }
#toolbar .menu-panel button, #tabs .menu-panel button{
  display:block; width:100%; text-align:left; white-space:nowrap;
  font-family:'IBM Plex Mono', monospace; font-size:12px; color:var(--ink-dim);
  background:transparent; border:0; border-radius:2px; padding:8px 12px; cursor:pointer;
}
#toolbar .menu-panel button:hover:not(:disabled), #tabs .menu-panel button:hover{ background:var(--field-dim); color:var(--ink); border:0; }
#toolbar .menu-panel button:disabled{ opacity:0.4; cursor:default; }
#toolbar .menu-panel button.on{ color:var(--ink); }



/* ===============================================================================================================
   CHAPTER 11 OF 18  --  STUDY LAYER
   ===============================================================================================================
   Everything the learning part adds: the notes panel, the confidence dots, the retention rings, the Review,
   Progress and Settings dialogs.
=============================================================================================================== */

/* -----------------------------------------------------------------
   STUDY LAYER (js/study.js)
   Node badges, "clean" label mode, study panel, AI output, modals
   (review / progress / settings).
----------------------------------------------------------------- */
#toolbar button.on{ color:var(--ink); border-color:var(--accent); }
#saveState{ font-size:10.5px; color:var(--ink-dim); font-family:'IBM Plex Mono', monospace; padding:0 4px; }

/* badges drawn on nodes */
.node circle.conf{ stroke:var(--bg); stroke-width:1.5px; pointer-events:none; }
.node circle.notedot{ fill:var(--ink); stroke:var(--bg); stroke-width:1.2px; pointer-events:none; }
.node.dim{ opacity:0.22; }

/* "clean" mode (Detail labels off): hide captions + edge text; a node's
   caption still appears while hovering it. */
svg.clean .caption{ display:none; }
svg.clean .node:not(.focus):hover .caption{ display:block; }

/* study panel — same slot as the editor (only one is shown at a time) */
#study{
  display:none; flex-direction:column;
  position:absolute; top:150px; right:28px; z-index:11; width:380px;
  max-height:calc(100vh - 175px);
  background:var(--bg-panel); border:1px solid var(--line); border-radius:8px;
  box-shadow:0 8px 30px rgba(0,0,0,0.5);
}
#study button, #modal button{
  font-family:'IBM Plex Mono', monospace; font-size:11.5px; color:var(--ink-dim);
  background:rgba(16,26,44,0.9); border:1px solid var(--line); border-radius:3px;
  padding:6px 10px; cursor:pointer;
}
#study button:hover:not(:disabled), #modal button:hover:not(:disabled){ color:var(--ink); border-color:var(--accent); }
#study button:disabled, #modal button:disabled{ opacity:0.45; cursor:default; }
#study .ed-head button{ padding:2px 8px; }
.st-title{ display:flex; align-items:center; gap:8px; font-size:14px; margin-bottom:8px; }
.st-title .dot, .pchip .dot{ width:8px; height:8px; border-radius:50%; flex-shrink:0; display:inline-block; }
.st-conf{ display:flex; gap:6px; }
.st-conf button{ flex:1; }
.st-conf button.sel.unseen{ color:var(--ink); border-color:var(--ink-dim); }
.st-conf button.sel.shaky{ color:#E58A3C; border-color:#E58A3C; }
.st-conf button.sel.solid{ color:#4CAF7D; border-color:#4CAF7D; }
.st-path{ display:flex; flex-wrap:wrap; gap:5px; align-items:center; }
.st-path .sep{ color:var(--ink-dim); font-size:11px; }
.pchip{ display:inline-flex !important; align-items:center; gap:6px; padding:4px 8px !important; font-family:'IBM Plex Sans',sans-serif !important; font-size:11.5px !important; }
.pc-solid{ color:#4CAF7D; } .pc-shaky{ color:#E58A3C; }
.mini{ padding:2px 8px !important; font-size:10.5px !important; margin-left:6px; }
.st-ai{ display:flex; flex-wrap:wrap; gap:6px; }

/* rendered markdown (notes preview, AI output, review cards) */
.md{ font-size:12.5px; line-height:1.6; color:#CBD5E6; }
.md p{ margin:0 0 8px 0; } .md ul, .md ol{ margin:0 0 8px 0; padding-left:20px; }
.md h5{ margin:8px 0 4px; font-size:12.5px; color:var(--ink); }
.md code{ font-family:'IBM Plex Mono',monospace; font-size:11.5px; background:var(--bg); padding:1px 4px; border-radius:2px; }
.md blockquote{ margin:0 0 8px; padding-left:10px; border-left:2px solid var(--line); color:var(--ink-dim); }
.md hr{ border:0; border-top:1px solid var(--line); }
.md .katex-display{ overflow-x:auto; overflow-y:hidden; }
#stNotePrev{ background:var(--bg); border:1px solid var(--line); border-radius:3px; padding:8px 10px; }
.ai-box{ margin-top:12px; padding:10px 12px; border:1px solid var(--line); border-left:3px solid var(--accent); border-radius:4px; background:rgba(11,18,32,0.6); }
.ai-tag{ font-family:'IBM Plex Mono',monospace; font-size:10px; text-transform:uppercase; letter-spacing:0.4px; color:var(--accent); margin-bottom:6px; }
.ai-actions{ margin-top:6px; }
.ctx summary, .ai-box details summary{ font-size:11px; color:var(--ink-dim); cursor:pointer; margin-top:6px; }
.ctx pre{ white-space:pre-wrap; font-size:10.5px; color:var(--ink-dim); max-height:160px; overflow:auto; }
.sug{ padding:8px 0; border-bottom:1px solid var(--line); } .sug:last-child{ border-bottom:0; }

/* modals */
#modal{
  display:none; position:absolute; inset:0; z-index:40; align-items:center; justify-content:center;
  background:rgba(5,9,16,0.6);
}
.md-card{
  position:relative; width:min(560px, 92vw); max-height:86vh; overflow-y:auto;
  background:var(--bg-panel); border:1px solid var(--line); border-radius:10px; padding:20px 24px;
  box-shadow:0 12px 40px rgba(0,0,0,0.6); color:var(--ink);
}
.md-card h3{ margin:0 0 10px 0; font-family:'Fraunces',Georgia,serif; font-size:18px; font-weight:600; }
.md-card label{ display:block; font-size:11px; color:var(--ink-dim); margin-bottom:10px; }
.md-card input{ display:block; width:100%; margin-top:4px; background:var(--bg); color:var(--ink); border:1px solid var(--line); border-radius:3px; padding:8px 10px; font-family:'IBM Plex Mono',monospace; font-size:12px; }
.md-x{ position:absolute; top:12px; right:14px; padding:2px 8px !important; }
.primary-b{ color:var(--bg) !important; background:var(--accent) !important; border-color:var(--accent) !important; font-weight:600; }
.danger-b{ color:#E58A3C !important; }
.card-front, .card-back{ padding:14px 16px; border:1px solid var(--line); border-radius:6px; margin-bottom:10px; background:var(--bg); }
.card-front h3{ margin:4px 0; }
.card-back{ border-left:3px solid var(--principle); }
.card-actions{ display:flex; gap:8px; align-items:center; }
.prow{ display:grid; grid-template-columns:1.3fr 2fr 0.9fr; gap:10px; align-items:center; padding:5px 4px; font-size:12.5px; }
.prow.link{ cursor:pointer; border-radius:4px; } .prow.link:hover{ background:var(--field-dim); }
.pbar{ height:8px; background:var(--line); border-radius:4px; overflow:hidden; display:flex; }
.pbar i{ display:block; height:100%; } .b-solid{ background:#4CAF7D; } .b-shaky{ background:#E58A3C; }



/* ===============================================================================================================
   CHAPTER 12 OF 18  --  EQUATIONS ATTACHED TO NODE LABELS
   ===============================================================================================================
   The golden formula blocks beside the node names.
=============================================================================================================== */

/* -----------------------------------------------------------------
   EQUATIONS ATTACHED TO NODE LABELS
   Drawn inside each node's <g>, right under its name, so they move and
   zoom with the node (see updateNodeEquations() in the app script).
----------------------------------------------------------------- */
#eqOverlay{ position:absolute; inset:0; overflow:hidden; pointer-events:none; z-index:2; }
/* Focused node's description box + figure: HTML overlay (not an SVG foreignObject,
   which Safari mis-positions). Sits above the SVG AND above the formula layer: where a description box and a node's formula
   box happen to overlap, the description box is on top and hides the formulas beneath it. */
#descOverlay{ position:absolute; inset:0; overflow:hidden; pointer-events:none; z-index:3; }
.node-desc-wrap{ position:absolute; left:0; top:0; transform-origin:0 0; pointer-events:none; }
.node-eq-lines{ position:absolute; left:0; top:0; transform-origin:0 0; display:flex; flex-direction:column; align-items:flex-start; gap:2px; will-change:transform; }
.node-eq-line{
  display:inline-block; white-space:nowrap; font-size:12.5px; line-height:1.3;
  color:#F0D998; background:rgba(27,21,8,0.9);
  border-left:2px solid var(--principle); border-radius:2px; padding:2px 8px;
}
.node-eq-line .katex{ color:#F0D998; }



/* ===============================================================================================================
   CHAPTER 13 OF 18  --  CLICKABLE EDGES
   ===============================================================================================================
   Makes the thin connection lines easy to hit with a mouse or a finger, and styles the card that explains a
   connection.
=============================================================================================================== */

/* -----------------------------------------------------------------
   CLICKABLE EDGES
   .link-hit is an invisible 14px-wide copy of each edge that receives the
   click (the visible line is only ~1px). Clicking toggles the edge's
   explanation label; the edge is highlighted while its label is shown.
----------------------------------------------------------------- */
.link-hit{ fill:none; stroke:transparent; stroke-width:14px; pointer-events:stroke; cursor:pointer; }
.link.link-active{ stroke:var(--accent); stroke-width:2px; }

/* Nodes the user placed by hand (sticky drag position). */
.node.pinned circle.core{ stroke-dasharray:3 2; }

/* New-graph dialog (graph menu -> "New graph…") and its menu item */
#tabs .menu-panel button.menu-new{ border-top:1px solid var(--line); color:var(--accent); }
.kg-modal{
  position:fixed; inset:0; z-index:50; display:flex; align-items:center; justify-content:center;
  background:rgba(5,9,18,0.6);
}
.kg-modal-card{
  width:380px; max-width:calc(100vw - 32px); padding:14px 16px;
  background:var(--bg-panel); border:1px solid var(--line); border-radius:8px;
  box-shadow:0 8px 30px rgba(0,0,0,0.5);
  max-height:calc(100vh - 32px); overflow-y:auto;
}
.kg-modal-sub{ margin:14px 0 8px; padding-top:10px; border-top:1px solid var(--line); font-size:11px; color:var(--ink-dim); }
.kg-check-list{ max-height:50vh; overflow-y:auto; margin-bottom:4px; }
.kg-check{ display:flex; align-items:center; gap:8px; margin:0 0 6px; font-size:12.5px; color:var(--ink); cursor:pointer; }
.kg-check em{ font-style:normal; font-size:10.5px; color:var(--ink-dim); margin-left:auto; padding-left:10px; }
.kg-check .kg-dot{ width:9px; height:9px; border-radius:50%; flex:none; }
.kg-modal-card input[type=checkbox]{ display:inline-block; width:auto; margin:0; }
.kg-modal-head{
  padding-bottom:10px; margin-bottom:12px; border-bottom:1px solid var(--line);
  font-family:'IBM Plex Mono', monospace; font-size:12px; letter-spacing:0.4px;
  text-transform:uppercase; color:var(--ink);
}
.kg-modal-card label{ display:block; font-size:11px; color:var(--ink-dim); margin-bottom:10px; }
.kg-modal-card input, .kg-modal-card select{
  display:block; width:100%; box-sizing:border-box; margin-top:4px; background:var(--bg); color:var(--ink);
  border:1px solid var(--line); border-radius:3px; padding:7px 9px;
  font-family:'IBM Plex Sans', sans-serif; font-size:12.5px; outline:none;
}
.kg-modal-card input:focus, .kg-modal-card select:focus{ border-color:var(--accent); }
.kg-modal-foot{ display:flex; gap:8px; margin-top:12px; }
.kg-modal-card button{
  font-family:'IBM Plex Mono', monospace; font-size:12px; padding:7px 14px; cursor:pointer;
  color:var(--ink-dim); background:var(--bg); border:1px solid var(--line); border-radius:4px;
}
.kg-modal-card button:hover{ color:var(--ink); border-color:var(--accent); }
.kg-modal-card button.primary{ color:var(--bg); background:var(--accent); border-color:var(--accent); font-weight:600; }
.kg-modal-card button.primary:hover{ color:var(--bg); background:#9BBDE8; }

/* Direction toggle on a cross-link row of the node editor. */
.conn-dir{ font-family:'IBM Plex Mono', monospace; font-size:10.5px; padding:1px 7px; margin-left:6px; cursor:pointer;
  color:var(--ink-dim); background:var(--bg); border:1px solid var(--line); border-radius:3px; }
.conn-dir:hover{ color:var(--accent); border-color:var(--accent); }

/* Halo around a node that has figure nodes attached: two soft rings in the node's own colour. */
.node .halo{ fill:none; stroke-width:1.5px; pointer-events:none; }
.node .halo1{ opacity:0.55; }
.node .halo2{ opacity:0.25; }



/* ===============================================================================================================
   CHAPTER 14 OF 18  --  ZOOM BUTTONS
   ===============================================================================================================
   The round + and - buttons in the bottom right corner.
=============================================================================================================== */

/* -----------------------------------------------------------------
   ZOOM BUTTONS (+ / −), bottom-right corner
----------------------------------------------------------------- */
#zoomCtl{
  position:absolute; right:28px; bottom:24px; z-index:6;
  display:flex; flex-direction:column; gap:6px;
}
#zoomCtl button{
  width:36px; height:36px; border-radius:50%; border:1px solid var(--line);
  background:rgba(16,26,44,0.85); color:var(--ink-dim); cursor:pointer;
  font-family:'IBM Plex Mono', monospace; font-size:20px; line-height:1; padding:0;
  display:flex; align-items:center; justify-content:center; user-select:none;
}
#zoomCtl button:hover{ color:var(--ink); border-color:var(--accent); }
#zoomCtl button:active{ transform:scale(0.94); }


/* ===============================================================================================================
   CHAPTER 15 OF 18  --  LATER ADDITIONS: stacking order, figure editor, gap report, tutorial pictures
   ===============================================================================================================
   A collection of smaller rule groups added later. Each begins with an original comment that says what it is for:
   which element lies on top of which while hovering, the live figure preview in the node editor, the "How to
   construct a figure" card, the names-only mode, the gap report, and the look-alike pictures in the tutorial.
   The stacking order matters here: z-index decides which element is in front, so a hovered description can be
   read over the others.
=============================================================================================================== */

/* While a non-centred node is hovered, its enlarged description (inside the SVG) must read on top of the centred node's
   description box: the box (an HTML overlay normally above the SVG) drops beneath the SVG and fades a little. */
#app.hover-caption #descOverlay{ z-index:0; opacity:0.35; transition:opacity .12s; }
/* The formula layer (other nodes' equations) goes beneath the SVG too, and fades, so the hovered description is in front of it. */
#app.hover-caption #eqOverlay{ z-index:0; opacity:0.3; transition:opacity .12s; }

/* Clicked edge card: in front of the focused node's description box and of all formulas. */
#app.edge-open #descOverlay, #app.edge-open #eqOverlay{ z-index:0; opacity:0.3; transition:opacity .12s; }

/* While a parent search is active the editor's parent selector is an open list: let it grow to show its rows
   (the normal drop-down style fixes its height, which hid every match but the first). */
.ed-body select[size]:not([size="1"]){ height:auto; padding:3px; }
.ed-body select[size]:not([size="1"]) option{ padding:5px 8px; }
.ed-field{ margin-bottom:10px; }
.ed-field > label{ display:block; font-size:11px; color:var(--ink-dim); }

/* A figure box can be clicked to close it. (The overlay itself ignores the mouse; only the box takes clicks.) */
.node-desc.fig-closable{ pointer-events:auto; cursor:pointer; }

/* Live figure preview inside the node editor (follows the figure formula as it is typed). */
.ed-figprev{ margin:2px 0 8px; }
.ed-figprev .fig-svg{ width:100%; max-width:300px; height:auto; }

/* "Show the figure as" selector in the node editor */
.ed-seg{ display:flex; gap:0; }
.ed-seg button{ flex:1; padding:6px 8px; font-size:11px; border-radius:0; border:1px solid var(--line, #2a3550); background:transparent; color:var(--ink-dim); cursor:pointer; }
.ed-seg button:first-child{ border-radius:6px 0 0 6px; } .ed-seg button:last-child{ border-radius:0 6px 6px 0; } .ed-seg button + button{ border-left:0; }
.ed-seg button.on{ background:rgba(240,217,152,.16); color:#F0D998; border-color:#F0D998; }
.ed-seg button:disabled{ opacity:.35; cursor:default; }

.ed-param{ display:flex; gap:6px; align-items:center; margin-top:5px; font-size:11px; color:var(--ink-dim); }
.ed-param > span{ min-width:48px; }
.ed-param input{ width:56px; flex:none; }
.ed-param select{ flex:1; min-width:0; }
.ed-coordnames{ margin-top:6px; font-size:11px; color:var(--ink-dim); display:flex; gap:6px; align-items:center; }
.ed-coordnames input{ width:60px; }

/* Figure section of the node editor: the "How to construct a figure" manual with worked examples, and the note for a ready-made figure. */
.ed-note{ margin:2px 0 8px; padding:8px 10px; font-size:11.5px; line-height:1.45; color:var(--ink-dim);
  border:1px solid var(--line, #2a3550); border-left:3px solid #F0D998; border-radius:6px; background:rgba(240,217,152,.06); }
.ed-note b{ color:var(--ink); }
.ed-manual{ margin:4px 0 10px; border:1px solid var(--line, #2a3550); border-radius:8px; background:rgba(255,255,255,.02); }
.ed-manual > summary{ cursor:pointer; padding:7px 10px; font-size:12px; font-weight:600; color:#F0D998; }
.ed-manual-body{ padding:2px 10px 10px; font-size:11.5px; line-height:1.5; color:var(--ink-dim); }
.ed-manual-body p{ margin:6px 0; } .ed-manual-body ol{ margin:6px 0 6px 18px; padding:0; } .ed-manual-body li{ margin-bottom:4px; }
.ed-manual-body b{ color:var(--ink); } .ed-manual-body code{ font-size:11px; color:#F0D998; background:rgba(255,255,255,.05); padding:0 3px; border-radius:3px; }
.ed-ex{ display:grid; grid-template-columns:112px 1fr; gap:10px; margin-top:8px; padding:8px; border:1px solid var(--line, #2a3550); border-radius:8px; background:rgba(0,0,0,.18); }
.ed-ex-pic .fig-svg{ width:100%; height:auto; } .ed-ex-txt{ font-size:11px; line-height:1.45; min-width:0; }
.ed-ex-txt b{ color:var(--ink); font-size:12px; } .ed-ex-txt .katex{ font-size:1em; }
.ed-ex-use{ margin-top:5px; padding:3px 9px; font-size:11px; border-radius:5px; border:1px solid #F0D998; background:transparent; color:#F0D998; cursor:pointer; }
.ed-ex-use:hover{ background:rgba(240,217,152,.16); }
/* the active kind of plot must win over the general editor button style (which has an id in its selector) */
#editor .ed-seg button.on{ background:rgba(240,217,152,.16); color:#F0D998; border-color:#F0D998; }
#editor .ed-ex-use{ background:transparent; color:#F0D998; border:1px solid #F0D998; }
#editor .ed-ex-use:hover{ background:rgba(240,217,152,.16); }

/* "How to construct a figure": a tutorial card whose pages (overview, four worked examples, "your turn") scroll sideways. */
.tut{ position:relative; background:rgba(16,26,44,0.97); border:1px solid var(--line); border-radius:8px; padding:14px 18px; width:440px; max-width:calc(100vw - 80px); outline:none; }
.tut h4{ margin:0 0 8px 0; font-family:'IBM Plex Mono', monospace; font-size:11px; letter-spacing:0.4px; color:var(--ink-dim); text-transform:uppercase;
  display:flex; align-items:center; justify-content:space-between; gap:8px; cursor:pointer; user-select:none; }
.tut h4:hover{ color:var(--ink); }
.tut .tut-arrow{ font-size:10px; transition:transform .2s ease; flex-shrink:0; }
.tut.collapsed{ width:auto; cursor:pointer; }
.tut.collapsed h4{ margin-bottom:0; }
.tut.collapsed .tut-body{ display:none; }
.tut.collapsed .tut-arrow{ transform:rotate(-90deg); }
.tut-pages{ display:flex; overflow-x:auto; overflow-y:hidden; scroll-snap-type:x mandatory; scroll-behavior:smooth; scrollbar-width:none; border-radius:6px; }
.tut-pages::-webkit-scrollbar{ display:none; }
.fg-page{ flex:0 0 100%; scroll-snap-align:start; box-sizing:border-box; padding:2px 4px 2px 0; overflow-y:auto; font-size:12px; line-height:1.5; color:var(--ink-dim); }
.fg-page h5{ margin:2px 0 6px; font-size:15px; font-weight:600; color:var(--ink); }
.fg-page b{ color:var(--ink); font-weight:600; } .fg-page code{ font-size:11px; color:#F0D998; background:rgba(255,255,255,.05); padding:0 3px; border-radius:3px; }
.fg-kicker{ font-family:'IBM Plex Mono', monospace; font-size:10px; letter-spacing:.4px; color:#F0D998; text-transform:uppercase; }
.fg-page ol{ margin:6px 0 6px 18px; padding:0; } .fg-page li{ margin-bottom:5px; } .fg-page p{ margin:6px 0; }
.fg-pic{ margin:6px auto 8px; max-width:300px; } .fg-pic .fig-svg{ width:100%; height:auto; display:block; }
.fg-steps{ width:100%; border-collapse:collapse; margin:4px 0 6px; }
.fg-steps td{ padding:4px 6px; vertical-align:top; border-top:1px solid var(--line, #2a3550); } .fg-steps td:first-child{ width:92px; color:#F0D998; font-size:11px; white-space:nowrap; }
.fg-steps .katex{ font-size:1em; color:var(--ink); }
.fg-alts{ display:flex; gap:10px; margin:6px 0 8px; } .fg-alt{ flex:1; text-align:center; font-size:10.5px; } .fg-alt .fig-svg{ width:100%; height:auto; display:block; }
.fg-use{ margin:4px 0 2px; padding:5px 12px; font-size:11.5px; border-radius:6px; border:1px solid #F0D998; background:transparent; color:#F0D998; cursor:pointer; }
.fg-use:hover{ background:rgba(240,217,152,.16); } .fg-msg{ margin-top:4px; font-size:11px; color:#F0D998; min-height:1em; }
.tut-nav{ display:flex; align-items:center; justify-content:space-between; gap:8px; margin-top:8px; }
.tut-nav button{ width:32px; height:28px; font-size:18px; line-height:1; border-radius:6px; border:1px solid var(--line, #2a3550); background:rgba(16,26,44,.9); color:var(--ink-dim); cursor:pointer; }
.tut-nav button:hover:not(:disabled){ color:var(--ink); border-color:var(--accent, #F0D998); } .tut-nav button:disabled{ opacity:.3; cursor:default; }
.tut-dots{ display:flex; gap:7px; align-items:center; }
.tut-dots i{ width:8px; height:8px; border-radius:50%; background:#2a3550; cursor:pointer; transition:background .15s, transform .15s; } .tut-dots i.on{ background:#F0D998; transform:scale(1.25); }
.tut-pages{ max-height:var(--fg-maxh, 420px); }
.fg-dir{ display:grid; grid-template-columns:110px 1fr; gap:10px; align-items:center; margin:6px 0 8px; padding:8px; border:1px solid var(--line, #2a3550); border-radius:8px; background:rgba(0,0,0,.18); font-size:11.5px; }
.fg-dir .fig-svg{ width:100%; height:auto; display:block; } .fg-dir .katex{ font-size:1em; color:var(--ink); }

/* editor figure steps: plane choice (step 4) */
.ed-plane{ display:block; margin:3px 0; font-size:11.5px; color:var(--ink-dim); cursor:pointer; line-height:1.4; }
.ed-plane input{ margin-right:6px; accent-color:#F0D998; } .ed-plane.off{ opacity:.5; }
#edVecRow label, #edScalarRow{ display:block; margin-bottom:6px; } #edVecRow label span, #edScalarRow span{ display:block; font-size:11px; color:var(--ink-dim); margin-bottom:3px; }
#edVecRow input{ width:100%; box-sizing:border-box; }
#editor .ed-plane input[type=radio]{ display:inline-block; width:auto; margin:0 6px 0 0; vertical-align:middle; padding:0; }

/* the instructions card ("How to use this graph") is a tutorial card too: the sixteen instructions are grouped into pages */
.tut-list{ margin:6px 0 0; padding-left:16px; } .tut-list li{ margin-bottom:9px; } .tut-list li:last-child{ margin-bottom:0; }
.tut .fg-page{ padding-bottom:4px; }
.tut-list + .fg-use{ margin-top:12px; }

/* "Hide details" (self-test) mode: names only. Formulas of every node but the clicked (centred) one are hidden, and captions never show,
   not even on hover. visibility (not display) so nothing is laid out differently. The clicked node's description box is unaffected. */
#app.hide-details .eq-other{ visibility:hidden; }
#app.hide-details svg .caption, #app.hide-details svg .node:not(.focus):hover .caption{ display:none; }

/* Source line under a description. width:0 + min-width:100% keeps a long source from widening the (max-content) description box. */
.node-source{ width:0; min-width:100%; box-sizing:border-box; margin-top:8px; padding-top:6px; border-top:1px solid var(--line); font-size:10.5px; line-height:1.45; color:var(--ink-dim); overflow-wrap:anywhere; pointer-events:auto; }
.node-source a{ color:var(--accent); }
.node-desc > .node-source:first-child{ margin-top:0; padding-top:0; border-top:0; }
/* "Highlight gaps": dotted red ring around nodes with a gap */
.node circle.gapring{ fill:none; stroke:#F87171; stroke-width:1.8; stroke-dasharray:1.5 3.5; stroke-linecap:round; pointer-events:none; }
/* Gap report */
.gap-card{ width:600px; }
.gap-sub{ margin:0 0 10px; font-size:11.5px; color:var(--ink-dim); line-height:1.5; }
.gap-kind{ border-top:1px solid var(--line); padding:6px 0; }
.gap-kind summary{ display:flex; align-items:center; gap:8px; cursor:pointer; font-size:12.5px; color:var(--ink); list-style:none; }
.gap-kind summary::-webkit-details-marker{ display:none; }
.gap-kind summary::before{ content:"\25B8"; color:var(--ink-dim); font-size:10px; }
.gap-kind[open] summary::before{ content:"\25BE"; }
.gap-kind summary em{ margin-left:auto; font-style:normal; font-size:11px; color:var(--ink-dim); }
.gap-kind summary em.has{ color:#F87171; }
.gap-items{ display:flex; flex-wrap:wrap; gap:4px 6px; padding:8px 0 4px 22px; }
.gap-items button{ background:var(--bg); color:var(--ink); border:1px solid var(--line); border-radius:3px; padding:2px 7px; font-size:11.5px; cursor:pointer; }
.gap-items button:hover{ border-color:var(--accent); }
.gap-pair{ width:100%; font-size:11.5px; color:var(--ink-dim); }
.gap-more{ font-size:11px; color:var(--ink-dim); }

/* "How to use this graph": lookalike pictures at the top of each page (see manualVisual in app.js). Nothing in them is clickable. */
.tut .fg-page{ max-height:calc(100vh - 250px); }
.vis{ pointer-events:none; user-select:none; margin:8px 0 12px; padding:10px; border:1px solid var(--line); border-radius:8px; background:rgba(8,14,26,.65); font-family:'IBM Plex Mono', monospace; }
.vis-row{ display:flex; flex-wrap:wrap; gap:8px 12px; align-items:flex-start; }
.vis-row + .vis-row{ margin-top:10px; }
.vis-cell{ display:flex; flex-direction:column; align-items:center; gap:3px; }
.vis-inner{ display:flex; gap:4px; align-items:center; }
.vis-n{ width:15px; height:15px; border-radius:50%; background:#F0D998; color:#0b1220; font-size:9.5px; font-weight:700; display:flex; align-items:center; justify-content:center; }
.vis-cap{ font-size:9.5px; line-height:1.35; color:var(--ink-dim); }
.vis-cap-l{ margin:0 0 4px; }
.vis-btn{ display:inline-flex; align-items:center; height:30px; box-sizing:border-box; padding:0 11px; font-size:11px; letter-spacing:.3px; color:var(--ink-dim); background:rgba(16,26,44,.9); border:1px solid var(--line); border-radius:3px; white-space:nowrap; }
.vis-graph{ color:var(--ink); border-color:var(--accent); background:var(--bg-panel); }
.vis-primary{ color:var(--bg); background:var(--accent); border-color:var(--accent); }
.vis-danger{ color:#F87171; border-color:#7a3a3a; }
.vis-status{ font-size:10.5px; color:var(--ink-dim); padding:6px 4px; display:inline-block; }
.vis-status.warn{ color:#F0D998; }
.vis-search{ display:inline-flex; align-items:center; width:170px; height:30px; box-sizing:border-box; padding:0 10px; font-size:11px; color:var(--ink-dim); background:var(--bg-panel); border:1px solid var(--line); border-radius:3px; }
.vis-search-s{ width:130px; }
.vis-menus{ display:flex; gap:12px; align-items:flex-start; margin-top:12px; flex-wrap:wrap; }
.vis-panel{ min-width:150px; padding:4px; background:var(--bg-panel); border:1px solid var(--line); border-radius:3px; box-shadow:0 4px 14px rgba(0,0,0,.4); }
.vis-panel-t{ font-size:9.5px; letter-spacing:.5px; text-transform:uppercase; color:var(--ink-dim); padding:3px 8px 5px; border-bottom:1px solid var(--line); margin-bottom:3px; }
.vis-item{ padding:5px 8px; font-size:10.5px; color:var(--ink-dim); border-radius:2px; white-space:nowrap; }
.vis-item.hi{ background:var(--field-dim); color:var(--ink); }
.vis-chips{ display:flex; flex-wrap:wrap; gap:6px; margin:6px 0 10px; }
.vis .chip{ cursor:default; font-size:11px; padding:5px 10px; }
.vis-syms{ display:grid; grid-template-columns:1fr 1fr; gap:4px 10px; margin-bottom:10px; }
.vis-sym{ display:flex; align-items:center; gap:6px; font-size:10px; line-height:1.3; color:var(--ink-dim); }
.vis-sym svg{ flex:0 0 40px; }
.vis-line{ display:flex; align-items:center; gap:10px; margin-top:8px; }
.vis-demo{ flex:0 0 auto; min-width:150px; display:flex; }
.vis-desc{ font-family:'IBM Plex Sans', sans-serif; font-size:11.5px; line-height:1.4; color:var(--ink-dim); }
.vis-pill{ padding:6px 13px; border-radius:20px; border:1px solid var(--line); background:rgba(16,26,44,.85); font-size:11px; color:var(--ink-dim); white-space:nowrap; }
.vis-zoomdemo{ gap:6px; }
.vis-zoom{ width:30px; height:30px; border-radius:50%; border:1px solid var(--line); background:rgba(16,26,44,.85); color:var(--ink-dim); font-size:17px; display:inline-flex; align-items:center; justify-content:center; }
.vis-editor{ margin-top:6px; padding:8px 10px 10px; border:1px solid var(--line); border-radius:6px; background:var(--bg-panel); }
.vis-grid{ display:grid; grid-template-columns:1fr 1fr; gap:6px 10px; }
.vis-fld{ display:flex; flex-direction:column; gap:2px; margin-top:6px; } .vis-grid .vis-fld{ margin-top:0; }
.vis-fld > span{ font-size:9.5px; color:var(--ink-dim); }
.vis-in{ min-height:22px; box-sizing:border-box; padding:4px 7px; font-size:10.5px; color:var(--ink-dim); background:rgba(255,255,255,.04); border:1px solid var(--line); border-radius:3px; }
.vis-in.tall{ min-height:40px; }
.vis-card{ padding:7px 12px; border:1px solid var(--line); border-radius:6px; background:rgba(16,26,44,.97); font-size:10px; letter-spacing:.4px; text-transform:uppercase; color:var(--ink-dim); white-space:nowrap; }
.vis-states{ display:flex; flex-direction:column; gap:6px; }
.vis-state{ display:flex; flex-direction:column; }
.vis-nav{ display:flex; align-items:center; justify-content:center; gap:10px; margin-top:12px; }
.vis-dots{ display:flex; gap:6px; } .vis-dots i{ width:7px; height:7px; border-radius:50%; background:#33415e; } .vis-dots i.on{ background:#F0D998; }

/* Tutorial: chapter list + chapter view */
.tut-menu{ display:flex; flex-direction:column; gap:6px; max-height:var(--fg-maxh, 420px); overflow-y:auto; scrollbar-width:thin; }
.tut-menu[hidden], #tutChapter[hidden]{ display:none; }
.tut-intro{ margin:0 0 4px; font-size:12px; color:var(--ink-dim); }
.tut-chap{ display:flex; align-items:center; gap:12px; width:100%; box-sizing:border-box; text-align:left; padding:7px 11px; border:1px solid var(--line); border-radius:8px; background:rgba(255,255,255,.03); color:var(--ink); cursor:pointer; font-family:inherit; }
.tut-chap:hover{ border-color:#F0D998; background:rgba(240,217,152,.07); }
.tut-no{ flex:0 0 24px; width:24px; height:24px; border-radius:50%; background:#F0D998; color:#0b1220; font:700 12px 'IBM Plex Mono', monospace; display:flex; align-items:center; justify-content:center; }
.tut-chap.seen .tut-no{ background:transparent; border:1px solid #F0D998; color:#F0D998; }
.tut-ct{ flex:1; display:flex; flex-direction:column; gap:1px; min-width:0; }
.tut-ct b{ font-size:13px; font-weight:600; color:var(--ink); }
.tut-ct i{ font-style:normal; font-size:11px; color:var(--ink-dim); }
.tut-pc{ font-size:10.5px; color:var(--ink-dim); font-family:'IBM Plex Mono', monospace; }
.tut-bar{ display:flex; align-items:center; gap:10px; margin-bottom:6px; }
.tut-back{ padding:4px 10px; font-size:11.5px; border-radius:6px; border:1px solid var(--line); background:transparent; color:var(--ink-dim); cursor:pointer; font-family:'IBM Plex Mono', monospace; }
.tut-back:hover{ color:var(--ink); border-color:#F0D998; }
.tut-crumb{ font-size:11px; color:var(--ink-dim); font-family:'IBM Plex Mono', monospace; }
.vis-solo{ display:inline-block; padding:6px 12px; border-radius:3px; }

/* small choice dialog (where the study notes go, Save as) */
.choice-card{ width:420px; }
.choice-opts{ display:flex; flex-direction:column; gap:8px; margin-top:6px; }
.choice-opts button{ text-align:left; padding:10px 14px; border:1px solid var(--line); border-radius:6px; background:rgba(255,255,255,.03); color:var(--ink); cursor:pointer; font-size:13px; }
.choice-opts button.dflt{ border-color:var(--accent); background:rgba(125,168,255,.10); }
.choice-opts button:hover{ border-color:#F0D998; background:rgba(240,217,152,.07); }
.choice-opts small{ display:block; margin-top:2px; font-size:11px; color:var(--ink-dim); }


/* ===============================================================================================================
   CHAPTER 16 OF 18  --  MODE SWITCH (Graph | Table) AND TABLE MODE
   ===============================================================================================================
   The Graph / Table switch and every rule of table mode: the filter row, the editable cells, the status icons and
   the phone version where rows become cards.
=============================================================================================================== */

/* -----------------------------------------------------------------
   MODE SWITCH (Graph | Table) and TABLE MODE
----------------------------------------------------------------- */
#modeSwitch{ display:none; pointer-events:auto; height:38px; box-sizing:border-box; border:1px solid var(--line); border-radius:3px; overflow:hidden; background:rgba(16,26,44,.9); }
#modeSwitch button{ height:100%; padding:0 14px; border:0; background:transparent; color:var(--ink-dim); font-family:'IBM Plex Mono', monospace; font-size:12px; letter-spacing:.3px; cursor:pointer; }
#modeSwitch button + button{ border-left:1px solid var(--line); }
#modeSwitch button:hover{ color:var(--ink); }
#modeSwitch button.on{ background:var(--field-dim); color:var(--ink); }
body.mode-table #canvas, body.mode-table #eqOverlay, body.mode-table #descOverlay, body.mode-table #legend, body.mode-table #zoomCtl{ display:none; }
#tableView{ display:none; position:absolute; top:84px; left:0; right:0; bottom:0; z-index:4; flex-direction:column; padding:0 28px 76px; box-sizing:border-box; }
body.mode-table #tableView{ display:flex; }
.tv-bar{ display:flex; align-items:center; gap:14px; flex-wrap:wrap; padding:6px 0 10px; }
.tv-tabs{ display:flex; gap:4px; }
.tv-tabs button{ padding:7px 14px; border:1px solid var(--line); border-radius:3px; background:rgba(16,26,44,.9); color:var(--ink-dim); font-family:'IBM Plex Mono', monospace; font-size:12px; cursor:pointer; }
.tv-tabs button em{ font-style:normal; color:var(--ink-dim); opacity:.7; margin-left:4px; }
.tv-tabs button.on{ color:var(--ink); border-color:var(--accent); background:var(--bg-panel); }
.tv-ctl{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.tv-ctl select, .tv-ctl button, .tv-chk{ height:30px; box-sizing:border-box; padding:0 10px; border:1px solid var(--line); border-radius:3px; background:rgba(16,26,44,.9); color:var(--ink-dim); font-family:'IBM Plex Mono', monospace; font-size:11.5px; cursor:pointer; }
.tv-chk{ display:inline-flex; align-items:center; gap:6px; }
.tv-ctl button:hover, .tv-ctl select:hover{ color:var(--ink); border-color:var(--accent); }
.tv-ctl .tv-add{ color:var(--ink); border-color:var(--accent); }
.tv-chip{ color:var(--ink) !important; border-color:#F0D998 !important; }
.tv-count{ margin-left:auto; font-size:11.5px; color:var(--ink-dim); font-family:'IBM Plex Mono', monospace; }
.tv-scroll{ flex:1; min-height:0; overflow:auto; border:1px solid var(--line); border-radius:6px; background:rgba(10,17,30,.92); }
table.tv{ border-collapse:separate; border-spacing:0; width:100%; min-width:1000px; table-layout:fixed; font-size:12.5px; }
table.tv th{ position:sticky; top:0; z-index:2; background:var(--bg-panel); text-align:left; font-weight:600; font-size:11px; letter-spacing:.4px; text-transform:uppercase; color:var(--ink-dim); padding:9px 8px; border-bottom:1px solid var(--line); cursor:pointer; white-space:nowrap; user-select:none; }
table.tv th.c-eq, table.tv th.c-act, table.tv th.c-arrow{ cursor:default; }
table.tv th:hover{ color:var(--ink); }
.srt{ margin-left:5px; color:#F0D998; font-size:9px; }
table.tv td{ padding:4px 6px; border-bottom:1px solid rgba(42,58,84,.55); vertical-align:top; }
table.tv tr:hover td{ background:rgba(124,168,224,.05); }
table.tv tr.sel td{ background:rgba(240,217,152,.08); }
table.tv tr.sel td:first-child{ box-shadow:inset 3px 0 0 #F0D998; }
.tv-nodes .c-name{ width:20%; } .tv-nodes .c-type{ width:10%; } .tv-nodes .c-par{ width:14%; } .tv-nodes .c-desc{ width:21%; } .tv-nodes .c-eq{ width:14%; } .tv-nodes .c-src{ width:8%; } .tv-nodes .c-n{ width:4%; } .tv-nodes .c-act{ width:9%; }
.tv-links .c-from{ width:22%; } .tv-links .c-arrow{ width:4%; text-align:center; color:var(--ink-dim); } .tv-links .c-kind{ width:10%; } .tv-links .c-rel{ width:36%; } .tv-links .c-act{ width:6%; }
.cell{ width:100%; box-sizing:border-box; background:transparent; border:1px solid transparent; border-radius:3px; color:var(--ink); font-family:'IBM Plex Sans', sans-serif; font-size:12.5px; padding:5px 6px; outline:none; }
textarea.cell{ resize:vertical; line-height:1.4; height:42px; overflow:hidden; display:block; }
.cell:hover:not(:disabled){ border-color:var(--line); }
.cell:focus{ border-color:var(--accent); background:rgba(124,168,224,.07); }
.cell:disabled{ color:var(--ink-dim); opacity:.7; }
select.cell{ background:var(--bg-panel); }
textarea.cell.gap{ border-color:rgba(248,113,113,.45); border-style:dotted; }
textarea.cell.mono, .cell.mono{ font-family:'IBM Plex Mono', monospace; font-size:11px; }
.nm{ display:flex; align-items:center; gap:4px; }
.nm .dot{ flex:0 0 10px; width:10px; height:10px; border-radius:50%; background:var(--tc); }
.nm .tg, .nm .tg0{ flex:0 0 18px; width:18px; }
.nm .tg{ border:0; background:transparent; color:var(--ink-dim); cursor:pointer; font-size:11px; padding:0; }
.nm .tg:hover{ color:var(--ink); }
tr.figrow .nm .dot{ box-shadow:0 0 0 2px rgba(240,217,152,.5); }
.eqprev{ font-size:11.5px; color:var(--ink); padding:2px 6px 0; overflow:hidden; max-height:46px; }
.eqprev .katex{ font-size:1em; } code.eqerr{ color:#F87171; font-size:10.5px; }
.c-n button, .c-act button, .c-arrow button{ border:1px solid var(--line); background:transparent; color:var(--ink-dim); border-radius:3px; cursor:pointer; font-size:12px; min-width:24px; height:24px; padding:0 5px; }
.c-n button:hover, .c-act button:hover:not(:disabled), .c-arrow button:hover:not(:disabled){ color:var(--ink); border-color:var(--accent); }
.c-arrow button:disabled{ opacity:.3; cursor:default; }
.c-act{ white-space:nowrap; } .c-act button + button{ margin-left:3px; }
.kb{ display:inline-block; padding:2px 8px; border-radius:10px; font-size:10.5px; font-family:'IBM Plex Mono', monospace; border:1px solid var(--line); color:var(--ink-dim); }
.kb.cross{ color:#F0D998; border-color:rgba(240,217,152,.5); } .kb.hier{ color:var(--ink-dim); }
tr.lr.hier td{ opacity:.9; }
tr.addrow td{ background:rgba(240,217,152,.05); border-bottom:1px solid rgba(240,217,152,.25); }

/* tutorial picture: the Graph | Table switch and a small table */
.vis-seg{ display:inline-flex; height:30px; border:1px solid var(--line); border-radius:3px; overflow:hidden; font-size:11px; }
.vis-seg span{ display:flex; align-items:center; padding:0 11px; color:var(--ink-dim); } .vis-seg span + span{ border-left:1px solid var(--line); }
.vis-seg span.on{ background:var(--field-dim); color:var(--ink); }
.vis-tbl{ margin-top:10px; border:1px solid var(--line); border-radius:6px; overflow:hidden; font-size:11px; }
.vis-tr{ display:grid; grid-template-columns:1.25fr .7fr 1.6fr; gap:8px; padding:6px 9px; border-top:1px solid var(--line); color:var(--ink); }
.vis-tr:first-child{ border-top:0; } .vis-th{ background:var(--bg-panel); color:var(--ink-dim); font-size:9.5px; letter-spacing:.4px; text-transform:uppercase; }
.vis-tr span{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; color:var(--ink-dim); } .vis-tr span:first-child{ color:var(--ink); }
.vis-d{ display:inline-block; width:8px; height:8px; border-radius:50%; margin-right:6px; }
.vis-tr .vis-edit{ color:var(--ink); outline:1px solid var(--accent); border-radius:3px; padding:0 4px; margin:-2px 0; }

/* table mode: nothing to show */
.tv-none{ padding:26px 16px; text-align:center; color:var(--ink-dim); font-size:12.5px; }
.tv-none button{ margin-left:8px; padding:4px 10px; border:1px solid var(--line); border-radius:4px; background:transparent; color:var(--ink); cursor:pointer; }
.tv-none button:hover{ border-color:#F0D998; }

/* the (sub)field menu in the graph's bottom row (same pill look as Return to root) */
.fld-sel{ display:inline-flex; align-items:center; gap:7px; padding:0 6px 0 14px; height:34px; box-sizing:border-box; border-radius:20px; border:1px solid var(--line); background:rgba(16,26,44,0.85); color:var(--ink-dim); font-family:'IBM Plex Mono', monospace; font-size:12px; cursor:pointer; }
.fld-sel:hover{ color:var(--ink); border-color:var(--accent); }
.fld-sel select{ max-width:190px; text-overflow:ellipsis; background:transparent; border:0; color:var(--ink); font:inherit; padding:6px 4px; cursor:pointer; outline:none; }
.fld-sel select option{ background:var(--bg-panel); color:var(--ink); }

/* LaTeX shown typeset until clicked; a click swaps in the source text */
.eqwrap textarea.cell{ display:none; }
.eqwrap.edit textarea.cell{ display:block; }
.eqwrap.edit .eqprev{ display:none; }
.eqwrap .eqprev, .ed-eqprev{ cursor:text; border:1px solid transparent; border-radius:3px; min-height:26px; box-sizing:border-box; }
.eqwrap .eqprev{ padding:5px 6px; max-height:90px; overflow:auto; }
.eqwrap .eqprev:hover, .ed-eqprev:hover{ border-color:var(--line); }
.eqwrap .eqprev:focus-visible, .ed-eqprev:focus-visible{ outline:none; border-color:var(--accent); }
.eqwrap .eqprev.empty::before{ content:attr(data-ph); color:var(--ink-dim); font-size:11px; opacity:.7; }
textarea.eq-off{ display:none !important; }
.ed-eqprev{ display:block; margin-top:4px; padding:7px 8px; max-height:160px; overflow:auto; background:rgba(124,168,224,.05); border:1px solid var(--line); font-size:13px; }

/* Node-type filter: one button, its tick list opens upwards */
.tm-wrap{ position:relative; }
#typeMenuBtn{ padding:7px 14px; border-radius:20px; border:1px solid var(--line); background:rgba(16,26,44,0.85); font-size:12px; cursor:pointer; color:var(--ink-dim); font-family:'IBM Plex Mono', monospace; }
#typeMenuBtn:hover, .tm-wrap.open #typeMenuBtn{ color:var(--ink); border-color:var(--ink-dim); }
#typeMenuBtn.filtered{ color:var(--ink); border-color:var(--accent); }
.tm-panel{ display:none; position:absolute; left:0; bottom:calc(100% + 8px); min-width:190px; padding:6px; border:1px solid var(--line); border-radius:10px; background:rgba(16,26,44,0.97); box-shadow:0 8px 24px rgba(0,0,0,.45); z-index:20; }
.tm-wrap.open .tm-panel{ display:block; }
.tm-row{ display:flex; align-items:center; gap:8px; padding:6px 8px; border-radius:6px; font-size:12px; cursor:pointer; user-select:none; }
.tm-row:hover{ background:rgba(124,168,224,.10); }
.tm-row input{ margin:0; accent-color:currentColor; cursor:pointer; }
.tm-row .dot{ width:8px; height:8px; border-radius:50%; flex:none; }
.tm-row .tm-name{ color:var(--ink); }
.tm-fake{ position:relative; display:inline-block; padding-bottom:4px; }
.tm-fake-panel{ margin-top:6px; padding:4px; border:1px solid var(--line); border-radius:10px; background:rgba(16,26,44,0.97); min-width:170px; }
.tm-fake-panel .tm-row{ cursor:default; padding:4px 8px; }
/* the tutorial card is for the graph; table mode does not show it */
body.mode-table #helpDock{ display:none; }
#legend{ z-index:6; }   /* above the tutorial card, so the open Node types list is never covered by it */

/* every control of the legend row has the same height */
#legend > *, #legend #typeMenuBtn{ box-sizing:border-box; height:32px; }
#legend > button, #legend > .chip, #legend #typeMenuBtn{ display:inline-flex; align-items:center; padding-top:0; padding-bottom:0; line-height:1; }
#legend > .tm-wrap{ height:32px; }
#legend > .fld-sel{ height:32px; }
#legend .fld-sel select{ padding-top:0; padding-bottom:0; }

/* name and parent: two rows, wrapped, like the description box */
.nm{ align-items:center; }
.nm textarea.cell{ flex:1 1 auto; min-width:0; resize:none; }
.parwrap .parview{ box-sizing:border-box; height:42px; padding:5px 6px; border:1px solid transparent; border-radius:3px; line-height:1.4; font-size:12.5px; color:var(--ink); overflow:hidden; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; word-break:break-word; cursor:text; }
.parwrap .parview:hover{ border-color:var(--line); }
.parwrap .parview:focus-visible{ outline:none; border-color:var(--accent); }
.parwrap .parview.empty::before{ content:attr(data-ph); color:var(--ink-dim); opacity:.7; }
.parwrap.ro .parview{ cursor:default; color:var(--ink-dim); }
.parwrap.ro .parview:hover{ border-color:transparent; }
.parwrap input.cell{ display:none; }
.parwrap.edit input.cell{ display:block; }
.parwrap.edit .parview{ display:none; }
table.tv th, table.tv td{ box-sizing:border-box; }
.tv-nodes .c-act button{ min-width:21px; padding:0 3px; } .tv-nodes .c-act button + button{ margin-left:2px; } .tv-nodes td.c-act{ padding-left:3px; padding-right:3px; }


/* ===============================================================================================================
   CHAPTER 17 OF 18  --  REVIEW CARD, QUICK ADD BAR, INBOX AND HISTORY ROWS
   ===============================================================================================================
   The review card (typed answer, four grade buttons, hints), the quick-add bar (Alt+N) and the rows in the inbox
   and version history lists.
=============================================================================================================== */

/* ===== review card (typed answer, four grades, hints) ===== */
.card-typed, #olText, #ibText{ width:100%; box-sizing:border-box; background:var(--bg); color:var(--ink); border:1px solid var(--line); border-radius:6px; padding:8px 10px; font:inherit; font-size:13px; resize:vertical; margin:0 0 10px; }
.card-typed:focus, #olText:focus, #ibText:focus{ outline:none; border-color:var(--accent); }
.card-actions{ flex-wrap:wrap; }
.card-actions.grades button{ display:inline-flex; flex-direction:column; align-items:center; gap:1px; min-width:74px; }
.card-actions.grades small{ opacity:.7; font-size:10.5px; }
#modal kbd{ font:10px 'IBM Plex Mono', monospace; border:1px solid var(--line); border-radius:3px; padding:0 4px; margin-left:4px; color:var(--ink-dim); }
#modal button.suggest{ box-shadow:0 0 0 2px var(--accent); }
b.ok{ color:#4CAF7D; } b.miss{ color:#E58A3C; }
.fcast{ display:flex; gap:6px; align-items:flex-end; margin:6px 0 12px; height:92px; }
.fcast > div{ flex:1; display:flex; flex-direction:column; align-items:center; justify-content:flex-end; gap:2px; font-size:10.5px; color:var(--ink-dim); }
.fcast i{ display:block; width:100%; max-width:34px; background:var(--accent); opacity:.75; border-radius:3px 3px 0 0; }
.fcast b{ color:var(--ink); font-weight:500; }
.pstats{ display:grid; grid-template-columns:repeat(4,1fr); gap:8px; margin:6px 0 8px; }
.pstats > div{ border:1px solid var(--line); border-radius:6px; padding:8px 6px; text-align:center; background:var(--bg); }
.pstats b{ display:block; font-size:20px; font-weight:600; } .pstats span{ font-size:10.5px; color:var(--ink-dim); }
.prow.weak{ cursor:pointer; }
circle.heat{ pointer-events:none; }
/* ===== quick add bar ===== */
#quickAdd{ display:none; position:fixed; left:50%; transform:translateX(-50%); bottom:84px; width:min(560px, calc(100vw - 24px)); z-index:40; background:var(--bg-panel); border:1px solid var(--accent); border-radius:10px; padding:8px 10px; box-shadow:0 8px 28px rgba(0,0,0,.5); }
#quickAdd.open{ display:block; }
#quickAdd .qa-row{ display:flex; gap:8px; align-items:center; }
#quickAdd input{ flex:1; min-width:0; background:var(--bg); color:var(--ink); border:1px solid var(--line); border-radius:6px; padding:8px 10px; font:inherit; font-size:14px; }
#quickAdd input:focus{ outline:none; border-color:var(--accent); }
#quickAdd .qa-where{ font-size:11px; color:var(--ink-dim); max-width:38%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
#quickAdd .qa-hint{ font-size:10.5px; color:var(--ink-dim); margin-top:5px; }
#quickAdd .mini{ background:none; border:1px solid var(--line); color:var(--ink-dim); border-radius:6px; padding:6px 9px; cursor:pointer; }
/* ===== inbox and history rows ===== */
.ib-item{ display:flex; gap:10px; align-items:flex-start; justify-content:space-between; border:1px solid var(--line); border-radius:6px; padding:8px 10px; margin:6px 0; background:var(--bg); }
.ib-text{ flex:1; min-width:0; white-space:pre-wrap; overflow-wrap:anywhere; font-size:13px; }
.ib-act{ display:flex; gap:6px; flex:none; }


/* ===============================================================================================================
   CHAPTER 18 OF 18  --  PHONE AND TOUCH
   ===============================================================================================================
   Everything that changes on a touch screen or a small one: bigger buttons, the bottom navigation, sheets that
   slide up, the Today screen and the table as cards. Selectors start with body.phone, body.tablet or body.touch,
   which js/mobile.js switches on.
=============================================================================================================== */

/* ===================================================================
   PHONE AND TOUCH  (classes set by js/mobile.js)
   =================================================================== */
html, body{ overscroll-behavior:none; }
#app{ height:100vh; height:100dvh; }
button, .chip, select, summary{ touch-action:manipulation; }
#phoneNav, #legendToggle, #today{ display:none; }

/* touch: fingers need bigger targets, and iOS zooms into inputs below 16px */
html.touch #toolbar button, html.touch #emptyState button, html.touch #editor button, html.touch #study button, html.touch #modal button, html.touch .menu-panel button{ min-height:42px; }
html.touch .chip, html.touch #typeMenuBtn{ min-height:40px; }
html.touch #zoomCtl button{ width:44px; height:44px; }
html.touch input, html.touch select, html.touch textarea{ font-size:16px !important; }
html.touch .tm-row{ min-height:42px; }
html.touch .tv .cell, html.touch .tv select{ min-height:40px; }
html.touch .tv td button{ min-width:40px; min-height:40px; }

/* phone */
body.phone{ --nav-h:calc(58px + env(safe-area-inset-bottom, 0px)); }
body.phone #phoneNav{ display:flex; position:fixed; left:0; right:0; bottom:0; z-index:60; height:var(--nav-h); padding-bottom:env(safe-area-inset-bottom, 0px); background:var(--bg-panel); border-top:1px solid var(--line); }
body.phone #phoneNav button{ flex:1; position:relative; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1px; background:none; border:0; color:var(--ink-dim); font:11px 'IBM Plex Mono', monospace; min-height:0; padding:4px 0; cursor:pointer; }
body.phone #phoneNav button i{ font-style:normal; font-size:20px; line-height:1; }
body.phone #phoneNav button.on{ color:var(--accent); }
body.phone #phoneNav b{ position:absolute; top:4px; left:calc(50% + 8px); min-width:16px; padding:0 4px; border-radius:8px; background:#E58A3C; color:#0B1220; font:600 10px sans-serif; line-height:16px; text-align:center; }
body.phone #app{ height:calc(100dvh - var(--nav-h)); }
body.phone header{ padding:calc(8px + env(safe-area-inset-top, 0px)) 10px 0 10px; gap:8px; }
body.phone h1{ font-size:17px; }
body.phone .subtitle, body.phone #saveState, body.phone #modeSwitch{ display:none !important; }
body.phone #toolbar{ margin-left:auto; flex-wrap:nowrap; gap:6px; }
body.phone #searchWrap{ display:none; flex:1 1 100%; } body.phone.search-open #searchWrap{ display:block; } body.phone #search{ width:100%; box-sizing:border-box; }
body.phone #helpDock{ display:none; }
body.phone #legendToggle{ display:flex; align-items:center; justify-content:center; position:fixed; left:12px; bottom:calc(var(--nav-h) + 12px); z-index:20; width:44px; height:44px; border-radius:50%; border:1px solid var(--line); background:rgba(16,26,44,.92); color:var(--ink); font-size:18px; cursor:pointer; }
body.phone #legend{ display:none; position:fixed; left:8px; right:8px; bottom:calc(var(--nav-h) + 64px); z-index:25; padding:10px; border:1px solid var(--line); border-radius:12px; background:var(--bg-panel); box-shadow:0 10px 30px rgba(0,0,0,.55); max-height:50dvh; overflow-y:auto; }
body.phone.legend-open #legend{ display:flex; }
body.phone #legend > *{ flex:1 1 auto; justify-content:center; }
body.phone #zoomCtl{ right:12px; bottom:12px; }
body.phone #quickAdd{ bottom:calc(var(--nav-h) + 8px + var(--kb, 0px)); }
body.phone.legend-open #zoomCtl{ display:none; }
/* panels become bottom sheets that stay above the keyboard */
body.phone #editor, body.phone #study{ position:fixed; left:0; right:0; top:auto; width:auto; bottom:calc(var(--nav-h) + var(--kb, 0px)); max-height:calc(var(--vvh, 100dvh) - var(--nav-h) - 56px); border-radius:16px 16px 0 0; z-index:50; }
body.phone #modal{ position:fixed; align-items:flex-end; }
body.phone .md-card{ width:100%; max-width:none; max-height:calc(var(--vvh, 100dvh) - var(--nav-h) - 16px); border-radius:16px 16px 0 0; padding:18px 16px 18px; box-sizing:border-box; }
body.phone #modal{ bottom:max(var(--kb, 0px), var(--nav-h)); }   /* above the navigation; above the keyboard when it is open */
body.phone .card-actions{ gap:6px; } body.phone .card-actions button{ flex:1 1 40%; }
body.phone .card-actions.grades button{ min-width:0; flex:1 1 22%; }
body.phone .pstats{ grid-template-columns:repeat(2,1fr); }
body.phone .menu-panel{ max-height:calc(var(--vvh, 100dvh) - 140px); overflow-y:auto; }
/* Today */
body.phone.today-open #today{ display:block; position:fixed; inset:0; z-index:55; overflow-y:auto; background:var(--bg); padding:calc(16px + env(safe-area-inset-top, 0px)) 16px calc(var(--nav-h) + 16px); box-sizing:border-box; }
#today .td-card{ max-width:520px; margin:0 auto; }
#today h2{ font-family:'Fraunces', Georgia, serif; font-size:26px; margin:6px 0 10px; }
#today h3{ font-size:13px; letter-spacing:.4px; text-transform:uppercase; color:var(--ink-dim); margin:22px 0 8px; font-weight:500; }
#today .td-big{ display:flex; align-items:baseline; gap:10px; margin:6px 0 12px; } #today .td-big b{ font-size:54px; font-weight:600; line-height:1; } #today .td-big span{ color:var(--ink-dim); }
#today button{ font:13px 'IBM Plex Mono', monospace; color:var(--ink); background:var(--bg-panel); border:1px solid var(--line); border-radius:10px; padding:12px 14px; cursor:pointer; min-height:46px; }
#today button:disabled{ opacity:.5; }
#today .td-main{ width:100%; font-size:16px; padding:16px; }
#today .td-row{ display:flex; gap:8px; margin-top:8px; } #today .td-row button{ flex:1; }
#today textarea{ width:100%; box-sizing:border-box; background:var(--bg-panel); color:var(--ink); border:1px solid var(--line); border-radius:10px; padding:10px 12px; font:16px inherit; resize:vertical; }
#today .td-link{ background:none; border:0; color:var(--accent); text-decoration:underline; margin-top:14px; }
/* the table as cards */
body.phone #tableView{ top:var(--hdr-h, 110px); bottom:0; padding:0 8px 8px; }   /* #app already ends above the navigation */
body.phone .tv{ display:block; width:100% !important; min-width:0 !important; }
body.phone .tv thead{ display:none; } body.phone .tv tbody{ display:block; }
body.phone .tv tbody tr{ display:grid; grid-template-columns:1fr 1fr; gap:8px 10px; margin:8px; padding:10px; border:1px solid var(--line); border-radius:10px; background:rgba(16,26,44,.6); }
body.phone .tv td{ display:block; width:auto !important; padding:0 !important; border:0 !important; min-width:0; }
body.phone .tv td::before{ display:block; font-size:10px; letter-spacing:.4px; text-transform:uppercase; color:var(--ink-dim); margin-bottom:2px; }
body.phone .tv td.c-name, body.phone .tv td.c-desc, body.phone .tv td.c-eq, body.phone .tv td.c-src, body.phone .tv td.c-rel, body.phone .tv td.c-act{ grid-column:1 / -1; }
body.phone .tv-nodes td.c-name::before{ content:"Name"; } body.phone .tv-nodes td.c-type::before{ content:"Type"; } body.phone .tv-nodes td.c-par::before{ content:"Parent"; }
body.phone .tv-nodes td.c-desc::before{ content:"Description"; } body.phone .tv-nodes td.c-eq::before{ content:"Equations"; } body.phone .tv-nodes td.c-src::before{ content:"Source"; } body.phone .tv-nodes td.c-n::before{ content:"Links"; }
body.phone .tv td.c-from:first-of-type::before{ content:"From"; } body.phone .tv td.c-rel::before{ content:"Why connected"; } body.phone .tv td.c-kind::before{ content:"Kind"; }
body.phone .tv td.c-act{ display:flex; gap:8px; } body.phone .tv td.c-act button{ flex:1; }

/* phone header: two compact rows (title + graph menu; undo, redo, Edit, Learn, search) */
#searchToggle{ display:none; }
body.phone #searchToggle{ display:inline-flex; align-items:center; justify-content:center; min-width:42px; }
body.phone h1 .accent{ display:none; }
body.phone header{ row-gap:6px; padding-bottom:6px; }
body.phone .title-block{ min-width:0; flex:1 1 auto; } body.phone h1{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:56vw; }
body.phone #toolbar button{ padding:7px 9px; min-height:40px; }
body.phone.mode-table #legendToggle, body.phone.today-open #legendToggle{ display:none; }
body.phone #phoneNav button.on{ background:rgba(124,168,224,.12); }
/* table controls: one scrolling row instead of a tall wrapped block */
body.phone .tv-bar{ flex-direction:column; align-items:stretch; flex-wrap:nowrap; gap:6px; padding:6px 0; }
body.phone .tv-tabs, body.phone .tv-ctl{ flex-wrap:nowrap; overflow-x:auto; gap:6px; padding-bottom:2px; -webkit-overflow-scrolling:touch; }
body.phone .tv-tabs > *, body.phone .tv-ctl > *{ flex:none; }
body.phone .tv-count{ display:none; }
body.phone .tv-scroll{ flex:1; min-height:0; border-radius:10px; }
body.phone #phoneNav button:hover{ background:none; } body.phone #phoneNav button.on, body.phone #phoneNav button.on:hover{ background:rgba(124,168,224,.12); }
#modal .primary-b kbd{ color:inherit; border-color:currentColor; opacity:.75; }

/* KaTeX writes every formula twice: typeset, and as hidden MathML for screen readers. If KaTeX's own stylesheet is missing (vendor/ not
   copied, offline without a cache) the MathML copy would show as a second line of plain text and make every formula block far too wide,
   which also shrinks the fitted view. This is the one rule that must never be missing. */
.katex .katex-mathml{ position:absolute !important; clip:rect(1px,1px,1px,1px); padding:0; border:0; height:1px; width:1px; overflow:hidden; }
