new main page
@@ -0,0 +1 @@
|
||||
.env
|
||||
@@ -0,0 +1,2 @@
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
@@ -25,13 +27,19 @@ func loadConfig() (*Config, error) {
|
||||
// ---------- Main ----------
|
||||
|
||||
func main() {
|
||||
|
||||
err := godotenv.Load()
|
||||
if err != nil {
|
||||
log.Fatal("Error loading .env file")
|
||||
}
|
||||
|
||||
port := flag.String("port", "8081", "port to listen on")
|
||||
flag.Parse()
|
||||
|
||||
fs := http.FileServer(http.Dir("static"))
|
||||
http.Handle("/static/", http.StripPrefix("/static/", fs))
|
||||
|
||||
http.HandleFunc("GET /{$}", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/about.html") })
|
||||
http.HandleFunc("GET /{$}", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/index.html") })
|
||||
http.HandleFunc("GET /infra", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/infra.html") })
|
||||
http.HandleFunc("GET /finance", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/finance.html") })
|
||||
http.HandleFunc("GET /cinema", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/cinema.html") })
|
||||
@@ -39,6 +47,22 @@ func main() {
|
||||
http.HandleFunc("GET /42", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/42.html") })
|
||||
http.HandleFunc("GET /secret", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/secret.html") })
|
||||
http.HandleFunc("GET /favicon.ico", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/icon.png") })
|
||||
http.HandleFunc("GET /login", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "./static/login.html") })
|
||||
|
||||
http.HandleFunc("POST /login", func(w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm()
|
||||
|
||||
password := r.FormValue("password")
|
||||
totp := r.FormValue("totp")
|
||||
|
||||
if os.Getenv("password") == password && os.Getenv("auth") == totp {
|
||||
fmt.Fprintf(w, "logged in")
|
||||
http.Redirect(w, r, "/admin", http.StatusAccepted)
|
||||
} else {
|
||||
w.WriteHeader(http.StatusAccepted)
|
||||
fmt.Fprintf(w, "password or auth is wrong")
|
||||
}
|
||||
})
|
||||
|
||||
http.HandleFunc("GET /status", func(w http.ResponseWriter, r *http.Request) {
|
||||
config, err := loadConfig()
|
||||
|
||||
@@ -42,32 +42,12 @@
|
||||
|
||||
|
||||
|
||||
function unhide42() {
|
||||
const alicegameSection = document.getElementById('alice');
|
||||
const tetrisSection = document.getElementById('tetris');
|
||||
const experiencesection = document.getElementById('experience');
|
||||
|
||||
const educationsection = document.getElementById('education');
|
||||
const automationsection = document.getElementById('automation');
|
||||
const interestssection = document.getElementById('interests');
|
||||
const opinionsection = document.getElementById('opinion');
|
||||
const interestlistsection = document.getElementById('interestlist');
|
||||
|
||||
const hiddenssection = document.getElementById('secret');
|
||||
|
||||
if (hiddenssection.style.display == 'none') {
|
||||
hiddenssection.style.display = 'block';
|
||||
} else {
|
||||
hiddenssection.style.display = 'none';
|
||||
}
|
||||
alicegameSection.style.display = 'none';
|
||||
tetrisSection.style.display = 'none';
|
||||
experiencesection.style.display = 'none';
|
||||
educationsection.style.display = 'none';
|
||||
automationsection.style.display = 'none';
|
||||
interestssection.style.display = 'none';
|
||||
|
||||
opinionsection.style.display = 'none';
|
||||
interestlistsection.style.display = 'none';
|
||||
// about.js
|
||||
function closeOverlay() {
|
||||
document.getElementById('overlay').style.display = 'none';
|
||||
}
|
||||
|
||||
// or toggle it from anywhere:
|
||||
function openOverlay() {
|
||||
document.getElementById('overlay').style.display = 'flex';
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
|
||||
<!-- row ~5% -->
|
||||
<div class="absolute" style="left:5%;top:3%;"><p class="text-red-500 rotate-12">49,020.00</p></div>
|
||||
<div class="absolute" style="left:38%;top:6%;"><img src="/static/images/mac.png" width="50px" class="rotate-6"></div>
|
||||
<div class="absolute" style="left:55%;top:4%;"><img src="/static/images/coffe.png" width="50px" class="rotate-45"></div>
|
||||
<div class="absolute" style="left:72%;top:7%;"><img src="/static/images/book.png" width="50px" class="-rotate-12"></div>
|
||||
<div class="absolute" style="left:88%;top:8%;"><img src="/static/images/keyboard.png" width="50px" class="rotate-20"></div>
|
||||
<div class="absolute" style="left:88%;top:3%;"><img src="/static/images/books.png" width="50px" class="rotate-20"></div>
|
||||
<div class="absolute" style="left:92%;top:3%;"><img src="/static/images/calc.png" width="50px" class="rotate-20"></div>
|
||||
<div class="absolute" style="left:65%;top:2%;"><p class="text-green-600 -rotate-6">1,204.50</p></div>
|
||||
<div class="absolute" style="left:20%;top:1%;"><img src="/static/images/keyboard.png" width="50px" class="-rotate-12"></div>
|
||||
<div class="absolute" style="left:45%;top:0%;"><img src="/static/images/calc.png" width="50px" class="rotate-30"></div>
|
||||
<div class="absolute" style="left:30%;top:5%;"><p class="text-red-500 rotate-8">-750.00</p></div>
|
||||
|
||||
<!-- row ~11% -->
|
||||
<div class="absolute" style="left:2%;top:11%;"><img src="/static/images/book.png" width="50px" class="rotate-25"></div>
|
||||
<div class="absolute" style="left:25%;top:10%;"><img src="/static/images/calc.png" width="50px" class="-rotate-15"></div>
|
||||
<div class="absolute" style="left:42%;top:12%;"><img src="/static/images/keyboard.png" width="50px" class="rotate-10"></div>
|
||||
<div class="absolute" style="left:60%;top:11%;"><img src="/static/images/mac.png" width="50px" class="-rotate-30"></div>
|
||||
<div class="absolute" style="left:78%;top:10%;"><p class="text-green-500 rotate-5">3,180.00</p></div>
|
||||
<div class="absolute" style="left:93%;top:12%;"><img src="/static/images/coffe.png" width="50px" class="rotate-15"></div>
|
||||
|
||||
<!-- row ~18% -->
|
||||
<div class="absolute" style="left:3%;top:18%;"><img src="/static/images/coffe.png" width="50px" class="rotate-78"></div>
|
||||
<div class="absolute" style="left:15%;top:20%;"><img src="/static/images/mac.png" width="50px" class="-rotate-6"></div>
|
||||
<div class="absolute" style="left:47%;top:19%;"><img src="/static/images/books.png" width="50px" class="-rotate-20"></div>
|
||||
<div class="absolute" style="left:78%;top:21%;"><img src="/static/images/coffe.png" width="50px" class="-rotate-35"></div>
|
||||
<div class="absolute" style="left:92%;top:18%;"><img src="/static/images/mac.png" width="50px" class="rotate-90"></div>
|
||||
<div class="absolute" style="left:10%;top:12%;"><p class="text-green-500 rotate-6">8,300.00</p></div>
|
||||
<div class="absolute" style="left:30%;top:17%;"><img src="/static/images/keyboard.png" width="50px" class="rotate-20"></div>
|
||||
<div class="absolute" style="left:62%;top:18%;"><img src="/static/images/calc.png" width="50px" class="-rotate-10"></div>
|
||||
<div class="absolute" style="left:55%;top:22%;"><p class="text-red-500 -rotate-12">-5,900.00</p></div>
|
||||
|
||||
<!-- row ~25% -->
|
||||
<div class="absolute" style="left:8%;top:25%;"><img src="/static/images/calc.png" width="50px" class="-rotate-20"></div>
|
||||
<div class="absolute" style="left:20%;top:26%;"><p class="text-green-600 rotate-10">14,750.00</p></div>
|
||||
<div class="absolute" style="left:38%;top:24%;"><img src="/static/images/keyboard.png" width="50px" class="rotate-15"></div>
|
||||
<div class="absolute" style="left:55%;top:27%;"><img src="/static/images/book.png" width="50px" class="-rotate-25"></div>
|
||||
<div class="absolute" style="left:72%;top:25%;"><img src="/static/images/coffe.png" width="50px" class="rotate-40"></div>
|
||||
<div class="absolute" style="left:87%;top:26%;"><p class="text-red-500 rotate-18">-320.00</p></div>
|
||||
|
||||
<!-- row ~32% -->
|
||||
<div class="absolute" style="left:8%;top:32%;"><img src="/static/images/book.png" width="50px" class="rotate-20"></div>
|
||||
<div class="absolute" style="left:22%;top:34%;"><img src="/static/images/coffe.png" width="50px" class="-rotate-12"></div>
|
||||
<div class="absolute" style="left:37%;top:31%;"><img src="/static/images/mac.png" width="50px" class="rotate-35"></div>
|
||||
<div class="absolute" style="left:67%;top:30%;"><img src="/static/images/books.png" width="50px" class="rotate-6"></div>
|
||||
<div class="absolute" style="left:22%;top:34%;"><p class="text-red-500 -rotate-6">-412.80</p></div>
|
||||
<div class="absolute" style="left:52%;top:33%;"><p class="text-green-600 rotate-15">88,500.00</p></div>
|
||||
<div class="absolute" style="left:83%;top:32%;"><p class="text-red-500 -rotate-20">-2,047.00</p></div>
|
||||
<div class="absolute" style="left:45%;top:36%;"><img src="/static/images/keyboard.png" width="50px" class="-rotate-30"></div>
|
||||
<div class="absolute" style="left:75%;top:35%;"><img src="/static/images/calc.png" width="50px" class="rotate-12"></div>
|
||||
|
||||
<!-- row ~39% -->
|
||||
<div class="absolute" style="left:2%;top:39%;"><img src="/static/images/keyboard.png" width="50px" class="rotate-18"></div>
|
||||
<div class="absolute" style="left:15%;top:41%;"><p class="text-green-500 -rotate-8">620.00</p></div>
|
||||
<div class="absolute" style="left:30%;top:40%;"><img src="/static/images/mac.png" width="50px" class="rotate-25"></div>
|
||||
<div class="absolute" style="left:57%;top:38%;"><img src="/static/images/coffe.png" width="50px" class="-rotate-20"></div>
|
||||
<div class="absolute" style="left:71%;top:41%;"><img src="/static/images/books.png" width="50px" class="rotate-30"></div>
|
||||
<div class="absolute" style="left:88%;top:40%;"><p class="text-red-500 rotate-6">-11,200.00</p></div>
|
||||
|
||||
<!-- row ~46% -->
|
||||
<div class="absolute" style="left:17%;top:48%;"><img src="/static/images/books.png" width="50px" class="rotate-15"></div>
|
||||
<div class="absolute" style="left:49%;top:47%;"><img src="/static/images/coffe.png" width="50px" class="rotate-35"></div>
|
||||
<div class="absolute" style="left:64%;top:44%;"><img src="/static/images/mac.png" width="50px" class="-rotate-15"></div>
|
||||
<div class="absolute" style="left:80%;top:49%;"><img src="/static/images/book.png" width="50px" class="rotate-45"></div>
|
||||
<div class="absolute" style="left:4%;top:45%;"><img src="/static/images/calc.png" width="50px" class="-rotate-25"></div>
|
||||
<div class="absolute" style="left:33%;top:46%;"><p class="text-green-600 rotate-12">2,890.00</p></div>
|
||||
<div class="absolute" style="left:92%;top:47%;"><img src="/static/images/keyboard.png" width="50px" class="rotate-8"></div>
|
||||
|
||||
<!-- row ~53% -->
|
||||
<div class="absolute" style="left:10%;top:53%;"><img src="/static/images/book.png" width="50px" class="rotate-30"></div>
|
||||
<div class="absolute" style="left:26%;top:55%;"><img src="/static/images/calc.png" width="50px" class="-rotate-18"></div>
|
||||
<div class="absolute" style="left:42%;top:52%;"><p class="text-red-500 rotate-20">-8,640.00</p></div>
|
||||
<div class="absolute" style="left:60%;top:54%;"><img src="/static/images/keyboard.png" width="50px" class="rotate-14"></div>
|
||||
<div class="absolute" style="left:76%;top:53%;"><img src="/static/images/books.png" width="50px" class="-rotate-40"></div>
|
||||
<div class="absolute" style="left:91%;top:55%;"><p class="text-green-500 -rotate-10">47,000.00</p></div>
|
||||
|
||||
<!-- row ~60% -->
|
||||
<div class="absolute" style="left:6%;top:60%;"><img src="/static/images/mac.png" width="50px" class="rotate-12"></div>
|
||||
<div class="absolute" style="left:20%;top:62%;"><img src="/static/images/coffe.png" width="50px" class="-rotate-45"></div>
|
||||
<div class="absolute" style="left:36%;top:59%;"><img src="/static/images/books.png" width="50px" class="rotate-20"></div>
|
||||
<div class="absolute" style="left:51%;top:63%;"><img src="/static/images/book.png" width="50px" class="-rotate-12"></div>
|
||||
<div class="absolute" style="left:65%;top:61%;"><img src="/static/images/calc.png" width="50px" class="rotate-35"></div>
|
||||
<div class="absolute" style="left:80%;top:60%;"><p class="text-red-500 rotate-10">-990.00</p></div>
|
||||
<div class="absolute" style="left:93%;top:62%;"><img src="/static/images/keyboard.png" width="50px" class="-rotate-20"></div>
|
||||
|
||||
<!-- row ~67% -->
|
||||
<div class="absolute" style="left:2%;top:67%;"><p class="text-green-600 rotate-15">5,500.00</p></div>
|
||||
<div class="absolute" style="left:18%;top:68%;"><img src="/static/images/keyboard.png" width="50px" class="rotate-22"></div>
|
||||
<div class="absolute" style="left:35%;top:66%;"><img src="/static/images/mac.png" width="50px" class="-rotate-10"></div>
|
||||
<div class="absolute" style="left:52%;top:69%;"><img src="/static/images/coffe.png" width="50px" class="rotate-50"></div>
|
||||
<div class="absolute" style="left:70%;top:67%;"><img src="/static/images/book.png" width="50px" class="-rotate-30"></div>
|
||||
<div class="absolute" style="left:85%;top:68%;"><img src="/static/images/calc.png" width="50px" class="rotate-5"></div>
|
||||
|
||||
<!-- row ~74% -->
|
||||
<div class="absolute" style="left:4%;top:74%;"><img src="/static/images/books.png" width="50px" class="rotate-35"></div>
|
||||
<div class="absolute" style="left:34%;top:73%;"><img src="/static/images/coffe.png" width="50px" class="rotate-15"></div>
|
||||
<div class="absolute" style="left:50%;top:77%;"><img src="/static/images/mac.png" width="50px" class="-rotate-35"></div>
|
||||
<div class="absolute" style="left:66%;top:75%;"><img src="/static/images/book.png" width="50px" class="rotate-45"></div>
|
||||
<div class="absolute" style="left:95%;top:76%;"><img src="/static/images/coffe.png" width="50px" class="rotate-20"></div>
|
||||
<div class="absolute" style="left:90%;top:75%;"><img src="/static/images/calc.png" width="50px" class="rotate-30"></div>
|
||||
<div class="absolute" style="left:18%;top:75%;"><img src="/static/images/keyboard.png" width="50px" class="-rotate-15"></div>
|
||||
<div class="absolute" style="left:40%;top:72%;"><p class="text-green-500 rotate-8">19,300.00</p></div>
|
||||
<div class="absolute" style="left:78%;top:73%;"><p class="text-red-500 -rotate-12">-3,750.00</p></div>
|
||||
|
||||
<!-- row ~81% -->
|
||||
<div class="absolute" style="left:8%;top:81%;"><img src="/static/images/calc.png" width="50px" class="rotate-20"></div>
|
||||
<div class="absolute" style="left:22%;top:83%;"><img src="/static/images/book.png" width="50px" class="-rotate-35"></div>
|
||||
<div class="absolute" style="left:40%;top:82%;"><p class="text-red-500 rotate-16">-60.50</p></div>
|
||||
<div class="absolute" style="left:55%;top:80%;"><img src="/static/images/keyboard.png" width="50px" class="rotate-28"></div>
|
||||
<div class="absolute" style="left:70%;top:83%;"><img src="/static/images/mac.png" width="50px" class="-rotate-8"></div>
|
||||
<div class="absolute" style="left:85%;top:81%;"><img src="/static/images/books.png" width="50px" class="rotate-42"></div>
|
||||
|
||||
<!-- row ~88% -->
|
||||
<div class="absolute" style="left:25%;top:90%;"><img src="/static/images/mac.png" width="50px" class="rotate-45"></div>
|
||||
<div class="absolute" style="left:58%;top:91%;"><img src="/static/images/books.png" width="50px" class="rotate-12"></div>
|
||||
<div class="absolute" style="left:74%;top:89%;"><img src="/static/images/coffe.png" width="50px" class="-rotate-45"></div>
|
||||
<div class="absolute" style="left:90%;top:88%;"><img src="/static/images/book.png" width="50px" class="rotate-30"></div>
|
||||
<div class="absolute" style="left:90%;top:88%;"><img src="/static/images/calc.png" width="50px" class="rotate-30"></div>
|
||||
<div class="absolute" style="left:5%;top:89%;"><img src="/static/images/keyboard.png" width="50px" class="-rotate-22"></div>
|
||||
<div class="absolute" style="left:42%;top:92%;"><p class="text-green-600 rotate-6">7,840.00</p></div>
|
||||
<div class="absolute" style="left:13%;top:91%;"><img src="/static/images/calc.png" width="50px" class="rotate-18"></div>
|
||||
|
||||
<!-- row ~95% -->
|
||||
<div class="absolute" style="left:10%;top:96%;"><img src="/static/images/coffe.png" width="50px" class="rotate-30"></div>
|
||||
<div class="absolute" style="left:30%;top:97%;"><img src="/static/images/book.png" width="50px" class="-rotate-20"></div>
|
||||
<div class="absolute" style="left:50%;top:95%;"><img src="/static/images/mac.png" width="50px" class="rotate-15"></div>
|
||||
<div class="absolute" style="left:67%;top:98%;"><img src="/static/images/keyboard.png" width="50px" class="-rotate-35"></div>
|
||||
<div class="absolute" style="left:82%;top:96%;"><p class="text-red-500 rotate-22">-1,130.00</p></div>
|
||||
<div class="absolute" style="left:93%;top:95%;"><img src="/static/images/books.png" width="50px" class="rotate-10"></div>
|
||||
@@ -0,0 +1,26 @@
|
||||
<div class="flex justify-center flex-wrap gap-6 p-5">
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<img src="/static/gamesbanners/minecraft.webp" class="w-42 h-20 object-cover rounded-lg">
|
||||
<p class="text-xs text-center">Minecraft</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<img src="/static/gamesbanners/Tombraider.png" class="w-42 h-20 object-cover rounded-lg">
|
||||
<p class="text-xs text-center">Rise of the Tomb Raider</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<img src="/static/gamesbanners/planetzoo.webp" class="w-42 h-20 object-cover rounded-lg">
|
||||
<p class="text-xs text-center">Planet Zoo</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<img src="/static/gamesbanners/gtav.webp" class="w-42 h-20 object-cover rounded-lg">
|
||||
<p class="text-xs text-center">GTA V</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<img src="/static/gamesbanners/factorio.jpg" class="w-42 h-20 object-cover rounded-lg">
|
||||
<p class="text-xs text-center">Factorio</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center gap-2">
|
||||
<img src="/static/gamesbanners/detroitbecomehuman.jpg" class="w-42 h-20 object-cover rounded-lg">
|
||||
<p class="text-xs text-center">Detroit: Become Human</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="#000000"><path d="M11 8.5L9.8 9L2.35172 12.3856C2.13752 12.4829 2 12.6965 2 12.9318V13.0682C2 13.3035 2.13752 13.5171 2.35172 13.6144L11.1724 17.6238C11.6982 17.8628 12.3018 17.8628 12.8276 17.6238L21.6483 13.6144C21.8625 13.5171 22 13.3035 22 13.0682V12.9318C22 12.6965 21.8625 12.4829 21.6483 12.3856L14.2 9L13 8.5" stroke="#000000" stroke-width="1.5"></path><path d="M22 13V17.112C22 17.3482 21.8615 17.5623 21.6462 17.6592L12.8207 21.6307C12.2988 21.8655 11.7012 21.8655 11.1793 21.6307L2.35378 17.6592C2.13847 17.5623 2 17.3482 2 17.112V13" stroke="#000000" stroke-width="1.5"></path><path d="M12 8C10.3431 8 9 6.65685 9 5C9 3.34315 10.3431 2 12 2C13.6569 2 15 3.34315 15 5C15 6.65685 13.6569 8 12 8Z" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11 8V13C11 13.5523 11.4477 14 12 14V14C12.5523 14 13 13.5523 13 13V8" stroke="#000000" stroke-width="1.5"></path><path d="M16 13H17" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" viewBox="0 0 24 24" stroke-width="1.5" fill="none" xmlns="http://www.w3.org/2000/svg" color="#000000"><path d="M17.5 19.1245C15.9791 20.3003 14.0712 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12C21 17.5 15 17.5 15 14C15 12 15 8 15 8" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 12V10.5C15 9.11929 13.6569 8 12 8C10.3431 8 9 9.11929 9 10.5V12" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 12V13.5C15 14.8807 13.6569 16 12 16C10.3431 16 9 14.8807 9 13.5V12" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
|
||||
|
After Width: | Height: | Size: 780 B |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#000000"><path d="M3 11.5066C3 16.7497 7.25034 21 12.4934 21C16.2209 21 19.4466 18.8518 21 15.7259C12.4934 15.7259 8.27411 11.5066 8.27411 3C5.14821 4.55344 3 7.77915 3 11.5066Z" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
|
||||
|
After Width: | Height: | Size: 438 B |
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg width="24px" height="24px" stroke-width="1.5" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" color="#000000"><path d="M12 18C15.3137 18 18 15.3137 18 12C18 8.68629 15.3137 6 12 6C8.68629 6 6 8.68629 6 12C6 15.3137 8.68629 18 12 18Z" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M22 12L23 12" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 2V1" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 23V22" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M20 20L19 19" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M20 4L19 5" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M4 20L5 19" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M4 4L5 5" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M1 12L2 12" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
@@ -0,0 +1,372 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Home</title>
|
||||
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
|
||||
<link rel="stylesheet" href="/static/tailwind.css" />
|
||||
<head>
|
||||
<body class="m-0 p-0 bg-zinc-50 rubik-400">
|
||||
|
||||
<!-- NAV -->
|
||||
<nav class="fixed inset-x-0 top-0 h-12 z-50 flex items-center px-8 bg-white/95 backdrop-blur-l border-b border-gray-200">
|
||||
<a class="text-blue-400 text-xs" href="#"><span class="text-green-500">></span> samantha_vero_friis</a>
|
||||
<div class="ml-auto">
|
||||
<button onclick="openOverlay()">login</button>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- MAIN with parallax -->
|
||||
<main id="parallax-section" class="relative h-screen overflow-hidden">
|
||||
<div id="parallax-bg"
|
||||
class="absolute inset-x-0 will-change-transform overflow-hidden"
|
||||
style="top:-100%;bottom:-30%;">
|
||||
<div hx-get="/static/components/background.html" hx-trigger="load" hx-swap="outerHTML"></div>
|
||||
|
||||
</div>
|
||||
<!-- scroller: fills the viewport, scrolls inside -->
|
||||
<div id="scroller" class="relative z-10 h-full flex justify-center overflow-y-auto">
|
||||
<div class="text-black bg-white h-fit w-4xl flex font-light">
|
||||
|
||||
<aside id="sidebar" class="w-48 bg-white shrink-0 p-6 sticky top-0 self-start h-screen overflow-y-auto pt-20 hidden lg:block">
|
||||
<div class="mb-6">
|
||||
<p class="text-xs uppercase tracking-widest text-gray-400 mb-2">navigate</p>
|
||||
<div class="flex flex-col gap-1 text-sm">
|
||||
<a href="#about">about</a>
|
||||
<a href="#experience">experience</a>
|
||||
<a href="#education">education</a>
|
||||
<a href="#opinion">opinion</a>
|
||||
<a href="#automation">automation</a>
|
||||
<a href="#interests" onclick="InterestShow()">interests</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-6">
|
||||
<p class="text-xs uppercase tracking-widest text-gray-400 mb-2">skills</p>
|
||||
<div class="flex flex-col gap-1 text-sm">
|
||||
<div>Excel</div>
|
||||
<div>Python</div>
|
||||
<div>SQL</div>
|
||||
<div>Go</div>
|
||||
<div>Git</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-6">
|
||||
<p class="text-xs uppercase tracking-widest text-gray-400 mb-2">location</p>
|
||||
<div class="text-xs text-gray-500 font-mono">Denmark<br>Aalborg Øst, 9220</div>
|
||||
</div>
|
||||
<div class="mb-6">
|
||||
<p class="text-xs uppercase tracking-widest text-gray-400 mb-2">languages</p>
|
||||
<div class="flex gap-2 text-xs">
|
||||
<span class="border px-2 py-0.5">Danish</span>
|
||||
<span class="border px-2 py-0.5">English</span>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<div class="bg-zinc-50 pt-20 " id="resume" >
|
||||
<section class="flex-1 pl-10 pr-6 ">
|
||||
<div id="about" class="mb-12">
|
||||
<p class="text-xs uppercase tracking-widest text-gray-400 mb-2">About Me · 2026</p>
|
||||
<h1 class="text-5xl font-light mb-4 libre-caslon-text-regular">Samantha<br><span class="text-blue-400 libre-caslon-text-regular ">Vero Friis</span></h1>
|
||||
<p class="text-base text-gray-600 leading-relaxed max-w-prose">Bachelor's student in Business Administration seeking an entry-level analyst or
|
||||
finance-related role while studying. Strong numerical skills, advanced Excel, and experience in company, risk,
|
||||
and financial analysis. Analytical, detail-oriented, and efficiency-focused.</p>
|
||||
<div class="mt-4 text-sm text-gray-500">
|
||||
<div hx-get="/status" hx-trigger="load" hx-swap="outerHTML"></div>
|
||||
<span>email: me@samantha42.xyz</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section id="experience" class="mb-12">
|
||||
<h2 class="text-2xl font-light border-b pb-2 mb-6">Experience</h2>
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
<div class="border border-gray-400 hover:border-pink-400 p-6 rounded-md cursor-pointer hover:bg-gray-50" onclick="window.location.href='#research'">
|
||||
<div class="flex justify-between mb-2">
|
||||
<span class="font-medium">Independent Equity Research</span>
|
||||
<span class="text-xs border border-blue-600 text-blue-600 rounded-sm px-2 py-0.5 self-start">finance</span>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600 leading-relaxed">Fundamental analysis using SEC filings (10-K, 10-Q) and earnings reports. Assess
|
||||
profitability, liquidity, risk factors, and long-term business sustainability. Handle incomplete or
|
||||
low-transparency information through structured cross-validation.</p>
|
||||
<a class="text-xs font-mono mt-3 inline-block text-blue-600" href="#research">// Go to Analysis</a>
|
||||
</div>
|
||||
<div class="border p-6 rounded-xl cursor-pointer hover:bg-gray-50" onclick="window.location.href='#automation'">
|
||||
<div class="flex justify-between mb-2">
|
||||
<span class="font-medium">Technical Tools & Automation</span>
|
||||
<span class="text-xs border px-2 py-0.5 self-start">engineering</span>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600 leading-relaxed">Build lightweight backend tools to automate repetitive analytical and operational tasks.
|
||||
Python for data processing, validation, and workflow automation. Lightweight online services in Go,
|
||||
focusing on speed and reliability.</p>
|
||||
<a class="text-xs font-mono mt-3 inline-block" href="#automation">// Go to Tools</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="education" class="mb-12">
|
||||
<h2 class="text-2xl font-light border-b pb-2 mb-6">Education</h2>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex gap-6 border-b pb-4">
|
||||
<div class="text-xs text-gray-400 font-mono w-28 shrink-0">2025 — present</div>
|
||||
<div>
|
||||
<div class="font-medium text-sm">Bachelor of Economics & Business Administration (HA)</div>
|
||||
<div class="text-xs text-gray-500">Aalborg University · Expected 2028</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-6 border-b pb-4">
|
||||
<div class="text-xs text-gray-400 font-mono w-28 shrink-0">2024 — 2025<br>
|
||||
<span class="text-red-400">discontinued</span>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-medium text-sm">Mathematics-Technology (BSc)</div>
|
||||
<div class="text-xs text-gray-500">Aalborg University · 1 semester</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-6 border-b pb-4">
|
||||
<div class="text-xs text-gray-400 font-mono w-28 shrink-0">2020 — 2023</div>
|
||||
<div>
|
||||
<div class="font-medium text-sm">HTX - Technical Upper Secondary Education</div>
|
||||
<div class="text-xs text-gray-500">Viden Gymnasier</div>
|
||||
<div class="text-xs text-gray-400">Mathematics A, Biology B · Study project: Mathematics & Technology</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="opinion" class="mb-12">
|
||||
<h2 class="text-2xl font-light border-b pb-2 mb-6">Opinion</h2>
|
||||
<div class="flex gap-4">
|
||||
<a class="border px-4 py-2 text-sm hover:bg-gray-50" href="/cinema">cinema</a>
|
||||
<a class="border px-4 py-2 text-sm hover:bg-gray-50" href="/finance">finance</a>
|
||||
<a class="border px-4 py-2 text-sm hover:bg-gray-50" href="/infra">infra</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="automation" class="mb-12">
|
||||
<h2 class="text-2xl font-light border-b pb-2 mb-6">Technical Tools & Automation <span class="text-sm text-gray-400">engineering/programming</span></h2>
|
||||
<p class="text-sm text-gray-600 leading-relaxed mb-6 max-w-prose">
|
||||
The task here is simple: to reduce work, it's a simple investment. The choice of picking the correct
|
||||
bottleneck is as important as the tool itself, as this gives it use. If it's never used, it never creates
|
||||
value. The same goes for uptime, it's important that stability is almost perfect, as downtime undermines
|
||||
the utility of having the tool. Remember that making and using a tool also creates debt for future
|
||||
maintenance of the tool.
|
||||
<br><br>
|
||||
To adhere to this, I often choose Golang or Python as they are cheap to maintain. Golang has good
|
||||
stability because it is easy to code and compile checks give early error detection. A word of caution on
|
||||
AI generated tools: while they are cheap to make, the maintenance debt grows exponentially, as the code is
|
||||
often poorly understood by the team and difficult to reason about over time.
|
||||
</p>
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
<div class="border p-6">
|
||||
<div class="font-medium mb-2">Portfolio Engine</div>
|
||||
<p class="text-sm text-gray-600 leading-relaxed mb-4">A lightweight portfolio and financial data backend written in Go. Tracks companies,
|
||||
currencies, revenue reports, and trades across configurable time periods — replacing spreadsheets with a
|
||||
proper database, REST API, and interactive shell.</p>
|
||||
<div class="font-medium text-sm mb-2">Roadmap</div>
|
||||
<ul class="list-disc pl-5 text-sm text-gray-600 space-y-1">
|
||||
<li>Price update endpoint</li>
|
||||
<li>Multi-currency conversion</li>
|
||||
<li>Frontend dashboard</li>
|
||||
<li>Shares outstanding history database table</li>
|
||||
<li>Earnings per share (EPS) based on shares owned</li>
|
||||
<li>First-In, First-Out (FIFO) realized gains</li>
|
||||
<li>Dividends earned and related taxes</li>
|
||||
<li>Total tax obligations</li>
|
||||
</ul>
|
||||
<a class="text-xs font-mono mt-4 inline-block" href="https://git.samantha42.xyz/samantha/Portfolio-Engine">// Git repo</a>
|
||||
</div>
|
||||
<div class="border p-6">
|
||||
<div class="font-medium mb-2">Accounting Management</div>
|
||||
<p class="text-sm text-gray-600 leading-relaxed">A lightweight, SQL-backed, web-based CLI system designed to track assets and liabilities. The goal is to
|
||||
provide a simple, fast, and scalable financial tracking tool that can grow from personal use to more
|
||||
advanced scenarios.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="research" class="mb-12">
|
||||
<h2 class="text-2xl font-light border-b pb-2 mb-6">Equity Research</h2>
|
||||
<div class="border p-6 mb-4">
|
||||
<div class="font-medium mb-2">Story vs Fundamental value</div>
|
||||
<p class="text-sm text-gray-600 leading-relaxed">
|
||||
The truth I keep coming back to is simple: find value grounded in the fundamental numbers of a company.
|
||||
<br><br>
|
||||
My approach is rooted in fundamental analysis using SEC filings (10-K, 10-Q), earnings reports,
|
||||
profitability, liquidity, risk factors, and long-term business sustainability. In low-transparency
|
||||
situations I rely on structured cross-validation across sources.
|
||||
<br><br>
|
||||
A pattern I keep seeing is CEOs speaking just close enough to reality to generate a short-term price
|
||||
boost, then moving the goalposts when reality catches up. What companies state in filings and what they
|
||||
communicate to retail or even professional investors can be two very different stories.
|
||||
</p>
|
||||
</div>
|
||||
<h3 class="text-lg font-light mb-4">Current stock analysis</h3>
|
||||
<div class="border p-6 mb-4">
|
||||
<div class="flex justify-between mb-2">
|
||||
<span class="font-medium">MSTR: Strategy</span>
|
||||
<span class="text-red-500 text-sm">Sell</span>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600 leading-relaxed">The company only owns btc by issuing debt and preferred stock offering.<br>
|
||||
The company is a ponzi scheme at its best.</p>
|
||||
<a class="text-xs font-mono mt-3 inline-block" href="/static/pdf/mstr.pdf" target="_blank">// Read file</a>
|
||||
</div>
|
||||
<div class="border p-6 mb-4">
|
||||
<div class="flex justify-between mb-2">
|
||||
<span class="font-medium">Novo.B/NVO: Novo Nordisk A/S</span>
|
||||
<span class="text-green-600 text-sm">Buy</span>
|
||||
</div>
|
||||
<p class="text-sm text-gray-600 leading-relaxed">The product sales of weight loss drugs are high class, pipeline is undervalued.<br>
|
||||
Pipeline and wegovy pill is not recognised correctly as high focus on expiration of current sold product. High pessimistic view of pipeline.</p>
|
||||
<a class="text-xs font-mono mt-3 inline-block" href="/static/pdf/novo.pdf" target="_blank">// Read file</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="interests" class="mb-12">
|
||||
<button onclick="toggleInterests()" class="w-full text-left flex items-center justify-between border-b pb-2 mb-6 group">
|
||||
<h2 class="text-2xl font-light">Interests/Free Time</h2>
|
||||
<span id="interests-chevron" class="text-gray-400 text-sm transition-transform duration-200">▼</span>
|
||||
</button>
|
||||
|
||||
<div id="interests-body" class="hidden">
|
||||
<div class="page-header">
|
||||
<span class="hidden" id="matrix-hidden">
|
||||
Boy: Do not try and bend the spoon. That's impossible. Instead... only try to realize the truth.
|
||||
<br>Neo: What truth?<br>Boy: There is no spoon.
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="section-head"><h2>Lunix rice</h2></div>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<div class="flex self-center w-80 shrink-0 mx-auto">
|
||||
<img src="/static/images/rice.png" class="w-full">
|
||||
</div>
|
||||
<p class="exp-body flex-1 min-w-64">I love my custom Linux setup. I use Hyprland, which automatically arranges app windows
|
||||
on my screen so everything stays organized without dragging things around. I also use Quickshell, which
|
||||
lets me customize menus, shortcuts, and system controls to work exactly how I want.
|
||||
My system is based on Arch Linux or Manjaro Linux, which are versions of Linux that give you more
|
||||
control and customization than a typical computer setup. The result is a clean, fast, and super
|
||||
efficient desktop that's hard to go back from.
|
||||
<a class="outlink" href="https://git.samantha42.xyz/samantha/dotfiles">Git repo</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="section-head"><h2>Movie/Show Top list</h2></div>
|
||||
<span class="page-sub" id="interest-sub">Fav lists</span>
|
||||
<div class="toplist-group">
|
||||
<h3>Top 5 Movies</h3>
|
||||
<div class="flex justify-center flex-wrap gap-3">
|
||||
<div class="flex flex-col items-center w-24" onclick="bladerunnerClick()">
|
||||
<img src="/static/posters/bladerunner2049.jpg" alt="Blade Runner 2049" class="w-24 h-36 object-cover rounded-lg">
|
||||
<p class="text-xs text-center mt-1">Blade Runner 2049</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center w-24" onclick="cureClick()">
|
||||
<img src="/static/posters/AcureForWellness.jpg" alt="A Cure of Wellness" class="w-24 h-36 object-cover rounded-lg">
|
||||
<p class="text-xs text-center mt-1">A Cure of Wellness</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center w-24" onclick="matrixClick()">
|
||||
<img src="/static/posters/matrix.jpg" alt="matrix" class="w-24 h-36 object-cover rounded-lg">
|
||||
<p class="text-xs text-center mt-1">The Matrix</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center w-24" onclick="draculaClick()">
|
||||
<img src="/static/posters/Dracula.webp" alt="Dracula: A Love Tale" class="w-24 h-36 object-cover rounded-lg">
|
||||
<p class="text-xs text-center mt-1">Dracula: A Love Tale</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center w-24" onclick="dragonTypewriterClick()">
|
||||
<img src="/static/posters/TheGirlwiththeDragonTattoo.webp" alt="Girl with a Dragon Tattoos" class="w-24 h-36 object-cover rounded-lg">
|
||||
<p class="text-xs text-center mt-1">Girl with a Dragon Tattoo</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Top 5 Shows</h3>
|
||||
<div class="flex justify-center flex-wrap gap-3">
|
||||
<div class="flex flex-col items-center w-24">
|
||||
<img src="/static/posters/foundation.jpg" alt="foundation" class="w-24 h-36 object-cover rounded-lg">
|
||||
<p class="text-xs text-center mt-1">Foundation</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center w-24">
|
||||
<img src="/static/posters/Chernobyl.webp" alt="Chernobyl" class="w-24 h-36 object-cover rounded-lg">
|
||||
<p class="text-xs text-center mt-1">Chernobyl</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center w-24">
|
||||
<img src="/static/posters/Breaking Bad.webp" alt="Breaking Bad" class="w-24 h-36 object-cover rounded-lg">
|
||||
<p class="text-xs text-center mt-1">Breaking Bad</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center w-24">
|
||||
<img src="/static/posters/Avatar.webp" alt="Avatar: The Last Airbender" class="w-24 h-36 object-cover rounded-lg">
|
||||
<p class="text-xs text-center mt-1">Avatar: The Last Airbender</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center w-24">
|
||||
<img src="/static/posters/Adolescence.webp" alt="Adolescence" class="w-24 h-36 object-cover rounded-lg">
|
||||
<p class="text-xs text-center mt-1">Adolescence</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-head"><h2>programing</h2></div>
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<div class="flex self-center w-50 shrink-0 mx-auto">
|
||||
<img src="/static/images/program.png" class="w-full" alt="program">
|
||||
</div>
|
||||
<div class="flex-1 min-w-64">
|
||||
<p class="exp-body">
|
||||
Programming can be a task, but for me it's a source of joy. This is something I do as a hobby, and I
|
||||
don't use AI much. It's about having fun and making a fool of yourself. It's not about how good it is,
|
||||
in this case, I'd rather just listen to music and drink a cup of tea. I enjoy the struggle to debug,
|
||||
the beauty in understanding why a bug is there to begin with.
|
||||
</p>
|
||||
<br>
|
||||
<p class="exp-body">
|
||||
The text editor I use most is VS Code, but I love the Neovim setup as it enables me to code on a
|
||||
low-level system without a desktop environment being necessary. I do most of my coding on my own
|
||||
desktop, synced with Git to other systems, like the server that hosts this website, which I have built
|
||||
myself. The creation of this website is more of a fun dumb activity for me... go click on one of the
|
||||
movie posters and see.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="section-head"><h2>Games</h2></div>
|
||||
<p class="exp-body">Game i will play in my free time to wind down.</p>
|
||||
<div hx-get="/static/components/games.html" hx-trigger="load" hx-swap="outerHTML"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="absolute flex items-center text-sm h-12 p-2 z-10 left-0 w-screen bg-white border-gray-200 border-t">
|
||||
<a class="mr-auto text-blue-500 " href="mailto:me@samantha42.xyz">me@samantha42.xyz</a>
|
||||
<p class="mx-auto text-gray-500" >Build by me ❤️</p>
|
||||
<div class="ml-auto text-gray-400 " >© 2026 - all rights reserved</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
function InterestShow() {
|
||||
const body = document.getElementById('interests-body');
|
||||
const chevron = document.getElementById('interests-chevron');
|
||||
chevron.classList.add("hidden")
|
||||
body.classList.remove("hidden")
|
||||
chevron.textContent = hidden ? '▶' : '▼';
|
||||
}
|
||||
|
||||
function toggleInterests() {
|
||||
const body = document.getElementById('interests-body');
|
||||
const chevron = document.getElementById('interests-chevron');
|
||||
const hidden = body.classList.toggle('hidden');
|
||||
chevron.textContent = hidden ? '▶' : '▼';
|
||||
}
|
||||
|
||||
const bg = document.getElementById('parallax-bg');
|
||||
const scroller = document.getElementById('scroller');
|
||||
const speed = 0.1;
|
||||
|
||||
scroller.addEventListener('scroll', () => {
|
||||
const offset = scroller.scrollTop * speed;
|
||||
bg.style.transform = `translateY(${offset}px)`;
|
||||
}, { passive: true });
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,80 @@
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Mono:wght@300;400;500&display=swap" rel="stylesheet" />
|
||||
|
||||
<style>
|
||||
.login-wrap { min-height: 520px; display: flex; align-items: center; justify-content: center; padding: 2rem 0; }
|
||||
.login-card { background: var(--bg); border: 0.5px solid var(--border); border-radius: 8px; width: 100%; max-width: 400px; overflow: hidden; }
|
||||
.card-header { background: #0C447C; padding: 2rem 2rem 1.5rem; }
|
||||
.brand { font-family: 'DM Serif Display', serif; font-size: 22px; color: #E6F1FB; letter-spacing: -0.5px; margin: 0 0 4px; }
|
||||
.brand span { font-style: italic; color: #85B7EB; }
|
||||
.brand-sub { font-family: 'DM Mono', monospace; font-size: 11px; color: #378ADD; letter-spacing: 2px; text-transform: uppercase; margin: 0; }
|
||||
.card-body { padding: 1.75rem 2rem; }
|
||||
.field-group { margin-bottom: 1rem; }
|
||||
.field-label { font-family: 'DM Mono', monospace; font-size: 11px; color: var(--muted); letter-spacing: 1px; text-transform: uppercase; display: block; margin-bottom: 6px; }
|
||||
.field-input { width: 100%; box-sizing: border-box; font-family: 'DM Mono', monospace; font-size: 14px; padding: 10px 12px; border-radius: 6px; border: 0.5px solid var(--border); background: var(--bg-2); color: var(--text); transition: border-color 0.2s, box-shadow 0.2s; }
|
||||
.field-input:focus { outline: none; border-color: #378ADD; box-shadow: 0 0 0 3px rgba(55,138,221,0.15); }
|
||||
.submit-btn { width: 100%; padding: 11px; background: #185FA5; color: #E6F1FB; border: none; border-radius: 6px; font-family: 'DM Mono', monospace; font-size: 13px; letter-spacing: 1px; cursor: pointer; transition: background 0.2s, transform 0.1s; margin-top: 0.5rem; }
|
||||
.submit-btn:hover { background: #0C447C; }
|
||||
.submit-btn:active { transform: scale(0.98); }
|
||||
.field-input.htmx-error { border-color: #E24B4A; box-shadow: 0 0 0 3px rgba(226,75,74,0.1); }
|
||||
.error-banner { font-family: 'DM Mono', monospace; font-size: 11px; color: #A32D2D; background: #FCEBEB; border: 0.5px solid #F09595; border-radius: 6px; padding: 8px 12px; margin-bottom: 1rem; display: none; }
|
||||
.htmx-indicator { opacity: 0; transition: opacity 0.2s; font-family: 'DM Mono', monospace; font-size: 11px; color: var(--muted); text-align: center; margin-top: 8px; }
|
||||
.htmx-request .htmx-indicator { opacity: 1; }
|
||||
.htmx-request .submit-btn { background: #0C447C; cursor: not-allowed; }
|
||||
</style>
|
||||
|
||||
<div class="login-wrap">
|
||||
<div class="login-card">
|
||||
<div class="card-header">
|
||||
<p class="brand">samantha<span>42</span>.xyz</p>
|
||||
<p class="brand-sub">Secure Portal</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<!-- error slot — your server renders this partial on failure -->
|
||||
<div id="login-error"></div>
|
||||
|
||||
<form
|
||||
hx-post="/login"
|
||||
hx-target="#login-result"
|
||||
hx-swap="outerHTML"
|
||||
hx-indicator="#login-spinner"
|
||||
>
|
||||
<div class="field-group">
|
||||
<label class="field-label" for="password">Password</label>
|
||||
<input
|
||||
class="field-input"
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
placeholder="••••••••"
|
||||
autocomplete="current-password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="field-group">
|
||||
<label class="field-label" for="totp">2FA Code</label>
|
||||
<input
|
||||
class="field-input"
|
||||
type="text"
|
||||
id="totp"
|
||||
name="totp"
|
||||
placeholder="123456"
|
||||
inputmode="numeric"
|
||||
maxlength="6"
|
||||
autocomplete="one-time-code"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button class="submit-btn" type="submit">Continue →</button>
|
||||
<p class="htmx-indicator" id="login-spinner">verifying...</p>
|
||||
</form>
|
||||
|
||||
<!-- server swaps this element on response -->
|
||||
<div id="login-result"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -134,7 +134,6 @@ main{
|
||||
display:flex;flex-direction:column;gap:4rem;
|
||||
}
|
||||
|
||||
.hero{padding-bottom:3rem;border-bottom:1px solid var(--border);}
|
||||
.hero-eyebrow{
|
||||
font-family:var(--ff-mono);font-size:0.72rem;color:var(--green);
|
||||
letter-spacing:0.18em;margin-bottom:1rem;
|
||||
@@ -596,4 +595,26 @@ a{
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
.dot--available { background: var(--green); }
|
||||
.dot--busy { background: red; }
|
||||
.dot--busy { background: red; }
|
||||
|
||||
/* styles2.css */
|
||||
.overlay {
|
||||
position: fixed;
|
||||
inset: 0; /* top/right/bottom/left: 0 */
|
||||
background: rgba(0, 0, 0, 0.6); /* semi-transparent dark */
|
||||
z-index: 100;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
button {
|
||||
font-family:var(--ff-mono);font-size:0.65rem;
|
||||
letter-spacing:0.1em;text-transform:uppercase;
|
||||
background:rgba(26,86,219,0.07);color:var(--accent);
|
||||
border:1px solid rgba(26,86,219,0.2);
|
||||
padding:2px 8px;border-radius:3px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
border:1px solid rgb(26, 87, 219);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
@theme {
|
||||
--color-regal-blue: #243c5a;
|
||||
}
|
||||
|
||||
@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Libre+Caslon+Display&family=Libre+Caslon+Text:ital,wght@0,400;0,700;1,400&family=Noto+Sans+JP:wght@100..900&family=Rubik:ital,wght@0,300..900;1,300..900&display=swap');
|
||||
@import url('https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,300..900;1,300..900&display=swap');
|
||||
|
||||
.theme-root.night {
|
||||
--bg: #1c1c1c;
|
||||
--surface: #252525;
|
||||
--surface2: #2a2a2a;
|
||||
--border: #363636;
|
||||
--border2: #ccc7be;
|
||||
--text: #ffffff;
|
||||
--muted: #d9d9d9;
|
||||
--dim: #b0aa9f;
|
||||
--navback: rgba(28, 28, 28, 0.8);
|
||||
--accent: #5389ff;
|
||||
--accent2:#1447b8;
|
||||
--green:#0eaf74;
|
||||
--amber:#ffd78e;
|
||||
}
|
||||
|
||||
.section-head{display:flex;align-items:center;gap:10px;margin-bottom:1.8rem;}
|
||||
.section-head h2{
|
||||
font-family:var(--ff-mono);font-size:0.72rem;font-weight:400;
|
||||
letter-spacing:0.25em;text-transform:uppercase;color:var(--muted);
|
||||
white-space:nowrap;
|
||||
}
|
||||
.section-head::after{content:'';flex:1;height:1px;background:var(--border);}
|
||||
|
||||
.exp-body{font-size:0.85rem;color:var(--muted);line-height:1.8;}
|
||||
|
||||
.libre-caslon-text-regular {
|
||||
font-family: "Libre Caslon Text", serif;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.libre-caslon-text-bold {
|
||||
font-family: "Libre Caslon Text", serif;
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.libre-caslon-text-regular-italic {
|
||||
font-family: "Libre Caslon Text", serif;
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.rubik-400 {
|
||||
font-family: "Rubik", sans-serif;
|
||||
font-optical-sizing: auto;
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
./tailwindcss-linux-x64 --input static/vars.css --content "./static/**/*.html" --output static/tailwind.css --watch
|
||||