diff --git a/src/apps/rednatco/color-picker.tsx b/src/apps/rednatco/color-picker.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..3958ea3d937c883c3feb186adf510ee8bd909297
--- /dev/null
+++ b/src/apps/rednatco/color-picker.tsx
@@ -0,0 +1,736 @@
+/**
+ * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Lada Biedermannová <Lada.Biedermannova@ibt.cas.cz>
+ * @author Jiří Černý <jiri.cerny@ibt.cas.cz>
+ * @author Michal MalĂ˝ <michal.maly@ibt.cas.cz>
+ * @author Bohdan Schneider <Bohdan.Schneider@ibt.cas.cz>
+ */
+
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { Colors } from './colors';
+import { PushButton, SpinBox } from './controls';
+import { parseInt as parseIntMS } from '../../mol-io/reader/common/text/number-parser';
+
+const PALETTE_CURSOR_HALFSIZE = 10;
+const VALUE_CURSOR_THICKNESS = 3;
+
+const MIN_RGB = 0;
+const MAX_RGB = 255;
+const MIN_HUE = 0;
+const MAX_HUE = 359;
+const MIN_SATVAL = 0;
+const MAX_SATVAL = 100;
+
+function isRgbVal(v: number) {
+    if (isNaN(v))
+        return false;
+    return v >= MIN_RGB && v <= MAX_RGB;
+}
+
+function isHueVal(v: number) {
+    if (isNaN(v))
+        return false;
+    return v >= MIN_HUE && v <= MAX_HUE;
+}
+
+function isSatValVal(v: number) {
+    if (isNaN(v))
+        return false;
+    return v >= MIN_SATVAL && v <= MAX_SATVAL;
+}
+
+function stoi(s: string) {
+    return parseIntMS(s, 0, s.length);
+}
+
+interface State {
+    h: number;
+    s: number;
+    v: number;
+    restoreOnCancel: boolean;
+
+    hIn: string;
+    sIn: string;
+    vIn: string;
+    rIn: string;
+    gIn: string;
+    bIn: string;
+}
+
+export class ColorPicker extends React.Component<ColorPicker.Props, State> {
+    private paletteRef: React.RefObject<HTMLCanvasElement>;
+    private valueColumnRef: React.RefObject<HTMLCanvasElement>;
+    private selfRef: React.RefObject<HTMLDivElement>;
+    private mouseListenerAttached: boolean;
+    private touchListenerAttached: boolean;
+    private lastPaletteX: number;
+    private lastPaletteY: number;
+    private lastValueY: number;
+
+    constructor(props: ColorPicker.Props) {
+        super(props);
+
+        this.paletteRef = React.createRef();
+        this.valueColumnRef = React.createRef();
+        this.selfRef = React.createRef();
+        this.mouseListenerAttached = false;
+        this.touchListenerAttached = false;
+        this.lastPaletteX = 0;
+        this.lastPaletteY = 0;
+        this.lastValueY = 0;
+
+        const { h, s, v } = Colors.colorToHsv(this.props.initialColor);
+        const { r, g, b } = Colors.colorToRgb(this.props.initialColor);
+        this.state = {
+            h: Math.round(h),
+            s,
+            v,
+            restoreOnCancel: false,
+            hIn: h.toString(),
+            sIn: v.toString(),
+            vIn: s.toString(),
+            rIn: r.toString(),
+            gIn: g.toString(),
+            bIn: b.toString(),
+        };
+    }
+
+    private calcLeft() {
+        const self = this.selfRef.current;
+        if (!self)
+            return this.props.left;
+
+        const bw = document.body.clientWidth;
+        const right = self.offsetLeft + self.clientWidth;
+        const overhang = right - bw;
+        if (overhang > 0)
+            return bw - self.clientWidth - 25;
+        return self.offsetLeft;
+    }
+
+    private calcTop() {
+        const self = this.selfRef.current;
+        if (!self)
+            return this.props.top;
+
+        const bh = document.body.clientHeight;
+        const bottom = self.offsetTop + self.clientHeight;
+        const overhang = bottom - bh;
+
+        if (overhang > 0)
+            return bh - self.clientHeight - 25;
+        return self.offsetTop;
+    }
+
+    private changeColorFromPalette(ex: number, ey: number) {
+        const tainer = this.selfRef.current!;
+        const palette = this.paletteRef.current!;
+        let x = ex - tainer.offsetLeft - tainer.clientLeft - palette.offsetLeft - palette.clientLeft;
+        let y = ey - tainer.offsetTop - tainer.clientTop - palette.offsetTop - palette.clientTop;
+
+        if (x < 0)
+            x = 0;
+        else if (x >= palette.width)
+            x = palette.width - 1;
+        if (y < 0)
+            y = 0;
+        else if (y >= palette.height)
+            y = palette.height - 1;
+
+        const { h, s } = this.paletteCoordsToHueSat(x, y);
+        this.updateColorHsv({ h, s, v: this.state.v });
+    }
+
+    private changeColorFromValue(ey: number) {
+        const tainer = this.selfRef.current!;
+        const valCol = this.valueColumnRef.current!;
+        let y = ey - tainer.offsetTop - tainer.clientTop - valCol.offsetTop - valCol.clientTop;
+        if (y < 0)
+            y = 0;
+        else if (y >= valCol.height)
+            y = valCol.height - 1;
+        const v = this.valueColumnCoordToVal(y);
+        this.updateColorHsv({ h: this.state.h, s: this.state.s, v });
+    }
+
+    private dispose() {
+        document.body.removeChild(this.props.parentElement);
+    }
+
+    private drawPalette() {
+        if (!this.paletteRef.current)
+            return;
+
+        const canvas = this.paletteRef.current;
+        const ctx = canvas.getContext('2d');
+        if (!ctx)
+            return;
+
+        this.drawPalleteInternal(ctx, canvas.width, canvas.height);
+        this.drawPaletteCursorInternal(ctx, canvas.width, canvas.height, this.state.h, this.state.s);
+    }
+
+    private drawPalleteInternal(ctx: CanvasRenderingContext2D, width: number, height: number) {
+        const hueStep = 360 / width;
+        const satStep = 1.0 / height;
+
+        ctx.clearRect(0, 0, width, height);
+
+        for (let x = 0; x < width; x++) {
+            const hue = hueStep * x;
+            for (let y = 0; y < height; y++) {
+                const sat = 1.0 - satStep * y;
+
+                ctx.fillStyle = Colors.hsvToHexString(hue, sat, 1.0);
+                ctx.fillRect(x, y, 1, 1);
+            }
+        }
+    }
+
+    private drawPaletteCursor(hue: number, sat: number) {
+        if (!this.paletteRef.current)
+            return;
+
+        const canvas = this.paletteRef.current;
+        const ctx = canvas.getContext('2d');
+        if (!ctx)
+            return;
+
+        this.drawPaletteCursorInternal(ctx, canvas.width, canvas.height, hue, sat);
+    }
+
+    private drawPaletteCursorInternal(ctx: CanvasRenderingContext2D, width: number, height: number, hue: number, sat: number) {
+        const hueStep = 360 / width;
+        const satStep = 1.0 / height;
+        const fullSize = Math.floor(PALETTE_CURSOR_HALFSIZE * 2);
+
+        let fx = Math.floor(this.lastPaletteX - PALETTE_CURSOR_HALFSIZE - 1);
+        if (fx < 0) fx = 0;
+        let tx = fx + fullSize + 2;
+        if (tx > width) tx = width;
+
+        let fy = Math.floor(this.lastPaletteY - PALETTE_CURSOR_HALFSIZE - 1);
+        if (fy < 0) fy = 0;
+        let ty = fy + fullSize + 2;
+        if (ty > height) ty = height;
+
+        for (let x = fx; x < tx; x++) {
+            const hue = hueStep * x;
+            for (let y = fy; y < ty; y++) {
+                const sat = 1.0 - satStep * y;
+
+                ctx.fillStyle = Colors.hsvToHexString(hue, sat, 1.0);
+                ctx.fillRect(x, y, 1, 1);
+            }
+        }
+
+        const cx = Math.round(hue / hueStep);
+        const cy = Math.round((1.0 - sat) / satStep);
+
+        ctx.beginPath();
+        ctx.fillStyle = 'rgba(0, 0, 0, 1.0)';
+        ctx.lineWidth = 2;
+        ctx.moveTo(cx - PALETTE_CURSOR_HALFSIZE, cy);
+        ctx.lineTo(cx + PALETTE_CURSOR_HALFSIZE, cy);
+        ctx.moveTo(cx, cy - PALETTE_CURSOR_HALFSIZE);
+        ctx.lineTo(cx, cy + PALETTE_CURSOR_HALFSIZE);
+        ctx.closePath();
+        ctx.stroke();
+
+        this.lastPaletteX = cx;
+        this.lastPaletteY = cy;
+    }
+
+    private drawValueColumn() {
+        if (!this.valueColumnRef.current)
+            return;
+
+        const canvas = this.valueColumnRef.current;
+        const ctx = canvas.getContext('2d');
+        if (!ctx)
+            return;
+
+        this.drawValueColumnInternal(ctx, canvas.width, canvas.height);
+        this.drawValueColumnCursorInternal(ctx, canvas.width, canvas.height, this.state.v);
+    }
+
+    private drawValueColumnInternal(ctx: CanvasRenderingContext2D, width: number, height: number) {
+        const valStep = 1.0 / height;
+
+        for (let y = 0; y < height; y++) {
+            const cv = 1.0 - y * valStep;
+
+            ctx.fillStyle = Colors.hsvToHexString(this.state.h, this.state.s, cv);
+            ctx.fillRect(0, y, width, 1);
+        }
+    }
+
+    private drawValueColumnCursor(val: number) {
+        if (!this.valueColumnRef.current)
+            return;
+
+        const canvas = this.valueColumnRef.current;
+        const ctx = canvas.getContext('2d');
+        if (!ctx)
+            return;
+
+        this.drawValueColumnCursorInternal(ctx, canvas.width, canvas.height, val);
+    }
+
+    private drawValueColumnCursorInternal(ctx: CanvasRenderingContext2D, width: number, height: number, val: number) {
+        const valStep = 1.0 / height;
+
+        let fy = Math.floor(this.lastValueY - 1);
+        if (fy < 0) fy = 0;
+        let ty = Math.floor(fy + VALUE_CURSOR_THICKNESS + 2);
+        if (ty > height)
+            ty = height;
+
+        for (let y = fy; y < ty; y++) {
+            const cv = 1.0 - y * valStep;
+
+            ctx.fillStyle = Colors.hsvToHexString(this.state.h, this.state.s, cv);
+            ctx.fillRect(0, y, width, 1);
+        }
+
+        const y = Math.round((1.0 - val) / valStep);
+        const halfWidth = Math.round(width / 2);
+
+        ctx.fillStyle = 'rgba(255, 255, 255, 1.0)';
+        ctx.fillRect(0, y, halfWidth, VALUE_CURSOR_THICKNESS);
+        ctx.fillStyle = 'rgba(0, 0, 0, 1.0)';
+        ctx.fillRect(halfWidth, y, width - halfWidth, VALUE_CURSOR_THICKNESS);
+
+        this.lastValueY = y;
+    }
+
+    private paletteCoordsToHueSat(x: number, y: number) {
+        const palette = this.paletteRef.current!;
+
+        const h = 360 * x / palette.width;
+        const s = 1.0 - 1.0 * y / palette.height;
+
+        return { h, s };
+    }
+
+    private onGlobalMouseMovedValue = (evt: MouseEvent) => {
+        if ((evt.buttons & 1) === 0) {
+            window.removeEventListener('mousemove', this.onGlobalMouseMovedValue);
+            this.mouseListenerAttached = false;
+            return;
+        }
+
+        this.changeColorFromValue(evt.pageY);
+    };
+
+    private onGlobalMouseMovedPalette = (evt: MouseEvent) => {
+        if ((evt.buttons & 1) === 0) {
+            window.removeEventListener('mousemove', this.onGlobalMouseMovedPalette);
+            this.mouseListenerAttached = false;
+            return;
+        }
+
+        this.changeColorFromPalette(evt.pageX, evt.pageY);
+    };
+
+    private onGlobalTouchMovedPalette = (evt: TouchEvent) => {
+        if (evt.touches.length !== 0)
+            this.changeColorFromPalette(evt.touches[0].pageX, evt.touches[0].pageY);
+    };
+
+    private updateColorHsv(hsv: { h: number, s: number, v: number }) {
+        const rgb = Colors.hsv2rgb(hsv.h, hsv.s, hsv.v);
+        this.updateColor(rgb, hsv);
+    }
+
+    private updateColorRgb(rgb: { r: number, g: number, b: number }) {
+        const hsv = Colors.rgb2hsv(rgb.r, rgb.g, rgb.b);
+        this.updateColor(rgb, hsv);
+    }
+
+    private updateColor(rgb: { r: number, g: number, b: number }, hsv: { h: number, s: number, v: number }) {
+        let update: Partial<State> = { ...hsv };
+        if (this.state.rIn === '')
+            update = { ...update, rIn: rgb.r.toString() };
+        if (this.state.gIn === '')
+            update = { ...update, gIn: rgb.g.toString() };
+        if (this.state.bIn === '')
+            update = { ...update, bIn: rgb.b.toString() };
+        if (this.state.hIn === '')
+            update = { ...update, hIn: hsv.h.toString() };
+        if (this.state.sIn === '')
+            update = { ...update, sIn: hsv.s.toString() };
+        if (this.state.vIn === '')
+            update = { ...update, vIn: hsv.v.toString() };
+
+        this.setState({
+            ...this.state,
+            ...update,
+        });
+    }
+
+    private onGlobalTouchMovedValue = (evt: TouchEvent) => {
+        if (evt.touches.length !== 0)
+            this.changeColorFromValue(evt.touches[0].pageY);
+    };
+
+    private valueColumnCoordToVal(y: number) {
+        const valCol = this.valueColumnRef.current!;
+
+        return 1.0 - 1.0 * y / valCol.height;
+    }
+
+    componentDidMount() {
+        this.drawPalette();
+        this.drawValueColumn();
+
+        this.forceUpdate();
+    }
+
+    componentDidUpdate(_prevProps: ColorPicker.Props, prevState: State) {
+        if (this.state.h !== prevState.h || this.state.s !== prevState.s) {
+            this.drawPaletteCursor(this.state.h, this.state.s);
+            this.drawValueColumn();
+        }
+        if (this.state.v !== prevState.v) {
+            this.drawValueColumnCursor(this.state.v);
+        }
+    }
+
+    componentWillUnmount() {
+        window.removeEventListener('mousemove', this.onGlobalMouseMovedValue);
+        window.removeEventListener('mousemove', this.onGlobalMouseMovedPalette);
+        window.removeEventListener('touchmove', this.onGlobalTouchMovedValue);
+        window.removeEventListener('touchmove', this.onGlobalTouchMovedPalette);
+    }
+
+    render() {
+        return (
+            <div
+                ref={this.selfRef}
+                style={{
+                    background: 'white',
+                    border: '0.15em solid #ccc',
+                    boxShadow: '0 0 0.3em 0 rgba(0, 0, 0, 0.5)',
+                    left: this.calcLeft(),
+                    padding: '0.5em',
+                    position: 'absolute',
+                    top: this.calcTop(),
+                    zIndex: 99,
+                }}
+            >
+                <div
+                    style={{
+                        display: 'grid',
+                        gridColumnGap: '0.5em',
+                        gridTemplateColumns: 'auto auto',
+                        marginBottom: '0.5em',
+                    }}
+                >
+                    <canvas
+                        width={360}
+                        height={256}
+                        ref={this.paletteRef}
+                        onMouseDown={evt => {
+                            if ((evt.buttons & 1) === 0 || this.mouseListenerAttached)
+                                return;
+                            this.changeColorFromPalette(evt.pageX, evt.pageY);
+                            this.mouseListenerAttached = true;
+                            window.addEventListener('mousemove', this.onGlobalMouseMovedPalette);
+                        }}
+                        onMouseUp={evt => {
+                            if (evt.buttons & 1) {
+                                window.removeEventListener('mousemove', this.onGlobalMouseMovedPalette);
+                                this.mouseListenerAttached = false;
+                            }
+                        }}
+                        onTouchStart={evt => {
+                            if (this.touchListenerAttached)
+                                return;
+
+                            window.addEventListener('touchmove', this.onGlobalTouchMovedPalette);
+                            this.touchListenerAttached = true;
+                            if (evt.touches.length !== 0)
+                                this.changeColorFromPalette(evt.touches[0].pageX, evt.touches[0].pageY);
+
+                        }}
+                        onTouchEnd={_evt => {
+                            window.removeEventListener('touchmove', this.onGlobalTouchMovedPalette);
+                            this.touchListenerAttached = false;
+                        }}
+                    />
+                    <canvas
+                        width={30}
+                        height={256}
+                        ref={this.valueColumnRef}
+                        style={{
+                            height: '100%',
+                            width: '1em',
+                        }}
+                        onMouseDown={evt => {
+                            if ((evt.buttons & 1) === 0 || this.mouseListenerAttached)
+                                return;
+                            this.changeColorFromValue(evt.pageY);
+                            this.mouseListenerAttached = true;
+                            window.addEventListener('mousemove', this.onGlobalMouseMovedValue);
+                        }}
+                        onMouseUp={evt => {
+                            if (evt.buttons & 1) {
+                                window.removeEventListener('mousemove', this.onGlobalMouseMovedValue);
+                                this.mouseListenerAttached = false;
+                            }
+                        }}
+                        onTouchStart={evt => {
+                            if (this.touchListenerAttached)
+                                return;
+
+                            window.addEventListener('touchmove', this.onGlobalTouchMovedValue);
+                            this.touchListenerAttached = true;
+                            if (evt.touches.length !== 0)
+                                this.changeColorFromValue(evt.touches[0].pageY);
+
+                        }}
+                        onTouchEnd={_evt => {
+                            window.removeEventListener('touchmove', this.onGlobalTouchMovedValue);
+                            this.touchListenerAttached = false;
+                        }}
+
+                        onWheel={evt => {
+                            if (evt.deltaY === 0)
+                                return;
+                            let v = this.state.v - 0.01 * Math.sign(evt.deltaY);
+                            if (v < 0)
+                                v = 0;
+                            else if (v > 1)
+                                v = 1;
+                            this.setState({ ...this.state, v });
+                        }}
+                    />
+                </div>
+                <div
+                    style={{
+                        display: 'flex',
+                        marginBottom: '0.5em',
+                    }}
+                >
+                    <div
+                        style={{
+                            background: Colors.colorToHexString(this.props.initialColor),
+                            flex: 1,
+                            height: '2em',
+                        }}
+                    />
+                    <div
+                        style={{
+                            background: Colors.colorToHexString(Colors.colorFromHsv(this.state.h, this.state.s, this.state.v)),
+                            flex: 1,
+                            height: '2em',
+                        }}
+                    />
+                </div>
+                <div
+                    style={{
+                        display: 'grid',
+                        gridColumnGap: '0.5em',
+                        gridTemplateColumns: 'auto 4em auto 4em auto 4em',
+                        marginBottom: '0.5em',
+                    }}
+                >
+                    <div>R</div>
+                    <SpinBox
+                        min={MIN_RGB}
+                        max={MAX_RGB}
+                        step={1}
+                        value={this.state.rIn === '' ? null : Math.round(Colors.hsv2rgb(this.state.h, this.state.s, this.state.v).r)}
+                        onChange={rIn => {
+                            if (rIn === '')
+                                this.setState({ ...this.state, rIn });
+                            else {
+                                const r = stoi(rIn);
+                                if (!isRgbVal(r))
+                                    return;
+
+                                const { g, b } = Colors.hsv2rgb(this.state.h, this.state.s, this.state.v);
+                                this.updateColorRgb({ r, g, b });
+                            }
+                        }}
+                        pathPrefix={this.props.pathPrefix}
+                    />
+                    <div>G</div>
+                    <SpinBox
+                        min={MIN_RGB}
+                        max={MAX_RGB}
+                        step={1}
+                        value={this.state.gIn === '' ? null : Math.round(Colors.hsv2rgb(this.state.h, this.state.s, this.state.v).g)}
+                        onChange={gIn => {
+                            if (gIn === '')
+                                this.setState({ ...this.state, gIn });
+                            else {
+                                const g = stoi(gIn);
+                                if (!isRgbVal(g))
+                                    return;
+
+                                const { r, b } = Colors.hsv2rgb(this.state.h, this.state.s, this.state.v);
+                                this.updateColorRgb({ r, g, b });
+                            }
+                        }}
+                        pathPrefix={this.props.pathPrefix}
+                    />
+                    <div>B</div>
+                    <SpinBox
+                        min={MIN_RGB}
+                        max={MAX_RGB}
+                        step={1}
+                        value={this.state.bIn === '' ? null : Math.round(Colors.hsv2rgb(this.state.h, this.state.s, this.state.v).b)}
+                        onChange={bIn => {
+                            if (bIn === '')
+                                this.setState({ ...this.state, bIn });
+                            else {
+                                const b = stoi(bIn);
+                                if (!isRgbVal(b))
+                                    return;
+
+                                const { r, g } = Colors.hsv2rgb(this.state.h, this.state.s, this.state.v);
+                                this.updateColorRgb({ r, g, b });
+                            }
+                        }}
+                        pathPrefix={this.props.pathPrefix}
+                    />
+                </div>
+                <div
+                    style={{
+                        display: 'grid',
+                        gridColumnGap: '0.5em',
+                        gridTemplateColumns: 'auto 4em auto 4em auto 4em',
+                        marginBottom: '0.5em',
+                    }}
+                >
+                    <div>H</div>
+                    <SpinBox
+                        min={MIN_HUE}
+                        max={MAX_HUE}
+                        step={1}
+                        value={this.state.hIn === '' ? null : Math.round(this.state.h)}
+                        onChange={hIn => {
+                            if (hIn === '')
+                                this.setState({ ...this.state, hIn });
+                            else {
+                                const h = stoi(hIn);
+                                if (!isHueVal(h))
+                                    return;
+
+                                this.updateColorHsv({ h, s: this.state.s, v: this.state.v });
+                            }
+                        }}
+                        pathPrefix={this.props.pathPrefix}
+                    />
+                    <div>S</div>
+                    <SpinBox
+                        min={MIN_SATVAL}
+                        max={MAX_SATVAL}
+                        step={1}
+                        value={this.state.sIn === '' ? null : Math.round(this.state.s * 100)}
+                        onChange={sIn => {
+                            if (sIn === '')
+                                this.setState({ ...this.state, sIn });
+                            else {
+                                const s = stoi(sIn);
+                                if (!isSatValVal(s))
+                                    return;
+
+                                this.updateColorHsv({ h: this.state.h, s: s / 100, v: this.state.v });
+                            }
+                        }}
+                        pathPrefix={this.props.pathPrefix}
+                    />
+                    <div>V</div>
+                    <SpinBox
+                        min={MIN_SATVAL}
+                        max={MAX_SATVAL}
+                        step={1}
+                        value={this.state.vIn === '' ? null : Math.round(this.state.v * 100)}
+                        onChange={vIn => {
+                            if (vIn === '')
+                                this.setState({ ...this.state, vIn });
+                            else {
+                                const v = stoi(vIn);
+                                if (!isSatValVal(v))
+                                    return;
+
+                                this.updateColorHsv({ h: this.state.h, s: this.state.s, v: v / 100 });
+                            }
+                        }}
+                        pathPrefix={this.props.pathPrefix}
+                    />
+                </div>
+                <div
+                    style={{
+                        display: 'flex',
+                        gap: '0.5em',
+                    }}
+                >
+                    <PushButton
+                        text='OK'
+                        onClick={() => {
+                            this.props.onColorPicked(Colors.colorFromHsv(this.state.h, this.state.s, this.state.v));
+                            this.dispose();
+                        }}
+                        enabled={true}
+                    />
+                    <PushButton
+                        text='Preview'
+                        onClick={() => {
+                            this.props.onColorPicked(Colors.colorFromHsv(this.state.h, this.state.s, this.state.v));
+                            this.setState({ ...this.state, restoreOnCancel: true });
+                        }}
+                        enabled={true}
+                    />
+                    <PushButton
+                        text='Cancel'
+                        onClick={() => {
+                            if (this.state.restoreOnCancel)
+                                this.props.onColorPicked(this.props.initialColor);
+                            this.dispose();
+                        }}
+                        enabled={true}
+                    />
+                </div>
+            </div>
+        );
+    }
+}
+
+export namespace ColorPicker {
+    export interface OnColorPicked {
+        (color: number): void;
+    }
+
+    export interface Props {
+        initialColor: number;
+        left: number;
+        top: number;
+        onColorPicked: OnColorPicked;
+        parentElement: HTMLElement;
+        pathPrefix: string;
+    }
+
+    export function create<T>(evt: React.MouseEvent<T, MouseEvent>, initialColor: number, handler: OnColorPicked, pathPrefix = '') {
+        const tainer = document.createElement('div');
+        tainer.classList.add('rmsp-color-picker-nest');
+        document.body.appendChild(tainer);
+
+        ReactDOM.render(
+            <ColorPicker
+                initialColor={initialColor}
+                left={evt.clientX}
+                top={evt.clientY}
+                onColorPicked={handler}
+                parentElement={tainer}
+                pathPrefix={pathPrefix}
+            />,
+            tainer
+        );
+    }
+}
diff --git a/src/apps/rednatco/colors.ts b/src/apps/rednatco/colors.ts
new file mode 100644
index 0000000000000000000000000000000000000000..10c4f5650d3b98c58fcb291d3b2f40b13cae8d3e
--- /dev/null
+++ b/src/apps/rednatco/colors.ts
@@ -0,0 +1,309 @@
+/**
+ * Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Lada Biedermannová <Lada.Biedermannova@ibt.cas.cz>
+ * @author Jiří Černý <jiri.cerny@ibt.cas.cz>
+ * @author Michal MalĂ˝ <michal.maly@ibt.cas.cz>
+ * @author Bohdan Schneider <Bohdan.Schneider@ibt.cas.cz>
+ */
+
+import { Color } from '../../mol-util/color';
+
+function ntxs(num: number) {
+    num = Math.round(num);
+    const str = num.toString(16);
+    return num < 16 ? '0' + str : str;
+}
+
+export namespace Colors {
+    export function colorFromRgb(r: number, g: number, b: number) {
+        return Color.fromRgb(r, g, b);
+    }
+
+    export function colorFromHsv(h: number, s: number, v: number) {
+        const { r, g, b } = hsv2rgb(h, s, v);
+        return Color.fromRgb(r, g, b);
+    }
+
+    export function colorToHexString(clr: number) {
+        const [r, g, b] = Color.toRgb(Color(clr));
+        return rgbToHexString(r, g, b);
+    }
+
+    export function colorToHsv(clr: number) {
+        const [r, g, b] = Color.toRgb(Color(clr));
+        return rgb2hsv(r, g, b);
+    }
+
+    export function colorToRgb(clr: number) {
+        const [r, g, b] = Color.toRgb(Color(clr));
+        return { r, g, b };
+    }
+
+    export function hsv2rgb(h: number, s: number, v: number): { r: number, g: number, b: number } {
+        const f = (n: number, k = (n + h / 60) % 6) => v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
+        return { r: f(5) * 255, g: f(3) * 255, b: f(1) * 255 };
+    }
+
+    export function hsvToColor(h: number, s: number, v: number) {
+        const { r, g, b } = hsv2rgb(h, s, v);
+        return Color.fromRgb(r, g, b);
+    }
+
+    export function hsvToHexString(h: number, s: number, v: number) {
+        const { r, g, b } = hsv2rgb(h, s, v);
+        return rgbToHexString(r, g, b);
+    }
+
+    export function rgbToHexString(r: number, g: number, b: number) {
+        return `#${ntxs(r)}${ntxs(g)}${ntxs(b)}`;
+    }
+
+    export function rgb2hsv(r: number, g: number, b: number) {
+        const rabs = r / 255;
+        const gabs = g / 255;
+        const babs = b / 255;
+        const v = Math.max(rabs, gabs, babs);
+        const diff = v - Math.min(rabs, gabs, babs);
+        const diffc = (c: number) => (v - c) / 6 / diff + 1 / 2;
+
+        let h = 0;
+        let s = 0;
+
+        if (diff !== 0) {
+            s = diff / v;
+            const rr = diffc(rabs);
+            const gg = diffc(gabs);
+            const bb = diffc(babs);
+
+            if (rabs === v) {
+                h = bb - gg;
+            } else if (gabs === v) {
+                h = (1 / 3) + rr - bb;
+            } else if (babs === v) {
+                h = (2 / 3) + gg - rr;
+            }
+
+            if (h < 0) {
+                h += 1;
+            } else if (h > 1) {
+                h -= 1;
+            }
+        }
+
+        return { h: h * 360, s, v };
+    }
+}
+
+export namespace NtCColors {
+    export const Classes = {
+        A: Color(0xFFC1C1),
+        B: Color(0xC8CFFF),
+        BII: Color(0x0059DA),
+        miB: Color(0x3BE8FB),
+        Z: Color(0x01F60E),
+        IC: Color(0xFA5CFB),
+        OPN: Color(0xE90000),
+        SYN: Color(0xFFFF01),
+        N: Color(0xF2F2F2),
+    };
+    export type Classes = typeof Classes;
+
+    export const Conformers = {
+        NANT_Upr: Classes.N,
+        NANT_Lwr: Classes.N,
+        AA00_Upr: Classes.A,
+        AA00_Lwr: Classes.A,
+        AA02_Upr: Classes.A,
+        AA02_Lwr: Classes.A,
+        AA03_Upr: Classes.A,
+        AA03_Lwr: Classes.A,
+        AA04_Upr: Classes.A,
+        AA04_Lwr: Classes.A,
+        AA08_Upr: Classes.A,
+        AA08_Lwr: Classes.A,
+        AA09_Upr: Classes.A,
+        AA09_Lwr: Classes.A,
+        AA01_Upr: Classes.A,
+        AA01_Lwr: Classes.A,
+        AA05_Upr: Classes.A,
+        AA05_Lwr: Classes.A,
+        AA06_Upr: Classes.A,
+        AA06_Lwr: Classes.A,
+        AA10_Upr: Classes.A,
+        AA10_Lwr: Classes.A,
+        AA11_Upr: Classes.A,
+        AA11_Lwr: Classes.A,
+        AA07_Upr: Classes.A,
+        AA07_Lwr: Classes.A,
+        AA12_Upr: Classes.A,
+        AA12_Lwr: Classes.A,
+        AA13_Upr: Classes.A,
+        AA13_Lwr: Classes.A,
+        AB01_Upr: Classes.A,
+        AB01_Lwr: Classes.B,
+        AB02_Upr: Classes.A,
+        AB02_Lwr: Classes.B,
+        AB03_Upr: Classes.A,
+        AB03_Lwr: Classes.B,
+        AB04_Upr: Classes.A,
+        AB04_Lwr: Classes.B,
+        AB05_Upr: Classes.A,
+        AB05_Lwr: Classes.B,
+        BA01_Upr: Classes.B,
+        BA01_Lwr: Classes.A,
+        BA05_Upr: Classes.B,
+        BA05_Lwr: Classes.A,
+        BA09_Upr: Classes.B,
+        BA09_Lwr: Classes.A,
+        BA08_Upr: Classes.BII,
+        BA08_Lwr: Classes.A,
+        BA10_Upr: Classes.B,
+        BA10_Lwr: Classes.A,
+        BA13_Upr: Classes.BII,
+        BA13_Lwr: Classes.A,
+        BA16_Upr: Classes.BII,
+        BA16_Lwr: Classes.A,
+        BA17_Upr: Classes.BII,
+        BA17_Lwr: Classes.A,
+        BB00_Upr: Classes.B,
+        BB00_Lwr: Classes.B,
+        BB01_Upr: Classes.B,
+        BB01_Lwr: Classes.B,
+        BB17_Upr: Classes.B,
+        BB17_Lwr: Classes.B,
+        BB02_Upr: Classes.B,
+        BB02_Lwr: Classes.B,
+        BB03_Upr: Classes.B,
+        BB03_Lwr: Classes.B,
+        BB11_Upr: Classes.B,
+        BB11_Lwr: Classes.B,
+        BB16_Upr: Classes.B,
+        BB16_Lwr: Classes.B,
+        BB04_Upr: Classes.B,
+        BB04_Lwr: Classes.BII,
+        BB05_Upr: Classes.B,
+        BB05_Lwr: Classes.BII,
+        BB07_Upr: Classes.BII,
+        BB07_Lwr: Classes.BII,
+        BB08_Upr: Classes.BII,
+        BB08_Lwr: Classes.BII,
+        BB10_Upr: Classes.miB,
+        BB10_Lwr: Classes.miB,
+        BB12_Upr: Classes.miB,
+        BB12_Lwr: Classes.miB,
+        BB13_Upr: Classes.miB,
+        BB13_Lwr: Classes.miB,
+        BB14_Upr: Classes.miB,
+        BB14_Lwr: Classes.miB,
+        BB15_Upr: Classes.miB,
+        BB15_Lwr: Classes.miB,
+        BB20_Upr: Classes.miB,
+        BB20_Lwr: Classes.miB,
+        IC01_Upr: Classes.IC,
+        IC01_Lwr: Classes.IC,
+        IC02_Upr: Classes.IC,
+        IC02_Lwr: Classes.IC,
+        IC03_Upr: Classes.IC,
+        IC03_Lwr: Classes.IC,
+        IC04_Upr: Classes.IC,
+        IC04_Lwr: Classes.IC,
+        IC05_Upr: Classes.IC,
+        IC05_Lwr: Classes.IC,
+        IC06_Upr: Classes.IC,
+        IC06_Lwr: Classes.IC,
+        IC07_Upr: Classes.IC,
+        IC07_Lwr: Classes.IC,
+        OP01_Upr: Classes.OPN,
+        OP01_Lwr: Classes.OPN,
+        OP02_Upr: Classes.OPN,
+        OP02_Lwr: Classes.OPN,
+        OP03_Upr: Classes.OPN,
+        OP03_Lwr: Classes.OPN,
+        OP04_Upr: Classes.OPN,
+        OP04_Lwr: Classes.OPN,
+        OP05_Upr: Classes.OPN,
+        OP05_Lwr: Classes.OPN,
+        OP06_Upr: Classes.OPN,
+        OP06_Lwr: Classes.OPN,
+        OP07_Upr: Classes.OPN,
+        OP07_Lwr: Classes.OPN,
+        OP08_Upr: Classes.OPN,
+        OP08_Lwr: Classes.OPN,
+        OP09_Upr: Classes.OPN,
+        OP09_Lwr: Classes.OPN,
+        OP10_Upr: Classes.OPN,
+        OP10_Lwr: Classes.OPN,
+        OP11_Upr: Classes.OPN,
+        OP11_Lwr: Classes.OPN,
+        OP12_Upr: Classes.OPN,
+        OP12_Lwr: Classes.OPN,
+        OP13_Upr: Classes.OPN,
+        OP13_Lwr: Classes.OPN,
+        OP14_Upr: Classes.OPN,
+        OP14_Lwr: Classes.OPN,
+        OP15_Upr: Classes.OPN,
+        OP15_Lwr: Classes.OPN,
+        OP16_Upr: Classes.OPN,
+        OP16_Lwr: Classes.OPN,
+        OP17_Upr: Classes.OPN,
+        OP17_Lwr: Classes.OPN,
+        OP18_Upr: Classes.OPN,
+        OP18_Lwr: Classes.OPN,
+        OP19_Upr: Classes.OPN,
+        OP19_Lwr: Classes.OPN,
+        OP20_Upr: Classes.OPN,
+        OP20_Lwr: Classes.OPN,
+        OP21_Upr: Classes.OPN,
+        OP21_Lwr: Classes.OPN,
+        OP22_Upr: Classes.OPN,
+        OP22_Lwr: Classes.OPN,
+        OP23_Upr: Classes.OPN,
+        OP23_Lwr: Classes.OPN,
+        OP24_Upr: Classes.OPN,
+        OP24_Lwr: Classes.OPN,
+        OP25_Upr: Classes.OPN,
+        OP25_Lwr: Classes.OPN,
+        OP26_Upr: Classes.OPN,
+        OP26_Lwr: Classes.OPN,
+        OP27_Upr: Classes.OPN,
+        OP27_Lwr: Classes.OPN,
+        OP28_Upr: Classes.OPN,
+        OP28_Lwr: Classes.OPN,
+        OP29_Upr: Classes.OPN,
+        OP29_Lwr: Classes.OPN,
+        OP30_Upr: Classes.OPN,
+        OP30_Lwr: Classes.OPN,
+        OP31_Upr: Classes.OPN,
+        OP31_Lwr: Classes.OPN,
+        OPS1_Upr: Classes.OPN,
+        OPS1_Lwr: Classes.OPN,
+        OP1S_Upr: Classes.OPN,
+        OP1S_Lwr: Classes.OPN,
+        AAS1_Upr: Classes.SYN,
+        AAS1_Lwr: Classes.A,
+        AB1S_Upr: Classes.A,
+        AB1S_Lwr: Classes.SYN,
+        AB2S_Upr: Classes.A,
+        AB2S_Lwr: Classes.SYN,
+        BB1S_Upr: Classes.B,
+        BB1S_Lwr: Classes.SYN,
+        BB2S_Upr: Classes.B,
+        BB2S_Lwr: Classes.SYN,
+        BBS1_Upr: Classes.SYN,
+        BBS1_Lwr: Classes.B,
+        ZZ01_Upr: Classes.Z,
+        ZZ01_Lwr: Classes.Z,
+        ZZ02_Upr: Classes.Z,
+        ZZ02_Lwr: Classes.Z,
+        ZZ1S_Upr: Classes.Z,
+        ZZ1S_Lwr: Classes.SYN,
+        ZZ2S_Upr: Classes.Z,
+        ZZ2S_Lwr: Classes.SYN,
+        ZZS1_Upr: Classes.SYN,
+        ZZS1_Lwr: Classes.Z,
+        ZZS2_Upr: Classes.SYN,
+        ZZS2_Lwr: Classes.Z,
+    };
+    export type Conformers = typeof Conformers;
+}
diff --git a/src/apps/rednatco/controls.tsx b/src/apps/rednatco/controls.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..62e751bb9a005bc9f6404753cde5d13949e79a06
--- /dev/null
+++ b/src/apps/rednatco/controls.tsx
@@ -0,0 +1,113 @@
+import React from 'react';
+
+export class PushButton extends React.Component<{ text: string, enabled: boolean, onClick: () => void }> {
+    render() {
+        return (
+            <div
+                className={`rmsp-pushbutton ${this.props.enabled ? '' : 'rmsp-pushbutton-disabled'}`}
+                onClick={() => this.props.enabled ? this.props.onClick() : {}}
+            >
+                <div className={`${this.props.enabled ? 'rmsp-pushbutton-text' : 'rmsp-pushbutton-text-disabled'}`}>{this.props.text}</div>
+            </div>
+        );
+    }
+}
+
+export class ToggleButton extends React.Component<{ text: string, enabled: boolean, switchedOn: boolean, onClick: () => void }> {
+    render() {
+        return (
+            <div
+                className={`rmsp-pushbutton ${this.props.enabled ? (this.props.switchedOn ? 'rmsp-togglebutton-switched-on' : 'rmsp-togglebutton-switched-off') : 'rmsp-pushbutton-disabled'}`}
+                onClick={() => this.props.enabled ? this.props.onClick() : {}}
+            >
+                <div className={`${this.props.enabled ? 'rmsp-pushbutton-text' : 'rmsp-pushbutton-text-disabled'}`}>{this.props.text}</div>
+            </div>
+        );
+    }
+}
+
+export class SpinBox extends React.Component<SpinBox.Props> {
+    private clsDisabled() {
+        return this.props.classNameDisabled ?? 'rmsp-spinbox-input-disabled';
+    }
+
+    private clsEnabled() {
+        return this.props.className ?? 'rmsp-spinbox-input';
+    }
+
+    private decrease() {
+        if (this.props.value === null)
+            return;
+        const nv = this.props.value - this.props.step;
+        if (nv >= this.props.min)
+            this.props.onChange(nv.toString());
+    }
+
+    private increase() {
+        if (this.props.value === null)
+            return;
+        const nv = this.props.value + this.props.step;
+        if (nv >= this.props.min)
+            this.props.onChange(nv.toString());
+    }
+
+    render() {
+        return (
+            <div className='rmsp-spinbox-container'>
+                <input
+                    type='text'
+                    className={this.props.disabled ? this.clsDisabled() : this.clsEnabled()}
+                    value={this.props.formatter ? this.props.formatter(this.props.value) : this.props.value?.toString() ?? ''}
+                    onChange={evt => this.props.onChange(evt.currentTarget.value)}
+                    onWheel={evt => {
+                        evt.stopPropagation();
+                        if (this.props.value === null)
+                            return;
+                        if (evt.deltaY < 0) {
+                            const nv = this.props.value + this.props.step;
+                            if (nv <= this.props.max)
+                                this.props.onChange(nv.toString());
+                        } else if (evt.deltaY > 0) {
+                            const nv = this.props.value - this.props.step;
+                            if (nv >= this.props.min)
+                                this.props.onChange(nv.toString());
+                        }
+                    }}
+                />
+                <div className='rmsp-spinbox-buttons'>
+                    <img
+                        className='rmsp-spinbox-button'
+                        src={`./${this.props.pathPrefix}assets/imgs/triangle-up.svg`} onClick={() => this.increase()}
+                    />
+                    <img
+                        className='rmsp-spinbox-button'
+                        src={`./${this.props.pathPrefix}assets/imgs/triangle-down.svg`} onClick={() => this.decrease()}
+                    />
+                </div>
+            </div>
+        );
+    }
+}
+
+export namespace SpinBox {
+    export interface Formatter {
+        (v: number|null): string;
+    }
+
+    export interface OnChange {
+        (newValue: string): void;
+    }
+
+    export interface Props {
+        value: number|null;
+        onChange: OnChange;
+        min: number;
+        max: number;
+        step: number;
+        pathPrefix: string;
+        disabled?: boolean;
+        className?: string;
+        classNameDisabled?: string;
+        formatter?: Formatter;
+    }
+}
diff --git a/src/apps/rednatco/idents.ts b/src/apps/rednatco/idents.ts
index 7f3a731cebc5b731210f265e6b09c85645eef76c..b83cb834a7ecf37814f9ddc183d61fed46f7516b 100644
--- a/src/apps/rednatco/idents.ts
+++ b/src/apps/rednatco/idents.ts
@@ -1,8 +1,12 @@
-export type ID ='data'|'structure'|'visual'|'pyramids';
+export type ID ='data'|'trajectory'|'model'|'structure'|'visual'|'pyramids';
 export type Substructure = 'nucleic'|'protein'|'water';
 
 export function ID(id: ID, sub: Substructure|'', ref: string) {
     if (sub === '')
-        return `${id}_${ref}`;
-    return `${id}_${sub}_${ref}`;
+        return `${ref}_${id}`;
+    return `${ref}_${sub}_${id}`;
+}
+
+export function isVisual(ident: string) {
+    return ident.endsWith('_visual');
 }
