A vibe coded tangled fork which supports pijul.
1{{ define "title" }}
2 {{ .Pull.Title }} · pull #{{ .Pull.PullId }} · {{ .RepoInfo.FullName }}
3{{ end }}
4
5{{ define "extrameta" }}
6 {{ template "repo/pulls/fragments/og" (dict "RepoInfo" .RepoInfo "Pull" .Pull) }}
7{{ end }}
8
9{{ define "mainLayout" }}
10 <div class="px-1 flex-grow flex flex-col gap-4">
11 <div class="max-w-full md:max-w-screen-lg mx-auto">
12 {{ block "contentLayout" . }}
13 {{ block "content" . }}{{ end }}
14 {{ end }}
15 </div>
16 {{ block "contentAfterLayout" . }}
17 <main>
18 {{ block "contentAfter" . }}{{ end }}
19 </main>
20 {{ end }}
21 </div>
22 <script>
23 (function() {
24 const details = document.getElementById('bottomSheet');
25 const isDesktop = () => window.matchMedia('(min-width: 768px)').matches;
26
27 // close on mobile initially
28 if (!isDesktop()) {
29 details.open = false;
30 }
31
32 // prevent closing on desktop
33 details.addEventListener('toggle', function(e) {
34 if (isDesktop() && !this.open) {
35 this.open = true;
36 }
37 });
38
39 const mediaQuery = window.matchMedia('(min-width: 768px)');
40 mediaQuery.addEventListener('change', function(e) {
41 if (e.matches) {
42 // switched to desktop - keep open
43 details.open = true;
44 } else {
45 // switched to mobile - close
46 details.open = false;
47 }
48 });
49 })();
50 </script>
51{{ end }}
52
53{{ define "repoContentLayout" }}
54 <div class="grid grid-cols-1 md:grid-cols-10 gap-4 w-full">
55 <section class="bg-white col-span-1 md:col-span-8 dark:bg-gray-800 p-6 rounded relative w-full mx-auto dark:text-white h-full flex-shrink">
56 {{ block "repoContent" . }}{{ end }}
57 </section>
58 <div class="flex flex-col gap-6 col-span-1 md:col-span-2">
59 {{ template "repo/fragments/labelPanel"
60 (dict "RepoInfo" $.RepoInfo
61 "Defs" $.LabelDefs
62 "Subject" $.Pull.AtUri
63 "State" $.Pull.Labels) }}
64 {{ template "repo/fragments/participants" $.Pull.Participants }}
65 {{ template "repo/fragments/backlinks"
66 (dict "RepoInfo" $.RepoInfo
67 "Backlinks" $.Backlinks) }}
68 {{ template "repo/fragments/externalLinkPanel" $.Pull.AtUri }}
69 </div>
70 </div>
71{{ end }}
72
73{{ define "contentAfter" }}
74 {{ template "repo/fragments/diff" (list .Diff .DiffOpts $) }}
75{{ end }}
76
77{{ define "repoContent" }}
78 {{ template "repo/pulls/fragments/pullHeader" . }}
79 {{ if .Pull.IsStacked }}
80 <div class="mt-8">
81 {{ template "repo/pulls/fragments/pullStack" . }}
82 </div>
83 {{ end }}
84{{ end }}
85
86{{ define "diffLayout" }}
87 {{ $diff := index . 0 }}
88 {{ $opts := index . 1 }}
89 {{ $root := index . 2 }}
90
91 <div class="flex col-span-full">
92 <!-- left panel -->
93 <div id="files" class="w-0 hidden md:block overflow-hidden sticky top-12 max-h-screen overflow-y-auto pb-12">
94 <section class="overflow-x-auto text-sm px-6 py-2 border-b border-x border-gray-200 dark:border-gray-700 w-full mx-auto min-h-full rounded-b rounded-t-none bg-white dark:bg-gray-800 drop-shadow-sm">
95 {{ template "repo/fragments/fileTree" $diff.FileTree }}
96 </section>
97 </div>
98
99 <!-- main content -->
100 <div class="flex-1 min-w-0 sticky top-12 pb-12">
101 {{ template "diffFiles" (list $diff $opts) }}
102 </div>
103
104 <!-- right panel -->
105 {{ template "subsPanel" $ }}
106 </div>
107{{ end }}
108
109{{ define "subsPanel" }}
110 {{ $root := index . 2 }}
111 {{ $pull := $root.Pull }}
112
113 <!-- backdrop overlay - only visible on mobile when open -->
114 <div class="
115 fixed inset-0 bg-black/50 z-50 md:hidden opacity-0
116 pointer-events-none transition-opacity duration-300
117 has-[~#subs_details[open]]:opacity-100 has-[~#subs_details[open]]:pointer-events-auto">
118 </div>
119 <!-- right panel - bottom sheet on mobile, side panel on desktop -->
120 <div id="subs" class="fixed bottom-0 left-0 right-0 z-50 w-full md:static md:z-auto md:max-h-screen md:sticky md:top-12 overflow-hidden">
121 <details open id="bottomSheet" class="group rounded-t-2xl md:rounded-t drop-shadow-lg md:drop-shadow-none">
122 <summary class="
123 flex gap-4 items-center justify-between
124 rounded-t-2xl md:rounded-t cursor-pointer list-none p-4 md:h-12
125 text-white md:text-black md:dark:text-white
126 bg-green-600 dark:bg-green-700
127 md:bg-white md:dark:bg-gray-800
128 drop-shadow-sm
129 border-t md:border-x md:border-t-0 border-gray-200 dark:border-gray-700">
130 <h2 class="">Submissions</h2>
131 {{ template "subsPanelSummary" $ }}
132 </summary>
133 <div class="max-h-[85vh] md:max-h-[calc(100vh-3rem-3rem)] w-full flex flex-col-reverse gap-4 overflow-y-auto bg-slate-100 dark:bg-gray-900 md:bg-transparent">
134 {{ template "submissions" $root }}
135 </div>
136 </details>
137 </div>
138{{ end }}
139
140{{ define "subsPanelSummary" }}
141 {{ $root := index . 2 }}
142 {{ $pull := $root.Pull }}
143 {{ $latest := $pull.LastRoundNumber }}
144 <div class="flex items-center gap-2 text-sm">
145 <!--{{ if $root.IsInterdiff }}
146 <span>
147 viewing interdiff of
148 <span class="font-mono">#{{ $root.ActiveRound }}</span>
149 and
150 <span class="font-mono">#{{ sub $root.ActiveRound 1 }}</span>
151 </span>
152 {{ else }}
153 {{ if ne $root.ActiveRound $latest }}
154 <span>(outdated)</span>
155 <span class="before:content-['·']"></span>
156 <a class="underline" href="/{{ $root.RepoInfo.FullName }}/pulls/{{ $root.Pull.PullId }}/round/{{ $latest }}?{{ safeUrl $root.DiffOpts.Encode }}">
157 view latest
158 </a>
159 {{ end }}
160 {{ end }}-->
161 <span class="md:hidden inline">
162 <span class="inline group-open:hidden">{{ i "chevron-up" "size-4" }}</span>
163 <span class="hidden group-open:inline">{{ i "chevron-down" "size-4" }}</span>
164 </span>
165 </div>
166{{ end }}
167
168{{ define "subsCheckbox" }}
169 <input type="checkbox" id="subsToggle" class="peer/subs hidden" checked/>
170{{ end }}
171
172{{ define "subsToggle" }}
173 <style>
174 /* Mobile: full width */
175 #subsToggle:checked ~ div div#subs {
176 width: 100%;
177 margin-left: 0;
178 }
179 #subsToggle:checked ~ div label[for="subsToggle"] .show-toggle { display: none; }
180 #subsToggle:checked ~ div label[for="subsToggle"] .hide-toggle { display: flex; }
181 #subsToggle:not(:checked) ~ div label[for="subsToggle"] .hide-toggle { display: none; }
182
183 /* Desktop: 25vw with left margin */
184 @media (min-width: 768px) {
185 #subsToggle:checked ~ div div#subs {
186 width: 25vw;
187 margin-left: 1rem;
188 }
189 /* Unchecked state */
190 #subsToggle:not(:checked) ~ div div#subs {
191 width: 0;
192 display: none;
193 margin-left: 0;
194 }
195 }
196 </style>
197 <label title="Toggle review panel" for="subsToggle" class="hidden md:flex items-center justify-end rounded cursor-pointer">
198 <span class="show-toggle">{{ i "message-square-more" "size-4" }}</span>
199 <span class="hide-toggle w-[25vw] flex justify-end">{{ i "message-square" "size-4" }}</span>
200 </label>
201{{ end }}
202
203
204{{ define "submissions" }}
205 {{ $lastIdx := sub (len .Pull.Submissions) 1 }}
206 {{ if not .LoggedInUser }}
207 {{ template "loginPrompt" $ }}
208 {{ end }}
209 {{ range $ridx, $item := reverse .Pull.Submissions }}
210 {{ $idx := sub $lastIdx $ridx }}
211 {{ template "submission" (list $item $idx $lastIdx $) }}
212 {{ end }}
213{{ end }}
214
215{{ define "submission" }}
216 {{ $item := index . 0 }}
217 {{ $idx := index . 1 }}
218 {{ $lastIdx := index . 2 }}
219 {{ $root := index . 3 }}
220 <div class="{{ if eq $item.RoundNumber 0 }}rounded-b border-t-0{{ else }}rounded{{ end }} border border-gray-200 dark:border-gray-700 w-full shadow-sm bg-gray-50 dark:bg-gray-800/50">
221 {{ template "submissionHeader" $ }}
222 {{ template "submissionComments" $ }}
223
224 {{ if eq $lastIdx $item.RoundNumber }}
225 {{ block "mergeStatus" $root }} {{ end }}
226 {{ block "resubmitStatus" $root }} {{ end }}
227 {{ end }}
228
229 {{ if $root.LoggedInUser }}
230 {{ template "repo/pulls/fragments/pullActions"
231 (dict
232 "LoggedInUser" $root.LoggedInUser
233 "Pull" $root.Pull
234 "RepoInfo" $root.RepoInfo
235 "RoundNumber" $item.RoundNumber
236 "MergeCheck" $root.MergeCheck
237 "ResubmitCheck" $root.ResubmitCheck
238 "BranchDeleteStatus" $root.BranchDeleteStatus
239 "Stack" $root.Stack) }}
240 {{ end }}
241 </div>
242{{ end }}
243
244{{ define "submissionHeader" }}
245 {{ $item := index . 0 }}
246 {{ $lastIdx := index . 2 }}
247 {{ $root := index . 3 }}
248 {{ $round := $item.RoundNumber }}
249 <div class="
250 {{ if eq $round 0 }}rounded-b{{ else }}rounded{{ end }}
251 px-6 py-4 pr-2 pt-2
252 {{ if eq $root.ActiveRound $round }}
253 bg-blue-100 dark:bg-blue-900 border-b border-blue-200 dark:border-blue-700
254 {{ else }}
255 bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700
256 {{ end }}
257 flex gap-2 sticky top-0 z-20">
258 <!-- left column: just profile picture -->
259 <div class="flex-shrink-0 pt-2">
260 <img
261 src="{{ tinyAvatar $root.Pull.OwnerDid }}"
262 alt=""
263 class="rounded-full size-8 mr-1 border-2 border-gray-100 dark:border-gray-900"
264 />
265 </div>
266 <!-- right column -->
267 <div class="flex-1 min-w-0 flex flex-col gap-1">
268 {{ template "submissionInfo" $ }}
269 {{ template "submissionCommits" $ }}
270 {{ template "submissionPipeline" $ }}
271 {{ if eq $lastIdx $round }}
272 {{ block "mergeCheck" $root }} {{ end }}
273 {{ end }}
274 </div>
275 </div>
276{{ end }}
277
278{{ define "submissionInfo" }}
279 {{ $item := index . 0 }}
280 {{ $idx := index . 1 }}
281 {{ $root := index . 3 }}
282 {{ $round := $item.RoundNumber }}
283 <div class="flex gap-2 items-center justify-between mb-1">
284 <span class="inline-flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400 pt-2">
285 {{ resolve $root.Pull.OwnerDid }} submitted
286 <span class="px-2 py-0.5 {{ if eq $root.ActiveRound $round }}text-white bg-blue-600 dark:bg-blue-500 border-blue-700 dark:border-blue-600{{ else }}text-black dark:text-white bg-gray-100 dark:bg-gray-700 border-gray-300 dark:border-gray-600{{ end }} rounded font-mono text-xs border">
287 #{{ $round }}
288 </span>
289 <span class="select-none before:content-['\00B7']"></span>
290 <a class="text-gray-500 dark:text-gray-400 hover:text-gray-500" href="#round-#{{ $round }}">
291 {{ template "repo/fragments/shortTime" $item.Created }}
292 </a>
293 </span>
294 <div class="flex gap-2 items-center">
295 {{ if ne $root.ActiveRound $round }}
296 <a class="btn-flat flex items-center gap-2 no-underline hover:no-underline text-sm"
297 href="/{{ $root.RepoInfo.FullName }}/pulls/{{ $root.Pull.PullId }}/round/{{ $round }}?{{ safeUrl $root.DiffOpts.Encode }}#round-#{{ $round }}">
298 {{ i "diff" "w-4 h-4" }}
299 diff
300 </a>
301 {{ end }}
302 {{ if ne $idx 0 }}
303 <a class="btn-flat flex items-center gap-2 no-underline hover:no-underline text-sm"
304 href="/{{ $root.RepoInfo.FullName }}/pulls/{{ $root.Pull.PullId }}/round/{{ $round }}/interdiff?{{ safeUrl $root.DiffOpts.Encode }}">
305 {{ i "chevrons-left-right-ellipsis" "w-4 h-4 rotate-90" }}
306 interdiff
307 </a>
308 {{ end }}
309 </div>
310 </div>
311{{ end }}
312
313{{ define "submissionCommits" }}
314 {{ $item := index . 0 }}
315 {{ $root := index . 3 }}
316 {{ $round := $item.RoundNumber }}
317 {{ $patches := $item.AsFormatPatch }}
318 {{ if $patches }}
319 <details class="group/commit">
320 <summary class="list-none cursor-pointer flex items-center gap-2">
321 <span>{{ i "git-commit-horizontal" "w-4 h-4" }}</span>
322 {{ len $patches }} commit{{ if ne (len $patches) 1 }}s{{ end }}
323 <div class="text-sm text-gray-500 dark:text-gray-400">
324 <span class="group-open/commit:hidden inline">expand</span>
325 <span class="hidden group-open/commit:inline">collapse</span>
326 </div>
327 </summary>
328 {{ range $patches }}
329 {{ template "submissionCommit" (list . $item $root) }}
330 {{ end }}
331 </details>
332 {{ end }}
333{{ end }}
334
335{{ define "submissionCommit" }}
336 {{ $patch := index . 0 }}
337 {{ $item := index . 1 }}
338 {{ $root := index . 2 }}
339 {{ $round := $item.RoundNumber }}
340 {{ with $patch }}
341 <div id="commit-{{.SHA}}" class="py-1 relative w-full md:max-w-3/5 md:w-fit flex flex-col text-gray-600 dark:text-gray-300">
342 <div class="flex items-baseline gap-2">
343 <div class="text-xs">
344 <!-- attempt to resolve $fullRepo: this is possible only on non-deleted forks and branches -->
345 {{ $fullRepo := "" }}
346 {{ if and $root.Pull.IsForkBased $root.Pull.PullSource.Repo }}
347 {{ $fullRepo = printf "%s/%s" $root.Pull.OwnerDid $root.Pull.PullSource.Repo.Name }}
348 {{ else if $root.Pull.IsBranchBased }}
349 {{ $fullRepo = $root.RepoInfo.FullName }}
350 {{ end }}
351
352 <!-- if $fullRepo was resolved, link to it, otherwise just span without a link -->
353 {{ if $fullRepo }}
354 <a href="/{{ $fullRepo }}/commit/{{ .SHA }}" class="font-mono text-gray-600 dark:text-gray-300">{{ slice .SHA 0 8 }}</a>
355 {{ else }}
356 <span class="font-mono">{{ slice .SHA 0 8 }}</span>
357 {{ end }}
358 </div>
359
360 <div>
361 <span>{{ .Title | description }}</span>
362 {{ if gt (len .Body) 0 }}
363 <button
364 class="py-1/2 px-1 mx-2 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600"
365 hx-on:click="document.getElementById('body-{{$round}}-{{.SHA}}').classList.toggle('hidden')"
366 >
367 {{ i "ellipsis" "w-3 h-3" }}
368 </button>
369 {{ end }}
370 {{ if gt (len .Body) 0 }}
371 <p id="body-{{$round}}-{{.SHA}}" class="hidden mt-1 pb-2">{{ nl2br .Body }}</p>
372 {{ end }}
373 </div>
374 </div>
375 </div>
376 {{ end }}
377{{ end }}
378
379{{ define "mergeCheck" }}
380 {{ $isOpen := .Pull.State.IsOpen }}
381 {{ if and $isOpen .MergeCheck .MergeCheck.Error }}
382 <div class="flex items-center gap-2">
383 {{ i "triangle-alert" "w-4 h-4 text-red-600 dark:text-red-500" }}
384 {{ .MergeCheck.Error }}
385 </div>
386 {{ else if and $isOpen .MergeCheck .MergeCheck.IsConflicted }}
387 <details class="group/conflict">
388 <summary class="flex items-center justify-between cursor-pointer list-none">
389 <div class="flex items-center gap-2 ">
390 {{ i "triangle-alert" "text-red-600 dark:text-red-500 w-4 h-4" }}
391 <span class="font-medium">merge conflicts detected</span>
392 <div class="text-sm text-gray-500 dark:text-gray-400">
393 <span class="group-open/conflict:hidden inline">expand</span>
394 <span class="hidden group-open/conflict:inline">collapse</span>
395 </div>
396 </div>
397 </summary>
398 {{ if gt (len .MergeCheck.Conflicts) 0 }}
399 <ul class="space-y-1 mt-2 overflow-x-auto">
400 {{ range .MergeCheck.Conflicts }}
401 {{ if .Filename }}
402 <li class="flex items-center whitespace-nowrap">
403 {{ i "file-warning" "inline-flex w-4 h-4 mr-1.5 text-red-600 dark:text-red-500 flex-shrink-0" }}
404 <span class="font-mono">{{ .Filename }}</span>
405 </li>
406 {{ else if .Reason }}
407 <li class="flex items-center whitespace-nowrap">
408 {{ i "file-warning" "w-4 h-4 mr-1.5 text-red-600 dark:text-red-500 " }}
409 <span>{{.Reason}}</span>
410 </li>
411 {{ end }}
412 {{ end }}
413 </ul>
414 {{ end }}
415 </details>
416 {{ else if and $isOpen .MergeCheck }}
417 <div class="flex items-center gap-2">
418 {{ i "check" "w-4 h-4 text-green-600 dark:text-green-500" }}
419 <span>no conflicts, ready to merge</span>
420 </div>
421 {{ end }}
422{{ end }}
423
424{{ define "mergeStatus" }}
425 {{ if .Pull.State.IsClosed }}
426 <div class="bg-gray-50 dark:bg-gray-700 border border-black dark:border-gray-500 rounded drop-shadow-sm px-6 py-2 relative">
427 <div class="flex items-center gap-2 text-black dark:text-white">
428 {{ i "ban" "w-4 h-4" }}
429 <span class="font-medium">closed without merging</span
430 >
431 </div>
432 </div>
433 {{ else if .Pull.State.IsMerged }}
434 <div class="bg-purple-50 dark:bg-purple-900 border border-purple-500 rounded drop-shadow-sm px-6 py-2 relative">
435 <div class="flex items-center gap-2 text-purple-500 dark:text-purple-300">
436 {{ i "git-merge" "w-4 h-4" }}
437 <span class="font-medium">pull request successfully merged</span
438 >
439 </div>
440 </div>
441 {{ else if .Pull.State.IsDeleted }}
442 <div class="bg-red-50 dark:bg-red-900 border border-red-500 rounded drop-shadow-sm px-6 py-2 relative">
443 <div class="flex items-center gap-2 text-red-500 dark:text-red-300">
444 {{ i "git-pull-request-closed" "w-4 h-4" }}
445 <span class="font-medium">This pull has been deleted (possibly by jj abandon or jj squash)</span>
446 </div>
447 </div>
448 {{ end }}
449{{ end }}
450
451{{ define "resubmitStatus" }}
452 {{ if .ResubmitCheck.Yes }}
453 <div class="bg-amber-50 dark:bg-amber-900 border border-amber-500 rounded drop-shadow-sm px-6 py-2 relative">
454 <div class="flex items-center gap-2 text-amber-500 dark:text-amber-300">
455 {{ i "triangle-alert" "w-4 h-4" }}
456 <span class="font-medium">this branch has been updated, consider resubmitting</span>
457 </div>
458 </div>
459 {{ end }}
460{{ end }}
461
462{{ define "submissionPipeline" }}
463 {{ $item := index . 0 }}
464 {{ $root := index . 3 }}
465 {{ $pipeline := index $root.Pipelines $item.SourceRev }}
466 {{ with $pipeline }}
467 {{ $id := .Id }}
468 {{ if .Statuses }}
469 <details class="group/pipeline">
470 <summary class="cursor-pointer list-none flex items-center gap-2">
471 {{ template "repo/pipelines/fragments/pipelineSymbol" (dict "Pipeline" $pipeline "ShortSummary" false) }}
472 <div class="text-sm text-gray-500 dark:text-gray-400">
473 <span class="group-open/pipeline:hidden inline">expand</span>
474 <span class="hidden group-open/pipeline:inline">collapse</span>
475 </div>
476 </summary>
477 <div class="my-2 grid grid-cols-1 bg-white dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 divide-y divide-gray-200 dark:divide-gray-700">
478 {{ range $name, $all := .Statuses }}
479 <a href="/{{ $root.RepoInfo.FullName }}/pipelines/{{ $id }}/workflow/{{ $name }}" class="no-underline hover:no-underline hover:bg-gray-100/25 hover:dark:bg-gray-700/25">
480 <div
481 class="flex gap-2 items-center justify-between p-2">
482 {{ $lastStatus := $all.Latest }}
483 {{ $kind := $lastStatus.Status.String }}
484
485 <div id="left" class="flex items-center gap-2 flex-shrink-0">
486 {{ template "repo/pipelines/fragments/workflowSymbol" $all }}
487 {{ $name }}
488 </div>
489 <div id="right" class="flex items-center gap-2 flex-shrink-0">
490 <span class="font-bold">{{ $kind }}</span>
491 {{ if .TimeTaken }}
492 {{ template "repo/fragments/duration" .TimeTaken }}
493 {{ else }}
494 {{ template "repo/fragments/shortTimeAgo" $lastStatus.Created }}
495 {{ end }}
496 </div>
497 </div>
498 </a>
499 {{ end }}
500 </div>
501 </details>
502 {{ end }}
503 {{ end }}
504{{ end }}
505
506{{ define "submissionComments" }}
507 {{ $item := index . 0 }}
508 <div class="relative ml-10 border-l-2 border-gray-200 dark:border-gray-700">
509 {{ range $item.Comments }}
510 {{ template "submissionComment" . }}
511 {{ end }}
512 </div>
513{{ end }}
514
515{{ define "submissionComment" }}
516 <div id="comment-{{.ID}}" class="flex gap-2 -ml-4 py-4 w-full mx-auto">
517 <!-- left column: profile picture -->
518 <div class="flex-shrink-0">
519 <img
520 src="{{ tinyAvatar .OwnerDid }}"
521 alt=""
522 class="rounded-full size-8 mr-1 border-2 border-gray-100 dark:border-gray-900"
523 />
524 </div>
525 <!-- right column: name and body in two rows -->
526 <div class="flex-1 min-w-0">
527 <!-- Row 1: Author and timestamp -->
528 <div class="text-sm text-gray-500 dark:text-gray-400 flex items-center gap-1">
529 <span>{{ resolve .OwnerDid }}</span>
530 <span class="before:content-['·']"></span>
531 <a class="text-gray-500 dark:text-gray-400 hover:text-gray-500 dark:hover:text-gray-300" href="#comment-{{.ID}}">
532 {{ template "repo/fragments/time" .Created }}
533 </a>
534 </div>
535 <!-- Row 2: Body text -->
536 <div class="prose dark:prose-invert mt-1">
537 {{ .Body | markdown }}
538 </div>
539 </div>
540 </div>
541{{ end }}
542
543{{ define "loginPrompt" }}
544 <div class="bg-amber-50 dark:bg-amber-900 border border-amber-500 rounded drop-shadow-sm p-2 relative flex gap-2 items-center">
545 <a href="/signup" class="btn-create py-0 hover:no-underline hover:text-white flex items-center gap-2">
546 sign up
547 </a>
548 <span class="text-gray-500 dark:text-gray-400">or</span>
549 <a href="/login" class="underline">login</a>
550 to add to the discussion
551 </div>
552{{ end }}