heyiam 0.3.6 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/archive.js +28 -0
- package/dist/db.js +9 -0
- package/dist/export.js +3 -0
- package/dist/llm/project-enhance.js +11 -5
- package/dist/mount.js +43 -18
- package/dist/public/assets/index-ByoBtx7P.css +1 -0
- package/dist/public/assets/index-LQHTU1Wz.js +37 -0
- package/dist/public/index.html +2 -2
- package/dist/render/build-render-data.js +1 -0
- package/dist/render/liquid.js +14 -1
- package/dist/render/mock-data.js +6 -0
- package/dist/render/select-profile-skills.js +54 -0
- package/dist/render/templates/aurora/portfolio.liquid +4 -4
- package/dist/render/templates/aurora/styles.css +6 -6
- package/dist/render/templates/bauhaus/portfolio.liquid +4 -4
- package/dist/render/templates/bauhaus/project.liquid +2 -2
- package/dist/render/templates/bauhaus/styles.css +1 -1
- package/dist/render/templates/blueprint/portfolio.liquid +4 -4
- package/dist/render/templates/blueprint/styles.css +1 -1
- package/dist/render/templates/canvas/portfolio.liquid +4 -4
- package/dist/render/templates/canvas/styles.css +2 -2
- package/dist/render/templates/carbon/portfolio.liquid +4 -4
- package/dist/render/templates/carbon/styles.css +7 -7
- package/dist/render/templates/chalk/portfolio.liquid +4 -4
- package/dist/render/templates/chalk/styles.css +44 -2
- package/dist/render/templates/circuit/portfolio.liquid +4 -4
- package/dist/render/templates/cosmos/portfolio.liquid +4 -4
- package/dist/render/templates/cosmos/styles.css +4 -4
- package/dist/render/templates/daylight/portfolio.liquid +4 -4
- package/dist/render/templates/editorial/portfolio.liquid +4 -4
- package/dist/render/templates/editorial/project.liquid +1 -1
- package/dist/render/templates/editorial/styles.css +6 -1
- package/dist/render/templates/ember/portfolio.liquid +4 -4
- package/dist/render/templates/ember/styles.css +2 -2
- package/dist/render/templates/glacier/portfolio.liquid +4 -4
- package/dist/render/templates/glacier/project.liquid +3 -3
- package/dist/render/templates/glacier/styles.css +2 -2
- package/dist/render/templates/grid/portfolio.liquid +4 -4
- package/dist/render/templates/grid/styles.css +2 -2
- package/dist/render/templates/kinetic/portfolio.liquid +4 -4
- package/dist/render/templates/kinetic/project.liquid +1 -1
- package/dist/render/templates/kinetic/styles.css +5 -5
- package/dist/render/templates/meridian/portfolio.liquid +4 -4
- package/dist/render/templates/meridian/styles.css +1 -1
- package/dist/render/templates/minimal/portfolio.liquid +3 -3
- package/dist/render/templates/minimal/project.liquid +1 -1
- package/dist/render/templates/mono/portfolio.liquid +4 -4
- package/dist/render/templates/mono/styles.css +15 -1
- package/dist/render/templates/neon/portfolio.liquid +4 -4
- package/dist/render/templates/neon/styles.css +11 -20
- package/dist/render/templates/noir/portfolio.liquid +4 -4
- package/dist/render/templates/noir/styles.css +5 -5
- package/dist/render/templates/obsidian/portfolio.liquid +4 -4
- package/dist/render/templates/obsidian/styles.css +2 -2
- package/dist/render/templates/paper/portfolio.liquid +4 -4
- package/dist/render/templates/paper/project.liquid +2 -2
- package/dist/render/templates/paper/styles.css +60 -1
- package/dist/render/templates/parallax/portfolio.liquid +4 -4
- package/dist/render/templates/parallax/styles.css +1 -1
- package/dist/render/templates/parchment/portfolio.liquid +4 -4
- package/dist/render/templates/parchment/styles.css +3 -3
- package/dist/render/templates/partials/_work-timeline.liquid +1 -1
- package/dist/render/templates/project.liquid +1 -1
- package/dist/render/templates/radar/portfolio.liquid +4 -4
- package/dist/render/templates/radar/project.liquid +1 -1
- package/dist/render/templates/radar/styles.css +4 -4
- package/dist/render/templates/showcase/portfolio.liquid +4 -4
- package/dist/render/templates/showcase/project.liquid +1 -1
- package/dist/render/templates/showcase/styles.css +7 -7
- package/dist/render/templates/signal/portfolio.liquid +4 -4
- package/dist/render/templates/signal/styles.css +5 -5
- package/dist/render/templates/strata/portfolio.liquid +4 -4
- package/dist/render/templates/strata/styles.css +3 -3
- package/dist/render/templates/styles.css +39 -28
- package/dist/render/templates/terminal/portfolio.liquid +2 -2
- package/dist/render/templates/terminal/project.liquid +1 -1
- package/dist/render/templates/verdant/portfolio.liquid +4 -4
- package/dist/render/templates/verdant/styles.css +17 -2
- package/dist/render/templates/zen/portfolio.liquid +4 -4
- package/dist/render/templates/zen/styles.css +8 -8
- package/dist/routes/context.js +26 -3
- package/dist/routes/enhance.js +10 -3
- package/dist/routes/export.js +1 -0
- package/dist/routes/github.js +1 -1
- package/dist/routes/portfolio-render-data.js +15 -1
- package/dist/routes/preview.js +31 -1
- package/dist/routes/projects.js +8 -1
- package/dist/routes/publish.js +9 -2
- package/dist/settings.js +2 -0
- package/package.json +1 -1
- package/dist/public/assets/index-7mUuxgqY.js +0 -37
- package/dist/public/assets/index-CMyamplX.css +0 -1
package/dist/public/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>app</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-LQHTU1Wz.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-ByoBtx7P.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
package/dist/render/liquid.js
CHANGED
|
@@ -110,7 +110,20 @@ export function renderProject(data, extras, templateName) {
|
|
|
110
110
|
const slug = typeof existingSlug === 'string' && existingSlug !== ''
|
|
111
111
|
? existingSlug
|
|
112
112
|
: (slugByToken.get(id) ?? '');
|
|
113
|
-
|
|
113
|
+
const merged = { ...rest, slug, rawLog: [] };
|
|
114
|
+
// When dates are hidden, strip every timestamp from the session so
|
|
115
|
+
// nothing leaks through the page source. The chart and overlay treat
|
|
116
|
+
// a missing `date` as "ordinal mode" — no axis labels, no gap markers.
|
|
117
|
+
if (data.hideSessionDates) {
|
|
118
|
+
delete merged.date;
|
|
119
|
+
delete merged.endTime;
|
|
120
|
+
const children = merged.children;
|
|
121
|
+
if (Array.isArray(children)) {
|
|
122
|
+
for (const c of children)
|
|
123
|
+
delete c.date;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return merged;
|
|
114
127
|
});
|
|
115
128
|
// Encode JSON safe for single-quoted HTML attributes
|
|
116
129
|
const sessionsJson = JSON.stringify(chartSessions).replace(/'/g, ''');
|
package/dist/render/mock-data.js
CHANGED
|
@@ -26,6 +26,7 @@ export function getMockPortfolioData() {
|
|
|
26
26
|
{
|
|
27
27
|
slug: 'budgetwise',
|
|
28
28
|
title: 'BudgetWise',
|
|
29
|
+
tagline: 'I built a personal finance tracker that categorizes your transactions without the bank-screen-scraping nonsense.',
|
|
29
30
|
narrative: 'A personal finance tracker with AI-powered categorization. Built the Prisma schema, REST API, and React dashboard in a single sprint using Claude as a coding partner.',
|
|
30
31
|
totalSessions: 8,
|
|
31
32
|
totalLoc: 3200,
|
|
@@ -33,6 +34,7 @@ export function getMockPortfolioData() {
|
|
|
33
34
|
totalAgentDurationMinutes: 2064,
|
|
34
35
|
totalFilesChanged: 45,
|
|
35
36
|
skills: ['TypeScript', 'React', 'Prisma', 'Node.js'],
|
|
37
|
+
profileSkills: ['TypeScript', 'React', 'Prisma', 'Node.js'],
|
|
36
38
|
sourceCounts: [{ tool: 'claude', count: 5 }, { tool: 'cursor', count: 3 }],
|
|
37
39
|
publishedCount: 6,
|
|
38
40
|
sessions: [
|
|
@@ -49,6 +51,7 @@ export function getMockPortfolioData() {
|
|
|
49
51
|
{
|
|
50
52
|
slug: 'shellhook',
|
|
51
53
|
title: 'ShellHook',
|
|
54
|
+
tagline: 'I built a git hooks manager that makes team hooks actually shareable — no more "did you run the setup script?"',
|
|
52
55
|
narrative: 'Git hooks manager that auto-installs and shares hooks across teams. Zero config, works with any shell, supports pre-commit, pre-push, and custom triggers.',
|
|
53
56
|
totalSessions: 5,
|
|
54
57
|
totalLoc: 1800,
|
|
@@ -56,6 +59,7 @@ export function getMockPortfolioData() {
|
|
|
56
59
|
totalAgentDurationMinutes: 900,
|
|
57
60
|
totalFilesChanged: 22,
|
|
58
61
|
skills: ['Rust', 'Shell', 'Git'],
|
|
62
|
+
profileSkills: ['Rust', 'Shell', 'Git'],
|
|
59
63
|
sourceCounts: [{ tool: 'claude', count: 3 }, { tool: 'cursor', count: 2 }],
|
|
60
64
|
publishedCount: 4,
|
|
61
65
|
sessions: [
|
|
@@ -69,6 +73,7 @@ export function getMockPortfolioData() {
|
|
|
69
73
|
{
|
|
70
74
|
slug: 'pixelboard',
|
|
71
75
|
title: 'PixelBoard',
|
|
76
|
+
tagline: 'I built a collaborative pixel art canvas that stays in sync even when two people draw the same pixel at once.',
|
|
72
77
|
narrative: 'Collaborative pixel art canvas with real-time sync. WebSocket-based with conflict-free replicated data types for seamless multi-user editing.',
|
|
73
78
|
totalSessions: 12,
|
|
74
79
|
totalLoc: 4500,
|
|
@@ -76,6 +81,7 @@ export function getMockPortfolioData() {
|
|
|
76
81
|
totalAgentDurationMinutes: 2160,
|
|
77
82
|
totalFilesChanged: 60,
|
|
78
83
|
skills: ['TypeScript', 'WebSocket', 'Canvas API', 'Redis'],
|
|
84
|
+
profileSkills: ['TypeScript', 'WebSocket', 'Canvas API', 'Redis'],
|
|
79
85
|
sourceCounts: [{ tool: 'claude', count: 8 }, { tool: 'cursor', count: 4 }],
|
|
80
86
|
publishedCount: 8,
|
|
81
87
|
sessions: [
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pick which skills to show on a portfolio card.
|
|
3
|
+
*
|
|
4
|
+
* The full skill list still lives on the project detail page; this trims
|
|
5
|
+
* the list to a handful for the dense card grid. Shared between the
|
|
6
|
+
* publish flow (`portfolio-render-data.ts`) and the preview flow
|
|
7
|
+
* (`preview.ts`) so what the user sees in the template browser matches
|
|
8
|
+
* what they actually ship.
|
|
9
|
+
*/
|
|
10
|
+
/** Cap for the number of skill chips shown on a portfolio card. */
|
|
11
|
+
export const PROFILE_SKILL_CAP = 4;
|
|
12
|
+
/**
|
|
13
|
+
* Return the capped, ranked subset of skills to render on the profile card.
|
|
14
|
+
*
|
|
15
|
+
* Ranks by **sessions-touched count** — the skill that appeared in the most
|
|
16
|
+
* distinct sessions wins. A skill mentioned in 8 of 10 sessions ranks above
|
|
17
|
+
* one mentioned in 1 of 10, regardless of how many times it appeared inside
|
|
18
|
+
* any single session (so one verbose session can't dominate the ranking).
|
|
19
|
+
* Ties are broken by the skill's order in `projectSkills` (stable, canonical).
|
|
20
|
+
*
|
|
21
|
+
* Invariants:
|
|
22
|
+
* - Output length ≤ PROFILE_SKILL_CAP.
|
|
23
|
+
* - Output is a subset of `projectSkills` (preserves canonical casing).
|
|
24
|
+
* - No duplicates.
|
|
25
|
+
* - Empty `projectSkills` → empty output.
|
|
26
|
+
* - Skills appearing in sessions but not in `projectSkills` are ignored
|
|
27
|
+
* (the enhance cache is the source of truth for which skills count).
|
|
28
|
+
*/
|
|
29
|
+
export function selectProfileSkills(input) {
|
|
30
|
+
const { projectSkills, sessionSkills } = input;
|
|
31
|
+
if (projectSkills.length === 0)
|
|
32
|
+
return [];
|
|
33
|
+
const canonical = new Set(projectSkills);
|
|
34
|
+
const sessionsTouched = new Map();
|
|
35
|
+
for (const skill of projectSkills)
|
|
36
|
+
sessionsTouched.set(skill, 0);
|
|
37
|
+
for (const perSession of sessionSkills) {
|
|
38
|
+
const seen = new Set();
|
|
39
|
+
for (const skill of perSession) {
|
|
40
|
+
if (canonical.has(skill) && !seen.has(skill)) {
|
|
41
|
+
seen.add(skill);
|
|
42
|
+
sessionsTouched.set(skill, (sessionsTouched.get(skill) ?? 0) + 1);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const order = new Map(projectSkills.map((s, i) => [s, i]));
|
|
47
|
+
return projectSkills
|
|
48
|
+
.slice()
|
|
49
|
+
.sort((a, b) => {
|
|
50
|
+
const diff = (sessionsTouched.get(b) ?? 0) - (sessionsTouched.get(a) ?? 0);
|
|
51
|
+
return diff !== 0 ? diff : (order.get(a) ?? 0) - (order.get(b) ?? 0);
|
|
52
|
+
})
|
|
53
|
+
.slice(0, PROFILE_SKILL_CAP);
|
|
54
|
+
}
|
|
@@ -94,17 +94,17 @@
|
|
|
94
94
|
<div class="aurora-card-header">
|
|
95
95
|
<h3>{{ p.title }}</h3>
|
|
96
96
|
</div>
|
|
97
|
-
{% if p.
|
|
98
|
-
<p class="aurora-card-narrative">{{ p.
|
|
97
|
+
{% if p.tagline != blank %}
|
|
98
|
+
<p class="aurora-card-narrative">{{ p.tagline }}</p>
|
|
99
99
|
{% endif %}
|
|
100
100
|
<div class="aurora-card-stats">
|
|
101
101
|
<span>{{ p.totalSessions }} sessions</span>
|
|
102
102
|
<span>{{ p.totalDurationMinutes | formatDuration }}</span>
|
|
103
103
|
<span>{{ p.totalLoc | localeNumber }} LOC</span>
|
|
104
104
|
</div>
|
|
105
|
-
{% if p.
|
|
105
|
+
{% if p.profileSkills.size > 0 %}
|
|
106
106
|
<div class="aurora-tags">
|
|
107
|
-
{% for skill in p.
|
|
107
|
+
{% for skill in p.profileSkills %}
|
|
108
108
|
<span class="aurora-tag">{{ skill }}</span>
|
|
109
109
|
{% endfor %}
|
|
110
110
|
</div>
|
|
@@ -245,7 +245,7 @@ body { background: var(--aurora-bg); color: var(--aurora-text); }
|
|
|
245
245
|
font-size: 1.375rem;
|
|
246
246
|
}
|
|
247
247
|
.aurora .aurora-stats--project .aurora-stat-label {
|
|
248
|
-
font-size: 0.
|
|
248
|
+
font-size: 0.75rem;
|
|
249
249
|
margin-top: 0.125rem;
|
|
250
250
|
}
|
|
251
251
|
.aurora .aurora-stat {
|
|
@@ -375,7 +375,7 @@ body { background: var(--aurora-bg); color: var(--aurora-text); }
|
|
|
375
375
|
color: var(--aurora-text);
|
|
376
376
|
}
|
|
377
377
|
.aurora .aurora-card-narrative {
|
|
378
|
-
font-size:
|
|
378
|
+
font-size: 1rem;
|
|
379
379
|
color: var(--aurora-text-secondary);
|
|
380
380
|
line-height: 1.65;
|
|
381
381
|
margin-bottom: 1.25rem;
|
|
@@ -495,7 +495,7 @@ body { background: var(--aurora-bg); color: var(--aurora-text); }
|
|
|
495
495
|
|
|
496
496
|
/* ── Narrative ── */
|
|
497
497
|
.aurora .aurora-narrative p {
|
|
498
|
-
font-size:
|
|
498
|
+
font-size: 1rem;
|
|
499
499
|
color: var(--aurora-text-secondary);
|
|
500
500
|
line-height: 1.75;
|
|
501
501
|
margin-bottom: 1rem;
|
|
@@ -651,7 +651,7 @@ body { background: var(--aurora-bg); color: var(--aurora-text); }
|
|
|
651
651
|
text-shadow: 0 0 10px rgba(45, 212, 191, 0.3);
|
|
652
652
|
}
|
|
653
653
|
.aurora .aurora-decision-text {
|
|
654
|
-
font-size:
|
|
654
|
+
font-size: 1rem;
|
|
655
655
|
color: var(--aurora-text-secondary);
|
|
656
656
|
line-height: 1.5;
|
|
657
657
|
}
|
|
@@ -815,7 +815,7 @@ body { background: var(--aurora-bg); color: var(--aurora-text); }
|
|
|
815
815
|
border-inline-start: 3px solid var(--aurora-accent);
|
|
816
816
|
border-radius: var(--aurora-radius);
|
|
817
817
|
padding: 1.25rem 1.5rem;
|
|
818
|
-
font-size:
|
|
818
|
+
font-size: 1rem;
|
|
819
819
|
color: var(--aurora-text-secondary);
|
|
820
820
|
line-height: 1.7;
|
|
821
821
|
font-style: italic;
|
|
@@ -1048,7 +1048,7 @@ body { background: var(--aurora-bg); color: var(--aurora-text); }
|
|
|
1048
1048
|
margin-bottom: 2.5rem;
|
|
1049
1049
|
}
|
|
1050
1050
|
.aurora .aurora-narrative-section p {
|
|
1051
|
-
font-size:
|
|
1051
|
+
font-size: 1rem;
|
|
1052
1052
|
color: var(--aurora-text-secondary);
|
|
1053
1053
|
line-height: 1.75;
|
|
1054
1054
|
}
|
|
@@ -110,12 +110,12 @@
|
|
|
110
110
|
<div class="project-header">
|
|
111
111
|
<h3 class="project-title">{{ p.title }}</h3>
|
|
112
112
|
</div>
|
|
113
|
-
{% if p.
|
|
114
|
-
<p class="project-narrative">{{ p.
|
|
113
|
+
{% if p.tagline != blank %}
|
|
114
|
+
<p class="project-narrative">{{ p.tagline }}</p>
|
|
115
115
|
{% endif %}
|
|
116
|
-
{% if p.
|
|
116
|
+
{% if p.profileSkills.size > 0 %}
|
|
117
117
|
<div class="project-skills" aria-label="Skills used">
|
|
118
|
-
{% for skill in p.
|
|
118
|
+
{% for skill in p.profileSkills %}
|
|
119
119
|
<span class="skill-chip">{{ skill }}</span>
|
|
120
120
|
{% endfor %}
|
|
121
121
|
</div>
|
|
@@ -218,7 +218,7 @@
|
|
|
218
218
|
<tr>
|
|
219
219
|
<th scope="col">#</th>
|
|
220
220
|
<th scope="col">Session</th>
|
|
221
|
-
<th scope="col">Date</th>
|
|
221
|
+
{% unless hideSessionDates %}<th scope="col">Date</th>{% endunless %}
|
|
222
222
|
<th scope="col">Duration</th>
|
|
223
223
|
<th scope="col">LOC</th>
|
|
224
224
|
<th scope="col">Source</th>
|
|
@@ -230,7 +230,7 @@
|
|
|
230
230
|
<tr>
|
|
231
231
|
<td><span class="session-num">{{ forloop.index }}</span></td>
|
|
232
232
|
<td><a href="{{ sessionBaseUrl }}/{{ s.slug }}{{ sessionSuffix }}" class="session-title-link">{{ s.title }}</a></td>
|
|
233
|
-
<td>{{ s.recordedAt | formatDateShort }}</td>
|
|
233
|
+
{% unless hideSessionDates %}<td>{{ s.recordedAt | formatDateShort }}</td>{% endunless %}
|
|
234
234
|
<td>{{ s.durationMinutes | formatDuration }}</td>
|
|
235
235
|
<td>{{ s.locChanged | localeNumber }}</td>
|
|
236
236
|
<td>{% if s.sourceTool %}<span class="session-source-badge badge-{{ s.sourceTool | downcase | replace: ' ', '-' }}">{{ s.sourceTool }}</span>{% endif %}</td>
|
|
@@ -107,17 +107,17 @@
|
|
|
107
107
|
</h2>
|
|
108
108
|
<span class="bp-project-ref">REF-{{ forloop.index | prepend: '00' | slice: -3, 3 }}</span>
|
|
109
109
|
</div>
|
|
110
|
-
{% if p.
|
|
111
|
-
<p class="bp-project-narrative">{{ p.
|
|
110
|
+
{% if p.tagline != blank %}
|
|
111
|
+
<p class="bp-project-narrative">{{ p.tagline }}</p>
|
|
112
112
|
{% endif %}
|
|
113
113
|
<div class="bp-project-meta" aria-label="Project statistics">
|
|
114
114
|
<span>{{ p.totalSessions }} sessions</span>
|
|
115
115
|
<span>{{ p.totalDurationMinutes | formatDuration }}</span>
|
|
116
116
|
<span>{{ p.totalLoc | localeNumber }} LOC</span>
|
|
117
117
|
</div>
|
|
118
|
-
{% if p.
|
|
118
|
+
{% if p.profileSkills.size > 0 %}
|
|
119
119
|
<ul class="bp-skills-list" aria-label="Skills">
|
|
120
|
-
{% for skill in p.
|
|
120
|
+
{% for skill in p.profileSkills %}
|
|
121
121
|
<li class="bp-skill-chip">{{ skill }}</li>
|
|
122
122
|
{% endfor %}
|
|
123
123
|
</ul>
|
|
@@ -124,13 +124,13 @@
|
|
|
124
124
|
<h3 class="project-card__title">{{ p.title }}</h3>
|
|
125
125
|
<span class="project-card__stats">{{ p.totalSessions }} sessions · {{ p.totalDurationMinutes | formatDuration }} · {{ p.totalLoc | formatLoc }} LOC</span>
|
|
126
126
|
</div>
|
|
127
|
-
{% if p.
|
|
128
|
-
<p class="project-card__narrative">{{ p.
|
|
127
|
+
{% if p.tagline != blank %}
|
|
128
|
+
<p class="project-card__narrative">{{ p.tagline }}</p>
|
|
129
129
|
{% endif %}
|
|
130
130
|
<div class="project-card__footer">
|
|
131
|
-
{% if p.
|
|
131
|
+
{% if p.profileSkills.size > 0 %}
|
|
132
132
|
<div class="project-card__skills">
|
|
133
|
-
{% for skill in p.
|
|
133
|
+
{% for skill in p.profileSkills %}
|
|
134
134
|
<span class="skill-pill">{{ skill }}</span>
|
|
135
135
|
{% endfor %}
|
|
136
136
|
</div>
|
|
@@ -205,7 +205,7 @@
|
|
|
205
205
|
}
|
|
206
206
|
.canvas .stat__label {
|
|
207
207
|
font-family: var(--canvas-font-mono);
|
|
208
|
-
font-size: 0.
|
|
208
|
+
font-size: 0.75rem;
|
|
209
209
|
color: var(--canvas-text-tertiary);
|
|
210
210
|
text-transform: uppercase;
|
|
211
211
|
letter-spacing: 0.1em;
|
|
@@ -340,7 +340,7 @@
|
|
|
340
340
|
}
|
|
341
341
|
.canvas .hero-stat__label {
|
|
342
342
|
font-family: var(--canvas-font-mono);
|
|
343
|
-
font-size: 0.
|
|
343
|
+
font-size: 0.75rem;
|
|
344
344
|
color: var(--canvas-text-tertiary);
|
|
345
345
|
text-transform: uppercase;
|
|
346
346
|
letter-spacing: 0.1em;
|
|
@@ -76,12 +76,12 @@
|
|
|
76
76
|
<h3 class="card__title"><a href="/{{ user.username }}/{{ p.slug }}">{{ p.title }}</a></h3>
|
|
77
77
|
</div>
|
|
78
78
|
<div class="card__body">
|
|
79
|
-
{% if p.
|
|
80
|
-
<p class="card__narrative">{{ p.
|
|
79
|
+
{% if p.tagline != blank %}
|
|
80
|
+
<p class="card__narrative">{{ p.tagline }}</p>
|
|
81
81
|
{% endif %}
|
|
82
|
-
{% if p.
|
|
82
|
+
{% if p.profileSkills.size > 0 %}
|
|
83
83
|
<ul class="skill-list" aria-label="Skills used in {{ p.title }}">
|
|
84
|
-
{% for skill in p.
|
|
84
|
+
{% for skill in p.profileSkills %}
|
|
85
85
|
<li class="skill-chip">{{ skill }}</li>
|
|
86
86
|
{% endfor %}
|
|
87
87
|
</ul>
|
|
@@ -195,7 +195,7 @@ body { background: var(--carbon-bg); color: var(--carbon-text); }
|
|
|
195
195
|
|
|
196
196
|
.carbon .stat-cell__label {
|
|
197
197
|
font-family: var(--font-mono);
|
|
198
|
-
font-size: 0.
|
|
198
|
+
font-size: 0.75rem;
|
|
199
199
|
color: var(--carbon-text-muted);
|
|
200
200
|
text-transform: uppercase;
|
|
201
201
|
letter-spacing: 0.08em;
|
|
@@ -309,7 +309,7 @@ body { background: var(--carbon-bg); color: var(--carbon-text); }
|
|
|
309
309
|
}
|
|
310
310
|
|
|
311
311
|
.carbon .card__narrative {
|
|
312
|
-
font-size:
|
|
312
|
+
font-size: 1rem;
|
|
313
313
|
color: var(--carbon-text-secondary);
|
|
314
314
|
line-height: 1.65;
|
|
315
315
|
margin-block-end: 1rem;
|
|
@@ -426,7 +426,7 @@ body { background: var(--carbon-bg); color: var(--carbon-text); }
|
|
|
426
426
|
}
|
|
427
427
|
|
|
428
428
|
.carbon.heyiam-project .stat-cell__label {
|
|
429
|
-
font-size: 0.
|
|
429
|
+
font-size: 0.75rem;
|
|
430
430
|
}
|
|
431
431
|
|
|
432
432
|
.carbon.heyiam-project .section-heading,
|
|
@@ -481,7 +481,7 @@ body { background: var(--carbon-bg); color: var(--carbon-text); }
|
|
|
481
481
|
}
|
|
482
482
|
|
|
483
483
|
.carbon .narrative p {
|
|
484
|
-
font-size:
|
|
484
|
+
font-size: 1rem;
|
|
485
485
|
color: var(--carbon-text-secondary);
|
|
486
486
|
line-height: 1.75;
|
|
487
487
|
margin-block-end: 1rem;
|
|
@@ -489,7 +489,7 @@ body { background: var(--carbon-bg); color: var(--carbon-text); }
|
|
|
489
489
|
.carbon .narrative p:last-child { margin-block-end: 0; }
|
|
490
490
|
|
|
491
491
|
.carbon .narrative-text {
|
|
492
|
-
font-size:
|
|
492
|
+
font-size: 1rem;
|
|
493
493
|
color: var(--carbon-text-secondary);
|
|
494
494
|
line-height: 1.75;
|
|
495
495
|
}
|
|
@@ -578,7 +578,7 @@ body { background: var(--carbon-bg); color: var(--carbon-text); }
|
|
|
578
578
|
display: flex;
|
|
579
579
|
gap: 0.75rem;
|
|
580
580
|
margin-block-end: 0.75rem;
|
|
581
|
-
font-size:
|
|
581
|
+
font-size: 1rem;
|
|
582
582
|
color: var(--carbon-text-secondary);
|
|
583
583
|
line-height: 1.6;
|
|
584
584
|
}
|
|
@@ -739,7 +739,7 @@ body { background: var(--carbon-bg); color: var(--carbon-text); }
|
|
|
739
739
|
}
|
|
740
740
|
|
|
741
741
|
.carbon .dev-take__text {
|
|
742
|
-
font-size:
|
|
742
|
+
font-size: 1rem;
|
|
743
743
|
color: var(--carbon-text);
|
|
744
744
|
line-height: 1.7;
|
|
745
745
|
font-style: italic;
|
|
@@ -98,17 +98,17 @@
|
|
|
98
98
|
{% for p in projects %}
|
|
99
99
|
<article class="chalk-card fade-in">
|
|
100
100
|
<h3 class="project-name"><a href="/{{ user.username }}/{{ p.slug }}">{{ p.title }}</a></h3>
|
|
101
|
-
{% if p.
|
|
102
|
-
<p class="project-narrative">{{ p.
|
|
101
|
+
{% if p.tagline != blank %}
|
|
102
|
+
<p class="project-narrative">{{ p.tagline }}</p>
|
|
103
103
|
{% endif %}
|
|
104
104
|
<div class="project-meta" aria-label="Project statistics">
|
|
105
105
|
<span>{{ p.totalSessions }} sessions</span>
|
|
106
106
|
<span>{{ p.totalDurationMinutes | formatDuration }}</span>
|
|
107
107
|
<span>{{ p.totalLoc | formatLoc }} LOC</span>
|
|
108
108
|
</div>
|
|
109
|
-
{% if p.
|
|
109
|
+
{% if p.profileSkills.size > 0 %}
|
|
110
110
|
<ul class="skills-list" aria-label="Skills">
|
|
111
|
-
{% for skill in p.
|
|
111
|
+
{% for skill in p.profileSkills %}
|
|
112
112
|
<li class="skill-chip">{{ skill }}</li>
|
|
113
113
|
{% endfor %}
|
|
114
114
|
</ul>
|
|
@@ -326,7 +326,7 @@ a:visited { color: inherit; }
|
|
|
326
326
|
}
|
|
327
327
|
.stat-label {
|
|
328
328
|
font-family: var(--font-mono);
|
|
329
|
-
font-size:
|
|
329
|
+
font-size: 12px;
|
|
330
330
|
text-transform: uppercase;
|
|
331
331
|
letter-spacing: 0.06em;
|
|
332
332
|
color: var(--fg-muted);
|
|
@@ -389,7 +389,7 @@ a:visited { color: inherit; }
|
|
|
389
389
|
}
|
|
390
390
|
.stat-item-label {
|
|
391
391
|
font-family: var(--font-mono);
|
|
392
|
-
font-size:
|
|
392
|
+
font-size: 12px;
|
|
393
393
|
text-transform: uppercase;
|
|
394
394
|
letter-spacing: 0.06em;
|
|
395
395
|
color: var(--fg-muted);
|
|
@@ -1156,6 +1156,48 @@ a.project-card:hover, a.session-card:hover {
|
|
|
1156
1156
|
}
|
|
1157
1157
|
}
|
|
1158
1158
|
|
|
1159
|
+
@media (max-width: 480px) {
|
|
1160
|
+
.hero {
|
|
1161
|
+
padding: 24px 0 20px;
|
|
1162
|
+
}
|
|
1163
|
+
.hero h1 {
|
|
1164
|
+
font-size: 1.5rem;
|
|
1165
|
+
}
|
|
1166
|
+
.heyiam-project .hero h1,
|
|
1167
|
+
.heyiam-session .hero h1 {
|
|
1168
|
+
font-size: 1.375rem;
|
|
1169
|
+
}
|
|
1170
|
+
.stats-grid {
|
|
1171
|
+
grid-template-columns: 1fr;
|
|
1172
|
+
}
|
|
1173
|
+
.chalk-card {
|
|
1174
|
+
padding: 16px;
|
|
1175
|
+
}
|
|
1176
|
+
.project-name {
|
|
1177
|
+
font-size: 1.125rem;
|
|
1178
|
+
}
|
|
1179
|
+
.sessions-table {
|
|
1180
|
+
font-size: 11px;
|
|
1181
|
+
}
|
|
1182
|
+
.sessions-table thead th,
|
|
1183
|
+
.sessions-table tbody td {
|
|
1184
|
+
padding: 6px 4px;
|
|
1185
|
+
}
|
|
1186
|
+
.agent-row {
|
|
1187
|
+
grid-template-columns: 80px 1fr 48px;
|
|
1188
|
+
gap: 6px;
|
|
1189
|
+
font-size: 12px;
|
|
1190
|
+
}
|
|
1191
|
+
.hero-meta {
|
|
1192
|
+
flex-direction: column;
|
|
1193
|
+
gap: 4px;
|
|
1194
|
+
}
|
|
1195
|
+
.profile-links {
|
|
1196
|
+
flex-direction: column;
|
|
1197
|
+
gap: 4px;
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1159
1201
|
|
|
1160
1202
|
/* Live-edit empty field hiding */
|
|
1161
1203
|
[data-portfolio-empty="true"] { display: none; }
|
|
@@ -126,17 +126,17 @@
|
|
|
126
126
|
<div class="project-card-header">
|
|
127
127
|
<h3><a href="/{{ user.username }}/{{ p.slug }}">{{ p.title }}</a></h3>
|
|
128
128
|
</div>
|
|
129
|
-
{% if p.
|
|
130
|
-
<p class="project-card-narrative">{{ p.
|
|
129
|
+
{% if p.tagline != blank %}
|
|
130
|
+
<p class="project-card-narrative">{{ p.tagline }}</p>
|
|
131
131
|
{% endif %}
|
|
132
132
|
<div class="project-card-stats">
|
|
133
133
|
<span><span class="val">{{ p.totalSessions }}</span> sessions</span>
|
|
134
134
|
<span><span class="val">{{ p.totalDurationMinutes | formatDuration }}</span></span>
|
|
135
135
|
<span><span class="val">{{ p.totalLoc | formatLoc }}</span> LOC</span>
|
|
136
136
|
</div>
|
|
137
|
-
{% if p.
|
|
137
|
+
{% if p.profileSkills.size > 0 %}
|
|
138
138
|
<div class="skill-pins">
|
|
139
|
-
{% for skill in p.
|
|
139
|
+
{% for skill in p.profileSkills %}
|
|
140
140
|
<span class="skill-pin">{{ skill }}</span>
|
|
141
141
|
{% endfor %}
|
|
142
142
|
</div>
|
|
@@ -119,17 +119,17 @@
|
|
|
119
119
|
<div class="cos-project-card-header">
|
|
120
120
|
<h3><a href="/{{ user.username }}/{{ p.slug }}">{{ p.title }}</a></h3>
|
|
121
121
|
</div>
|
|
122
|
-
{% if p.
|
|
123
|
-
<p class="cos-project-card-narrative">{{ p.
|
|
122
|
+
{% if p.tagline != blank %}
|
|
123
|
+
<p class="cos-project-card-narrative">{{ p.tagline }}</p>
|
|
124
124
|
{% endif %}
|
|
125
125
|
<div class="cos-project-card-meta">
|
|
126
126
|
<span><strong>{{ p.totalSessions }}</strong> sessions</span>
|
|
127
127
|
<span><strong>{{ p.totalDurationMinutes | formatDuration }}</strong></span>
|
|
128
128
|
<span><strong>{{ p.totalLoc | localeNumber }}</strong> LOC</span>
|
|
129
129
|
</div>
|
|
130
|
-
{% if p.
|
|
130
|
+
{% if p.profileSkills.size > 0 %}
|
|
131
131
|
<div class="cos-skill-chips">
|
|
132
|
-
{% for skill in p.
|
|
132
|
+
{% for skill in p.profileSkills %}
|
|
133
133
|
<span class="cos-skill-chip">{{ skill }}</span>
|
|
134
134
|
{% endfor %}
|
|
135
135
|
</div>
|
|
@@ -246,7 +246,7 @@ body { background: var(--cos-bg); color: var(--cos-text); }
|
|
|
246
246
|
}
|
|
247
247
|
.cosmos .cos-narrative p {
|
|
248
248
|
color: var(--cos-text-secondary);
|
|
249
|
-
font-size:
|
|
249
|
+
font-size: 1rem;
|
|
250
250
|
line-height: 1.75;
|
|
251
251
|
margin-block-end: 1rem;
|
|
252
252
|
}
|
|
@@ -431,7 +431,7 @@ body { background: var(--cos-bg); color: var(--cos-text); }
|
|
|
431
431
|
}
|
|
432
432
|
.cosmos .cos-project-card-narrative {
|
|
433
433
|
color: var(--cos-text-secondary);
|
|
434
|
-
font-size:
|
|
434
|
+
font-size: 1rem;
|
|
435
435
|
line-height: 1.6;
|
|
436
436
|
margin-block-end: 1.25rem;
|
|
437
437
|
}
|
|
@@ -710,7 +710,7 @@ body { background: var(--cos-bg); color: var(--cos-text); }
|
|
|
710
710
|
}
|
|
711
711
|
.cosmos .cos-decision p {
|
|
712
712
|
color: var(--cos-text-secondary);
|
|
713
|
-
font-size:
|
|
713
|
+
font-size: 1rem;
|
|
714
714
|
line-height: 1.5;
|
|
715
715
|
}
|
|
716
716
|
|
|
@@ -890,7 +890,7 @@ body { background: var(--cos-bg); color: var(--cos-text); }
|
|
|
890
890
|
}
|
|
891
891
|
.cosmos .cos-dev-take blockquote {
|
|
892
892
|
color: var(--cos-text-secondary);
|
|
893
|
-
font-size:
|
|
893
|
+
font-size: 1rem;
|
|
894
894
|
line-height: 1.7;
|
|
895
895
|
font-style: italic;
|
|
896
896
|
border: none;
|
|
@@ -92,15 +92,15 @@
|
|
|
92
92
|
<h3 class="dl-project-title">
|
|
93
93
|
<a href="/{{ user.username }}/{{ p.slug }}">{{ p.title }}</a>
|
|
94
94
|
</h3>
|
|
95
|
-
{% if p.
|
|
96
|
-
<p class="dl-project-narrative">{{ p.
|
|
95
|
+
{% if p.tagline != blank %}
|
|
96
|
+
<p class="dl-project-narrative">{{ p.tagline }}</p>
|
|
97
97
|
{% endif %}
|
|
98
98
|
<p class="dl-project-meta">
|
|
99
99
|
{{ p.totalSessions }} session{% if p.totalSessions != 1 %}s{% endif %} · {{ p.totalDurationMinutes | formatDuration }} · {{ p.totalLoc | localeNumber }} LOC
|
|
100
100
|
</p>
|
|
101
|
-
{% if p.
|
|
101
|
+
{% if p.profileSkills.size > 0 %}
|
|
102
102
|
<div class="dl-project-skills">
|
|
103
|
-
{% for skill in p.
|
|
103
|
+
{% for skill in p.profileSkills %}
|
|
104
104
|
<span class="dl-skill-chip">{{ skill }}</span>
|
|
105
105
|
{% endfor %}
|
|
106
106
|
</div>
|
|
@@ -86,17 +86,17 @@
|
|
|
86
86
|
{% for p in projects %}
|
|
87
87
|
<a href="/{{ user.username }}/{{ p.slug }}" class="ed-project-card">
|
|
88
88
|
<h3 class="ed-project-card-title">{{ p.title }}</h3>
|
|
89
|
-
{% if p.
|
|
90
|
-
<p class="ed-project-card-narrative">{{ p.
|
|
89
|
+
{% if p.tagline != blank %}
|
|
90
|
+
<p class="ed-project-card-narrative">{{ p.tagline }}</p>
|
|
91
91
|
{% endif %}
|
|
92
92
|
<div class="ed-project-card-stats">
|
|
93
93
|
<span class="ed-project-card-stat"><strong>{{ p.totalSessions }}</strong> sessions</span>
|
|
94
94
|
<span class="ed-project-card-stat"><strong>{{ p.totalLoc | localeNumber }}</strong> LOC</span>
|
|
95
95
|
<span class="ed-project-card-stat"><strong>{{ p.totalDurationMinutes | formatDuration }}</strong></span>
|
|
96
96
|
</div>
|
|
97
|
-
{% if p.
|
|
97
|
+
{% if p.profileSkills.size > 0 %}
|
|
98
98
|
<div class="ed-chip-list">
|
|
99
|
-
{% for skill in p.
|
|
99
|
+
{% for skill in p.profileSkills %}
|
|
100
100
|
<span class="chip chip--violet">{{ skill }}</span>
|
|
101
101
|
{% endfor %}
|
|
102
102
|
</div>
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
{% if sessionsJson %}
|
|
91
91
|
<section class="ed-card-section" aria-label="Agent work timeline">
|
|
92
92
|
<h2 class="ed-section-title">Work Timeline</h2>
|
|
93
|
-
<div data-work-timeline data-sessions='{{ sessionsJson | raw }}'></div>
|
|
93
|
+
<div data-work-timeline data-sessions='{{ sessionsJson | raw }}'{% if hideSessionDates %} data-hide-dates="1"{% endif %}></div>
|
|
94
94
|
</section>
|
|
95
95
|
{% endif %}
|
|
96
96
|
|