pull the terminal styling back and add an ASCII backdrop
The first pass applied terminal decoration to everything, which read as costume rather than design. Strip it back to a few deliberate cues and let an animated backdrop carry the character instead: - Drop the prefix glyphs from links, tags, nav items, badges and headings, and restore plain section names in place of snake_case. - Keep one prompt in the hero, the ~/ on the wordmark, ISO dates and status dots; everything else is ordinary type. - Restore depth: acrylic surfaces over soft radial light, 6px radii, and an accent glow on the primary action and status dots. - Draw a dithered ASCII field behind the page. A fixed per-cell dither value decides which cells are lit so coverage stays even, while slow interfering waves move brightness through it. It idles when the tab is hidden and stays still under prefers-reduced-motion. - Remove the nested panel boxes on the projects page and size the entry page to its article column. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8595290318
commit
54c00bf16f
10 files changed
+693
-698
No files matched your search
+6
-4
@@ -73,6 +73,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="js-stop-transition" data-page="about">
|
<body class="js-stop-transition" data-page="about">
|
||||||
|
<canvas id="ascii-bg" aria-hidden="true"></canvas>
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<nav class="nav">
|
<nav class="nav">
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
@@ -134,7 +135,7 @@
|
|||||||
<main class="container page-shell">
|
<main class="container page-shell">
|
||||||
<div class="left-content">
|
<div class="left-content">
|
||||||
<section id="profile">
|
<section id="profile">
|
||||||
<h2 class="panel__bar">profile</h2>
|
<h2 class="panel__bar">Profile</h2>
|
||||||
<div class="panel__body">
|
<div class="panel__body">
|
||||||
<img src="https://avatars.githubusercontent.com/u/48144618" class="profile" alt="Braeden Sowinski profile photo">
|
<img src="https://avatars.githubusercontent.com/u/48144618" class="profile" alt="Braeden Sowinski profile photo">
|
||||||
<div class="profile-sub">
|
<div class="profile-sub">
|
||||||
@@ -149,7 +150,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="skills">
|
<section id="skills">
|
||||||
<h2 class="panel__bar">skills</h2>
|
<h2 class="panel__bar">Skills</h2>
|
||||||
<div class="panel__body">
|
<div class="panel__body">
|
||||||
<ul class="text skills-list">
|
<ul class="text skills-list">
|
||||||
<li>Java, C, Go, OCaml</li>
|
<li>Java, C, Go, OCaml</li>
|
||||||
@@ -170,7 +171,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section class="about" id="about">
|
<section class="about" id="about">
|
||||||
<h2 class="panel__bar title">about_me</h2>
|
<h2 class="panel__bar title">About</h2>
|
||||||
<div class="panel__body">
|
<div class="panel__body">
|
||||||
<p class="text">
|
<p class="text">
|
||||||
I'm Braeden Sowinski, a Computer Systems Technology student at
|
I'm Braeden Sowinski, a Computer Systems Technology student at
|
||||||
@@ -200,7 +201,7 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="honors" id="honors">
|
<section class="honors" id="honors">
|
||||||
<h2 class="panel__bar title">highlights</h2>
|
<h2 class="panel__bar title">Highlights</h2>
|
||||||
<div class="panel__body">
|
<div class="panel__body">
|
||||||
<dl>
|
<dl>
|
||||||
<dt class="text"><b>Red Team Hackathon - 3rd Place</b></dt>
|
<dt class="text"><b>Red Team Hackathon - 3rd Place</b></dt>
|
||||||
@@ -259,6 +260,7 @@
|
|||||||
|
|
||||||
<script src="./public/scripts/mobile.js"></script>
|
<script src="./public/scripts/mobile.js"></script>
|
||||||
<script src="./public/scripts/theme.js"></script>
|
<script src="./public/scripts/theme.js"></script>
|
||||||
|
<script src="./public/scripts/ascii-bg.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -52,6 +52,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="js-stop-transition" data-page="projects">
|
<body class="js-stop-transition" data-page="projects">
|
||||||
|
<canvas id="ascii-bg" aria-hidden="true"></canvas>
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<nav class="nav">
|
<nav class="nav">
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
@@ -118,6 +119,7 @@
|
|||||||
|
|
||||||
<script src="./public/scripts/mobile.js"></script>
|
<script src="./public/scripts/mobile.js"></script>
|
||||||
<script src="./public/scripts/theme.js"></script>
|
<script src="./public/scripts/theme.js"></script>
|
||||||
|
<script src="./public/scripts/ascii-bg.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||||
<script src="./public/scripts/content.js"></script>
|
<script src="./public/scripts/content.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
+15
-18
@@ -110,6 +110,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="js-stop-transition" data-page="home">
|
<body class="js-stop-transition" data-page="home">
|
||||||
|
<canvas id="ascii-bg" aria-hidden="true"></canvas>
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<nav class="nav">
|
<nav class="nav">
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
@@ -171,42 +172,39 @@
|
|||||||
<main class="main">
|
<main class="main">
|
||||||
<section class="term">
|
<section class="term">
|
||||||
<div class="term__bar">
|
<div class="term__bar">
|
||||||
<span class="term__title">braeden@sowinski.dev: <b>~</b></span>
|
<span class="term__dot"></span>
|
||||||
<span class="term__dots">─ □ ✕</span>
|
<span class="term__dot"></span>
|
||||||
|
<span class="term__dot"></span>
|
||||||
|
<span class="term__title">braeden@sowinski.dev</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="term__body">
|
<div class="term__body">
|
||||||
<div class="term__avatar-wrap">
|
<div class="term__avatar-wrap">
|
||||||
<img src="https://avatars.githubusercontent.com/u/48144618" class="term__avatar" alt="Braeden Sowinski profile photo">
|
<img src="https://avatars.githubusercontent.com/u/48144618" class="term__avatar" alt="Braeden Sowinski profile photo">
|
||||||
<span class="term__avatar-caption">./braeden.png</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="term__stream">
|
<div class="term__stream">
|
||||||
<p class="cmd">whoami</p>
|
<p class="cmd"><span class="cmd__text">whoami</span><span class="caret"></span></p>
|
||||||
<h1 class="name line">Braeden Sowinski</h1>
|
|
||||||
|
|
||||||
<p class="cmd">cat ./role</p>
|
<h1 class="name">Braeden Sowinski</h1>
|
||||||
<p class="des line">
|
<p class="des">
|
||||||
Software Engineer & Systems Admin | CST Student @ BCIT
|
Software Engineer & Systems Admin | CST Student @ BCIT
|
||||||
</p>
|
</p>
|
||||||
<p class="des line hero-description-secondary">
|
<p class="des hero-description-secondary">
|
||||||
Backend systems, APIs, data-driven software, and low-level problem solving
|
Backend systems, APIs, data-driven software, and low-level problem solving
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="cmd">ls ./highlights</p>
|
<div class="hero-badges">
|
||||||
<div class="hero-badges line">
|
|
||||||
<span class="badge">BCIT CST Diploma</span>
|
<span class="badge">BCIT CST Diploma</span>
|
||||||
<span class="badge">C4A President</span>
|
<span class="badge">C4A President</span>
|
||||||
<span class="badge">Hackathon Podium Finisher</span>
|
<span class="badge">Hackathon Podium Finisher</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="cmd">ls ./pages</p>
|
<div class="hero-actions">
|
||||||
<div class="hero-actions line">
|
<a class="button button-primary" href="./projects.html">Projects</a>
|
||||||
<a class="button button-primary" href="./projects.html">projects</a>
|
<a class="button button-secondary" href="./about.html">About</a>
|
||||||
<a class="button button-secondary" href="./about.html">about</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="cmd">cat ./contact</p>
|
<div class="social-icons">
|
||||||
<div class="social-icons line">
|
|
||||||
<a class="icon" href="https://www.linkedin.com/in/SowinskiBraeden" target="_blank" rel="noopener noreferrer me"
|
<a class="icon" href="https://www.linkedin.com/in/SowinskiBraeden" target="_blank" rel="noopener noreferrer me"
|
||||||
title="LinkedIn">
|
title="LinkedIn">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-linkedin"
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-linkedin"
|
||||||
@@ -229,8 +227,6 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="prompt-end">$ <span class="caret"></span></p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -238,6 +234,7 @@
|
|||||||
|
|
||||||
<script src="./public/scripts/mobile.js"></script>
|
<script src="./public/scripts/mobile.js"></script>
|
||||||
<script src="./public/scripts/theme.js"></script>
|
<script src="./public/scripts/theme.js"></script>
|
||||||
|
<script src="./public/scripts/ascii-bg.js"></script>
|
||||||
<script src="./public/scripts/hero-effects.js"></script>
|
<script src="./public/scripts/hero-effects.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
+6
-5
@@ -49,6 +49,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="js-stop-transition" data-page="projects">
|
<body class="js-stop-transition" data-page="projects">
|
||||||
|
<canvas id="ascii-bg" aria-hidden="true"></canvas>
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<nav class="nav">
|
<nav class="nav">
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
@@ -109,7 +110,6 @@
|
|||||||
|
|
||||||
<main class="projects-page page-shell">
|
<main class="projects-page page-shell">
|
||||||
<section class="projects-hero">
|
<section class="projects-hero">
|
||||||
<p class="cmd">ls ~/projects --all</p>
|
|
||||||
<h1>Braeden Sowinski projects, milestones, and technical writeups.</h1>
|
<h1>Braeden Sowinski projects, milestones, and technical writeups.</h1>
|
||||||
<p class="projects-intro">
|
<p class="projects-intro">
|
||||||
A collection of backend, infrastructure, data-driven, and full-stack projects,
|
A collection of backend, infrastructure, data-driven, and full-stack projects,
|
||||||
@@ -119,10 +119,10 @@
|
|||||||
|
|
||||||
<section class="content-section">
|
<section class="content-section">
|
||||||
<div class="section-heading">
|
<div class="section-heading">
|
||||||
<h2>selected_projects</h2>
|
<h2>Selected Projects</h2>
|
||||||
<div class="section-heading__right">
|
<div class="section-heading__right">
|
||||||
<span id="projects-count" class="section-count"></span>
|
<span id="projects-count" class="section-count"></span>
|
||||||
<a class="section-link" href="https://git.sowinski.dev/SowinskiBraeden" target="_blank" rel="noopener noreferrer">gitea</a>
|
<a class="section-link" href="https://git.sowinski.dev/SowinskiBraeden" target="_blank" rel="noopener noreferrer">Gitea</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="projects-grid" class="content-grid">
|
<div id="projects-grid" class="content-grid">
|
||||||
@@ -130,14 +130,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="projects-toggle-shell" class="projects-toggle-shell" hidden>
|
<div id="projects-toggle-shell" class="projects-toggle-shell" hidden>
|
||||||
<button id="projects-toggle" class="projects-toggle" type="button" aria-expanded="false">
|
<button id="projects-toggle" class="projects-toggle" type="button" aria-expanded="false">
|
||||||
show more projects
|
Show more projects
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="content-section updates-section">
|
<section class="content-section updates-section">
|
||||||
<div class="section-heading">
|
<div class="section-heading">
|
||||||
<h2>updates_and_achievements</h2>
|
<h2>Updates & Achievements</h2>
|
||||||
<div class="section-heading__right">
|
<div class="section-heading__right">
|
||||||
<span id="updates-count" class="section-count"></span>
|
<span id="updates-count" class="section-count"></span>
|
||||||
</div>
|
</div>
|
||||||
@@ -177,6 +177,7 @@
|
|||||||
|
|
||||||
<script src="./public/scripts/mobile.js"></script>
|
<script src="./public/scripts/mobile.js"></script>
|
||||||
<script src="./public/scripts/theme.js"></script>
|
<script src="./public/scripts/theme.js"></script>
|
||||||
|
<script src="./public/scripts/ascii-bg.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||||
<script src="./public/scripts/content.js"></script>
|
<script src="./public/scripts/content.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
+148
-172
@@ -1,243 +1,219 @@
|
|||||||
.container {
|
.container {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(260px, 300px) repeat(3, 1fr);
|
grid-template-columns: minmax(260px, 310px) repeat(3, 1fr);
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"pro about about about"
|
"pro about about about"
|
||||||
"pro other other other"
|
"pro other other other"
|
||||||
"footer footer footer footer";
|
"footer footer footer footer";
|
||||||
grid-template-rows: auto 1fr auto;
|
grid-template-rows: auto 1fr auto;
|
||||||
gap: 18px;
|
gap: 20px;
|
||||||
padding-top: 22px;
|
padding-top: 40px;
|
||||||
min-height: calc(100vh - 120px);
|
min-height: calc(100vh - 140px);
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.left-content {
|
.left-content {
|
||||||
grid-area: pro;
|
grid-area: pro;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 18px;
|
gap: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.about {
|
.about {
|
||||||
grid-area: about;
|
grid-area: about;
|
||||||
}
|
}
|
||||||
|
|
||||||
.honors {
|
.honors {
|
||||||
grid-area: other;
|
grid-area: other;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
grid-area: footer;
|
grid-area: footer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------- TUI panels */
|
|
||||||
|
|
||||||
section {
|
section {
|
||||||
padding: 0;
|
padding: 24px;
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
border: 1px solid var(--border);
|
backdrop-filter: blur(16px) saturate(130%);
|
||||||
display: flex;
|
-webkit-backdrop-filter: blur(16px) saturate(130%);
|
||||||
flex-direction: column;
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel__bar {
|
.panel__bar {
|
||||||
margin: 0;
|
margin: 0 0 16px;
|
||||||
padding: 6px 12px;
|
font-size: 0.95rem;
|
||||||
background: var(--bar);
|
font-weight: 700;
|
||||||
border-bottom: 1px solid var(--border);
|
color: var(--bright);
|
||||||
font-size: 0.92rem;
|
|
||||||
font-weight: 700;
|
|
||||||
letter-spacing: 0.02em;
|
|
||||||
color: var(--bright);
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel__bar::before {
|
|
||||||
content: "▸ ";
|
|
||||||
color: var(--secondary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel__body {
|
.panel__body {
|
||||||
padding: 16px;
|
flex: 1;
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#skills {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#profile .panel__body {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#profile img.profile {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 180px;
|
|
||||||
aspect-ratio: 1;
|
|
||||||
object-fit: cover;
|
|
||||||
border: 1px solid var(--border-strong);
|
|
||||||
border-radius: 0;
|
|
||||||
filter: grayscale(0.3) contrast(1.03);
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-sub {
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-name {
|
|
||||||
margin: 0 0 4px;
|
|
||||||
font-size: 1.15rem;
|
|
||||||
line-height: 1.25;
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-role,
|
|
||||||
.profile-focus {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 0.82rem;
|
|
||||||
color: var(--primary);
|
|
||||||
padding-left: 14px;
|
|
||||||
text-indent: -14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-focus {
|
|
||||||
margin-top: 6px;
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-role::before,
|
|
||||||
.profile-focus::before {
|
|
||||||
content: "#\00a0";
|
|
||||||
color: var(--border-strong);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------- contents */
|
|
||||||
|
|
||||||
.skills-list {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skills-list li {
|
|
||||||
margin-bottom: 4px;
|
|
||||||
color: var(--primary);
|
|
||||||
padding-left: 14px;
|
|
||||||
text-indent: -14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skills-list li::before {
|
|
||||||
content: "-\00a0";
|
|
||||||
color: var(--secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.text {
|
|
||||||
font-weight: 400;
|
|
||||||
margin: 0 0 14px;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.about .panel__body,
|
.about .panel__body,
|
||||||
.honors .panel__body {
|
.honors .panel__body {
|
||||||
max-width: 92ch;
|
max-width: 86ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
#skills {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#profile .panel__body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#profile img.profile {
|
||||||
|
width: 100%;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
border: 1px solid var(--border-strong);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-sub {
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-name {
|
||||||
|
margin: 0 0 8px;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-role,
|
||||||
|
.profile-focus {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.84rem;
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-focus {
|
||||||
|
margin-top: 8px;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------- content */
|
||||||
|
|
||||||
|
.skills-list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.86rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skills-list li {
|
||||||
|
color: var(--primary);
|
||||||
|
padding-left: 16px;
|
||||||
|
text-indent: -16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skills-list li::before {
|
||||||
|
content: "—\00a0";
|
||||||
|
color: var(--secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-weight: 400;
|
||||||
|
margin: 0 0 16px;
|
||||||
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.about .text:last-child {
|
.about .text:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.about .text,
|
.about .text,
|
||||||
.honors .text {
|
.honors .text {
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.honors dl {
|
.honors dl {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dt {
|
dt {
|
||||||
margin-top: 16px;
|
margin-top: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
dt:first-of-type {
|
dt:first-of-type {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dt.text {
|
dt.text {
|
||||||
margin-bottom: 4px;
|
margin-bottom: 6px;
|
||||||
color: var(--bright);
|
color: var(--bright);
|
||||||
}
|
|
||||||
|
|
||||||
dt.text b::before {
|
|
||||||
content: "▸ ";
|
|
||||||
color: var(--secondary);
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dd {
|
dd {
|
||||||
margin-left: 14px;
|
margin-left: 0;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
border-left: 1px solid var(--border);
|
|
||||||
padding-left: 12px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dd.text {
|
dd.text {
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.honor-inline-link {
|
.honor-inline-link {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-top: 6px;
|
margin-top: 8px;
|
||||||
font-size: 0.82rem;
|
font-size: 0.84rem;
|
||||||
color: var(--secondary);
|
color: var(--secondary);
|
||||||
}
|
|
||||||
|
|
||||||
.honor-inline-link::before {
|
|
||||||
content: "> ";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.honor-subitem {
|
.honor-subitem {
|
||||||
margin-top: 10px;
|
margin-top: 12px;
|
||||||
padding-left: 12px;
|
padding-left: 14px;
|
||||||
border-left: 1px solid var(--border);
|
border-left: 1px solid var(--border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.honor-subitem__label {
|
.honor-subitem__label {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 0.68rem;
|
font-size: 0.7rem;
|
||||||
font-weight: 700;
|
letter-spacing: 0.12em;
|
||||||
letter-spacing: 0.1em;
|
text-transform: uppercase;
|
||||||
text-transform: uppercase;
|
color: var(--secondary);
|
||||||
color: var(--secondary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.honor-subitem__text {
|
.honor-subitem__text {
|
||||||
margin: 2px 0 0;
|
margin: 4px 0 0;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
font-size: 0.85rem;
|
font-size: 0.86rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
abbr {
|
abbr {
|
||||||
text-decoration: underline dotted var(--border-strong);
|
text-decoration: underline dotted var(--border-strong);
|
||||||
cursor: help;
|
cursor: help;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 920px) {
|
@media only screen and (max-width: 920px) {
|
||||||
.container {
|
.container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: auto;
|
min-height: auto;
|
||||||
gap: 14px;
|
gap: 16px;
|
||||||
}
|
padding-top: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
#profile img.profile {
|
section {
|
||||||
max-width: 140px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#profile img.profile {
|
||||||
|
max-width: 160px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+136
-235
@@ -1,108 +1,82 @@
|
|||||||
.projects-page,
|
.projects-page,
|
||||||
.entry-page {
|
.entry-page {
|
||||||
padding-top: 22px;
|
padding-top: 40px;
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------- TUI panels */
|
|
||||||
|
|
||||||
.projects-hero,
|
|
||||||
.entry-shell,
|
|
||||||
.content-section {
|
|
||||||
background: var(--surface);
|
|
||||||
border: 1px solid var(--border);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The page header sits on the background; only cards get a surface. */
|
||||||
.projects-hero {
|
.projects-hero {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 40px;
|
||||||
padding: 20px;
|
max-width: 760px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.projects-hero h1,
|
.projects-hero h1,
|
||||||
.entry-title {
|
.entry-title {
|
||||||
font-size: clamp(1.3rem, 2.6vw, 1.75rem);
|
font-size: clamp(1.5rem, 3vw, 2.1rem);
|
||||||
line-height: 1.25;
|
line-height: 1.2;
|
||||||
margin: 8px 0 10px;
|
margin: 0 0 14px;
|
||||||
max-width: 860px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.projects-intro,
|
.projects-intro,
|
||||||
.entry-summary {
|
.entry-summary {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
max-width: 760px;
|
max-width: 720px;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
font-size: 0.92rem;
|
font-size: 0.92rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.eyebrow {
|
.eyebrow {
|
||||||
margin: 0;
|
margin: 0 0 10px;
|
||||||
font-size: 11px;
|
font-size: 12px;
|
||||||
letter-spacing: 0.16em;
|
letter-spacing: 0.18em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--secondary);
|
color: var(--secondary);
|
||||||
font-weight: 700;
|
font-weight: 500;
|
||||||
}
|
|
||||||
|
|
||||||
.eyebrow::before {
|
|
||||||
content: "// ";
|
|
||||||
color: var(--border-strong);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-section {
|
.content-section {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 44px;
|
||||||
padding: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Panel title bar, like a window chrome strip in a TUI. */
|
|
||||||
.section-heading {
|
.section-heading {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: baseline;
|
||||||
gap: 12px;
|
gap: 14px;
|
||||||
margin: 0;
|
margin: 0 0 18px;
|
||||||
padding: 6px 12px;
|
padding-bottom: 10px;
|
||||||
background: var(--bar);
|
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-heading h2 {
|
.section-heading h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 0.95rem;
|
font-size: 1.05rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: 0.02em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-heading h2::before {
|
.section-heading__right {
|
||||||
content: "▸ ";
|
display: flex;
|
||||||
color: var(--secondary);
|
align-items: baseline;
|
||||||
|
gap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-heading .eyebrow {
|
.section-count {
|
||||||
display: none;
|
font-size: 12px;
|
||||||
|
color: var(--muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-link {
|
.section-link {
|
||||||
font-size: 12px;
|
font-size: 13px;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
border: 1px solid var(--border);
|
|
||||||
padding: 1px 8px;
|
|
||||||
background: var(--surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-link::before {
|
|
||||||
content: "> ";
|
|
||||||
color: var(--secondary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-link:hover {
|
.section-link:hover {
|
||||||
color: var(--bright);
|
color: var(--secondary);
|
||||||
border-color: var(--secondary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-grid {
|
.content-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
gap: 14px;
|
gap: 16px;
|
||||||
padding: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.updates-grid {
|
.updates-grid {
|
||||||
@@ -113,92 +87,91 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ TUI cards */
|
/* ---------------------------------------------------------------- cards */
|
||||||
|
|
||||||
.content-card {
|
.content-card {
|
||||||
padding: 0;
|
padding: 20px;
|
||||||
background: var(--surface-alt);
|
background: var(--surface);
|
||||||
|
backdrop-filter: blur(16px) saturate(130%);
|
||||||
|
-webkit-backdrop-filter: blur(16px) saturate(130%);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
scroll-margin-top: 80px;
|
scroll-margin-top: 90px;
|
||||||
transition:
|
transition:
|
||||||
border-color 0.12s linear,
|
border-color 0.2s ease,
|
||||||
background-color 0.12s linear;
|
box-shadow 0.2s ease,
|
||||||
|
transform 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-card:hover {
|
.content-card:hover {
|
||||||
border-color: var(--border-strong);
|
border-color: var(--border-strong);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-card.featured {
|
.content-card.featured {
|
||||||
border-color: rgba(235, 82, 52, 0.42);
|
border-color: rgba(235, 82, 52, 0.28);
|
||||||
}
|
}
|
||||||
|
|
||||||
body.light .content-card.featured {
|
body.light .content-card.featured {
|
||||||
border-color: rgba(200, 64, 31, 0.42);
|
border-color: rgba(200, 64, 31, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-meta {
|
.card-meta {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 12px;
|
||||||
margin: 0;
|
margin: 0 0 14px;
|
||||||
padding: 4px 12px;
|
font-size: 11.5px;
|
||||||
background: var(--bar);
|
color: var(--muted);
|
||||||
border-bottom: 1px solid var(--border);
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-kicker {
|
.card-kicker {
|
||||||
color: var(--secondary);
|
color: var(--secondary);
|
||||||
font-weight: 700;
|
letter-spacing: 0.1em;
|
||||||
letter-spacing: 0.08em;
|
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
font-size: 11px;
|
||||||
|
|
||||||
.card-date {
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-status {
|
.card-status {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
color: var(--muted);
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 6px;
|
gap: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-status::before {
|
.card-status::before {
|
||||||
content: "";
|
content: "";
|
||||||
width: 6px;
|
width: 5px;
|
||||||
height: 6px;
|
height: 5px;
|
||||||
|
border-radius: 50%;
|
||||||
background: var(--muted);
|
background: var(--muted);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-status[data-state="active"]::before {
|
.card-status[data-state="active"]::before {
|
||||||
background: var(--ok);
|
background: var(--ok);
|
||||||
|
box-shadow: 0 0 8px rgba(127, 176, 105, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-status[data-state="attention"]::before {
|
.card-status[data-state="attention"]::before {
|
||||||
background: var(--secondary);
|
background: var(--secondary);
|
||||||
|
box-shadow: 0 0 8px rgba(235, 82, 52, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-card h3 {
|
.content-card h3 {
|
||||||
margin: 0;
|
margin: 0 0 10px;
|
||||||
padding: 12px 12px 0;
|
font-size: 1.1rem;
|
||||||
font-size: 1.05rem;
|
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-summary {
|
.card-summary {
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
margin: 0;
|
margin: 0 0 16px;
|
||||||
padding: 8px 12px 12px;
|
font-size: 0.86rem;
|
||||||
font-size: 0.85rem;
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,40 +182,29 @@ body.light .content-card.featured {
|
|||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag-list {
|
|
||||||
padding: 0 12px 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag,
|
.tag,
|
||||||
.entry-tag {
|
.entry-tag {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
text-transform: lowercase;
|
padding: 2px 8px;
|
||||||
padding: 0 6px;
|
border-radius: var(--radius);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
background: transparent;
|
background: var(--bar);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag::before,
|
|
||||||
.entry-tag::before {
|
|
||||||
content: "#";
|
|
||||||
color: var(--border-strong);
|
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-links,
|
.card-links,
|
||||||
.entry-links {
|
.entry-links {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 8px;
|
gap: 18px;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-links {
|
.card-links {
|
||||||
margin-top: auto;
|
margin-top: 18px;
|
||||||
padding: 10px 12px;
|
padding-top: 16px;
|
||||||
border-top: 1px solid var(--border);
|
border-top: 1px solid var(--border);
|
||||||
background: var(--surface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-link,
|
.card-link,
|
||||||
@@ -250,48 +212,25 @@ body.light .content-card.featured {
|
|||||||
.inline-button {
|
.inline-button {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border: 1px solid var(--border);
|
color: var(--muted);
|
||||||
background: transparent;
|
font-size: 13px;
|
||||||
color: var(--primary);
|
|
||||||
padding: 2px 9px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-link::before,
|
|
||||||
.entry-back::before,
|
|
||||||
.inline-button::before {
|
|
||||||
content: ">\00a0";
|
|
||||||
color: var(--secondary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-link:hover,
|
.card-link:hover,
|
||||||
.entry-back:hover,
|
.entry-back:hover,
|
||||||
.inline-button:hover {
|
.inline-button:hover {
|
||||||
color: var(--bright);
|
color: var(--secondary);
|
||||||
border-color: var(--secondary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-link-primary,
|
.card-link-primary,
|
||||||
.inline-button-primary {
|
.inline-button-primary {
|
||||||
border-color: var(--border-strong);
|
color: var(--primary);
|
||||||
color: var(--bright);
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-link-primary:hover,
|
|
||||||
.inline-button-primary:hover {
|
|
||||||
background: var(--secondary);
|
|
||||||
color: #0c0d10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-link-primary:hover::before,
|
|
||||||
.inline-button-primary:hover::before {
|
|
||||||
color: #0c0d10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.projects-toggle-shell {
|
.projects-toggle-shell {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0 16px 16px;
|
margin-top: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.projects-toggle {
|
.projects-toggle {
|
||||||
@@ -299,110 +238,87 @@ body.light .content-card.featured {
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
padding: 4px 14px;
|
border-radius: var(--radius);
|
||||||
font-size: 12px;
|
padding: 7px 18px;
|
||||||
background: var(--surface-alt);
|
font-size: 13px;
|
||||||
|
background: var(--bar);
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition:
|
transition:
|
||||||
color 0.12s linear,
|
color 0.18s ease,
|
||||||
border-color 0.12s linear;
|
border-color 0.18s ease;
|
||||||
}
|
|
||||||
|
|
||||||
.projects-toggle::before {
|
|
||||||
content: "+\00a0";
|
|
||||||
color: var(--secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.projects-toggle[aria-expanded="true"]::before {
|
|
||||||
content: "-\00a0";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.projects-toggle:hover {
|
.projects-toggle:hover {
|
||||||
color: var(--bright);
|
color: var(--bright);
|
||||||
border-color: var(--secondary);
|
border-color: var(--border-strong);
|
||||||
}
|
|
||||||
|
|
||||||
.updates-grid .content-card {
|
|
||||||
background: var(--surface-alt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.site-footer {
|
.site-footer {
|
||||||
margin-bottom: 22px;
|
margin-bottom: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ entry page */
|
/* ----------------------------------------------------------- entry page */
|
||||||
|
|
||||||
|
/* The article column sets the page width, so the card hugs its text. */
|
||||||
|
.entry-page.page-shell {
|
||||||
|
width: min(880px, calc(100% - 32px));
|
||||||
|
}
|
||||||
|
|
||||||
.entry-shell {
|
.entry-shell {
|
||||||
padding: 20px 22px 26px;
|
background: var(--surface);
|
||||||
|
backdrop-filter: blur(18px) saturate(135%);
|
||||||
|
-webkit-backdrop-filter: blur(18px) saturate(135%);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
box-shadow: var(--shadow);
|
||||||
|
padding: 32px 34px 38px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-header {
|
.entry-header {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-back {
|
.entry-back {
|
||||||
margin-bottom: 18px;
|
margin-bottom: 26px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-meta {
|
.entry-meta {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 10px;
|
|
||||||
margin-bottom: 14px;
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entry-pill {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 1px 8px;
|
gap: 14px;
|
||||||
border: 1px solid var(--border);
|
margin-bottom: 14px;
|
||||||
|
font-size: 11.5px;
|
||||||
|
color: var(--muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-pill-primary {
|
.entry-pill-primary {
|
||||||
color: var(--secondary);
|
color: var(--secondary);
|
||||||
border-color: rgba(235, 82, 52, 0.4);
|
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.08em;
|
letter-spacing: 0.1em;
|
||||||
font-weight: 700;
|
font-size: 11px;
|
||||||
}
|
|
||||||
|
|
||||||
.entry-pill-secondary {
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-links {
|
.entry-links {
|
||||||
margin-top: 16px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-content {
|
.entry-content {
|
||||||
margin-top: 24px;
|
margin-top: 30px;
|
||||||
padding-top: 20px;
|
padding-top: 26px;
|
||||||
border-top: 1px solid var(--border);
|
border-top: 1px solid var(--border);
|
||||||
font-size: 0.92rem;
|
font-size: 0.92rem;
|
||||||
max-width: 88ch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-content h1,
|
.entry-content h1,
|
||||||
.entry-content h2,
|
.entry-content h2,
|
||||||
.entry-content h3,
|
.entry-content h3,
|
||||||
.entry-content h4 {
|
.entry-content h4 {
|
||||||
margin-top: 26px;
|
margin-top: 32px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 10px;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
font-size: 1rem;
|
font-size: 1.02rem;
|
||||||
}
|
|
||||||
|
|
||||||
.entry-content h2::before,
|
|
||||||
.entry-content h3::before {
|
|
||||||
content: "## ";
|
|
||||||
color: var(--secondary);
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entry-content h3::before {
|
|
||||||
content: "### ";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-content p,
|
.entry-content p,
|
||||||
@@ -415,24 +331,17 @@ body.light .content-card.featured {
|
|||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-content ul {
|
.entry-content li {
|
||||||
list-style: none;
|
margin-bottom: 4px;
|
||||||
padding-left: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-content ul li {
|
.entry-content li::marker {
|
||||||
padding-left: 14px;
|
|
||||||
text-indent: -14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entry-content ul li::before {
|
|
||||||
content: "-\00a0";
|
|
||||||
color: var(--secondary);
|
color: var(--secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-content a {
|
.entry-content a {
|
||||||
color: var(--secondary);
|
color: var(--secondary);
|
||||||
border-bottom: 1px solid rgba(235, 82, 52, 0.35);
|
border-bottom: 1px solid rgba(235, 82, 52, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-content a:hover {
|
.entry-content a:hover {
|
||||||
@@ -440,28 +349,34 @@ body.light .content-card.featured {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.entry-content blockquote {
|
.entry-content blockquote {
|
||||||
margin: 16px 0;
|
margin: 18px 0;
|
||||||
padding: 10px 14px;
|
padding: 12px 16px;
|
||||||
border-left: 2px solid var(--secondary);
|
border-left: 2px solid var(--secondary);
|
||||||
background: var(--surface-alt);
|
background: var(--bar);
|
||||||
|
border-radius: 0 var(--radius) var(--radius) 0;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-content code {
|
.entry-content code {
|
||||||
background: var(--bar);
|
background: var(--bar);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
padding: 0 4px;
|
border-radius: 3px;
|
||||||
|
padding: 1px 5px;
|
||||||
font-size: 0.86rem;
|
font-size: 0.86rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-content pre {
|
.entry-content pre {
|
||||||
padding: 14px;
|
padding: 16px 18px;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
background: var(--bar);
|
background: rgba(0, 0, 0, 0.22);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-left: 2px solid var(--secondary);
|
border-radius: var(--radius);
|
||||||
font-size: 0.84rem;
|
font-size: 0.84rem;
|
||||||
line-height: 1.5;
|
line-height: 1.55;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.light .entry-content pre {
|
||||||
|
background: rgba(0, 0, 0, 0.05);
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-content pre code {
|
.entry-content pre code {
|
||||||
@@ -472,18 +387,25 @@ body.light .content-card.featured {
|
|||||||
|
|
||||||
.entry-empty {
|
.entry-empty {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 36px 18px;
|
padding: 40px 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 860px) {
|
@media only screen and (max-width: 860px) {
|
||||||
.projects-hero,
|
.projects-page,
|
||||||
.entry-shell {
|
.entry-page {
|
||||||
padding: 18px;
|
padding-top: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-grid {
|
.entry-page.page-shell {
|
||||||
padding: 12px;
|
width: min(880px, calc(100% - 20px));
|
||||||
gap: 12px;
|
}
|
||||||
|
|
||||||
|
.entry-shell {
|
||||||
|
padding: 22px 20px 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-section {
|
||||||
|
margin-bottom: 34px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-heading {
|
.section-heading {
|
||||||
@@ -492,24 +414,3 @@ body.light .content-card.featured {
|
|||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-heading__right {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-count {
|
|
||||||
font-size: 11px;
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-count::before {
|
|
||||||
content: "[ ";
|
|
||||||
color: var(--border-strong);
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-count::after {
|
|
||||||
content: " ]";
|
|
||||||
color: var(--border-strong);
|
|
||||||
}
|
|
||||||
+179
-248
@@ -1,40 +1,47 @@
|
|||||||
@import url("https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap");
|
@import url("https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap");
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--theme: #0c0d10;
|
--theme: #0b0c0f;
|
||||||
--surface: #111318;
|
--surface: rgba(21, 23, 28, 0.58);
|
||||||
--surface-alt: #15171d;
|
--surface-raised: rgba(28, 31, 37, 0.62);
|
||||||
--bar: #16181e;
|
--bar: rgba(255, 255, 255, 0.035);
|
||||||
--primary: #c9cdd6;
|
--primary: #cbcfd8;
|
||||||
--bright: #eef1f6;
|
--bright: #f1f3f7;
|
||||||
--secondary: #eb5234;
|
--secondary: #eb5234;
|
||||||
--accent: #ff005a;
|
--accent: #ff005a;
|
||||||
--ok: #7fb069;
|
--ok: #7fb069;
|
||||||
--muted: #767d8a;
|
--muted: #7b8290;
|
||||||
--border: #262a33;
|
--border: rgba(255, 255, 255, 0.09);
|
||||||
--border-strong: #3a404c;
|
--border-strong: rgba(255, 255, 255, 0.18);
|
||||||
--grid: rgba(255, 255, 255, 0.022);
|
--glow: rgba(235, 82, 52, 0.16);
|
||||||
--selection: rgba(235, 82, 52, 0.28);
|
--shadow: 0 18px 50px rgba(0, 0, 0, 0.34);
|
||||||
|
--selection: rgba(235, 82, 52, 0.3);
|
||||||
|
--ascii-base: #8e97a8;
|
||||||
|
--ascii-accent: #eb5234;
|
||||||
|
--radius: 6px;
|
||||||
--mono:
|
--mono:
|
||||||
"JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo,
|
"JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo,
|
||||||
Consolas, "Liberation Mono", monospace;
|
Consolas, "Liberation Mono", monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.light {
|
body.light {
|
||||||
--theme: #e7e7e2;
|
--theme: #e9e9e4;
|
||||||
--surface: #f2f2ee;
|
--surface: rgba(255, 255, 255, 0.56);
|
||||||
--surface-alt: #ebebe5;
|
--surface-raised: rgba(255, 255, 255, 0.72);
|
||||||
--bar: #ddddd6;
|
--bar: rgba(0, 0, 0, 0.035);
|
||||||
--primary: #24262b;
|
--primary: #2a2d33;
|
||||||
--bright: #0e0f12;
|
--bright: #101216;
|
||||||
--secondary: #c8401f;
|
--secondary: #c8401f;
|
||||||
--accent: #c20046;
|
--accent: #c20046;
|
||||||
--ok: #4b7a3a;
|
--ok: #4b7a3a;
|
||||||
--muted: #6a6e76;
|
--muted: #6b6f78;
|
||||||
--border: #cbcbc2;
|
--border: rgba(0, 0, 0, 0.1);
|
||||||
--border-strong: #a9a9a0;
|
--border-strong: rgba(0, 0, 0, 0.2);
|
||||||
--grid: rgba(0, 0, 0, 0.03);
|
--glow: rgba(200, 64, 31, 0.14);
|
||||||
|
--shadow: 0 18px 44px rgba(0, 0, 0, 0.1);
|
||||||
--selection: rgba(200, 64, 31, 0.22);
|
--selection: rgba(200, 64, 31, 0.22);
|
||||||
|
--ascii-base: #6f7682;
|
||||||
|
--ascii-accent: #c8401f;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@@ -63,21 +70,38 @@ body {
|
|||||||
position: relative;
|
position: relative;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
transition:
|
transition:
|
||||||
background-color 0.25s linear,
|
background-color 0.3s ease,
|
||||||
color 0.25s linear;
|
color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Faint graph-paper grid, fixed so it reads as a backdrop, not content. */
|
/* Soft light behind the ASCII field, so the page has depth without gloss. */
|
||||||
body::before {
|
body::before {
|
||||||
content: "";
|
content: "";
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
background-image:
|
background:
|
||||||
linear-gradient(var(--grid) 1px, transparent 1px),
|
radial-gradient(circle at 18% 12%, var(--glow), transparent 42%),
|
||||||
linear-gradient(90deg, var(--grid) 1px, transparent 1px);
|
radial-gradient(circle at 82% 8%, rgba(255, 0, 90, 0.07), transparent 38%),
|
||||||
background-size: 28px 28px;
|
radial-gradient(
|
||||||
|
circle at 50% 95%,
|
||||||
|
rgba(255, 255, 255, 0.035),
|
||||||
|
transparent 46%
|
||||||
|
);
|
||||||
|
filter: blur(28px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ascii-bg {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.22;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.light #ascii-bg {
|
||||||
|
opacity: 0.17;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.js-stop-transition * {
|
body.js-stop-transition * {
|
||||||
@@ -108,7 +132,7 @@ h2,
|
|||||||
h3,
|
h3,
|
||||||
h4 {
|
h4 {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
letter-spacing: -0.01em;
|
letter-spacing: -0.015em;
|
||||||
color: var(--bright);
|
color: var(--bright);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,9 +140,10 @@ a {
|
|||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition:
|
transition:
|
||||||
color 0.12s linear,
|
color 0.18s ease,
|
||||||
background-color 0.12s linear,
|
background-color 0.18s ease,
|
||||||
border-color 0.12s linear;
|
border-color 0.18s ease,
|
||||||
|
box-shadow 0.18s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:hover {
|
a:hover {
|
||||||
@@ -141,10 +166,13 @@ pre {
|
|||||||
/* ---------------------------------------------------------------- header */
|
/* ---------------------------------------------------------------- header */
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
position: relative;
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
background: var(--bar);
|
background: var(--surface);
|
||||||
|
backdrop-filter: blur(16px) saturate(130%);
|
||||||
|
-webkit-backdrop-filter: blur(16px) saturate(130%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav {
|
.nav {
|
||||||
@@ -155,7 +183,7 @@ pre {
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
width: min(1120px, calc(100% - 32px));
|
width: min(1120px, calc(100% - 32px));
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
min-height: 46px;
|
min-height: 52px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
@@ -167,11 +195,10 @@ pre {
|
|||||||
.logo a {
|
.logo a {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 9px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--bright);
|
color: var(--bright);
|
||||||
letter-spacing: 0.01em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo a::before {
|
.logo a::before {
|
||||||
@@ -183,11 +210,10 @@ pre {
|
|||||||
.logo a img {
|
.logo a img {
|
||||||
display: block;
|
display: block;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
border-radius: 2px !important;
|
border-radius: 3px !important;
|
||||||
width: 22px;
|
width: 22px;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
border: 1px solid var(--border-strong);
|
border: 1px solid var(--border);
|
||||||
filter: grayscale(0.25);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo a:hover {
|
.logo a:hover {
|
||||||
@@ -198,56 +224,28 @@ pre {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
gap: 4px;
|
gap: 22px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#menu a {
|
#menu a {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 13px;
|
font-size: 13.5px;
|
||||||
text-transform: lowercase;
|
|
||||||
padding: 3px 9px;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
}
|
padding: 2px 0;
|
||||||
|
border-bottom: 1px solid transparent;
|
||||||
#menu a::before {
|
|
||||||
content: "[";
|
|
||||||
color: var(--border-strong);
|
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#menu a::after {
|
|
||||||
content: "]";
|
|
||||||
color: var(--border-strong);
|
|
||||||
margin-left: 2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#menu a:hover {
|
#menu a:hover {
|
||||||
color: var(--secondary);
|
color: var(--primary);
|
||||||
}
|
|
||||||
|
|
||||||
#menu a:hover::before,
|
|
||||||
#menu a:hover::after {
|
|
||||||
color: var(--secondary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-page="home"] #home-link a,
|
body[data-page="home"] #home-link a,
|
||||||
body[data-page="about"] #about-link a,
|
body[data-page="about"] #about-link a,
|
||||||
body[data-page="projects"] #projects-link a {
|
body[data-page="projects"] #projects-link a {
|
||||||
color: var(--bright);
|
color: var(--bright);
|
||||||
background: var(--surface-alt);
|
border-bottom-color: var(--secondary);
|
||||||
border-color: var(--border);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[data-page="home"] #home-link a::before,
|
|
||||||
body[data-page="about"] #about-link a::before,
|
|
||||||
body[data-page="projects"] #projects-link a::before,
|
|
||||||
body[data-page="home"] #home-link a::after,
|
|
||||||
body[data-page="about"] #about-link a::after,
|
|
||||||
body[data-page="projects"] #projects-link a::after {
|
|
||||||
color: var(--secondary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-switches {
|
.logo-switches {
|
||||||
@@ -257,27 +255,23 @@ body[data-page="projects"] #projects-link a::after {
|
|||||||
|
|
||||||
button#theme-toggle {
|
button#theme-toggle {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: 1px solid var(--border);
|
border: 0;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
padding: 2px 5px;
|
padding: 2px;
|
||||||
height: 24px;
|
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition:
|
transition: color 0.18s ease;
|
||||||
color 0.12s linear,
|
|
||||||
border-color 0.12s linear;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button#theme-toggle svg {
|
button#theme-toggle svg {
|
||||||
height: 13px;
|
height: 14px;
|
||||||
width: 13px;
|
width: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button#theme-toggle:hover {
|
button#theme-toggle:hover {
|
||||||
color: var(--secondary);
|
color: var(--secondary);
|
||||||
border-color: var(--secondary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body.light #moon {
|
body.light #moon {
|
||||||
@@ -291,22 +285,18 @@ body:not(.light) #sun {
|
|||||||
.menu.cta {
|
.menu.cta {
|
||||||
display: none;
|
display: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
text-transform: lowercase;
|
padding: 4px 10px;
|
||||||
padding: 2px 8px;
|
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
}
|
background: var(--bar);
|
||||||
|
|
||||||
.menu.cta::before {
|
|
||||||
content: "≡ ";
|
|
||||||
color: var(--secondary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu.cta:hover {
|
.menu.cta:hover {
|
||||||
color: var(--secondary);
|
color: var(--secondary);
|
||||||
border-color: var(--secondary);
|
border-color: var(--border-strong);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------- overlay */
|
/* --------------------------------------------------------------- overlay */
|
||||||
@@ -316,14 +306,20 @@ body:not(.light) #sun {
|
|||||||
inset: 0;
|
inset: 0;
|
||||||
z-index: 2147483647;
|
z-index: 2147483647;
|
||||||
isolation: isolate;
|
isolation: isolate;
|
||||||
background: var(--theme);
|
background: rgba(11, 12, 15, 0.82);
|
||||||
|
backdrop-filter: blur(18px) saturate(130%);
|
||||||
|
-webkit-backdrop-filter: blur(18px) saturate(130%);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transition:
|
transition:
|
||||||
opacity 0.15s linear,
|
opacity 0.2s ease,
|
||||||
visibility 0.15s linear;
|
visibility 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.light .overlay {
|
||||||
|
background: rgba(233, 233, 228, 0.86);
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay--active {
|
.overlay--active {
|
||||||
@@ -341,31 +337,21 @@ body:not(.light) #sun {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 6px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay a {
|
.overlay a {
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
text-transform: lowercase;
|
padding: 12px 20px;
|
||||||
padding: 10px 18px;
|
font-size: 1.4rem;
|
||||||
font-size: 1.3rem;
|
|
||||||
display: block;
|
display: block;
|
||||||
text-align: left;
|
text-align: center;
|
||||||
width: min(320px, 80%);
|
width: min(300px, 80%);
|
||||||
border: 1px solid var(--border);
|
|
||||||
background: var(--surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
.overlay a::before {
|
|
||||||
content: "> ";
|
|
||||||
color: var(--secondary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay a:hover,
|
.overlay a:hover,
|
||||||
.overlay a:focus {
|
.overlay a:focus {
|
||||||
color: var(--bright);
|
color: var(--secondary);
|
||||||
border-color: var(--secondary);
|
|
||||||
background: var(--surface-alt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay .close {
|
.overlay .close {
|
||||||
@@ -373,19 +359,18 @@ body:not(.light) #sun {
|
|||||||
z-index: 3;
|
z-index: 3;
|
||||||
top: 14px;
|
top: 14px;
|
||||||
right: 18px;
|
right: 18px;
|
||||||
font-size: 26px;
|
font-size: 28px;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
font-family: var(--mono);
|
font-family: var(--mono);
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 1px solid var(--border);
|
border: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
padding: 0 10px;
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.overlay .close:hover {
|
.overlay .close:hover {
|
||||||
color: var(--secondary);
|
color: var(--secondary);
|
||||||
border-color: var(--secondary);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body.menu-open {
|
body.menu-open {
|
||||||
@@ -412,105 +397,83 @@ body.menu-open .overlay * {
|
|||||||
.page-shell {
|
.page-shell {
|
||||||
width: min(1120px, calc(100% - 32px));
|
width: min(1120px, calc(100% - 32px));
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding-bottom: 28px;
|
padding-bottom: 36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------- terminal window */
|
/* ------------------------------------------------------- terminal window */
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
width: min(1120px, calc(100% - 32px));
|
width: min(1120px, calc(100% - 32px));
|
||||||
margin: 34px auto 0;
|
margin: 0 auto;
|
||||||
padding-bottom: 28px;
|
padding: 0 0 36px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
min-height: calc(100vh - 52px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.term {
|
.term {
|
||||||
|
width: 100%;
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
}
|
backdrop-filter: blur(18px) saturate(140%);
|
||||||
|
-webkit-backdrop-filter: blur(18px) saturate(140%);
|
||||||
body[data-page="home"] .main {
|
box-shadow: var(--shadow);
|
||||||
display: flex;
|
overflow: hidden;
|
||||||
min-height: calc(100vh - 110px);
|
|
||||||
}
|
|
||||||
|
|
||||||
body[data-page="home"] .term {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
body[data-page="home"] .term__body {
|
|
||||||
flex: 1;
|
|
||||||
align-content: start;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.term__bar {
|
.term__bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
gap: 7px;
|
||||||
gap: 12px;
|
padding: 9px 14px;
|
||||||
padding: 5px 10px;
|
|
||||||
background: var(--bar);
|
background: var(--bar);
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.term__dot {
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--border-strong);
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.term__dot:first-child {
|
||||||
|
background: rgba(235, 82, 52, 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
.term__title {
|
.term__title {
|
||||||
color: var(--muted);
|
margin-left: 8px;
|
||||||
}
|
|
||||||
|
|
||||||
.term__title b {
|
|
||||||
color: var(--primary);
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.term__dots {
|
|
||||||
letter-spacing: 2px;
|
|
||||||
color: var(--border-strong);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.term__body {
|
.term__body {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto 1fr;
|
grid-template-columns: auto 1fr;
|
||||||
gap: 26px;
|
gap: 34px;
|
||||||
padding: 22px 22px 18px;
|
padding: 34px 32px;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.term__avatar {
|
.term__avatar {
|
||||||
width: 148px;
|
width: 160px;
|
||||||
height: 148px;
|
height: 160px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
|
border-radius: var(--radius);
|
||||||
border: 1px solid var(--border-strong);
|
border: 1px solid var(--border-strong);
|
||||||
border-radius: 0;
|
box-shadow:
|
||||||
filter: grayscale(0.3) contrast(1.03);
|
var(--shadow),
|
||||||
}
|
0 0 0 6px rgba(235, 82, 52, 0.05);
|
||||||
|
|
||||||
.term__avatar-wrap {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 8px;
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.term__avatar-caption {
|
|
||||||
font-size: 11px;
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.term__stream {
|
.term__stream {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.line {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line + .cmd {
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cmd {
|
.cmd {
|
||||||
|
margin: 0 0 18px;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
@@ -518,98 +481,82 @@ body[data-page="home"] .term__body {
|
|||||||
.cmd::before {
|
.cmd::before {
|
||||||
content: "$ ";
|
content: "$ ";
|
||||||
color: var(--secondary);
|
color: var(--secondary);
|
||||||
font-weight: 700;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
font-size: clamp(1.5rem, 3.2vw, 2.1rem);
|
font-size: clamp(1.7rem, 3.6vw, 2.4rem);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
margin: 2px 0 0;
|
margin: 0;
|
||||||
line-height: 1.2;
|
line-height: 1.15;
|
||||||
color: var(--bright);
|
color: var(--bright);
|
||||||
}
|
}
|
||||||
|
|
||||||
.des {
|
.des {
|
||||||
margin: 2px 0 0;
|
margin: 10px 0 0;
|
||||||
font-size: 0.94rem;
|
font-size: 0.95rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-description-secondary {
|
.hero-description-secondary {
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-badges {
|
.hero-badges {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
margin-top: 6px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge {
|
.badge {
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
background: var(--surface-alt);
|
background: var(--bar);
|
||||||
color: var(--primary);
|
color: var(--muted);
|
||||||
padding: 2px 8px;
|
border-radius: var(--radius);
|
||||||
|
padding: 3px 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge::before {
|
|
||||||
content: "+ ";
|
|
||||||
color: var(--ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-actions {
|
.hero-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
margin-top: 6px;
|
margin-top: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border: 1px solid var(--border-strong);
|
border: 1px solid var(--border);
|
||||||
background: var(--surface-alt);
|
border-radius: var(--radius);
|
||||||
|
background: var(--bar);
|
||||||
color: var(--primary);
|
color: var(--primary);
|
||||||
padding: 5px 12px;
|
padding: 7px 16px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button::before {
|
|
||||||
content: ">\00a0";
|
|
||||||
color: var(--secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.button:hover {
|
.button:hover {
|
||||||
color: var(--bright);
|
color: var(--bright);
|
||||||
border-color: var(--secondary);
|
border-color: var(--border-strong);
|
||||||
background: var(--surface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-primary {
|
.button-primary {
|
||||||
border-color: var(--secondary);
|
border-color: rgba(235, 82, 52, 0.5);
|
||||||
color: var(--bright);
|
color: var(--bright);
|
||||||
|
background: rgba(235, 82, 52, 0.14);
|
||||||
|
box-shadow: 0 6px 22px rgba(235, 82, 52, 0.14);
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-primary:hover {
|
.button-primary:hover {
|
||||||
background: var(--secondary);
|
border-color: var(--secondary);
|
||||||
color: #0c0d10;
|
background: rgba(235, 82, 52, 0.22);
|
||||||
}
|
box-shadow: 0 8px 28px rgba(235, 82, 52, 0.22);
|
||||||
|
|
||||||
.button-primary:hover::before {
|
|
||||||
color: #0c0d10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prompt-end {
|
|
||||||
margin: 14px 0 0;
|
|
||||||
color: var(--secondary);
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.caret {
|
.caret {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 0.6em;
|
width: 0.55em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
vertical-align: -0.15em;
|
vertical-align: -0.15em;
|
||||||
background: var(--secondary);
|
background: var(--secondary);
|
||||||
@@ -630,12 +577,13 @@ body[data-page="home"] .term__body {
|
|||||||
.social-icons {
|
.social-icons {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 14px;
|
gap: 16px;
|
||||||
|
margin-top: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.social-icons a svg {
|
.social-icons a svg {
|
||||||
height: 15px;
|
height: 16px;
|
||||||
width: 15px;
|
width: 16px;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -648,49 +596,36 @@ body[data-page="home"] .term__body {
|
|||||||
color: var(--secondary);
|
color: var(--secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------- status footer */
|
/* ---------------------------------------------------------------- footer */
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
padding: 0;
|
padding: 14px 18px;
|
||||||
background: var(--bar);
|
background: var(--surface);
|
||||||
|
backdrop-filter: blur(16px) saturate(130%);
|
||||||
|
-webkit-backdrop-filter: blur(16px) saturate(130%);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
font-size: 12px;
|
border-radius: var(--radius);
|
||||||
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer p {
|
.footer p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 6px 12px;
|
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer p::before {
|
|
||||||
content: "";
|
|
||||||
display: inline-block;
|
|
||||||
width: 6px;
|
|
||||||
height: 6px;
|
|
||||||
background: var(--ok);
|
|
||||||
margin-right: 8px;
|
|
||||||
vertical-align: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer .social-icons {
|
.footer .social-icons {
|
||||||
padding: 6px 12px;
|
margin-top: 0;
|
||||||
border-left: 1px solid var(--border);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-state {
|
.loading-state {
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-state::before {
|
/* ------------------------------------------------------------ responsive */
|
||||||
content: "… ";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------------------------------------------------------- responsive */
|
|
||||||
|
|
||||||
@media only screen and (max-width: 860px) {
|
@media only screen and (max-width: 860px) {
|
||||||
#menu,
|
#menu,
|
||||||
@@ -702,19 +637,16 @@ body[data-page="home"] .term__body {
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav {
|
.main {
|
||||||
min-height: 42px;
|
min-height: auto;
|
||||||
|
margin-top: 28px;
|
||||||
|
width: min(1120px, calc(100% - 20px));
|
||||||
}
|
}
|
||||||
|
|
||||||
.term__body {
|
.term__body {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
gap: 0;
|
gap: 0;
|
||||||
padding: 18px 16px 14px;
|
padding: 26px 20px;
|
||||||
}
|
|
||||||
|
|
||||||
.main {
|
|
||||||
margin-top: 22px;
|
|
||||||
width: min(1120px, calc(100% - 20px));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-shell {
|
.page-shell {
|
||||||
@@ -726,8 +658,7 @@ body[data-page="home"] .term__body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.footer .social-icons {
|
.footer .social-icons {
|
||||||
border-left: 0;
|
margin-top: 12px;
|
||||||
border-top: 1px solid var(--border);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,178 @@
|
|||||||
|
(function() {
|
||||||
|
const canvas = document.getElementById("ascii-bg");
|
||||||
|
|
||||||
|
if (!canvas || !canvas.getContext) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const context = canvas.getContext("2d", { alpha: true });
|
||||||
|
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
|
||||||
|
|
||||||
|
const CHARS = "·.:-=+*#";
|
||||||
|
const CELL_WIDTH = 14;
|
||||||
|
const CELL_HEIGHT = 19;
|
||||||
|
const FRAME_MS = 1000 / 18;
|
||||||
|
const BASE_DENSITY = 0.09;
|
||||||
|
const WAVE_DENSITY = 0.24;
|
||||||
|
|
||||||
|
let columns = 0;
|
||||||
|
let rows = 0;
|
||||||
|
let dither = new Float32Array(0);
|
||||||
|
let baseColor = "rgba(255, 255, 255, 1)";
|
||||||
|
let accentColor = "rgba(235, 82, 52, 1)";
|
||||||
|
let time = 0;
|
||||||
|
let lastFrame = 0;
|
||||||
|
let rafId = 0;
|
||||||
|
|
||||||
|
// Interfering waves, centred on the viewport, give the field slow bright and
|
||||||
|
// dark swells. Which cells are lit comes from a fixed per-cell dither value,
|
||||||
|
// so the texture stays even everywhere instead of pooling into blobs, and
|
||||||
|
// cells brighten as a swell passes rather than flickering at random.
|
||||||
|
const waveAt = (x, y, t) => {
|
||||||
|
const radius = Math.sqrt(
|
||||||
|
((x - columns / 2) * 0.55) ** 2 + (y - rows / 2) ** 2
|
||||||
|
);
|
||||||
|
|
||||||
|
const a = Math.sin(x * 0.068 + t * 0.55);
|
||||||
|
const b = Math.sin(y * 0.1 - t * 0.42);
|
||||||
|
const c = Math.sin((x * 0.4 + y * 0.6) * 0.07 + t * 0.33);
|
||||||
|
const d = Math.sin(radius * 0.1 - t * 0.6);
|
||||||
|
|
||||||
|
return (a + b + c + d) / 8 + 0.5;
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildDither = () => {
|
||||||
|
dither = new Float32Array(columns * rows);
|
||||||
|
|
||||||
|
for (let row = 0; row < rows; row += 1) {
|
||||||
|
for (let column = 0; column < columns; column += 1) {
|
||||||
|
const noise = Math.sin(column * 127.1 + row * 311.7) * 43758.5453;
|
||||||
|
dither[row * columns + column] = noise - Math.floor(noise);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const readThemeColors = () => {
|
||||||
|
const styles = getComputedStyle(document.body);
|
||||||
|
baseColor = styles.getPropertyValue("--ascii-base").trim() || baseColor;
|
||||||
|
accentColor = styles.getPropertyValue("--ascii-accent").trim() || accentColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
const resize = () => {
|
||||||
|
const ratio = Math.min(window.devicePixelRatio || 1, 2);
|
||||||
|
const width = window.innerWidth;
|
||||||
|
const height = window.innerHeight;
|
||||||
|
|
||||||
|
canvas.width = Math.floor(width * ratio);
|
||||||
|
canvas.height = Math.floor(height * ratio);
|
||||||
|
canvas.style.width = `${width}px`;
|
||||||
|
canvas.style.height = `${height}px`;
|
||||||
|
|
||||||
|
context.setTransform(ratio, 0, 0, ratio, 0, 0);
|
||||||
|
context.font = `12px "JetBrains Mono", ui-monospace, monospace`;
|
||||||
|
context.textBaseline = "top";
|
||||||
|
|
||||||
|
columns = Math.ceil(width / CELL_WIDTH);
|
||||||
|
rows = Math.ceil(height / CELL_HEIGHT);
|
||||||
|
buildDither();
|
||||||
|
};
|
||||||
|
|
||||||
|
const draw = () => {
|
||||||
|
const width = canvas.width;
|
||||||
|
const height = canvas.height;
|
||||||
|
|
||||||
|
context.save();
|
||||||
|
context.setTransform(1, 0, 0, 1, 0, 0);
|
||||||
|
context.clearRect(0, 0, width, height);
|
||||||
|
context.restore();
|
||||||
|
|
||||||
|
let currentColor = null;
|
||||||
|
|
||||||
|
for (let row = 0; row < rows; row += 1) {
|
||||||
|
for (let column = 0; column < columns; column += 1) {
|
||||||
|
const level = waveAt(column, row, time);
|
||||||
|
|
||||||
|
if (dither[row * columns + column] > BASE_DENSITY + level * WAVE_DENSITY) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const glyph = CHARS[Math.min(CHARS.length - 1, Math.floor(level * CHARS.length))];
|
||||||
|
const color = level > 0.9 ? accentColor : baseColor;
|
||||||
|
|
||||||
|
if (color !== currentColor) {
|
||||||
|
context.fillStyle = color;
|
||||||
|
currentColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.globalAlpha = 0.06 + level * 0.5;
|
||||||
|
context.fillText(glyph, column * CELL_WIDTH, row * CELL_HEIGHT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context.globalAlpha = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const loop = (timestamp) => {
|
||||||
|
rafId = window.requestAnimationFrame(loop);
|
||||||
|
|
||||||
|
if (timestamp - lastFrame < FRAME_MS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastFrame = timestamp;
|
||||||
|
time += 0.021;
|
||||||
|
draw();
|
||||||
|
};
|
||||||
|
|
||||||
|
const stop = () => {
|
||||||
|
if (rafId) {
|
||||||
|
window.cancelAnimationFrame(rafId);
|
||||||
|
rafId = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const start = () => {
|
||||||
|
if (rafId || prefersReducedMotion.matches) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastFrame = 0;
|
||||||
|
rafId = window.requestAnimationFrame(loop);
|
||||||
|
};
|
||||||
|
|
||||||
|
const reset = () => {
|
||||||
|
readThemeColors();
|
||||||
|
resize();
|
||||||
|
draw();
|
||||||
|
};
|
||||||
|
|
||||||
|
reset();
|
||||||
|
start();
|
||||||
|
|
||||||
|
let resizeTimer = 0;
|
||||||
|
window.addEventListener("resize", () => {
|
||||||
|
window.clearTimeout(resizeTimer);
|
||||||
|
resizeTimer = window.setTimeout(reset, 150);
|
||||||
|
});
|
||||||
|
|
||||||
|
// The theme toggle swaps a class on <body>; re-read the palette when it does.
|
||||||
|
new MutationObserver(() => {
|
||||||
|
readThemeColors();
|
||||||
|
draw();
|
||||||
|
}).observe(document.body, { attributes: true, attributeFilter: ["class"] });
|
||||||
|
|
||||||
|
document.addEventListener("visibilitychange", () => {
|
||||||
|
if (document.hidden) {
|
||||||
|
stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
start();
|
||||||
|
});
|
||||||
|
|
||||||
|
prefersReducedMotion.addEventListener("change", () => {
|
||||||
|
stop();
|
||||||
|
start();
|
||||||
|
draw();
|
||||||
|
});
|
||||||
|
})();
|
||||||
@@ -134,12 +134,12 @@
|
|||||||
|
|
||||||
const renderLinks = (entry, className) => {
|
const renderLinks = (entry, className) => {
|
||||||
const links = [];
|
const links = [];
|
||||||
const sourceLabel = entry.github && entry.github.includes("git.sowinski.dev") ? "gitea" : "github";
|
const sourceLabel = entry.github && entry.github.includes("git.sowinski.dev") ? "Gitea" : "GitHub";
|
||||||
|
|
||||||
links.push(`<a class="${className} ${className}-primary" href="./entry.html?type=${encodeURIComponent(entry.type)}&slug=${encodeURIComponent(entry.slug)}">details</a>`);
|
links.push(`<a class="${className} ${className}-primary" href="./entry.html?type=${encodeURIComponent(entry.type)}&slug=${encodeURIComponent(entry.slug)}">Details</a>`);
|
||||||
|
|
||||||
if (entry.demo) {
|
if (entry.demo) {
|
||||||
links.push(`<a class="${className}" href="${escapeHtml(entry.demo)}" target="_blank" rel="noopener noreferrer">live</a>`);
|
links.push(`<a class="${className}" href="${escapeHtml(entry.demo)}" target="_blank" rel="noopener noreferrer">Live</a>`);
|
||||||
} else if (entry.github) {
|
} else if (entry.github) {
|
||||||
links.push(`<a class="${className}" href="${escapeHtml(entry.github)}" target="_blank" rel="noopener noreferrer">${sourceLabel}</a>`);
|
links.push(`<a class="${className}" href="${escapeHtml(entry.github)}" target="_blank" rel="noopener noreferrer">${sourceLabel}</a>`);
|
||||||
}
|
}
|
||||||
@@ -224,7 +224,7 @@
|
|||||||
card.classList.toggle("is-hidden", !expanded && index >= defaultVisibleCount);
|
card.classList.toggle("is-hidden", !expanded && index >= defaultVisibleCount);
|
||||||
});
|
});
|
||||||
|
|
||||||
toggleButton.textContent = expanded ? "show fewer projects" : "show more projects";
|
toggleButton.textContent = expanded ? "Show fewer projects" : "Show more projects";
|
||||||
toggleButton.setAttribute("aria-expanded", String(expanded));
|
toggleButton.setAttribute("aria-expanded", String(expanded));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
<div class="entry-empty">
|
<div class="entry-empty">
|
||||||
<p class="eyebrow">Not found</p>
|
<p class="eyebrow">Not found</p>
|
||||||
<h1 class="entry-title">This entry could not be loaded.</h1>
|
<h1 class="entry-title">This entry could not be loaded.</h1>
|
||||||
<a class="entry-back" href="./projects.html">cd ../projects</a>
|
<a class="entry-back" href="./projects.html">← Back to projects</a>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
return;
|
return;
|
||||||
@@ -332,7 +332,7 @@
|
|||||||
|
|
||||||
shell.innerHTML = `
|
shell.innerHTML = `
|
||||||
<div class="entry-header">
|
<div class="entry-header">
|
||||||
<a class="entry-back" href="./projects.html">cd ../projects</a>
|
<a class="entry-back" href="./projects.html">← Back to projects</a>
|
||||||
<div class="entry-meta">
|
<div class="entry-meta">
|
||||||
<span class="entry-pill entry-pill-primary">${escapeHtml(entry.label || entry.type)}</span>
|
<span class="entry-pill entry-pill-primary">${escapeHtml(entry.label || entry.type)}</span>
|
||||||
${entry.date ? `<span class="entry-pill entry-pill-secondary">${escapeHtml(formatDate(entry.date))}</span>` : ""}
|
${entry.date ? `<span class="entry-pill entry-pill-secondary">${escapeHtml(formatDate(entry.date))}</span>` : ""}
|
||||||
@@ -342,8 +342,8 @@
|
|||||||
<p class="entry-summary">${escapeHtml(entry.summary || "")}</p>
|
<p class="entry-summary">${escapeHtml(entry.summary || "")}</p>
|
||||||
${renderTags(entry.tags || [], "entry-tag-list")}
|
${renderTags(entry.tags || [], "entry-tag-list")}
|
||||||
<div class="entry-links">
|
<div class="entry-links">
|
||||||
${entry.demo ? `<a class="inline-button inline-button-primary" href="${escapeHtml(entry.demo)}" target="_blank" rel="noopener noreferrer">live</a>` : ""}
|
${entry.demo ? `<a class="inline-button inline-button-primary" href="${escapeHtml(entry.demo)}" target="_blank" rel="noopener noreferrer">Live</a>` : ""}
|
||||||
${entry.github ? `<a class="inline-button" href="${escapeHtml(entry.github)}" target="_blank" rel="noopener noreferrer">${entry.github.includes("git.sowinski.dev") ? "gitea" : "github"}</a>` : ""}
|
${entry.github ? `<a class="inline-button" href="${escapeHtml(entry.github)}" target="_blank" rel="noopener noreferrer">${entry.github.includes("git.sowinski.dev") ? "Gitea" : "GitHub"}</a>` : ""}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<article class="entry-content">
|
<article class="entry-content">
|
||||||
@@ -355,7 +355,7 @@
|
|||||||
<div class="entry-empty">
|
<div class="entry-empty">
|
||||||
<p class="eyebrow">Not found</p>
|
<p class="eyebrow">Not found</p>
|
||||||
<h1 class="entry-title">${escapeHtml(error.message)}</h1>
|
<h1 class="entry-title">${escapeHtml(error.message)}</h1>
|
||||||
<a class="entry-back" href="./projects.html">cd ../projects</a>
|
<a class="entry-back" href="./projects.html">← Back to projects</a>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,18 @@
|
|||||||
|
|
||||||
// Build the playback script before hiding anything, so a thrown error here
|
// Build the playback script before hiding anything, so a thrown error here
|
||||||
// leaves the page in its fully rendered state.
|
// leaves the page in its fully rendered state.
|
||||||
const steps = Array.from(stream.children).map((element) => ({
|
// Commands type into their own span so the blinking caret beside them
|
||||||
element,
|
// survives the text rewrites.
|
||||||
isCommand: element.classList.contains("cmd"),
|
const steps = Array.from(stream.children).map((element) => {
|
||||||
text: element.textContent
|
const target = element.querySelector(".cmd__text");
|
||||||
}));
|
|
||||||
|
return {
|
||||||
|
element,
|
||||||
|
target: target || element,
|
||||||
|
isCommand: element.classList.contains("cmd"),
|
||||||
|
text: (target || element).textContent
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
if (!steps.some((step) => step.isCommand)) {
|
if (!steps.some((step) => step.isCommand)) {
|
||||||
return;
|
return;
|
||||||
@@ -29,7 +36,7 @@
|
|||||||
|
|
||||||
steps.forEach((step) => {
|
steps.forEach((step) => {
|
||||||
if (step.isCommand) {
|
if (step.isCommand) {
|
||||||
step.element.textContent = "";
|
step.target.textContent = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +55,7 @@
|
|||||||
const play = async () => {
|
const play = async () => {
|
||||||
for (const step of steps) {
|
for (const step of steps) {
|
||||||
if (step.isCommand) {
|
if (step.isCommand) {
|
||||||
await typeCommand(step.element, step.text);
|
await typeCommand(step.target, step.text);
|
||||||
await wait(AFTER_COMMAND_DELAY);
|
await wait(AFTER_COMMAND_DELAY);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user