Repository navigation
Expand file tree
/
Copy pathabout-this-site.html
More file actions
319 lines (292 loc) · 12.4 KB
/
Copy pathabout-this-site.html
File metadata and controls
319 lines (292 loc) · 12.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>About this site — Shabnam Hakimi</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,wght@0,300;0,400;0,500;1,300;1,400&family=Space+Mono:ital,wght@0,400;0,700;1,400&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<style>
/* ── PAGE ── */
.page-header {
padding: 9.8rem 2.5rem 4rem;
border-bottom: 1px solid var(--blue-G);
max-width: 820px;
}
.page-eyebrow.s-yellow { --hl-rgb: 255 255 119; --hl-a: 0.75; }
.page-title { font-family: var(--sans); font-size: clamp(2rem,5vw,3.5rem); font-weight: 300; color: var(--ink); line-height: 1.05; letter-spacing: -0.02em; margin-bottom: 1rem; }
.page-desc { font-size: 0.68rem; color: var(--ink-dim); max-width: 540px; line-height: 1.95; }
.page-desc em { font-style: normal; color: var(--ink-blue); }
/* ── BODY ── */
.colophon {
padding: 2.5rem 2.5rem 6rem;
max-width: 760px;
}
/* Section divider — matches projects.html */
.section-divider {
padding: 16px 0 8px;
margin-top: 56px;
font-size: 0.72rem; letter-spacing: 0.35em; text-transform: uppercase;
color: var(--ink-blue);
border-top: 1.5px solid var(--ink-blue);
}
.section-divider > .hl {
display: inline;
/* inline + clone, not inline-block: the band is one linear-gradient over
the element box, so on a label that wraps, inline-block stretched a
single gradient across BOTH lines and the colour landed in the gap
between them. Cloning the box decoration gives each line fragment its
own gradient, i.e. a highlighter stroke per line. */
-webkit-box-decoration-break: clone;
box-decoration-break: clone;
padding: 0 6px;
margin-left: -6px;
background-image: linear-gradient(
transparent 22%,
rgb(var(--hl-rgb, 26 44 107) / var(--hl-a, 0.0)) 22%,
rgb(var(--hl-rgb, 26 44 107) / var(--hl-a, 0.0)) 92%,
transparent 92%
);
}
.section-divider.s-slate { --hl-rgb: 119 119 255; --hl-a: 0.65; }
.section-divider.s-helio { --hl-rgb: 201 119 255; --hl-a: 0.55; }
.section-divider.s-violet { --hl-rgb: 255 119 228; --hl-a: 0.55; }
.section-divider.s-cheese { --hl-rgb: 255 174 119; --hl-a: 0.65; }
.section-divider.s-mint { --hl-rgb: 119 255 228; --hl-a: 0.65; }
.colophon p {
font-size: 0.75rem;
color: var(--ink);
line-height: 1.95;
margin-top: 1.4rem;
max-width: 640px;
}
.colophon p.note {
color: var(--ink-dim);
}
.colophon a {
color: var(--ink-blue);
text-decoration: none;
border-bottom: 1px solid rgba(26,44,107,0.55);
transition: border-color 0.2s;
}
.colophon a:hover { border-color: var(--ink-blue); }
/* A small monospaced inline tag used for tool/file references */
.colophon code {
font-family: var(--mono);
font-size: 0.7rem;
background: rgba(26,44,107,0.06);
padding: 0.05rem 0.3rem;
color: var(--ink-blue);
border-radius: 2px;
}
.colophon ul {
list-style: none;
margin-top: 1rem;
max-width: 640px;
}
.colophon ul li {
padding: 0.55rem 0;
border-bottom: 1px solid rgba(100,160,210,0.18);
font-size: 0.7rem;
color: var(--ink-dim);
display: grid;
grid-template-columns: 130px 1fr;
gap: 1rem;
align-items: baseline;
}
.colophon ul li::before { content: none; }
.colophon ul li .k {
font-size: 0.68rem; letter-spacing: 0.2em; text-transform: uppercase;
color: var(--ink-blue);
}
.colophon ul li .v { color: var(--ink); }
.colophon ul li .v code { background: none; padding: 0; }
/* ── FOOTER ── */
footer { position: relative; z-index: 10; }
@media (max-width: 700px) {
nav { padding: 1rem 1.5rem; }
.page-header, .colophon { padding-left: 1.5rem; padding-right: 1.5rem; }
body, a, button { cursor: auto; }
.cursor { display: none; }
.colophon ul li { grid-template-columns: 1fr; gap: 0.2rem; }
}
/* ── CONTENT CARD ── */
.content-card {
background: rgba(245,242,236,0.80);
margin: 0 1rem;
padding: 0;
}
</style>
</head>
<body>
<div class="cursor" id="cursor">+</div>
<nav>
<a href="index.html" class="nav-logo">
<span class="nav-logo-hl" id="nav-logo-hl"></span>
<span class="nav-logo-text">SH</span>
</a>
<ul class="nav-links" id="nav-links">
<li><a href="index.html#about">About</a></li>
<li><a href="index.html#research">Research</a>
<div class="nav-sub-links">
<a href="graph.html">Graph</a>
<a href="projects.html">Projects</a>
<a href="cv.html">CV</a>
</div>
</li>
<li><a href="extracurriculars.html">Extracurriculars</a></li>
<li><a href="index.html#contact">Contact</a></li>
</ul>
<button class="nav-toggle" id="nav-toggle" aria-label="Toggle menu" aria-expanded="false" aria-controls="nav-links">
<span></span><span></span><span></span>
</button>
</nav>
<div class="content-card">
<div class="page-header">
<p class="page-eyebrow s-yellow"><span class="hl">Colophon</span></p>
<h1 class="page-title">About this site</h1>
<p class="page-desc">A short note on <em>how</em> rather than <em>what</em> — the design choices, the
knowledge graph, and the pipeline that keeps everything in sync.</p>
</div>
<div class="colophon">
<p>
This site is a small experiment in making an academic personal page that
behaves like the work it represents — interconnected concepts, mechanisms
visible underneath the surface, room for the reader to wander.
It's hand-rolled HTML, CSS, and a bit of JavaScript: no framework, no
build step, no tracking. The source lives on <a href="https://github.com/shabtastic/shabweb">GitHub</a>.
</p>
<!-- ─── THE KNOWLEDGE GRAPH ───────────────────────── -->
<div class="section-divider s-slate"><span class="hl">The knowledge graph</span></div>
<p>
The most distinctive feature is the <a href="graph.html">research graph</a> —
a force-directed visualization where each node is a concept extracted
from one of my publications and each edge encodes a theoretical
relationship. The contour lines under the nodes are a topographic
rendering of <em>spreading activation</em> — a computational model of
how concepts in memory illuminate each other along associative pathways
(Collins & Loftus, 1975). The same field also drives the small
animation on the home page.
</p>
<p>
Nodes are extracted from full paper text using a small Node CLI that
asks Claude for a structured set of <code>{id, label, weight, cluster,
level}</code> tuples per paper. A separate pass classifies every node by
abstraction level — <em>theory</em>, <em>construct</em>, <em>method</em>,
<em>mechanism</em>, or <em>domain</em> — so that the rendered graph can
show only the mid-level theoretical scaffolding by default and hide
specific brain regions or instruments unless explicitly requested.
</p>
<p>
Clusters correspond to my eight research areas. Their highlighter colors
(slate, heliotrope, violet, ultra red, laser lemon, mac & cheese,
mint, lime) carry meaning only inside graph and publication contexts —
elsewhere on the site the same palette is purely decorative.
</p>
<!-- ─── DATA PIPELINE ──────────────────────────────── -->
<div class="section-divider s-cheese"><span class="hl">Data pipeline</span></div>
<p>
My CV lives in a separate <a href="https://github.com/shabtastic/cv-that-is-awesome">LaTeX
repository</a> built with the <em>awesome-cv</em> template. The bib files
in that repo are the source of truth for publications. A small Node
script (<code>data/sync-bib.js</code>) parses them into a structured
<code>publications.json</code> and updates the graph's
<code>meta.papers</code> entries. A GitHub Actions workflow runs the
sync nightly so this site stays current as new papers are added, with
no manual step. The published CV PDF is itself a release artifact —
the viewer fetches <code>shabnam-hakimi-cv.pdf</code> from the CV repo's
latest release on each visit.
</p>
<!-- ─── AESTHETIC ──────────────────────────────────── -->
<div class="section-divider s-helio"><span class="hl">Aesthetic</span></div>
<p>
The visual language is graph paper — paper-warm background, fine grid
in two scales, and ink-blue accents — chosen because most of my early
research notes still live in physical notebooks of the same kind. The
typefaces are <em>DM Sans</em> for display and <em>Space Mono</em> for
everything else; together they're meant to read as
"researcher's draft" rather than "polished portfolio."
</p>
<p>
Small details: a custom <em>+</em> crosshair cursor that scales on
interactive elements, animated <a href="https://en.wikipedia.org/wiki/Eulerian_path">Eulerian
path</a> doodles in the page backgrounds, a section-marker palette
drawn from <a href="https://en.wikipedia.org/wiki/List_of_Crayola_crayon_colors">Crayola
highlighter colors</a>, and structural borders snapped to the 16-pixel
grid so the typography lines up with the paper underneath.
</p>
<!-- ─── BUILD ─────────────────────────────────────── -->
<div class="section-divider s-violet"><span class="hl">Build & tools</span></div>
<ul>
<li><span class="k">Pages</span><span class="v">Static HTML / CSS / vanilla JS</span></li>
<li><span class="k">Hosting</span><span class="v"><a href="https://vercel.com">Vercel</a></span></li>
<li><span class="k">Registrar</span><span class="v">IONOS</span></li>
<li><span class="k">Source</span><span class="v"><a href="https://github.com/shabtastic/shabweb">github.com/shabtastic/shabweb</a></span></li>
<li><span class="k">Concept extraction</span><span class="v">Claude (Opus 4.7) via the Anthropic SDK</span></li>
<li><span class="k">CV pipeline</span><span class="v"><a href="https://github.com/posquit0/Awesome-CV">awesome-cv</a> (LaTeX) + a sync script</span></li>
<li><span class="k">Authoring</span><span class="v"><a href="https://claude.com/claude-code">Claude Code</a></span></li>
</ul>
<p class="note" style="margin-top:2.4rem;">
If anything here doesn't render right, or you notice something broken,
I'd love to hear about it — <a href="index.html#contact">contact info is on the home page</a>.
</p>
</div>
</div>
<footer>
<p>Shabnam Hakimi, Ph.D. — Researcher & Synthesist</p>
<p>MMXXVI</p>
</footer>
<script>
// Cursor
(function() {
const cursor = document.getElementById('cursor');
document.addEventListener('mousemove', e => {
cursor.style.left = e.clientX + 'px';
cursor.style.top = e.clientY + 'px';
});
document.querySelectorAll('a, button').forEach(el => {
el.addEventListener('mouseenter', () => { cursor.style.transform = 'translate(-50%,-50%) scale(1.9)'; cursor.style.color = 'var(--ink-blue)'; });
el.addEventListener('mouseleave', () => { cursor.style.transform = 'translate(-50%,-50%) scale(1)'; cursor.style.color = 'var(--ink)'; });
});
// Logo highlight cycle
const COLORS = ['#FFFF77','#7777FF','#C977FF','#FF77E4','#FF7792','#FFAE77'];
let idx = 0, hovered = false, lastSwap = 0;
const hl = document.getElementById('nav-logo-hl');
const logo = document.querySelector('.nav-logo');
if (hl && logo) {
hl.style.backgroundColor = COLORS[0];
logo.addEventListener('mouseenter', () => hovered = true);
logo.addEventListener('mouseleave', () => hovered = false);
function tick(ts) {
if (ts - lastSwap > (hovered ? 600 : 3000)) {
idx = (idx + 1) % COLORS.length;
hl.style.backgroundColor = COLORS[idx];
lastSwap = ts;
}
requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
}
})();
</script>
<script>
(function(){
var nav = document.querySelector('nav');
var toggle = document.getElementById('nav-toggle');
if (!nav || !toggle) return;
toggle.addEventListener('click', function(){
var open = nav.classList.toggle('nav-open');
toggle.setAttribute('aria-expanded', open ? 'true' : 'false');
});
nav.querySelectorAll('.nav-links a').forEach(function(a){
a.addEventListener('click', function(){
nav.classList.remove('nav-open');
toggle.setAttribute('aria-expanded', 'false');
});
});
})();
</script>
</body>
</html>