/* UMind (https://pponec.github.io/UMind/) — Apache License 2.0 */
/* UMind — outliner styling.
   Hierarchy is conveyed purely by CSS indentation + vertical guide lines.
   No connector lines in the MVP (see assignment §2). */

:root {
  --bg: #ffffff;
  --fg: #1f2328;
  --muted: #6b7280;
  --guide: #d0d7de;
  --accent: #2563eb;
  --focus-bg: #eef4ff;
  --toolbar-bg: #f6f8fa;
  --border: #d0d7de;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0d1117;
    --fg: #e6edf3;
    --muted: #8b949e;
    --guide: #30363d;
    --accent: #58a6ff;
    --focus-bg: #161b22;
    --toolbar-bg: #161b22;
    --border: #30363d;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: var(--fg);
  background: var(--bg);
  font-size: 15px;
  line-height: 1.5;
}

/* ---- Toolbar ---- */
.toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  background: var(--toolbar-bg);
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  z-index: 10;
}
.brand-logo { height: 32px; width: auto; border-radius: 6px; flex: none; cursor: zoom-in; transform: translateY(-2px); }

/* Full-size logo viewer (opened by clicking the toolbar logo). */
.logo-dialog { border: none; background: transparent; padding: 0; max-width: 92vw; max-height: 92vh; }
.logo-dialog::backdrop { background: rgba(0, 0, 0, 0.7); }
.logo-dialog img { display: block; max-width: 100%; max-height: 100%; width: auto; height: auto; cursor: zoom-out; border-radius: 12px; }
.brand {
  color: var(--accent);
  font-family: Arial, Helvetica, sans-serif;
  font-weight: 800;
  font-size: 38px;
  line-height: 1;
  letter-spacing: 0.3px;
  margin-right: 14px; /* extra breathing room before the action buttons */
  text-decoration: none; /* it is now an <a> to the home page */
  cursor: pointer;
}
.brand:hover { text-decoration: underline; }
.spacer { flex: 1; }
.status { color: var(--muted); font-size: 13px; min-width: 60px; }
.file-name {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 12px;
  color: var(--fg);
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.file-name.unbound { color: var(--muted); font-style: italic; }

button {
  font: inherit;
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--fg);
  cursor: pointer;
}
button:hover { border-color: var(--accent); }
button:active { background: var(--focus-bg); }

/* ---- Workspace: outline (left) + detail panel (right) ---- */
.workspace {
  display: flex;
  align-items: flex-start;
  gap: 0;
}
main {
  flex: 0 1 auto;         /* hug the outline so the panel sits beside the tree */
  min-width: 0;
  padding: 18px 20px 40px;
}
.outline { width: 620px; max-width: 100%; }

/* ---- Detail panel (floating, pinned to the top of the viewport) ---- */
.detail {
  flex: none;
  width: 340px;
  /* Height follows the content, not the (tall) column, so the sticky offset
     has room to work and the panel stays pinned while the outline scrolls. */
  align-self: flex-start;
  position: sticky;
  top: 61px; /* toolbar height + a small gap so it reads as floating */
  max-height: calc(100vh - 73px);
  overflow: auto;
  margin: 12px 12px 0 0;
  padding: 16px 18px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--toolbar-bg);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.12);
}
.detail-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}
.detail-title {
  margin: 0;
  font-size: 1.05em;
  line-height: 1.3;
  word-break: break-word;
}
.detail-body.empty { color: var(--muted); }
.detail-body .hint kbd { margin: 0 1px; }

/* Basic Markdown rendering inside the detail panel. */
.markdown { font-size: 14px; line-height: 1.6; }
.markdown > :first-child { margin-top: 0; }
.markdown > :last-child { margin-bottom: 0; }
.markdown h1,
.markdown h2,
.markdown h3 { margin: 1em 0 0.4em; line-height: 1.25; }
.markdown h1 { font-size: 1.3em; }
.markdown h2 { font-size: 1.15em; }
.markdown h3 { font-size: 1.02em; }
.markdown p { margin: 0.6em 0; }
.markdown ul,
.markdown ol { margin: 0.5em 0; padding-left: 1.4em; }
/* Restore list markers: the global `ul { list-style: none }` (for the outline
   tree) otherwise strips bullets from Markdown lists too. */
