diff --git a/ivette/src/dome/renderer/colors.tsx b/ivette/src/dome/renderer/colors.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..09046e30ff60b7c0fc49d0b48eeef64ec9f393e2
--- /dev/null
+++ b/ivette/src/dome/renderer/colors.tsx
@@ -0,0 +1,96 @@
+/* ************************************************************************ */
+/*                                                                          */
+/*   This file is part of Frama-C.                                          */
+/*                                                                          */
+/*   Copyright (C) 2007-2024                                                */
+/*     CEA (Commissariat à l'énergie atomique et aux énergies               */
+/*          alternatives)                                                   */
+/*                                                                          */
+/*   you can redistribute it and/or modify it under the terms of the GNU    */
+/*   Lesser General Public License as published by the Free Software        */
+/*   Foundation, version 2.1.                                               */
+/*                                                                          */
+/*   It is distributed in the hope that it will be useful,                  */
+/*   but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
+/*   GNU Lesser General Public License for more details.                    */
+/*                                                                          */
+/*   See the GNU Lesser General Public License version 2.1                  */
+/*   for more details (enclosed in the file licenses/LGPLv2.1).             */
+/*                                                                          */
+/* ************************************************************************ */
+
+/**
+   @packageDocumentation
+   @module dome/colors
+ */
+
+import React from 'react';
+import { useStyle, useColorTheme } from 'dome/themes';
+
+export enum EColor {
+  DEFAULT = "default",
+  WHITE = 'white',
+  GREY = 'grey',
+  DARK = 'dark',
+  PRIMARY = 'primary',
+  SELECTED = 'selected',
+  GREEN = 'green',
+  ORANGE = 'orange',
+  RED = 'red',
+  YELLOW = 'yellow',
+  BLUE = 'blue',
+  PINK = 'pink'
+}
+
+export type TColor = `${EColor}`
+
+type TColorVal = {
+  [key in EColor]: string
+}
+
+export interface IHookColors {
+  BGCOLOR: TColorVal;
+  SGCOLOR: TColorVal;
+  FGCOLOR: TColorVal;
+  EDCOLOR: TColorVal;
+}
+
+type TColorCategory = 'bg'|'fg'|'sg'|'ed';
+
+export function useColor(): IHookColors  {
+  const style = useStyle();
+  const [theme, ] = useColorTheme();
+
+  const enum2Tcolor = (callback: (elt: EColor) => string): TColorVal => {
+    return {
+      ...(Object.fromEntries(
+        Object.values(EColor).map((val: EColor) => [ val, callback(val)])
+      )),
+    } as TColorVal;
+  };
+
+  function getColorType(type: TColorCategory): TColorVal {
+    return enum2Tcolor(
+      (elt) => style.getPropertyValue('--graph-'+type+'-color-'+elt)
+    );
+  }
+
+  const colors = React.useMemo(() => {
+    return {
+      // node background colors
+      BGCOLOR: getColorType('bg'),
+      // // cluster background colors
+      SGCOLOR: getColorType('sg'),
+      //  foreground colors
+      FGCOLOR: getColorType('fg'),
+      // // edge colors
+      EDCOLOR: getColorType('ed'),
+    };
+  },
+    /** style is dependent on theme but it is not used directly */
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+    [theme]
+  );
+  return colors;
+}
diff --git a/ivette/src/dome/renderer/dark.css b/ivette/src/dome/renderer/dark.css
index 31e009d27d3c4418244c47c03fa1ebfd8a0f24e0..8282b2569fecae7b711f543a3d42a24f840de2e0 100644
--- a/ivette/src/dome/renderer/dark.css
+++ b/ivette/src/dome/renderer/dark.css
@@ -124,5 +124,59 @@
     --status-valid-under-hyp: linear-gradient(to right, var(--status-valid) 49%, var(--status-unknown) 51%);
     --status-considered-valid: linear-gradient(to right, var(--status-valid) 49%, #73BBBB 51%);
     --status-invalid-under-hyp: linear-gradient(to right, var(--status-invalid) 49%, var(--status-unknown) 51%);
+
+    /* node background colors */
+    --graph-bg-color-default: #4c596b;
+    --graph-bg-color-white: #fff;
+    --graph-bg-color-grey: #ccc;
+    --graph-bg-color-dark: #666;
+    --graph-bg-color-primary: dodgerblue;
+    --graph-bg-color-selected: deepskyblue;
+    --graph-bg-color-green: lime;
+    --graph-bg-color-orange: #ffa700;
+    --graph-bg-color-red: red;
+    --graph-bg-color-yellow: yellow;
+    --graph-bg-color-blue: cyan;
+    --graph-bg-color-pink: hotpink;
+    /* cluster background colors */
+    --graph-sg-color-default: #4c596b;
+    --graph-sg-color-white: #ccc;
+    --graph-sg-color-grey: #bbb;
+    --graph-sg-color-dark: #aaa;
+    --graph-sg-color-primary: #4fc3f7;
+    --graph-sg-color-selected: #4c596b;
+    --graph-sg-color-green: #AED581;
+    --graph-sg-color-orange: #FFCC80;
+    --graph-sg-color-red: #ff6e6e;
+    --graph-sg-color-yellow: #d4cc82;
+    --graph-sg-color-blue: #bbdefb;
+    --graph-sg-color-pink: #f8bbd0;
+    /** foreground colors */
+    --graph-fg-color-default: white;
+    --graph-fg-color-white: black;
+    --graph-fg-color-grey: black;
+    --graph-fg-color-dark: white;
+    --graph-fg-color-primary: white;
+    --graph-fg-color-selected: black;
+    --graph-fg-color-green: black;
+    --graph-fg-color-orange: black;
+    --graph-fg-color-red: white;
+    --graph-fg-color-yellow: black;
+    --graph-fg-color-blue: black;
+    --graph-fg-color-pink: white;
+    /** edge colors */
+    --graph-ed-color-default: white;
+    --graph-ed-color-white: #fff;
+    --graph-ed-color-grey: #ddd;
+    --graph-ed-color-dark: black;
+    --graph-ed-color-primary: dodgerblue;
+    --graph-ed-color-selected: deepskyblue;
+    --graph-ed-color-green: green;
+    --graph-ed-color-orange: orange;
+    --graph-ed-color-red: red;
+    --graph-ed-color-yellow: #e5e100;
+    --graph-ed-color-blue: deepskyblue;
+    --graph-ed-color-pink: palevioletred1;
+
   }
 }
