@intentius/behold 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +9 -2
- package/README.md +12 -2
- package/demos.json +8 -0
- package/dist/cli.js +769 -139
- package/example-argo-estate/README.md +46 -0
- package/example-argo-estate/app-a/chant.config.ts +10 -0
- package/example-argo-estate/app-a/manifests/app.yaml +54 -0
- package/example-argo-estate/app-a/package.json +13 -0
- package/example-argo-estate/app-a/src/app.ts +35 -0
- package/example-argo-estate/app-a/tsconfig.json +1 -0
- package/example-argo-estate/app-b/chant.config.ts +9 -0
- package/example-argo-estate/app-b/manifests/app.yaml +54 -0
- package/example-argo-estate/app-b/package.json +13 -0
- package/example-argo-estate/app-b/src/app.ts +34 -0
- package/example-argo-estate/app-b/tsconfig.json +1 -0
- package/example-argo-estate/control-plane/chant.config.ts +14 -0
- package/example-argo-estate/control-plane/package.json +13 -0
- package/example-argo-estate/control-plane/src/argo.ts +69 -0
- package/example-argo-estate/control-plane/tsconfig.json +1 -0
- package/example-argo-estate/package-lock.json +1949 -0
- package/example-argo-estate/package.json +10 -0
- package/example-flux-estate/README.md +13 -8
- package/example-flux-estate/app-a/package.json +3 -3
- package/example-flux-estate/app-b/package.json +3 -3
- package/example-flux-estate/control-plane/package.json +2 -2
- package/example-flux-estate/control-plane/src/flux.ts +6 -0
- package/example-flux-estate/package-lock.json +17 -17
- package/example-k8s/README.md +16 -2
- package/example-k8s/base/deployment.yaml +21 -0
- package/example-k8s/base/kustomization.yaml +3 -0
- package/example-k8s/base/service.yaml +12 -0
- package/example-k8s/chant.config.ts +10 -0
- package/example-k8s/overlays/dev/kustomization.yaml +6 -0
- package/example-k8s/package-lock.json +43 -40
- package/example-k8s/package.json +4 -4
- package/example-writes/package-lock.json +18 -16
- package/example-writes/package.json +3 -3
- package/package.json +3 -2
- package/web/app.js +359 -21
- package/web/icons/cncf/argo.svg +1 -0
- package/web/icons/cncf/flux.svg +1 -0
- package/web/icons/cncf/helm.svg +1 -0
- package/web/icons/k8s/c-role.svg +1 -0
- package/web/icons/k8s/cm.svg +1 -0
- package/web/icons/k8s/crb.svg +1 -0
- package/web/icons/k8s/crd.svg +1 -0
- package/web/icons/k8s/cronjob.svg +1 -0
- package/web/icons/k8s/deploy.svg +1 -0
- package/web/icons/k8s/ds.svg +1 -0
- package/web/icons/k8s/ep.svg +1 -0
- package/web/icons/k8s/group.svg +1 -0
- package/web/icons/k8s/hpa.svg +1 -0
- package/web/icons/k8s/ing.svg +1 -0
- package/web/icons/k8s/job.svg +1 -0
- package/web/icons/k8s/limits.svg +1 -0
- package/web/icons/k8s/netpol.svg +1 -0
- package/web/icons/k8s/ns.svg +1 -0
- package/web/icons/k8s/pod.svg +1 -0
- package/web/icons/k8s/psp.svg +1 -0
- package/web/icons/k8s/pv.svg +1 -0
- package/web/icons/k8s/pvc.svg +1 -0
- package/web/icons/k8s/quota.svg +1 -0
- package/web/icons/k8s/rb.svg +1 -0
- package/web/icons/k8s/role.svg +1 -0
- package/web/icons/k8s/rs.svg +1 -0
- package/web/icons/k8s/sa.svg +1 -0
- package/web/icons/k8s/sc.svg +1 -0
- package/web/icons/k8s/secret.svg +1 -0
- package/web/icons/k8s/sts.svg +1 -0
- package/web/icons/k8s/svc.svg +1 -0
- package/web/icons/k8s/user.svg +1 -0
- package/web/icons/k8s/vol.svg +1 -0
- package/web/index.html +192 -84
- package/web/layout-store.js +118 -0
- package/web/layout-store.test.js +163 -0
- package/web/theme.js +58 -6
package/web/app.js
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
// renderPanelView never rewrites, so the select mounts once and survives re-renders).
|
|
11
11
|
import { initTheme, mountThemePicker, readableOn, colorForCategory, onThemeChange, getTokens } from "./theme.js";
|
|
12
12
|
import { initPanel, setPanelTab, togglePanelCollapsed, isPanelCollapsed } from "./panel.js";
|
|
13
|
+
// #228: the hand-layout delta store — everything about WHAT gets remembered and
|
|
14
|
+
// under which key. The pointer work and the SVG surgery stay here (see the
|
|
15
|
+
// "Hand layout" section below).
|
|
16
|
+
import { applicable, clearLayout, isEmpty, layoutKey, lensKeyOf, projectKeyOf, readLayout, setDelta, writeLayout } from "./layout-store.js";
|
|
13
17
|
initTheme();
|
|
14
18
|
initPanel();
|
|
15
19
|
mountThemePicker(document.getElementById("panel-theme"));
|
|
@@ -63,6 +67,39 @@ function recolorNodesByCategory(ir) {
|
|
|
63
67
|
}
|
|
64
68
|
onThemeChange(() => recolorNodesByCategory());
|
|
65
69
|
|
|
70
|
+
// #229, the one motion signature behold spends on data: a node whose drift
|
|
71
|
+
// `_status` CHANGED between two renders pulses once in the colour it just
|
|
72
|
+
// became. Node ids are stable across renders, so the diff is a single map
|
|
73
|
+
// compare — no extra fetch, no per-node bookkeeping. The first render seeds the
|
|
74
|
+
// map and pulses nothing (everything would "change"), and a lens switch that
|
|
75
|
+
// swaps the id set pulses nothing either, since only ids present in BOTH
|
|
76
|
+
// renders can have changed. The CSS keyframes + the reduced-motion guard live
|
|
77
|
+
// in index.html.
|
|
78
|
+
let lastStatusById = new Map();
|
|
79
|
+
function markStatusChanges(ir, statusVar) {
|
|
80
|
+
const prev = lastStatusById;
|
|
81
|
+
const next = new Map();
|
|
82
|
+
for (const n of ir.nodes) {
|
|
83
|
+
const s = n.attrs && n.attrs._status;
|
|
84
|
+
if (s) next.set(n.id, s);
|
|
85
|
+
}
|
|
86
|
+
lastStatusById = next;
|
|
87
|
+
if (!prev.size) return;
|
|
88
|
+
const svg = document.querySelector("#graph svg");
|
|
89
|
+
if (!svg) return;
|
|
90
|
+
for (const g of svg.querySelectorAll("[data-node-id]")) {
|
|
91
|
+
const id = g.getAttribute("data-node-id");
|
|
92
|
+
const now = next.get(id);
|
|
93
|
+
if (!now || prev.get(id) === undefined || prev.get(id) === now) continue;
|
|
94
|
+
// The pulse wears the NEW status's hue, read through whichever vocabulary
|
|
95
|
+
// this graph is painted in — a node going foreign glows yellow in the drift
|
|
96
|
+
// overlay; a component that rolled back glows red in the component view,
|
|
97
|
+
// where the same `warn` means something else entirely.
|
|
98
|
+
g.style.setProperty("--pulse", statusVar[now] || "var(--pending)");
|
|
99
|
+
g.classList.add("status-changed");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
66
103
|
// Static-export mode (`behold export`): the SPA runs off a pre-captured bundle
|
|
67
104
|
// with no backend. Detect the flag the export injects, load its manifest, and
|
|
68
105
|
// replay every read from `snapshots/` — the graph, zoom dial, radial, inspect,
|
|
@@ -141,7 +178,6 @@ function inspect(node) {
|
|
|
141
178
|
const section = (title) => {
|
|
142
179
|
const h = document.createElement("h3");
|
|
143
180
|
h.textContent = title;
|
|
144
|
-
h.style.cssText = "font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin:14px 0 6px";
|
|
145
181
|
panel.appendChild(h);
|
|
146
182
|
const dl = document.createElement("dl");
|
|
147
183
|
panel.appendChild(dl);
|
|
@@ -202,7 +238,6 @@ function inspect(node) {
|
|
|
202
238
|
if (isComposite) {
|
|
203
239
|
const h = document.createElement("h3");
|
|
204
240
|
h.textContent = `members · ${node.attrs.members}`;
|
|
205
|
-
h.style.cssText = "font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin:14px 0 6px";
|
|
206
241
|
panel.appendChild(h);
|
|
207
242
|
const loading = document.createElement("p");
|
|
208
243
|
loading.style.color = "var(--muted)";
|
|
@@ -354,7 +389,7 @@ function inspect(node) {
|
|
|
354
389
|
panel.appendChild(p);
|
|
355
390
|
return;
|
|
356
391
|
}
|
|
357
|
-
renderObserved(panel, j.observed, j.health); // #30 observed state + #26 health
|
|
392
|
+
renderObserved(panel, j.observed, j.health, j.healthDetail); // #30 observed state + #26/#226 health
|
|
358
393
|
renderDiff(panel, j.diff); // #27 — drift since snapshot
|
|
359
394
|
renderFieldDrift(panel, j.fieldDrift); // #87 — field-level (per-manager) drift
|
|
360
395
|
});
|
|
@@ -388,11 +423,10 @@ const HEALTH_COLOR = {
|
|
|
388
423
|
};
|
|
389
424
|
|
|
390
425
|
// Render a node's observed live state (#30) + health verdict (#26).
|
|
391
|
-
function renderObserved(panel, o, health) {
|
|
426
|
+
function renderObserved(panel, o, health, healthDetail) {
|
|
392
427
|
if (!o) return; // pending/foreign nodes have no observed record in the diff
|
|
393
428
|
const h = document.createElement("h3");
|
|
394
429
|
h.textContent = "observed";
|
|
395
|
-
h.style.cssText = "font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin:14px 0 6px";
|
|
396
430
|
panel.appendChild(h);
|
|
397
431
|
const dl = document.createElement("dl");
|
|
398
432
|
const add = (k, v, color) => {
|
|
@@ -405,7 +439,14 @@ function renderObserved(panel, o, health) {
|
|
|
405
439
|
};
|
|
406
440
|
// Health first — the "is it well?" verdict, distinct from drift. Absent when
|
|
407
441
|
// the substrate reports no status (not fabricated).
|
|
408
|
-
|
|
442
|
+
// #226: for an Argo Application or a Flux object the verdict comes from the
|
|
443
|
+
// controller's own conditions, and `healthDetail` is the sentence it read
|
|
444
|
+
// there — `Ready=False (BuildFailed)`, `health=Degraded, sync=OutOfSync`.
|
|
445
|
+
// Appended to the verdict rather than given its own row, because it is the
|
|
446
|
+
// same claim said precisely.
|
|
447
|
+
if (health && health !== "unknown") {
|
|
448
|
+
add("health", healthDetail ? `${health} — ${healthDetail}` : health, HEALTH_COLOR[health]);
|
|
449
|
+
}
|
|
409
450
|
if (o.type) add("type", o.type);
|
|
410
451
|
if (o.status) add("status", o.status, HEALTH_COLOR[health] || undefined);
|
|
411
452
|
if (o.physicalId) add("physical id", o.physicalId);
|
|
@@ -448,7 +489,6 @@ const DIFF_LABEL = {
|
|
|
448
489
|
function renderDiff(panel, diff) {
|
|
449
490
|
const h = document.createElement("h3");
|
|
450
491
|
h.textContent = "drift";
|
|
451
|
-
h.style.cssText = "font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin:14px 0 6px";
|
|
452
492
|
panel.appendChild(h);
|
|
453
493
|
if (!diff) {
|
|
454
494
|
const p = document.createElement("p");
|
|
@@ -460,6 +500,16 @@ function renderDiff(panel, diff) {
|
|
|
460
500
|
const cat = document.createElement("p");
|
|
461
501
|
cat.textContent = DIFF_LABEL[diff.category] || diff.category;
|
|
462
502
|
panel.appendChild(cat);
|
|
503
|
+
// chant#1620 (#192): where the live read actually looked — the line that
|
|
504
|
+
// separates "not there" from "looked in the wrong place" (a declared k8s
|
|
505
|
+
// object with no namespace reads from the DEFAULTED namespace, and only
|
|
506
|
+
// this address makes that visible). Monospace so a request path scans.
|
|
507
|
+
if (diff.queried) {
|
|
508
|
+
const q = document.createElement("p");
|
|
509
|
+
q.className = "queried"; // mono + muted, styled with the rest of the pane's scale
|
|
510
|
+
q.textContent = `queried: ${diff.queried} → ${diff.category === "missing" ? "not found" : "read failed"}`;
|
|
511
|
+
panel.appendChild(q);
|
|
512
|
+
}
|
|
463
513
|
// chant#1168 (#1089): show WHY chant couldn't look, instead of the
|
|
464
514
|
// "no field changes" text below — that phrasing implies a comparison ran
|
|
465
515
|
// and found nothing, which is exactly the wrong read for a hole in the
|
|
@@ -529,7 +579,6 @@ function renderFieldDrift(panel, fieldDrift) {
|
|
|
529
579
|
if (!fieldDrift.drifted.length && !fieldDrift.accepted.length) return; // deep ran, nothing to report for this node
|
|
530
580
|
const h = document.createElement("h3");
|
|
531
581
|
h.textContent = "field ownership";
|
|
532
|
-
h.style.cssText = "font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);margin:14px 0 6px";
|
|
533
582
|
panel.appendChild(h);
|
|
534
583
|
const dl = document.createElement("dl");
|
|
535
584
|
for (const ch of fieldDrift.drifted) {
|
|
@@ -724,7 +773,7 @@ function renderPanelView() {
|
|
|
724
773
|
lanes.href = "/lanes";
|
|
725
774
|
lanes.textContent = "lanes →";
|
|
726
775
|
lanes.title = "The time-lanes view — captured frames of this graph over time";
|
|
727
|
-
lanes.style.cssText = "color:var(--pending);text-decoration:none;font-size:
|
|
776
|
+
lanes.style.cssText = "color:var(--pending);text-decoration:none;font-size:var(--t-body)";
|
|
728
777
|
row.appendChild(lanes);
|
|
729
778
|
tools.appendChild(row);
|
|
730
779
|
}
|
|
@@ -1200,7 +1249,7 @@ function renderDial() {
|
|
|
1200
1249
|
}
|
|
1201
1250
|
host.style.display = "flex";
|
|
1202
1251
|
const hint = document.createElement("span");
|
|
1203
|
-
hint.style.cssText = "font-size:
|
|
1252
|
+
hint.style.cssText = "font-size:var(--t-caption);color:var(--muted);align-self:center";
|
|
1204
1253
|
hint.textContent = "observe → reconcile → apply needs an environment — pick one in ⌘K (env: …)";
|
|
1205
1254
|
host.appendChild(hint);
|
|
1206
1255
|
// A pipeline run (#163) is env-less — its progress still belongs here.
|
|
@@ -1273,7 +1322,7 @@ function renderApplyPicker() {
|
|
|
1273
1322
|
wrap.style.gap = "6px";
|
|
1274
1323
|
const sel = document.createElement("select");
|
|
1275
1324
|
sel.style.cssText =
|
|
1276
|
-
"background:var(--
|
|
1325
|
+
"background:var(--well);color:var(--fg);border:1px solid var(--line);border-radius:var(--r-ctl);padding:3px 8px;font-size:var(--t-body)";
|
|
1277
1326
|
sel.add(new Option("all components", "all"));
|
|
1278
1327
|
for (const name of componentChoices) sel.add(new Option(applyOptionLabel(name), name));
|
|
1279
1328
|
const go = button("Apply →", "", () => {
|
|
@@ -1395,7 +1444,7 @@ function renderApplyProgress(state) {
|
|
|
1395
1444
|
const wrap = document.createElement("div");
|
|
1396
1445
|
wrap.style.cssText = "display:flex;flex-direction:column;gap:6px;width:100%;margin-top:4px";
|
|
1397
1446
|
const summary = document.createElement("div");
|
|
1398
|
-
summary.style.cssText = `font-size:
|
|
1447
|
+
summary.style.cssText = `font-size:var(--t-caption);color:${APPLY_STATUS_COLOR[state.status] || "var(--muted)"}`;
|
|
1399
1448
|
// A pipeline run (#163) reuses this whole panel — same shape, different
|
|
1400
1449
|
// executor — and says so instead of claiming to be an apply.
|
|
1401
1450
|
summary.textContent = `${state.kind || "apply"}: ${state.status}`;
|
|
@@ -1404,14 +1453,14 @@ function renderApplyProgress(state) {
|
|
|
1404
1453
|
const row = document.createElement("div");
|
|
1405
1454
|
row.style.cssText = "display:flex;align-items:center;gap:8px;flex-wrap:wrap";
|
|
1406
1455
|
const label = document.createElement("span");
|
|
1407
|
-
label.style.cssText = `font-size:
|
|
1456
|
+
label.style.cssText = `font-size:var(--t-caption);color:${APPLY_STATUS_COLOR[w.status] || "var(--muted)"};min-width:52px`;
|
|
1408
1457
|
label.textContent = `wave ${w.wave}`;
|
|
1409
1458
|
row.appendChild(label);
|
|
1410
1459
|
for (const cname of w.components) {
|
|
1411
1460
|
const c = (state.components || []).find((x) => x.component === cname) || { status: "pending" };
|
|
1412
1461
|
const color = APPLY_STATUS_COLOR[c.status] || "var(--muted)";
|
|
1413
1462
|
const chip = document.createElement("span");
|
|
1414
|
-
chip.style.cssText = `border:1px solid ${color};color:${color};border-radius:
|
|
1463
|
+
chip.style.cssText = `border:1px solid ${color};color:${color};border-radius:var(--r-ctl);padding:2px 8px;font-size:var(--t-caption)`;
|
|
1415
1464
|
const detail = [c.phase, c.step].filter(Boolean).join(" · ");
|
|
1416
1465
|
chip.textContent = `${cname}${detail ? " · " + detail : ""} (${c.status})`;
|
|
1417
1466
|
if (c.error) chip.title = c.error;
|
|
@@ -1647,6 +1696,7 @@ function render(ir, svg, m) {
|
|
|
1647
1696
|
// green — the SVG's own :root shadows behold's override within the graph subtree.
|
|
1648
1697
|
g.innerHTML = svg.replace(/:root\s*\{[^{}]*--pin-[^{}]*\}/g, "");
|
|
1649
1698
|
recolorNodesByCategory(ir); // #62: category-hued fills from the theme's full palette
|
|
1699
|
+
markStatusChanges(ir, componentStatus ? COMPONENT_STATUS_VAR : DRIFT_STATUS_VAR); // #229
|
|
1650
1700
|
const svgEl = g.querySelector("svg");
|
|
1651
1701
|
if (svgEl) {
|
|
1652
1702
|
// Drop pinhole's fixed pixel size so the viewBox drives sizing; behold then
|
|
@@ -1666,6 +1716,7 @@ function render(ir, svg, m) {
|
|
|
1666
1716
|
ensureBackToInfra(g);
|
|
1667
1717
|
wire(ir);
|
|
1668
1718
|
if (view.radial && !view.components && !view.logical) addRadialLabels(ir);
|
|
1719
|
+
applyLayout(); // #228: last, so the hand-placed deltas ride on top of every other pass
|
|
1669
1720
|
renderDial();
|
|
1670
1721
|
}
|
|
1671
1722
|
|
|
@@ -1823,6 +1874,11 @@ function ensureZoomControls(host) {
|
|
|
1823
1874
|
let py = 0;
|
|
1824
1875
|
host.addEventListener("mousedown", (e) => {
|
|
1825
1876
|
if (!vb) return;
|
|
1877
|
+
// #228: pan is the default on empty ground, but a node card (or a box's
|
|
1878
|
+
// title / resize handle) belongs to the layout drag — starting a pan too
|
|
1879
|
+
// would move the graph out from under the thing you grabbed. The layout
|
|
1880
|
+
// drag owns the panMoved latch for the rest of the gesture.
|
|
1881
|
+
if (layoutTargetOf(e)) return;
|
|
1826
1882
|
drag = true;
|
|
1827
1883
|
panMoved = false;
|
|
1828
1884
|
px = e.clientX;
|
|
@@ -1852,6 +1908,288 @@ function ensureZoomControls(host) {
|
|
|
1852
1908
|
});
|
|
1853
1909
|
}
|
|
1854
1910
|
|
|
1911
|
+
// --- Hand layout (#228): drag a node, resize a containment box -------------
|
|
1912
|
+
// dagre is a good first draft and a bad final layout. A pointer-drag on a card
|
|
1913
|
+
// writes a {dx,dy} for that `data-node-id`; a corner handle on a containment
|
|
1914
|
+
// box writes {dw,dh} (and its title drags the box). The deltas live in
|
|
1915
|
+
// localStorage per project + lens (web/layout-store.js) and are re-applied at
|
|
1916
|
+
// the end of every render(), so the graph underneath stays chant's and a
|
|
1917
|
+
// delta for a node that left the estate is simply not applied.
|
|
1918
|
+
//
|
|
1919
|
+
// What this does NOT do, said plainly rather than faked:
|
|
1920
|
+
// * a resized box does not reflow its children — that is dagre's job on the
|
|
1921
|
+
// next layout, and the reset control's tooltip says so;
|
|
1922
|
+
// * an edge touching a displaced node is redrawn as a STRAIGHT line between
|
|
1923
|
+
// its original anchor points, each shifted by its own node's delta. #228
|
|
1924
|
+
// accepts the straight-line fallback; spline re-routing is pinhole's job.
|
|
1925
|
+
// An edge with both ends where dagre put them keeps its bezier untouched.
|
|
1926
|
+
// * nothing is written to the server. The second tier of #228 (a
|
|
1927
|
+
// `.behold/layout.json` sidecar behind POST /api/layout, so a server-side
|
|
1928
|
+
// export honours the same deltas) is the follow-up half.
|
|
1929
|
+
let layoutIndex = null; // {nodes,boxes,edges} for the SVG currently on screen
|
|
1930
|
+
let layoutDeltas = {}; // the deltas in force for the current key
|
|
1931
|
+
let layoutDrag = null; // the gesture in flight
|
|
1932
|
+
let layoutWired = false;
|
|
1933
|
+
|
|
1934
|
+
/** The storage key for the project + lens on screen; null before /api/project lands. */
|
|
1935
|
+
function currentLayoutKey() {
|
|
1936
|
+
if (!projectInfo) return null;
|
|
1937
|
+
return layoutKey(projectKeyOf(projectInfo), lensKeyOf({ zoom: zoomValue(), radial: view.radial, stack: view.stack }));
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
/** First and last coordinate pair of a path `d` — pinhole's own edge anchors. */
|
|
1941
|
+
function pathAnchors(d) {
|
|
1942
|
+
const n = String(d || "").match(/-?\d*\.?\d+(?:e[-+]?\d+)?/gi);
|
|
1943
|
+
if (!n || n.length < 4) return null;
|
|
1944
|
+
return { sx: +n[0], sy: +n[1], ex: +n[n.length - 2], ey: +n[n.length - 1] };
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
/**
|
|
1948
|
+
* Wrap each containment box in a `<g data-layout-box>` and give it a corner
|
|
1949
|
+
* handle, once per rendered SVG.
|
|
1950
|
+
*
|
|
1951
|
+
* FRAGILE BY CONSTRUCTION, and knowingly so: pinhole's `Canvas.groupBox` emits
|
|
1952
|
+
* a bare `<rect rx=…>` immediately followed by its title `<text>`, as a direct
|
|
1953
|
+
* child of the `<svg>` — no group, no `data-group-id` to match on. So behold
|
|
1954
|
+
* matches the structure, exactly the way addGitlabWaveBadges already has to.
|
|
1955
|
+
* The discriminators: a positive `rx` (the two page-background rects have
|
|
1956
|
+
* none), a `<text>` as the next non-badge sibling, and svg-root parentage (a
|
|
1957
|
+
* card's rect lives inside `[data-node-id]`, an edge-label's inside its own
|
|
1958
|
+
* `<g>`). The real fix is upstream — a `data-group-id` on the box — and until
|
|
1959
|
+
* pinhole stamps one, prefer the attribute here the moment it exists.
|
|
1960
|
+
*/
|
|
1961
|
+
function wrapContainmentBoxes(svgEl) {
|
|
1962
|
+
const boxes = new Map();
|
|
1963
|
+
const handleSize = Math.max(12, Math.round((vbInit ? vbInit[2] : 1000) / 90));
|
|
1964
|
+
for (const rect of [...svgEl.children]) {
|
|
1965
|
+
if (rect.tagName.toLowerCase() !== "rect") continue;
|
|
1966
|
+
const x = parseFloat(rect.getAttribute("x"));
|
|
1967
|
+
const y = parseFloat(rect.getAttribute("y"));
|
|
1968
|
+
const w = parseFloat(rect.getAttribute("width"));
|
|
1969
|
+
const h = parseFloat(rect.getAttribute("height"));
|
|
1970
|
+
if (!(parseFloat(rect.getAttribute("rx")) > 0) || !(w > 0) || !(h > 0) || Number.isNaN(x) || Number.isNaN(y)) continue;
|
|
1971
|
+
// Collect rect → title, stepping over anything already stamped between
|
|
1972
|
+
// them (the GitLab wave badge), and bail at the next box or card.
|
|
1973
|
+
const members = [rect];
|
|
1974
|
+
let title = null;
|
|
1975
|
+
for (let el = rect.nextElementSibling; el; el = el.nextElementSibling) {
|
|
1976
|
+
const tag = el.tagName.toLowerCase();
|
|
1977
|
+
if (tag === "rect" || (tag === "g" && (el.hasAttribute("data-node-id") || el.hasAttribute("data-edge-from")))) break;
|
|
1978
|
+
members.push(el);
|
|
1979
|
+
if (tag === "text") {
|
|
1980
|
+
title = el;
|
|
1981
|
+
break;
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
if (!title) continue;
|
|
1985
|
+
const id = `box:${(title.textContent || "").trim() || boxes.size}`;
|
|
1986
|
+
if (boxes.has(id)) continue;
|
|
1987
|
+
const g = document.createElementNS(SVGNS, "g");
|
|
1988
|
+
g.setAttribute("data-layout-box", id);
|
|
1989
|
+
rect.parentNode.insertBefore(g, rect);
|
|
1990
|
+
members.forEach((m) => g.appendChild(m));
|
|
1991
|
+
// The title doubles as the box's move handle — the interior stays pan
|
|
1992
|
+
// territory, which on a logical view is most of the canvas.
|
|
1993
|
+
title.setAttribute("data-layout-move", id);
|
|
1994
|
+
title.setAttribute("cursor", "move");
|
|
1995
|
+
const handle = document.createElementNS(SVGNS, "g");
|
|
1996
|
+
handle.setAttribute("data-layout-resize", id);
|
|
1997
|
+
handle.setAttribute("cursor", "nwse-resize");
|
|
1998
|
+
handle.setAttribute("opacity", "0"); // CSS reveals it on hover; a static export never shows it
|
|
1999
|
+
const grip = document.createElementNS(SVGNS, "rect");
|
|
2000
|
+
grip.setAttribute("width", String(handleSize));
|
|
2001
|
+
grip.setAttribute("height", String(handleSize));
|
|
2002
|
+
grip.setAttribute("rx", "3");
|
|
2003
|
+
grip.setAttribute("fill", "var(--focus)");
|
|
2004
|
+
const tip = document.createElementNS(SVGNS, "title");
|
|
2005
|
+
tip.textContent = "Drag to resize this box. Children don't move with it — that's the next layout's job.";
|
|
2006
|
+
handle.append(tip, grip);
|
|
2007
|
+
g.appendChild(handle);
|
|
2008
|
+
boxes.set(id, { g, rect, handle, x, y, w0: w, h0: h, size: handleSize });
|
|
2009
|
+
}
|
|
2010
|
+
return boxes;
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
/** Park the corner handle at the box's current bottom-right. */
|
|
2014
|
+
function positionBoxHandle(b, w, h) {
|
|
2015
|
+
b.handle.setAttribute("transform", `translate(${b.x + w - b.size - 3}, ${b.y + h - b.size - 3})`);
|
|
2016
|
+
}
|
|
2017
|
+
|
|
2018
|
+
/** Index the freshly rendered SVG: node groups, containment boxes, edge paths. */
|
|
2019
|
+
function indexLayout(svgEl) {
|
|
2020
|
+
const nodes = new Map();
|
|
2021
|
+
for (const el of svgEl.querySelectorAll("[data-node-id]")) {
|
|
2022
|
+
const id = el.getAttribute("data-node-id");
|
|
2023
|
+
if (!nodes.has(id)) nodes.set(id, { el, base: el.getAttribute("transform") || "" });
|
|
2024
|
+
}
|
|
2025
|
+
const edges = [];
|
|
2026
|
+
for (const g of svgEl.querySelectorAll("g[data-edge-from]")) {
|
|
2027
|
+
const paths = [...g.querySelectorAll("path")];
|
|
2028
|
+
if (!paths.length) continue;
|
|
2029
|
+
const d0 = paths[0].getAttribute("d");
|
|
2030
|
+
edges.push({ from: g.getAttribute("data-edge-from"), to: g.getAttribute("data-edge-to"), paths, d0, anchors: pathAnchors(d0) });
|
|
2031
|
+
}
|
|
2032
|
+
layoutIndex = { nodes, boxes: wrapContainmentBoxes(svgEl), edges };
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
/** Paint `layoutDeltas` onto the indexed SVG. Idempotent: always from the original. */
|
|
2036
|
+
function renderLayout() {
|
|
2037
|
+
if (!layoutIndex) return;
|
|
2038
|
+
for (const [id, n] of layoutIndex.nodes) {
|
|
2039
|
+
const d = layoutDeltas[id];
|
|
2040
|
+
const t = d && (d.dx || d.dy) ? `translate(${d.dx || 0}, ${d.dy || 0}) ${n.base}`.trim() : n.base;
|
|
2041
|
+
if (t) n.el.setAttribute("transform", t);
|
|
2042
|
+
else n.el.removeAttribute("transform");
|
|
2043
|
+
}
|
|
2044
|
+
for (const [id, b] of layoutIndex.boxes) {
|
|
2045
|
+
const d = layoutDeltas[id] || {};
|
|
2046
|
+
const w = Math.max(b.size * 3, b.w0 + (d.dw || 0));
|
|
2047
|
+
const h = Math.max(b.size * 3, b.h0 + (d.dh || 0));
|
|
2048
|
+
b.rect.setAttribute("width", String(w));
|
|
2049
|
+
b.rect.setAttribute("height", String(h));
|
|
2050
|
+
if (d.dx || d.dy) b.g.setAttribute("transform", `translate(${d.dx || 0}, ${d.dy || 0})`);
|
|
2051
|
+
else b.g.removeAttribute("transform");
|
|
2052
|
+
positionBoxHandle(b, w, h);
|
|
2053
|
+
}
|
|
2054
|
+
for (const e of layoutIndex.edges) {
|
|
2055
|
+
const a = layoutDeltas[e.from];
|
|
2056
|
+
const z = layoutDeltas[e.to];
|
|
2057
|
+
if ((!a && !z) || !e.anchors) {
|
|
2058
|
+
if (e.paths[0].getAttribute("d") !== e.d0) e.paths.forEach((p) => p.setAttribute("d", e.d0));
|
|
2059
|
+
continue;
|
|
2060
|
+
}
|
|
2061
|
+
const { sx, sy, ex, ey } = e.anchors;
|
|
2062
|
+
const d = `M ${sx + ((a && a.dx) || 0)} ${sy + ((a && a.dy) || 0)} L ${ex + ((z && z.dx) || 0)} ${ey + ((z && z.dy) || 0)}`;
|
|
2063
|
+
e.paths.forEach((p) => p.setAttribute("d", d));
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
|
|
2067
|
+
/** Re-index the SVG, load this lens's deltas, paint them. Called from render(). */
|
|
2068
|
+
function applyLayout() {
|
|
2069
|
+
const svgEl = currentSvg();
|
|
2070
|
+
const host = document.getElementById("graph");
|
|
2071
|
+
if (!svgEl || !host) return;
|
|
2072
|
+
indexLayout(svgEl);
|
|
2073
|
+
const key = currentLayoutKey();
|
|
2074
|
+
// Stale ids are dropped on apply, not on write: a lens the user hasn't
|
|
2075
|
+
// opened in a while shouldn't have its deltas quietly deleted because this
|
|
2076
|
+
// render happened to be a different projection of the same estate.
|
|
2077
|
+
layoutDeltas = key ? applicable(readLayout(localStorage, key), [...layoutIndex.nodes.keys(), ...layoutIndex.boxes.keys()]) : {};
|
|
2078
|
+
renderLayout();
|
|
2079
|
+
ensureLayoutReset(host);
|
|
2080
|
+
ensureLayoutDrag(host);
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
/** The grabbable thing at or above `el`, if any. */
|
|
2084
|
+
function layoutTargetIn(el) {
|
|
2085
|
+
if (!el || typeof el.closest !== "function") return null;
|
|
2086
|
+
const resize = el.closest("[data-layout-resize]");
|
|
2087
|
+
if (resize) return { kind: "resize", id: resize.getAttribute("data-layout-resize") };
|
|
2088
|
+
const move = el.closest("[data-layout-move]");
|
|
2089
|
+
if (move) return { kind: "move", id: move.getAttribute("data-layout-move") };
|
|
2090
|
+
const node = el.closest("[data-node-id]");
|
|
2091
|
+
if (node) return { kind: "move", id: node.getAttribute("data-node-id") };
|
|
2092
|
+
return null;
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2095
|
+
/** What (if anything) a pointerdown grabbed. Also the pan handler's bail test. */
|
|
2096
|
+
function layoutTargetOf(e) {
|
|
2097
|
+
const direct = layoutTargetIn(e.target);
|
|
2098
|
+
if (direct) return direct;
|
|
2099
|
+
// An edge can swallow the grab: wireEdgeHighlight raises every edge on a
|
|
2100
|
+
// hovered card to the top of the SVG, and pinhole's 14-wide transparent
|
|
2101
|
+
// hit-path is anchored at the card's own centre — so by the time the pointer
|
|
2102
|
+
// is down, the edge you just lit is lying across the card you meant to move.
|
|
2103
|
+
// Look through the stack for the card underneath instead of giving up.
|
|
2104
|
+
if (!e.target || typeof e.target.closest !== "function" || !e.target.closest("g[data-edge-from]")) return null;
|
|
2105
|
+
for (const el of document.elementsFromPoint(e.clientX, e.clientY)) {
|
|
2106
|
+
const t = layoutTargetIn(el);
|
|
2107
|
+
if (t) return t;
|
|
2108
|
+
}
|
|
2109
|
+
return null;
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
/** Screen pixels → viewBox units at the current zoom. */
|
|
2113
|
+
function userPerPixel(svgEl) {
|
|
2114
|
+
const m = svgEl.getScreenCTM && svgEl.getScreenCTM();
|
|
2115
|
+
if (m && m.a && m.d) return { x: 1 / m.a, y: 1 / m.d };
|
|
2116
|
+
const r = svgEl.getBoundingClientRect();
|
|
2117
|
+
return vb && r.width && r.height ? { x: vb[2] / r.width, y: vb[3] / r.height } : { x: 1, y: 1 };
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
function ensureLayoutDrag(host) {
|
|
2121
|
+
if (layoutWired) return;
|
|
2122
|
+
layoutWired = true;
|
|
2123
|
+
host.addEventListener("pointerdown", (e) => {
|
|
2124
|
+
if (e.button !== 0 || !layoutIndex) return;
|
|
2125
|
+
const t = layoutTargetOf(e);
|
|
2126
|
+
if (!t || !currentSvg()) return;
|
|
2127
|
+
layoutDrag = { ...t, x0: e.clientX, y0: e.clientY, base: layoutDeltas[t.id] || {}, moved: false };
|
|
2128
|
+
// The same latch pan uses (wire()'s click-inspect bails on it): claim it on
|
|
2129
|
+
// grab so a drag is never also a click, and so the NEXT plain click on a
|
|
2130
|
+
// node isn't swallowed by a stale `true` from the gesture before it.
|
|
2131
|
+
panMoved = false;
|
|
2132
|
+
// Deliberately no preventDefault(): cancelling pointerdown suppresses the
|
|
2133
|
+
// compatibility mouse events, and click-inspect rides on those. The pan is
|
|
2134
|
+
// held off by its own guard instead, and the text selection a drag would
|
|
2135
|
+
// otherwise smear across the graph by `user-select: none` on the SVG.
|
|
2136
|
+
});
|
|
2137
|
+
window.addEventListener("pointermove", (e) => {
|
|
2138
|
+
if (!layoutDrag) return;
|
|
2139
|
+
const svgEl = currentSvg();
|
|
2140
|
+
if (!svgEl) return;
|
|
2141
|
+
const px = e.clientX - layoutDrag.x0;
|
|
2142
|
+
const py = e.clientY - layoutDrag.y0;
|
|
2143
|
+
if (!layoutDrag.moved && Math.abs(px) + Math.abs(py) <= 3) return;
|
|
2144
|
+
layoutDrag.moved = true;
|
|
2145
|
+
panMoved = true;
|
|
2146
|
+
const s = userPerPixel(svgEl);
|
|
2147
|
+
const dx = px * s.x;
|
|
2148
|
+
const dy = py * s.y;
|
|
2149
|
+
const b = layoutDrag.base;
|
|
2150
|
+
const next =
|
|
2151
|
+
layoutDrag.kind === "resize"
|
|
2152
|
+
? { dx: b.dx || 0, dy: b.dy || 0, dw: (b.dw || 0) + dx, dh: (b.dh || 0) + dy }
|
|
2153
|
+
: { dx: (b.dx || 0) + dx, dy: (b.dy || 0) + dy, dw: b.dw || 0, dh: b.dh || 0 };
|
|
2154
|
+
layoutDeltas = setDelta(layoutDeltas, layoutDrag.id, next);
|
|
2155
|
+
renderLayout();
|
|
2156
|
+
});
|
|
2157
|
+
window.addEventListener("pointerup", () => {
|
|
2158
|
+
if (!layoutDrag) return;
|
|
2159
|
+
const moved = layoutDrag.moved;
|
|
2160
|
+
layoutDrag = null;
|
|
2161
|
+
if (!moved) return;
|
|
2162
|
+
const key = currentLayoutKey();
|
|
2163
|
+
if (key) writeLayout(localStorage, key, layoutDeltas);
|
|
2164
|
+
ensureLayoutReset(document.getElementById("graph"));
|
|
2165
|
+
});
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
/** The "↺ layout" control beside ⤢ fit — shown only while something is hand-placed. */
|
|
2169
|
+
function ensureLayoutReset(host) {
|
|
2170
|
+
if (!host) return;
|
|
2171
|
+
let btn = document.getElementById("layout-reset");
|
|
2172
|
+
if (!btn || btn.parentElement !== host) {
|
|
2173
|
+
btn = document.createElement("button");
|
|
2174
|
+
btn.id = "layout-reset";
|
|
2175
|
+
btn.textContent = "↺ layout";
|
|
2176
|
+
btn.title =
|
|
2177
|
+
"Drop the hand-placed layout for this project + this lens and go back to dagre's. " +
|
|
2178
|
+
"(A resized box never reflows what's inside it — only the next layout does that.)";
|
|
2179
|
+
btn.addEventListener("click", (e) => {
|
|
2180
|
+
e.stopPropagation();
|
|
2181
|
+
const key = currentLayoutKey();
|
|
2182
|
+
if (key) clearLayout(localStorage, key);
|
|
2183
|
+
layoutDeltas = {};
|
|
2184
|
+
renderLayout();
|
|
2185
|
+
ensureLayoutReset(host);
|
|
2186
|
+
nowline("↺ layout reset — back to dagre's placement");
|
|
2187
|
+
});
|
|
2188
|
+
host.appendChild(btn);
|
|
2189
|
+
}
|
|
2190
|
+
btn.style.display = isEmpty(layoutDeltas) ? "none" : "";
|
|
2191
|
+
}
|
|
2192
|
+
|
|
1855
2193
|
// Precondition-failure codes (#72) → a short, human title for the entry/error
|
|
1856
2194
|
// screen below. Mirrors every `code` a read route's structured error can
|
|
1857
2195
|
// carry (src/server.ts RouteErrorCode: chant.ts's lint/not-installed/eval,
|
|
@@ -2228,7 +2566,7 @@ function showToast(msg, ok) {
|
|
|
2228
2566
|
}
|
|
2229
2567
|
const t = document.createElement("div");
|
|
2230
2568
|
const color = ok ? "var(--managed)" : "var(--degraded)";
|
|
2231
|
-
t.style.cssText = `background:var(--panel);color:var(--fg);border:1px solid ${color};border-left:4px solid ${color};border-radius:
|
|
2569
|
+
t.style.cssText = `background:var(--panel);color:var(--fg);border:1px solid ${color};border-left:4px solid ${color};border-radius:var(--r-ctl);padding:8px 12px;font-size:var(--t-body);box-shadow:0 6px 18px color-mix(in srgb, var(--shadow) 50%, transparent);cursor:pointer;white-space:pre-wrap`;
|
|
2232
2570
|
t.textContent = msg;
|
|
2233
2571
|
t.onclick = () => t.remove();
|
|
2234
2572
|
host.appendChild(t);
|
|
@@ -2309,7 +2647,7 @@ async function openRollback(btn) {
|
|
|
2309
2647
|
wrap.style.cssText = "display:flex;gap:6px;align-self:center";
|
|
2310
2648
|
const sel = document.createElement("select");
|
|
2311
2649
|
sel.style.cssText =
|
|
2312
|
-
"background:var(--
|
|
2650
|
+
"background:var(--well);color:var(--fg);border:1px solid var(--line);border-radius:var(--r-ctl);padding:4px 8px;font-size:var(--t-body);max-width:340px";
|
|
2313
2651
|
for (const c of commits) sel.add(new Option(`${c.sha} · ${c.subject} (${c.date})`, c.sha));
|
|
2314
2652
|
const go = button("Roll back →", "", () => {
|
|
2315
2653
|
const to = sel.value;
|
|
@@ -2353,7 +2691,7 @@ async function initActions() {
|
|
|
2353
2691
|
const pill = document.createElement("span");
|
|
2354
2692
|
pill.textContent = `● static snapshot${manifest && manifest.capturedAt ? " · " + manifest.capturedAt.slice(0, 16).replace("T", " ") : ""}`;
|
|
2355
2693
|
pill.title = "An exported, read-only snapshot — no live observe or deploy.";
|
|
2356
|
-
pill.style.cssText = "align-self:center;font-
|
|
2694
|
+
pill.style.cssText = "align-self:center;font:var(--t-caption)/1.4 var(--font-mono);color:var(--muted);border:1px solid var(--line);border-radius:var(--r-ctl);padding:2px 8px";
|
|
2357
2695
|
bar.appendChild(pill);
|
|
2358
2696
|
previewMode = true;
|
|
2359
2697
|
return; // nothing else in the bar is a read
|
|
@@ -2385,7 +2723,7 @@ async function initActions() {
|
|
|
2385
2723
|
local.emulators.map((e) => `${e.lexicon} ${e.name} @ ${e.endpoint}`).join("; ") +
|
|
2386
2724
|
". Deploys and the overlay observe them — no cloud creds.";
|
|
2387
2725
|
pill.style.cssText =
|
|
2388
|
-
"align-self:center;font-
|
|
2726
|
+
"align-self:center;font:var(--t-caption)/1.4 var(--font-mono);color:var(--managed);border:1px solid var(--managed);border-radius:var(--r-ctl);padding:2px 8px";
|
|
2389
2727
|
bar.appendChild(pill);
|
|
2390
2728
|
}
|
|
2391
2729
|
// Auto-sync banner (#29) — make an active self-heal loop visible, not silent.
|
|
@@ -2394,7 +2732,7 @@ async function initActions() {
|
|
|
2394
2732
|
pill.textContent = `⟳ auto-sync: ${autoSync}`;
|
|
2395
2733
|
pill.title = `On polled drift, behold triggers the ${autoSync === "apply" ? "ApplyOp (heal)" : "ReconcileOp (adopt)"}. Gated applies still wait for Approve.`;
|
|
2396
2734
|
pill.style.cssText =
|
|
2397
|
-
"align-self:center;font-
|
|
2735
|
+
"align-self:center;font:var(--t-caption)/1.4 var(--font-mono);color:var(--pending);border:1px solid var(--pending);border-radius:var(--r-ctl);padding:2px 8px";
|
|
2398
2736
|
bar.appendChild(pill);
|
|
2399
2737
|
}
|
|
2400
2738
|
opsApply = ops.find((o) => o.kind === "apply") ?? null;
|
|
@@ -2441,7 +2779,7 @@ async function initActions() {
|
|
|
2441
2779
|
// its deploy path is Apply all, not committed Ops).
|
|
2442
2780
|
if (ops.length === 0 && !previewMode && !opsInitialEnv) {
|
|
2443
2781
|
const hint = document.createElement("span");
|
|
2444
|
-
hint.style.cssText = "color:var(--muted);font-size:
|
|
2782
|
+
hint.style.cssText = "color:var(--muted);font-size:var(--t-caption);align-self:center";
|
|
2445
2783
|
hint.textContent = "no Ops — commit an *.op.ts (ApplyOp / ReconcileOp / any deploy Op) to act";
|
|
2446
2784
|
hint.title = "behold triggers committed Ops on your executor. Add one to enable Deploy / Adopt / Run.";
|
|
2447
2785
|
bar.appendChild(hint);
|
|
@@ -2510,7 +2848,7 @@ events.addEventListener("pr", (e) => {
|
|
|
2510
2848
|
slot.id = "pr-link";
|
|
2511
2849
|
slot.target = "_blank";
|
|
2512
2850
|
slot.rel = "noopener";
|
|
2513
|
-
slot.style.cssText = "color:var(--managed);text-decoration:none;font-size:
|
|
2851
|
+
slot.style.cssText = "color:var(--managed);text-decoration:none;font-size:var(--t-body);align-self:center";
|
|
2514
2852
|
document.getElementById("actions").after(slot);
|
|
2515
2853
|
}
|
|
2516
2854
|
slot.href = url;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" viewBox="0 0 581 747"><path id="cncf-argo-a" fill="#fff" d="M336.76 437.61c0 28.31-18.83 43.36-49.29 43.36-30.45 0-47.2-17.84-47.2-43.36 0 0 16.75 23.65 47.2 23.65 30.46 0 49.3-23.65 49.3-23.65Z"/><path fill="#E2F5FC" d="M290.5 547.98c148.47 0 268.84-120.45 268.84-269.04 0-148.58-120.37-269.03-268.84-269.03-148.47 0-268.84 120.45-268.84 269.03 0 148.59 120.37 269.04 268.84 269.04Z"/><path fill="#CDECF6" d="M290.5 504.04c121.36 0 219.74-98.45 219.74-219.9S411.86 64.24 290.5 64.24c-121.36 0-219.74 98.45-219.74 219.9s98.38 219.9 219.74 219.9Z"/><path fill="#fff" d="M208.31 91.51a12.98 12.98 0 1 0 0-25.96 12.98 12.98 0 0 0 0 25.96Zm-96.57 325.82a4.5 4.5 0 1 0 7.08-5.54c-87.8-112.21-37.15-257.65 62.5-314.74a4.5 4.5 0 0 0-4.47-7.8C73.23 148.6 20.03 300.12 111.74 417.33Z"/><path fill="#B5D2F3" d="M19.26 225.54a3.5 3.5 0 1 0-7 0h7Zm-7 105.38a3.5 3.5 0 1 0 7 0h-7Zm555.07-105.88a3.5 3.5 0 1 0-7 0h7Zm-7 105.38a3.5 3.5 0 1 0 7 0h-7ZM289.79 555.97c153.28 0 277.54-124.35 277.54-277.73h-7c0 149.52-121.13 270.73-270.54 270.73v7Zm277.54-277.73C567.33 124.84 443.07.5 289.79.5v7c149.41 0 270.54 121.21 270.54 270.74h7ZM289.79.5C136.51.5 12.26 124.85 12.26 278.24h7C19.26 128.7 140.38 7.5 289.79 7.5v-7ZM12.26 278.24c0 153.38 124.25 277.73 277.53 277.73v-7c-149.4 0-270.53-121.2-270.53-270.73h-7Zm0-52.7v105.38h7V225.54h-7Zm548.07-.5v105.38h7V225.04h-7Z"/><path fill="#B5D2F3" d="M21.66 225.73a10.84 10.84 0 1 0-21.66 0v106.43a10.84 10.84 0 1 0 21.66 0V225.73Zm559.34 0a10.84 10.84 0 1 0-21.66 0v106.43a10.84 10.84 0 1 0 21.66 0V225.73Z"/><path fill="#FE733E" d="M171.17 687.76c12.53-5.1 9.98-10.2 9.98-12.74l-6.1-92.55-5.37-46.3-8.12-289.07c0-68.6 50.73-132.72 127.3-132.72s130.76 61.71 130.88 132.77c-2.2 137.24-5.9 189.47-11.07 288.02-.63 13.47-2.38 33.86-2.96 46.32-2.88 61.66-6.14 91.87-6.14 93.53 0 2.55-2.54 7.64 9.98 12.74 12.52 5.1 41.46 11.71 41.46 13.33 0 1.6-48.89 0-48.89 0-28.02 0-28.02-20.98-28.02-26.07 0-5.1-7.64-92.6-7.64-92.6l-2.55 112.99c0 5.1 2.55 12.74 20.38 17.84 0 0 38.91 5.89 38.91 8.01 0 2.13-46.55 0-46.55 0-35.45 0-35.45-20.75-35.45-20.75l-7.64-92.6S331 700.5 331 713.24c0 9.99 1.73 17.63 29.54 22.73 13.43 3.73 40.54 8.35 40.54 10.2 0 1.85-61.86 0-61.86 0-33.11-2.55-36.24-25.5-36.24-25.5l-12.55-46.14-12.5 46.15s-5.09 22.94-38.2 25.49c0 0-56.17 1.85-56.17 0s22.5-5.99 36.81-10.2c19.36-5.69 29.55-12.74 29.55-22.73 0-12.74-2.55-105.35-2.55-105.35l-7.64 92.6s0 22.74-35.45 22.74c0 0-50.5.15-50.5-1.98 0-2.12 42.64-8 42.64-8 17.83-5.1 20.38-12.75 20.38-17.85l-2.55-113s-7.64 87.5-7.64 92.6c0 5.1 0 28.05-28.02 28.05 0 0-47.13-2.33-47.13-3.95 0-1.6 27.18-6.25 39.7-11.35Z"/><path fill="#FE6446" d="M169.68 536.16s-5.23 12.8-17.05 19.7c-11.81 6.9-25.51 9.14-38.4 10.84 0 0 17.72 8.87 39.39 6.9 13.58-1.1 19.28 2.36 21.42 8.87l-5.36-46.3Zm238.99-.99s7.63 12.8 19.45 19.7c11.82 6.9 25.51 9.15 38.4 10.85 0 0-17.72 8.87-39.38 6.9-13.58-1.1-19.29 2.35-21.43 8.87l2.96-46.32Z"/><path fill="#FE6446" d="m408.81 533 .99-16.02c-62.56 29.54-120.7 26.43-120.7 26.43s-58.49 2.45-119.92-26.57l.4 15.57s43.82 26.94 119.52 26.94c75.7 0 119.71-26.35 119.71-26.35Z" opacity=".3"/><path fill="#FEA777" d="M238.78 194.25a17.84 17.84 0 1 0-.01-35.67 17.84 17.84 0 0 0 .01 35.67Z" opacity=".5"/><path fill="#FE6B3C" d="M419.5 249.06s1.88-22.34-7.88-48.94c-26.77-73.01-92.56-87.71-128.02-85.64 0 0 50.28 23.76 52.61 99.8 1.06 33.72 1.06 34.78 1.06 34.78h82.23Z"/><use xlink:href="#cncf-argo-a"/><use xlink:href="#cncf-argo-a"/><path fill="#fff" d="M336.76 437.61c0 28.31-11.39 72.92-49.29 72.92s-47.2-47.4-47.2-72.92c0 0 0 43.36 47.2 43.36 51.62 0 49.3-43.36 49.3-43.36Z"/><path fill="#070909" d="M336.76 437.61c0 28.31-11.39 72.92-49.29 72.92s-47.2-47.4-47.2-72.92c0 0 0 43.36 47.2 43.36 51.62 0 49.3-43.36 49.3-43.36Z"/><path fill="#FE6446" d="M197.93 394.25a77.82 77.82 0 0 0 77.8-77.85c0-43-34.83-77.85-77.8-77.85a77.82 77.82 0 0 0-77.8 77.85c0 43 34.84 77.85 77.8 77.85Z"/><path fill="#fff" d="M197.73 378.32a60.94 60.94 0 0 0 60.92-60.96 60.94 60.94 0 0 0-60.92-60.97 60.94 60.94 0 0 0-60.92 60.97 60.94 60.94 0 0 0 60.92 60.96Z"/><path fill="#090B0B" d="M195.96 325.27a18.72 18.72 0 1 0-.01-37.44 18.72 18.72 0 0 0 .01 37.44Z"/><path fill="#FE6446" d="M381.1 394.25a77.82 77.82 0 0 0 77.79-77.85c0-43-34.83-77.85-77.8-77.85a77.82 77.82 0 0 0-77.79 77.85c0 43 34.83 77.85 77.8 77.85Z"/><path fill="#fff" d="M378 378.21a60.94 60.94 0 0 0 60.93-60.96A60.94 60.94 0 0 0 378 256.29a60.94 60.94 0 0 0-60.92 60.96A60.94 60.94 0 0 0 378 378.21Z"/><path fill="#090B0B" d="M379.13 325.27a18.72 18.72 0 1 0-.02-37.44 18.72 18.72 0 0 0 .01 37.44Z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="48.00 -2.25 262.50 364.00"><defs><style>.cncf-flux-cls-1{fill:#326ce5}.cncf-flux-cls-3{fill:none}</style></defs><path d="M59.72393 97.77847a10.18251 10.18251 0 0 1 0-17.07393l114.0703-74.16023a10.18258 10.18258 0 0 1 11.10024 0l114.07029 74.16023a10.1825 10.1825 0 0 1 0 17.07394l-114.07029 74.16021a10.18254 10.18254 0 0 1-11.10024 0z" class="cncf-flux-cls-1"/><path fill="#c1d2f7" d="M197.35565 110.866h7.91277a6.00326 6.00326 0 0 0 5.19908-9.005l-25.92381-44.902a6.00355 6.00355 0 0 0-10.39838 0l-25.924 44.902a6.00326 6.00326 0 0 0 5.19905 9.005h7.913a6.0034 6.0034 0 0 1 6.00341 6.0034v51.2563l5.31037 3.45252a12.28743 12.28743 0 0 0 13.39445 0l5.31062-3.45252v-51.25628a6.0034 6.0034 0 0 1 6.0034-6.00341z"/><path d="M173.79348 353.27108a10.12828 10.12828 0 0 0 3.45643 1.402c-2.17549-1.2312-4.38727-2.37429-6.62269-3.46036zm-6.45667-161.19546l-11.3157 7.35661a110.993 110.993 0 0 0 11.31571 6.5997zm24.01537 23.71607c9.73858 3.11505 19.81317 5.64851 30.10973 8.18655 10.92032 2.69182 21.97355 5.42717 32.81792 9.00839l-35.41606-23.02482a215.88133 215.88133 0 0 1-27.51161-9.41007zm0 62.19159v.58577c0 2.56929-2.68787 4.65195-6.00338 4.65195h-12.00855c-3.31549 0-6.00338-2.08266-6.00338-4.65195v-6.60473c-24.90538-6.40209-49.87294-14.48506-70.85945-33.8211L81.94819 247.589c22.46761 22.0509 50.27893 28.93291 79.71441 36.1886 27.17852 6.69856 55.18051 13.65144 78.68557 33.44222l14.67907-9.54334c-18.53142-16.50431-40.40962-23.68778-63.67506-29.6932zm-98.03756 22.96639l38.90829 25.29525c20.06438 5.11336 40.20029 11.24773 58.311 23.36044l14.90023-9.687c-19.7518-13.6724-42.5505-19.3134-66.41889-25.197-15.28704-3.76779-30.83479-7.6166-45.70063-13.77169zm74.02219-82.25413a124.3199 124.3199 0 0 1-21.53392-12.62006l-14.80531 9.62521a124.54057 124.54057 0 0 0 36.33923 18.708zm51.41006 16.29412c-9.1062-2.24474-18.30362-4.52388-27.39469-7.29853v13.68209q5.051 1.2853 10.17672 2.53817c29.93438 7.37818 60.8879 15.00885 85.70767 39.82861.60979.60979 1.16261 1.23989 1.752 1.85715l9.97427-6.48445a10.10425 10.10425 0 0 0 3.47529-3.79928c-1.06644-1.17252-2.144-2.34132-3.28875-3.48612-22.58513-22.5853-50.66938-29.50856-80.40251-36.83764zm-19.93295 19.93298q-3.72217-.91747-7.46168-1.85484v13.20974c25.81676 6.56181 51.80263 14.68843 73.4551 35.04069l14.52114-9.44055c-.03854-.03875-.07256-.07916-.11131-.11792-22.58546-22.58524-50.66975-29.50848-80.40325-36.83712zm-31.47711-8.58681c-16.28-5.27813-32.11777-12.39682-46.344-24.13081l-14.68176 9.5451c17.87023 15.55727 38.7844 22.67266 61.02572 28.50068z" class="cncf-flux-cls-3"/><path d="M73.24049 254.95972c-.348-.348-.6585-.70949-.99967-1.05976l-12.51495 8.13648a10.16548 10.16548 0 0 0-1.64428 1.3968c1.05336 1.15677 2.11561 2.31024 3.24544 3.44 22.5852 22.58519 50.66968 29.50838 80.40322 36.83688 25.3425 6.24691 51.40113 12.71661 73.86454 29.60253l14.80574-9.62562c-20.86424-16.41993-45.53021-22.50891-71.45287-28.898-29.93385-7.37888-60.88738-15.00944-85.70717-39.82931z" class="cncf-flux-cls-3"/><path d="M218.86377 209.9618l-27.51159-17.886v8.4759a215.88 215.88 0 0 0 27.51159 9.4101zm-27.51159 5.82989v11.89938c9.09108 2.77471 18.28849 5.05388 27.39469 7.29853 29.73311 7.32909 57.81738 14.25232 80.40261 36.83773 1.14474 1.14474 2.22232 2.31354 3.28875 3.48611a10.19327 10.19327 0 0 0-3.4753-13.27711l-44.6831-29.04976c-10.84437-3.58121-21.89768-6.31656-32.81794-9.00838-10.29656-2.53799-20.37113-5.07145-30.10971-8.1865zm-24.01537-9.75969a110.99292 110.99292 0 0 1-11.31571-6.59969l-10.21821 6.6432a124.31932 124.31932 0 0 0 21.53392 12.62007zm34.19212 37.87941q-5.12528-1.26352-10.17673-2.53816v11.6946q3.73686.938 7.46168 1.85485c29.73352 7.32863 57.8178 14.25187 80.40318 36.83709.03876.03876.07277.07916.11132.11792l9.66023-6.28051c-.58945-.61726-1.14225-1.24733-1.752-1.85715-24.81978-24.81979-55.7733-32.45048-85.70768-39.82864zm-34.19212-9.50272a124.54057 124.54057 0 0 1-36.33923-18.708l-10.00473 6.50436c14.22612 11.734 30.06393 18.85268 46.344 24.1308zm0 25.84203c-22.24132-5.828-43.1555-12.94341-61.02572-28.5006l-9.8338 6.39315c20.98652 19.336 45.95407 27.41893 70.85947 33.8211zm24.01537 17.73256c23.26546 6.00539 45.14367 13.18886 63.67506 29.69312l9.78-6.35823c-21.65249-20.35225-47.63835-28.47893-73.45509-35.04068zM81.94813 247.589l-9.70729 6.311c.34117.35032.65166.71178.99967 1.05976 24.81977 24.81979 55.77329 32.45043 85.70706 39.82925 25.92266 6.38909 50.58863 12.47807 71.45288 28.898l9.94772-6.46724c-23.50506-19.79078-51.507-26.74365-78.68557-33.44222-29.43548-7.25569-57.2468-14.1377-79.71447-36.18855zM61.327 266.87321c-1.12983-1.12983-2.19209-2.28328-3.24545-3.44a10.1544 10.1544 0 0 0 1.64428 15.67957l33.5887 21.83694c14.86583 6.15509 30.41359 10.0039 45.70058 13.77166 23.8684 5.88357 46.66708 11.52464 66.4189 25.197l10.1606-6.6057c-22.46332-16.88587-48.522-23.35562-73.86447-29.60253-29.73343-7.32851-57.81791-14.25175-80.40314-36.83694zm109.30024 84.33948c2.2354 1.0861 4.44718 2.22919 6.62269 3.46036a10.16012 10.16012 0 0 0 7.64543-1.402l5.63858-3.66577c-18.11065-12.11266-38.24653-18.247-58.31095-23.36044z" class="cncf-flux-cls-1"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg id="cncf-helm-Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cncf-helm-cls-1{fill:#0f1689;}</style></defs><path class="cncf-helm-cls-1" d="M136.52938,121.13478c-.572-.54252-1.19462-1.12636-1.81-1.71761-12.61677-12.12115-22.38092-26.13637-28.279-42.702-1.65073-4.63637-2.89692-9.36515-2.67587-14.35871.021-.4739.01959-.94915.05226-1.42214.445-6.44594,4.75912-9.70322,11.05839-8.17669a27.325,27.325,0,0,1,5.73149,2.19653c6.89022,3.45538,12.5062,8.56359,17.67051,14.16571a112.52651,112.52651,0,0,1,21.722,33.42965,8.29635,8.29635,0,0,0,.38946.861c.07116.12855.22232.21282.55927.51883A176.357,176.357,0,0,1,241.968,79.06864c-.17651-.8761-.28195-1.54571-.44772-2.2a112.49436,112.49436,0,0,1-2.65292-36.95637,84.07478,84.07478,0,0,1,4.44444-21.76378,31.32555,31.32555,0,0,1,5.47651-10.17139,15.687,15.687,0,0,1,3.16336-2.82149,7.026,7.026,0,0,1,8.03255-.056,17.27854,17.27854,0,0,1,5.8402,6.73185A53.05435,53.05435,0,0,1,271.08657,26.508a112.50469,112.50469,0,0,1,2.12263,33.00356,95.59806,95.59806,0,0,1-3.49052,19.91081c7.12171,1.31193,14.20955,2.32869,21.1473,3.97713a186.37909,186.37909,0,0,1,20.44069,6.0033A188.31671,188.31671,0,0,1,331.0769,97.9721c6.34538,3.16433,12.38553,6.94066,18.71757,10.53829.20571-.433.50439-.94982.706-1.50212A108.65959,108.65959,0,0,1,383.40128,60.246a37.75787,37.75787,0,0,1,11.822-6.883,17.24558,17.24558,0,0,1,3.67827-.84512c6.264-.71729,8.89351,3.2244,9.35653,7.93183a29.94372,29.94372,0,0,1-.77381,10.35466A87.90551,87.90551,0,0,1,396.75426,95.492c-6.79016,10.97178-14.85015,20.85494-25.09307,28.83042-.30234.2354-.56784.51814-1.07988.99029a177.77993,177.77993,0,0,1,26.59293,30.88244,10.96227,10.96227,0,0,1-1.689.29762c-10.59546.015-21.1911-.01829-31.78622.04607a4.004,4.004,0,0,1-3.17246-1.69,147.87522,147.87522,0,0,0-88.17776-46.54846,143.35862,143.35862,0,0,0-30.27955-1.16923,146.40735,146.40735,0,0,0-82.53728,31.81054,140.06663,140.06663,0,0,0-16.97616,15.84186,4.72839,4.72839,0,0,1-3.86326,1.75742c-10.12056-.07028-20.24188-.035-30.36293-.03495h-2.15212c.618-2.408,6.84026-10.93786,13.88352-18.55281C125.31349,132.2744,130.87768,126.8839,136.52938,121.13478Z"/><path class="cncf-helm-cls-1" d="M394.52934,347.9123a176.63854,176.63854,0,0,1-23.97343,27.16338c.70941.59068,1.28594,1.07041,1.86212,1.55057A108.31456,108.31456,0,0,1,406.10131,424.772a34.61831,34.61831,0,0,1,2.202,14.42026,14.88544,14.88544,0,0,1-.74786,3.69206,7.20762,7.20762,0,0,1-8.15793,5.02308,22.23329,22.23329,0,0,1-6.76276-2.00629,51.23237,51.23237,0,0,1-9.18151-5.8151,107.59183,107.59183,0,0,1-32.936-46.7072c-.18746-.51334-.39218-1.0204-.72243-1.87691a194.65008,194.65008,0,0,1-25.01223,14.00774,181.66925,181.66925,0,0,1-26.6869,9.72442,187.55649,187.55649,0,0,1-28.3045,5.38805c.16807.84015.26446,1.5098.43745,2.15907a109.172,109.172,0,0,1,2.9708,36.44311,80.804,80.804,0,0,1-4.42286,22.4773,78.24971,78.24971,0,0,1-4.16475,8.74473,13.39,13.39,0,0,1-2.33865,2.97083c-3.98009,4.109-8.73225,4.144-12.61157-.07366a27.28012,27.28012,0,0,1-3.907-5.61776c-3.07685-5.77569-4.6604-12.056-5.791-18.46021a116.86329,116.86329,0,0,1-1.35893-26.465,94.4795,94.4795,0,0,1,2.88466-19.18513c.14009-.53269.268-1.0696.37134-1.61034.02629-.13754-.06342-.2973-.17067-.73825a176.12108,176.12108,0,0,1-80.96855-24.99386c-.40992.90921-.76206,1.67473-1.10168,2.44579a110.47729,110.47729,0,0,1-30.90112,41.42041,38.16071,38.16071,0,0,1-12.04706,6.95909,12.08987,12.08987,0,0,1-6.51516.70023,7.11858,7.11858,0,0,1-5.40329-4.4892c-1.41614-3.424-1.16526-6.985-.68438-10.51691a55.45267,55.45267,0,0,1,4.30768-14.25037A112.49985,112.49985,0,0,1,134.88761,380.779c.459-.43461.92981-.857,1.38087-1.29954a3.76029,3.76029,0,0,0,.36534-.65529,178.90466,178.90466,0,0,1-28.469-31.31672c.98458-.08018,1.64327-.18,2.30205-.1806,10.51436-.00976,21.029.02736,31.54284-.04358a4.70554,4.70554,0,0,1,3.70344,1.62615,146.94611,146.94611,0,0,0,39.40276,28.88494,139.94667,139.94667,0,0,0,49.70395,14.77367q70.68048,6.87067,121.59971-42.85452a7.64571,7.64571,0,0,1,5.99261-2.44347c9.80139.12121,19.60512.04986,29.408.04986h2.53353Z"/><path class="cncf-helm-cls-1" d="M350.73576,197.76167c2.78711,0,5.47037.18919,8.11487-.0501,2.9951-.271,5.139.8001,7.32354,2.81308,12.61275,11.62214,25.35732,23.10129,38.05863,34.62729.63855.57948,1.29039,1.14432,2.1101,1.8701.76445-.65718,1.48119-1.24318,2.16483-1.8655Q428.14636,217.27914,447.756,199.37a5.44772,5.44772,0,0,1,4.20358-1.64576c3.21888.13038,6.44673.03746,9.8412.03746V303.13036c-1.72309.50368-24.8756.60366-27.63911.0611v-53.362l-.53656-.25427c-9.01079,8.21784-18.0216,16.43564-27.23786,24.8408-9.22584-8.31119-18.34194-16.52347-27.458-24.73577l-.52449.19192c-.023,4.45359-.00774,8.90828-.01046,13.36233q-.00408,6.63942-.00058,13.27882v26.87211h-27.428C350.45161,301.61243,350.21289,203.72342,350.73576,197.76167Z"/><path class="cncf-helm-cls-1" d="M97.63436,197.88229h27.26325c.55054,1.75251.65821,102.97139.09469,105.525H97.70468c-.15021-6.70344-.04736-13.38394-.06622-20.06131-.01871-6.62261-.0041-13.24531-.0041-20.03958H63.84679V303.047c-2.05946.61518-25.33374.67417-27.64758.123V197.89436H63.73742v37.18876c1.96793.56844,30.92319.67339,33.872.12942.00818-2.97713.02-6.02646.024-9.0758q.0063-4.7433.00094-9.4866,0-4.625,0-9.25C97.63437,204.32179,97.63436,201.24346,97.63436,197.88229Z"/><path class="cncf-helm-cls-1" d="M157.5757,303.3683V198.1946c1.617-.52913,61.545-.73586,65.46219-.20457v22.41432c-.87869.063-1.7857.18341-2.69279.18454q-16.0086.01994-32.01725.00881l-2.96767,0v17.43353H218.7067V261.2229H185.65838c-.55339,1.98509-.70531,15.81681-.25622,19.64583.84488.05679,1.75.16952,2.6553.17059q16.00862.01863,32.01727.00822h2.96945V303.3683Z"/><path class="cncf-helm-cls-1" d="M254.28291,303.40855c-.50074-2.82232-.39948-103.60181.09747-105.51735h27.16208v77.76453c1.17173.06084,2.09122.14921,3.01077.15005q16.128.01468,32.2561.00658c.92562,0,1.85125,0,2.90733,0v27.59622Z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="18.035334mm" height="17.500378mm" viewBox="0 0 18.035334 17.500378" version="1.1" id="k8s-c-role-svg13826" inkscape:version="0.91 r13725" sodipodi:docname="c-role.svg"><defs id="k8s-c-role-defs13820" /><g inkscape:label="Calque 1" inkscape:groupmode="layer" id="k8s-c-role-layer1" transform="translate(-0.99262638,-1.174181)"><g id="k8s-c-role-g70" transform="matrix(1.0148887,0,0,1.0148887,16.902146,-2.698726)"><path inkscape:export-ydpi="250.55" inkscape:export-xdpi="250.55" inkscape:export-filename="new.png" inkscape:connector-curvature="0" id="k8s-c-role-path3055" d="m -6.8492015,4.2724668 a 1.1191255,1.1099671 0 0 0 -0.4288818,0.1085303 l -5.8524037,2.7963394 a 1.1191255,1.1099671 0 0 0 -0.605524,0.7529759 l -1.443828,6.2812846 a 1.1191255,1.1099671 0 0 0 0.151943,0.851028 1.1191255,1.1099671 0 0 0 0.06362,0.08832 l 4.0508,5.036555 a 1.1191255,1.1099671 0 0 0 0.874979,0.417654 l 6.4961011,-0.0015 a 1.1191255,1.1099671 0 0 0 0.8749788,-0.416906 L 1.3818872,15.149453 A 1.1191255,1.1099671 0 0 0 1.5981986,14.210104 L 0.15212657,7.9288154 A 1.1191255,1.1099671 0 0 0 -0.45339794,7.1758396 L -6.3065496,4.3809971 A 1.1191255,1.1099671 0 0 0 -6.8492015,4.2724668 Z" style="fill:#326ce5;fill-opacity:1;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /><path id="k8s-c-role-path3054-2-9" d="M -6.8523435,3.8176372 A 1.1814304,1.171762 0 0 0 -7.3044284,3.932904 l -6.1787426,2.9512758 a 1.1814304,1.171762 0 0 0 -0.639206,0.794891 l -1.523915,6.6308282 a 1.1814304,1.171762 0 0 0 0.160175,0.89893 1.1814304,1.171762 0 0 0 0.06736,0.09281 l 4.276094,5.317236 a 1.1814304,1.171762 0 0 0 0.92363,0.440858 l 6.8576188,-0.0015 a 1.1814304,1.171762 0 0 0 0.9236308,-0.44011 l 4.2745966,-5.317985 a 1.1814304,1.171762 0 0 0 0.228288,-0.990993 L 0.53894439,7.6775738 A 1.1814304,1.171762 0 0 0 -0.10026101,6.8834313 L -6.2790037,3.9321555 A 1.1814304,1.171762 0 0 0 -6.8523435,3.8176372 Z m 0.00299,0.4550789 a 1.1191255,1.1099671 0 0 1 0.5426517,0.1085303 l 5.85315169,2.7948425 A 1.1191255,1.1099671 0 0 1 0.15197811,7.9290648 L 1.598051,14.21035 a 1.1191255,1.1099671 0 0 1 -0.2163123,0.939348 l -4.0493032,5.037304 a 1.1191255,1.1099671 0 0 1 -0.8749789,0.416906 l -6.4961006,0.0015 a 1.1191255,1.1099671 0 0 1 -0.874979,-0.417652 l -4.0508,-5.036554 a 1.1191255,1.1099671 0 0 1 -0.06362,-0.08832 1.1191255,1.1099671 0 0 1 -0.151942,-0.851028 l 1.443827,-6.2812853 a 1.1191255,1.1099671 0 0 1 0.605524,-0.7529758 l 5.8524036,-2.7963395 a 1.1191255,1.1099671 0 0 1 0.4288819,-0.1085303 z" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;marker:none;enable-background:accumulate" inkscape:connector-curvature="0" /></g><g id="k8s-c-role-g3341" transform="translate(0,0.28092246)"><ellipse id="k8s-c-role-ellipse7838-2" pointer-events="none" ry="0.50229818" rx="0.50633514" cy="9.9493122" cx="9.9282999" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.12665248" /><path id="k8s-c-role-path7840-40" pointer-events="none" d="m 10.010926,5.8761701 -3.1080511,1.374181 0,2.0505009 c 0,1.901056 1.3247841,3.677988 3.1080511,4.109873 1.780734,-0.431885 3.106786,-2.208817 3.106786,-4.109873 l 0,-2.0505009 z m 1.645216,5.5182459 -3.291698,0 0,-2.7635579 0.472414,0 0,-0.301428 c 0,-0.650995 0.53194,-1.17914 1.189266,-1.17914 0.657327,0 1.189267,0.528145 1.189267,1.17914 l 0,0.301428 0.440751,0 z" inkscape:connector-curvature="0" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.12665248" /><path id="k8s-c-role-path7836-7" pointer-events="none" d="m 9.9878259,7.5890498 c -0.393889,0.0014 -0.713053,0.317896 -0.713053,0.707987 l 0,0.296364 1.4273741,0 0,-0.301428 c -0.0038,-0.388828 -0.321698,-0.701659 -0.7143211,-0.702923 z" inkscape:connector-curvature="0" style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.12665248" /></g></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="18.035334mm" height="17.500378mm" viewBox="0 0 18.035334 17.500378" version="1.1" id="k8s-cm-svg13826" inkscape:version="0.91 r13725" sodipodi:docname="cm.svg"><defs id="k8s-cm-defs13820" /><g inkscape:label="Calque 1" inkscape:groupmode="layer" id="k8s-cm-layer1" transform="translate(-0.99262638,-1.174181)"><g id="k8s-cm-g70" transform="matrix(1.0148887,0,0,1.0148887,16.902146,-2.698726)"><path inkscape:export-ydpi="250.55" inkscape:export-xdpi="250.55" inkscape:export-filename="new.png" inkscape:connector-curvature="0" id="k8s-cm-path3055" d="m -6.8492015,4.2724668 a 1.1191255,1.1099671 0 0 0 -0.4288818,0.1085303 l -5.8524037,2.7963394 a 1.1191255,1.1099671 0 0 0 -0.605524,0.7529759 l -1.443828,6.2812846 a 1.1191255,1.1099671 0 0 0 0.151943,0.851028 1.1191255,1.1099671 0 0 0 0.06362,0.08832 l 4.0508,5.036555 a 1.1191255,1.1099671 0 0 0 0.874979,0.417654 l 6.4961011,-0.0015 a 1.1191255,1.1099671 0 0 0 0.8749788,-0.416906 L 1.3818872,15.149453 A 1.1191255,1.1099671 0 0 0 1.5981986,14.210104 L 0.15212657,7.9288154 A 1.1191255,1.1099671 0 0 0 -0.45339794,7.1758396 L -6.3065496,4.3809971 A 1.1191255,1.1099671 0 0 0 -6.8492015,4.2724668 Z" style="fill:#326ce5;fill-opacity:1;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /><path id="k8s-cm-path3054-2-9" d="M -6.8523435,3.8176372 A 1.1814304,1.171762 0 0 0 -7.3044284,3.932904 l -6.1787426,2.9512758 a 1.1814304,1.171762 0 0 0 -0.639206,0.794891 l -1.523915,6.6308282 a 1.1814304,1.171762 0 0 0 0.160175,0.89893 1.1814304,1.171762 0 0 0 0.06736,0.09281 l 4.276094,5.317236 a 1.1814304,1.171762 0 0 0 0.92363,0.440858 l 6.8576188,-0.0015 a 1.1814304,1.171762 0 0 0 0.9236308,-0.44011 l 4.2745966,-5.317985 a 1.1814304,1.171762 0 0 0 0.228288,-0.990993 L 0.53894439,7.6775738 A 1.1814304,1.171762 0 0 0 -0.10026101,6.8834313 L -6.2790037,3.9321555 A 1.1814304,1.171762 0 0 0 -6.8523435,3.8176372 Z m 0.00299,0.4550789 a 1.1191255,1.1099671 0 0 1 0.5426517,0.1085303 l 5.85315169,2.7948425 A 1.1191255,1.1099671 0 0 1 0.15197811,7.9290648 L 1.598051,14.21035 a 1.1191255,1.1099671 0 0 1 -0.2163123,0.939348 l -4.0493032,5.037304 a 1.1191255,1.1099671 0 0 1 -0.8749789,0.416906 l -6.4961006,0.0015 a 1.1191255,1.1099671 0 0 1 -0.874979,-0.417652 l -4.0508,-5.036554 a 1.1191255,1.1099671 0 0 1 -0.06362,-0.08832 1.1191255,1.1099671 0 0 1 -0.151942,-0.851028 l 1.443827,-6.2812853 a 1.1191255,1.1099671 0 0 1 0.605524,-0.7529758 l 5.8524036,-2.7963395 a 1.1191255,1.1099671 0 0 1 0.4288819,-0.1085303 z" style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:Sans;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;marker:none;enable-background:accumulate" inkscape:connector-curvature="0" /></g><g id="k8s-cm-g3349" transform="translate(0.11778981,0.45794291)"><path inkscape:export-ydpi="376.57999" inkscape:export-xdpi="376.57999" style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" inkscape:connector-curvature="0" d="m 8.236948,6.2914262 5.825001,0" id="k8s-cm-path876" /><path inkscape:export-ydpi="376.57999" inkscape:export-xdpi="376.57999" style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" inkscape:connector-curvature="0" d="m 5.723058,6.2914262 1.45834,0" id="k8s-cm-path880" /><a id="k8s-cm-a3346"><path id="k8s-cm-path884" d="m 10.353619,8.4080928 3.70833,0" inkscape:connector-curvature="0" style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" inkscape:export-xdpi="376.57999" inkscape:export-ydpi="376.57999" /></a><path inkscape:export-ydpi="376.57999" inkscape:export-xdpi="376.57999" style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" inkscape:connector-curvature="0" d="m 7.839728,8.4080928 1.4583305,0" id="k8s-cm-path888" /><path inkscape:export-ydpi="376.57999" inkscape:export-xdpi="376.57999" style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" inkscape:connector-curvature="0" d="m 10.353619,10.52476 3.70833,0" id="k8s-cm-path892" /><path inkscape:export-ydpi="376.57999" inkscape:export-xdpi="376.57999" style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" inkscape:connector-curvature="0" d="m 7.839728,10.52476 1.4583305,0" id="k8s-cm-path896" /><path inkscape:export-ydpi="376.57999" inkscape:export-xdpi="376.57999" style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" inkscape:connector-curvature="0" d="m 8.236948,12.641428 5.825001,0" id="k8s-cm-path900" /><path inkscape:export-ydpi="376.57999" inkscape:export-xdpi="376.57999" style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.79374999;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:10;stroke-opacity:1" inkscape:connector-curvature="0" d="m 5.723058,12.641428 1.45834,0" id="k8s-cm-path904" /></g></g></svg>
|