/* @flatppl/web — gallery shell layout + theming. */

:root {
  --bg:        #1e1e1e;
  --bg-pane:   #252526;
  --bg-header: #2d2d30;
  --fg:        #cccccc;
  --fg-muted:  #858585;
  --border:    #3c3c3c;
  --accent:    #007acc;
  --mono: ui-monospace, 'Cascadia Code', 'JetBrains Mono', 'Source Code Pro',
          Menlo, Consolas, monospace;
}

html, body {
  margin: 0; padding: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  width: 100%; height: 100%;
  overflow: hidden;
}

/* Three-pane shell: header bar across the top, then file tree /
   source view / viewer side-by-side, separated by drag handles.
   The grid-template-columns starting value is overridden by
   layout.js once it loads (which restores the user's persisted
   widths from localStorage) — the value here is the bootstrap
   default that applies during the brief window before layout.js
   runs, plus a no-JS fallback. */
#app {
  display: grid;
  grid-template-rows: 36px 1fr;
  grid-template-columns: 240px 5px 1fr 5px 1.5fr;
  width: 100vw;
  height: 100vh;
}

/* Pin every pane and handle to an explicit grid column so that
   `display: none` on the file pane (collapse) doesn't auto-shift
   the remaining items into the now-empty cells. */
#files-pane                                 { grid-column: 1; grid-row: 2; }
.resize-handle[data-resize="files-source"]  { grid-column: 2; grid-row: 2; }
#source-pane                                { grid-column: 3; grid-row: 2; }
.resize-handle[data-resize="source-viewer"] { grid-column: 4; grid-row: 2; }
#viewer-pane                                { grid-column: 5; grid-row: 2; }

#app-header {
  grid-column: 1 / -1;
  background: var(--bg-header);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 0.6em;
  padding: 0 1em;
  font-weight: 600;
  letter-spacing: 0.02em;
}

#toggle-files,
#nav-back,
#nav-forward {
  background: transparent;
  color: var(--fg-muted);
  border: none;
  font-size: 1.1em;
  line-height: 1;
  padding: 0.2em 0.4em;
  cursor: pointer;
  border-radius: 3px;
}
#toggle-files:hover,
#nav-back:hover,
#nav-forward:hover { color: var(--fg); background: rgba(255,255,255,0.05); }
#toggle-files:focus,
#nav-back:focus,
#nav-forward:focus { outline: 1px solid var(--accent); outline-offset: 1px; }
#nav-back, #nav-forward { font-size: 1.3em; padding: 0 0.35em; }

/* Drag handles between adjacent panes. Thin column inside the grid;
   colour-shift on hover so the user can see they're interactive. */
.resize-handle {
  background: var(--bg-pane);
  cursor: col-resize;
  user-select: none;
  /* Keep the visible band narrower than the actual hit-target so
     the user can grab without pixel-perfect aiming. */
  position: relative;
}
.resize-handle::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--border);
  transition: background 0.15s ease;
}
.resize-handle:hover::before {
  background: var(--accent);
}

.pane {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  background: var(--bg-pane);
  border-right: 1px solid var(--border);
}
.pane:last-child { border-right: none; }