diff --git a/ivette/src/dome/renderer/graph/diagram.tsx b/ivette/src/dome/renderer/graph/diagram.tsx
index 291f0a79f4f7bedce638fdcdd7fc7c85ae838d08..d594f647ca21f1aa19bdea0b29be528c7f48262b 100644
--- a/ivette/src/dome/renderer/graph/diagram.tsx
+++ b/ivette/src/dome/renderer/graph/diagram.tsx
@@ -23,6 +23,7 @@
 import React from 'react';
 import { Catch } from 'dome/errors';
 import { classes } from 'dome/misc/utils';
+import { useColor, IHookColors, TColor, EColor } from '../colors';
 import { Size } from 'react-virtualized';
 import { select, selectAll } from 'd3-selection';
 import { graphviz } from 'd3-graphviz';
@@ -37,12 +38,6 @@ export type Direction = 'LR' | 'TD';
 
 export type Font = 'serif' | 'sans' | 'mono';
 
-export type Color =
-  | 'white' | 'grey' | 'dark'
-  | 'primary' | 'selected'
-  | 'green' | 'orange' | 'red'
-  | 'yellow' | 'blue' | 'pink';
-
 export type Shape =
   | 'point' | 'box'
   | 'diamond' | 'hexagon'
@@ -72,7 +67,7 @@ export interface Node {
   /** Node font (label) */
   font?: Font;
   /** Node color (filled background) */
-  color?: Color;
+  color?: TColor;
   /**
    * Shape. Nested boxes alternate LR and TD directions. Initial direction is
    * orthogonal to the graph direction. Node label is ignored for box layout.
@@ -96,7 +91,7 @@ export interface Edge {
   /** Default is `solid` */
   line?: Line;
   /** Default is `dark` */
-  color?: Color;
+  color?: TColor;
   head?: Arrow;
   headLabel?: string,
   headAnchor?: Anchor;
@@ -120,7 +115,7 @@ export interface Cluster {
   /** Title (default is none) */
   title?: string;
   /** Background color (default is grey) */
-  color?: Color;
+  color?: TColor;
 }
 
 /* -------------------------------------------------------------------------- */
@@ -152,7 +147,6 @@ export interface DiagramProps {
 
   /** Debug the generated DotModel */
   onModelChanged?: (model: string) => void;
-
 }
 
 /* -------------------------------------------------------------------------- */
@@ -165,66 +159,6 @@ const FONTNAME = {
   'mono': 'Courier',
 };
 
-// node background colors
-const BGCOLOR = {
-  'white': '#fff',
-  'grey': '#ccc',
-  'dark': '#666',
-  'primary': 'dodgerblue',
-  'selected': 'deepskyblue',
-  'green': 'lime',
-  'orange': '#ffa700',
-  'red': 'red',
-  'yellow': 'yellow',
-  'blue': 'cyan',
-  'pink': 'hotpink',
-};
-
-// cluster background colors
-const SGCOLOR = {
-  'white': '#eee',
-  'grey': '#ccc',
-  'dark': '#aaa',
-  'primary': '#4fc3f7',
-  'selected': '#90caf9',
-  'green': '#AED581',
-  'orange': '#FFCC80',
-  'red': '#ff6e6e',
-  'yellow': '#fff59d',
-  'blue': '#bbdefb',
-  'pink': '#f8bbd0',
-};
-
-// foreground colors
-const FGCOLOR = {
-  'white': 'black',
-  'grey': 'black',
-  'dark': 'white',
-  'primary': 'white',
-  'selected': 'black',
-  'green': 'black',
-  'orange': 'black',
-  'red': 'white',
-  'yellow': 'black',
-  'blue': 'black',
-  'pink': 'white',
-};
-
-// edge colors
-const EDCOLOR = {
-  'white': '#ccc',
-  'grey': '#888',
-  'dark': 'black',
-  'primary': 'dodgerblue',
-  'selected': 'deepskyblue',
-  'green': 'green',
-  'orange': 'orange',
-  'red': 'red',
-  'yellow': '#e5e100',
-  'blue': 'deepskyblue',
-  'pink': 'palevioletred1',
-};
-
 /* -------------------------------------------------------------------------- */
 /* --- Edge Model                                                         --- */
 /* -------------------------------------------------------------------------- */
@@ -242,6 +176,7 @@ type cluster = { props: Cluster; nodes: Node[]; }
 
 class Builder {
 
+  private colors: IHookColors;
   private selected: string | undefined;
   private spec = '';
 
@@ -250,6 +185,10 @@ class Builder {
   private rmap = new Map<string, string>();
   private cmap = new Map<string, cluster>();
 
+  constructor(colors: IHookColors) {
+    this.colors = colors;
+  }
+
   index(id: string): string {
     const n = this.imap.get(id);
     if (n !== undefined) return n;
@@ -372,23 +311,24 @@ class Builder {
         .attr('shape', n.shape)
         .attr('tooltip', n.title ?? n.label ?? n.id);
     }
-    const color = n.color ?? (n.id === this.selected ? 'selected' : 'white');
+    const color = n.color ??
+      ( n.id === this.selected ? EColor.SELECTED : EColor.DEFAULT );
     this
-      .attr('fontcolor', FGCOLOR[color])
-      .attr('fillcolor', BGCOLOR[color])
+      .attr('fontcolor', this.colors.FGCOLOR[color])
+      .attr('fillcolor', this.colors.BGCOLOR[color])
       .println(' ];');
   }
 
   cluster(c: cluster): void {
     const { props: s, nodes } = c;
-    const { color = 'grey' } = s;
+    const { color = EColor.GREY } = s;
     this
       .print('  subgraph cluster_', this.index(s.id), ' {\n   ')
       .attr('style', 'filled')
       .attr('label', s.label)
       .attr('tooltip', s.title ?? s.id)
-      .attr('fontcolor', FGCOLOR[color])
-      .attr('fillcolor', SGCOLOR[color])
+      .attr('fontcolor', this.colors.FGCOLOR[color])
+      .attr('fillcolor', this.colors.SGCOLOR[color])
       .print('\n   ');
     nodes.forEach(n => this.print(' ', this.index(n.id), ';'));
     this.println('\n  }');
@@ -433,7 +373,12 @@ class Builder {
       .attr('tailtooltip', e.tailLabel ? tooltip : undefined)
       .attr('tooltip', tooltip)
       .attr('dir', DIR(head, tail))
-      .attr('color', e.color ? EDCOLOR[e.color] : undefined)
+      .attr('color', e.color ?
+        this.colors.EDCOLOR[e.color] :
+        this.colors.EDCOLOR[EColor.DEFAULT])
+      .attr('fontcolor', e.color ?
+        this.colors.EDCOLOR[e.color] :
+        this.colors.EDCOLOR[EColor.DEFAULT])
       .attr('style', line === 'solid' ? undefined : line)
       .attr('arrowhead', head === 'arrow' ? undefined : head)
       .attr('arrowtail', tail === 'arrow' ? undefined : tail)
@@ -457,9 +402,11 @@ const newDivId = (): string => `dome_xDiagram_g${++divId}`;
 interface GraphvizProps extends DiagramProps { size: Size }
 
 function GraphvizView(props: GraphvizProps): JSX.Element {
+  // Colors
+  const colors = useColor();
 
   // --- Builder Instance (unique)
-  const builder = React.useMemo(() => new Builder, []);
+  const builder = React.useMemo(() => new Builder(colors), [colors]);
 
   // --- Model Generation
   const {
diff --git a/ivette/src/dome/renderer/graph/graph.tsx b/ivette/src/dome/renderer/graph/graph.tsx
index 535d0dd9bb118e6f0e3d3b272a70ff37dcdb31ef..751e815ca44c8c9671492bbd3c03a4988cae1a30 100644
--- a/ivette/src/dome/renderer/graph/graph.tsx
+++ b/ivette/src/dome/renderer/graph/graph.tsx
@@ -21,6 +21,7 @@
 /* ************************************************************************ */
 
 import React from 'react';
+import { createRoot } from 'react-dom/client';
 
 import ForceGraph2D, {
   ForceGraphMethods as ForceGraphMethods2D,
@@ -32,17 +33,25 @@ import ForceGraph3D, {
   ForceGraphMethods as ForceGraphMethods3D,
   LinkObject as LinkObject3D,
   NodeObject as NodeObject3D,
+  ForceGraphProps as ForceGraphProps3D,
 } from 'react-force-graph-3d';
 
+/** Three is a dependency of 3d-force-graph */
+import {
+  CSS2DRenderer, CSS2DObject
+} from 'three/examples/jsm/renderers/CSS2DRenderer';
+
 import { Size } from 'react-virtualized';
 import AutoSizer from 'react-virtualized-auto-sizer';
 
-// ForceGraphMethods as ForceGraphMethods3D,
+import * as Dome from 'dome';
+import * as Themes from 'dome/themes';
 
 /* -------------------------------------------------------------------------- */
 /* --- Graph Specifications                                               --- */
 /* -------------------------------------------------------------------------- */
 
+/** Type layout */
 export type Layout = '2D' | '3D';
 
 export interface Node {
@@ -57,6 +66,131 @@ export interface Edge {
   target: string /** Target node identifier */;
 }
 
+/* -------------------------------------------------------------------------- */
+/* --- Force Graph Components                                             --- */
+/* -------------------------------------------------------------------------- */
+
+interface GNode {
+  id: string;
+  label?: string;
+}
+interface GLink {
+  source: string;
+  target: string;
+}
+interface GData {
+  nodes: GNode[];
+  links: GLink[];
+}
+
+interface IGProps {
+  data: GData;
+  onSelection?: SelectionCallback;
+  selected: string | undefined;
+  size: Size;
+}
+
+interface IGProps2D extends IGProps {
+  options?: IGraphOptions;
+}
+
+interface IGProps3D extends IGProps {
+  options?: IGraphOptions3D;
+}
+
+/* -------------------------------------------------------------------------- */
+/* --- Graph options                                                      --- */
+/* -------------------------------------------------------------------------- */
+/** Nodes options */
+export interface INodesOptions {
+  /** visibility of the nodes */
+  visibility?: boolean | ((node: GNode) => boolean);
+}
+
+/** Links options */
+export interface ILinksOptions {
+  /** Width of the links */
+  width?: number | ((node: GLink) => number);
+  /** Color of the links */
+  color?: string | ((node: GLink) => string);
+  /** visibility of the links */
+  visibility?: boolean | ((node: GLink) => boolean);
+  /** Size of the arrows */
+  directionalArrow?: number;
+  /** Number of directional particles */
+  directionalParticle?: number;
+  /** Width of directional particles */
+  particleWidth?: number;
+  /** Color of directional particles */
+  particleColor?: string | ((node: GLink) => string)
+}
+
+/** Common options for Graph2D and Graph3D */
+export interface IGraphOptions {
+  /** Background color */
+  backgroundColor?: string;
+  /** Moves the camera to see all of the nodes if active */
+  autoCenter?: boolean;
+  /**
+   * If displayMode = td, the graph will be display like a tree from top to down
+   * Work only if the graph has no cycle
+   */
+  displayMode?: 'td';
+  /** Spacing between depths level */
+  depthSpacing?: number;
+  /** A string[][] ref to save the cycles */
+  cycles?: React.MutableRefObject<string[][]>
+  /** Nodes options */
+  nodesOptions?: INodesOptions;
+  /** Links options */
+  linkOptions?: ILinksOptions;
+}
+
+/** Specific options for graph3D */
+export interface IGraphOptions3D extends IGraphOptions {
+  /** function to create the HTML for 2D object */
+  htmlNode?: (node: NodeObject3D<GNode>) => JSX.Element;
+  /** Node repulsion */
+  horizontalSpacing?: number;
+}
+
+function getOnEngineStop(
+  fgRef: React.MutableRefObject<ForceGraphMethods3D<NodeObject3D<GNode>,
+  LinkObject3D<GNode, GLink>> | undefined>,
+  options: {
+    autoCenter?: boolean
+  }
+):() => void {
+  return () => {
+    if (options.autoCenter && fgRef.current) {
+      fgRef.current.zoomToFit(400, 20);
+    }
+  };
+}
+
+function getOnDagError(
+  cycles: React.MutableRefObject<string[][]>
+):(val: (string | number)[]) => void {
+  return (val: (string | number)[]) => cycles.current.push(val as string[]);
+}
+
+/** Tranform JSX.Element to HtmlObject */
+const jsxToHtmlObject = (jsxElement: JSX.Element): HTMLDivElement => {
+  const container = document.createElement('div');
+  createRoot(container).render(jsxElement);
+  return container;
+};
+
+/** Return a function who make an object2D */
+function getObject2DFunction(
+  getNode: (node: NodeObject3D<GNode>) => JSX.Element
+) {
+  return (node: NodeObject3D<GNode>) => {
+    const nodeEl = jsxToHtmlObject(getNode(node));
+    return new CSS2DObject(nodeEl || document.createElement('div'));
+  };
+}
+
 /* -------------------------------------------------------------------------- */
 /* --- Graph Component Properties                                         --- */
 /* -------------------------------------------------------------------------- */
@@ -88,37 +222,19 @@ export interface GraphProps {
 
   /** Styling the Graph main div element. */
   className?: string;
-}
-
-/* -------------------------------------------------------------------------- */
-/* --- Force Graph Components                                             --- */
-/* -------------------------------------------------------------------------- */
 
-interface GNode {
-  id: string;
-  label?: string;
-}
-interface GLink {
-  source: string;
-  target: string;
-}
-interface GData {
-  nodes: GNode[];
-  links: GLink[];
-}
+  /** Options graph 2D */
+  options2D?: IGraphOptions;
 
-interface GProps {
-  data: GData;
-  onSelection?: SelectionCallback;
-  selected: string | undefined;
-  size: Size;
+  /** Options graph 3D */
+  options3D?: IGraphOptions3D;
 }
 
 /* -------------------------------------------------------------------------- */
 /* --- 2D Force Graph Component                                           --- */
 /* -------------------------------------------------------------------------- */
 
-function Graph2D(props: GProps): JSX.Element {
+function Graph2D(props: IGProps2D): JSX.Element {
   const { data, onSelection, selected, size } = props;
   const { width, height } = size;
 
@@ -127,6 +243,8 @@ function Graph2D(props: GProps): JSX.Element {
     | undefined
   >(undefined);
 
+  const style = Themes.useStyle();
+
   React.useEffect(() => {
     if (fgRef2D.current && selected) {
       const selectedNode: NodeObject2D | undefined = data.nodes.find(
@@ -160,7 +278,10 @@ function Graph2D(props: GProps): JSX.Element {
         node.fy = node.y;
       }}
       cooldownTime={50}
-      nodeColor={(node) => (node.id === selected ? '#F4D03F' : '#5DADE2')}
+      nodeColor={(node) => (node.id === selected ?
+        style.getPropertyValue('--graph-bg-color-selected') :
+        style.getPropertyValue('--graph-bg-color-orange'))
+      }
     />
   );
 }
@@ -168,9 +289,56 @@ function Graph2D(props: GProps): JSX.Element {
 /* -------------------------------------------------------------------------- */
 /* --- 3D Force Graph Component                                           --- */
 /* -------------------------------------------------------------------------- */
+function getForceGraphOptions(
+  fgRef: React.MutableRefObject<ForceGraphMethods3D<NodeObject3D<GNode>,
+  LinkObject3D<GNode, GLink>> | undefined>,
+  options: IGraphOptions3D,
+): ForceGraphProps3D<GNode, GLink> {
+  const ret: ForceGraphProps3D<GNode, GLink> = {};
+
+  const { linkOptions, nodesOptions } = options;
+
+  if (linkOptions) {
+    const { width, color, visibility, directionalArrow,
+      directionalParticle, particleWidth, particleColor
+    } = linkOptions;
+    if (width) ret.linkWidth = width;
+    if (color) ret.linkColor = color;
+    if (visibility) ret.linkVisibility = visibility;
+    if (directionalArrow) ret.linkDirectionalArrowLength = directionalArrow;
+    if (directionalParticle) ret.linkDirectionalParticles = directionalParticle;
+    if (particleWidth) ret.linkDirectionalParticleWidth = particleWidth;
+    if (particleColor) ret.linkDirectionalParticleColor = particleColor;
+  }
+
+  if (nodesOptions?.visibility) ret.nodeVisibility = nodesOptions?.visibility;
+
+  if(options) {
+    const {
+      backgroundColor, displayMode, depthSpacing, cycles, htmlNode, autoCenter
+    } = options;
+
+    if (displayMode) ret.dagMode = displayMode;
+    if (depthSpacing) ret.dagLevelDistance = depthSpacing;
+    if (backgroundColor) ret.backgroundColor = backgroundColor;
+
+    ret.onEngineStop = getOnEngineStop(fgRef, { autoCenter });
+    if(cycles) ret.onDagError = getOnDagError(cycles);
+
+    if(htmlNode) {
+      ret.extraRenderers = [new CSS2DRenderer()];
+      ret.nodeThreeObjectExtend = false;
+      ret.nodeThreeObject = getObject2DFunction(htmlNode);
+     }
+  }
+
+  return ret;
+}
 
-function Graph3D(props: GProps): JSX.Element {
-  const { data, onSelection, selected, size } = props;
+function Graph3D(props: IGProps3D): JSX.Element {
+  const { data, onSelection, selected, size,
+           options = {}
+        } = props;
   const { width, height } = size;
 
   const fgRef3D = React.useRef<
@@ -178,6 +346,12 @@ function Graph3D(props: GProps): JSX.Element {
     | undefined
   >(undefined);
 
+  const graphOptions = getForceGraphOptions(fgRef3D, options || {});
+  const style = Themes.useStyle();
+
+  const [ , flipHorizontalSpacingIsSet ] =
+    Dome.useFlipSettings('ivette.callgraph.horizontalSpacingIsSet', true);
+
   React.useEffect(() => {
     if (fgRef3D.current && selected) {
       // distance to set between camera and node
@@ -198,7 +372,23 @@ function Graph3D(props: GProps): JSX.Element {
         }
       }
     }
-  }, [selected, data]);
+  }, [fgRef3D, selected, data]);
+
+  React.useEffect(() => {
+    /** Waiting for fgRef3D.current initialization */
+    if (!fgRef3D.current) {
+      const timer = setTimeout(() => {
+        flipHorizontalSpacingIsSet();
+      }, 100);
+      return () => clearTimeout(timer);
+    }
+
+    if (options.horizontalSpacing) {
+      // Adjust node repulsion
+      fgRef3D.current.d3Force('charge')?.strength(-options.horizontalSpacing);
+    }
+    return;
+  }, [options.horizontalSpacing, flipHorizontalSpacingIsSet]);
 
   return (
     <ForceGraph3D<GNode, GLink>
@@ -223,7 +413,11 @@ function Graph3D(props: GProps): JSX.Element {
         node.fy = node.y;
         node.fz = node.z;
       }}
-      nodeColor={(node) => (node.id === selected ? '#F4D03F' : '#5DADE2')}
+      nodeColor={(node) => (node.id === selected ?
+        style.getPropertyValue('--graph-bg-color-selected') :
+        style.getPropertyValue('--graph-bg-color-orange'))
+      }
+      {...graphOptions}
     />
   );
 }
@@ -233,7 +427,8 @@ function Graph3D(props: GProps): JSX.Element {
 /* -------------------------------------------------------------------------- */
 
 export function Graph(props: GraphProps): JSX.Element {
-  const { nodes, edges, onSelection, display = true, selected } = props;
+  const { nodes, edges, onSelection,
+          display = true, selected, options3D } = props;
   const data: GData = React.useMemo(
     () => ({
       nodes: nodes.slice(),
@@ -268,6 +463,7 @@ export function Graph(props: GraphProps): JSX.Element {
                 data={data}
                 onSelection={onSelection}
                 selected={selected}
+                options={options3D}
                 size={size}
               />
             </div>
diff --git a/ivette/src/dome/renderer/graph/style.css b/ivette/src/dome/renderer/graph/style.css
index c8818cb37fc1b12a09f3fc820acec6e7e6a256a0..3f7a38c09b5c5fd3ab43b766765e161b004e28d8 100644
--- a/ivette/src/dome/renderer/graph/style.css
+++ b/ivette/src/dome/renderer/graph/style.css
@@ -3,5 +3,5 @@
 /* -------------------------------------------------------------------------- */
 
 .dome-xDiagram {
-    background: #eee;
+    background: var(--background);
 }
diff --git a/ivette/src/dome/renderer/light.css b/ivette/src/dome/renderer/light.css
index 732c57a2427ad095520fba78a333b5638bca3ba1..0975353f91073cfaea9e7b57b000e09502782c89 100644
--- a/ivette/src/dome/renderer/light.css
+++ b/ivette/src/dome/renderer/light.css
@@ -124,5 +124,58 @@
     --status-valid-under-hyp: linear-gradient(to right, var(--status-valid) 49%, var(--status-unknown) 51%);
     --status-considered-valid: linear-gradient(to right, var(--status-valid) 49%, #73BBBB 51%);
     --status-invalid-under-hyp: linear-gradient(to right, var(--status-invalid) 49%, var(--status-unknown) 51%);
+
+    /* node background colors */
+    --graph-bg-color-default: #fff;
+    --graph-bg-color-white: #fff;
+    --graph-bg-color-grey: #ccc;
+    --graph-bg-color-dark: #666;
+    --graph-bg-color-primary: dodgerblue;
+    --graph-bg-color-selected: deepskyblue;
+    --graph-bg-color-green: lime;
+    --graph-bg-color-orange: #ffa700;
+    --graph-bg-color-red: red;
+    --graph-bg-color-yellow: yellow;
+    --graph-bg-color-blue: cyan;
+    --graph-bg-color-pink: hotpink;
+    /* cluster background colors */
+    --graph-sg-color-default: #eee;
+    --graph-sg-color-white: #eee;
+    --graph-sg-color-grey: #ccc;
+    --graph-sg-color-dark: #aaa;
+    --graph-sg-color-primary: #4fc3f7;
+    --graph-sg-color-selected: #90caf9;
+    --graph-sg-color-green: #AED581;
+    --graph-sg-color-orange: #FFCC80;
+    --graph-sg-color-red: #ff6e6e;
+    --graph-sg-color-yellow: #fff59d;
+    --graph-sg-color-blue: #bbdefb;
+    --graph-sg-color-pink: #f8bbd0;
+    /** foreground colors */
+    --graph-fg-color-default: black;
+    --graph-fg-color-white: black;
+    --graph-fg-color-grey: black;
+    --graph-fg-color-dark: white;
+    --graph-fg-color-primary: white;
+    --graph-fg-color-selected: black;
+    --graph-fg-color-green: black;
+    --graph-fg-color-orange: black;
+    --graph-fg-color-red: white;
+    --graph-fg-color-yellow: black;
+    --graph-fg-color-blue: black;
+    --graph-fg-color-pink: white;
+    /** edge colors */
+    --graph-ed-color-default: black;
+    --graph-ed-color-white: #ccc;
+    --graph-ed-color-grey: #888;
+    --graph-ed-color-dark: black;
+    --graph-ed-color-primary: dodgerblue;
+    --graph-ed-color-selected: deepskyblue;
+    --graph-ed-color-green: green;
+    --graph-ed-color-orange: orange;
+    --graph-ed-color-red: red;
+    --graph-ed-color-yellow: #e5e100;
+    --graph-ed-color-blue: deepskyblue;
+    --graph-ed-color-pink: palevioletred1;
   }
 }
diff --git a/ivette/src/dome/renderer/themes.tsx b/ivette/src/dome/renderer/themes.tsx
index 655d4639010a5e7bcba1f07f674f2908e15ef6b3..f878aab3500fda3fbee0ffa8bb34b005f15e9478 100644
--- a/ivette/src/dome/renderer/themes.tsx
+++ b/ivette/src/dome/renderer/themes.tsx
@@ -29,6 +29,7 @@
    @module dome/themes
  */
 
+import React from 'react';
 import * as Dome from 'dome';
 import * as Settings from 'dome/data/settings';
 import { State } from 'dome/data/states';
@@ -80,4 +81,13 @@ export function useColorThemeSettings(): State<ColorSettings> {
   return [jColorSettings(pref), setTheme];
 }
 
+export function useStyle(): CSSStyleDeclaration {
+  const [theme, ] = useColorTheme();
+  const style = React.useMemo(() => getComputedStyle(document.body),
+    /** style is dependent on theme but it is not used directly */
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+    [theme]
+  );
+  return style;
+}
 /* -------------------------------------------------------------------------- */
diff --git a/ivette/src/frama-c/react-three-css2drenderer.d.ts b/ivette/src/frama-c/react-three-css2drenderer.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ea2d9ce6f51a0787586b80cd0ce73e8db8b44300
--- /dev/null
+++ b/ivette/src/frama-c/react-three-css2drenderer.d.ts
@@ -0,0 +1,23 @@
+/* ************************************************************************ */
+/*                                                                          */
+/*   This file is part of Frama-C.                                          */
+/*                                                                          */
+/*   Copyright (C) 2007-2024                                                */
+/*     CEA (Commissariat à l'énergie atomique et aux énergies               */
+/*          alternatives)                                                   */
+/*                                                                          */
+/*   you can redistribute it and/or modify it under the terms of the GNU    */
+/*   Lesser General Public License as published by the Free Software        */
+/*   Foundation, version 2.1.                                               */
+/*                                                                          */
+/*   It is distributed in the hope that it will be useful,                  */
+/*   but WITHOUT ANY WARRANTY; without even the implied warranty of         */
+/*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
+/*   GNU Lesser General Public License for more details.                    */
+/*                                                                          */
+/*   See the GNU Lesser General Public License version 2.1                  */
+/*   for more details (enclosed in the file licenses/LGPLv2.1).             */
+/*                                                                          */
+/* ************************************************************************ */
+
+declare module 'three/examples/jsm/renderers/CSS2DRenderer';
diff --git a/ivette/src/sandbox/dotdiagram.tsx b/ivette/src/sandbox/dotdiagram.tsx
index 191617f28bc1a6299abcf24c7ad53caf922ebd39..93cdf010d7325b61e51584d0d0688c2172ce4d21 100644
--- a/ivette/src/sandbox/dotdiagram.tsx
+++ b/ivette/src/sandbox/dotdiagram.tsx
@@ -89,7 +89,10 @@ const edges: Edge[] = [
 
 function makeCluster(s: string | undefined): Cluster {
   const color = nodes.find(n => n.id === s)?.color;
-  return { id: 'BG', title: 'Background Cluster', color };
+  return {
+    id: 'BG',
+    title: 'Background Cluster',
+    color: color ?? "default" };
 }
 
 function DiagramSample(): JSX.Element {