diff --git a/ivette/src/dome/renderer/controls/displays.tsx b/ivette/src/dome/renderer/controls/displays.tsx
index 3363c1486fce9bef64d4c9cf538818371f672b76..7e10cc7e444d1b95c26f77a25bd330d690a2911c 100644
--- a/ivette/src/dome/renderer/controls/displays.tsx
+++ b/ivette/src/dome/renderer/controls/displays.tsx
@@ -62,8 +62,15 @@ export function LCD(props: LabelProps): JSX.Element {
 // --- Led
 // --------------------------------------------------------------------------
 
-export type LEDstatus =
-  undefined | 'inactive' | 'active' | 'positive' | 'negative' | 'warning';
+export const LEDStatusList = [
+  'active', 'inactive', 'positive', 'negative', 'warning'
+] as const;
+
+export type LEDstatus = typeof LEDStatusList[number] | undefined;
+
+export function jLEDstatus(js : string) : LEDstatus {
+  return LEDStatusList.find(elt => elt === js);
+}
 
 export interface LEDprops {
   /**
diff --git a/ivette/src/dome/renderer/controls/icons.tsx b/ivette/src/dome/renderer/controls/icons.tsx
index 3cfff841d62a7ee2edf80998e7c55755d9a494f9..ab8c24acde7abcead42327c0e934f23d0a8bfe87 100644
--- a/ivette/src/dome/renderer/controls/icons.tsx
+++ b/ivette/src/dome/renderer/controls/icons.tsx
@@ -95,8 +95,15 @@ export function SVG(props: SVGprops): null | JSX.Element {
 // --- Icon Component
 // --------------------------------------------------------------------------
 
-export type IconKind =
-  'disabled' | 'selected' | 'positive' | 'negative' | 'warning' | 'default';
+export const iconKindList = [
+  'disabled', 'selected', 'positive', 'negative', 'warning', 'default'
+] as const;
+
+export type IconKind = typeof iconKindList[number]
+
+export function jIconKind(js : string) : IconKind | undefined {
+  return iconKindList.find(elt => elt === js);
+}
 
 /** Icon Component Properties */
 export interface IconProps extends SVGprops {
diff --git a/ivette/src/dome/renderer/controls/style.css b/ivette/src/dome/renderer/controls/style.css
index 2d21b7bcd7cef2aa675b1a5a81c93c90bd1c12c1..126ed6edcd9ea1a452cdae8b5baed0fc6a3bd43c 100644
--- a/ivette/src/dome/renderer/controls/style.css
+++ b/ivette/src/dome/renderer/controls/style.css
@@ -267,7 +267,7 @@
 }
 
 .dome-xButton-led {
-    display: inline ;
+    display: inline-block ;
     position: relative ;
     border-color: var(--border) ;
     border-style: solid ;
diff --git a/ivette/src/dome/renderer/style.css b/ivette/src/dome/renderer/style.css
index 0c341b788d3ca63ebb793db3c1104c7bfa21f035..f3f86601cd02cfe1038e2dd3dd475536658a1971 100644
--- a/ivette/src/dome/renderer/style.css
+++ b/ivette/src/dome/renderer/style.css
@@ -278,7 +278,7 @@ input[type="checkbox"]:checked {
 }
 
 .dome-xModal-overlay {
-  z-index: 100;
+  z-index: 1000;
   position: fixed;
   top: 0;
   left: 0;
diff --git a/ivette/src/dome/renderer/text/markdown.tsx b/ivette/src/dome/renderer/text/markdown.tsx
index 8641cc6e7a7b558d8614aceadaf51905d7eb531e..d40921b92270f0d3025dc29ef307e35f0a781b90 100644
--- a/ivette/src/dome/renderer/text/markdown.tsx
+++ b/ivette/src/dome/renderer/text/markdown.tsx
@@ -26,22 +26,57 @@ import remarkCustomHeaderId from 'remark-custom-header-id';
 
 import * as Themes from 'dome/themes';
 import { classes } from 'dome/misc/utils';
-import { Icon } from 'dome/controls/icons';
+import { Icon, jIconKind, IconKind as _IconKind  } from 'dome/controls/icons';
 import {
   CodeBlock, atomOneDark, atomOneLight
 } from "react-code-blocks";
+import {
+  jLEDstatus, LED, LEDstatus as _LEDstatus
+} from 'dome/controls/displays';
+
 export interface Pattern {
   pattern: RegExp,
   replace: (key: number, match?: RegExpExecArray) => JSX.Element | null
 }
 
+/**
+ * iconTag allows you to replace the tag with an {@link Icon}.
+ *
+ * `[icon-<id>(-<kind | color>)?]` :
+ *
+ * * Id : case-insensitive, consult [Icon Gallery](../../doc/guides/icons.md)
+ * * kind : {@link _IconKind}
+ * * color : Hexa or html
+ *
+ * @example
+ * [icon-tunings-#FF0000] : this tag will be replaced by a red TUNINGS icon
+ */
+
 export const iconTag: Pattern = {
-  pattern: /(\[ex:\])?\[icon-([^\]]+)\]/g,
+  pattern: /(\[icon-([^-\]]+)(-([^\]]+))?\])/g,
   replace: (key: number, match?: RegExpExecArray) => {
-    if(match && match[1] === "[ex:]") {
-      return <span key={key}>{`[icon-${match[2]}]`}</span>;
-    }
-    return match ? <Icon key={key} id={match[2]}/> : null;
+    if(!match) return null;
+    const kind = jIconKind(match[4]);
+    const color = !kind ? match[4] : undefined;
+    return <Icon key={key}
+     id={match[2].toUpperCase()}
+     kind={kind}
+     fill={color}
+    />;
+  }
+};
+
+/**
+ * ledTag allows you to replace the tag with an {@link LED}.
+ *
+ * `[led-<status>]` : {@link _LEDstatus}
+ * */
+export const ledTag: Pattern = {
+  pattern: /\[led-([^\]]+)\]/g,
+  replace: (key: number, match?: RegExpExecArray) => {
+    if(!match) return null;
+    const status = jLEDstatus(match[1]);
+    return <LED key={key} status={status} />;
   }
 };
 