.markdown ul { list-style: disc; }
.markdown ol { list-style: decimal; }
.markdown li { margin: 0.2em 0; list-style: inherit; }
.markdown a { color: var(--accent); }
.markdown code {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.9em;
  padding: 1px 4px;
  border-radius: 4px;
  background: var(--bg);
  border: 1px solid var(--border);
}
.markdown blockquote {
  margin: 0.6em 0;
  padding: 2px 0 2px 12px;
  border-left: 3px solid var(--guide);
  color: var(--muted);
}

/* In-panel description editor (replaces the old modal dialog). */
.detail-editor {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* An author `display` beats the UA `[hidden]{display:none}`, so restore it. */
.detail-editor[hidden] { display: none; }
#detail-note-text {
  width: 100%;
  min-height: 140px;
  font-family: inherit;
  font-size: 14px;
  line-height: 1.5;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--fg);
  padding: 10px;
  resize: vertical;
  box-sizing: border-box;
}
.detail-editor .note-actions button.secondary { background: var(--bg); }

/* The grip handle belongs to the mobile bottom sheet only; hidden on desktop
   where the panel is a fixed floating column. */
.detail-grip { display: none; }

/* On narrow screens the detail panel is a bottom SHEET that is always present
   for the focused node and sizes ITSELF to the content: a short note gives a
   short sheet, a long one grows up to half the screen (the default cap) and
   then scrolls. The grip drags it taller (to read a long note / edit) or down
   to a thin bar (to see the tree). So the note is readable at once, with no
   drag needed for the common case. A constant bottom reserve keeps the scroll
   height stable (no jumping) and lets the focused row clear the sheet. */
@media (max-width: 760px) {
  .workspace { flex-direction: column; }
  .detail {
    width: auto;
    align-self: stretch;
    position: fixed;
    /* Clear the desktop rule's `top: 61px`; with both top and bottom set on a
       fixed box `top` would win and dock the sheet at the TOP over the tree. */
    top: auto;
    left: 8px;
    right: 8px;
    bottom: 8px;
    z-index: 40;
    margin: 0;
    height: auto;               /* fit the content... */
    max-height: 50vh;           /* ...up to half the screen, then scroll */
    overflow-y: auto;
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.28);
    transition: max-height 0.2s ease;
    padding: 6px 14px calc(10px + env(safe-area-inset-bottom, 0px));
  }
  /* Grip pulled up: more room for a long note / the editor + keyboard. An
     explicit height (not just max-height) is needed because the default sheet
     is content-fit (height: auto) — without it a note shorter than the screen
     would keep its content height and the drag-up / expand would do nothing. */
  .detail.expanded,
  .detail.editing { height: 85vh; max-height: 85vh; }
  /* Grip pulled down: a thin bar (just the title) to get the tree back. */
  .detail.collapsed { height: 64px; max-height: 64px; }

  /* Constant bottom reserve (independent of the sheet's height, so the scroll
     height never changes as the note length varies — that constancy is what
     stops the view from jumping while navigating). Sized to the sheet's cap so
     any row can be scrolled clear of even a half-screen sheet. */
  main { padding-bottom: calc(50vh + 16px); }

  /* Tighter internals on the sheet. */
  .detail-head { margin-bottom: 6px; }
  .detail-title {
    font-size: 0.98em;
    cursor: pointer; /* tap the title to collapse / restore */
  }
  .detail-body.markdown { font-size: 13px; }

  /* Draggable pill at the top edge — the affordance that says "grab me".
     A wider transparent hit area makes it easy to grab; user-select/touch-action
     off so dragging it resizes the sheet instead of selecting text or scrolling. */
  .detail-grip {
    display: block;
    width: 36px;
    height: 4px;
    margin: 0 auto 8px;
    border-radius: 3px;
    background: var(--guide);
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
    padding: 8px 40px;
    background-clip: content-box;
    box-sizing: content-box;
  }
}

ul {
  list-style: none;
  margin: 0;
  padding-left: 26px;
}
/* The top-level list holds only the root node, flush to the left. */
ul.outline-root { padding-left: 0; }

/* Nested lists draw the vertical guide line that shows depth. */
li > ul {
  border-left: 1px solid var(--guide);
  margin-left: 9px;
}

li { position: relative; }

/* Node text + its description marker on one line. The node shrinks to its
   text so the marker sits right after it (not at the far right edge). */
.row {
  position: relative;
  display: flex;
  align-items: baseline;
}

