diff --git a/src/components/Footer.astro b/src/components/Footer.astro
index 76ecad9..9207fbf 100644
--- a/src/components/Footer.astro
+++ b/src/components/Footer.astro
@@ -15,7 +15,7 @@ const funding = lang === 'de' ? fundingDe : fundingEn;
const columns = [
{
title: ui.footer.capabilities,
- links: ui.stages.items.map((item, i) => ({ href: `${home}#capability-${i + 1}`, label: item.title })),
+ links: ui.method.stages.map((s) => ({ href: `${home}#capability-${s.card}`, label: s.title })),
},
{
title: ui.footer.company,
diff --git a/src/components/home/Method.astro b/src/components/home/Method.astro
index 91171e3..1f5641e 100644
--- a/src/components/home/Method.astro
+++ b/src/components/home/Method.astro
@@ -2,7 +2,7 @@
import { Picture } from 'astro:assets';
import MethodDiagram from './MethodDiagram.astro';
import monitoringRoom from '../../assets/images/monitoring-room-glass.jpg';
-import { localePath, t, type Lang } from '../../i18n/ui';
+import { t, type Lang } from '../../i18n/ui';
interface Props { lang: Lang }
const { lang } = Astro.props;
const ui = t(lang);
@@ -26,8 +26,7 @@ const ui = t(lang);
{ui.method.lines.map((line, i) => 0 }]}>{line})}
-
{ui.method.body}
-
{ui.method.cta}
+
{ui.method.body.map((line) => {line})}
@@ -51,11 +50,21 @@ const ui = t(lang);
align-items: start;
}
.method__title { grid-column: 1 / -1; }
- .method__body { grid-column: 1 / -1; max-width: 30em; display: grid; gap: var(--space-5); justify-items: start; }
+ .method__body { grid-column: 1 / -1; max-width: 30em; text-wrap: balance; }
.method__figure { padding-bottom: var(--section); }
- .method__figure :global(.diagram) { max-width: 78rem; margin-inline: auto; }
+ .method__figure :global(.diagram) { margin-inline: auto; }
+ .method__figure :global(.diagram--wide) { max-width: 78rem; }
@media (min-width: 48rem) {
.method__title { grid-column: 1 / span 6; }
- .method__body { grid-column: 7 / span 5; padding-top: var(--space-2); }
+ /* Short text: it sits on the headline's last line rather than hanging from its top, set flush
+ right against the grid's edge, with a bar in the text colour along its full height. */
+ .method__body {
+ grid-column: 7 / -1;
+ justify-self: end;
+ align-self: end;
+ text-align: right;
+ padding-right: var(--space-4);
+ border-right: var(--bar) solid currentColor;
+ }
}
diff --git a/src/components/home/MethodDiagram.astro b/src/components/home/MethodDiagram.astro
index fdf1699..d30aa50 100644
--- a/src/components/home/MethodDiagram.astro
+++ b/src/components/home/MethodDiagram.astro
@@ -1,8 +1,11 @@
---
/**
- * The method as a closed loop of four stages, drawn as a spec-sheet diagram.
- * Main nodes sit on the corners of the loop with their labels inside;
- * each stage's instruments fan outwards. Wide and tall compositions of the same drawing.
+ * The method as a triangle of three pillars, drawn as a spec-sheet diagram.
+ * Every pillar is joined to the other two; each edge carries arrows both ways, since the pillars feed each other.
+ * Each pillar's instruments fan outwards. Below 64rem a compact version shows the triangle alone,
+ * without the instruments, which would scale too small to read.
+ *
+ * Hovering a pillar brings its instruments forward: lines, dots and labels take the brighter tone.
*/
interface Stage { title: string; items: string[] }
interface Props { title: string; desc: string; stages: Stage[] }
@@ -10,98 +13,77 @@ const { title, desc, stages } = Astro.props;
const stroke = 1.25;
const ring = 36;
+type Point = { x: number; y: number };
-/* Wide composition: 1400 x 560. Nodes on the corners of a loop. */
-const W = { w: 1400, h: 560, x1: 420, x2: 980, y1: 140, y2: 420, sat: 175, dy: 62 };
-const wideNodes = [
- { x: W.x1, y: W.y1, side: -1, up: -1 }, // top-left: threat analysis
- { x: W.x2, y: W.y1, side: 1, up: -1 }, // top-right: engineering
- { x: W.x2, y: W.y2, side: 1, up: 1 }, // bottom-right: verification
- { x: W.x1, y: W.y2, side: -1, up: 1 }, // bottom-left: monitoring
-];
-
-/* Tall composition: 400 x 780. Nodes stacked on a spine, the loop closes on the left.
- The title sits right of the node, its instruments hang below the title. */
-const T = { w: 400, h: 780, x: 60, loopX: 20, y0: 60, step: 200, ring: 28, labelX: 40, satX: 44, satY: 36, dy: 28 };
-const tallNodes = stages.map((_, i) => ({ x: T.x, y: T.y0 + i * T.step }));
-
-/* Direction tick: a small chevron at the midpoint of an edge, pointing along it. */
-const tick = (x: number, y: number, dx: number, dy: number, s = 7) => {
+/* Direction tick: a small chevron near the midpoint of an edge, pointing along it, set `gap` past the midpoint. */
+const tick = (a: Point, b: Point, s = 7, gap = 0) => {
+ const dx = b.x - a.x, dy = b.y - a.y;
const len = Math.hypot(dx, dy) || 1; const ux = dx / len, uy = dy / len;
+ const x = (a.x + b.x) / 2 + ux * gap, y = (a.y + b.y) / 2 + uy * gap;
const px = -uy, py = ux;
return `${x - ux * s + px * s},${y - uy * s + py * s} ${x},${y} ${x - ux * s - px * s},${y - uy * s - py * s}`;
};
+/* Both ways: a pair of chevrons either side of the midpoint, pointing away from each other. */
+const ticks = (a: Point, b: Point, s = 7, gap = 20) => [tick(a, b, s, gap), tick(b, a, s, gap)];
+const pts = (list: Point[]) => list.map((p) => `${p.x},${p.y}`).join(' ');
+
+/* Wide composition: 1400 x 560. Security on the apex, engineering bottom right, research bottom left.
+ Labels sit outside the triangle: above the apex, below the base corners. */
+const W = { w: 1400, h: 560, sat: 160, dy: 62 };
+const wideNodes = [
+ { x: 680, y: 110, side: -1, up: -1 },
+ { x: 950, y: 440, side: 1, up: 1 },
+ { x: 410, y: 440, side: -1, up: 1 },
+];
+const wideEdges = wideNodes.map((n, i) => [n, wideNodes[(i + 1) % wideNodes.length]]);
+
+/* Compact composition: 600 x 480. The same triangle with the pillar titles only; the labels are set
+ larger so they still read at phone width. */
+const C = { w: 600, h: 480, label: 22 };
+const compactNodes = [
+ { x: 300, y: 80, up: -1 },
+ { x: 520, y: 390, up: 1 },
+ { x: 80, y: 390, up: 1 },
+];
+const compactEdges = compactNodes.map((n, i) => [n, compactNodes[(i + 1) % compactNodes.length]]);
---
-