heyiam 0.2.28 → 0.3.0

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.
Files changed (177) hide show
  1. package/README.md +45 -0
  2. package/dist/config.js +10 -1
  3. package/dist/db.js +1 -2
  4. package/dist/export.js +40 -25
  5. package/dist/format-utils.js +5 -0
  6. package/dist/index.js +168 -0
  7. package/dist/mount.js +300 -102
  8. package/dist/parsers/claude.js +2 -28
  9. package/dist/parsers/codex.js +2 -26
  10. package/dist/parsers/cursor.js +2 -26
  11. package/dist/parsers/duration.js +35 -0
  12. package/dist/parsers/gemini.js +2 -20
  13. package/dist/parsers/types.js +0 -1
  14. package/dist/public/assets/index-BZ65TU_Y.js +40 -0
  15. package/dist/public/assets/index-CqCaW2cb.css +1 -0
  16. package/dist/public/index.html +2 -2
  17. package/dist/redact.js +4 -104
  18. package/dist/render/build-render-data.js +9 -2
  19. package/dist/render/index.js +32 -5
  20. package/dist/render/liquid.js +147 -7
  21. package/dist/render/mock-data.js +303 -0
  22. package/dist/render/templates/aurora/portfolio.liquid +204 -0
  23. package/dist/render/templates/aurora/project.liquid +260 -0
  24. package/dist/render/templates/aurora/session.liquid +223 -0
  25. package/dist/render/templates/aurora/styles.css +1178 -0
  26. package/dist/render/templates/bauhaus/portfolio.liquid +179 -0
  27. package/dist/render/templates/bauhaus/project.liquid +300 -0
  28. package/dist/render/templates/bauhaus/session.liquid +333 -0
  29. package/dist/render/templates/bauhaus/styles.css +1641 -0
  30. package/dist/render/templates/blueprint/portfolio.liquid +167 -0
  31. package/dist/render/templates/blueprint/project.liquid +286 -0
  32. package/dist/render/templates/blueprint/session.liquid +248 -0
  33. package/dist/render/templates/blueprint/styles.css +1285 -0
  34. package/dist/render/templates/canvas/portfolio.liquid +215 -0
  35. package/dist/render/templates/canvas/project.liquid +235 -0
  36. package/dist/render/templates/canvas/session.liquid +223 -0
  37. package/dist/render/templates/canvas/styles.css +1436 -0
  38. package/dist/render/templates/carbon/portfolio.liquid +170 -0
  39. package/dist/render/templates/carbon/project.liquid +249 -0
  40. package/dist/render/templates/carbon/session.liquid +190 -0
  41. package/dist/render/templates/carbon/styles.css +1091 -0
  42. package/dist/render/templates/chalk/portfolio.liquid +199 -0
  43. package/dist/render/templates/chalk/project.liquid +245 -0
  44. package/dist/render/templates/chalk/session.liquid +215 -0
  45. package/dist/render/templates/chalk/styles.css +1157 -0
  46. package/dist/render/templates/circuit/portfolio.liquid +162 -0
  47. package/dist/render/templates/circuit/project.liquid +247 -0
  48. package/dist/render/templates/circuit/session.liquid +205 -0
  49. package/dist/render/templates/circuit/styles.css +1403 -0
  50. package/dist/render/templates/cosmos/portfolio.liquid +232 -0
  51. package/dist/render/templates/cosmos/project.liquid +327 -0
  52. package/dist/render/templates/cosmos/session.liquid +239 -0
  53. package/dist/render/templates/cosmos/styles.css +1151 -0
  54. package/dist/render/templates/daylight/portfolio.liquid +217 -0
  55. package/dist/render/templates/daylight/project.liquid +229 -0
  56. package/dist/render/templates/daylight/session.liquid +219 -0
  57. package/dist/render/templates/daylight/styles.css +1311 -0
  58. package/dist/render/templates/editorial/portfolio.liquid +126 -0
  59. package/dist/render/templates/editorial/project.liquid +202 -0
  60. package/dist/render/templates/editorial/session.liquid +171 -0
  61. package/dist/render/templates/editorial/styles.css +822 -0
  62. package/dist/render/templates/ember/portfolio.liquid +318 -0
  63. package/dist/render/templates/ember/project.liquid +232 -0
  64. package/dist/render/templates/ember/session.liquid +202 -0
  65. package/dist/render/templates/ember/styles.css +1283 -0
  66. package/dist/render/templates/glacier/portfolio.liquid +271 -0
  67. package/dist/render/templates/glacier/project.liquid +288 -0
  68. package/dist/render/templates/glacier/session.liquid +217 -0
  69. package/dist/render/templates/glacier/styles.css +1200 -0
  70. package/dist/render/templates/grid/portfolio.liquid +265 -0
  71. package/dist/render/templates/grid/project.liquid +306 -0
  72. package/dist/render/templates/grid/session.liquid +260 -0
  73. package/dist/render/templates/grid/styles.css +1441 -0
  74. package/dist/render/templates/kinetic/portfolio.liquid +170 -0
  75. package/dist/render/templates/kinetic/project.liquid +242 -0
  76. package/dist/render/templates/kinetic/session.liquid +228 -0
  77. package/dist/render/templates/kinetic/styles.css +944 -0
  78. package/dist/render/templates/meridian/portfolio.liquid +255 -0
  79. package/dist/render/templates/meridian/project.liquid +376 -0
  80. package/dist/render/templates/meridian/session.liquid +298 -0
  81. package/dist/render/templates/meridian/styles.css +1369 -0
  82. package/dist/render/templates/minimal/portfolio.liquid +71 -0
  83. package/dist/render/templates/minimal/project.liquid +154 -0
  84. package/dist/render/templates/minimal/session.liquid +140 -0
  85. package/dist/render/templates/minimal/styles.css +525 -0
  86. package/dist/render/templates/mono/portfolio.liquid +291 -0
  87. package/dist/render/templates/mono/project.liquid +275 -0
  88. package/dist/render/templates/mono/session.liquid +276 -0
  89. package/dist/render/templates/mono/styles.css +1016 -0
  90. package/dist/render/templates/neon/portfolio.liquid +217 -0
  91. package/dist/render/templates/neon/project.liquid +225 -0
  92. package/dist/render/templates/neon/session.liquid +195 -0
  93. package/dist/render/templates/neon/styles.css +1265 -0
  94. package/dist/render/templates/noir/portfolio.liquid +137 -0
  95. package/dist/render/templates/noir/project.liquid +220 -0
  96. package/dist/render/templates/noir/session.liquid +241 -0
  97. package/dist/render/templates/noir/styles.css +1223 -0
  98. package/dist/render/templates/obsidian/portfolio.liquid +257 -0
  99. package/dist/render/templates/obsidian/project.liquid +280 -0
  100. package/dist/render/templates/obsidian/session.liquid +241 -0
  101. package/dist/render/templates/obsidian/styles.css +1401 -0
  102. package/dist/render/templates/paper/portfolio.liquid +267 -0
  103. package/dist/render/templates/paper/project.liquid +235 -0
  104. package/dist/render/templates/paper/session.liquid +271 -0
  105. package/dist/render/templates/paper/styles.css +1509 -0
  106. package/dist/render/templates/parallax/portfolio.liquid +305 -0
  107. package/dist/render/templates/parallax/project.liquid +275 -0
  108. package/dist/render/templates/parallax/session.liquid +295 -0
  109. package/dist/render/templates/parallax/styles.css +1874 -0
  110. package/dist/render/templates/parchment/portfolio.liquid +290 -0
  111. package/dist/render/templates/parchment/project.liquid +289 -0
  112. package/dist/render/templates/parchment/session.liquid +346 -0
  113. package/dist/render/templates/parchment/styles.css +1397 -0
  114. package/dist/render/templates/partials/_beats.liquid +16 -0
  115. package/dist/render/templates/partials/_breadcrumb.liquid +9 -0
  116. package/dist/render/templates/partials/_footer.liquid +7 -0
  117. package/dist/render/templates/partials/_growth-chart.liquid +7 -0
  118. package/dist/render/templates/partials/_key-decisions.liquid +20 -0
  119. package/dist/render/templates/partials/_links.liquid +16 -0
  120. package/dist/render/templates/partials/_narrative.liquid +8 -0
  121. package/dist/render/templates/partials/_phases.liquid +20 -0
  122. package/dist/render/templates/partials/_portfolio-header.liquid +20 -0
  123. package/dist/render/templates/partials/_portfolio-projects.liquid +16 -0
  124. package/dist/render/templates/partials/_portfolio-stats.liquid +19 -0
  125. package/dist/render/templates/partials/_qa.liquid +13 -0
  126. package/dist/render/templates/partials/_screenshot.liquid +15 -0
  127. package/dist/render/templates/partials/_session-cards.liquid +30 -0
  128. package/dist/render/templates/partials/_session-header.liquid +39 -0
  129. package/dist/render/templates/partials/_session-sidebar.liquid +30 -0
  130. package/dist/render/templates/partials/_skills.liquid +12 -0
  131. package/dist/render/templates/partials/_source-breakdown.liquid +22 -0
  132. package/dist/render/templates/partials/_stats.liquid +38 -0
  133. package/dist/render/templates/partials/_work-timeline.liquid +7 -0
  134. package/dist/render/templates/project.liquid +7 -4
  135. package/dist/render/templates/radar/portfolio.liquid +233 -0
  136. package/dist/render/templates/radar/project.liquid +278 -0
  137. package/dist/render/templates/radar/session.liquid +300 -0
  138. package/dist/render/templates/radar/styles.css +1049 -0
  139. package/dist/render/templates/showcase/portfolio.liquid +231 -0
  140. package/dist/render/templates/showcase/project.liquid +237 -0
  141. package/dist/render/templates/showcase/session.liquid +210 -0
  142. package/dist/render/templates/showcase/styles.css +1279 -0
  143. package/dist/render/templates/signal/portfolio.liquid +227 -0
  144. package/dist/render/templates/signal/project.liquid +278 -0
  145. package/dist/render/templates/signal/session.liquid +282 -0
  146. package/dist/render/templates/signal/styles.css +1395 -0
  147. package/dist/render/templates/strata/portfolio.liquid +192 -0
  148. package/dist/render/templates/strata/project.liquid +282 -0
  149. package/dist/render/templates/strata/session.liquid +261 -0
  150. package/dist/render/templates/strata/styles.css +1350 -0
  151. package/dist/render/templates/styles.css +1190 -0
  152. package/dist/render/templates/terminal/portfolio.liquid +118 -0
  153. package/dist/render/templates/terminal/project.liquid +161 -0
  154. package/dist/render/templates/terminal/session.liquid +145 -0
  155. package/dist/render/templates/terminal/styles.css +492 -0
  156. package/dist/render/templates/verdant/portfolio.liquid +333 -0
  157. package/dist/render/templates/verdant/project.liquid +309 -0
  158. package/dist/render/templates/verdant/session.liquid +237 -0
  159. package/dist/render/templates/verdant/styles.css +1257 -0
  160. package/dist/render/templates/zen/portfolio.liquid +136 -0
  161. package/dist/render/templates/zen/project.liquid +187 -0
  162. package/dist/render/templates/zen/session.liquid +203 -0
  163. package/dist/render/templates/zen/styles.css +1207 -0
  164. package/dist/render/templates.js +90 -0
  165. package/dist/routes/context.js +15 -10
  166. package/dist/routes/enhance.js +17 -40
  167. package/dist/routes/export.js +14 -4
  168. package/dist/routes/preview.js +480 -108
  169. package/dist/routes/projects.js +11 -19
  170. package/dist/routes/publish.js +15 -17
  171. package/dist/routes/settings.js +94 -1
  172. package/dist/routes/sse.js +9 -0
  173. package/dist/server.js +8 -2
  174. package/dist/settings.js +17 -9
  175. package/package.json +2 -4
  176. package/dist/public/assets/index-B_d6DlEI.js +0 -21
  177. package/dist/public/assets/index-Dalqz2mC.css +0 -1
