repos

blog.bythewood.me-flask

mirror archived upstream

Markdown blog on Flask with Vite-built assets and WeasyPrint PDF export, rewritten from the Wagtail build that preceded it.

blogdockerflaskmarkdownpythonself-hostedvite

6.7 KB · 358 lines · SCSS Raw History
  1body {
  2  min-height: 100vh;
  3  display: flex;
  4  flex-direction: column;
  5  -webkit-font-smoothing: antialiased;
  6  -moz-osx-font-smoothing: grayscale;
  7  letter-spacing: 0.01em;
  8}
  9
 10// ── Logo ──
 11
 12.logo {
 13  content: "";
 14  display: flex;
 15  align-items: center;
 16  justify-content: center;
 17  background-image: linear-gradient(
 18    135deg,
 19    rgb(14, 63, 180) 0%,
 20    rgb(107, 158, 120) 100%
 21  );
 22  width: 36px;
 23  height: 36px;
 24  margin-top: auto;
 25  margin-bottom: auto;
 26  border-radius: 3px;
 27  transition: transform 0.25s ease, box-shadow 0.25s ease;
 28  position: relative;
 29  text-decoration: none !important;
 30
 31  &::after {
 32    content: ">_";
 33    font-family: monospace;
 34    font-weight: bold;
 35    font-size: 14px;
 36    color: rgba(255, 255, 255, 0.9);
 37    line-height: 1;
 38    text-decoration: none;
 39  }
 40
 41  &[style*="width: 20px"]::after {
 42    font-size: 8px;
 43  }
 44
 45  &:hover {
 46    transform: rotate(12deg) scale(1.08);
 47    box-shadow: 0 0 14px rgba(107, 158, 120, 0.3);
 48  }
 49}
 50
 51// ── Navbar ──
 52
 53.navbar {
 54  border-bottom: 1px solid rgba(107, 158, 120, 0.06);
 55
 56  .nav-link {
 57    font-size: 0.82rem;
 58    font-weight: 500;
 59    letter-spacing: 0.04em;
 60    padding-left: 1rem !important;
 61    padding-right: 1rem !important;
 62    text-transform: lowercase;
 63    position: relative;
 64
 65    &::after {
 66      content: '';
 67      position: absolute;
 68      bottom: 0;
 69      left: 1rem;
 70      right: 1rem;
 71      height: 1px;
 72      background: #6b9e78;
 73      box-shadow: 0 0 6px rgba(107, 158, 120, 0.3);
 74      transform: scaleX(0);
 75      transition: transform 250ms ease;
 76    }
 77
 78    &:hover::after,
 79    &.active::after {
 80      transform: scaleX(1);
 81    }
 82  }
 83}
 84
 85// ── Breadcrumb bar ──
 86
 87.breadcrumb-bar {
 88  background: rgba(107, 158, 120, 0.02);
 89  border-bottom: 1px solid rgba(107, 158, 120, 0.04);
 90}
 91
 92// ── Footer ──
 93
 94footer {
 95  padding-top: 4rem;
 96  position: relative;
 97
 98  .links {
 99    padding-top: 4rem;
100    padding-bottom: 2rem;
101    position: relative;
102    z-index: 20;
103  }
104
105  .h5 {
106    font-size: 0.72rem;
107    letter-spacing: 0.1em;
108    text-transform: uppercase;
109    color: rgba(201, 168, 76, 0.55);
110    font-weight: 600;
111  }
112
113  p {
114    color: rgba(221, 215, 205, 0.5);
115    font-size: 0.88rem;
116    line-height: 1.75;
117
118    a {
119      color: rgba(221, 215, 205, 0.75);
120      text-decoration: underline;
121      text-underline-offset: 2px;
122      transition: color 200ms ease;
123
124      &:hover {
125        color: #ddd7cd;
126      }
127    }
128  }
129}
130
131// ── Footer bar (sosumi) ──
132
133.footer-bar {
134  background: #070605;
135  border-top: 1px solid rgba(107, 158, 120, 0.05);
136  padding: 1rem 0;
137  color: rgba(221, 215, 205, 0.3);
138  font-size: 0.78rem;
139  letter-spacing: 0.03em;
140  position: relative;
141  z-index: 20;
142
143  small {
144    color: rgba(221, 215, 205, 0.3);
145  }
146
147  &-link {
148    color: rgba(221, 215, 205, 0.3);
149    transition: color 200ms ease;
150
151    &:hover {
152      color: #ddd7cd;
153    }
154  }
155}
156
157// ── Footer animated plane ──
158
159.footer-plane {
160  position: relative;
161  width: 100%;
162  height: 300px;
163  overflow: hidden;
164  z-index: 10;
165  perspective: 350px;
166
167  &-overlay {
168    width: 100%;
169    height: 100%;
170    position: absolute;
171    z-index: 11;
172    background: radial-gradient(
173      ellipse at 50% 50%,
174      rgba(9, 8, 6, 0) 0,
175      rgb(9, 8, 6) 80%
176    );
177  }
178
179  @keyframes footer-plane-keyframes {
180    0% {
181      transform: rotateX(45deg) translateY(-50%);
182    }
183
184    to {
185      transform: rotateX(45deg) translateY(0);
186    }
187  }
188
189  &-grid {
190    position: relative;
191    width: 100%;
192    height: 200%;
193    background-image: linear-gradient(
194        90deg,
195        rgba(107, 158, 120, 0.18) 1px,
196        transparent 0
197      ),
198      linear-gradient(180deg, rgba(107, 158, 120, 0.18) 1px, transparent 0);
199    background-size: 40px 30px;
200    background-repeat: repeat;
201    transform-origin: 100% 0 0;
202    animation: footer-plane-keyframes 17s linear infinite;
203  }
204}
205
206// ── Section labels — terminal-prompt style with amber ──
207
208.section-label {
209  font-size: 0.72rem;
210  font-weight: 600;
211  letter-spacing: 0.1em;
212  text-transform: uppercase;
213  color: #c9a84c;
214
215  &::before {
216    content: '> ';
217    opacity: 0.5;
218  }
219}
220
221// ── Card hover effects ──
222
223.card {
224  transition: border-color 250ms ease, box-shadow 250ms ease;
225
226  &:hover {
227    border-color: rgba(107, 158, 120, 0.18);
228    box-shadow: 0 0 20px rgba(107, 158, 120, 0.04);
229  }
230}
231
232// ── Search form — terminal style ──
233
234.search-form {
235  .search-icon {
236    position: absolute;
237    left: 0.85rem;
238    top: 50%;
239    transform: translateY(-50%);
240    color: #665f56;
241    pointer-events: none;
242    z-index: 2;
243  }
244
245  .search-input {
246    padding-left: 2.5rem;
247    font-size: 0.85rem;
248    letter-spacing: 0.02em;
249    border: 1px solid rgba(107, 158, 120, 0.15);
250    background: rgba(19, 18, 14, 0.6);
251    color: #ddd7cd;
252    transition: border-color 200ms ease, box-shadow 200ms ease;
253
254    &::placeholder {
255      color: #665f56;
256      font-style: normal;
257    }
258
259    &:focus {
260      border-color: rgba(107, 158, 120, 0.4);
261      box-shadow: 0 0 0 2px rgba(107, 158, 120, 0.1);
262      background: #13120e;
263    }
264  }
265}
266
267// ── Live search results ──
268
269#id_search_results .list-group-item {
270  color: #ddd7cd;
271  border-color: rgba(107, 158, 120, 0.08);
272
273  .fw-bold {
274    color: #ddd7cd;
275  }
276
277  &.active {
278    background: rgba(107, 158, 120, 0.12);
279    border-color: rgba(107, 158, 120, 0.2);
280    color: #ddd7cd;
281  }
282
283  &:hover {
284    background: rgba(107, 158, 120, 0.08);
285  }
286}
287
288// ── Blog index filter pills ──
289
290.filter-label {
291  font-size: 0.68rem;
292  font-weight: 600;
293  letter-spacing: 0.1em;
294  text-transform: uppercase;
295  color: #c9a84c;
296  opacity: 0.7;
297}
298
299.filter-divider {
300  width: 1px;
301  height: 1.2rem;
302  background: rgba(221, 215, 205, 0.1);
303  margin: 0 0.25rem;
304}
305
306.btn-filter {
307  background: rgba(221, 215, 205, 0.04);
308  color: #a09890;
309  border: 1px solid rgba(221, 215, 205, 0.08);
310  font-size: 0.75rem;
311  line-height: 1;
312  padding: 0.4rem 0.75rem;
313  display: inline-flex;
314  align-items: center;
315  transition: all 200ms ease;
316
317  &:hover {
318    background: rgba(107, 158, 120, 0.1);
319    color: #ddd7cd;
320    border-color: rgba(107, 158, 120, 0.2);
321  }
322}
323
324.btn-filter-active {
325  background: rgba(107, 158, 120, 0.15);
326  color: #7db88c;
327  border: 1px solid rgba(107, 158, 120, 0.3);
328  font-size: 0.75rem;
329  line-height: 1;
330  padding: 0.4rem 0.75rem;
331  display: inline-flex;
332  align-items: center;
333}
334
335.btn-filter-clear {
336  background: rgba(196, 112, 85, 0.1);
337  color: #c47055;
338  border: 1px solid rgba(196, 112, 85, 0.2);
339  font-size: 0.75rem;
340  line-height: 1;
341  padding: 0.4rem 0.75rem;
342  display: inline-flex;
343  align-items: center;
344  transition: all 200ms ease;
345
346  &:hover {
347    background: rgba(196, 112, 85, 0.2);
348    color: #d88a70;
349    border-color: rgba(196, 112, 85, 0.35);
350  }
351}
352
353// ── Vertical rule override ──
354
355.vr {
356  background-color: rgba(107, 158, 120, 0.12);
357}