fix visual bugs + enhance sections + revise project orders
This commit is contained in:
9 files changed
+205
-58
No files matched your search
+7
-7
@@ -93,7 +93,7 @@
|
||||
<li>Python3+</li>
|
||||
<li>Git, Github, GitLab</li>
|
||||
<li>Docker</li>
|
||||
<li>MongoDB & SQL</li>
|
||||
<li>MongoDB & PostgreSQL</li>
|
||||
<li>Windows/Debian based OS</li>
|
||||
<li>Data Structures & Algorithms</li>
|
||||
<li>System Administration</li>
|
||||
@@ -129,15 +129,15 @@
|
||||
<h3 class="title">Highlights</h3>
|
||||
|
||||
<dl>
|
||||
<dt class="text"><b>Red Team Hackathon — 3rd Place</b></dt>
|
||||
<dt class="text"><b>Red Team Hackathon - 3rd Place</b></dt>
|
||||
<dd class="text">
|
||||
Team Cerberus Gate earned a third-place finish at the inaugural Red Team Hackathon for building a working
|
||||
prototype around signal classification and emitter tracking.
|
||||
</dd>
|
||||
|
||||
<dt class="text"><b>Best Dressed Award</b></dt>
|
||||
<dd class="text">
|
||||
Team Cerberus Gate also received the Best Dressed Award during the same hackathon event.
|
||||
<a class="honor-inline-link" href="/entry.html?type=updates&slug=red-team-hackathon-2026">Read the full write-up</a>
|
||||
<div class="honor-subitem">
|
||||
<span class="honor-subitem__label">Additional recognition</span>
|
||||
<p class="honor-subitem__text">Best Dressed Award at the inaugural Red Team Hackathon.</p>
|
||||
</div>
|
||||
</dd>
|
||||
|
||||
<dt class="text"><b>Capstone Project Recognition</b></dt>
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@
|
||||
|
||||
<div class="hero-badges">
|
||||
<span class="badge">BCIT CST Diploma</span>
|
||||
<span class="badge">Backend Systems</span>
|
||||
<span class="badge">C4A President</span>
|
||||
<span class="badge">Hackathon Podium Finiher</span>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -91,6 +91,11 @@
|
||||
<div id="projects-grid" class="content-grid">
|
||||
<p class="loading-state">Loading projects...</p>
|
||||
</div>
|
||||
<div id="projects-toggle-shell" class="projects-toggle-shell" hidden>
|
||||
<button id="projects-toggle" class="projects-toggle" type="button" aria-expanded="false">
|
||||
Show More Projects
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="content-section updates-section">
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"github": "https://github.com/SowinskiBraeden/school-management-api",
|
||||
"demo": null,
|
||||
"featured": true,
|
||||
"order": 2,
|
||||
"order": 6,
|
||||
"tags": [
|
||||
"Go",
|
||||
"API",
|
||||
@@ -51,7 +51,7 @@
|
||||
"github": "https://github.com/LinesMerrill/police-cad",
|
||||
"demo": "https://www.linespolice-cad.com/",
|
||||
"featured": false,
|
||||
"order": 3,
|
||||
"order": 4,
|
||||
"tags": [
|
||||
"Node.js",
|
||||
"Express",
|
||||
@@ -71,7 +71,7 @@
|
||||
"github": "https://github.com/SowinskiBraeden/boker",
|
||||
"demo": null,
|
||||
"featured": true,
|
||||
"order": 4,
|
||||
"order": 2,
|
||||
"tags": [
|
||||
"Python",
|
||||
"Flask",
|
||||
@@ -93,7 +93,7 @@
|
||||
"github": "https://github.com/SowinskiBraeden/dayz-reforger",
|
||||
"demo": null,
|
||||
"featured": true,
|
||||
"order": 4,
|
||||
"order": 3,
|
||||
"tags": [
|
||||
"Node.js",
|
||||
"Discord.js",
|
||||
@@ -114,7 +114,7 @@
|
||||
"github": "https://github.com/SowinskiBraeden/XP-System",
|
||||
"demo": null,
|
||||
"featured": false,
|
||||
"order": 5,
|
||||
"order": 7,
|
||||
"tags": [
|
||||
"Web App",
|
||||
"Education Tech",
|
||||
@@ -133,7 +133,7 @@
|
||||
"github": "https://github.com/SowinskiBraeden/SowinskiBraeden",
|
||||
"demo": null,
|
||||
"featured": false,
|
||||
"order": 6,
|
||||
"order": 5,
|
||||
"tags": [
|
||||
"HTML",
|
||||
"CSS",
|
||||
@@ -183,6 +183,26 @@
|
||||
"BICT"
|
||||
],
|
||||
"path": "./public/content/updates/joined-bcit-computing-club.md"
|
||||
},
|
||||
{
|
||||
"title": "Appointed President of Coding 4 All (C4A)",
|
||||
"slug": "appointed-president-c4a",
|
||||
"type": "updates",
|
||||
"summary": "Appointed to lead Coding 4 All at BCIT, helping guide student events, technical community-building, and collaboration across computing initiatives.",
|
||||
"label": "Update",
|
||||
"date": "2026-05-04",
|
||||
"status": "Leadership",
|
||||
"github": null,
|
||||
"demo": null,
|
||||
"featured": true,
|
||||
"order": 20,
|
||||
"tags": [
|
||||
"Leadership",
|
||||
"BCIT",
|
||||
"Community",
|
||||
"C4A"
|
||||
],
|
||||
"path": "./public/content/updates/appointed-president-c4a.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
+59
-4
@@ -41,9 +41,30 @@
|
||||
section {
|
||||
transition: 0.8s;
|
||||
padding: 24px;
|
||||
background-color: var(--menu-text-bg);
|
||||
border-radius: 18px;
|
||||
border: 1px solid var(--border);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.025)),
|
||||
linear-gradient(135deg, rgba(235, 82, 52, 0.05), transparent 48%),
|
||||
rgba(20, 21, 24, 0.36);
|
||||
border-radius: 22px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
box-shadow:
|
||||
0 18px 44px rgba(0, 0, 0, 0.16),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.12),
|
||||
inset 0 -1px 0 rgba(255, 255, 255, 0.03);
|
||||
backdrop-filter: blur(14px) saturate(120%);
|
||||
-webkit-backdrop-filter: blur(14px) saturate(120%);
|
||||
}
|
||||
|
||||
body.light section {
|
||||
background:
|
||||
linear-gradient(180deg, rgba(255, 255, 255, 0.68), rgba(255, 255, 255, 0.42)),
|
||||
linear-gradient(135deg, rgba(235, 82, 52, 0.04), transparent 48%),
|
||||
rgba(255, 255, 255, 0.34);
|
||||
border-color: rgba(255, 255, 255, 0.52);
|
||||
box-shadow:
|
||||
0 16px 36px rgba(0, 0, 0, 0.06),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.72),
|
||||
inset 0 -1px 0 rgba(255, 255, 255, 0.22);
|
||||
}
|
||||
|
||||
section h3 {
|
||||
@@ -74,10 +95,20 @@ section h3 {
|
||||
}
|
||||
|
||||
.profile-sub {
|
||||
background-color: rgba(0, 0, 0, 0.62);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(0, 0, 0, 0.56), rgba(0, 0, 0, 0.42)),
|
||||
rgba(0, 0, 0, 0.36);
|
||||
padding: 16px;
|
||||
border-radius: 14px;
|
||||
margin-top: 16px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.profile-sub .profile-name,
|
||||
.profile-sub .profile-role,
|
||||
.profile-sub .profile-focus {
|
||||
color: #f4f1ed;
|
||||
}
|
||||
|
||||
.skills-list {
|
||||
@@ -103,6 +134,30 @@ dd {
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.honor-inline-link {
|
||||
display: inline-block;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.honor-subitem {
|
||||
margin-top: 10px;
|
||||
padding-left: 14px;
|
||||
}
|
||||
|
||||
.honor-subitem__label {
|
||||
display: inline-block;
|
||||
font-size: 0.74rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.honor-subitem__text {
|
||||
margin: 4px 0 0;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.honors dl,
|
||||
.skills-list {
|
||||
margin-bottom: 0;
|
||||
|
||||
@@ -84,6 +84,10 @@
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.content-card.is-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.updates-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
@@ -96,6 +100,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100%;
|
||||
scroll-margin-top: 96px;
|
||||
}
|
||||
|
||||
.content-card.featured {
|
||||
@@ -180,6 +185,29 @@
|
||||
filter: brightness(1.04);
|
||||
}
|
||||
|
||||
.projects-toggle-shell {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.projects-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 999px;
|
||||
border: 1px solid var(--border);
|
||||
padding: 12px 18px;
|
||||
font-weight: 600;
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.projects-toggle:hover {
|
||||
border-color: rgba(235, 82, 52, 0.32);
|
||||
color: var(--secondary);
|
||||
}
|
||||
|
||||
.updates-grid .content-card {
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
|
||||
+2
-16
@@ -203,10 +203,8 @@ ul {
|
||||
}
|
||||
|
||||
.logo a img {
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
display: block;
|
||||
pointer-events: none;
|
||||
transform: translate(0, -10%);
|
||||
border-radius: 6pt;
|
||||
margin-inline-end: 8pt;
|
||||
}
|
||||
@@ -315,16 +313,6 @@ ul {
|
||||
box-shadow: var(--shadow);
|
||||
}
|
||||
|
||||
.hero-main .profile,
|
||||
.hero-main .svg-wrapper,
|
||||
.hero-main .hero-description,
|
||||
.hero-main .hero-badges,
|
||||
.hero-main .hero-actions,
|
||||
.hero-main .social-icons {
|
||||
will-change: transform;
|
||||
transition: transform 0.18s ease-out;
|
||||
}
|
||||
|
||||
.hero-badges {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -660,8 +648,6 @@ body.menu-open .overlay * {
|
||||
:root {
|
||||
--hero-shell-spot-x: 50%;
|
||||
--hero-shell-spot-y: 28%;
|
||||
--hero-shell-tilt-x: 0deg;
|
||||
--hero-shell-tilt-y: 0deg;
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -725,7 +711,7 @@ button#theme-toggle {
|
||||
backdrop-filter: blur(22px) saturate(135%);
|
||||
-webkit-backdrop-filter: blur(22px) saturate(135%);
|
||||
isolation: isolate;
|
||||
transform: perspective(1200px) rotateX(var(--hero-shell-tilt-x)) rotateY(var(--hero-shell-tilt-y));
|
||||
transform: none;
|
||||
transition: transform 0.18s ease-out, border-color 0.25s ease-out, box-shadow 0.25s ease-out;
|
||||
}
|
||||
|
||||
|
||||
@@ -78,9 +78,10 @@
|
||||
const createCard = (entry) => {
|
||||
const formattedDate = formatDate(entry.date);
|
||||
const featuredClass = entry.featured ? " featured" : "";
|
||||
const anchorId = entry.slug ? ` id="${escapeHtml(entry.slug)}"` : "";
|
||||
|
||||
return `
|
||||
<article class="content-card${featuredClass}">
|
||||
<article class="content-card${featuredClass}"${anchorId}>
|
||||
<div class="card-meta">
|
||||
<span class="card-kicker">${escapeHtml(entry.label || entry.type)}</span>
|
||||
${formattedDate ? `<span class="card-date">${escapeHtml(formattedDate)}</span>` : ""}
|
||||
@@ -107,11 +108,83 @@
|
||||
container.innerHTML = entries.map(createCard).join("");
|
||||
};
|
||||
|
||||
const initProjectsToggle = (entries) => {
|
||||
const projectsGrid = document.getElementById("projects-grid");
|
||||
const toggleShell = document.getElementById("projects-toggle-shell");
|
||||
const toggleButton = document.getElementById("projects-toggle");
|
||||
const defaultVisibleCount = 6;
|
||||
|
||||
if (!projectsGrid || !toggleShell || !toggleButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cards = Array.from(projectsGrid.querySelectorAll(".content-card"));
|
||||
if (entries.length <= defaultVisibleCount || cards.length <= defaultVisibleCount) {
|
||||
toggleShell.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const setExpandedState = (expanded) => {
|
||||
cards.forEach((card, index) => {
|
||||
card.classList.toggle("is-hidden", !expanded && index >= defaultVisibleCount);
|
||||
});
|
||||
|
||||
toggleButton.textContent = expanded ? "Show Fewer Projects" : "Show More Projects";
|
||||
toggleButton.setAttribute("aria-expanded", String(expanded));
|
||||
};
|
||||
|
||||
toggleShell.hidden = false;
|
||||
setExpandedState(false);
|
||||
|
||||
toggleButton.addEventListener("click", () => {
|
||||
const expanded = toggleButton.getAttribute("aria-expanded") === "true";
|
||||
setExpandedState(!expanded);
|
||||
});
|
||||
};
|
||||
|
||||
const compareByNewestDate = (left, right) => {
|
||||
const leftTime = left.date ? Date.parse(`${left.date}T00:00:00`) : Number.NEGATIVE_INFINITY;
|
||||
const rightTime = right.date ? Date.parse(`${right.date}T00:00:00`) : Number.NEGATIVE_INFINITY;
|
||||
|
||||
if (leftTime !== rightTime) {
|
||||
return rightTime - leftTime;
|
||||
}
|
||||
|
||||
const leftOrder = Number.isFinite(left.order) ? left.order : Number.MAX_SAFE_INTEGER;
|
||||
const rightOrder = Number.isFinite(right.order) ? right.order : Number.MAX_SAFE_INTEGER;
|
||||
|
||||
if (leftOrder !== rightOrder) {
|
||||
return leftOrder - rightOrder;
|
||||
}
|
||||
|
||||
return String(left.title || "").localeCompare(String(right.title || ""));
|
||||
};
|
||||
|
||||
const compareByPriorityOrder = (left, right) => {
|
||||
const leftOrder = Number.isFinite(left.order) ? left.order : Number.MAX_SAFE_INTEGER;
|
||||
const rightOrder = Number.isFinite(right.order) ? right.order : Number.MAX_SAFE_INTEGER;
|
||||
|
||||
if (leftOrder !== rightOrder) {
|
||||
return leftOrder - rightOrder;
|
||||
}
|
||||
|
||||
const leftTime = left.date ? Date.parse(`${left.date}T00:00:00`) : Number.NEGATIVE_INFINITY;
|
||||
const rightTime = right.date ? Date.parse(`${right.date}T00:00:00`) : Number.NEGATIVE_INFINITY;
|
||||
|
||||
if (leftTime !== rightTime) {
|
||||
return rightTime - leftTime;
|
||||
}
|
||||
|
||||
return String(left.title || "").localeCompare(String(right.title || ""));
|
||||
};
|
||||
|
||||
const initListPage = async () => {
|
||||
try {
|
||||
const index = await getIndex();
|
||||
renderSection("projects-grid", index.projects || [], "No projects added yet.");
|
||||
renderSection("updates-grid", index.updates || [], "No updates added yet.");
|
||||
const sortedProjects = [...(index.projects || [])].sort(compareByPriorityOrder);
|
||||
renderSection("projects-grid", sortedProjects, "No projects added yet.");
|
||||
initProjectsToggle(sortedProjects);
|
||||
renderSection("updates-grid", [...(index.updates || [])].sort(compareByNewestDate), "No updates added yet.");
|
||||
} catch (error) {
|
||||
renderSection("projects-grid", [], error.message);
|
||||
renderSection("updates-grid", [], error.message);
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
(function() {
|
||||
const hero = document.querySelector(".hero-main");
|
||||
const heroShell = document.querySelector(".hero-main .hero-shell");
|
||||
const profile = document.querySelector(".hero-main .profile");
|
||||
const title = document.querySelector(".hero-main .svg-wrapper");
|
||||
const descriptions = document.querySelectorAll(
|
||||
".hero-main .hero-description, .hero-main .hero-badges, .hero-main .hero-actions, .hero-main .social-icons"
|
||||
);
|
||||
|
||||
if (!hero || !heroShell || !profile || !title) {
|
||||
if (!heroShell) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -25,10 +19,6 @@
|
||||
|
||||
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
||||
|
||||
const setTransform = (element, x, y) => {
|
||||
element.style.transform = `translate3d(${x}px, ${y}px, 0)`;
|
||||
};
|
||||
|
||||
const animate = () => {
|
||||
currentX += (targetX - currentX) * 0.065;
|
||||
currentY += (targetY - currentY) * 0.065;
|
||||
@@ -51,16 +41,6 @@
|
||||
|
||||
heroShell.style.setProperty("--hero-shell-spot-x", `${50 + currentX * 14}%`);
|
||||
heroShell.style.setProperty("--hero-shell-spot-y", `${28 + currentY * 10}%`);
|
||||
heroShell.style.setProperty("--hero-shell-tilt-x", `${currentY * -2.2}deg`);
|
||||
heroShell.style.setProperty("--hero-shell-tilt-y", `${currentX * 2.6}deg`);
|
||||
|
||||
setTransform(profile, currentX * -4.5, currentY * -4.5);
|
||||
setTransform(title, currentX * 2.2, currentY * 2.2);
|
||||
|
||||
descriptions.forEach((element, index) => {
|
||||
const strength = 1.3 + index * 0.35;
|
||||
setTransform(element, currentX * strength, currentY * strength);
|
||||
});
|
||||
|
||||
requestAnimationFrame(animate);
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user