.node {
  position: relative;
  flex: 0 1 auto;
  min-width: 0;
  padding: 3px 6px 3px 26px;
  border-radius: 5px;
  outline: none;
  white-space: pre-wrap;
  word-break: break-word;
  min-height: 1.5em;
  cursor: text;
  /* Keep a focused row clear of the sticky toolbar when the browser scrolls it
     into view (native focus scroll honours scroll-margin). Clearing the mobile
     bottom sheet is handled separately, in JS (revealFocusedRow). */
  scroll-margin-top: 52px;
}

/* Bullet handle before each node. Its centre (left 8 + width 6 -> 11px) is
   shared with the collapse toggle so leaves and branches line up per level. */
.node::before {
  content: "";
  position: absolute;
  left: 8px;
  top: 0.72em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--muted);
}

/* Collapse/expand toggle, sitting in the gutter to the left of the bullet.
   z-index lifts it above the (position:relative) node, which follows it in
   the DOM and would otherwise capture the click and start text editing. */
.toggle {
  position: absolute;
  left: 1px;      /* width 20 -> centre at 11px, matching the bullet */
  top: 2px;
  z-index: 2;
  width: 20px;
  height: 22px;
  padding: 0;
  font-size: 15px;
  line-height: 22px;
  text-align: center;
  color: var(--muted);
  background: transparent;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
.toggle:hover {
  color: var(--fg);
  background: var(--focus-bg);
}

/* On branches with a toggle the bullet is redundant, so hide it. */
.node.has-children::before { display: none; }

/* The root ("central topic") reads as the title. */
.node.root {
  font-weight: 600;
  font-size: 1.15em;
}
.node.root::before { display: none; }

.node:focus {
  background: var(--focus-bg);
  box-shadow: inset 0 0 0 1px var(--accent);
}

/* Description marker: a separate, non-editable element beside the node text
   (kept out of the contenteditable so editing never displaces it). The glyph
   is emitted in text presentation by the JS, so `color` can darken it — the
   colour emoji is too light to read on a highlighted row. */
.note-mark {
  flex: none;
  margin-left: 12px;
  color: var(--fg);
  opacity: 0.85;
  font-size: 0.95em;
  cursor: pointer;
  user-select: none;
}
.note-mark:hover { opacity: 1; }

/* ---- Drag and drop (optional; remove together with the JS DnD block) ---- */
.drag-grip {
  position: absolute;
  left: -18px;
  top: 3px;
  width: 16px;
  height: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  line-height: 1;
  color: var(--muted);
  cursor: grab;
  opacity: 0;
  user-select: none;
}
li:hover > .row > .drag-grip { opacity: 0.6; }
.drag-grip:hover { opacity: 1; }
.drag-grip:active { cursor: grabbing; }
.row.dragging { opacity: 0.45; }

/* Drop indicator: an accent line above (before) or below (after) the row. */
.row.drop-before::before,
.row.drop-after::after {
  content: "";
  position: absolute;
  left: 26px;
  right: 6px;
  height: 2px;
  background: var(--accent);
  border-radius: 1px;
  pointer-events: none;
}
.row.drop-before::before { top: -1px; }
.row.drop-after::after { bottom: -1px; }
/* "after" an expanded branch means "first child": indent the line to show it. */
.row.drop-after.drop-into::after { left: 52px; }

/* ---- Description dialog ---- */
.note-dialog {
  width: min(560px, 92vw);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0;
  background: var(--bg);
  color: var(--fg);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
}
.note-dialog::backdrop {
  background: rgba(0, 0, 0, 0.45);
}
.note-dialog form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px 20px;
}
.note-heading { margin: 0; font-size: 1.1em; }
.note-subject { margin: 0; color: var(--muted); font-size: 13px; }
.note-subject span { color: var(--fg); font-weight: 600; }
.name-input {
  width: 100%;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 14px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--fg);
  padding: 8px 10px;
}
#note-text {
  width: 100%;
  min-height: 160px;
  font-family: inherit;
  font-size: 14px;
  line-height: 1.5;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--fg);
  padding: 10px;
  resize: vertical;
}
.note-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  margin: 0;
  padding: 0;
}
.note-hint {
  margin-right: auto;
  color: var(--muted);
  font-size: 12px;
}
.note-hint kbd { margin: 0 1px; }
.note-actions button.primary {
  border-color: var(--accent);
  background: var(--accent);
  color: #fff;
}
.note-actions button.primary:hover { filter: brightness(1.05); }