@@ -52,6 +87,10 @@ export const iconTag: Pattern = {
 /**
  * Replace all tag in children.
  * This function doesn't replace any tags added by a previous replacement.
+ *
+ * Patterns added to the table will be processed to make replacements
+ * in the markdown file. Markdown component provides two patterns,
+ * iconTag and ledTag
  */
 function replaceTags(
   children: React.ReactNode,
@@ -120,6 +159,7 @@ export function Markdown(
   const markdownClasses = classes(
     "dome-xMarkdown", "dome-pages", className
   );
+  let liKey: number = 0;
 
   const scroll = (id: string): void => {
     const elt = document.getElementById(id);
@@ -134,7 +174,9 @@ export function Markdown(
   };
   options.components = {
     p: ({ children }) => <div>{replaceTags(children, patterns)}</div>,
-    li: ({ children }) => <li>{replaceTags(children, patterns)}</li>,
+    li: ({ children }) => {
+      return <li key={liKey++}>{replaceTags(children, patterns)}</li>;
+    },
     /** Uses codeBlock if ``` is used in markdown with a language,
      *  otherwise the code-inline class is added */
     code: ({ className, children }) => {
diff --git a/ivette/src/dome/renderer/text/style.css b/ivette/src/dome/renderer/text/style.css
index 9ead4605dfe6a982f18f647427c8b56e291219b4..b11471622d669db0ac4170423c9a18626e91e9e4 100644
--- a/ivette/src/dome/renderer/text/style.css
+++ b/ivette/src/dome/renderer/text/style.css
@@ -72,7 +72,9 @@
 
 .dome-pages li
 {
-
+  &:has(.code-inline) {
+    margin: 5px 0;
+  }
 }
 
 .dome-pages a
diff --git a/ivette/src/frama-c/plugins/callgraph/callgraph.css b/ivette/src/frama-c/plugins/callgraph/callgraph.css
index 758c026c0eaa99630bf57a877e74226ebc243480..fb03f827b3866d7c96c5a90846d805137345ea3d 100644
--- a/ivette/src/frama-c/plugins/callgraph/callgraph.css
+++ b/ivette/src/frama-c/plugins/callgraph/callgraph.css
@@ -82,7 +82,6 @@
   .node-graph {
     display: flex;
     align-items: center;
-    display: flex;
     background-color: rgb(from var(--background-profound) r g b / .5);
     padding: .5em;
     border-radius: .5em;
@@ -96,10 +95,6 @@
     &.node-selected {
       border: solid var(--activated-button-color) 2px;
     }
-
-    .dome-xButton-led {
-      display: block;
-    }
   }
 
   .cg-display-mode {
diff --git a/ivette/src/frama-c/plugins/callgraph/callgraph.md b/ivette/src/frama-c/plugins/callgraph/callgraph.md
new file mode 100644
index 0000000000000000000000000000000000000000..d081648af84c0595f89f8b34d9cb2f685713196e
--- /dev/null
+++ b/ivette/src/frama-c/plugins/callgraph/callgraph.md
@@ -0,0 +1,104 @@
+# Callgraph {#callgraph}
+
+The callgraph represents calling relationships between functions of the program.
+Each node represents a C function, and each edge from f to g indicates that
+f contains a call to g.
+
+The graph also highlights some functions, such as functions containing unproven
+properties.
+The [panel](#callgraph-panel) displays more information on selected functions.
+The [titlebar](#callgraph-titlebar) and [toolbar](#callgraph-toolbar) contain
+various options to configure the graph and show/hide some functions.
+
+## Titlebar {#callgraph-titlebar}
+
+The titlebar contains the following buttons:
+
+* [icon-tunings]: filter functions appearing in the graph.
+  This filter is synchronized with the sidebar function filter.
+* [icon-target]: move the camera to show each node after each render.
+* [icon-pin]: automatically select in the graph the node of the function
+  selected in the AST.
+* [icon-help]: show this help modal.
+
+## Toolbar {#callgraph-toolbar}
+
+The toolbar contains display and selection parameters on the left and graph
+management parameters on the right.
+
+On the left:
+
+* The first group of buttons can hide nodes from the graph, according to their
+  relation to the currently selected nodes (which are always shown).
+  + Try it yourself: [button-displaymode]
+* [button-select]: select in the graph a list of functions according to some
+  criteria:
+  + functions containing unproven properties;
+  + functions selected in the `Locations` component, if a multi-selection is
+    currently active;
+  + functions containing tainted variables, if an Eva taint analysis has been
+    performed;
+  + functions within cycle in the callgraph.
+
+On the right:
+
+* Horizontal and vertical distance management between graph nodes.
+* [icon-sidebar]: opens or closes the side [panel](#callgraph-panel).
+
+## Graph {#callgraph-graph}
+
+### Nodes
+
+Each node represents a C function and may have the following icons:
+
+* [led-warning]: the function contains unproven properties
+  (the number of which is given in a tooltip).
+* [led-negative]: the function contains invalid properties
+  (the number of which is given in a tooltip);
+* [icon-redo-orange]: the function is recursive;
+* [icon-drop.filled-#882288] or [icon-drop.filled-#73BBBB]:
+  the function contains tainted properties.
+
+### Edges
+
+Edges are oriented from caller to callees, and may have different colors
+depending on the selected nodes:
+
+* A green edge connects two selected functions.
+* A red edge links a selected function node and one of its callers.
+* A blue edge links a selected function node and one of its callees.
+
+### Cycle
+
+The graph is in 3D but is displayed as a tree, which prevents cycles from
+appearing in the graph.
+
+If a cycle is detected:
+
+* Nodes of recursive functions have the [icon-redo-orange] icon.
+* If cycles between several functions are detected, such functions can be
+  selected via the [button-select] button in the [toolbar](#callgraph-toolbar).
+
+## Panel {#callgraph-panel}
+
+The panel displays additional information about the graph in general,
+and lists the logical properties from each function selected in the graph.
+
+The buttons above the list can be used to filter the kind of properties
+shown in this panel. They are synchronised with the filters in the `Properties`
+component.
+
+At the top right, two buttons allow changing the side of the panel,
+and closing it (it can be reopen via the far-right button in the toolbar).
+
+## Shortcuts {#callgraph-shortcuts}
+
+* In the graph:
+  * Left-click: rotate the graph
+  * Right-click: move in the graph
+  * Mouse-wheel: zoom
+ 
+* On nodes:
+  * Left-Click: select node in the graph
+  * Ctrl+click: add node to the selected graph nodes (multi-selection)
+  * Alt+click: select the function in all Ivette components
diff --git a/ivette/src/frama-c/plugins/callgraph/components/node.tsx b/ivette/src/frama-c/plugins/callgraph/components/node.tsx
index 39eb1eb75b6843017bbc702bef050ec9fb21ac16..2eec2ab21f20f314c48d66a528689b4f7775df00 100644
--- a/ivette/src/frama-c/plugins/callgraph/components/node.tsx
+++ b/ivette/src/frama-c/plugins/callgraph/components/node.tsx
@@ -42,16 +42,14 @@ const isTaintedScope = (node: NodeObject3D<CGNode>): boolean => {
 
 const getNodeAlarms = (node: CGNode): JSX.Element => {
   return <>
-    <div>
-      {node.alarmStatuses && node.alarmStatuses.invalid > 0 && LED({
-        status: "negative",
-        title: node.alarmStatuses.invalid+" invalid",
-        })}
-      {node.alarmStatuses && node.alarmStatuses.unknown > 0 && LED({
-        status: "warning",
-        title: node.alarmStatuses.unknown+" unknown",
-        })}
-    </div>
+    {node.alarmStatuses && node.alarmStatuses.invalid > 0 && LED({
+      status: "negative",
+      title: node.alarmStatuses.invalid+" invalid",
+      })}
+    {node.alarmStatuses && node.alarmStatuses.unknown > 0 && LED({
+      status: "warning",
+      title: node.alarmStatuses.unknown+" unknown",
+      })}
   </>;
 };
 
diff --git a/ivette/src/frama-c/plugins/callgraph/components/threeStateButton.tsx b/ivette/src/frama-c/plugins/callgraph/components/threeStateButton.tsx
index 83eea62d370dc68d8e42d8cf1b7fa28c1cb87cb6..fc104952a46ed9f44421c7718234bdff993fcb66 100644
--- a/ivette/src/frama-c/plugins/callgraph/components/threeStateButton.tsx
+++ b/ivette/src/frama-c/plugins/callgraph/components/threeStateButton.tsx
@@ -32,14 +32,16 @@ export interface IThreeStateButton {
   value: number,
 }
 
+export type TThreesButtonState = [
+  IThreeStateButton,
+  (newValue: IThreeStateButton) => void
+];
+
 interface ThreeStateButtonProps {
   label?: string;
   icon?: string;
   title?: string;
-  buttonState: [
-    IThreeStateButton,
-    (newValue: IThreeStateButton) => void
-  ];
+  buttonState: TThreesButtonState;
 }
 
 export function ThreeStateButton(
diff --git a/ivette/src/frama-c/plugins/callgraph/components/titlebar.tsx b/ivette/src/frama-c/plugins/callgraph/components/titlebar.tsx
index a83e80787b7ca87a40f2ba9a1bd7fad39cb25b3e..edb0362351906347f5c324edfcad523df4a75e33 100644
--- a/ivette/src/frama-c/plugins/callgraph/components/titlebar.tsx
+++ b/ivette/src/frama-c/plugins/callgraph/components/titlebar.tsx
@@ -26,34 +26,20 @@ import * as Ivette from 'ivette';
 import * as Dome from 'dome';
 
 import { IconButton } from 'dome/controls/buttons';
-import { Inset } from 'dome/frame/toolbars';
-import * as Dialogs from 'dome/dialogs';
-
-// Help popup
-async function displayShortcuts(): Promise<void> {
-  await Dialogs.showMessageBox({
-    buttons: [{ label: "Ok" }],
-    details: (
-      'In the graph:\n' +
-      '  - Left-click: rotate the graph\n' +
-      '  - Right-click: move in the graph\n' +
-      '  - Mouse-wheel: zoom\n' +
-      '\n' +
-      'On nodes:\n' +
-      '  - Left-Click: select node (in the graph)\n'+
-      '  - Ctrl+click: add node to the selected nodes (multi-selection)\n' +
-      '  - Alt+click: select function (in all Ivette components)\n' +
-      '\n' +
-      'Function filters (in the titlebar of this component) are synchronized ' +
-      'with the filter of the functions sidebar.'
-    ),
-    message: 'Callgraph Help',
-  });
-}
+import { Button, ButtonGroup, Inset } from 'dome/frame/toolbars';
+import { HelpIcon } from 'dome/help';
+import * as Themes from 'dome/themes';
+import { ledTag, iconTag, Pattern } from 'dome/text/markdown';
+import docCallgraph from '../callgraph.md?raw';
+import { ModeDisplay } from '../definitions';
+import {
+  IThreeStateButton, ThreeStateButton, TThreesButtonState
+} from './threeStateButton';
 
 /* -------------------------------------------------------------------------- */
 /* --- Callgraph titlebar component                                       --- */
 /* -------------------------------------------------------------------------- */
+
 interface CallgraphTitleBarProps {
   /** Context menu to filtering nodes */
   contextMenuItems: Dome.PopupMenuItem[],
@@ -89,12 +75,139 @@ export function CallgraphTitleBar(props: CallgraphTitleBarProps): JSX.Element {
         title={"Automatically select node of the function selected in AST"}
       />
       <Inset />
-      <IconButton
-        icon="HELP"
-        onClick={displayShortcuts}
-        title='Callgraph help'
-      />
+      <HelpIcon
+        label='Callgraph'
+        scrollTo={'callgraph'}
+        patterns={[iconTag, ledTag, selectButtonTag, TSButtonTag]}
+      >{ docCallgraph }</HelpIcon>
       <Inset />
     </Ivette.TitleBar>
   );
 }
+
+/* -------------------------------------------------------------------------- */
+/* --- Callgraph documentation                                            --- */
+/* -------------------------------------------------------------------------- */
+
+/** Pattern used for callgraph documentation */
+const TSButtonTag: Pattern = {
+  pattern: /\[button-displaymode\]/g,
+  replace: (key: number, match?: RegExpExecArray) => {
+    return match ? <span key={key}>{DocShowNodesButton()}</span> : null;
+  }
+};
+
+/** Pattern used for callgraph documentation */
+const selectButtonTag: Pattern = {
+  pattern: /\[button-select\]/g,
+  replace: (key: number, match?: RegExpExecArray) => {
+    return match ? <Button key={key} label="Select" title={`Nodes selection`}/>
+      : null;
+  }
+};
+
+interface ShowNodesButtonProps {
+  displayModeState: [ModeDisplay, (newValue: ModeDisplay) => void],
+  selectedParentsState: TThreesButtonState,
+  selectedChildrenState: TThreesButtonState,
+}
+
+function ShowNodesButton(props: ShowNodesButtonProps): JSX.Element {
+  const {
+    displayModeState, selectedParentsState, selectedChildrenState
+  } = props;
+  const [ displayMode, setDisplayMode] = displayModeState;
+
+  return (
+    <ButtonGroup>
+      <Button
+        label='all'
+        title='show all nodes'
+        selected={displayMode === 'all'}
+        onClick={() => setDisplayMode("all")}
+        />
+      <Button
+        label='linked'
+        title='only show nodes linked to the selected ones'
+        selected={displayMode === 'linked'}
+        onClick={() => setDisplayMode("linked")}
+        />
+      <Button
+        label='selected'
+        title='only show selected nodes, their parents and their childrens'
+        selected={displayMode === 'selected'}
+        onClick={() => setDisplayMode("selected")}
+        />
+      { displayMode === "selected" ? (
+          <>
+            <ThreeStateButton
+              label={"Parents"}
+              title={"Choose how many parents you want to see."}
+              buttonState={selectedParentsState}
+              />
+            <ThreeStateButton
+              label={"Children"}
+              title={"Choose how many children you want to see."}
+              buttonState={selectedChildrenState}
+              />
+          </>
+        ) : <></>
+      }
+    </ButtonGroup>
+  );
+}
+
+export function DocShowNodesButton(): JSX.Element {
+  const displayModeState = React.useState<ModeDisplay>("all");
+  const selectedParentsState = React.useState<IThreeStateButton>(
+      { active: false, max: false, value: 1 });
+  const selectedChildrenState = React.useState<IThreeStateButton>(
+      { active: true, max: true, value: 1 });
+  const [ displayMode, ] = displayModeState;
+  const [ parent, ] = selectedParentsState;
+  const [ children, ] = selectedChildrenState;
+
+  const style = Themes.useStyle();
+  const infosStyle = { color: style.getPropertyValue('--text-highlighted') };
+
+  function getDocSelected(
+    parent: IThreeStateButton,
+    children: IThreeStateButton
+  ):JSX.Element {
+    function getDocTSB(name: string, tsb: IThreeStateButton):string {
+      return !tsb.active ? '' :
+        tsb.max ? ` all ${name}` :
+          tsb.value > 0 ?
+            (tsb.value+' level'+(tsb.value > 1 ? 's':'')+` of ${name}`):
+            "";
+    }
+    const p = getDocTSB('parents', parent);
+    const c = getDocTSB('children', children);
+
+    return (
+      <div style={infosStyle}>
+        Selected nodes displayed { (p || c) && " with " }
+        { p }{ p && c && " and " }{ c }
+        { !p && !c && " only " }.
+      </div>
+    );
+  }
+
+  const docAll = <div style={infosStyle}>All nodes displayed.</div>;
+  const docLinked = <div style={infosStyle}>Hide unlinked nodes.</div>;
+  const docSelected = getDocSelected(parent, children);
+
+  return (
+    <>
+      <ShowNodesButton
+        displayModeState={displayModeState}
+        selectedParentsState={selectedParentsState}
+        selectedChildrenState={selectedChildrenState}
+      />
+      { displayMode === 'all' ? docAll :
+        displayMode === 'linked' ? docLinked :
+        docSelected
+      }
+    </>
+  );
+}
diff --git a/ivette/src/frama-c/plugins/callgraph/components/toolbar.tsx b/ivette/src/frama-c/plugins/callgraph/components/toolbar.tsx
index 2154ae91ebcd550fd93c991941c5f35c35641c06..59ea6ae387e6ed59e06573fee67df029a356072d 100644
--- a/ivette/src/frama-c/plugins/callgraph/components/toolbar.tsx
+++ b/ivette/src/frama-c/plugins/callgraph/components/toolbar.tsx
@@ -37,6 +37,7 @@ import { IThreeStateButton, ThreeStateButton } from "./threeStateButton";
 /* -------------------------------------------------------------------------- */
 /* --- Callgraph Toolsbar component                                       --- */
 /* -------------------------------------------------------------------------- */
+
 interface CallgraphToolsBarProps {
   /* eslint-disable max-len */
   displayModeState: [ModeDisplay, (newValue: ModeDisplay) => void],
diff --git a/ivette/src/sandbox/sandbox.md b/ivette/src/sandbox/sandbox.md
index ccc9ff3f982acf4066add0406c39c4d4c1915793..39bec4de1a9006374d5f9e857325a2752f302317 100644
--- a/ivette/src/sandbox/sandbox.md
+++ b/ivette/src/sandbox/sandbox.md
@@ -100,8 +100,9 @@ You can used patterns to replace parts of the text by JSX Element.
 
 There is one basic pattern to replace tags by an `Icon`, it name `iconTag`  in markdown component .
 
-* [icon-TUNINGS] : [ex:][icon-TUNINGS]
-* [icon-TARGET] : [ex:][icon-TARGET]
-* [icon-PIN] : [ex:][icon-PIN]
+* [icon-tunings] : `[icon-tunings]`
+* [icon-tunings-#ff0000] : `[icon-tunings-#ff0000]`
+* [icon-target] : `[icon-target]`
+* [icon-pin] : `[icon-pin]`
 
-or inline [icon-TUNINGS], [icon-TARGET], [icon-PIN]
+or inline [icon-tunings], [icon-target], [icon-pin]