commit d6da14e4bb8a13b64708b5b1338e66ae88257ec5
Author: Didier <didier@faulty.nl>
Date:   Fri Mar 29 16:17:59 2024 +0100

    init: initial site

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..dbe9c82
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.vscode/
\ No newline at end of file
diff --git a/.woodpecker.yml b/.woodpecker.yml
new file mode 100644
index 0000000..a7528a8
--- /dev/null
+++ b/.woodpecker.yml
@@ -0,0 +1,13 @@
+when:
+  - push
+  - tag
+  - manual
+
+steps:
+  publish:
+    image: woodpeckerci/plugin-docker-buildx
+    secrets: [docker_username, docker_password]
+    settings:
+      repo: git.ixvd.net/${CI_REPO_OWNER}/web
+      registry: git.ixvd.net
+      tags: latest
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..cfa8d5f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# Nebulosus website
+
+The site running on [nebulosus.nl](https://nebulosus.nl).
+
+Written in pure HTML, JS & CSS.
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 0000000..70d4a86
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,71 @@
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Nebulosus</title>
+
+    <link rel="stylesheet" href="./res/style.css">
+    <script src="./res/cases.js" defer></script>
+    <script src="./res/anchors.js" defer></script>
+</head>
+
+<body>
+    <header>
+        <div class="logo">
+            <span class="mono">[N]</span>
+        </div>
+    </header>
+    <main>
+        <section id="intro">
+            <h1>Nebulosus</h1>
+        </section>
+        <div class="columns">
+            <div>
+                <section id="offer">
+                    <h2>What do we offer?</h2>
+                    <span>We offer a variety of services:</span>
+                    <ol>
+                        <li><span>Server Hosting</span></li>
+                        <li><span>Website / Application Development</span></li>
+                        <li><span>Technical Support</span></li>
+                    </ol>
+                    <button id="cases-button" hidden>Cases</button>
+                    <div id="cases" hidden></div>
+                </section>
+                <section id="about">
+                    <h2>About Nebulosus</h2>
+                    <p>
+                        Nebulosus is simplicity, redundancy, reliability and friendliness. <br />
+                        Software should be intuitive, aware of it's environment. That's what Nebulosus strives for.
+                        <br />
+                        If you want simple, intuitive and reliable software, you're in the right spot.
+
+
+                    </p>
+                </section>
+            </div>
+            <section id="contact" hidden>
+                <!-- Not done yet :) -->
+                <!-- Technical question? dev (at) faulty (dot) nl -->
+                <h2>Contact</h2>
+                <span>To contact us please use the following form:</span>
+                <form action="/api/form">
+                    <input name="name" type="text" placeholder="Name">
+                    <input name="email" type="text" placeholder="E-Mail">
+                    <textarea name="message" rows="5" placeholder="Your message"></textarea>
+                    <input type="button" value="Submit">
+                </form>
+            </section>
+        </div>
+        <section id="more-info">
+            <h2>More information about Nebulosus</h2>
+            <div class="rows">
+                <span>Chamber of Commerce number: <strong>93409583</strong></span>
+                <span>E-mail: <strong>info@nebulosus.nl</strong></span>
+            </div>
+        </section>
+    </main>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/public/res/anchors.js b/public/res/anchors.js
new file mode 100644
index 0000000..70a25e9
--- /dev/null
+++ b/public/res/anchors.js
@@ -0,0 +1,4 @@
+document.querySelectorAll("h2")
+    .forEach(e => {
+        e.onclick = () => window.location.hash = e.parentElement.id;
+    });
\ No newline at end of file
diff --git a/public/res/cases.js b/public/res/cases.js
new file mode 100644
index 0000000..f4aca47
--- /dev/null
+++ b/public/res/cases.js
@@ -0,0 +1,30 @@
+class Case {
+    constructor (name = "Project", description = "This is a project.", url = undefined) {
+        this.name = name;
+        this.description = description;
+        this.url = url;
+    }
+}
+
+const CASES = [
+];
+
+const casesButton = document.querySelector("button#cases-button");
+const casesDiv = document.querySelector("div#cases");
+if (casesButton && CASES.length > 0) casesButton.hidden = false; 
+
+function showCases() {
+    if (!casesButton) return console.log("k");
+    if (casesDiv.hidden) casesDiv.innerHTML = "";
+    casesDiv.hidden = !casesDiv.hidden;
+
+    let list = document.createElement("ul");
+    CASES.forEach(c => {
+        console.log(c);
+        // a dirty hack :p
+        list.innerHTML += `<li><${c.url ? 'a' : 'span'}><strong>${c.name}<strong> - ${c.description}</${c.url ? 'a' : 'span'}></li>`;
+    });
+    casesDiv.appendChild(list);
+}
+
+casesButton.onclick = showCases;
\ No newline at end of file
diff --git a/public/res/style.css b/public/res/style.css
new file mode 100644
index 0000000..9724b99
--- /dev/null
+++ b/public/res/style.css
@@ -0,0 +1,168 @@
+:root {
+    --fonts: Inter, 'Open Sans', 'Helvetica', 'Roboto', sans-serif;
+    --theme-color: #33e;
+    --theme-color-highlight: #55f;
+    --theme-color-highlight-2: #99f;
+    --theme-color-lowlight: #11b;
+
+    font-family: var(--fonts);
+}
+
+body {
+    display: flex;
+    flex-direction: column;
+    margin: 0;
+    padding: 0;
+}
+
+header {
+    position: sticky;
+    top: 0%;
+    width: 100vw;
+    height: fit-content;
+    background-color: var(--theme-color, gray);
+    color: #fff;
+
+    box-shadow: 0 0 20px var(--theme-color-lowlight);
+}
+
+header div.logo {
+    padding: 1em;
+}
+
+header div.logo span {
+    font-weight: bolder;
+    font-size: 1.5em;
+
+    border: 1px;
+}
+
+main {
+    display: flex;
+    flex-direction: column;
+    gap: 1em;
+    width: 100vw;
+}
+
+main section {
+    margin: 0 2.5em;
+    width: calc(100vw - (2.5em * 2));
+
+    >h2 {
+        text-decoration: underline;
+        text-decoration-color: #aaa;
+    }
+}
+
+section#intro {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+
+    margin: 0;
+    width: 100vw;
+    background-color: var(--theme-color);
+    color: #fff;
+
+    font-size: 2em;
+
+    border-bottom: 3px solid gray;
+}
+
+div section {
+    width: fit-content;
+}
+
+/* --- */
+
+/* for anchors.js */
+h2:hover {
+    cursor: pointer;
+
+    &::before {
+        position: absolute;
+        content: '#';
+        text-decoration: underline;
+        text-decoration-color: var(--theme-color);
+        transform: translateX(-150%);
+    }
+}
+
+/* --- */
+
+pre, 
+code, 
+.mono {
+    font-family: 'Mononoki', 'Droid Sans Mono', monospace;
+}
+
+/* --- */
+
+form {
+    display: flex;
+    flex-direction: column;
+
+    gap: .75em;
+    margin: .5em 0;
+
+    padding: 1rem .5rem;
+    border: 2px solid #e3e3e3;
+    border-radius: 5px;
+}
+
+
+form input,
+form textarea {
+    font-family: var(--fonts);
+
+    width: 100%;
+    padding: .3em .2em;
+
+    outline: none;
+
+    border: 1px solid #e3e3e3;
+    border-radius: 5px;
+
+
+    &:hover {
+        background-color: 1px solid var(--theme-color-highlight);
+    }
+
+    transition: border .2s ease-in-out;
+}
+
+form input[type=button],
+form input[type=submit],
+button {
+    outline: none;
+    padding: .3em .5em;
+    border: 1px solid #e3e3e3;
+    background-color: #eee;
+    border-radius: 5px;
+
+    cursor: pointer;
+
+    &:hover {
+        background-color: var(--theme-color-highlight-2);
+    }
+
+    transition: background-color .2s ease-in-out;
+}
+
+div.columns {
+    display: flex;
+
+    @media (max-width: 600px) {
+        flex-direction: column;
+    }
+}
+
+div.rows {
+    display: flex;
+    flex-direction: column;
+}
+
+.faded {
+    opacity: .2;
+}
\ No newline at end of file