diff --git a/main b/main new file mode 100755 index 0000000..11523f2 Binary files /dev/null and b/main differ diff --git a/main.go b/main.go index 6428348..40e8a38 100644 --- a/main.go +++ b/main.go @@ -96,15 +96,14 @@ func main() { flag.Parse() http.HandleFunc("/styles.css", Styles) - http.HandleFunc("/", Home) - http.HandleFunc("/about", About) - http.HandleFunc("/portfolio", Portfolio) + http.HandleFunc("/", About) + //http.HandleFunc("/portfolio", Portfolio) http.HandleFunc("/infra", Infra) http.HandleFunc("/cyber", Cyber) - http.HandleFunc("/gitpage", GitPage) - http.HandleFunc("/gitpage/TicTacToe", GitPageTicTacToe) - http.HandleFunc("/trades", TradesHandler) - http.HandleFunc("/api/prices", PricesHandler) + //http.HandleFunc("/gitpage", GitPage) + //http.HandleFunc("/gitpage/TicTacToe", GitPageTicTacToe) + //http.HandleFunc("/trades", TradesHandler) + //http.HandleFunc("/api/prices", PricesHandler) fmt.Printf("running on http://localhost:%s/\n", *port) if err := http.ListenAndServe(":"+*port, nil); err != nil { diff --git a/static/about.html b/static/about.html index 66e5395..430b92d 100644 --- a/static/about.html +++ b/static/about.html @@ -1,103 +1,196 @@ - + - - - - About — Samantha Friis - - - - -
+ + + + About — Samantha Friis + + + + +
+ + -
- ← back -

// about me

-

Samantha
Friis

-

Denmark, Aalborg  ·  samantha42.xyz

-
+
+

// about me

+

Samantha
Friis

+

+ Denmark, Aalborg  ·  samantha42.xyz +

+
-
+
+

+ 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. +

-

- 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. -

+ +
+ +
+
+ Excel +
+
+
+
+
+ Python +
+
+
+
+
+ SQL +
+
+
+
+
+ Go +
+
+
+
+
+ Git +
+
+
+
+
+
- -
- -
-
Excel
-
Python
-
SQL
-
Go
-
Git
-
-
+ +
+ - -
- +
+

Independent Equity Research

+

+ Perform 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. +

+
-
-

Independent Equity Research

-

Perform 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.

-
+
+

Technical Tools & Automation

+

+ Build lightweight backend tools to automate + repetitive analytical and operational tasks. Use + Python for data processing, validation, and workflow + automation. Develop lightweight online services in + Go, focusing on speed and reliability. +

+
+
-
-

Technical Tools & Automation

-

Build lightweight backend tools to automate repetitive analytical and operational tasks. Use Python for data processing, validation, and workflow automation. Develop lightweight online services in Go, focusing on speed and reliability.

-
-
+ +
+ - -
- +
+ 2025 — now +
+

+ Bachelor of Economics & Business Administration + (HA) +

+

+ Aalborg University  ·  Expected 2028 +

+
+
-
- 2025 — now -
-

Bachelor of Economics & Business Administration (HA)

-

Aalborg University  ·  Expected 2028

+
+ 2020 — 2023 +
+

+ HTX – Technical Upper Secondary Education +

+

+ Viden Gymnasier  ·  Mathematics A, + Biology B
Study project: Mathematics & + Technology +

+
+
+
+ + +
+ +
+
+ Danish +
+
+
+
+
+ English +
+
+
+
+
+
+ + +
+ +
+ Gaming + Board games + Programming + Financial markets +
+
+
+ +
-
- -
- 2020 — 2023 -
-

HTX – Technical Upper Secondary Education

-

Viden Gymnasier  ·  Mathematics A, Biology B
Study project: Mathematics & Technology

-
-
- - - -
-

// languages

-
-
Danish
-
English
-
-
- - -
-

// interests

-
- Gaming - Board games - Programming - Financial markets -
-
- - - - - - - - \ No newline at end of file + + diff --git a/static/styles.css b/static/styles.css index d0671f1..abd65c6 100644 --- a/static/styles.css +++ b/static/styles.css @@ -1,451 +1,1051 @@ /* ─── Variables ─── */ :root { - --bg: #252525; - --surface: #2b2b2b; - --surface2: #313131; - --border: #3a3a3a; - --border-focus: #4e4e4e; - --text: #e8e8e0; - --muted: #777770; - --accent: #B88FE0; - --accent2: #6247AA; - --green: #6fcf8a; - --red: #e07070; - --yellow: #e0c870; + --bg: #252525; + --surface: #2b2b2b; + --surface2: #313131; + --border: #3a3a3a; + --border-focus: #4e4e4e; + --text: #e8e8e0; + --muted: #777770; + --accent: #b88fe0; + --accent2: #6247aa; + --green: #6fcf8a; + --red: #e07070; + --yellow: #e0c870; } /* ─── Reset ─── */ -*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } -html { scroll-behavior: smooth; } +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} +html { + scroll-behavior: smooth; +} /* ─── Base ─── */ body { - background: var(--bg); - color: var(--text); - font-family: 'DM Mono', monospace; - min-height: 100vh; - overflow-x: hidden; + background: var(--bg); + color: var(--text); + font-family: "DM Mono", monospace; + min-height: 100vh; + overflow-x: hidden; } /* Grain overlay */ body::before { - content: ''; - position: fixed; - inset: 0; - background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.04'/%3E%3C/svg%3E"); - pointer-events: none; - z-index: 999; - opacity: 0.35; + content: ""; + position: fixed; + inset: 0; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.04'/%3E%3C/svg%3E"); + pointer-events: none; + z-index: 999; + opacity: 0.35; } /* ─── Layout ─── */ -.container { max-width: 860px; margin: 0 auto; padding: 0 2rem; } -.container--wide { max-width: 1100px; margin: 0 auto; padding: 0 2rem; } -.container--narrow { max-width: 720px; margin: 0 auto; padding: 0 2rem; } +.container { + max-width: 860px; + margin: 0 auto; + padding: 0 2rem; +} +.container--wide { + max-width: 1100px; + margin: 0 auto; + padding: 0 2rem; +} +.container--narrow { + max-width: 720px; + margin: 0 auto; + padding: 0 2rem; +} /* ─── Header ─── */ header { - padding: 4rem 0 3rem; - border-bottom: 1px solid var(--border); - animation: fadeUp 0.6s ease both; + padding: 4rem 0 3rem; + border-bottom: 1px solid var(--border); + animation: fadeUp 0.6s ease both; } .back { - display: inline-flex; - align-items: center; - gap: 0.4rem; - font-size: 0.72rem; - color: var(--muted); - text-decoration: none; - letter-spacing: 0.1em; - text-transform: uppercase; - margin-bottom: 2rem; - transition: color 0.2s; + display: inline-flex; + align-items: center; + gap: 0.4rem; + font-size: 0.72rem; + color: var(--muted); + text-decoration: none; + letter-spacing: 0.1em; + text-transform: uppercase; + margin-bottom: 2rem; + transition: color 0.2s; +} +.back:hover { + color: var(--accent); } -.back:hover { color: var(--accent); } .tag { - font-size: 0.7rem; - letter-spacing: 0.2em; - text-transform: uppercase; - color: var(--accent); - margin-bottom: 1rem; + font-size: 0.7rem; + letter-spacing: 0.2em; + text-transform: uppercase; + color: var(--accent); + margin-bottom: 1rem; } h1 { - font-family: 'Syne', sans-serif; - font-size: clamp(2.2rem, 4vw, 3.5rem); - font-weight: 800; - line-height: 1.05; - letter-spacing: -0.02em; + font-family: "Syne", sans-serif; + font-size: clamp(2.2rem, 4vw, 3.5rem); + font-weight: 800; + line-height: 1.05; + letter-spacing: -0.02em; +} +h1 span { + color: var(--accent); } -h1 span { color: var(--accent); } -h1--hero { font-size: clamp(2.8rem, 6vw, 5rem); line-height: 1; } +h1--hero { + font-size: clamp(2.8rem, 6vw, 5rem); + line-height: 1; +} .header-sub { - margin-top: 0.6rem; - font-size: 0.78rem; - color: var(--muted); + margin-top: 0.6rem; + font-size: 0.78rem; + color: var(--muted); } .byline { - margin-top: 1.2rem; - font-size: 0.72rem; - color: var(--muted); - display: flex; - gap: 1.5rem; + margin-top: 1.2rem; + font-size: 0.72rem; + color: var(--muted); + display: flex; + gap: 1.5rem; +} +.byline span { + color: var(--accent); } -.byline span { color: var(--accent); } /* ─── Typography ─── */ h2 { - font-family: 'Syne', sans-serif; - font-size: 1.2rem; - font-weight: 700; - color: var(--accent); - margin: 2.8rem 0 1rem; - letter-spacing: -0.01em; + font-family: "Syne", sans-serif; + font-size: 1.2rem; + font-weight: 700; + color: var(--accent); + margin: 2.8rem 0 1rem; + letter-spacing: -0.01em; } h2::before { - content: '// '; - color: var(--accent2); - font-family: 'DM Mono', monospace; - font-weight: 300; + content: "// "; + color: var(--accent2); + font-family: "DM Mono", monospace; + font-weight: 300; } p { - font-size: 0.85rem; - line-height: 1.9; - color: #c8c8c0; - margin-bottom: 1.2rem; + font-size: 0.85rem; + line-height: 1.9; + color: #c8c8c0; + margin-bottom: 1.2rem; } code { - font-family: 'DM Mono', monospace; - font-size: 0.78rem; - color: var(--accent); - background: rgba(184, 143, 224, 0.08); - padding: 0.1rem 0.4rem; - border: 1px solid rgba(184, 143, 224, 0.15); + font-family: "DM Mono", monospace; + font-size: 0.78rem; + color: var(--accent); + background: rgba(184, 143, 224, 0.08); + padding: 0.1rem 0.4rem; + border: 1px solid rgba(184, 143, 224, 0.15); } -hr { border: none; border-top: 1px solid var(--border); margin: 2.5rem 0; } +hr { + border: none; + border-top: 1px solid var(--border); + margin: 2.5rem 0; +} .section-label { - font-size: 0.65rem; - letter-spacing: 0.2em; - text-transform: uppercase; - color: var(--accent); - margin-bottom: 1.2rem; + font-size: 0.65rem; + letter-spacing: 0.2em; + text-transform: uppercase; + color: var(--accent); + margin-bottom: 1.2rem; } .lead { - font-size: 1rem; - line-height: 1.9; - color: var(--text); - border-left: 2px solid var(--accent2); - padding-left: 1.5rem; - margin-bottom: 3rem; + font-size: 1rem; + line-height: 1.9; + color: var(--text); + border-left: 2px solid var(--accent2); + padding-left: 1.5rem; + margin-bottom: 3rem; } blockquote { - margin: 2.5rem 0; - padding: 1.6rem 2rem; - background: var(--surface); - border-left: 3px solid var(--accent); - font-family: 'Syne', sans-serif; - font-size: 1.05rem; - font-weight: 700; - color: var(--text); - line-height: 1.5; - letter-spacing: -0.01em; + margin: 2.5rem 0; + padding: 1.6rem 2rem; + background: var(--surface); + border-left: 3px solid var(--accent); + font-family: "Syne", sans-serif; + font-size: 1.05rem; + font-weight: 700; + color: var(--text); + line-height: 1.5; + letter-spacing: -0.01em; +} +blockquote span { + color: var(--accent); } -blockquote span { color: var(--accent); } /* ─── Color utilities ─── */ -.up { color: var(--green); } -.down { color: var(--red); } -.neutral { color: var(--muted); } +.up { + color: var(--green); +} +.down { + color: var(--red); +} +.neutral { + color: var(--muted); +} /* ─── Cards ─── */ .cards { - display: grid; - grid-template-columns: repeat(4, 1fr); - gap: 1px; - background: var(--border); - border: 1px solid var(--border); - margin: 3rem 0 2.5rem; - animation: fadeUp 0.6s 0.1s ease both; + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 1px; + background: var(--border); + border: 1px solid var(--border); + margin: 3rem 0 2.5rem; + animation: fadeUp 0.6s 0.1s ease both; +} +.card { + background: var(--surface); + padding: 1.4rem 1.6rem; } -.card { background: var(--surface); padding: 1.4rem 1.6rem; } .card-label { - font-size: 0.62rem; - letter-spacing: 0.15em; - text-transform: uppercase; - color: var(--muted); - margin-bottom: 0.5rem; + font-size: 0.62rem; + letter-spacing: 0.15em; + text-transform: uppercase; + color: var(--muted); + margin-bottom: 0.5rem; } .card-value { - font-family: 'Syne', sans-serif; - font-size: 1.5rem; - font-weight: 700; + font-family: "Syne", sans-serif; + font-size: 1.5rem; + font-weight: 700; } /* ─── Nav grid (homepage) ─── */ .nav-grid { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 1px; - background: var(--border); - border: 1px solid var(--border); + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1px; + background: var(--border); + border: 1px solid var(--border); } .nav-item { - display: block; - background: var(--surface); - padding: 2rem 2rem 1.8rem; - text-decoration: none; - color: var(--text); - position: relative; - overflow: hidden; - transition: background 0.2s ease; - animation: fadeUp 0.7s ease both; + display: block; + background: var(--surface); + padding: 2rem 2rem 1.8rem; + text-decoration: none; + color: var(--text); + position: relative; + overflow: hidden; + transition: background 0.2s ease; + animation: fadeUp 0.7s ease both; } .nav-item::after { - content: ''; - position: absolute; - bottom: 0; left: 0; - width: 0; height: 2px; - background: var(--accent); - transition: width 0.3s ease; + content: ""; + position: absolute; + bottom: 0; + left: 0; + width: 0; + height: 2px; + background: var(--accent); + transition: width 0.3s ease; +} +.nav-item:hover { + background: #161616; +} +.nav-item:hover::after { + width: 100%; +} +.nav-item:hover .arrow { + transform: translate(4px, -4px); +} +.nav-number { + font-size: 0.65rem; + color: var(--muted); + letter-spacing: 0.15em; + margin-bottom: 1.4rem; } -.nav-item:hover { background: #161616; } -.nav-item:hover::after { width: 100%; } -.nav-item:hover .arrow { transform: translate(4px, -4px); } -.nav-number { font-size: 0.65rem; color: var(--muted); letter-spacing: 0.15em; margin-bottom: 1.4rem; } .nav-title { - font-family: 'Syne', sans-serif; - font-size: 1.35rem; - font-weight: 700; - margin-bottom: 0.5rem; - display: flex; - align-items: center; - justify-content: space-between; - gap: 0.5rem; + font-family: "Syne", sans-serif; + font-size: 1.35rem; + font-weight: 700; + margin-bottom: 0.5rem; + display: flex; + align-items: center; + justify-content: space-between; + gap: 0.5rem; +} +.arrow { + font-size: 1rem; + color: var(--accent); + transition: transform 0.25s ease; + flex-shrink: 0; +} +.nav-desc { + font-size: 0.75rem; + color: var(--muted); + line-height: 1.6; } -.arrow { font-size: 1rem; color: var(--accent); transition: transform 0.25s ease; flex-shrink: 0; } -.nav-desc { font-size: 0.75rem; color: var(--muted); line-height: 1.6; } /* ─── Table ─── */ -.table-wrap { overflow-x: auto; animation: fadeUp 0.6s 0.2s ease both; margin-bottom: 2.5rem; } -table { width: 100%; border-collapse: collapse; font-size: 0.78rem; } -thead tr { border-bottom: 1px solid var(--border); } +.table-wrap { + overflow-x: auto; + animation: fadeUp 0.6s 0.2s ease both; + margin-bottom: 2.5rem; +} +table { + width: 100%; + border-collapse: collapse; + font-size: 0.78rem; +} +thead tr { + border-bottom: 1px solid var(--border); +} thead th { - font-size: 0.62rem; - letter-spacing: 0.12em; - text-transform: uppercase; - color: var(--muted); - padding: 0.7rem 1rem; - text-align: right; - white-space: nowrap; + font-size: 0.62rem; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--muted); + padding: 0.7rem 1rem; + text-align: right; + white-space: nowrap; +} +thead th:first-child { + text-align: left; +} +tbody tr { + border-bottom: 1px solid var(--border); + transition: background 0.15s; +} +tbody tr:hover { + background: var(--surface2); +} +tbody td { + padding: 1rem; + text-align: right; + white-space: nowrap; + color: var(--text); +} +tbody td:first-child { + text-align: left; } -thead th:first-child { text-align: left; } -tbody tr { border-bottom: 1px solid var(--border); transition: background 0.15s; } -tbody tr:hover { background: var(--surface2); } -tbody td { padding: 1rem; text-align: right; white-space: nowrap; color: var(--text); } -tbody td:first-child { text-align: left; } -.ticker { font-family: 'Syne', sans-serif; font-weight: 700; font-size: 0.9rem; color: var(--text); } -.currency-badge { - display: inline-block; - font-size: 0.6rem; - padding: 0.15rem 0.4rem; - border: 1px solid var(--border); - color: var(--muted); - margin-left: 0.4rem; - vertical-align: middle; +.ticker { + font-family: "Syne", sans-serif; + font-weight: 700; + font-size: 0.9rem; + color: var(--text); +} +.currency-badge { + display: inline-block; + font-size: 0.6rem; + padding: 0.15rem 0.4rem; + border: 1px solid var(--border); + color: var(--muted); + margin-left: 0.4rem; + vertical-align: middle; +} +.weight-cell { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 0.6rem; +} +.weight-bar-track { + width: 60px; + height: 3px; + background: var(--border); + border-radius: 2px; + overflow: hidden; +} +.weight-bar-fill { + height: 100%; + background: linear-gradient(90deg, var(--accent2), var(--accent)); + border-radius: 2px; +} +.watchlist-row td { + color: var(--muted); +} +.watchlist-label { + font-size: 0.62rem; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--muted); + padding: 1.2rem 1rem 0.5rem; } -.weight-cell { display: flex; align-items: center; justify-content: flex-end; gap: 0.6rem; } -.weight-bar-track { width: 60px; height: 3px; background: var(--border); border-radius: 2px; overflow: hidden; } -.weight-bar-fill { height: 100%; background: linear-gradient(90deg, var(--accent2), var(--accent)); border-radius: 2px; } -.watchlist-row td { color: var(--muted); } -.watchlist-label { font-size: 0.62rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); padding: 1.2rem 1rem 0.5rem; } /* ─── Skill bars ─── */ -.skills-list { display: flex; flex-direction: column; gap: 0.75rem; } -.skill-row { display: grid; grid-template-columns: 80px 1fr; align-items: center; gap: 1rem; font-size: 0.78rem; color: var(--muted); } -.skill-bar-track { height: 3px; background: var(--border); border-radius: 2px; overflow: hidden; } +.skills-list { + display: flex; + flex-direction: column; + gap: 0.75rem; +} +.skill-row { + display: grid; + grid-template-columns: 80px 1fr; + align-items: center; + gap: 1rem; + font-size: 0.78rem; + color: var(--muted); +} +.skill-bar-track { + height: 3px; + background: var(--border); + border-radius: 2px; + overflow: hidden; +} .skill-bar-fill { - height: 100%; - background: linear-gradient(90deg, var(--accent2), var(--accent)); - border-radius: 2px; - transform-origin: left; - animation: growBar 0.8s ease both; + height: 100%; + background: linear-gradient(90deg, var(--accent2), var(--accent)); + border-radius: 2px; + transform-origin: left; + animation: growBar 0.8s ease both; } /* ─── Compare grid ─── */ -.compare { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--border); border: 1px solid var(--border); margin: 2rem 0; } -.compare-col { background: var(--surface); padding: 1.4rem 1.6rem; } -.compare-col h3 { font-family: 'Syne', sans-serif; font-size: 0.85rem; font-weight: 700; margin-bottom: 1rem; padding-bottom: 0.6rem; border-bottom: 1px solid var(--border); } -.compare-col.bad h3 { color: var(--red); } -.compare-col.good h3 { color: var(--green); } -.compare-col ul { list-style: none; display: flex; flex-direction: column; gap: 0.6rem; } -.compare-col ul li { font-size: 0.75rem; color: var(--muted); line-height: 1.5; padding-left: 1rem; position: relative; } -.compare-col.bad ul li::before { content: '—'; position: absolute; left: 0; color: var(--red); } -.compare-col.good ul li::before { content: '+'; position: absolute; left: 0; color: var(--green); } +.compare { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1px; + background: var(--border); + border: 1px solid var(--border); + margin: 2rem 0; +} +.compare-col { + background: var(--surface); + padding: 1.4rem 1.6rem; +} +.compare-col h3 { + font-family: "Syne", sans-serif; + font-size: 0.85rem; + font-weight: 700; + margin-bottom: 1rem; + padding-bottom: 0.6rem; + border-bottom: 1px solid var(--border); +} +.compare-col.bad h3 { + color: var(--red); +} +.compare-col.good h3 { + color: var(--green); +} +.compare-col ul { + list-style: none; + display: flex; + flex-direction: column; + gap: 0.6rem; +} +.compare-col ul li { + font-size: 0.75rem; + color: var(--muted); + line-height: 1.5; + padding-left: 1rem; + position: relative; +} +.compare-col.bad ul li::before { + content: "—"; + position: absolute; + left: 0; + color: var(--red); +} +.compare-col.good ul li::before { + content: "+"; + position: absolute; + left: 0; + color: var(--green); +} /* ─── Experience & Education ─── */ -.exp-block { background: var(--surface); border: 1px solid var(--border); padding: 1.5rem; margin-bottom: 1px; } -.exp-block p { font-size: 0.78rem; color: var(--muted); line-height: 1.7; margin-top: 0.4rem; } +.exp-block { + background: var(--surface); + border: 1px solid var(--border); + padding: 1.5rem; + margin-bottom: 1px; +} +.exp-block p { + font-size: 0.78rem; + color: var(--muted); + line-height: 1.7; + margin-top: 0.4rem; +} -.edu-item { display: grid; grid-template-columns: 80px 1fr; gap: 1.5rem; margin-bottom: 1.5rem; padding-bottom: 1.5rem; border-bottom: 1px solid var(--border); } -.edu-item:last-child { border-bottom: none; margin-bottom: 0; } -.edu-year { font-size: 0.65rem; color: var(--accent); letter-spacing: 0.1em; padding-top: 0.15rem; } -.edu-title { font-family: 'Syne', sans-serif; font-size: 0.95rem; font-weight: 700; margin-bottom: 0.25rem; } -.edu-sub { font-size: 0.75rem; color: var(--muted); line-height: 1.6; } +.edu-item { + display: grid; + grid-template-columns: 80px 1fr; + gap: 1.5rem; + margin-bottom: 1.5rem; + padding-bottom: 1.5rem; + border-bottom: 1px solid var(--border); +} +.edu-item:last-child { + border-bottom: none; + margin-bottom: 0; +} +.edu-year { + font-size: 0.65rem; + color: var(--accent); + letter-spacing: 0.1em; + padding-top: 0.15rem; +} +.edu-title { + font-family: "Syne", sans-serif; + font-size: 0.95rem; + font-weight: 700; + margin-bottom: 0.25rem; +} +.edu-sub { + font-size: 0.75rem; + color: var(--muted); + line-height: 1.6; +} -.tags { display: flex; flex-wrap: wrap; gap: 0.5rem; } -.tag-pill { font-size: 0.7rem; padding: 0.3rem 0.75rem; border: 1px solid var(--border); color: var(--muted); letter-spacing: 0.05em; } +.tags { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; +} +.tag-pill { + font-size: 0.7rem; + padding: 0.3rem 0.75rem; + border: 1px solid var(--border); + color: var(--muted); + letter-spacing: 0.05em; +} /* ─── Forms / Login ─── */ -.form-group { margin-bottom: 1.2rem; } -label { display: block; font-size: 0.62rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); margin-bottom: 0.5rem; } -input[type="text"], input[type="password"] { - width: 100%; - background: var(--bg); - border: 1px solid var(--border); - color: var(--text); - font-family: 'DM Mono', monospace; - font-size: 0.82rem; - padding: 0.7rem 0.9rem; - outline: none; - transition: border-color 0.2s, box-shadow 0.2s; - -webkit-appearance: none; +.form-group { + margin-bottom: 1.2rem; } -input[type="text"]:focus, input[type="password"]:focus { - border-color: var(--accent2); - box-shadow: 0 0 0 2px rgba(98, 71, 170, 0.15); +label { + display: block; + font-size: 0.62rem; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--muted); + margin-bottom: 0.5rem; +} +input[type="text"], +input[type="password"] { + width: 100%; + background: var(--bg); + border: 1px solid var(--border); + color: var(--text); + font-family: "DM Mono", monospace; + font-size: 0.82rem; + padding: 0.7rem 0.9rem; + outline: none; + transition: + border-color 0.2s, + box-shadow 0.2s; + -webkit-appearance: none; +} +input[type="text"]:focus, +input[type="password"]:focus { + border-color: var(--accent2); + box-shadow: 0 0 0 2px rgba(98, 71, 170, 0.15); +} +input::placeholder { + color: var(--muted); } -input::placeholder { color: var(--muted); } -.btn { width: 100%; background: var(--accent2); color: var(--text); font-family: 'DM Mono', monospace; font-size: 0.78rem; letter-spacing: 0.1em; text-transform: uppercase; padding: 0.8rem 1rem; border: none; cursor: pointer; transition: background 0.2s, opacity 0.2s; } -.btn:hover { background: var(--accent); } -.btn:active { opacity: 0.8; } +.btn { + width: 100%; + background: var(--accent2); + color: var(--text); + font-family: "DM Mono", monospace; + font-size: 0.78rem; + letter-spacing: 0.1em; + text-transform: uppercase; + padding: 0.8rem 1rem; + border: none; + cursor: pointer; + transition: + background 0.2s, + opacity 0.2s; +} +.btn:hover { + background: var(--accent); +} +.btn:active { + opacity: 0.8; +} /* ─── Footer ─── */ footer { - padding: 2.5rem 0 3rem; - border-top: 1px solid var(--border); - display: flex; - flex-direction: column; - align-items: center; - gap: 0.6rem; - text-align: center; - animation: fadeUp 0.6s 0.4s ease both; + padding: 2.5rem 0 3rem; + border-top: 1px solid var(--border); + display: flex; + flex-direction: column; + align-items: center; + gap: 0.6rem; + text-align: center; + animation: fadeUp 0.6s 0.4s ease both; +} +footer a { + color: var(--accent); + text-decoration: none; + font-size: 0.85rem; + transition: opacity 0.2s; +} +footer a:hover { + opacity: 0.7; +} +.footer-copy { + font-size: 0.68rem; + color: var(--muted); + letter-spacing: 0.05em; } -footer a { color: var(--accent); text-decoration: none; font-size: 0.85rem; transition: opacity 0.2s; } -footer a:hover { opacity: 0.7; } -.footer-copy { font-size: 0.68rem; color: var(--muted); letter-spacing: 0.05em; } /* ─── Animations ─── */ @keyframes fadeUp { - from { opacity: 0; transform: translateY(16px); } - to { opacity: 1; transform: translateY(0); } + from { + opacity: 0; + transform: translateY(16px); + } + to { + opacity: 1; + transform: translateY(0); + } } @keyframes growBar { - from { transform: scaleX(0); } - to { transform: scaleX(1); } + from { + transform: scaleX(0); + } + to { + transform: scaleX(1); + } } @keyframes shake { - 0%, 100% { transform: translateX(0); } - 20% { transform: translateX(-6px); } - 40% { transform: translateX(6px); } - 60% { transform: translateX(-4px); } - 80% { transform: translateX(4px); } + 0%, + 100% { + transform: translateX(0); + } + 20% { + transform: translateX(-6px); + } + 40% { + transform: translateX(6px); + } + 60% { + transform: translateX(-4px); + } + 80% { + transform: translateX(4px); + } +} +.shake { + animation: shake 0.4s ease; } -.shake { animation: shake 0.4s ease; } /* ─── Article layout ─── */ -article { padding: 3.5rem 0; animation: fadeUp 0.6s 0.1s ease both; } -main { padding: 3.5rem 0; } +article { + padding: 3.5rem 0; + animation: fadeUp 0.6s 0.1s ease both; +} +main { + padding: 3.5rem 0; +} /* ─── Classify grid (cyber page) ─── */ .classify-grid { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 1px; - background: var(--border); - border: 1px solid var(--border); - margin: 2rem 0; + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1px; + background: var(--border); + border: 1px solid var(--border); + margin: 2rem 0; +} +.classify-card { + background: var(--surface); + padding: 1.4rem 1.3rem; +} +.classify-card h3 { + font-family: "Syne", sans-serif; + font-size: 0.9rem; + font-weight: 700; + margin-bottom: 0.5rem; +} +.classify-card p { + font-size: 0.72rem; + color: var(--muted); + margin: 0; + line-height: 1.6; +} +.level { + font-size: 0.6rem; + letter-spacing: 0.18em; + text-transform: uppercase; + margin-bottom: 0.6rem; + font-weight: 500; +} +.level-critical { + color: var(--red); +} +.level-high { + color: var(--yellow); +} +.level-standard { + color: var(--green); } -.classify-card { background: var(--surface); padding: 1.4rem 1.3rem; } -.classify-card h3 { font-family: 'Syne', sans-serif; font-size: 0.9rem; font-weight: 700; margin-bottom: 0.5rem; } -.classify-card p { font-size: 0.72rem; color: var(--muted); margin: 0; line-height: 1.6; } -.level { font-size: 0.6rem; letter-spacing: 0.18em; text-transform: uppercase; margin-bottom: 0.6rem; font-weight: 500; } -.level-critical { color: var(--red); } -.level-high { color: var(--yellow); } -.level-standard { color: var(--green); } /* ─── Principles (cyber page) ─── */ -.principles { display: flex; flex-direction: column; gap: 1px; margin: 2rem 0; } -.principle { display: grid; grid-template-columns: 2.5rem 1fr; gap: 1.2rem; background: var(--surface); padding: 1.2rem 1.4rem; border: 1px solid var(--border); margin-bottom: 1px; align-items: start; } -.principle-num { font-family: 'Syne', sans-serif; font-size: 1.1rem; font-weight: 800; color: var(--accent2); padding-top: 0.1rem; } -.principle-title { font-family: 'Syne', sans-serif; font-size: 0.9rem; font-weight: 700; color: var(--text); margin-bottom: 0.35rem; } -.principle p { font-size: 0.77rem; color: var(--muted); line-height: 1.65; margin: 0; } +.principles { + display: flex; + flex-direction: column; + gap: 1px; + margin: 2rem 0; +} +.principle { + display: grid; + grid-template-columns: 2.5rem 1fr; + gap: 1.2rem; + background: var(--surface); + padding: 1.2rem 1.4rem; + border: 1px solid var(--border); + margin-bottom: 1px; + align-items: start; +} +.principle-num { + font-family: "Syne", sans-serif; + font-size: 1.1rem; + font-weight: 800; + color: var(--accent2); + padding-top: 0.1rem; +} +.principle-title { + font-family: "Syne", sans-serif; + font-size: 0.9rem; + font-weight: 700; + color: var(--text); + margin-bottom: 0.35rem; +} +.principle p { + font-size: 0.77rem; + color: var(--muted); + line-height: 1.65; + margin: 0; +} /* ─── Attack table (cyber page) ─── */ -.attack-table { width: 100%; border-collapse: collapse; font-size: 0.76rem; margin: 2rem 0; } -.attack-table thead th { font-size: 0.6rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); padding: 0.6rem 1rem; text-align: left; border-bottom: 1px solid var(--border); } -.attack-table tbody tr { border-bottom: 1px solid var(--border); transition: background 0.15s; } -.attack-table tbody tr:hover { background: var(--surface2); } -.attack-table tbody td { padding: 0.9rem 1rem; color: #c8c8c0; vertical-align: top; line-height: 1.55; text-align: left; } -.attack-table td:first-child { color: var(--red); font-weight: 500; white-space: nowrap; } -.counter { color: var(--green); font-size: 0.72rem; } +.attack-table { + width: 100%; + border-collapse: collapse; + font-size: 0.76rem; + margin: 2rem 0; +} +.attack-table thead th { + font-size: 0.6rem; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--muted); + padding: 0.6rem 1rem; + text-align: left; + border-bottom: 1px solid var(--border); +} +.attack-table tbody tr { + border-bottom: 1px solid var(--border); + transition: background 0.15s; +} +.attack-table tbody tr:hover { + background: var(--surface2); +} +.attack-table tbody td { + padding: 0.9rem 1rem; + color: #c8c8c0; + vertical-align: top; + line-height: 1.55; + text-align: left; +} +.attack-table td:first-child { + color: var(--red); + font-weight: 500; + white-space: nowrap; +} +.counter { + color: var(--green); + font-size: 0.72rem; +} /* ─── Login panel ─── */ -.login-panel { border: 1px solid var(--border); background: var(--surface); padding: 2rem; } -.login-panel h2 { font-family: 'Syne', sans-serif; font-size: 1rem; font-weight: 700; margin-bottom: 0.3rem; } -.login-panel .desc { font-size: 0.72rem; color: var(--muted); margin-bottom: 2rem; line-height: 1.6; } -.twofa-group { display: none; margin-bottom: 1.2rem; } -.twofa-group.visible { display: block; } -.twofa-hint { font-size: 0.68rem; color: var(--muted); margin-top: 0.4rem; } -.btn-login { width: 100%; background: var(--accent2); color: var(--text); font-family: 'DM Mono', monospace; font-size: 0.78rem; letter-spacing: 0.1em; text-transform: uppercase; padding: 0.8rem 1rem; border: none; cursor: pointer; transition: background 0.2s, opacity 0.2s; margin-top: 0.4rem; } -.btn-login:hover { background: var(--accent); } -.btn-login:active { opacity: 0.8; } -.login-error { font-size: 0.72rem; color: var(--red); margin-top: 1rem; display: none; } -.login-error.visible { display: block; } +.login-panel { + border: 1px solid var(--border); + background: var(--surface); + padding: 2rem; +} +.login-panel h2 { + font-family: "Syne", sans-serif; + font-size: 1rem; + font-weight: 700; + margin-bottom: 0.3rem; +} +.login-panel .desc { + font-size: 0.72rem; + color: var(--muted); + margin-bottom: 2rem; + line-height: 1.6; +} +.twofa-group { + display: none; + margin-bottom: 1.2rem; +} +.twofa-group.visible { + display: block; +} +.twofa-hint { + font-size: 0.68rem; + color: var(--muted); + margin-top: 0.4rem; +} +.btn-login { + width: 100%; + background: var(--accent2); + color: var(--text); + font-family: "DM Mono", monospace; + font-size: 0.78rem; + letter-spacing: 0.1em; + text-transform: uppercase; + padding: 0.8rem 1rem; + border: none; + cursor: pointer; + transition: + background 0.2s, + opacity 0.2s; + margin-top: 0.4rem; +} +.btn-login:hover { + background: var(--accent); +} +.btn-login:active { + opacity: 0.8; +} +.login-error { + font-size: 0.72rem; + color: var(--red); + margin-top: 1rem; + display: none; +} +.login-error.visible { + display: block; +} /* ─── Private dashboard ─── */ -#private-dashboard { display: none; } -#private-dashboard.visible { display: block; } -.repo-list { display: flex; flex-direction: column; gap: 1px; } -.repo-item { background: var(--surface); border: 1px solid var(--border); padding: 1.1rem 1.3rem; display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; transition: background 0.15s; cursor: pointer; text-decoration: none; } -.repo-item:hover { background: var(--surface2); } -.repo-name { font-family: 'Syne', sans-serif; font-size: 0.88rem; font-weight: 700; color: var(--text); margin-bottom: 0.2rem; } -.repo-desc { font-size: 0.7rem; color: var(--muted); } -.repo-badge { font-size: 0.6rem; padding: 0.2rem 0.5rem; border: 1px solid var(--border); color: var(--muted); white-space: nowrap; flex-shrink: 0; } -.repo-badge.private { color: var(--red); border-color: rgba(224, 112, 112, 0.3); } -.repo-badge.active { color: var(--green); border-color: rgba(111, 207, 138, 0.3); } -.logout-btn { margin-top: 1.2rem; font-size: 0.65rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); background: none; border: none; cursor: pointer; font-family: 'DM Mono', monospace; padding: 0; transition: color 0.2s; } -.logout-btn:hover { color: var(--red); } +#private-dashboard { + display: none; +} +#private-dashboard.visible { + display: block; +} +.repo-list { + display: flex; + flex-direction: column; + gap: 1px; +} +.repo-item { + background: var(--surface); + border: 1px solid var(--border); + padding: 1.1rem 1.3rem; + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: 1rem; + transition: background 0.15s; + cursor: pointer; + text-decoration: none; +} +.repo-item:hover { + background: var(--surface2); +} +.repo-name { + font-family: "Syne", sans-serif; + font-size: 0.88rem; + font-weight: 700; + color: var(--text); + margin-bottom: 0.2rem; +} +.repo-desc { + font-size: 0.7rem; + color: var(--muted); +} +.repo-badge { + font-size: 0.6rem; + padding: 0.2rem 0.5rem; + border: 1px solid var(--border); + color: var(--muted); + white-space: nowrap; + flex-shrink: 0; +} +.repo-badge.private { + color: var(--red); + border-color: rgba(224, 112, 112, 0.3); +} +.repo-badge.active { + color: var(--green); + border-color: rgba(111, 207, 138, 0.3); +} +.logout-btn { + margin-top: 1.2rem; + font-size: 0.65rem; + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--muted); + background: none; + border: none; + cursor: pointer; + font-family: "DM Mono", monospace; + padding: 0; + transition: color 0.2s; +} +.logout-btn:hover { + color: var(--red); +} /* ─── Empty state ─── */ -.empty-state { border: 1px dashed var(--border); padding: 3rem 2rem; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 0.8rem; min-height: 280px; } -.empty-icon { font-size: 1.8rem; opacity: 0.2; } -.empty-title { font-family: 'Syne', sans-serif; font-size: 0.9rem; font-weight: 700; color: var(--muted); } -.empty-sub { font-size: 0.7rem; color: var(--muted); opacity: 0.6; max-width: 200px; line-height: 1.6; } +.empty-state { + border: 1px dashed var(--border); + padding: 3rem 2rem; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + gap: 0.8rem; + min-height: 280px; +} +.empty-icon { + font-size: 1.8rem; + opacity: 0.2; +} +.empty-title { + font-family: "Syne", sans-serif; + font-size: 0.9rem; + font-weight: 700; + color: var(--muted); +} +.empty-sub { + font-size: 0.7rem; + color: var(--muted); + opacity: 0.6; + max-width: 200px; + line-height: 1.6; +} /* ─── Two column main ─── */ -main.two-col { padding: 3.5rem 0; display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; animation: fadeUp 0.6s 0.1s ease both; } +main.two-col { + padding: 3.5rem 0; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 3rem; + animation: fadeUp 0.6s 0.1s ease both; +} /* ─── Responsive ─── */ -@media (max-width: 700px) { .cards { grid-template-columns: 1fr 1fr; } } -@media (max-width: 640px) { main.two-col { grid-template-columns: 1fr; gap: 2.5rem; } } -@media (max-width: 560px) { - .nav-grid { grid-template-columns: 1fr; } - .edu-item { grid-template-columns: 1fr; gap: 0.4rem; } - .skill-row { grid-template-columns: 70px 1fr; } - .compare { grid-template-columns: 1fr; } - footer { flex-direction: column; gap: 0.5rem; } +@media (max-width: 700px) { + .cards { + grid-template-columns: 1fr 1fr; + } +} +@media (max-width: 640px) { + main.two-col { + grid-template-columns: 1fr; + gap: 2.5rem; + } +} +@media (max-width: 560px) { + .nav-grid { + grid-template-columns: 1fr; + } + .edu-item { + grid-template-columns: 1fr; + gap: 0.4rem; + } + .skill-row { + grid-template-columns: 70px 1fr; + } + .compare { + grid-template-columns: 1fr; + } + footer { + flex-direction: column; + gap: 0.5rem; + } +} +@media (max-width: 420px) { + .cards { + grid-template-columns: 1fr; + } +} + +/* Add to styles.css */ +.page-nav { + display: flex; + gap: 6px; + flex-wrap: wrap; + margin-bottom: 40px; + width: 100%; +} + +.page-nav a { + font-family: var(--font-mono); + font-size: 11px; + color: var(--muted); + border: 1px solid var(--border); + padding: 5px 12px; + border-radius: 2px; + text-decoration: none; + letter-spacing: 0.04em; + transition: + color 0.18s, + border-color 0.18s, + background 0.18s; + position: relative; + overflow: hidden; +} + +.page-nav a::before { + content: ""; + position: absolute; + inset: 0; + background: var(--accent); + opacity: 0; + transition: opacity 0.18s; +} + +.page-nav a:hover { + color: var(--bg); + border-color: var(--accent); +} +.page-nav a:hover::before { + opacity: 1; +} +.page-nav a span { + position: relative; + z-index: 1; +} +.page-nav a.active { + color: var(--accent); + border-color: var(--accent); +} + +.page-nav { + display: flex; + justify-content: center; /* ← this */ + gap: 6px; + flex-wrap: wrap; + margin-bottom: 40px; + padding-top: 6px; } -@media (max-width: 420px) { .cards { grid-template-columns: 1fr; } } \ No newline at end of file