@@ -0,0 +1,199 @@
1
+ <div class="heyiam-portfolio chalk" data-render-version="2" data-template="chalk" data-username="{{ user.username }}">
2
+
3
+ {%- comment -%} SVG filters {%- endcomment -%}
4
+ <svg class="svg-filters" aria-hidden="true">
5
+ <defs>
6
+ <filter id="chalk-rough">
7
+ <feTurbulence type="turbulence" baseFrequency="0.03" numOctaves="4" seed="1" result="noise" />
8
+ <feDisplacementMap in="SourceGraphic" in2="noise" scale="1.2" xChannelSelector="R" yChannelSelector="G" />
9
+ </filter>
10
+ </defs>
11
+ </svg>
12
+
13
+ {%- comment -%} Hero {%- endcomment -%}
14
+ {% if hasProfile %}
15
+ <section class="hero" aria-label="Profile">
16
+ {% if user.photoUrl %}
17
+ <img src="{{ user.photoUrl }}" alt="{{ user.displayName }}" class="hero-photo portfolio-photo" width="120" height="120">
18
+ {% endif %}
19
+ {% if user.displayName != blank %}
20
+ <h1>{{ user.displayName }}</h1>
21
+ {% endif %}
22
+ {% if user.bio != blank %}
23
+ <p class="hero-bio portfolio-bio">{{ user.bio }}</p>
24
+ {% endif %}
25
+ {% if user.location != blank %}
26
+ <p class="hero-location portfolio-location">{{ user.location }}</p>
27
+ {% endif %}
28
+ <div class="profile-links">
29
+ {% if user.email %}
30
+ <a href="mailto:{{ user.email }}">
31
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m2 4 10 8 10-8"/></svg>
32
+ {{ user.email }}
33
+ </a>
34
+ {% endif %}
35
+ {% if user.linkedinUrl %}
36
+ <a href="{{ user.linkedinUrl }}" target="_blank" rel="noopener">
37
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M20.5 2h-17A1.5 1.5 0 002 3.5v17A1.5 1.5 0 003.5 22h17a1.5 1.5 0 001.5-1.5v-17A1.5 1.5 0 0020.5 2zM8 19H5v-9h3zM6.5 8.25A1.75 1.75 0 118.3 6.5a1.78 1.78 0 01-1.8 1.75zM19 19h-3v-4.74c0-1.42-.6-1.93-1.38-1.93A1.74 1.74 0 0013 14.19V19h-3v-9h2.9v1.3a3.11 3.11 0 012.7-1.4c1.55 0 3.36.86 3.36 3.66z"/></svg>
38
+ LinkedIn
39
+ </a>
40
+ {% endif %}
41
+ {% if user.githubUrl %}
42
+ <a href="{{ user.githubUrl }}" target="_blank" rel="noopener">
43
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"/></svg>
44
+ GitHub
45
+ </a>
46
+ {% endif %}
47
+ {% if user.twitterHandle %}
48
+ <a href="https://x.com/{{ user.twitterHandle }}" target="_blank" rel="noopener">
49
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
50
+ @{{ user.twitterHandle }}
51
+ </a>
52
+ {% endif %}
53
+ {% if user.websiteUrl %}
54
+ <a href="{{ user.websiteUrl }}" target="_blank" rel="noopener">{{ user.websiteUrl | stripProtocol }}</a>
55
+ {% endif %}
56
+ {% if user.resumeUrl %}
57
+ <a href="{{ user.resumeUrl }}" download>
58
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="12" y1="18" x2="12" y2="12"/><polyline points="9 15 12 18 15 15"/></svg>
59
+ Resume (PDF)
60
+ </a>
61
+ {% endif %}
62
+ </div>
63
+ </section>
64
+ {% endif %}
65
+
66
+ {%- comment -%} Stats {%- endcomment -%}
67
+ <section class="stats-section" aria-label="Aggregate statistics">
68
+ <h2 class="section-heading"><span class="sketch-underline">The Numbers</span></h2>
69
+ <div class="stats-grid" role="list">
70
+ <div class="stat-card" role="listitem">
71
+ <div class="stat-value" data-target="{{ projects.size }}">0</div>
72
+ <div class="stat-label">Projects</div>
73
+ </div>
74
+ <div class="stat-card" role="listitem">
75
+ <div class="stat-value" data-target="{{ totalSessions }}">0</div>
76
+ <div class="stat-label">Sessions</div>
77
+ </div>
78
+ <div class="stat-card" role="listitem">
79
+ <div class="stat-value" data-target="{{ totalLoc }}">0</div>
80
+ <div class="stat-label">Lines Changed</div>
81
+ </div>
82
+ </div>
83
+ {% if efficiencyMultiplier %}
84
+ <div class="leverage-annotation" role="img" aria-label="Leverage multiplier">
85
+ <div class="leverage-annotation__numbers">
86
+ <span class="leverage-annotation__human">{{ totalDurationMinutes | formatDuration }} <small>you</small></span>
87
+ <span class="leverage-annotation__arrow">&rarr;</span>
88
+ <span class="leverage-annotation__agent">{{ totalAgentDurationMinutes | formatDuration }} <small>agents</small></span>
89
+ <span class="leverage-annotation__arrow">=</span>
90
+ <span class="leverage-annotation__multiplier">{{ efficiencyMultiplier }}</span>
91
+ </div>
92
+ </div>
93
+ {% else %}
94
+ <div class="leverage-annotation" role="img" aria-label="Total time">
95
+ <div class="leverage-annotation__numbers">
96
+ <span class="leverage-annotation__human">{{ totalDurationMinutes | formatDuration }}</span>
97
+ <small class="leverage-annotation__arrow">Total Time</small>
98
+ </div>
99
+ </div>
100
+ {% endif %}
101
+ </section>
102
+
103
+ {%- comment -%} Projects {%- endcomment -%}
104
+ {% if projects.size > 0 %}
105
+ <section class="projects-section" aria-label="Projects">
106
+ <h2 class="section-heading"><span class="sketch-underline">Projects</span></h2>
107
+
108
+ {% for p in projects %}
109
+ <article class="chalk-card fade-in">
110
+ <h3 class="project-name"><a href="/{{ user.username }}/{{ p.slug }}">{{ p.title }}</a></h3>
111
+ {% if p.narrative %}
112
+ <p class="project-narrative">{{ p.narrative | truncate: 120 }}</p>
113
+ {% endif %}
114
+ <div class="project-meta" aria-label="Project statistics">
115
+ <span>{{ p.totalSessions }} sessions</span>
116
+ <span>{{ p.totalDurationMinutes | formatDuration }}</span>
117
+ <span>{{ p.totalLoc | formatLoc }} LOC</span>
118
+ </div>
119
+ {% if p.skills.size > 0 %}
120
+ <ul class="skills-list" aria-label="Skills">
121
+ {% for skill in p.skills %}
122
+ <li class="skill-chip">{{ skill }}</li>
123
+ {% endfor %}
124
+ </ul>
125
+ {% endif %}
126
+ </article>
127
+ {% endfor %}
128
+ </section>
129
+ {% endif %}
130
+
131
+ {%- comment -%} Activity Chart {%- endcomment -%}
132
+ {% if activityByMonth.size > 0 %}
133
+ {% assign maxSessions = 0 %}
134
+ {% for m in activityByMonth %}
135
+ {% if m.sessions > maxSessions %}{% assign maxSessions = m.sessions %}{% endif %}
136
+ {% endfor %}
137
+ <section class="activity-section" aria-label="Activity overview">
138
+ <h2 class="section-heading"><span class="sketch-underline">Activity</span></h2>
139
+ <div class="activity-chart" role="img" aria-label="Monthly session activity">
140
+ <svg viewBox="0 0 800 200" preserveAspectRatio="xMidYMid meet">
141
+ <line x1="60" y1="30" x2="60" y2="150" stroke="#e2e8f0" stroke-width="1" stroke-dasharray="6 4" />
142
+ <line x1="60" y1="150" x2="780" y2="150" stroke="#e2e8f0" stroke-width="1" stroke-dasharray="6 4" />
143
+ {% assign spacing = 720 | divided_by: activityByMonth.size %}
144
+ {% for m in activityByMonth %}
145
+ {% if maxSessions > 0 %}
146
+ {% assign barH = m.sessions | times: 120 | divided_by: maxSessions %}
147
+ {% else %}
148
+ {% assign barH = 0 %}
149
+ {% endif %}
150
+ {% assign halfSpace = spacing | divided_by: 2 %}
151
+ {% assign centerX = forloop.index0 | times: spacing | plus: 60 | plus: halfSpace %}
152
+ {% assign barX = centerX | minus: 20 %}
153
+ {% assign barY = 150 | minus: barH %}
154
+ <rect x="{{ barX }}" y="{{ barY }}" width="40" height="{{ barH }}" rx="3" fill="#334155" opacity="0.7" filter="url(#chalk-rough)"/>
155
+ <text x="{{ centerX }}" y="170" text-anchor="middle" font-family="'Caveat', cursive" font-size="14" fill="#334155">{{ m.month }}</text>
156
+ {% assign labelY = barY | minus: 8 %}
157
+ <text x="{{ centerX }}" y="{{ labelY }}" text-anchor="middle" font-family="'IBM Plex Mono', monospace" font-size="10" fill="#64748b">{{ m.sessions }}</text>
158
+ {% endfor %}
159
+ </svg>
160
+ </div>
161
+ </section>
162
+ {% endif %}
163
+
164
+ {%- comment -%} Source Overview {%- endcomment -%}
165
+ {% if sourceCounts.size > 0 %}
166
+ <section class="source-overview" aria-label="Overall source breakdown">
167
+ <h2 class="section-heading"><span class="sketch-underline">Source Mix</span></h2>
168
+ <div class="source-bar-lg" role="img" aria-label="Overall source breakdown">
169
+ {% assign firstSrcPct = sourceCounts[0].count | times: 100.0 | divided_by: totalSourceSessions | round %}
170
+ <div class="source-fill-lg" style="width: {{ firstSrcPct }}%"></div>
171
+ </div>
172
+ <div class="source-legend-lg">
173
+ {% for src in sourceCounts %}
174
+ {% assign srcPct = src.count | times: 100.0 | divided_by: totalSourceSessions | round %}
175
+ <span><span class="dot-{{ src.tool | downcase | replace: ' ', '-' }}-lg"></span> {{ src.tool }} {{ srcPct }}%</span>
176
+ {% endfor %}
177
+ </div>
178
+ </section>
179
+ {% endif %}
180
+
181
+ {%- comment -%} Skills Overview {%- endcomment -%}
182
+ {% if allSkills.size > 0 %}
183
+ <section class="skills-overview" aria-label="All skills">
184
+ <h2 class="section-heading"><span class="sketch-underline">Skills</span></h2>
185
+ <div class="skills-grid" role="list">
186
+ {% for skill in topSkills %}
187
+ <div class="skill-card" role="listitem">
188
+ <div class="skill-card-name">{{ skill.name }}</div>
189
+ <div class="skill-card-count">{{ skill.projectCount }}</div>
190
+ <div class="skill-card-label">project{% if skill.projectCount != 1 %}s{% endif %}</div>
191
+ </div>
192
+ {% endfor %}
193
+ </div>
194
+ </section>
195
+ {% endif %}
196
+
197
+ {%- comment -%} Counter animation script {%- endcomment -%}
198
+
199
+ </div>
@@ -0,0 +1,245 @@
1
+ <div class="heyiam-project chalk" data-render-version="2" data-template="chalk"{% if sessionBaseUrl %} data-session-base-url="{{ sessionBaseUrl }}"{% endif %} data-username="{{ user.username }}" data-project-slug="{{ project.slug }}">
2
+
3
+ {%- comment -%} SVG filters {%- endcomment -%}
4
+ <svg class="svg-filters" aria-hidden="true">
5
+ <defs>
6
+ <filter id="chalk-rough">
7
+ <feTurbulence type="turbulence" baseFrequency="0.03" numOctaves="4" seed="1" result="noise" />
8
+ <feDisplacementMap in="SourceGraphic" in2="noise" scale="1.2" xChannelSelector="R" yChannelSelector="G" />
9
+ </filter>
10
+ </defs>
11
+ </svg>
12
+
13
+ {%- comment -%} Hero {%- endcomment -%}
14
+ <section class="hero" aria-label="Project header">
15
+ <h1 data-editable="title">{{ project.title }}</h1>
16
+ {% if project.repoUrl or project.projectUrl %}
17
+ <p class="hero-links">
18
+ {% if project.repoUrl %}
19
+ <a href="{{ project.repoUrl }}" target="_blank" rel="noopener">{{ project.repoUrl | stripProtocol }}</a>
20
+ {% endif %}
21
+ {% if project.repoUrl and project.projectUrl %}
22
+ &middot;
23
+ {% endif %}
24
+ {% if project.projectUrl %}
25
+ <a href="{{ project.projectUrl }}" target="_blank" rel="noopener">{{ project.projectUrl | stripProtocol }}</a>
26
+ {% endif %}
27
+ </p>
28
+ {% endif %}
29
+ </section>
30
+
31
+ {%- comment -%} Screenshot {%- endcomment -%}
32
+ {% if project.screenshotUrl %}
33
+ <div class="screenshot browser-chrome" role="img" aria-label="{{ project.title }} screenshot">
34
+ <div class="screenshot-chrome" aria-hidden="true">
35
+ <span class="chrome-dot"></span>
36
+ <span class="chrome-dot"></span>
37
+ <span class="chrome-dot"></span>
38
+ </div>
39
+ <img src="{{ project.screenshotUrl }}" alt="{{ project.title }} screenshot" style="width: 100%; display: block; margin-top: 32px;">
40
+ </div>
41
+ {% endif %}
42
+
43
+ {%- comment -%} Narrative {%- endcomment -%}
44
+ {% if project.narrative %}
45
+ <section class="narrative-section" aria-label="Project narrative">
46
+ <h2 class="section-heading"><span class="sketch-underline">The Story</span></h2>
47
+ <div class="narrative">
48
+ <p>{{ project.narrative }}</p>
49
+ </div>
50
+ </section>
51
+ {% endif %}
52
+
53
+ {%- comment -%} Stats row {%- endcomment -%}
54
+ <section aria-label="Project statistics">
55
+ <div class="stats-row">
56
+ <div class="stat-item">
57
+ <div class="stat-item-value">{{ project.totalSessions }}</div>
58
+ <div class="stat-item-label">Sessions</div>
59
+ </div>
60
+ <div class="stat-item">
61
+ <div class="stat-item-value">{{ project.totalLoc | localeNumber }}</div>
62
+ <div class="stat-item-label">LOC</div>
63
+ </div>
64
+ <div class="stat-item">
65
+ <div class="stat-item-value">{{ project.totalFilesChanged }}</div>
66
+ <div class="stat-item-label">Files</div>
67
+ </div>
68
+ {% if project.totalTokens %}
69
+ <div class="stat-item">
70
+ <div class="stat-item-value">{{ project.totalTokens | formatTokens }}</div>
71
+ <div class="stat-item-label">Tokens</div>
72
+ </div>
73
+ {% endif %}
74
+ </div>
75
+ {% if efficiencyMultiplier %}
76
+ <div class="leverage-annotation" role="img" aria-label="Leverage multiplier">
77
+ <div class="leverage-annotation__numbers">
78
+ <span class="leverage-annotation__human">{{ project.totalDurationMinutes | formatDuration }} <small>you</small></span>
79
+ <span class="leverage-annotation__arrow">&rarr;</span>
80
+ <span class="leverage-annotation__agent">{{ project.totalAgentDurationMinutes | formatDuration }} <small>agents</small></span>
81
+ <span class="leverage-annotation__arrow">=</span>
82
+ <span class="leverage-annotation__multiplier">{{ efficiencyMultiplier }}</span>
83
+ </div>
84
+ </div>
85
+ {% endif %}
86
+ </section>
87
+
88
+ {%- comment -%} Work timeline chart (CSS-only SVG) {%- endcomment -%}
89
+ {% if featuredSessions.size > 0 %}
90
+ <section class="timeline-section" aria-label="Work timeline">
91
+ <h2 class="section-heading"><span class="sketch-underline">Work Timeline</span></h2>
92
+ <div class="timeline-chart" role="img" aria-label="Bar chart showing session LOC over time">
93
+ {% assign maxLoc = 1 %}
94
+ {% for s in featuredSessions %}
95
+ {% if s.locChanged > maxLoc %}{% assign maxLoc = s.locChanged %}{% endif %}
96
+ {% endfor %}
97
+ {% assign barCount = featuredSessions.size %}
98
+ {% assign chartWidth = barCount | times: 90 | plus: 80 %}
99
+ {% assign chartHeight = 260 %}
100
+ <svg viewBox="0 0 {{ chartWidth }} {{ chartHeight }}" preserveAspectRatio="xMidYMid meet">
101
+ {%- comment -%} Grid lines {%- endcomment -%}
102
+ <line x1="60" y1="20" x2="60" y2="200" stroke="#e2e8f0" stroke-width="1.5" stroke-dasharray="6 4" />
103
+ <line x1="60" y1="200" x2="{{ chartWidth | minus: 20 }}" y2="200" stroke="#e2e8f0" stroke-width="1.5" stroke-dasharray="6 4" />
104
+
105
+ {%- comment -%} Y-axis labels {%- endcomment -%}
106
+ <text x="50" y="40" text-anchor="end" font-family="'IBM Plex Mono', monospace" font-size="10" fill="#64748b">{{ maxLoc }}</text>
107
+ {% assign halfMax = maxLoc | divided_by: 2 %}
108
+ <text x="50" y="120" text-anchor="end" font-family="'IBM Plex Mono', monospace" font-size="10" fill="#64748b">{{ halfMax }}</text>
109
+ <text x="50" y="200" text-anchor="end" font-family="'IBM Plex Mono', monospace" font-size="10" fill="#64748b">0</text>
110
+ <text x="20" y="115" text-anchor="middle" font-family="'IBM Plex Mono', monospace" font-size="10" fill="#64748b" transform="rotate(-90 20 115)">LOC</text>
111
+
112
+ {%- comment -%} Bars {%- endcomment -%}
113
+ {% for s in featuredSessions %}
114
+ {% assign barX = forloop.index0 | times: 90 | plus: 80 %}
115
+ {% assign barHeight = s.locChanged | times: 180 | divided_by: maxLoc %}
116
+ {% assign barY = 200 | minus: barHeight %}
117
+ {% assign isClaude = s.sourceTool | downcase %}
118
+ {% if isClaude == "claude code" or isClaude == "claude" %}
119
+ {% assign barFill = "#334155" %}
120
+ {% assign barStroke = "#334155" %}
121
+ {% else %}
122
+ {% assign barFill = "#94a3b8" %}
123
+ {% assign barStroke = "#475569" %}
124
+ {% endif %}
125
+ <rect x="{{ barX }}" y="{{ barY }}" width="70" height="{{ barHeight }}" rx="4" fill="{{ barFill }}" opacity="0.85" stroke="{{ barStroke }}" stroke-width="1.5" stroke-dasharray="8 2 3 2" />
126
+ <text x="{{ barX | plus: 35 }}" y="220" text-anchor="middle" font-family="'IBM Plex Mono', monospace" font-size="9" fill="#64748b">{{ s.recordedAt | formatDateShort }}</text>
127
+ {% endfor %}
128
+
129
+ {%- comment -%} Legend {%- endcomment -%}
130
+ {% assign legendX = chartWidth | divided_by: 2 | minus: 80 %}
131
+ <rect x="{{ legendX }}" y="240" width="12" height="12" rx="3" fill="#334155" />
132
+ <text x="{{ legendX | plus: 18 }}" y="251" font-family="'IBM Plex Mono', monospace" font-size="11" fill="#64748b">Claude</text>
133
+ {% assign legendX2 = legendX | plus: 80 %}
134
+ <rect x="{{ legendX2 }}" y="240" width="12" height="12" rx="3" fill="#94a3b8" />
135
+ <text x="{{ legendX2 | plus: 18 }}" y="251" font-family="'IBM Plex Mono', monospace" font-size="11" fill="#64748b">Cursor</text>
136
+ </svg>
137
+ </div>
138
+ </section>
139
+ {% endif %}
140
+
141
+ {%- comment -%} Phases {%- endcomment -%}
142
+ {% if arc.size > 0 %}
143
+ <section class="phases-section" aria-label="Project phases">
144
+ <h2 class="section-heading"><span class="sketch-underline">Phases</span></h2>
145
+ <ol class="phase-list">
146
+ {% for item in arc %}
147
+ <li class="phase-item">
148
+ <svg class="phase-circle" viewBox="0 0 24 24" aria-hidden="true">
149
+ <circle cx="12" cy="12" r="10" />
150
+ <text x="12" y="12">{{ item.phase }}</text>
151
+ </svg>
152
+ <div class="phase-name">{{ item.title }}</div>
153
+ {% if item.dates %}<div class="phase-dates">{{ item.dates }}</div>{% endif %}
154
+ <div class="phase-desc">{{ item.description }}</div>
155
+ </li>
156
+ {% endfor %}
157
+ </ol>
158
+ </section>
159
+ {% endif %}
160
+
161
+ {%- comment -%} Key Decisions {%- endcomment -%}
162
+ {% if arc.size > 0 %}
163
+ <section class="decisions-section" aria-label="Key decisions">
164
+ <h2 class="section-heading"><span class="sketch-underline">Key Decisions</span></h2>
165
+ <ol class="decision-list">
166
+ {% for item in arc %}
167
+ <li class="decision-item">{{ item.description }}</li>
168
+ {% endfor %}
169
+ </ol>
170
+ </section>
171
+ {% endif %}
172
+
173
+ {%- comment -%} Source Breakdown {%- endcomment -%}
174
+ {% if sourceCounts.size > 0 %}
175
+ <section class="source-section" aria-label="Source breakdown">
176
+ <h2 class="section-heading"><span class="sketch-underline">Source Mix</span></h2>
177
+ {% assign totalSourceSessions = 0 %}
178
+ {% for src in sourceCounts %}
179
+ {% assign totalSourceSessions = totalSourceSessions | plus: src.count %}
180
+ {% endfor %}
181
+ {% if totalSourceSessions > 0 %}
182
+ {% assign firstPct = sourceCounts[0].count | times: 100.0 | divided_by: totalSourceSessions | round %}
183
+ <div class="source-bar-lg" role="img" aria-label="Source distribution">
184
+ <div class="source-fill-lg" style="width: {{ firstPct }}%"></div>
185
+ </div>
186
+ <div class="source-legend-lg">
187
+ {% for src in sourceCounts %}
188
+ {% assign srcPct = src.count | times: 100.0 | divided_by: totalSourceSessions | round %}
189
+ <span>{% if forloop.first %}<span class="dot-claude-lg"></span>{% else %}<span class="dot-cursor-lg"></span>{% endif %} {{ src.tool }} {{ srcPct }}% ({{ src.count }} session{% if src.count != 1 %}s{% endif %})</span>
190
+ {% endfor %}
191
+ </div>
192
+ {% endif %}
193
+ </section>
194
+ {% endif %}
195
+
196
+ {%- comment -%} Skills {%- endcomment -%}
197
+ {% if project.skills.size > 0 %}
198
+ <section class="skills-section" aria-label="Skills used">
199
+ <h2 class="section-heading"><span class="sketch-underline">Skills</span></h2>
200
+ <ul class="skills-list">
201
+ {% for skill in project.skills %}
202
+ <li class="skill-chip">{{ skill }}</li>
203
+ {% endfor %}
204
+ </ul>
205
+ </section>
206
+ {% endif %}
207
+
208
+ {%- comment -%} Sessions {%- endcomment -%}
209
+ {% if featuredSessions.size > 0 %}
210
+ <section class="sessions-section" aria-label="Featured sessions">
211
+ <h2 class="section-heading"><span class="sketch-underline">Sessions</span></h2>
212
+ <div style="overflow-x: auto;">
213
+ <table class="sessions-table">
214
+ <thead>
215
+ <tr>
216
+ <th scope="col">#</th>
217
+ <th scope="col">Title</th>
218
+ <th scope="col">Date</th>
219
+ <th scope="col">Duration</th>
220
+ <th scope="col">LOC</th>
221
+ <th scope="col" class="hide-mobile">Source</th>
222
+ <th scope="col" class="hide-mobile">Agents</th>
223
+ </tr>
224
+ </thead>
225
+ <tbody>
226
+ {% for s in featuredSessions %}
227
+ <tr>
228
+ <td>{{ forloop.index }}</td>
229
+ <td><a href="{{ sessionBaseUrl }}/{{ s.slug }}{{ sessionSuffix }}" class="session-title-link session-card">{{ s.title }}</a></td>
230
+ <td>{{ s.recordedAt | formatDateShort }}</td>
231
+ <td>{{ s.durationMinutes | formatDuration }}</td>
232
+ <td>{{ s.locChanged | localeNumber }}</td>
233
+ <td class="hide-mobile"><span class="session-source">{{ s.sourceTool }}</span></td>
234
+ <td class="hide-mobile">{% if s.agentCount %}{{ s.agentCount }}{% else %}0{% endif %}</td>
235
+ </tr>
236
+ {% endfor %}
237
+ </tbody>
238
+ </table>
239
+ </div>
240
+ </section>
241
+ {% endif %}
242
+
243
+ {%- comment -%} Fade-in animation script {%- endcomment -%}
244
+
245
+ </div>
@@ -0,0 +1,215 @@
1
+ <div class="heyiam-session chalk" data-render-version="2" data-template="chalk">
2
+
3
+ {%- comment -%} SVG filters {%- endcomment -%}
4
+ <svg class="svg-filters" aria-hidden="true">
5
+ <defs>
6
+ <filter id="chalk-rough">
7
+ <feTurbulence type="turbulence" baseFrequency="0.03" numOctaves="4" seed="1" result="noise" />
8
+ <feDisplacementMap in="SourceGraphic" in2="noise" scale="1.2" xChannelSelector="R" yChannelSelector="G" />
9
+ </filter>
10
+ </defs>
11
+ </svg>
12
+
13
+ {%- comment -%} Breadcrumb {%- endcomment -%}
14
+ <nav class="breadcrumb" aria-label="Breadcrumb">
15
+ <a href="/{{ user.username }}">{{ user.username }}</a>
16
+ {% if projectSlug %}
17
+ <span class="breadcrumb-sep" aria-hidden="true">/</span>
18
+ <a href="/{{ user.username }}/{{ projectSlug }}">{{ projectSlug }}</a>
19
+ {% endif %}
20
+ <span class="breadcrumb-sep" aria-hidden="true">/</span>
21
+ <span aria-current="page">{{ session.title }}</span>
22
+ </nav>
23
+
24
+ {%- comment -%} Hero {%- endcomment -%}
25
+ <section class="hero" aria-label="Session header">
26
+ <h1>{{ session.title }}</h1>
27
+ <div class="hero-meta">
28
+ {% if session.recordedAt %}
29
+ <span class="hero-meta-item">{{ session.recordedAt | formatDate }}</span>
30
+ {% endif %}
31
+ {% if session.sourceTool %}
32
+ <span class="hero-meta-item">{{ session.sourceTool }}</span>
33
+ {% endif %}
34
+ <span class="hero-meta-item">{{ session.durationMinutes | formatDuration }}{% if session.wallClockMinutes %} ({{ session.wallClockMinutes | formatDuration }} wall){% endif %}</span>
35
+ <span class="hero-meta-item">{{ session.turns }} turns</span>
36
+ <span class="hero-meta-item">{{ session.locChanged | localeNumber }} LOC</span>
37
+ <span class="hero-meta-item">{{ session.filesChanged }} files</span>
38
+ </div>
39
+ </section>
40
+
41
+ {%- comment -%} Dev Take {%- endcomment -%}
42
+ {% if session.devTake %}
43
+ <div class="dev-take fade-in">
44
+ <div class="dev-take-label">Dev Take</div>
45
+ <p>{{ session.devTake }}</p>
46
+ </div>
47
+ {% endif %}
48
+
49
+ {%- comment -%} Two-column layout {%- endcomment -%}
50
+ <div class="layout-grid">
51
+ {%- comment -%} Main content {%- endcomment -%}
52
+ <div>
53
+
54
+ {%- comment -%} Execution Path (Beats) {%- endcomment -%}
55
+ {% if session.beats.size > 0 %}
56
+ <section class="beats-section" aria-label="Execution path">
57
+ <h2 class="section-heading"><span class="sketch-underline">Execution Path</span></h2>
58
+ <ol class="beat-list">
59
+ {% for beat in session.beats %}
60
+ <li class="beat-item">
61
+ <svg class="beat-circle" viewBox="0 0 24 24" aria-hidden="true">
62
+ <circle cx="12" cy="12" r="10" />
63
+ <text x="12" y="12">{{ beat.stepNumber }}</text>
64
+ </svg>
65
+ <div class="beat-title">{{ beat.title }}</div>
66
+ <div class="beat-desc">{{ beat.body }}</div>
67
+ </li>
68
+ {% endfor %}
69
+ </ol>
70
+ </section>
71
+ {% endif %}
72
+
73
+ {%- comment -%} Q&A {%- endcomment -%}
74
+ {% if session.qaPairs.size > 0 %}
75
+ <section class="qa-section" aria-label="Questions and answers">
76
+ <h2 class="section-heading"><span class="sketch-underline">Q&amp;A</span></h2>
77
+ {% for qa in session.qaPairs %}
78
+ <div class="qa-item qa-pair">
79
+ <h3 class="qa-question">{{ qa.question }}</h3>
80
+ <p class="qa-answer">{{ qa.answer }}</p>
81
+ </div>
82
+ {% endfor %}
83
+ </section>
84
+ {% endif %}
85
+
86
+ {%- comment -%} Narrative {%- endcomment -%}
87
+ {% if session.narrative %}
88
+ <section class="narrative-section" aria-label="Session narrative">
89
+ <h2 class="section-heading"><span class="sketch-underline">Narrative</span></h2>
90
+ <div class="narrative">
91
+ <p>{{ session.narrative }}</p>
92
+ </div>
93
+ </section>
94
+ {% endif %}
95
+
96
+ {%- comment -%} Highlights {%- endcomment -%}
97
+ {% if session.highlights.size > 0 %}
98
+ <section class="beats-section" aria-label="Session highlights">
99
+ <h2 class="section-heading"><span class="sketch-underline">Highlights</span></h2>
100
+ <ul class="highlights-list">
101
+ {% for h in session.highlights %}
102
+ <li>{{ h }}</li>
103
+ {% endfor %}
104
+ </ul>
105
+ </section>
106
+ {% endif %}
107
+
108
+ {%- comment -%} Agent Summary {%- endcomment -%}
109
+ {% if session.agentSummary %}
110
+ <section class="agents-section" aria-label="Agent summary">
111
+ <h2 class="section-heading"><span class="sketch-underline">Agents</span></h2>
112
+ <p class="annotation">{{ session.agentSummary.agents.size }} sub-session{% if session.agentSummary.agents.size != 1 %}s{% endif %}</p>
113
+
114
+ {% assign maxAgentLoc = 0 %}
115
+ {% for agent in session.agentSummary.agents %}
116
+ {% if agent.loc_changed > maxAgentLoc %}
117
+ {% assign maxAgentLoc = agent.loc_changed %}
118
+ {% endif %}
119
+ {% endfor %}
120
+
121
+ {% assign agent_colors = 'var(--agent-backend),var(--agent-qa),var(--agent-frontend),var(--agent-security),var(--agent-reviewer),var(--agent-ux)' | split: ',' %}
122
+ <div class="agent-bar-chart" role="list" aria-label="Agent contribution breakdown">
123
+ {% for agent in session.agentSummary.agents %}
124
+ <div class="agent-row" role="listitem">
125
+ <span class="agent-name">{{ agent.role }}</span>
126
+ <div class="agent-bar">
127
+ {% if maxAgentLoc > 0 %}
128
+ {% assign barPct = agent.loc_changed | times: 100 | divided_by: maxAgentLoc %}
129
+ {% else %}
130
+ {% assign barPct = 0 %}
131
+ {% endif %}
132
+ {% assign colorIdx = forloop.index0 | modulo: 6 %}
133
+ <div class="agent-bar-fill" style="width: {{ barPct }}%; background: {{ agent_colors[colorIdx] }};"></div>
134
+ </div>
135
+ <span class="agent-stats">{{ agent.duration_minutes }}m / {{ agent.loc_changed }} LOC</span>
136
+ </div>
137
+ {% endfor %}
138
+ </div>
139
+ </section>
140
+ {% endif %}
141
+
142
+ </div>
143
+
144
+ {%- comment -%} Sidebar {%- endcomment -%}
145
+ <aside class="sidebar" aria-label="Session details">
146
+
147
+ {%- comment -%} Tools Used {%- endcomment -%}
148
+ {% if session.toolBreakdown.size > 0 %}
149
+ <section class="sidebar-section chalk-card">
150
+ <h2 class="sidebar-heading">Tools Used</h2>
151
+ <table class="tools-table tool-list" aria-label="Tool usage counts">
152
+ <thead>
153
+ <tr>
154
+ <th scope="col">Tool</th>
155
+ <th scope="col">Count</th>
156
+ <th scope="col" aria-label="Relative usage">Usage</th>
157
+ </tr>
158
+ </thead>
159
+ <tbody>
160
+ {% assign maxToolCount = 0 %}
161
+ {% for t in session.toolBreakdown %}
162
+ {% if t.count > maxToolCount %}
163
+ {% assign maxToolCount = t.count %}
164
+ {% endif %}
165
+ {% endfor %}
166
+ {% for t in session.toolBreakdown %}
167
+ <tr>
168
+ <td>{{ t.tool }}</td>
169
+ <td>{{ t.count }}</td>
170
+ <td>
171
+ {% if maxToolCount > 0 %}
172
+ {% assign toolPct = t.count | times: 100 | divided_by: maxToolCount %}
173
+ <div class="tool-bar"><div class="tool-bar-fill" style="width: {{ toolPct }}%"></div></div>
174
+ {% endif %}
175
+ </td>
176
+ </tr>
177
+ {% endfor %}
178
+ </tbody>
179
+ </table>
180
+ </section>
181
+ {% endif %}
182
+
183
+ {%- comment -%} Files Changed {%- endcomment -%}
184
+ {% if session.topFiles.size > 0 %}
185
+ <section class="sidebar-section chalk-card">
186
+ <h2 class="sidebar-heading">Files Changed</h2>
187
+ <ul class="files-list file-list" aria-label="Modified files">
188
+ {% for f in session.topFiles %}
189
+ <li class="file-item">
190
+ <span class="file-name">{{ f.path }}</span>
191
+ <span class="file-diff">+{{ f.additions }}{% if f.deletions > 0 %} -{{ f.deletions }}{% endif %}</span>
192
+ </li>
193
+ {% endfor %}
194
+ </ul>
195
+ </section>
196
+ {% endif %}
197
+
198
+ {%- comment -%} Skills {%- endcomment -%}
199
+ {% if session.skills.size > 0 %}
200
+ <section class="sidebar-section chalk-card">
201
+ <h2 class="sidebar-heading">Skills</h2>
202
+ <ul class="skills-list" aria-label="Skills used in session">
203
+ {% for skill in session.skills %}
204
+ <li class="skill-chip chip">{{ skill }}</li>
205
+ {% endfor %}
206
+ </ul>
207
+ </section>
208
+ {% endif %}
209
+
210
+ </aside>
211
+ </div>
212
+
213
+ {%- comment -%} Animation scripts {%- endcomment -%}
214
+
215
+ </div>