/* ---- Help footer ---- */
.help {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  padding: 10px 20px 24px;
  color: var(--muted);
  font-size: 13px;
}
kbd {
  font-family: inherit;
  border: 1px solid var(--border);
  border-bottom-width: 2px;
  border-radius: 4px;
  padding: 0 5px;
  background: var(--toolbar-bg);
  font-size: 12px;
}
.persist-note { flex-basis: 100%; }
.persist-note code {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.92em;
}

/* ---- Graph view (URL ".../?project/graph") ----
   The exported picture hosted in the app's own chrome: the toolbar keeps the
   logo, the wordmark and the project name, and swaps the editing buttons for
   "Edit map". The sheet is shown at its natural size and scrolls; it is wider
   than any window on all but the smallest maps. */
.graph {
  padding: 0;
  overflow-x: auto;          /* the sheet scrolls, the page body never does */
  background: #ffffff;       /* the picture is always light, whatever the theme */
}
/* An author `display` beats the UA `[hidden]{display:none}`, so restore it —
   the graph view hides the editor with the attribute (cf. .detail-editor). */
.workspace[hidden], .help[hidden] { display: none; }
.graph-canvas { display: inline-block; line-height: 0; }
.graph-canvas svg { display: block; max-width: none; }
/* Which controls belong to which mode is decided here, once — the script only
   sets `body.graph-view`. The header keeps the logo and the wordmark exactly as
   the editor has them; only the editing buttons give way to the two viewing
   ones, and the status (which is about saving) goes with them. */
.graph-only { display: none; }
body.graph-view .edit-only { display: none; }
body.graph-view .graph-only { display: inline-block; }
body.graph-view .file-name,
body.graph-view .status { display: none; }

/* ---- Toolbar icons ----
   Discreet monochrome glyphs drawn as CSS masks, so each one takes its
   button's own text colour and follows the light/dark theme with no second
   set of assets. Wide screens only: below the mobile breakpoint the toolbar
   is already tight, and the labels do the work on their own. */
@media (min-width: 761px) {
  #btn-undo::before, #btn-redo::before, #btn-new::before, #btn-open::before,
  #btn-save::before, #btn-saveas::before, #btn-svg::before, #btn-edit::before,
  #btn-graph-new::before, #btn-svg-save::before {
    content: "";
    display: inline-block;
    width: 14px;
    height: 14px;
    margin-right: 6px;
    vertical-align: -2px;
    background-color: currentColor;   /* the mask decides the shape */
    opacity: 0.7;                     /* the label leads, the icon follows */
    -webkit-mask: var(--icon) center / contain no-repeat;
    mask: var(--icon) center / contain no-repeat;
  }
  #btn-undo { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 14 4 9l5-5'/%3E%3Cpath d='M4 9h11a5 5 0 0 1 0 10h-3'/%3E%3C/svg%3E"); }
  #btn-redo { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m15 14 5-5-5-5'/%3E%3Cpath d='M20 9H9a5 5 0 0 0 0 10h3'/%3E%3C/svg%3E"); }
  #btn-new, #btn-graph-new { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E"); }
  #btn-open { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 20a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h5l2 2h8a1 1 0 0 1 1 1v11a1 1 0 0 1-1 1z'/%3E%3C/svg%3E"); }
  #btn-save { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z'/%3E%3Cpath d='M17 21v-8H7v8M7 3v5h8'/%3E%3C/svg%3E"); }
  #btn-saveas { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3v10'/%3E%3Cpath d='m8 11 4 4 4-4'/%3E%3Cpath d='M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2'/%3E%3C/svg%3E"); }
  #btn-svg { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='5' cy='12' r='2'/%3E%3Ccircle cx='19' cy='6' r='2'/%3E%3Ccircle cx='19' cy='18' r='2'/%3E%3Cpath d='m7 11 10-4M7 13l10 4'/%3E%3C/svg%3E"); }
  #btn-edit { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 20h9'/%3E%3Cpath d='M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4z'/%3E%3C/svg%3E"); }
  #btn-svg-save { --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='16' rx='2'/%3E%3Cpath d='m3 16 5-5 4 4 3-3 5 5'/%3E%3Ccircle cx='8.5' cy='9' r='1.2'/%3E%3C/svg%3E"); }
}