.pane-header {
  background: var(--bg-header);
  border-bottom: 1px solid var(--border);
  padding: 0.4em 1em;
  font-size: 0.78em;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--fg-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Variant of .pane-header that holds inline children (currently the
   source pane's title + right-aligned toolbar buttons). The plain
   text-style rules above still apply; the flex layout governs the
   horizontal distribution of the children. */
.pane-header--row {
  display: flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.2em 1em;
}
.pane-header-text {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Buttons inside a pane header (e.g. the "Visualize whole module"
   action). Visual style matches the header chrome — quiet by
   default, lights up on hover. */
.pane-header button {
  background: transparent;
  border: none;
  padding: 2px 4px;
  border-radius: 3px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--fg);
  opacity: 1;
}
.pane-header button:hover { background: rgba(255,255,255,0.07); }
.pane-header button:focus { outline: 1px solid var(--accent); outline-offset: 1px; }
.pane-header button img { display: block; }
.pane-header button[aria-pressed="true"] {
  background: rgba(13, 113, 199, 0.55);
  color: #fff;
}
.pane-header button[hidden] { display: none; }

.pane-body {
  flex: 1 1 auto;
  overflow: auto;
  position: relative;
}

.pane-placeholder {
  color: var(--fg-muted);
  font-style: italic;
  font-size: 0.9em;
  padding: 0.8em;
}

#file-tree { padding: 0.5em 0; }

.file-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.file-list-item {
  padding: 0.4em 1em;
  cursor: pointer;
  font-size: 0.9em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  user-select: none;
}
.file-list-item:hover    { background: #2a2d2e; }
.file-list-item.selected {
  background: #094771;
  color: #ffffff;
}

/* "Unsaved" section header above ephemeral entries. */
.file-list-header {
  padding: 0.8em 1em 0.2em;
  font-size: 0.75em;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  opacity: 0.6;
  user-select: none;
}

/* Ephemeral entries get italicised + a soft accent so they stand out
   from on-disk manifest entries. The session-only nature should be
   visually obvious at a glance. */
.file-list-item--ephemeral {
  font-style: italic;
}
.file-list-item--ephemeral::before {
  content: '* ';
  opacity: 0.5;
}

#source-view {
  margin: 0;
  padding: 1em;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.45;
  white-space: pre;
  tab-size: 4;
  color: var(--fg);
}

/* Per-line wrapper emitted by the syntax highlighter — addressable
   target for the DAG → source flash + scroll path (host adapter
   revealSourceLine). Inline by default so the wrapper itself adds
   nothing visual; the .src-line-flash class drives a brief background
   flash via CSS animation. The trailing newline lives outside the
   wrapper so copy-paste preserves it under <pre>. */
.src-line { display: inline; }
.src-line.src-line-flash {
  animation: src-line-flash 1.5s ease-out;
  border-radius: 2px;
}
@keyframes src-line-flash {
  0%   { background: rgba(255, 235, 100, 0.45); }
  100% { background: transparent; }
}

/* Token palette. Roughly tracks VS Code's Dark+ for familiarity, with
   one FlatPPL-specific addition — `tok-ident-binding` (identifiers
   that resolve to a binding in the current module) is rendered with
   its own colour and a hover affordance, so users can tell which
   names in the source map to nodes in the DAG view. The click handler
   that turns this into actual cross-pane navigation lands in step 1.6. */
.tok-comment        { color: #6a9955; font-style: italic; }
.tok-string         { color: #ce9178; }
.tok-number         { color: #b5cea8; }
.tok-op             { color: #d4d4d4; }
.tok-punct          { color: #d4d4d4; }
.tok-placeholder    { color: #9cdcfe; }
.tok-hole           { color: #9cdcfe; }
.tok-ident          { color: #9cdcfe; }
.tok-ident-binding  { color: #4ec9b0; }
.tok-ident-binding:hover {
  text-decoration: underline;
  cursor: pointer;
}
.tok-keyword   { color: #c586c0; }   /* and, or, not, in, true/false (variant kwds) */
.tok-special   { color: #c586c0; }   /* draw, lawof, fn, …  */
.tok-mop       { color: #c586c0; }   /* weighted, joint, … */
.tok-dist      { color: #4fc1ff; }   /* Normal, Poisson, … */
.tok-set       { color: #569cd6; }   /* reals, interval,    */
.tok-const     { color: #569cd6; }   /* true, pi, inf, im   */
.tok-func      { color: #dcdcaa; }   /* exp, log, sum, …    */
.tok-reserved  { color: #c586c0; }   /* self, base, flatppl_compat */

/* The viewer manages its own internal scroll and resize, so the
   right pane's body must not introduce a second scrollbar. */
#viewer-pane > .pane-body { overflow: hidden; }

/* Playground mode (CodeMirror editor mounted in the source pane).
   The editor handles its own scrolling, so the pane-body shouldn't
   add another scrollbar of its own. */
#source-pane.playground > .pane-body { overflow: hidden; }
#source-editor { width: 100%; height: 100%; }
.cm-editor { height: 100%; }

#flatppl-viewer-root {
  width: 100%;
  height: 100%;
  /* The viewer was originally written for the VS Code webview, where
     it occupies the full panel — its outermost #main child uses
     viewport units (100vw, calc(100vh - 86px)) to size itself.
     Embedded inside the gallery's right pane, those viewport values
     overflow the column, pushing the DAG and plot content off to the
     right. The rules below override the viewer's outer layout
     (#header / #main / #info) into a flex column that fills
     #flatppl-viewer-root instead of the viewport. Selector
     specificity (0,2,0,0 vs the viewer's 0,1,0,0) makes the override
     win without !important. */
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
#flatppl-viewer-root > #header,
#flatppl-viewer-root > #info {
  flex: 0 0 auto;
}
#flatppl-viewer-root > #main {
  flex: 1 1 auto;
  width: 100%;     /* override viewer's 100vw */
  height: auto;    /* override viewer's calc(100vh - 86px) */
  min-height: 0;
  min-width: 0;
}
