repos
/ orchard main

orchard

mirror

Every site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.

blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics

7.2 KB · 368 lines · CSS Raw History
  1@keyframes code-transformRight {
  2  from {
  3    transform: scaleX(0);
  4  }
  5  to {
  6    transform: scaleX(1);
  7  }
  8}
  9
 10@keyframes code-transformLeft {
 11  from {
 12    transform: scaleX(1);
 13  }
 14  to {
 15    transform: scaleX(0);
 16  }
 17}
 18
 19@keyframes code-cardEnter {
 20  from {
 21    opacity: 0;
 22    transform: translateY(20px);
 23  }
 24  to {
 25    opacity: 1;
 26    transform: translateY(0);
 27  }
 28}
 29
 30.code-background {
 31  position: absolute;
 32  top: 0;
 33  left: 0;
 34  right: 0;
 35  bottom: 0;
 36  background-color: white;
 37  z-index: -2;
 38}
 39
 40.code-heading {
 41  font-weight: 700;
 42  margin-top: 60px;
 43  margin-bottom: 20px;
 44  font-size: 2.5em;
 45  color: black;
 46}
 47
 48.code-heading::before {
 49  content: "";
 50  display: block;
 51  width: 50px;
 52  height: 5px;
 53  margin-bottom: 20px;
 54  background-color: var(--color-blue);
 55}
 56
 57.code-paragraph {
 58  font-size: 1.5em;
 59  margin-top: 0;
 60  margin-bottom: 30px;
 61  font-weight: 300;
 62  color: black;
 63}
 64
 65.code-paragraph a {
 66  color: black;
 67  text-decoration: none;
 68  position: relative;
 69  white-space: nowrap;
 70}
 71
 72.code-paragraph a::before {
 73  content: "";
 74  position: absolute;
 75  left: 0;
 76  right: 0;
 77  bottom: 0;
 78  height: 2px;
 79  background: rgba(0, 0, 0, 1);
 80  transform-origin: left;
 81  animation: code-transformLeft 300ms normal forwards;
 82}
 83
 84.code-paragraph a::after {
 85  content: "";
 86  position: absolute;
 87  left: 0;
 88  right: 0;
 89  bottom: 0;
 90  height: 2px;
 91  background: rgba(0, 0, 0, 0.2);
 92}
 93
 94.code-paragraph a:hover::before {
 95  animation: code-transformRight 300ms normal forwards;
 96}
 97
 98.code-projects {
 99  display: flex;
100  width: 100%;
101  flex-wrap: wrap;
102  gap: 20px;
103}
104
105/* Only the last grid on the page needs room under it. When a section follows,
106   that section's own heading margin is the gap, and adding this as well left a
107   void under a short list. */
108.code-projects:last-child {
109  padding-bottom: 60px;
110}
111
112.code-project {
113  width: calc(50% - 10px);
114  display: flex;
115  flex-direction: column;
116  animation: code-cardEnter 600ms cubic-bezier(0.16, 1, 0.3, 1) both;
117}
118
119@media (max-width: 767.98px) {
120  .code-project {
121    width: 100%;
122  }
123}
124
125.code-projectHeading {
126  font-weight: 700;
127  margin-top: 40px;
128  margin-bottom: 8px;
129  font-size: 2em;
130  color: black;
131}
132
133.code-tags {
134  display: flex;
135  flex-wrap: wrap;
136  gap: 6px;
137  margin-bottom: 12px;
138}
139
140.code-tag {
141  display: inline-block;
142  font-size: 0.75em;
143  padding: 2px 8px;
144  background-color: var(--color-blue);
145  border-radius: var(--radius-2);
146  color: white;
147  font-family: monospace;
148  text-transform: uppercase;
149  letter-spacing: 1px;
150}
151
152.code-projectParagraph {
153  font-size: 1.3em;
154  margin-top: 0;
155  margin-bottom: 16px;
156  font-weight: 300;
157  color: black;
158  flex-grow: 1;
159  line-height: 1.5;
160}
161
162.code-projectCommit {
163  font-family: monospace;
164  background: var(--color-primary);
165  color: #00ff00;
166  padding: 16px;
167  overflow-x: hidden;
168  max-width: 100%;
169  text-overflow: ellipsis;
170  font-size: 0.85em;
171  line-height: 1.6;
172  border-radius: var(--radius-2);
173  margin-top: 0;
174  margin-bottom: 16px;
175}
176
177.code-projectButton {
178  padding: 8px 12px;
179  font-size: 0.9em;
180  text-decoration: none;
181  background-color: black;
182  font-weight: 700;
183  text-transform: uppercase;
184  display: inline-flex;
185  align-items: center;
186  justify-content: center;
187  letter-spacing: 2px;
188  color: white;
189  background-image: linear-gradient(
190    to right,
191    var(--color-blue) 0,
192    var(--color-purple) 100%
193  );
194  transform: scale(1);
195  transition-duration: 250ms;
196  transition-property: transform;
197  width: 120px;
198  text-align: center;
199  border-radius: var(--radius-2);
200}
201
202.code-projectButton svg {
203  margin-right: 10px;
204}
205
206.code-projectButton:hover {
207  transform: scale(1.2);
208}
209
210/* The live cards carry two buttons instead of one. The gap is wider than it
211   looks like it needs to be because the buttons scale to 1.2 on hover and a
212   tighter gap put one on top of its neighbour. */
213.code-projectButtons {
214  display: flex;
215  flex-wrap: wrap;
216  gap: 16px;
217}
218
219.code-project-live .code-projectButton {
220  width: auto;
221  min-width: 120px;
222  padding-left: 16px;
223  padding-right: 16px;
224}
225
226.code-projectButton-secondary {
227  background-image: none;
228  background-color: transparent;
229  color: black;
230  border: 2px solid rgba(0, 0, 0, 0.2);
231  transition-property: transform, border-color;
232}
233
234.code-projectButton-secondary:hover {
235  border-color: var(--color-blue);
236}
237
238.code-sectionNote-live {
239  color: black;
240}
241
242/* The active / archived split.
243 *
244 * The archived half is quieter: grey tag pills, an outline button instead of a
245 * gradient, softer body text. A separate palette rather than a filter, because
246 * grayscale() would also flatten the heading and the focus ring.
247 *
248 * Hovering one brings the colour back. */
249
250.code-sectionHead {
251  display: flex;
252  align-items: center;
253  gap: 16px;
254  width: 100%;
255  margin-top: 50px;
256}
257
258.code-sectionTitle {
259  font-weight: 700;
260  font-size: 1.1em;
261  text-transform: uppercase;
262  letter-spacing: 3px;
263  color: black;
264  margin: 0;
265}
266
267/* The rule takes the leftover width, so the count always sits at the far edge
268   however long the title is. */
269.code-sectionRule {
270  flex: 1;
271  height: 2px;
272  background-color: var(--color-blue);
273}
274
275.code-sectionCount {
276  font-family: monospace;
277  font-size: 0.85em;
278  letter-spacing: 2px;
279  color: var(--color-blue);
280}
281
282.code-sectionHead-archived .code-sectionRule {
283  background-color: rgba(0, 0, 0, 0.15);
284}
285
286.code-sectionHead-archived .code-sectionCount {
287  color: rgba(0, 0, 0, 0.4);
288}
289
290.code-sectionHead-archived .code-sectionTitle {
291  color: rgba(0, 0, 0, 0.55);
292}
293
294.code-sectionNote {
295  font-size: 1.1em;
296  font-weight: 300;
297  color: rgba(0, 0, 0, 0.55);
298  margin: 12px 0 0;
299  max-width: 46em;
300}
301
302/* The heading margin already spaces the first row of cards. */
303.code-projects-archived .code-projectHeading {
304  margin-top: 30px;
305  color: rgba(0, 0, 0, 0.65);
306}
307
308.code-project-archived .code-projectParagraph {
309  color: rgba(0, 0, 0, 0.55);
310}
311
312.code-project-archived .code-tag {
313  background-color: rgba(0, 0, 0, 0.35);
314}
315
316/* The one pill that stays legible at rest: it is the label doing the work of
317   the whole section. */
318.code-tag-archived {
319  background-color: transparent !important;
320  color: rgba(0, 0, 0, 0.55);
321  border: 1px solid rgba(0, 0, 0, 0.25);
322  padding: 1px 7px;
323}
324
325.code-project-archived .code-projectButton {
326  background-image: none;
327  background-color: transparent;
328  color: rgba(0, 0, 0, 0.6);
329  border: 2px solid rgba(0, 0, 0, 0.2);
330  transition-property: transform, color, border-color, background-color;
331}
332
333.code-project-archived:hover .code-projectHeading,
334.code-project-archived:focus-within .code-projectHeading {
335  color: black;
336}
337
338.code-project-archived:hover .code-projectParagraph,
339.code-project-archived:focus-within .code-projectParagraph {
340  color: black;
341}
342
343.code-project-archived:hover .code-tag,
344.code-project-archived:focus-within .code-tag {
345  background-color: var(--color-blue);
346}
347
348.code-project-archived:hover .code-projectButton,
349.code-project-archived:focus-within .code-projectButton {
350  background-image: linear-gradient(
351    to right,
352    var(--color-blue) 0,
353    var(--color-purple) 100%
354  );
355  border-color: transparent;
356  color: white;
357}
358
359/* The card already animates in; anything that only fires on hover is decoration
360   and should stop when asked. */
361@media (prefers-reduced-motion: reduce) {
362  .code-project,
363  .code-project-archived .code-projectButton {
364    animation: none;
365    transition: none;
366  }
367}