summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md20
-rw-r--r--css/fonts.scss96
-rw-r--r--css/glyph.scss15
-rw-r--r--css/header.scss27
-rw-r--r--css/navBar.scss34
-rw-r--r--css/page.scss15
-rw-r--r--css/sideMenu.scss50
-rw-r--r--html/achernar.html24
-rw-r--r--html/agbsum.html4
-rw-r--r--html/ax.html8
-rw-r--r--html/backspace.html4
-rw-r--r--html/benoit.html10
-rw-r--r--html/bowshock.html4
-rw-r--r--html/bzipper.html4
-rw-r--r--html/deltaWorld.html4
-rw-r--r--html/dux.html46
-rw-r--r--html/eas.html8
-rw-r--r--html/luma.html14
-rw-r--r--html/pollex.html4
-rw-r--r--html/u8c.html4
-rw-r--r--include/header.shtml49
-rw-r--r--js/init.ts118
-rw-r--r--js/main.ts36
-rw-r--r--js/navigation.ts174
-rw-r--r--js/theme.ts70
-rwxr-xr-xmake.sh25
-rw-r--r--svg/achernar-old.svg5
-rw-r--r--svg/benoitBackground.svg16
-rw-r--r--svg/favicon.svg11
-rw-r--r--svg/glyph/deltaWorld.svg4
-rw-r--r--svg/glyph/dux.svg60
-rw-r--r--svg/icon/hamburger.svg (renamed from svg/hamburger.svg)2
-rw-r--r--svg/icon/home.svg12
-rw-r--r--svg/logo/achernar.svg (renamed from svg/achernar.svg)0
-rw-r--r--svg/logo/achernarIcon.svg (renamed from svg/achernarIcon.svg)0
-rw-r--r--svg/logo/achernarVertical.svg (renamed from svg/achernarVertical.svg)0
-rw-r--r--svg/logo/ax.svg12
-rw-r--r--svg/logo/benoit.svg23
-rw-r--r--svg/logo/bowshock.svg6
-rw-r--r--svg/logo/bzipper.svg9
-rw-r--r--svg/logo/deltaWorld.svg9
-rw-r--r--svg/logo/dux.svg74
-rw-r--r--svg/logo/eas.svg16
-rw-r--r--svg/logo/luma.svg20
-rw-r--r--svg/logo/pollex.svg29
-rw-r--r--svg/logo/u8c.svg40
46 files changed, 881 insertions, 334 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 90be126..2ba0a26 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,25 @@
# Changelog
+## 9.0
+
+* Update side menu on touch screens
+* Update vertical styling
+* Round favicon
+* Caption images
+* Update home button
+* Restructure vector graphics
+* Update note styling
+* Elaborate pages
+* Add new project *Dux*
+* Add project logos (to tree)
+* Make links crawlable
+* Specify font display
+* Calculate default theme from time
+* Fix wrong page for *Luma*
+* Refactor scripts
+* Indicate current page
+* Update make script
+
## 8.1
* Add more meta tags
diff --git a/css/fonts.scss b/css/fonts.scss
index 33f1cee..603c9ec 100644
--- a/css/fonts.scss
+++ b/css/fonts.scss
@@ -1,93 +1,109 @@
@font-face {
- font-family: "Fira Mono";
- src: url("/font/FiraMono-Regular.ttf");
+ font-display: fallback;
+ font-family: "Fira Mono";
+ src: url("/font/FiraMono-Regular.ttf");
}
@font-face {
- font-family: "Fira Mono";
- font-weight: bold;
- src: url("/font/FiraMono-Bold.ttf");
+ font-display: fallback;
+ font-family: "Fira Mono";
+ font-weight: bold;
+ src: url("/font/FiraMono-Bold.ttf");
}
@font-face {
- font-family: "Martian Mono";
- src: url("/font/MartianMono-Regular.ttf");
+ font-display: fallback;
+ font-family: "Martian Mono";
+ src: url("/font/MartianMono-Regular.ttf");
}
@font-face {
- font-family: "Martian Mono";
- font-weight: bold;
- src: url("/font/MartianMono-Bold.ttf");
+ font-display: fallback;
+ font-family: "Martian Mono";
+ font-weight: bold;
+ src: url("/font/MartianMono-Bold.ttf");
}
@font-face {
- font-family: "Montserrat";
- src: url("/font/Montserrat-Regular.ttf");
+ font-display: fallback;
+ font-family: "Montserrat";
+ src: url("/font/Montserrat-Regular.ttf");
}
@font-face {
- font-family: "Montserrat";
+ font-display: fallback;
+ font-family: "Montserrat";
font-style: italic;
- src: url("/font/Montserrat-Italic.ttf");
+ src: url("/font/Montserrat-Italic.ttf");
}
@font-face {
- font-family: "Montserrat";
- font-weight: bold;
- src: url("/font/Montserrat-Bold.ttf");
+ font-display: fallback;
+ font-family: "Montserrat";
+ font-weight: bold;
+ src: url("/font/Montserrat-Bold.ttf");
}
@font-face {
- font-family: "Montserrat";
+ font-display: fallback;
+ font-family: "Montserrat";
font-style: italic;
- font-weight: bold;
- src: url("/font/Montserrat-BoldItalic.ttf");
+ font-weight: bold;
+ src: url("/font/Montserrat-BoldItalic.ttf");
}
@font-face {
- font-family: "Playfair Display";
- src: url("/font/PlayfairDisplay-Regular.ttf");
+ font-display: fallback;
+ font-family: "Playfair Display";
+ src: url("/font/PlayfairDisplay-Regular.ttf");
}
@font-face {
- font-family: "Playfair Display";
- font-weight: bold;
- src: url("/font/PlayfairDisplay-Regular.ttf");
+ font-display: fallback;
+ font-family: "Playfair Display";
+ font-weight: bold;
+ src: url("/font/PlayfairDisplay-Regular.ttf");
}
@font-face {
- font-family: "Playfair Display";
+ font-display: fallback;
+ font-family: "Playfair Display";
font-style: italic;
- src: url("/font/PlayfairDisplay-Italic.ttf");
+ src: url("/font/PlayfairDisplay-Italic.ttf");
}
@font-face {
- font-family: "Playfair Display";
+ font-display: fallback;
+ font-family: "Playfair Display";
font-style: italic;
- font-weight: bold;
- src: url("/font/PlayfairDisplay-BoldItalic.ttf");
+ font-weight: bold;
+ src: url("/font/PlayfairDisplay-BoldItalic.ttf");
}
@font-face {
- font-family: "Raleway";
- src: url("/font/Raleway-Regular.ttf");
+ font-display: fallback;
+ font-family: "Raleway";
+ src: url("/font/Raleway-Regular.ttf");
}
@font-face {
- font-family: "Raleway";
- font-weight: bold;
- src: url("/font/Raleway-Bold.ttf");
+ font-display: fallback;
+ font-family: "Raleway";
+ font-weight: bold;
+ src: url("/font/Raleway-Bold.ttf");
}
@font-face {
- font-family: "Raleway";
+ font-display: fallback;
+ font-family: "Raleway";
font-style: italic;
- src: url("/font/Raleway-Italic.ttf");
+ src: url("/font/Raleway-Italic.ttf");
}
@font-face {
- font-family: "Raleway";
+ font-display: fallback;
+ font-family: "Raleway";
font-style: italic;
- font-weight: bold;
- src: url("/font/Raleway-BoldItalic.ttf");
+ font-weight: bold;
+ src: url("/font/Raleway-BoldItalic.ttf");
}
diff --git a/css/glyph.scss b/css/glyph.scss
index 04d6568..f819298 100644
--- a/css/glyph.scss
+++ b/css/glyph.scss
@@ -3,7 +3,10 @@
background-position: center;
background-repeat: no-repeat;
background-size: contain;
- pointer-events: none;
+ left: 50%;
+ position: absolute;
+ top: 50%;
+ transform: translate(-50%, -50%);
width: 50vmin;
body[data-page = "achernar"] & {
@@ -28,9 +31,9 @@
background-image: url("/svg/glyph/ax.svg");
}
- body[data-page = "backspace"] & {
- background-image: url("/svg/glyph/backspace.svg");
- }
+// body[data-page = "backspace"] & {
+// background-image: url("/svg/glyph/backspace.svg");
+// }
body[data-page = "benoit"] & {
background-image: url("/svg/glyph/benoit.svg");
@@ -49,6 +52,10 @@
filter: drop-shadow(0 0 calc(100vmin / 128) var(--textColour));
}
+ body[data-page = "dux"] & {
+ background-image: url("/svg/glyph/dux.svg");
+ }
+
body[data-page = "eas"] & {
background-image: url("/svg/glyph/eas.svg");
}
diff --git a/css/header.scss b/css/header.scss
index 423d0f5..cd9d63b 100644
--- a/css/header.scss
+++ b/css/header.scss
@@ -3,23 +3,20 @@
--hamburgerHeight: 2rem;
- align-items: center;
background-color: var(--backgroundColour);
background-size: cover;
border-bottom-left-radius: 1rem;
border-bottom-right-radius: 1rem;
- display: flex;
- height: calc(100vh + 1rem);
+ height: fit-content;
image-rendering: pixelated;
- justify-content: center;
overflow: hidden;
- padding-bottom: 1rem;
position: relative;
+ user-select: none;
width: 100%;
body[data-page = "achernar"] & {
--backgroundColour: #007B34;
- --textColour: #FFFFFF;
+ --textColour: white;
@media not (prefers-reduced-motion) {
background-image: url("/image/vertex.webp");
@@ -37,8 +34,8 @@
}
body[data-page = "backspace"] & {
- --backgroundColour: #FFFFFF;
- --textColour: #000000;
+ --backgroundColour: #000000;
+ --textColour: #FFFFFF;
}
body[data-page = "benoit"] & {
@@ -63,6 +60,13 @@
--textColour: #FFFFFF;
}
+ body[data-page = "dux"] & {
+ --backgroundColour: #131313;
+ --textColour: #06fbb2;
+
+ background-image: url("/image/duxBackground.webp");
+ }
+
body[data-page = "eas"] & {
--backgroundColour: #01CD93;
--textColour: #00291B;
@@ -87,8 +91,10 @@
--hamburgerHeight: 4rem;
}
- p, a, a:hover {
- color: var(--textColour)
+ p, a {
+ @media not (prefers-reduced-motion) {
+ transition-timing-function: ease-in-out;
+ }
}
a {
@@ -96,7 +102,6 @@
font-weight: bold;
text-decoration: underline;
text-decoration-color: #00000000;
- user-select: none;
@media not (prefers-reduced-motion) {
transition: text-decoration-color 0.125s;
diff --git a/css/navBar.scss b/css/navBar.scss
index 16c003e..737eb18 100644
--- a/css/navBar.scss
+++ b/css/navBar.scss
@@ -6,7 +6,6 @@
padding: 1rem;
position: absolute;
top: 0;
- max-width: $contentWidth;
width: 100%;
body[data-page = "achernar"] & {
@@ -30,14 +29,30 @@
}
a {
+ position: relative;
text-decoration-color: #00000000;
+ &[aria-current = "page"]:not(#home)::after {
+ background-color: var(--textColour);
+ border-radius: $separatorWidth;
+ content: "";
+ display: block;
+ height: $separatorWidth;
+ left: 50%;
+ position: absolute;
+ top: calc(100% + $separatorWidth);
+ transform: translateX(-50%);
+ width: 100%;
+ }
+
@media not (prefers-reduced-motion) {
transition: opacity $slideDuration, text-decoration-color 0.125s;
}
@media (orientation: portrait) or (pointer: coarse) {
- display: none;
+ &:not(#home, #hamburger) {
+ display: none;
+ }
}
&:hover {
@@ -45,18 +60,21 @@
}
}
- #home {
- z-index: 255;
- }
-
- #hamburger {
+ #home, #hamburger {
aspect-ratio: 1;
background-color: var(--textColour);
cursor: pointer;
height: var(--hamburgerHeight);
- mask-image: url("/svg/hamburger.svg");
mask-size: cover;
z-index: 255;
}
+
+ #home {
+ mask-image: url("/svg/home.svg");
+ }
+
+ #hamburger {
+ mask-image: url("/svg/hamburger.svg");
+ }
}
}
diff --git a/css/page.scss b/css/page.scss
index de9edd7..abe49e5 100644
--- a/css/page.scss
+++ b/css/page.scss
@@ -34,15 +34,10 @@
section {
line-height: 2em;
- max-width: calc(36rem - $padding);
+ max-width: calc($contentWidth / 2 - $padding);
+ text-align: justify;
width: 100%;
- &:nth-of-type(odd) {
- p.note {
- text-align: right;
- }
- }
-
&:nth-of-type(even) {
margin-left: auto;
@@ -61,7 +56,11 @@
}
p.note {
- font-weight: bold;
+ background-color: var(--foregroundColour);
+ border-radius: 1rem;
+ font-weight: bold;
+ padding: 1rem;
+ text-align: center;
&::before {
content: "Note:\0020";
diff --git a/css/sideMenu.scss b/css/sideMenu.scss
index 480d35c..59c93a3 100644
--- a/css/sideMenu.scss
+++ b/css/sideMenu.scss
@@ -4,14 +4,14 @@
display: flex;
flex-direction: column;
gap: 1rem;
- height: calc(100% + 1rem);
justify-content: space-between;
left: 100%;
- overflow: hidden;
+ min-height: calc(100vh + 1rem);
padding: 1rem;
padding-bottom: 2rem;
- padding-top: calc(var(--hamburgerHeight) + 2rem);
- position: absolute;
+ padding-top: calc(var(--hamburgerHeight) + 1rem);
+ position: relative;
+ top: 0;
width: 100%;
z-index: 127;
@@ -24,42 +24,52 @@
transition-timing-function: ease-in-out;
}
- @media (pointer: coarse) {
- font-size: 2em;
- overflow: scroll;
- }
-
&.visible {
left: 0;
}
- div.links {
- display: flex;
- gap: 1rem;
- max-width: $contentWidth;
- padding: 1rem;
- width: 100%;
+ section.links {
+ display: flex;
+ gap: 1rem;
+ justify-content: end;
+ max-width: $contentWidth;
+ padding: 1rem;
+ width: 100%;
- @media (pointer: coarse) {
+ @media (orientation: portrait) {
flex-direction: column;
}
section {
display: flex;
flex-direction: column;
- gap: 0.25rem;
+ gap: $separatorWidth;
p {
background-color: var(--textColour);
- border-radius: 0.25rem;
+ border-radius: $separatorWidth;
color: var(--backgroundColour);
font-weight: bold;
- padding: 0.25rem 1rem;
+ padding: $separatorWidth 1rem;
text-align: center;
}
a {
- padding: 0.25rem;
+ padding: 0 calc($separatorWidth * 2);
+ position: relative;
+
+ &[aria-current = "page"]::after {
+ background-color: var(--textColour);
+ border-radius: $separatorWidth;
+ content: "";
+ display: block;
+ height: 100%;
+ position: absolute;
+ right: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ width: $separatorWidth;
+ }
}
}
}
diff --git a/html/achernar.html b/html/achernar.html
index e1399dc..3bee5fd 100644
--- a/html/achernar.html
+++ b/html/achernar.html
@@ -17,7 +17,7 @@
<link href="/css/noScript.css" rel="stylesheet">
</noscript>
- <script src="/js/init.js" type="text/javascript"></script>
+ <script src="/js/main.js" type="text/javascript"></script>
</head>
<body data-page="achernar">
@@ -29,8 +29,8 @@
<section>
<p><em>Achernar</em> is a european indie development studio based in the Capital Region of Denmark. &#127465;&#127472;</p>
<br>
- <p>We aim to develop high-quality video games and software alike, and we believe that all technologies should be for humanity as a whole. We therefore publish all relavent source code for our products.</p>
-
+ <p>We aim to develop high-quality video games and software alike, and we believe that all technologies should be for humanity as a whole. We therefore publish all relevant source code for our products.</p>
+ <br>
<p class="note">See footer for contact information.</p>
</section>
@@ -40,7 +40,11 @@
<p>The goal of <em>Achernar</em> is to promote modern and robust software for everyone. In other words, our vision is to develop a human and clean industry and community for technology.</p>
<br>
<p>We believe in a society free of patents, and as such we release our scientific software in open-source form. For our games, we try to keep the base engine as open as possible whilst still keeping in mind that they yield our main income.</p>
- <br>
+ </section>
+
+ <h1 id="anchor.roadmap">roadmap</h1>
+
+ <section class="fullWidth">
<p>Currently, our roadmap is as follows:</p>
<br>
<ul>
@@ -48,21 +52,23 @@
<p>Complete the webservice before <em>autumn, 2024</em></p>
</li>
<li>
- <p>Release our first game by <em>2024</em>, including basic merchandise in some form</p>
+ <p>Release our first game by <em>2024</em>, as well as company merchandise in some form</p>
</li>
<li>
- <p>Release early-access for Bowshock on Steam by <em>2025</em></p>
+ <p>Release early-access for Bowshock (on Steam) by <em>2025</em></p>
</li>
<li>
<p>Restructure to a normal sole proprietorship</p>
</li>
</ul>
+ <br>
+ <p>This roadmap is, however, subject to change, altough we do strive to live up to it.</p>
</section>
<h1 id="anchor.team">team</h1>
<section>
- <p>As <em>Achernar</em> is currently registered as a <em>PMV</em> (lesser sole proprietorship), <em>Gabriel Bjørnager Jensen</em> is currently our only member.</p>
+ <p>As <em>Achernar</em> is currently registered as a PMV (lesser sole proprietorship), <em>Gabriel Bjørnager Jensen</em> is currently our only member.</p>
</section>
<h1 id="anchor.inception">inception</h1>
@@ -72,7 +78,7 @@
<br>
<p>Our domain &ndash; <code>achernar.dk</code> &ndash; was already registered in the winter of 2021, at that time being used for hosting on-line source code repositories. This was, however, quickly outsourced to <code><a href="https://mandelbrot.dk">mandelbrot.dk</a></code> after I had managed to secure that domain.</p>
<br>
- <p><code>achernar.dk</code> was then, in the mean time, used for hosting a few look-up references. This mostly served as my own notes for school &ndash; mainly mathematics, physics, and chemistry &ndash; but quickly grew unorganised and umaintained, although I did have plans to expand the lexicon.</p>
+ <p><code>achernar.dk</code> was then, in the mean time, used for hosting a few look-up references. This mostly served as my own notes for school &ndash; mainly mathematics, physics, and chemistry &ndash; but quickly grew unorganised and unmaintained, although I did have plans to expand the lexicon.</p>
<br>
<p>The idea of a company had started in the spring of 2020. At that time it would've been named after the binary system <em>Sheliak</em> (Bayer: <code>&beta; Lyr&#230;</code>). But it was this idea that evolved into <em>Achernar</em>.</p>
</section>
@@ -126,6 +132,6 @@
</body>
<script type="text/javascript">
- init();
+ Ach.init();
</script>
</html>
diff --git a/html/agbsum.html b/html/agbsum.html
index 52aa07d..30fd73e 100644
--- a/html/agbsum.html
+++ b/html/agbsum.html
@@ -17,7 +17,7 @@
<link href="/css/noScript.css" rel="stylesheet">
</noscript>
- <script src="/js/init.js" type="text/javascript"></script>
+ <script src="/js/main.js" type="text/javascript"></script>
</head>
<body data-page="agbsum">
@@ -35,6 +35,6 @@
</body>
<script type="text/javascript">
- init();
+ Ach.init();
</script>
</html>
diff --git a/html/ax.html b/html/ax.html
index 267e4d9..5495bc3 100644
--- a/html/ax.html
+++ b/html/ax.html
@@ -17,7 +17,7 @@
<link href="/css/noScript.css" rel="stylesheet">
</noscript>
- <script src="/js/init.js" type="text/javascript"></script>
+ <script src="/js/main.js" type="text/javascript"></script>
</head>
<body data-page="ax">
@@ -30,10 +30,10 @@
<p><em>Advanced X</em> (or just <em>AX</em>) is a C library for developing applications for the <em>AGB</em> line of hardware.</p>
</section>
- <h1 id="anchor.status">docs</h1>
+ <h1 id="anchor.status">status</h1>
<section>
- <p>The development of <em>AX</em> is currently on hold to prioritise <a onclick="loadPage('luma');"><em>Luma</em></a> and <a onclick="loadpage('eas');"><em>eAS</em></a>.</p>
+ <p>The development of <em>AX</em> is currently on hold to prioritise <a href="/html/luma.html"><em>Luma</em></a> and <a href="/html/eas.html"><em>eAS</em></a>.</p>
</section>
<!--#include virtual="/include/footer.shtml"-->
@@ -41,6 +41,6 @@
</body>
<script type="text/javascript">
- init();
+ Ach.init();
</script>
</html>
diff --git a/html/backspace.html b/html/backspace.html
index f80d298..ca033ae 100644
--- a/html/backspace.html
+++ b/html/backspace.html
@@ -17,7 +17,7 @@
<link href="/css/noScript.css" rel="stylesheet">
</noscript>
- <script src="/js/init.js" type="text/javascript"></script>
+ <script src="/js/main.js" type="text/javascript"></script>
</head>
<body data-page="backspace">
@@ -33,6 +33,6 @@
</body>
<script type="text/javascript">
- init();
+ Ach.init();
</script>
</html>
diff --git a/html/benoit.html b/html/benoit.html
index d4938f7..bc0c2d0 100644
--- a/html/benoit.html
+++ b/html/benoit.html
@@ -17,7 +17,7 @@
<link href="/css/noScript.css" rel="stylesheet">
</noscript>
- <script src="/js/init.js" type="text/javascript"></script>
+ <script src="/js/main.js" type="text/javascript"></script>
</head>
<body data-page="benoit">
@@ -29,7 +29,7 @@
<section>
<p><em>Benoit</em> is a Rust-written programme for visualising complex functions, e.g. <em>the Mandelbrot Set</em> and similar fractals.</p>
<br>
- <x-image data-file="benoit_screenshot0"></x-image>
+ <x-image alt="A render of a single Minibrot on a green background. The render is coloures so that it resembles lightning coming from the Minibrot." data-file="benoit_screenshot0"></x-image>
<br>
<p>The project consists of the core <a href="https://crates.io/crates/benoit/"><code>benoit</code></a> crate, from which the frontends <code>benoit-cli</code> and (in the future) <code>benoit-gui</code> derive.</p>
</section>
@@ -39,7 +39,7 @@
<section>
<p>The <code>benoit-cli</code> executable can render and animate using <a href="https://en.wikipedia.org/wiki/TOML/">TOML</a> files right from the commandline.</p>
<br>
- <x-image data-file="benoit_screenshot1"></x-image>
+ <x-image alt="A Julia Set centred on a point inside the Mandelbrot Set. The resulting image resembles creeping, black vines with rainbows around." data-file="benoit_screenshot1"></x-image>
</section>
<h1 id="anchor.benoitGui">benoit-gui</h1>
@@ -47,7 +47,7 @@
<section>
<p>The <code>benoit-gui</code> executable, on the other hand, allows viewing fractals in realtime. Do note, however, that this frontend is currently unimplemented.</p>
<br>
- <x-image data-file="benoit_screenshot2"></x-image>
+ <x-image alt="An render of an inverse Julia Set of the Mandelbrot. It appears on a grey gradiant background with a warm-coloured pattern resembling smaller minibrots." data-file="benoit_screenshot2"></x-image>
</section>
<h1 id="anchor.docs">docs</h1>
@@ -61,6 +61,6 @@
</body>
<script type="text/javascript">
- init();
+ Ach.init();
</script>
</html>
diff --git a/html/bowshock.html b/html/bowshock.html
index b3f2810..f3a117f 100644
--- a/html/bowshock.html
+++ b/html/bowshock.html
@@ -17,7 +17,7 @@
<link href="/css/noScript.css" rel="stylesheet">
</noscript>
- <script src="/js/init.js" type="text/javascript"></script>
+ <script src="/js/main.js" type="text/javascript"></script>
</head>
<body data-page="bowshock">
@@ -33,6 +33,6 @@
</body>
<script type="text/javascript">
- init();
+ Ach.init();
</script>
</html>
diff --git a/html/bzipper.html b/html/bzipper.html
index 729ab4c..1ab5584 100644
--- a/html/bzipper.html
+++ b/html/bzipper.html
@@ -17,7 +17,7 @@
<link href="/css/noScript.css" rel="stylesheet">
</noscript>
- <script src="/js/init.js" type="text/javascript"></script>
+ <script src="/js/main.js" type="text/javascript"></script>
</head>
<body data-page="bzipper">
@@ -43,6 +43,6 @@
</body>
<script type="text/javascript">
- init();
+ Ach.init();
</script>
</html>
diff --git a/html/deltaWorld.html b/html/deltaWorld.html
index 40e3b2c..d1417d9 100644
--- a/html/deltaWorld.html
+++ b/html/deltaWorld.html
@@ -17,7 +17,7 @@
<link href="/css/noScript.css" rel="stylesheet">
</noscript>
- <script src="/js/init.js" type="text/javascript"></script>
+ <script src="/js/main.js" type="text/javascript"></script>
</head>
<body data-page="deltaWorld">
@@ -33,6 +33,6 @@
</body>
<script type="text/javascript">
- init();
+ Ach.init();
</script>
</html>
diff --git a/html/dux.html b/html/dux.html
new file mode 100644
index 0000000..73f0e15
--- /dev/null
+++ b/html/dux.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+ <meta name="author" content="Gabriel Bjørnager Jensen">
+ <meta name="darkreader-lock">
+ <meta name="description" content="About the Dux library.">
+ <meta name="keywords" content="achernar, dux, multimedia, rust, webgpu, widget">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+ <link href="/favicon.ico" rel="icon" type="image/vnd.microsoft.icon">
+ <link href="/apple-touch-icon.png" rel="apple-touch-icon" type="image/png">
+ <title>Dux | Achernar</title>
+
+ <link href="/css/main.css" rel="stylesheet">
+ <noscript>
+ <link href="/css/noScript.css" rel="stylesheet">
+ </noscript>
+
+ <script src="/js/main.js" type="text/javascript"></script>
+ </head>
+
+ <body data-page="dux">
+ <!--#include virtual="/include/header.shtml"-->
+
+ <div id="page">
+ <h1 id="anchor.about">Dux</h1>
+
+ <section>
+ <p><em>Dux</em> is a cross-platform widgeting library for developing GUI applications.</p>
+ </section>
+
+ <h1 id="anchor.status">status</h1>
+
+ <section>
+ <p>The <em>Dux</em> library is currently unmaintained.</p>
+ </section>
+
+ <!--#include virtual="/include/footer.shtml"-->
+ </div>
+ </body>
+
+ <script type="text/javascript">
+ Ach.init();
+ </script>
+</html>
diff --git a/html/eas.html b/html/eas.html
index d9c3304..bb76850 100644
--- a/html/eas.html
+++ b/html/eas.html
@@ -17,7 +17,7 @@
<link href="/css/noScript.css" rel="stylesheet">
</noscript>
- <script src="/js/init.js" type="text/javascript"></script>
+ <script src="/js/main.js" type="text/javascript"></script>
</head>
<body data-page="eas">
@@ -28,18 +28,20 @@
<section>
<p>The <em>Embedded Assembler</em> (or simply <em>eAS</em>) is an assembler for cross-compiling to Arm ISAs.</p>
+ <br>
+ <p>The assembler is intended as a drop-in replacement for the official <em>armasm</em> assembler by Arm Limited. It therefore imitates the same syntax.</p>
</section>
<h1 id="anchor.status">docs</h1>
<section>
- <p>Like <a onclick="loadPage('luma');"><em>Luma</em></a>, the development of <em>eAS</em> is currently on hold in favour of the <a onclick="loadPage('pollex');"><em>Pollex</em></a> library, which will be used as a backend.</p>
+ <p>Like <a href="/html/luma.html"><em>Luma</em></a>, the development of <em>eAS</em> is currently on hold in favour of the <a href="/html/pollex.html"><em>Pollex</em></a> library, which will be used as a backend.</p>
</section>
<!--#include virtual="/include/footer.shtml"-->
</div>
</body>
<script type="text/javascript">
- init();
+ Ach.init();
</script>
</html>
diff --git a/html/luma.html b/html/luma.html
index 27e8232..600ed68 100644
--- a/html/luma.html
+++ b/html/luma.html
@@ -17,25 +17,23 @@
<link href="/css/noScript.css" rel="stylesheet">
</noscript>
- <script src="/js/init.js" type="text/javascript"></script>
+ <script src="/js/main.js" type="text/javascript"></script>
</head>
<body data-page="luma">
<!--#include virtual="/include/header.shtml"-->
<div id="page">
- <h1 id ="anchor.about">kuma</h1>
+ <h1 id ="anchor.about">luma</h1>
<section>
- <p><em>bzipper</em> is a Rust crate for serialisation and deserialisation of binary streams.</p>
- <br>
- <p>See more at <code><a href="https://crates.io/crates/bzipper/">crates.io</a></code>.</p>
+ <p><em>Luma</em> is an emulator for the <em>AGB</em> line of game consoles by Nintendo Co.</p>
</section>
- <h1 id="anchor.docs">docs</h1>
+ <h1 id="anchor.status">status</h1>
<section>
- <p>See <a href="https://docs.rs/pollex/latest/pollex/"><code>docs.rs</code></a> for documentation.</p>
+ <p>The development of <em>Luma</em> is currently on hold in favour of <a href="/html/pollex.html"><em>Pollex</em></a>, which is to be used as a backend.</p>
</section>
<!--#include virtual="/include/footer.shtml"-->
@@ -43,6 +41,6 @@
</body>
<script type="text/javascript">
- init();
+ Ach.init();
</script>
</html>
diff --git a/html/pollex.html b/html/pollex.html
index 1d7af17..25ef4f5 100644
--- a/html/pollex.html
+++ b/html/pollex.html
@@ -17,7 +17,7 @@
<link href="/css/noScript.css" rel="stylesheet">
</noscript>
- <script src="/js/init.js" type="text/javascript"></script>
+ <script src="/js/main.js" type="text/javascript"></script>
</head>
<body data-page="pollex">
@@ -43,6 +43,6 @@
</body>
<script type="text/javascript">
- init();
+ Ach.init();
</script>
</html>
diff --git a/html/u8c.html b/html/u8c.html
index 45ab545..44c8a07 100644
--- a/html/u8c.html
+++ b/html/u8c.html
@@ -17,7 +17,7 @@
<link href="/css/noScript.css" rel="stylesheet">
</noscript>
- <script src="/js/init.js" type="text/javascript"></script>
+ <script src="/js/main.js" type="text/javascript"></script>
</head>
<body data-page="u8c">
@@ -35,6 +35,6 @@
</body>
<script type="text/javascript">
- init();
+ Ach.init();
</script>
</html>
diff --git a/include/header.shtml b/include/header.shtml
index 63cb519..1e0c7d0 100644
--- a/include/header.shtml
+++ b/include/header.shtml
@@ -1,54 +1,59 @@
<header id="header">
<div id="navBar">
<section>
- <a id="home" onclick="loadPage('achernar');">ACHERNAR</a>
+ <a id="home" href="/html/achernar.html"></a>
</section>
<section>
- <a onclick="loadPage('benoit');">BENOIT</a>
- <a onclick="loadPage('bowshock');">BOWSHOCK</a>
- <a onclick="loadPage('deltaWorld');">DELTA&middot;WORLD</a>
+ <a href="/html/benoit.html">BENOIT</a>
+ <a href="/html/bowshock.html">BOWSHOCK</a>
+ <a href="/html/deltaWorld.html">DELTA&middot;WORLD</a>
+ <a href="/html/eas.html">eAS</a>
</section>
<section>
- <div id="hamburger" onclick="toggleSideMenu();"></div>
+ <a id="hamburger" onclick="Ach.toggleSideMenu();"></a>
</section>
</div>
<div id="sideMenu">
- <div class="links">
+ <section class="links">
<section>
<p>ACHERNAR</p>
- <a onclick="loadPage('achernar', 'about');">ABOUT</a>
- <a onclick="loadPage('achernar', 'vision');">VISION</a>
- <a onclick="loadPage('achernar', 'team');">TEAM</a>
+ <a href="/html/achernar.html#about">ABOUT</a>
+ <a href="/html/achernar.html#vision">VISION</a>
+ <a href="/html/achernar.html#roadmap">ROADMAP</a>
+ <a href="/html/achernar.html#team">TEAM</a>
<a href="https://mandelbrot.dk" rel="noopener noreferrer" target="_blank">SOURCES</a>
</section>
<section>
<p>GAMES</p>
- <a onclick="loadPage('bowshock');">BOWSHOCK</a>
- <a onclick="loadPage('deltaWorld');">DELTA&middot;WORLD</a>
+ <a href="/html/bowshock.html">BOWSHOCK</a>
+ <a href="/html/deltaWorld.html">DELTA&middot;WORLD</a>
</section>
<section>
<p>PROJECTS</p>
- <a onclick="loadPage('agbsum');">AGBSUM</a>
- <a onclick="loadPage('ax');">AX</a>
- <a onclick="loadPage('backspace');">BACKSPACE</a>
- <a onclick="loadPage('benoit');">BENOIT</a>
- <a onclick="loadPage('bzipper');">BZIPPER</a>
- <a onclick="loadPage('eas');">eAS</a>
- <a onclick="loadPage('luma');">LUMA</a>
- <a onclick="loadPage('pollex');">POLLEX</a>
- <a onclick="loadPage('u8c');">U8C</a>
+ <a href="/html/agbsum.html">AGBSUM</a>
+ <a href="/html/ax.html">AX</a>
+ <a href="/html/backspace.html">BACKSPACE</a>
+ <a href="/html/benoit.html">BENOIT</a>
+ <a href="/html/bzipper.html">BZIPPER</a>
+ <a href="/html/dux.html">DUX</a>
+ <a href="/html/eas.html">eAS</a>
+ <a href="/html/luma.html">LUMA</a>
+ <a href="/html/pollex.html">POLLEX</a>
+ <a href="/html/u8c.html">U8C</a>
</section>
- </div>
+ </section>
- <a id="themeToggler" onclick="toggleTheme();">TOGGLE THEME</a>
+ <section>
+ <a id="themeToggler" onclick="Ach.toggleTheme();">TOGGLE THEME</a>
+ </section>
</div>
<div id="glyph"></div>
diff --git a/js/init.ts b/js/init.ts
index 020171b..f249902 100644
--- a/js/init.ts
+++ b/js/init.ts
@@ -1,12 +1,114 @@
-/// <reference path="navigation.ts" />
-/// <reference path="theme.ts" />
+namespace Ach {
+ export async function init() {
+ Ach.loadTheme();
-function init() {
- window.addEventListener("popstate", (_e) => {
- location.reload();
- });
+ Ach.initImages();
+ Ach.initLinks();
- loadTheme();
+ window.addEventListener("popstate", (_e) => {
+ location.reload();
+ });
+ }
- initImages();
+ export async function initImages() {
+ let page = Ach.getOnlyElement(document, "page");
+
+ let imageList = Array.from(page.getElementsByTagName("x-image"));
+
+ for (let image of imageList) {
+ let alt = image.getAttribute("alt");
+ let file = image.getAttribute("data-file");
+
+ if (!alt) {
+ alert("stupid superuser forgot to add image caption, please notify");
+ alt = "";
+ }
+
+ if (!file) {
+ throw new Error("file not set for image element");
+ }
+
+ console.log("initialising image that links to \"" + file + "\"");
+
+ let sourceUrl = "/image/source/" + file + ".webp";
+ let thumbnailUrl = "/image/thumbnail/" + file + ".avif";
+
+ let blurElement = document.createElement("img");
+ blurElement.setAttribute("class", "blur");
+ blurElement.setAttribute("src", thumbnailUrl);
+
+ let hyperlinkElement = document.createElement("a");
+ hyperlinkElement.setAttribute("href", sourceUrl);
+ hyperlinkElement.setAttribute("rel", "noopener noreferrer");
+ hyperlinkElement.setAttribute("target", "_blank");
+
+ let image_element = document.createElement("img");
+ image_element.setAttribute("alt", alt);
+ image_element.setAttribute("src", thumbnailUrl);
+
+ hyperlinkElement.appendChild(image_element);
+
+ image.appendChild(blurElement);
+ image.appendChild(hyperlinkElement);
+ }
+ }
+
+ export async function initLinks() {
+ console.log("initialising links");
+
+ let stats = {
+ total: 0x0,
+ overrideCount: 0x0,
+ currentCount: 0x0,
+ };
+
+ for (let link of document.getElementsByTagName("a")) {
+ ++stats.total;
+
+ let address = link.getAttribute("href");
+
+ if (!address) {
+ console.log("note: skipping override of empty link");
+ continue;
+ }
+
+ let pageAnchor = Ach.parseInternalLink(address);
+
+ if (!pageAnchor) {
+ console.log(`note: skipping override of link to "${address}"`);
+ continue;
+ }
+
+ console.log(`note: overriding link to "${address}"`);
+ ++stats.overrideCount;
+
+ let command = `Ach.loadPage(${JSON.stringify(pageAnchor[0x0])}, ${JSON.stringify(pageAnchor[0x1])})`
+
+ link.removeAttribute("href");
+ link.setAttribute("data-page", pageAnchor[0x0]);
+ link.setAttribute("onclick", command);
+
+ if (pageAnchor[0x1]) {
+ link.setAttribute("data-anchor", pageAnchor[0x1]);
+ }
+ }
+
+ let currentPage = Ach.currentPage();
+
+ for (let link of document.getElementsByTagName("a")) {
+ let page = link.getAttribute("data-page");
+ let anchor = link.getAttribute("data-anchor");
+
+ if (page == currentPage && !anchor) {
+ ++stats.currentCount;
+ link.setAttribute("aria-current", "page");
+ } else {
+ link.setAttribute("aria-current", "false");
+ }
+ }
+
+ console.log(`note: initialised (${stats.total}) links`);
+ console.log(`note: of which (${stats.overrideCount}) overrides were done`);
+ console.log(`note: and of which (${stats.currentCount}) were marked as current`);
+ }
}
diff --git a/js/main.ts b/js/main.ts
new file mode 100644
index 0000000..44d28ad
--- /dev/null
+++ b/js/main.ts
@@ -0,0 +1,36 @@
+/// <reference path="init.ts" />
+/// <reference path="navigation.ts" />
+/// <reference path="theme.ts" />
+
+namespace Ach {
+ export function currentPage() {
+ let body = Ach.getFirstElement(document, "body");
+ let page = body.getAttribute("data-page");
+
+ if (!page) {
+ throw new Error("body does not specify page");
+ }
+
+ return page;
+ }
+
+ export function getFirstElement(dom: Document, tag: string): Element {
+ let elements = dom.getElementsByTagName(tag);
+
+ if (elements.length < 0x0) {
+ throw new Error(`unable to find <${tag}> element`);
+ }
+
+ return elements[0x0];
+ }
+
+ export function getOnlyElement(dom: Document, id: string): Element {
+ let element = dom.getElementById(id);
+
+ if (!element) {
+ throw new Error(`unable to find #${id} element`);
+ }
+
+ return element;
+ }
+}
diff --git a/js/navigation.ts b/js/navigation.ts
index 4a83be6..c1af99f 100644
--- a/js/navigation.ts
+++ b/js/navigation.ts
@@ -1,145 +1,97 @@
-async function loadPage(page_name: string, anchor?: string) {
- console.log(`loading page \`${page_name}\``);
+namespace Ach {
+ export async function loadPage(page_name: string, anchor?: string) {
+ console.log(`loading page \`${page_name}\``);
- let url = `/html/${page_name}.html`;
- console.log(`note: page is at "${url}"`);
+ window.scrollTo({
+ top: 0.0,
+ left: undefined,
+ behavior: "smooth",
+ });
- window.history.pushState(page_name, "", url);
+ let url = `/html/${page_name}.html`;
+ console.log(`note: page is at "${url}"`);
- let response = await fetch(url);
+ window.history.pushState(page_name, "", url);
- if (!response.ok) {
- throw new Error(`unable to load page: \"${response.status}\"`);
- }
+ let response = await fetch(url);
- let markup = await response.text();
+ if (!response.ok) {
+ throw new Error(`unable to load page: \"${response.status}\"`);
+ }
- let parser = new DOMParser();
- let dom = parser.parseFromString(markup, "text/html");
+ let markup = await response.text();
- let titles = document.getElementsByTagName("title");
- let bodies = document.getElementsByTagName("body");
- let page = document.getElementById("page")!;
+ let parser = new DOMParser();
+ let dom = parser.parseFromString(markup, "text/html");
- if (titles.length < 0x1) {
- throw new Error("unable to find title");
- }
+ let body = Ach.getFirstElement(document, "body");
- if (bodies.length < 0x1) {
- throw new Error("unable to find body");
- }
+ let title = Ach.getFirstElement(document, "title");
+ let page = Ach.getOnlyElement(document, "page");
- if (!page) {
- throw new Error("unable to find page element");
- }
+ let newTitle = Ach.getFirstElement(dom, "title");
+ let newPage = Ach.getOnlyElement(dom, "page");
- let newTitles = dom.getElementsByTagName("title");
- let newPage = dom.getElementById("page");
+ title.replaceWith(newTitle);
+ body.setAttribute("data-page", page_name);
+ page.replaceWith(newPage);
- if (newTitles.length < 0x1) {
- throw new Error("unable to find new title");
- }
+ initImages();
+ initLinks();
- if (!newPage) {
- throw new Error("unable to find new page element");
- }
+ if (anchor) {
+ console.log(`going to anchor \`${anchor}\``);
- titles[0x0].replaceWith(newTitles[0x0]);
- bodies[0x0].setAttribute("data-page", page_name);
- page.replaceWith(newPage);
+ anchor = `anchor.${anchor}`;
- initImages();
+ console.log(`note: anchor has id "${anchor}"`);
- if (anchor) {
- console.log(`going to anchor \`${anchor}\``);
+ let anchor_element = document.getElementById(anchor);
- anchor = `anchor.${anchor}`;
+ if (!anchor_element) {
+ throw new Error(`unable to find anchor "${anchor}"`);
+ }
- console.log(`note: anchor has id "${anchor}"`);
-
- let anchor_element = document.getElementById(anchor);
-
- if (!anchor_element) {
- throw new Error(`unable to find anchor "${anchor}"`);
+ anchor_element.scrollIntoView({
+ behavior: "smooth",
+ });
}
+ }
- anchor_element.scrollIntoView({
+ export function toggleSideMenu() {
+ window.scrollTo({
+ top: 0.0,
+ left: undefined,
behavior: "smooth",
});
- }
-}
-
-function toggleSideMenu() {
- scrollToTop();
-
- let sideMenu = document.getElementById("sideMenu");
- let navBar = document.getElementById("navBar");
- let glyph = document.getElementById("glyph");
-
- if (!sideMenu) {
- throw new Error("unable to find sideMenu");
- }
-
- if (!navBar) {
- throw new Error("unable to find navigation bar");
- }
-
- if (!glyph) {
- throw new Error("unable to find glyph");
- }
- sideMenu.classList.toggle("visible");
- glyph.classList.toggle("hidden");
+ let sideMenu = Ach.getOnlyElement(document, "sideMenu");
+ let navBar = Ach.getOnlyElement(document, "navBar");
+ let glyph = Ach.getOnlyElement(document, "glyph");
- for (let link of navBar.getElementsByTagName("a")) {
- link.classList.toggle("hidden");
- }
-}
-
-async function scrollToTop() {
- window.scroll({
- top: 0,
- left: 0,
- behavior: "smooth",
- });
-}
+ sideMenu.classList.toggle("visible");
+ glyph.classList.toggle("hidden");
-function initImages() {
- let page = document.getElementById("page");
-
- if (!page) {
- throw new Error("unable to find page");
+ for (let link of navBar.getElementsByTagName("a")) {
+ link.classList.toggle("hidden");
+ }
}
- let imageList = Array.from(page.getElementsByTagName("x-image"));
+ export function parseInternalLink(address: string): [string, string | undefined] | undefined {
+ let regex = /\/html\/([A-Za-z0-9]+)\.html(?:#([A-Za-z0-9]+)){0,1}/;
+ let regex_result = regex.exec(address);
- for (let image of imageList) {
- let file = image.getAttribute("data-file");
-
- if (!file) {
- throw new Error("file not set for image element")
+ if (!regex_result) {
+ return;
}
- console.log("initialising image that links to \"" + file + "\"");
-
- let sourceUrl = "/image/source/" + file + ".webp";
- let thumbnailUrl = "/image/thumbnail/" + file + ".avif";
+ let page = regex_result[0x1];
+ let anchor = regex_result[0x2];
- let blurElement = document.createElement("img");
- blurElement.setAttribute("class", "blur");
- blurElement.setAttribute("src", thumbnailUrl);
-
- let hyperlinkElement = document.createElement("a");
- hyperlinkElement.setAttribute("href", sourceUrl);
- hyperlinkElement.setAttribute("rel", "noopener noreferrer");
- hyperlinkElement.setAttribute("target", "_blank");
-
- let image_element = document.createElement("img");
- image_element.setAttribute("src", thumbnailUrl);
-
- hyperlinkElement.appendChild(image_element);
+ if (!page) {
+ return;
+ }
- image.appendChild(blurElement);
- image.appendChild(hyperlinkElement);
+ return [page, anchor];
}
}
diff --git a/js/theme.ts b/js/theme.ts
index 36959bc..45101da 100644
--- a/js/theme.ts
+++ b/js/theme.ts
@@ -1,51 +1,55 @@
-const DEFAULT_THEME = "dark";
+namespace Ach {
+ export function toggleTheme() {
+ let body = Ach.getFirstElement(document, "body");
-function toggleTheme() {
- let bodies = document.getElementsByTagName("body");
+ let theme = "light";
- if (!bodies) {
- throw new Error("unable to find body");
- }
+ if (body.classList.contains("light")) {
+ theme = "dark";
+ }
- let theme = "light";
+ console.log("setting theme to `" + theme + "`");
- if (bodies[0x0].classList.contains("light")) {
- theme = "dark";
+ body.classList.toggle("light");
+ sessionStorage.setItem("theme", theme);
}
- console.log("setting theme to `" + theme + "`");
+ export function loadTheme() {
+ let theme = sessionStorage.getItem("theme");
- bodies[0x0].classList.toggle("light");
- localStorage.setItem("theme", theme);
-}
+ if (!theme) {
+ console.log("theme not set, using default");
+ theme = defaultTheme();
+ }
-function loadTheme() {
- let theme = localStorage.getItem("theme");
+ switch (theme) {
+ case "dark":
+ // We assume this theme in our stylesheets.
+ break;
- if (!theme) {
- console.log("theme not set, using default");
- theme = DEFAULT_THEME;
- }
+ case "light":
+ let body = Ach.getFirstElement(document, "body");
+ body.classList.add("light");
- switch (theme) {
- case "dark":
- // We assume this theme in our stylesheets.
- break;
+ break;
- case "light":
- let bodies = document.getElementsByTagName("body");
+ default:
+ console.log(`invalid theme \"${theme}\", using default`);
+ //theme = DEFAULT_THEME; // Redundant now.
- if (!bodies) {
- throw new Error("unable to find body");
+ break;
}
- bodies[0x0].classList.add("light");
- break;
+ console.log(`note: theme is now \`${theme}\``);
+ }
- default:
- console.log(`invalid theme \"${theme}\", using default`);
- //theme = DEFAULT_THEME; // Redundant now.
+ function defaultTheme(): string {
+ let hour = new Date().getHours();
- break;
+ if (hour >= 0x6 && hour <= 0x12) {
+ return "light";
+ } else {
+ return "dark";
+ }
}
}
diff --git a/make.sh b/make.sh
index b354f83..f8007f9 100755
--- a/make.sh
+++ b/make.sh
@@ -1,15 +1,18 @@
#!/usr/bin/env sh
-make_icon() {
- render_icon() {
- input="${1}"
- width="${2}"
- output="${3}"
+render_icon() {
+ input="${1}"
+ width="${2}"
+ output="${3}"
+
+ printf "rendering icon at \"%s\" as %ipx by %ipx to \"%s\"\n" "${input}" ${width} ${width} "${output}"
+ inkscape -w ${width} -h ${width} "${input}" -o "${output}"
+}
- printf "rendering icon at \"%s\" as %ipx by %ipx to \"%s\"\n" "${input}" ${width} ${width} "${output}"
- inkscape -w ${width} -h ${width} "${input}" -o "${output}"
- }
+directory="$(mktemp -d)"
+printf "using temporary directory at \"%s\"\n" "${directory}"
+make_favicon() {
input="${1}"
directory="$(mktemp -d)"
@@ -46,9 +49,11 @@ make_script() {
tsc --outFile "${output}" --target ES2022 "${input}"
}
-make_icon "svg/achernarIcon.svg"
+render_icon "svg/logo/achernarIcon.svg" 180 "apple-touch-icon.png"
+
+make_favicon "svg/favicon.svg"
make_stylesheet "main"
make_stylesheet "noScript"
-make_script "init"
+make_script "main"
diff --git a/svg/achernar-old.svg b/svg/achernar-old.svg
deleted file mode 100644
index 2c7d650..0000000
--- a/svg/achernar-old.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg height="60" width="60" xmlns="http://www.w3.org/2000/svg">
- <rect fill="#1B1A1A" height="60" rx="12" width="60" x="0" y="0" />
- <rect fill="#1B1A1A" height="12" width="12" x="0" y="0" />
- <polygon fill="#F6F4F4" points="12,48 30,12 48,48 37.267,48 27.317,28.1 17.367,48" />
-</svg>
diff --git a/svg/benoitBackground.svg b/svg/benoitBackground.svg
index a4d8468..121133c 100644
--- a/svg/benoitBackground.svg
+++ b/svg/benoitBackground.svg
@@ -1,10 +1,10 @@
<svg height="1" width="1" xmlns="http://www.w3.org/2000/svg">
- <polygon fill="#BA0035" points="0,0 1,0 1,1 0,1" /> <!-- oklch(50% 0.199 17.860) "red" -->
- <polygon fill="#CD0325" points="0,0 1,0 1,1 0.198912367,1" />
- <polygon fill="#DC1D02" points="0,0 1,0 1,1 0.414213562,1" />
- <polygon fill="#E04400" points="0,0 1,0 1,1 0.668178638,1" />
- <polygon fill="#E55C04" points="0,0 1,0 1,1 1,1" />
- <polygon fill="#EB6F02" points="0,0 1,0 1,0.668178638" />
- <polygon fill="#F18103" points="0,0 1,0 1,0.414213562" />
- <polygon fill="#F79204" points="0,0 1,0 1,0.198912367" /> <!-- oklch(75% 0.170 63.220) "yellow" -->
+ <polygon fill="oklch(50% 0.199 17.860)" points="0,0 1,0 1,1 0,1" />
+ <polygon fill="oklch(53.571% 0.195 24.340)" points="0,0 1,0 1,1 0.198912367,1" />
+ <polygon fill="oklch(57.143% 0.191 30.820)" points="0,0 1,0 1,1 0.414213562,1" />
+ <polygon fill="oklch(60.714% 0.187 37.300)" points="0,0 1,0 1,1 0.668178638,1" />
+ <polygon fill="oklch(64.286% 0.182 43.780)" points="0,0 1,0 1,1 1,1" />
+ <polygon fill="oklch(67.857% 0.178 50.260)" points="0,0 1,0 1,0.668178638" />
+ <polygon fill="oklch(71.429% 0.174 56.740)" points="0,0 1,0 1,0.414213562" />
+ <polygon fill="oklch(75% 0.170 63.220)" points="0,0 1,0 1,0.198912367" />
</svg>
diff --git a/svg/favicon.svg b/svg/favicon.svg
new file mode 100644
index 0000000..6a9c06d
--- /dev/null
+++ b/svg/favicon.svg
@@ -0,0 +1,11 @@
+<svg height="96" width="96" xmlns="http://www.w3.org/2000/svg">
+ <mask id="letter">
+ <polygon fill="white" points="24,32 72,32 80,40 80,64 64,64 64,56 32,56 32,64 16,64 16,40" />
+ <polygon fill="black" points="32,40 64,40 64,48 32,48" />
+ <circle cx="24" cy="40" fill="white" r="8" />
+ <circle cx="72" cy="40" fill="white" r="8" />
+ </mask>
+
+ <rect fill="#007B34" height="100%" rx="16" width="100%" x="0" y="0" /> <!-- 356 C -->
+ <rect fill="#FFFFFF" mask="url(#letter)" height="100%" width="100%" x="0" y="0" />
+</svg>
diff --git a/svg/glyph/deltaWorld.svg b/svg/glyph/deltaWorld.svg
index cf40682..56c8f92 100644
--- a/svg/glyph/deltaWorld.svg
+++ b/svg/glyph/deltaWorld.svg
@@ -1,7 +1,7 @@
<svg height="96" width="96" xmlns="http://www.w3.org/2000/svg">
<mask id="glyph">
- <polygon fill="white" points="48,0 6.430780618,72 89.569219382,72" />
- <polygon fill="black" points="48,32 34.143593539,56 61.856406461,56" />
+ <polygon fill="white" points="48,12 6.430780618,84 89.569219382,84" />
+ <polygon fill="black" points="48,44 34.143593539,68 61.856406461,68" />
</mask>
<rect fill="#FFFFFF" height="100%" mask="url(#glyph)" width="100%" x="0" y="0" />
diff --git a/svg/glyph/dux.svg b/svg/glyph/dux.svg
new file mode 100644
index 0000000..02f65b1
--- /dev/null
+++ b/svg/glyph/dux.svg
@@ -0,0 +1,60 @@
+<svg height="176" width="176" xmlns="http://www.w3.org/2000/svg">
+ <linearGradient id="foregroundColour" x1="0" x2="1" y1="0" y2="1">
+ <stop offset="0%" stop-color="#05f8d4" />
+ <stop offset="100%" stop-color="#20ff75" />
+ </linearGradient>
+
+ <clipPath id="semicircle-horizontal-high">
+ <rect height="50%" width="100%" x="0" y="0" />
+ </clipPath>
+
+ <clipPath id="semicircle-vertical-left">
+ <rect height="100%" width="50%" x="0" y="0" />
+ </clipPath>
+
+ <clipPath id="semicircle-horizontal-low">
+ <rect height="50%" width="100%" x="0" y="50%" />
+ </clipPath>
+
+ <clipPath id="semicircle-vertical-right">
+ <rect height="100%" width="50%" x="50%" y="0" />
+ </clipPath>
+
+ <mask id="inner">
+ <circle cx="88" cy="88" fill="white" r="72" />
+
+ <circle clip-path="url(#semicircle-vertical-left)" cx="88" cy="130" fill="none" r="42" stroke="black" stroke-width="24" />
+ <circle clip-path="url(#semicircle-vertical-right)" cx="88" cy="46" fill="none" r="42" stroke="black" stroke-width="24" />
+
+ <circle clip-path="url(#semicircle-horizontal-high)" cx="46" cy="88" fill="none" r="42" stroke="black" stroke-width="24" />
+ <circle clip-path="url(#semicircle-horizontal-low)" cx="130" cy="88" fill="none" r="42" stroke="black" stroke-width="24" />
+ </mask>
+
+ <mask id="spiral">
+ <circle cx="88" cy="88" fill="none" r="84" stroke="white" stroke-width="8" />
+
+ <circle clip-path="url(#semicircle-vertical-left)" cx="88" cy="130" fill="none" r="42" stroke="#000" stroke-width="24" />
+ <circle clip-path="url(#semicircle-vertical-right)" cx="88" cy="46" fill="none" r="42" stroke="#000" stroke-width="24" />
+ <circle cx="88" cy="88" fill="#000" r="8" />
+
+ <circle clip-path="url(#semicircle-vertical-left)" cx="88" cy="130" fill="none" r="42" stroke="white" stroke-width="8" />
+ <circle clip-path="url(#semicircle-vertical-right)" cx="88" cy="46" fill="none" r="42" stroke="white" stroke-width="8" />
+ <circle cx="88" cy="88" fill="white" r="4" />
+
+ <circle clip-path="url(#semicircle-horizontal-high)" cx="46" cy="88" fill="none" r="42" stroke="#000" stroke-width="24" />
+ <circle clip-path="url(#semicircle-horizontal-low)" cx="130" cy="88" fill="none" r="42" stroke="#000" stroke-width="24" />
+ <circle cx="88" cy="88" fill="#000" r="8" />
+
+ <circle clip-path="url(#semicircle-horizontal-high)" cx="46" cy="88" fill="none" r="42" stroke="white" stroke-width="8" />
+ <circle clip-path="url(#semicircle-horizontal-low)" cx="130" cy="88" fill="none" r="42" stroke="white" stroke-width="8" />
+ <circle cx="88" cy="88" fill="white" r="4" />
+
+ <circle cx="88" cy="4" fill="white" r="4" />
+ <circle cx="4" cy="88" fill="white" r="4" />
+ <circle cx="88" cy="172" fill="white" r="4" />
+ <circle cx="172" cy="88" fill="white" r="4" />
+ </mask>
+
+ <rect fill="#FFFFFF" height="100%" mask="url(#inner)" width="100%" x="0" y="0" />
+ <rect fill="url(#foregroundColour)" height="100%" mask="url(#spiral)" width="100%" x="0" y="0" />
+</svg>
diff --git a/svg/hamburger.svg b/svg/icon/hamburger.svg
index 6ecae15..fec654b 100644
--- a/svg/hamburger.svg
+++ b/svg/icon/hamburger.svg
@@ -5,5 +5,5 @@
<rect fill="white" height="3" rx="1" width="100%" x="0" y="12" />
</mask>
- <rect fill="#FFFFFF" mask="url(#glyph)" height="100%" width="100%" x="0" y="0" />
+ <rect fill="white" mask="url(#glyph)" height="100%" width="100%" x="0" y="0" />
</svg>
diff --git a/svg/icon/home.svg b/svg/icon/home.svg
new file mode 100644
index 0000000..17bfa19
--- /dev/null
+++ b/svg/icon/home.svg
@@ -0,0 +1,12 @@
+<svg height="96" width="96" xmlns="http://www.w3.org/2000/svg">
+ <mask id="glyph">
+ <rect fill="white" height="100%" rx="16" width="100%" x="0" y="0" />
+
+ <polygon fill="black" points="24,32 72,32 80,40 80,64 64,64 64,56 32,56 32,64 16,64 16,40" />
+ <polygon fill="white" points="32,40 64,40 64,48 32,48" />
+ <circle cx="24" cy="40" fill="black" r="8" />
+ <circle cx="72" cy="40" fill="black" r="8" />
+ </mask>
+
+ <rect fill="black" mask="url(#glyph)" height="100%" width="100%" x="0" y="0" />
+</svg>
diff --git a/svg/achernar.svg b/svg/logo/achernar.svg
index b0ed284..b0ed284 100644
--- a/svg/achernar.svg
+++ b/svg/logo/achernar.svg
diff --git a/svg/achernarIcon.svg b/svg/logo/achernarIcon.svg
index 4a28eef..4a28eef 100644
--- a/svg/achernarIcon.svg
+++ b/svg/logo/achernarIcon.svg
diff --git a/svg/achernarVertical.svg b/svg/logo/achernarVertical.svg
index 78006e8..78006e8 100644
--- a/svg/achernarVertical.svg
+++ b/svg/logo/achernarVertical.svg
diff --git a/svg/logo/ax.svg b/svg/logo/ax.svg
new file mode 100644
index 0000000..cda6147
--- /dev/null
+++ b/svg/logo/ax.svg
@@ -0,0 +1,12 @@
+<svg height="108" width="108" xmlns="http://www.w3.org/2000/svg">
+ <mask id="letters">
+ <polygon fill="white" points="24,36 36,36 48,72 36,72 30,54 24,72 12,72" />
+ <polygon fill="black" points="12,36 30,54 12,54" />
+
+ <polygon fill="white" points="60,36 72,36 78,45 84,36 96,36 84,54 96,72 84,72 78,63 72,72 60,72 72,54" />
+ <polygon fill="black" points="60,36 78,54 60,54" />
+ </mask>
+
+ <rect fill="#422984" height="100%" width="100%" x="0" y="0" />
+ <rect fill="#FFFFFF" height="100%" mask="url(#letters)" width="100%" x="0" y="0" />
+</svg>
diff --git a/svg/logo/benoit.svg b/svg/logo/benoit.svg
new file mode 100644
index 0000000..0eca755
--- /dev/null
+++ b/svg/logo/benoit.svg
@@ -0,0 +1,23 @@
+<svg height="96" width="96" xmlns="http://www.w3.org/2000/svg">
+ <mask id="eye">
+ <ellipse cx="48" cy="48" fill="white" rx="36" ry="24" />
+ <ellipse cx="48" cy="48" fill="black" rx="33" ry="21" />
+
+ <ellipse cx="48" cy="48" fill="white" rx="30" ry="24" />
+ <ellipse cx="48" cy="48" fill="black" rx="27" ry="21" />
+
+ <ellipse cx="48" cy="48" fill="white" rx="24" wry="24" />
+ <ellipse cx="48" cy="48" fill="black" rx="21" ry="21" />
+ </mask>
+
+ <polygon fill="#BA0035" points="0,0 96,0 96,96 0,96" /> <!-- oklch(50% 0.199 17.860) "red" -->
+ <polygon fill="#CD0325" points="0,0 96,0 96,96 19.096,96" />
+ <polygon fill="#DC1D02" points="0,0 96,0 96,96 39.765,96" />
+ <polygon fill="#E04400" points="0,0 96,0 96,96 64.145,96" />
+ <polygon fill="#E55C04" points="0,0 96,0 96,96 96,96" />
+ <polygon fill="#EB6F02" points="0,0 96,0 143.674,96" />
+ <polygon fill="#F18103" points="0,0 96,0 231.766,96" />
+ <polygon fill="#F79204" points="0,0 96,0 482.625,96" /> <!-- oklch(75% 0.170 63.220) "yellow" -->
+
+ <rect fill="#FFFFFF" mask="url(#eye)" height="100%" width="100%" x="0" y="0" />
+</svg>
diff --git a/svg/logo/bowshock.svg b/svg/logo/bowshock.svg
new file mode 100644
index 0000000..787b537
--- /dev/null
+++ b/svg/logo/bowshock.svg
@@ -0,0 +1,6 @@
+<svg height="96" width="96" xmlns="http://www.w3.org/2000/svg">
+ <rect fill="#B61833" height="100%" width="100%" x="0" y="0" />
+
+ <circle cx="48" cy="54" fill="none" r="24" stroke="#FFEEE0" stroke-width="12" />
+ <circle cx="48" cy="42" fill="none" r="24" stroke="#0F0F0F" stroke-width="12" />
+</svg>
diff --git a/svg/logo/bzipper.svg b/svg/logo/bzipper.svg
new file mode 100644
index 0000000..974c50b
--- /dev/null
+++ b/svg/logo/bzipper.svg
@@ -0,0 +1,9 @@
+<svg height="96" width="96" xmlns="http://www.w3.org/2000/svg">
+ <mask id="z">
+ <polyline fill="none" points="20,28 20,20 76,20 36.970562748,76" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" />
+ <polyline fill="none" points="76,68 76,76 20,76 59.029437252,20" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="8" />
+ </mask>
+
+ <rect fill="#FFFFFF" height="100%" width="100%" x="0" y="0" />
+ <rect fill="#B4202D" height="100%" mask="url(#z)" width="100%" x="0" y="0" />
+</svg>
diff --git a/svg/logo/deltaWorld.svg b/svg/logo/deltaWorld.svg
new file mode 100644
index 0000000..3e674bc
--- /dev/null
+++ b/svg/logo/deltaWorld.svg
@@ -0,0 +1,9 @@
+<svg height="160" width="160" xmlns="http://www.w3.org/2000/svg">
+ <mask id="triangle">
+ <polygon fill="white" points="80,44 38.430780618,116 121.569219382,116" />
+ <polygon fill="black" points="80,76 66.143593539,100 93.856406461,100" />
+ </mask>
+
+ <rect fill="#000000" height="100%" width="100%" x="0" y="0" />
+ <rect fill="#FFFFFF" height="100%" mask="url(#triangle)" width="100%" x="0" y="0" />
+</svg>
diff --git a/svg/logo/dux.svg b/svg/logo/dux.svg
new file mode 100644
index 0000000..d8bcf97
--- /dev/null
+++ b/svg/logo/dux.svg
@@ -0,0 +1,74 @@
+<svg height="192" width="192" xmlns="http://www.w3.org/2000/svg">
+ <linearGradient id="backgroundColour" x1="0" x2="1" y1="0" y2="1">
+ <stop offset="0%" stop-color="#222222" />
+ <stop offset="100%" stop-color="#060606" />
+ </linearGradient>
+
+ <linearGradient id="foregroundColour" x1="0" x2="1" y1="0" y2="1">
+ <stop offset="0%" stop-color="#05f8d4" />
+ <stop offset="100%" stop-color="#20ff75" />
+ </linearGradient>
+
+ <clipPath id="semicircle-horizontal-high">
+ <rect height="50%" width="100%" x="0" y="0" />
+ </clipPath>
+
+ <clipPath id="semicircle-vertical-left">
+ <rect height="100%" width="50%" x="0" y="0" />
+ </clipPath>
+
+ <clipPath id="semicircle-horizontal-low">
+ <rect height="50%" width="100%" x="0" y="50%" />
+ </clipPath>
+
+ <clipPath id="semicircle-vertical-right">
+ <rect height="100%" width="50%" x="50%" y="0" />
+ </clipPath>
+
+ <mask id="inner">
+ <circle cx="96" cy="96" fill="white" r="72" />
+
+ <!-- vertical spiral arm -->
+ <circle clip-path="url(#semicircle-vertical-left)" cx="96" cy="138" fill="none" r="42" stroke="black" stroke-width="24" />
+ <circle clip-path="url(#semicircle-vertical-right)" cx="96" cy="54" fill="none" r="42" stroke="black" stroke-width="24" />
+
+ <!-- horizontal spiral arm -->
+ <circle clip-path="url(#semicircle-horizontal-high)" cx="54" cy="96" fill="none" r="42" stroke="black" stroke-width="24" />
+ <circle clip-path="url(#semicircle-horizontal-low)" cx="138" cy="96" fill="none" r="42" stroke="black" stroke-width="24" />
+ </mask>
+
+ <mask id="spiral">
+ <!-- outer ring -->
+ <circle cx="96" cy="96" fill="none" r="84" stroke="white" stroke-width="8" />
+
+ <!-- vertical spiral arm border -->
+ <circle clip-path="url(#semicircle-vertical-left)" cx="96" cy="138" fill="none" r="42" stroke="#000" stroke-width="24" />
+ <circle clip-path="url(#semicircle-vertical-right)" cx="96" cy="54" fill="none" r="42" stroke="#000" stroke-width="24" />
+ <circle cx="96" cy="96" fill="#000" r="8" />
+
+ <!-- vertical spiral arm -->
+ <circle clip-path="url(#semicircle-vertical-left)" cx="96" cy="138" fill="none" r="42" stroke="white" stroke-width="8" />
+ <circle clip-path="url(#semicircle-vertical-right)" cx="96" cy="54" fill="none" r="42" stroke="white" stroke-width="8" />
+ <circle cx="96" cy="96" fill="white" r="4" />
+
+ <!-- horizontal spiral arm border -->
+ <circle clip-path="url(#semicircle-horizontal-high)" cx="54" cy="96" fill="none" r="42" stroke="#000" stroke-width="24" />
+ <circle clip-path="url(#semicircle-horizontal-low)" cx="138" cy="96" fill="none" r="42" stroke="#000" stroke-width="24" />
+ <circle cx="96" cy="96" fill="#000" r="8" />
+
+ <!-- horizontal spiral arm -->
+ <circle clip-path="url(#semicircle-horizontal-high)" cx="54" cy="96" fill="none" r="42" stroke="white" stroke-width="8" />
+ <circle clip-path="url(#semicircle-horizontal-low)" cx="138" cy="96" fill="none" r="42" stroke="white" stroke-width="8" />
+ <circle cx="96" cy="96" fill="white" r="4" />
+
+ <!-- joints -->
+ <circle cx="96" cy="12" fill="white" r="4" />
+ <circle cx="12" cy="96" fill="white" r="4" />
+ <circle cx="96" cy="180" fill="white" r="4" />
+ <circle cx="180" cy="96" fill="white" r="4" />
+ </mask>
+
+ <rect fill="url(#backgroundColour)" height="100%" width="100%" x="0" y="0" />
+ <rect fill="#FFFFFF" height="100%" mask="url(#inner)" width="100%" x="0" y="0" />
+ <rect fill="url(#foregroundColour)" height="100%" mask="url(#spiral)" width="100%" x="0" y="0" />
+</svg>
diff --git a/svg/logo/eas.svg b/svg/logo/eas.svg
new file mode 100644
index 0000000..1778c5b
--- /dev/null
+++ b/svg/logo/eas.svg
@@ -0,0 +1,16 @@
+<svg height="96" width="96" xmlns="http://www.w3.org/2000/svg">
+ <mask id="strike">
+ <circle cx="48" cy="48" fill="white" r="30" />
+ <polygon fill="black" points="84,12 84,84 12,84" />
+ </mask>
+
+ <mask id="e">
+ <circle cx="48" cy="48" fill="white" r="36" />
+ <circle cx="48" cy="48" fill="black" r="24" />
+ <polygon fill="black" points="84,12 84,48 48,48" />
+ <polyline mask="url(#strike)" points="84,12 12,84" stroke="white" stroke-width="24" />
+ </mask>
+
+ <rect fill="#01CD93" height="100%" width="100%" x="0" y="0" />
+ <rect fill="#00291B" height="100%" mask="url(#e)" width="100%" x="0" y="0" />
+</svg>
diff --git a/svg/logo/luma.svg b/svg/logo/luma.svg
new file mode 100644
index 0000000..c1108e1
--- /dev/null
+++ b/svg/logo/luma.svg
@@ -0,0 +1,20 @@
+<svg height="144" width="144" xmlns="http://www.w3.org/2000/svg">
+ <mask id="wordmark">
+ <polygon points="16,16 32,16 32,48 64,48 64,64 24,64 16,56" fill="white" />
+ <circle cx="24" cy="56" fill="white" r="8" />
+
+ <polygon points="80,16 96,16 96,48 112,48 112,16 128,16 128,56 120,64 88,64 80,56" fill="white" />
+ <circle cx="88" cy="56" fill="white" r="8" />
+ <circle cx="120" cy="56" fill="white" r="8" />
+
+ <polygon points="16,80 64,80 16,128" fill="white" />
+ <polygon points="40,104 64,104 64,128" fill="white" />
+
+ <polygon points="88,80 120,80 128,88 128,128 112,128 112,96 96,96 96,128 80,128 80,88" fill="white" />
+ <circle cx="88" cy="88" fill="white" r="8" />
+ <circle cx="120" cy="88" fill="white" r="8" />
+ </mask>
+
+ <rect fill="#6051B2" height="100%" width="100%" x="0" y="0" />
+ <rect fill="#FFFFFF" height="100%" mask="url(#wordmark)" width="100%" x="0" y="0" />
+</svg>
diff --git a/svg/logo/pollex.svg b/svg/logo/pollex.svg
new file mode 100644
index 0000000..211247a
--- /dev/null
+++ b/svg/logo/pollex.svg
@@ -0,0 +1,29 @@
+<svg height="112" width="256" xmlns="http://www.w3.org/2000/svg">
+ <mask id="wordmark">
+ <polygon fill="white" points="16,16 68,16 68,40 32,40 32,48 16,48" />
+ <circle cx="68" cy="28" fill="white" r="12" />
+
+ <polygon fill="black" points="32,24 60,24 60,32 32,32" />
+ <circle cx="60" cy="28" fill="black" r="4" />
+
+ <polygon fill="white" points="104,16 152,16 160,24 160,40 152,48 104,48 96,40 96,24" />
+ <circle cx="104" cy="24" fill="white" r="8" />
+ <circle cx="152" cy="24" fill="white" r="8" />
+ <circle cx="152" cy="40" fill="white" r="8" />
+ <circle cx="104" cy="40" fill="white" r="8" />
+
+ <polygon fill="black" points="112,24 144,24 144,40 112,40" />
+
+ <polygon fill="white" points="176,16 192,16 192,40 240,40 240,48 176,48" />
+
+ <polygon fill="white" points="16,64 32,64 32,88 80,88 80,96 16,96" />
+
+ <polygon fill="white" points="96,64 160,64 160,72 112,72 112,76 144,76 144,84 112,84 112,88 160,88 160,96 96,96" />
+
+ <polygon fill="white" points="176,64 192,64 240,96 224,96" />
+ <polygon fill="white" points="224,64 240,64 192,96 176,96" />
+ </mask>
+
+ <rect fill="#4D4084" height="100%" width="100%" x="0" y="0" /> <!-- 7672 C -->
+ <rect fill="#FFFFFF" height="100%" mask="url(#wordmark)" width="100%" x="0" y="0" />
+</svg>
diff --git a/svg/logo/u8c.svg b/svg/logo/u8c.svg
new file mode 100644
index 0000000..00f8e3d
--- /dev/null
+++ b/svg/logo/u8c.svg
@@ -0,0 +1,40 @@
+<svg height="96" width="96" xmlns="http://www.w3.org/2000/svg">
+ <clipPath id="clip0">
+ <rect height="100%" width="50%" x="0" y="0" />
+ </clipPath>
+
+ <clipPath id="clip1">
+ <rect height="100%" width="50%" x="50%" y="0" />
+ </clipPath>
+
+ <mask id="inner">
+ <circle cx="48" cy="48" fill="white" r="42" />
+
+ <circle cx="48" cy="48" fill="none" r="42" stroke="black" stroke-width="12" />
+
+ <circle cx="48" cy="29" fill="none" r="23" stroke="black" stroke-width="12" />
+ <circle cx="48" cy="67" fill="none" r="23" stroke="black" stroke-width="12" />
+ </mask>
+
+ <mask id="rings">
+ <circle clip-path="url(#clip0)" cx="48" cy="67" fill="none" r="23" stroke="white" stroke-width="4" />
+
+ <circle clip-path="url(#clip0)" cx="48" cy="29" fill="none" r="23" stroke="black" stroke-width="12" />
+ <circle clip-path="url(#clip0)" cx="48" cy="29" fill="none" r="23" stroke="white" stroke-width="4" />
+
+ <circle clip-path="url(#clip1)" cx="48" cy="29" fill="none" r="23" stroke="white" stroke-width="4" />
+
+ <circle clip-path="url(#clip1)" cx="48" cy="67" fill="none" r="23" stroke="black" stroke-width="12" />
+ <circle clip-path="url(#clip1)" cx="48" cy="67" fill="none" r="23" stroke="white" stroke-width="4" />
+
+ <circle cx="48" cy="48" fill="none" r="42" stroke="white" stroke-width="4" />
+
+ <!-- joints -->
+ <circle cx="48" cy="44" fill="white" r="2" />
+ <circle cx="48" cy="52" fill="white" r="2" />
+ </mask>
+
+ <rect fill="#444747" height="100%" width="100%" x="0" y="0" />
+ <rect fill="#FFFFFF" height="100%" mask="url(#inner)" width="100%" x="0" y="0" />
+ <rect fill="#A9E13D" height="100%" mask="url(#rings)" width="100%" x="0" y="0" />
+</svg>