diff --git a/src/apps/rednatco/index.html b/src/apps/rednatco/index.html
index 653f6c175698cc6d9145d64f721a2e15b2fa78b0..675cf4b28021d521a09995abe8fa61f3637236cd 100644
--- a/src/apps/rednatco/index.html
+++ b/src/apps/rednatco/index.html
@@ -4,8 +4,8 @@
         <meta charset="utf-8" />
         <link rel="stylesheet" type="text/css" href="molstar.css" />
     </head>
-    <body style="height: 100vh; width: 100hw">
-        <div id="xxx-app" style="height: 100%; width: 100%"></div>
+    <body style="height: 100vh; display: flex; overflow: hidden;">
+        <div id="xxx-app" style="flex: 1"></div>
         <script type="text/javascript" src="./molstar.js"></script>
         <script>
             async function loadStructure() {
diff --git a/src/apps/rednatco/index.tsx b/src/apps/rednatco/index.tsx
index 8ad2b7d1c566adead36f834aa2350b63447fde61..4085262b6ec37991309fb062cf70f8c2ee4aee4f 100644
--- a/src/apps/rednatco/index.tsx
+++ b/src/apps/rednatco/index.tsx
@@ -1,11 +1,15 @@
 import React from 'react';
 import ReactDOM from 'react-dom';
+import { NtCColors } from './colors';
+import { ColorPicker } from './color-picker';
+import { PushButton, ToggleButton } from './controls';
 import * as IDs from './idents';
 import { DnatcoConfalPyramids } from '../../extensions/dnatco';
 import { ConfalPyramidsParams } from '../../extensions/dnatco/confal-pyramids/representation';
-import { ConfalPyramidsColorThemeParams } from '../../extensions/dnatco/confal-pyramids/color';
+import { BoundaryHelper } from '../../mol-math/geometry/boundary-helper';
 import { Loci } from '../../mol-model/loci';
-import { Structure } from '../../mol-model/structure';
+import { Model, Structure, Trajectory } from '../../mol-model/structure';
+import { MmcifFormat } from '../../mol-model-formats/structure/mmcif';
 import { PluginBehavior, PluginBehaviors } from '../../mol-plugin/behavior';
 import { PluginCommands } from '../../mol-plugin/commands';
 import { PluginContext } from '../../mol-plugin/context';
@@ -18,8 +22,9 @@ import { createPluginUI } from '../../mol-plugin-ui';
 import { PluginUIContext } from '../../mol-plugin-ui/context';
 import { DefaultPluginUISpec, PluginUISpec } from '../../mol-plugin-ui/spec';
 import { Representation } from '../../mol-repr/representation';
-import { StateSelection } from '../../mol-state';
+import { StateObjectCell, StateObject, StateSelection } from '../../mol-state';
 import { StateTreeSpine } from '../../mol-state/tree/spine';
+import { Script } from '../../mol-script/script';
 import { lociLabel } from '../../mol-theme/label';
 import { Color } from '../../mol-util/color';
 import { arrayMax } from '../../mol-util/array';
@@ -39,6 +44,9 @@ const Extensions = {
 const BaseRef = 'rdo';
 const AnimationDurationMsec = 150;
 
+const SelectAllScript = Script('(sel.atom.atoms true)', 'mol-script');
+const SphereBoundaryHelper = new BoundaryHelper('98');
+
 function capitalize(s: string) {
     if (s.length === 0)
         return s;
@@ -46,31 +54,32 @@ function capitalize(s: string) {
 
 }
 
-class PushButton extends React.Component<{ caption: string, enabled: boolean, onClick: () => void }> {
+class ColorBox extends React.Component<{ caption: string, color: Color }> {
     render() {
         return (
-            <div
-                className={`rmsp-pushbutton ${this.props.enabled ? '' : 'rmsp-pushbutton-disabled'}`}
-                onClick={() => this.props.enabled ? this.props.onClick() : {}}
-            >
-                <div className={`${this.props.enabled ? 'rmsp-pushbutton-text' : 'rmsp-pushbutton-text-disabled'}`}>{this.props.caption}</div>
+            <div className='rmsp-color-box'>
+                <div className='rmsp-color-box-caption'>{this.props.caption}</div>
+                <div
+                    className='rmsp-color-box-color'
+                    style={{ backgroundColor: Color.toStyle(this.props.color) }}
+                />
             </div>
         );
     }
 }
 
-class ToggleButton extends React.Component<{ caption: string, enabled: boolean, switchedOn: boolean, onClick: () => void }> {
-    render() {
-        return (
-            <div
-                className={`rmsp-pushbutton ${this.props.enabled ? (this.props.switchedOn ? 'rmsp-togglebutton-switched-on' : 'rmsp-togglebutton-switched-off') : 'rmsp-pushbutton-disabled'}`}
-                onClick={() => this.props.enabled ? this.props.onClick() : {}}
-            >
-                <div className={`${this.props.enabled ? 'rmsp-pushbutton-text' : 'rmsp-pushbutton-text-disabled'}`}>{this.props.caption}</div>
-            </div>
-        );
-    }
-}
+const ConformersByClass = {
+    A: ['AA00_Upr', 'AA00_Lwr', 'AA02_Upr', 'AA02_Lwr', 'AA03_Upr', 'AA03_Lwr', 'AA04_Upr', 'AA04_Lwr', 'AA08_Upr', 'AA08_Lwr', 'AA09_Upr', 'AA09_Lwr', 'AA01_Upr', 'AA01_Lwr', 'AA05_Upr', 'AA05_Lwr', 'AA06_Upr', 'AA06_Lwr', 'AA10_Upr', 'AA10_Lwr', 'AA11_Upr', 'AA11_Lwr', 'AA07_Upr', 'AA07_Lwr', 'AA12_Upr', 'AA12_Lwr', 'AA13_Upr', 'AA13_Lwr', 'AB01_Upr', 'AB02_Upr', 'AB03_Upr', 'AB04_Upr', 'AB05_Upr', 'BA01_Lwr', 'BA05_Lwr', 'BA09_Lwr', 'BA08_Lwr', 'BA10_Lwr', 'BA13_Lwr', 'BA16_Lwr', 'BA17_Lwr', 'AAS1_Lwr', 'AB1S_Upr'],
+    B: ['AB01_Lwr', 'AB02_Lwr', 'AB03_Lwr', 'AB04_Lwr', 'AB05_Lwr', 'BA09_Upr', 'BA10_Upr', 'BB00_Upr', 'BB00_Lwr', 'BB01_Upr', 'BB01_Lwr', 'BB17_Upr', 'BB17_Lwr', 'BB02_Upr', 'BB02_Lwr', 'BB03_Upr', 'BB03_Lwr', 'BB11_Upr', 'BB11_Lwr', 'BB16_Upr', 'BB16_Lwr', 'BB04_Upr', 'BB05_Upr', 'BB1S_Upr', 'BB2S_Upr', 'BBS1_Lwr'],
+    BII: ['BA08_Upr', 'BA13_Upr', 'BA16_Upr', 'BA17_Upr', 'BB04_Lwr', 'BB05_Lwr', 'BB07_Upr', 'BB07_Lwr', 'BB08_Upr', 'BB08_Lwr'],
+    miB: ['BB10_Upr', 'BB10_Lwr', 'BB12_Upr', 'BB12_Lwr', 'BB13_Upr', 'BB13_Lwr', 'BB14_Upr', 'BB14_Lwr', 'BB15_Upr', 'BB15_Lwr', 'BB20_Upr', 'BB20_Lwr'],
+    IC: ['IC01_Upr', 'IC01_Lwr', 'IC02_Upr', 'IC02_Lwr', 'IC03_Upr', 'IC03_Lwr', 'IC04_Upr', 'IC04_Lwr', 'IC05_Upr', 'IC05_Lwr', 'IC06_Upr', 'IC06_Lwr', 'IC07_Upr', 'IC07_Lwr'],
+    OPN: ['OP01_Upr', 'OP01_Lwr', 'OP02_Upr', 'OP02_Lwr', 'OP03_Upr', 'OP03_Lwr', 'OP04_Upr', 'OP04_Lwr', 'OP05_Upr', 'OP05_Lwr', 'OP06_Upr', 'OP06_Lwr', 'OP07_Upr', 'OP07_Lwr', 'OP08_Upr', 'OP08_Lwr', 'OP09_Upr', 'OP09_Lwr', 'OP10_Upr', 'OP10_Lwr', 'OP11_Upr', 'OP11_Lwr', 'OP12_Upr', 'OP12_Lwr', 'OP13_Upr', 'OP13_Lwr', 'OP14_Upr', 'OP14_Lwr', 'OP15_Upr', 'OP15_Lwr', 'OP16_Upr', 'OP16_Lwr', 'OP17_Upr', 'OP17_Lwr', 'OP18_Upr', 'OP18_Lwr', 'OP19_Upr', 'OP19_Lwr', 'OP20_Upr', 'OP20_Lwr', 'OP21_Upr', 'OP21_Lwr', 'OP22_Upr', 'OP22_Lwr', 'OP23_Upr', 'OP23_Lwr', 'OP24_Upr', 'OP24_Lwr', 'OP25_Upr', 'OP25_Lwr', 'OP26_Upr', 'OP26_Lwr', 'OP27_Upr', 'OP27_Lwr', 'OP28_Upr', 'OP28_Lwr', 'OP29_Upr', 'OP29_Lwr', 'OP30_Upr', 'OP30_Lwr', 'OP31_Upr', 'OP31_Lwr', 'OPS1_Upr', 'OPS1_Lwr', 'OP1S_Upr', 'OP1S_Lwr'],
+    SYN: ['AAS1_Upr', 'AB1S_Lwr', 'AB2S_Lwr', 'BB1S_Lwr', 'BB2S_Lwr', 'BBS1_Upr', 'ZZ1S_Lwr', 'ZZ2S_Lwr', 'ZZS1_Upr', 'ZZS2_Upr'],
+    Z: ['ZZ01_Upr', 'ZZ01_Lwr', 'ZZ02_Upr', 'ZZ02_Lwr', 'ZZ1S_Upr', 'ZZ2S_Upr', 'ZZS1_Lwr', 'ZZS2_Lwr'],
+    N: ['NANT_Upr', 'NANT_Lwr'],
+};
+type ConformersByClass = typeof ConformersByClass;
 
 const Display = {
     representation: 'cartoon',
@@ -80,8 +89,15 @@ const Display = {
     showWater: false,
 
     showPyramids: true,
+    pyramidsTransparent: false,
+
+    showBalls: false,
+    ballsTransparent: false,
 
     modelNumber: 1,
+
+    classColors: { ...NtCColors.Classes },
+    conformerColors: { ...NtCColors.Conformers },
 };
 type Display = typeof Display;
 
@@ -228,23 +244,61 @@ class ReDNATCOMspViewer {
         return this.plugin.state.data.build().to(IDs.ID(id, sub, ref));
     }
 
-    private pyramidsParams(colors: Map<string, Color>, visible: Map<string, boolean>, transparent: boolean) {
+    private getStructureParent(cell: StateObjectCell) {
+        if (!cell.sourceRef)
+            return undefined;
+        const parent = this.plugin.state.data.cells.get(cell.sourceRef);
+        if (!parent)
+            return undefined;
+        return parent.obj?.type.name === 'Structure' ? parent.obj : undefined;
+    }
+
+    private pyramidsParams(colors: NtCColors.Conformers, visible: Map<string, boolean>, transparent: boolean) {
         const typeParams = {} as PD.Values<ConfalPyramidsParams>;
         for (const k of Reflect.ownKeys(ConfalPyramidsParams) as (keyof ConfalPyramidsParams)[]) {
             if (ConfalPyramidsParams[k].type === 'boolean')
                 (typeParams[k] as any) = visible.get(k) ?? ConfalPyramidsParams[k]['defaultValue'];
         }
 
-        const colorParams = {} as Record<string, Color>; // HAKZ until we implement changeable pyramid colors in Molstar !!!
-        for (const k of Reflect.ownKeys(ConfalPyramidsColorThemeParams) as (keyof ConfalPyramidsColorThemeParams)[])
-            colorParams[k] = colors.get(k) ?? ConfalPyramidsColorThemeParams[k]['defaultValue'];
-
         return {
             type: { name: 'confal-pyramids', params: { ...typeParams, alpha: transparent ? 0.5 : 1.0 } },
-            colorTheme: { name: 'confal-pyramids', params: colorParams }
+            colorTheme: { name: 'confal-pyramids', params: colors }
         };
     }
 
+    private resetCameraRadius() {
+        if (!this.plugin.canvas3d)
+            return;
+
+        const spheres = [];
+        for (const [ref, cell] of Array.from(this.plugin.state.data.cells)) {
+            if (!IDs.isVisual(ref))
+                continue;
+            const parent = this.getStructureParent(cell);
+            if (parent) {
+                const s = Loci.getBoundingSphere(Script.toLoci(SelectAllScript, parent.data));
+                if (s)
+                    spheres.push(s);
+            }
+        }
+
+        if (spheres.length === 0)
+            return;
+
+        SphereBoundaryHelper.reset();
+        for (const s of spheres)
+            SphereBoundaryHelper.includePositionRadius(s.center, s.radius);
+        SphereBoundaryHelper.finishedIncludeStep();
+        for (const s of spheres)
+            SphereBoundaryHelper.radiusPositionRadius(s.center, s.radius);
+        const bs = SphereBoundaryHelper.getSphere();
+
+        const snapshot = this.plugin.canvas3d.camera.getSnapshot();
+        snapshot.radius = bs.radius;
+        snapshot.target = bs.center;
+        PluginCommands.Camera.SetSnapshot(this.plugin, { snapshot, durationMs: AnimationDurationMsec });
+    }
+
     static async create(target: HTMLElement) {
         const defaultSpec = DefaultPluginUISpec();
         const spec: PluginUISpec = {
@@ -281,6 +335,50 @@ class ReDNATCOMspViewer {
         return new ReDNATCOMspViewer(plugin);
     }
 
+    async changeNtCColors(display: Partial<Display>) {
+        if (!this.has('pyramids', 'nucleic'))
+            return;
+
+        const b = this.plugin.state.data.build().to(IDs.ID('pyramids', 'nucleic', BaseRef));
+        b.update(
+            StateTransforms.Representation.StructureRepresentation3D,
+            old => ({
+                ...old,
+                colorTheme: { name: 'confal-pyramids', params: display.conformerColors ?? NtCColors.Conformers },
+            })
+        );
+
+        await b.commit();
+    }
+
+    async changePyramids(display: Partial<Display>) {
+        if (display.showPyramids) {
+            if (!this.has('pyramids', 'nucleic')) {
+                const b = this.getBuilder('structure', 'nucleic');
+                if (b) {
+                    b.apply(
+                        StateTransforms.Representation.StructureRepresentation3D,
+                        this.pyramidsParams(display.conformerColors ?? NtCColors.Conformers, new Map(), display.pyramidsTransparent ?? false),
+                        { ref: IDs.ID('pyramids', 'nucleic', BaseRef) }
+                    );
+                    await b.commit();
+                }
+            } else {
+                const b = this.getBuilder('pyramids', 'nucleic');
+                b.update(
+                    StateTransforms.Representation.StructureRepresentation3D,
+                    old => ({
+                        ...old,
+                        ...this.pyramidsParams(display.conformerColors ?? NtCColors.Conformers, new Map(), display.pyramidsTransparent ?? false),
+                    })
+                );
+                await b.commit();
+            }
+        } else {
+            await PluginCommands.State.RemoveObject(this.plugin, { state: this.plugin.state.data, ref: IDs.ID('pyramids', 'nucleic', BaseRef) });
+        }
+    }
+
     async changeRepresentation(display: Partial<Display>) {
         const b = this.plugin.state.data.build();
         const repr = display.representation ?? 'cartoon';
@@ -301,18 +399,74 @@ class ReDNATCOMspViewer {
         await b.commit();
     }
 
+    getModelCount() {
+        const obj = this.plugin.state.data.cells.get(IDs.ID('trajectory', '', BaseRef))?.obj;
+        if (!obj)
+            return 0;
+        return (obj as StateObject<Trajectory>).data.frameCount;
+    }
+
+    getPresentConformers() {
+        const obj = this.plugin.state.data.cells.get(IDs.ID('model', '', BaseRef))?.obj;
+        if (!obj)
+            return [];
+        const model = (obj as StateObject<Model>);
+        const modelNum = model.data.modelNum;
+        const sourceData = model.data.sourceData;
+        if (MmcifFormat.is(sourceData)) {
+            const tableSum = sourceData.data.frame.categories['ndb_struct_ntc_step_summary'];
+            const tableStep = sourceData.data.frame.categories['ndb_struct_ntc_step'];
+            if (!tableSum || !tableStep) {
+                console.warn('NtC information not present');
+                return [];
+            }
+
+            const _stepIds = tableSum.getField('step_id');
+            const _assignedNtCs = tableSum.getField('assigned_NtC');
+            const _ids = tableStep.getField('id');
+            const _modelNos = tableStep.getField('PDB_model_number');
+            if (!_stepIds || !_assignedNtCs || !_ids || !_modelNos) {
+                console.warn('Expected fields are not present in NtC categories');
+                return [];
+            }
+
+            const stepIds = _stepIds.toIntArray();
+            const assignedNtCs = _assignedNtCs.toStringArray();
+            const ids = _ids.toIntArray();
+            const modelNos = _modelNos.toIntArray();
+
+            const present = new Array<string>();
+            for (let row = 0; row < stepIds.length; row++) {
+                const idx = ids.indexOf(stepIds[row]);
+                if (modelNos[idx] === modelNum) {
+                    const ntc = assignedNtCs[row];
+                    if (!present.includes(ntc))
+                        present.push(ntc);
+                }
+            }
+
+            present.sort();
+            return present;
+        }
+        return [];
+    }
+
     has(id: IDs.ID, sub: IDs.Substructure|'' = '', ref = BaseRef) {
         return !!this.plugin.state.data.cells.get(IDs.ID(id, sub, ref))?.obj;
     }
 
+    isReady() {
+        return this.has('structure', '', BaseRef);
+    }
+
     async loadStructure(data: string, type: 'pdb'|'cif', display: Partial<Display>) {
         await this.plugin.state.data.build().toRoot().commit();
 
         const b = (t => type === 'pdb'
-            ? t.apply(StateTransforms.Model.TrajectoryFromPDB)
-            : t.apply(StateTransforms.Data.ParseCif).apply(StateTransforms.Model.TrajectoryFromMmCif)
+            ? t.apply(StateTransforms.Model.TrajectoryFromPDB, {}, { ref: IDs.ID('trajectory', '', BaseRef) })
+            : t.apply(StateTransforms.Data.ParseCif).apply(StateTransforms.Model.TrajectoryFromMmCif, {}, { ref: IDs.ID('trajectory', '', BaseRef) })
         )(this.plugin.state.data.build().toRoot().apply(RawData, { data }, { ref: IDs.ID('data', '', BaseRef) }))
-            .apply(StateTransforms.Model.ModelFromTrajectory, { modelIndex: 0 })
+            .apply(StateTransforms.Model.ModelFromTrajectory, { modelIndex: display.modelNumber ? display.modelNumber - 1 : 0 }, { ref: IDs.ID('model', '', BaseRef) })
             .apply(StateTransforms.Model.StructureFromModel, {}, { ref: IDs.ID('structure', '', BaseRef) })
             // Extract substructures
             .apply(StateTransforms.Model.StructureComplexElement, { type: 'nucleic' }, { ref: IDs.ID('structure', 'nucleic', BaseRef) })
@@ -338,7 +492,7 @@ class ReDNATCOMspViewer {
                 bb.to(IDs.ID('structure', 'nucleic', BaseRef))
                     .apply(
                         StateTransforms.Representation.StructureRepresentation3D,
-                        this.pyramidsParams(new Map(), new Map(), false),
+                        this.pyramidsParams(display.conformerColors ?? NtCColors.Conformers, new Map(), false),
                         { ref: IDs.ID('pyramids', 'nucleic', BaseRef) }
                     );
             }
@@ -367,24 +521,17 @@ class ReDNATCOMspViewer {
         await bb.commit();
     }
 
-    isReady() {
-        return this.has('structure', '', BaseRef);
-    }
+    async switchModel(display: Partial<Display>) {
+        const b = this.getBuilder('model', '', BaseRef);
+        b.update(
+            StateTransforms.Model.ModelFromTrajectory,
+            old => ({
+                ...old,
+                modelIndex: display.modelNumber ? display.modelNumber - 1 : 0
+            })
+        );
 
-    async togglePyramids(display: Partial<Display>) {
-        if (display.showPyramids && !this.has('pyramids', 'nucleic')) {
-            const b = this.getBuilder('structure', 'nucleic');
-            if (b) {
-                b.apply(
-                    StateTransforms.Representation.StructureRepresentation3D,
-                    this.pyramidsParams(new Map(), new Map(), false),
-                    { ref: IDs.ID('pyramids', 'nucleic', BaseRef) }
-                );
-                await b.commit();
-            }
-        } else {
-            await PluginCommands.State.RemoveObject(this.plugin, { state: this.plugin.state.data, ref: IDs.ID('pyramids', 'nucleic', BaseRef) });
-        }
+        await b.commit();
     }
 
     async toggleSubstructure(sub: IDs.Substructure, display: Partial<Display>) {
@@ -404,28 +551,67 @@ class ReDNATCOMspViewer {
                 );
                 await b.commit();
             }
-        } else
+        } else {
             await PluginCommands.State.RemoveObject(this.plugin, { state: this.plugin.state.data, ref: IDs.ID('visual', sub, BaseRef) });
+            this.resetCameraRadius();
+        }
     }
 }
 
 interface State {
     display: Display;
+    showControls: boolean;
 }
 class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
+    private presentConformers: string[] = [];
     private viewer: ReDNATCOMspViewer|null = null;
 
+    private classColorToConformers(k: keyof ConformersByClass, color: Color) {
+        const updated: Partial<NtCColors.Conformers> = {};
+        ConformersByClass[k].map(cfmr => updated[cfmr as keyof NtCColors.Conformers] = color);
+
+        return updated;
+    }
+
+    private updateClassColor(k: keyof NtCColors.Classes, color: number) {
+        const clr = Color(color);
+        const classColors = { ...this.state.display.classColors };
+        classColors[k] = clr;
+
+        const conformerColors = {
+            ...this.state.display.conformerColors,
+            ...this.classColorToConformers(k as keyof ConformersByClass, clr),
+        };
+
+        const display = { ...this.state.display, classColors, conformerColors };
+        this.viewer!.changeNtCColors(display);
+        this.setState({ ...this.state, display });
+    }
+
+    private updateConformerColor(k: keyof NtCColors.Conformers, color: number) {
+        const conformerColors = { ...this.state.display.conformerColors };
+        conformerColors[k] = Color(color);
+
+        const display = { ...this.state.display, conformerColors };
+        this.viewer!.changeNtCColors(display);
+        this.setState({ ...this.state, display });
+    }
+
     constructor(props: ReDNATCOMsp.Props) {
         super(props);
 
         this.state = {
             display: { ...Display },
+            showControls: false,
         };
     }
 
     loadStructure(data: string, type: 'pdb'|'cif') {
         if (this.viewer)
-            this.viewer.loadStructure(data, type, this.state.display).then(() => this.forceUpdate());
+            this.viewer.loadStructure(data, type, this.state.display).then(() => {
+                this.presentConformers = this.viewer!.getPresentConformers();
+                this.forceUpdate();
+            });
     }
 
     componentDidMount() {
@@ -452,102 +638,211 @@ class ReDNATCOMsp extends React.Component<ReDNATCOMsp.Props, State> {
             <div className='rmsp-app'>
                 <div id={this.props.elemId + '-viewer'} className='rmsp-viewer'></div>
                 <div>
-                    <div>Display and control</div>
-                    <div className='rmsp-controls'>
-                        <div className='rmsp-controls-section-caption'>Representation</div>
-                        <div className='rmsp-controls-line'>
-                            <div className='rmsp-control-item'>
-                                <PushButton
-                                    caption={capitalize(this.state.display.representation)}
-                                    enabled={ready}
-                                    onClick={() => {
-                                        const display = {
-                                            ...this.state.display,
-                                            representation: this.state.display.representation === 'cartoon' ? 'ball-and-stick' : 'cartoon',
-                                        };
-                                        this.viewer!.changeRepresentation(display);
-                                        this.setState({ ...this.state, display });
-                                    }}
-                                />
+                    <div
+                        onClick={() => this.setState({ ...this.state, showControls: !this.state.showControls })}
+                    >
+                        Display and control
+                    </div>
+                    {this.state.showControls ?
+                        <div className='rmsp-controls'>
+                            <div className='rmsp-controls-section-caption'>Representation</div>
+                            <div className='rmsp-controls-line'>
+                                <div className='rmsp-control-item'>
+                                    <PushButton
+                                        text={capitalize(this.state.display.representation)}
+                                        enabled={ready}
+                                        onClick={() => {
+                                            const display = {
+                                                ...this.state.display,
+                                                representation: this.state.display.representation === 'cartoon' ? 'ball-and-stick' : 'cartoon',
+                                            };
+                                            this.viewer!.changeRepresentation(display);
+                                            this.setState({ ...this.state, display });
+                                        }}
+                                    />
+                                </div>
                             </div>
-                        </div>
 
-                        <div className='rmsp-controls-section-caption'>Substructure parts</div>
-                        <div className='rmsp-controls-line'>
-                            <div className='rmsp-control-item'>
-                                <ToggleButton
-                                    caption='Nucleic'
-                                    enabled={hasNucleic}
-                                    switchedOn={this.state.display.showNucleic}
-                                    onClick={() => {
-                                        const display = {
-                                            ...this.state.display,
-                                            showNucleic: !this.state.display.showNucleic,
-                                        };
-                                        this.viewer!.toggleSubstructure('nucleic', display);
-                                        this.setState({ ...this.state, display });
-                                    }}
-                                />
-                            </div>
-                            <div className='rmsp-control-item'>
-                                <ToggleButton
-                                    caption='Protein'
-                                    enabled={hasProtein}
-                                    switchedOn={this.state.display.showProtein}
-                                    onClick={() => {
-                                        const display = {
-                                            ...this.state.display,
-                                            showProtein: !this.state.display.showProtein,
-                                        };
-                                        this.viewer!.toggleSubstructure('protein', display);
-                                        this.setState({ ...this.state, display });
-                                    }}
-                                />
+                            <div className='rmsp-controls-section-caption'>Substructure parts</div>
+                            <div className='rmsp-controls-line'>
+                                <div className='rmsp-control-item'>
+                                    <ToggleButton
+                                        text='Nucleic'
+                                        enabled={hasNucleic}
+                                        switchedOn={this.state.display.showNucleic}
+                                        onClick={() => {
+                                            const display = {
+                                                ...this.state.display,
+                                                showNucleic: !this.state.display.showNucleic,
+                                            };
+                                            this.viewer!.toggleSubstructure('nucleic', display);
+                                            this.setState({ ...this.state, display });
+                                        }}
+                                    />
+                                </div>
+                                <div className='rmsp-control-item'>
+                                    <ToggleButton
+                                        text='Protein'
+                                        enabled={hasProtein}
+                                        switchedOn={this.state.display.showProtein}
+                                        onClick={() => {
+                                            const display = {
+                                                ...this.state.display,
+                                                showProtein: !this.state.display.showProtein,
+                                            };
+                                            this.viewer!.toggleSubstructure('protein', display);
+                                            this.setState({ ...this.state, display });
+                                        }}
+                                    />
+                                </div>
+                                <div className='rmsp-control-item'>
+                                    <ToggleButton
+                                        text='Water'
+                                        enabled={hasWater}
+                                        switchedOn={this.state.display.showWater}
+                                        onClick={() => {
+                                            const display = {
+                                                ...this.state.display,
+                                                showWater: !this.state.display.showWater,
+                                            };
+                                            this.viewer!.toggleSubstructure('water', display);
+                                            this.setState({ ...this.state, display });
+                                        }}
+                                    />
+                                </div>
                             </div>
-                            <div className='rmsp-control-item'>
-                                <ToggleButton
-                                    caption='Water'
-                                    enabled={hasWater}
-                                    switchedOn={this.state.display.showWater}
-                                    onClick={() => {
-                                        const display = {
-                                            ...this.state.display,
-                                            showWater: !this.state.display.showWater,
-                                        };
-                                        this.viewer!.toggleSubstructure('water', display);
-                                        this.setState({ ...this.state, display });
-                                    }}
-                                />
+
+                            <div className='rmsp-controls-section-caption'>NtC visuals</div>
+                            <div className='rmsp-controls-line'>
+                                <div className='rmsp-control-item-group'>
+                                    <div className='rmsp-control-item'>
+                                        <ToggleButton
+                                            text='Pyramids'
+                                            enabled={ready}
+                                            switchedOn={this.state.display.showPyramids}
+                                            onClick={() => {
+                                                const display = {
+                                                    ...this.state.display,
+                                                    showPyramids: !this.state.display.showPyramids,
+                                                };
+                                                this.viewer!.changePyramids(display);
+                                                this.setState({ ...this.state, display });
+                                            }}
+                                        />
+                                    </div>
+                                    <div className='rmsp-control-item'>
+                                        <PushButton
+                                            text={this.state.display.pyramidsTransparent ? 'Transparent' : 'Solid'}
+                                            enabled={this.state.display.showPyramids}
+                                            onClick={() => {
+                                                const display = {
+                                                    ...this.state.display,
+                                                    pyramidsTransparent: !this.state.display.pyramidsTransparent,
+                                                };
+                                                this.viewer!.changePyramids(display);
+                                                this.setState({ ...this.state, display });
+                                            }}
+                                        />
+                                    </div>
+                                </div>
+                                <div className='rmsp-control-item-group'>
+                                    <div className='rmsp-control-item'>
+                                        <ToggleButton
+                                            text='Balls'
+                                            enabled={false}
+                                            switchedOn={false}
+                                            onClick={() => {}}
+                                        />
+                                    </div>
+                                    <div className='rmsp-control-item'>
+                                        <PushButton
+                                            text={this.state.display.ballsTransparent ? 'Transparent' : 'Solid'}
+                                            enabled={this.state.display.showBalls}
+                                            onClick={() => {
+                                                const display = {
+                                                    ...this.state.display,
+                                                    ballsTransparent: !this.state.display.ballsTransparent,
+                                                };
+                                                /* No balls today... */
+                                                this.setState({ ...this.state, display });
+                                            }}
+                                        />
+                                    </div>
+                                </div>
                             </div>
-                        </div>
 
-                        <div className='rmsp-controls-section-caption'>NtC visuals</div>
-                        <div className='rmsp-controls-line'>
-                            <div className='rmsp-control-item'>
-                                <ToggleButton
-                                    caption='Pyramids'
-                                    enabled={ready}
-                                    switchedOn={this.state.display.showPyramids}
-                                    onClick={() => {
-                                        const display = {
-                                            ...this.state.display,
-                                            pyramidsShown: !this.state.display.showPyramids,
-                                        };
-                                        this.viewer!.togglePyramids(display);
-                                        this.setState({ ...this.state, display });
-                                    }}
-                                />
+                            <div className='rmsp-controls-section-caption'>NtC classes colors</div>
+                            <div className='rmsp-controls-line'>
+                                {(['A', 'B', 'BII', 'miB', 'Z', 'IC', 'OPN', 'SYN', 'N'] as (keyof NtCColors.Classes)[]).map(k =>
+                                    <div className='rmsp-control-item-group' key={k}>
+                                        <div
+                                            className='rmsp-control-item'
+                                            onClick={evt => ColorPicker.create(
+                                                evt,
+                                                this.state.display.classColors[k],
+                                                color => this.updateClassColor(k, color)
+                                            )}
+                                        >
+                                            <ColorBox caption={k} color={this.state.display.classColors[k]} />
+                                        </div>
+                                        <PushButton
+                                            text='R'
+                                            onClick={() => this.updateClassColor(k, NtCColors.Classes[k])}
+                                            enabled={true}
+                                        />
+                                    </div>
+                                )}
                             </div>
-                            <div className='rmsp-control-item'>
-                                <ToggleButton
-                                    caption='Balls'
-                                    enabled={false}
-                                    switchedOn={false}
-                                    onClick={() => {}}
-                                />
+
+                            <div className='rmsp-controls-section-caption'>NtC colors</div>
+                            <div className='rmsp-controls-line'>
+                                {this.presentConformers.map(ntc => {
+                                    const uprKey = ntc + '_Upr' as keyof NtCColors.Conformers;
+                                    const lwrKey = ntc + '_Lwr' as keyof NtCColors.Conformers;
+
+                                    return (
+                                        <div className='rmsp-control-item' key={ntc}>
+                                            <div className='rmsp-control-item-group'>
+                                                <div
+                                                    className='rmsp-control-item'
+                                                    onClick={evt => ColorPicker.create(
+                                                        evt,
+                                                        this.state.display.conformerColors[uprKey],
+                                                        color => this.updateConformerColor(uprKey, color)
+                                                    )}
+                                                >
+                                                    <ColorBox caption={`${ntc} Upr`} color={this.state.display.conformerColors[uprKey]} />
+                                                </div>
+                                                <PushButton
+                                                    text='R'
+                                                    onClick={() => this.updateConformerColor(uprKey, NtCColors.Conformers[uprKey])}
+                                                    enabled={true}
+                                                />
+                                            </div>
+                                            <div className='rmsp-control-item-group'>
+                                                <div
+                                                    className='rmsp-control-item'
+                                                    onClick={evt => ColorPicker.create(
+                                                        evt,
+                                                        this.state.display.conformerColors[lwrKey],
+                                                        color => this.updateConformerColor(lwrKey, color)
+                                                    )}
+                                                >
+                                                    <ColorBox caption={`${ntc} Lwr`} color={this.state.display.conformerColors[lwrKey]} />
+                                                </div>
+                                                <PushButton
+                                                    text='R'
+                                                    onClick={() => this.updateConformerColor(lwrKey, NtCColors.Conformers[lwrKey])}
+                                                    enabled={true}
+                                                />
+                                            </div>
+                                        </div>
+                                    );
+                                })}
                             </div>
                         </div>
-                    </div>
+                        : undefined
+                    }
                 </div>
             </div>
         );
diff --git a/src/apps/rednatco/rednatco-molstar.css b/src/apps/rednatco/rednatco-molstar.css
index 56e69831bfe95d95a1fd0091ad3cb8aa1b9480f7..8b25615cbc29c7b60af92a19fb8cc09528203f36 100644
--- a/src/apps/rednatco/rednatco-molstar.css
+++ b/src/apps/rednatco/rednatco-molstar.css
@@ -28,7 +28,7 @@
 .rmsp-app {
     display: flex;
     flex-direction: column;
-    height: 90%;
+    height: 100%;
     width: 100%;
 
     font-family: Verdana, sans-serif;
@@ -36,6 +36,20 @@
     line-height: 1.5;
 }
 
+.rmsp-color-box {
+    display: flex;
+}
+
+.rmsp-color-box-color {
+    flex: 1;
+}
+
+.rmsp-color-picker-nest {
+    font-family: Verdana, sans-serif;
+    font-size: 12pt;
+    line-height: 1.5;
+}
+
 .rmsp-controls {
     display: grid;
     grid-template-columns: auto 1fr;
@@ -43,6 +57,12 @@
     overflow: scroll;
 }
 
+.rmsp-control-item-group {
+    display: flex;
+    flex: 1;
+    gap: 0;
+}
+
 .rmsp-control-item {
     flex: 1;
 }
@@ -90,6 +110,41 @@
     margin: 0.15em;
 }
 
+.rmsp-spinbox-container {
+    background-color: white;
+    border: 0.15em solid #ccc;
+    border-radius: 0;
+    display: grid;
+    grid-template-columns: auto 1fr;
+}
+
+.rmsp-spinbox-button {
+    height: 0.6em;
+    text-align: center;
+}
+.rmsp-spinbox-button:hover {
+    background-color: #aaa;
+}
+
+.rmsp-spinbox-buttons {
+    display: flex;
+    flex-direction: column;
+    gap: 0.05em;
+    margin: 0.1em;
+}
+
+.rmsp-spinbox-input {
+    -moz-appearance: none;
+    -webkit-appearance: none;
+    appearance: none;
+    border: none;
+
+    width: 100%;
+}
+.rmsp-spinbox-input:focus {
+    outline: none;
+}
+
 .rmsp-viewer {
     flex: 1;
     position: relative;