moonwalk 0.1.2 → 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.
- checksums.yaml +4 -4
- data/README.md +128 -23
- data/_config.yml +29 -6
- data/_data/home.yml +104 -0
- data/_includes/back_to_top.html +53 -0
- data/_includes/code_copy.html +31 -0
- data/_includes/date_and_social_share.html +29 -22
- data/_includes/footnotes.html +39 -0
- data/_includes/github_alerts.html +41 -0
- data/_includes/head.html +19 -1
- data/_includes/link_preview.html +56 -0
- data/_includes/post_nav.html +10 -0
- data/_includes/progress_bar.html +25 -0
- data/_includes/search.html +61 -0
- data/_includes/toc.html +42 -0
- data/_includes/toggle_theme_button.html +14 -8
- data/_includes/toggle_theme_js.html +19 -14
- data/_layouts/blog.html +5 -1
- data/_layouts/default.html +25 -2
- data/_layouts/post.html +17 -2
- data/_sass/list.scss +35 -17
- data/_sass/moonwalk.scss +668 -55
- data/_sass/syntax.scss +99 -1
- data/assets/css/main.scss +3 -3
- data/assets/images/favicon/android-chrome-192x192.png +0 -0
- data/assets/images/favicon/android-chrome-256x256.png +0 -0
- data/assets/images/favicon/apple-touch-icon.png +0 -0
- data/assets/images/favicon/browserconfig.xml +9 -0
- data/assets/images/favicon/favicon-16x16.png +0 -0
- data/assets/images/favicon/favicon-32x32.png +0 -0
- data/assets/images/favicon/favicon.ico +0 -0
- data/assets/images/favicon/mstile-150x150.png +0 -0
- data/assets/images/favicon/safari-pinned-tab.svg +19 -0
- data/assets/images/favicon/site.webmanifest +19 -0
- metadata +73 -11
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
(function() {
|
|
3
|
+
// Hover any internal post link to see a small preview card with title,
|
|
4
|
+
// excerpt and date. Pulls from /search.json which is a Jekyll-generated
|
|
5
|
+
// index of all posts.
|
|
6
|
+
var postIndex = null;
|
|
7
|
+
var loading = null;
|
|
8
|
+
|
|
9
|
+
function loadIndex() {
|
|
10
|
+
if (loading) return loading;
|
|
11
|
+
loading = fetch('{{ "/search.json" | relative_url }}')
|
|
12
|
+
.then(function(r) { return r.ok ? r.json() : []; })
|
|
13
|
+
.then(function(data) { postIndex = data; return data; })
|
|
14
|
+
.catch(function() { postIndex = []; return []; });
|
|
15
|
+
return loading;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
var card = document.createElement('div');
|
|
19
|
+
card.className = 'link-preview';
|
|
20
|
+
document.body.appendChild(card);
|
|
21
|
+
var hideTimer;
|
|
22
|
+
|
|
23
|
+
function show(link, post) {
|
|
24
|
+
card.innerHTML =
|
|
25
|
+
'<div class="lp-title">' + escape(post.title) + '</div>' +
|
|
26
|
+
(post.excerpt ? '<div class="lp-excerpt">' + escape(post.excerpt) + '</div>' : '') +
|
|
27
|
+
'<div class="lp-meta">' + escape(post.date || '') + '</div>';
|
|
28
|
+
var rect = link.getBoundingClientRect();
|
|
29
|
+
card.style.top = (window.scrollY + rect.bottom + 8) + 'px';
|
|
30
|
+
card.style.left = Math.max(12, window.scrollX + rect.left) + 'px';
|
|
31
|
+
card.classList.add('visible');
|
|
32
|
+
}
|
|
33
|
+
function hide() {
|
|
34
|
+
hideTimer = setTimeout(function() { card.classList.remove('visible'); }, 100);
|
|
35
|
+
}
|
|
36
|
+
function escape(s) {
|
|
37
|
+
return String(s || '').replace(/[&<>"']/g, function(c) {
|
|
38
|
+
return { '&':'&','<':'<','>':'>','"':'"',"'":''' }[c];
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
document.querySelectorAll('.page-content a[href^="/"], .page-content a[href^="{{ site.url }}"]').forEach(function(link) {
|
|
43
|
+
link.addEventListener('mouseenter', function() {
|
|
44
|
+
clearTimeout(hideTimer);
|
|
45
|
+
loadIndex().then(function(idx) {
|
|
46
|
+
var href = link.getAttribute('href').replace('{{ site.url }}', '');
|
|
47
|
+
var match = idx.find(function(p) { return p.url === href || p.url === href + '/'; });
|
|
48
|
+
if (match) show(link, match);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
link.addEventListener('mouseleave', hide);
|
|
52
|
+
});
|
|
53
|
+
card.addEventListener('mouseenter', function() { clearTimeout(hideTimer); });
|
|
54
|
+
card.addEventListener('mouseleave', hide);
|
|
55
|
+
})();
|
|
56
|
+
</script>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{% if page.previous or page.next %}
|
|
2
|
+
<nav class="post-nav" aria-label="Post navigation">
|
|
3
|
+
{% if page.previous %}
|
|
4
|
+
<a class="post-nav-prev" href="{{ page.previous.url | relative_url }}">← {{ page.previous.title }}</a>
|
|
5
|
+
{% endif %}
|
|
6
|
+
{% if page.next %}
|
|
7
|
+
<a class="post-nav-next" href="{{ page.next.url | relative_url }}">{{ page.next.title }} →</a>
|
|
8
|
+
{% endif %}
|
|
9
|
+
</nav>
|
|
10
|
+
{% endif %}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<div class="progress-bar" aria-hidden="true"></div>
|
|
2
|
+
<style>
|
|
3
|
+
.progress-bar {
|
|
4
|
+
position: fixed;
|
|
5
|
+
top: 0;
|
|
6
|
+
left: 0;
|
|
7
|
+
width: 0%;
|
|
8
|
+
height: 3px;
|
|
9
|
+
background: var(--links);
|
|
10
|
+
z-index: 100;
|
|
11
|
+
transition: width 50ms linear;
|
|
12
|
+
}
|
|
13
|
+
</style>
|
|
14
|
+
<script>
|
|
15
|
+
(function() {
|
|
16
|
+
var bar = document.querySelector('.progress-bar');
|
|
17
|
+
window.addEventListener('scroll', function() {
|
|
18
|
+
var scrollTop = window.scrollY;
|
|
19
|
+
var docHeight = document.documentElement.scrollHeight - window.innerHeight;
|
|
20
|
+
if (docHeight > 0) {
|
|
21
|
+
bar.style.width = (scrollTop / docHeight * 100) + '%';
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
})();
|
|
25
|
+
</script>
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
<div class="search">
|
|
2
|
+
<input type="search" id="search-input" class="search-input" placeholder="Search posts..." aria-label="Search posts" autocomplete="off">
|
|
3
|
+
<ul id="search-results" class="search-results" hidden></ul>
|
|
4
|
+
</div>
|
|
5
|
+
|
|
6
|
+
<script>
|
|
7
|
+
(function() {
|
|
8
|
+
var input = document.getElementById('search-input');
|
|
9
|
+
var list = document.getElementById('search-results');
|
|
10
|
+
if (!input || !list) return;
|
|
11
|
+
|
|
12
|
+
var index = null;
|
|
13
|
+
function loadIndex() {
|
|
14
|
+
return fetch('{{ "/search.json" | relative_url }}')
|
|
15
|
+
.then(function(r) { return r.ok ? r.json() : []; })
|
|
16
|
+
.then(function(data) { index = data; return data; });
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function score(p, q) {
|
|
20
|
+
var s = 0;
|
|
21
|
+
var ql = q.toLowerCase();
|
|
22
|
+
if ((p.title || '').toLowerCase().indexOf(ql) !== -1) s += 5;
|
|
23
|
+
if ((p.tags || []).some(function(t) { return t.toLowerCase().indexOf(ql) !== -1; })) s += 3;
|
|
24
|
+
if ((p.excerpt || '').toLowerCase().indexOf(ql) !== -1) s += 1;
|
|
25
|
+
return s;
|
|
26
|
+
}
|
|
27
|
+
function escape(s) {
|
|
28
|
+
return String(s || '').replace(/[&<>"']/g, function(c) {
|
|
29
|
+
return { '&':'&','<':'<','>':'>','"':'"',"'":''' }[c];
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function render(results, q) {
|
|
33
|
+
if (!results.length) {
|
|
34
|
+
list.innerHTML = '<li class="search-empty">No matches for "' + escape(q) + '"</li>';
|
|
35
|
+
list.hidden = false;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
list.innerHTML = results.slice(0, 8).map(function(p) {
|
|
39
|
+
return '<li class="search-result">' +
|
|
40
|
+
'<a href="' + escape(p.url) + '">' +
|
|
41
|
+
'<span class="search-result-title">' + escape(p.title) + '</span>' +
|
|
42
|
+
'<span class="search-result-date">' + escape(p.date) + '</span>' +
|
|
43
|
+
'</a></li>';
|
|
44
|
+
}).join('');
|
|
45
|
+
list.hidden = false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
input.addEventListener('input', function() {
|
|
49
|
+
var q = input.value.trim();
|
|
50
|
+
if (!q) { list.hidden = true; list.innerHTML = ''; return; }
|
|
51
|
+
var run = function() {
|
|
52
|
+
var hits = index.map(function(p) { return [score(p, q), p]; })
|
|
53
|
+
.filter(function(r) { return r[0] > 0; })
|
|
54
|
+
.sort(function(a, b) { return b[0] - a[0]; })
|
|
55
|
+
.map(function(r) { return r[1]; });
|
|
56
|
+
render(hits, q);
|
|
57
|
+
};
|
|
58
|
+
if (!index) loadIndex().then(run); else run();
|
|
59
|
+
});
|
|
60
|
+
})();
|
|
61
|
+
</script>
|
data/_includes/toc.html
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{% assign headers = content | split: '<h' %}
|
|
2
|
+
{% assign toc_items = "" %}
|
|
3
|
+
{% for header in headers %}
|
|
4
|
+
{% assign first_char = header | slice: 0, 1 %}
|
|
5
|
+
{% if first_char == "2" or first_char == "3" %}
|
|
6
|
+
{% assign id_start = header | split: 'id="' %}
|
|
7
|
+
{% if id_start.size > 1 %}
|
|
8
|
+
{% assign id_rest = id_start[1] | split: '"' %}
|
|
9
|
+
{% assign header_id = id_rest[0] %}
|
|
10
|
+
{% assign text_start = header | split: '>' %}
|
|
11
|
+
{% assign text_rest = text_start[1] | split: '</h' %}
|
|
12
|
+
{% assign header_text = text_rest[0] %}
|
|
13
|
+
{% if first_char == "2" %}
|
|
14
|
+
{% assign toc_items = toc_items | append: "2|" | append: header_id | append: "|" | append: header_text | append: ";;;" %}
|
|
15
|
+
{% else %}
|
|
16
|
+
{% assign toc_items = toc_items | append: "3|" | append: header_id | append: "|" | append: header_text | append: ";;;" %}
|
|
17
|
+
{% endif %}
|
|
18
|
+
{% endif %}
|
|
19
|
+
{% endif %}
|
|
20
|
+
{% endfor %}
|
|
21
|
+
|
|
22
|
+
{% assign items = toc_items | split: ";;;" %}
|
|
23
|
+
{% if items.size > 0 %}
|
|
24
|
+
<details class="toc" open>
|
|
25
|
+
<summary>Table of Contents</summary>
|
|
26
|
+
<ul>
|
|
27
|
+
{% for item in items %}
|
|
28
|
+
{% if item != "" %}
|
|
29
|
+
{% assign parts = item | split: "|" %}
|
|
30
|
+
{% assign level = parts[0] %}
|
|
31
|
+
{% assign id = parts[1] %}
|
|
32
|
+
{% assign text = parts[2] %}
|
|
33
|
+
{% if level == "2" %}
|
|
34
|
+
<li><a href="#{{ id }}">{{ text }}</a></li>
|
|
35
|
+
{% else %}
|
|
36
|
+
<li class="toc-sub"><a href="#{{ id }}">{{ text }}</a></li>
|
|
37
|
+
{% endif %}
|
|
38
|
+
{% endif %}
|
|
39
|
+
{% endfor %}
|
|
40
|
+
</ul>
|
|
41
|
+
</details>
|
|
42
|
+
{% endif %}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
<button
|
|
2
|
-
<svg viewBox="0 0
|
|
3
|
-
<circle cx="
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
<button aria-label="Toggle dark mode" aria-pressed="false" class="theme-toggle">
|
|
2
|
+
<svg class="icon-sun" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentcolor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
3
|
+
<circle cx="12" cy="12" r="5"></circle>
|
|
4
|
+
<line x1="12" y1="1" x2="12" y2="3"></line>
|
|
5
|
+
<line x1="12" y1="21" x2="12" y2="23"></line>
|
|
6
|
+
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
|
|
7
|
+
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
|
|
8
|
+
<line x1="1" y1="12" x2="3" y2="12"></line>
|
|
9
|
+
<line x1="21" y1="12" x2="23" y2="12"></line>
|
|
10
|
+
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
|
|
11
|
+
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
|
|
12
|
+
</svg>
|
|
13
|
+
<svg class="icon-moon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentcolor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
14
|
+
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
|
9
15
|
</svg>
|
|
10
16
|
</button>
|
|
@@ -5,27 +5,32 @@
|
|
|
5
5
|
document.documentElement.setAttribute('data-theme', currentTheme);
|
|
6
6
|
|
|
7
7
|
function themeChange() {
|
|
8
|
-
|
|
8
|
+
var button = document.querySelector('.theme-toggle');
|
|
9
|
+
if (!button) return;
|
|
10
|
+
|
|
11
|
+
function updateIcon(theme) {
|
|
12
|
+
button.setAttribute('aria-pressed', theme === 'dark' ? 'true' : 'false');
|
|
13
|
+
button.querySelector('.icon-sun').style.display = theme === 'dark' ? 'block' : 'none';
|
|
14
|
+
button.querySelector('.icon-moon').style.display = theme === 'dark' ? 'none' : 'block';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
updateIcon(document.documentElement.getAttribute('data-theme'));
|
|
9
18
|
|
|
10
19
|
button.addEventListener('click', function (e) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
document.documentElement.setAttribute('data-theme', 'dark');
|
|
19
|
-
localStorage.setItem('theme', 'dark');
|
|
20
|
-
}
|
|
20
|
+
var currentTheme = document.documentElement.getAttribute('data-theme');
|
|
21
|
+
var next = currentTheme === 'dark' ? 'light' : 'dark';
|
|
22
|
+
|
|
23
|
+
transition();
|
|
24
|
+
document.documentElement.setAttribute('data-theme', next);
|
|
25
|
+
localStorage.setItem('theme', next);
|
|
26
|
+
updateIcon(next);
|
|
21
27
|
});
|
|
22
28
|
|
|
23
|
-
|
|
29
|
+
function transition() {
|
|
24
30
|
document.documentElement.classList.add('transition');
|
|
25
|
-
window.setTimeout(()
|
|
31
|
+
window.setTimeout(function () {
|
|
26
32
|
document.documentElement.classList.remove('transition');
|
|
27
33
|
}, 1000);
|
|
28
34
|
}
|
|
29
35
|
}
|
|
30
36
|
</script>
|
|
31
|
-
|
data/_layouts/blog.html
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
layout: default
|
|
3
3
|
---
|
|
4
|
-
<a href="
|
|
4
|
+
<a href="javascript:history.back()" class="back-link" aria-label="Go back">
|
|
5
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
6
|
+
<polyline points="15 18 9 12 15 6"></polyline>
|
|
7
|
+
</svg>
|
|
8
|
+
</a>
|
|
5
9
|
|
|
6
10
|
<header>
|
|
7
11
|
<h1>{{ site.title }}</h1>
|
data/_layouts/default.html
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
<html lang="{{ page.lang | default: "en" }}" class="html" data-theme="{{ site.theme_config.appearance | default: "auto" }}">
|
|
3
3
|
{%- include head.html -%}
|
|
4
4
|
<body>
|
|
5
|
+
{%- if site.theme_config.show_progress_bar and page.layout == "post" -%}
|
|
6
|
+
{% include progress_bar.html %}
|
|
7
|
+
{%- endif -%}
|
|
5
8
|
<main class="page-content" aria-label="Content">
|
|
6
9
|
<div class="w">
|
|
7
10
|
{{ content }}
|
|
@@ -16,16 +19,36 @@
|
|
|
16
19
|
|
|
17
20
|
{%- endif -%}
|
|
18
21
|
{%- if site.soopr -%}
|
|
19
|
-
Powered by <a href="https://www.soopr.co" target="_blank" rel="noreferrer">Soopr</a>
|
|
22
|
+
Powered by <a href="https://www.soopr.co" target="_blank" rel="noopener noreferrer">Soopr</a>
|
|
20
23
|
|
|
21
24
|
•
|
|
22
25
|
|
|
23
26
|
{%- endif -%}
|
|
24
|
-
Theme <a href="https://github.com/abhinavs/moonwalk" target="_blank" rel="noreferrer">Moonwalk</a>
|
|
27
|
+
Theme <a href="https://github.com/abhinavs/moonwalk" target="_blank" rel="noopener noreferrer">Moonwalk</a>
|
|
25
28
|
</div>
|
|
26
29
|
</div>
|
|
27
30
|
</main>
|
|
28
31
|
|
|
32
|
+
{%- if page.layout == "post" -%}
|
|
33
|
+
{% include github_alerts.html %}
|
|
34
|
+
{%- endif -%}
|
|
35
|
+
|
|
36
|
+
{%- if site.theme_config.show_code_copy and page.layout == "post" -%}
|
|
37
|
+
{% include code_copy.html %}
|
|
38
|
+
{%- endif -%}
|
|
39
|
+
|
|
40
|
+
{%- if site.theme_config.show_footnote_tooltips and page.layout == "post" -%}
|
|
41
|
+
{% include footnotes.html %}
|
|
42
|
+
{%- endif -%}
|
|
43
|
+
|
|
44
|
+
{%- if site.theme_config.show_link_previews and page.layout == "post" -%}
|
|
45
|
+
{% include link_preview.html %}
|
|
46
|
+
{%- endif -%}
|
|
47
|
+
|
|
48
|
+
{%- if site.theme_config.show_back_to_top and page.layout == "post" -%}
|
|
49
|
+
{% include back_to_top.html %}
|
|
50
|
+
{%- endif -%}
|
|
51
|
+
|
|
29
52
|
{%- if site.soopr -%}
|
|
30
53
|
{%- if site.soopr.publish_token and jekyll.environment == "production" -%}
|
|
31
54
|
<script async defer data-soopr-token="{{site.soopr.publish_token}}" src="https://sdk.soopr.co/soopr.js"></script>
|
data/_layouts/post.html
CHANGED
|
@@ -2,7 +2,22 @@
|
|
|
2
2
|
layout: default
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
<a href="
|
|
5
|
+
<a href="javascript:history.back()" class="back-link" aria-label="Go back">
|
|
6
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
7
|
+
<polyline points="15 18 9 12 15 6"></polyline>
|
|
8
|
+
</svg>
|
|
9
|
+
</a>
|
|
6
10
|
<h1 class="post-title">{{ page.title }}</h1>
|
|
7
11
|
{% include date_and_social_share.html %}
|
|
8
|
-
|
|
12
|
+
|
|
13
|
+
{%- if site.theme_config.show_toc and page.toc -%}
|
|
14
|
+
{% include toc.html %}
|
|
15
|
+
{%- endif -%}
|
|
16
|
+
|
|
17
|
+
<div class="post-content{% if page.dropcap %} has-dropcap{% endif %}">
|
|
18
|
+
{{ content }}
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
{%- if site.theme_config.show_post_nav -%}
|
|
22
|
+
{% include post_nav.html %}
|
|
23
|
+
{%- endif -%}
|
data/_sass/list.scss
CHANGED
|
@@ -1,46 +1,62 @@
|
|
|
1
1
|
ul.horizontal-list {
|
|
2
2
|
display: flex;
|
|
3
|
-
//justify-content: space-between;
|
|
4
3
|
margin-top: 0em;
|
|
5
|
-
|
|
4
|
+
padding-left: 0;
|
|
5
|
+
list-style: none;
|
|
6
6
|
flex-wrap: wrap;
|
|
7
|
+
font-family: var(--font-sans);
|
|
8
|
+
gap: 0.8em;
|
|
7
9
|
|
|
8
10
|
li {
|
|
9
|
-
display:inline;
|
|
10
|
-
margin-right: 1em;
|
|
11
|
+
display: inline;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
li a {
|
|
14
15
|
text-decoration: none;
|
|
15
|
-
font-weight:
|
|
16
|
+
font-weight: 500;
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
li:not(.card) {
|
|
20
|
+
margin-right: 1em;
|
|
21
|
+
}
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
.card {
|
|
21
|
-
padding: 1em;
|
|
22
|
-
border: 1px var(--
|
|
23
|
-
width:
|
|
25
|
+
padding: 1.1em 1.15em;
|
|
26
|
+
border: 1px solid var(--border);
|
|
27
|
+
width: calc(33.333% - 0.6em);
|
|
28
|
+
box-sizing: border-box;
|
|
24
29
|
height: auto;
|
|
25
|
-
text-align:
|
|
30
|
+
text-align: left;
|
|
26
31
|
font-size: 1em;
|
|
27
|
-
align-items:
|
|
28
|
-
background-color: var(--bg-
|
|
29
|
-
|
|
30
|
-
border-
|
|
32
|
+
align-items: flex-start;
|
|
33
|
+
background-color: var(--bg-subtle);
|
|
34
|
+
border-radius: var(--radius-md);
|
|
35
|
+
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
|
|
36
|
+
|
|
37
|
+
&:hover {
|
|
38
|
+
transform: translateY(-2px);
|
|
39
|
+
box-shadow: 0 4px 16px rgba(0,0,0,0.06);
|
|
40
|
+
border-color: var(--links);
|
|
41
|
+
}
|
|
31
42
|
|
|
32
43
|
.header {
|
|
33
44
|
color: var(--links);
|
|
45
|
+
font-weight: 600;
|
|
46
|
+
letter-spacing: -0.005em;
|
|
34
47
|
}
|
|
35
48
|
|
|
36
49
|
.body {
|
|
37
|
-
font-size: 0.
|
|
50
|
+
font-size: 0.85em;
|
|
51
|
+
color: var(--text-secondary);
|
|
52
|
+
line-height: 1.55;
|
|
38
53
|
}
|
|
39
54
|
|
|
40
55
|
hr {
|
|
41
56
|
margin: 0.5em 0;
|
|
57
|
+
border: none;
|
|
58
|
+
border-top: 1px solid var(--border-subtle);
|
|
42
59
|
}
|
|
43
|
-
|
|
44
60
|
}
|
|
45
61
|
|
|
46
62
|
/* Responsive cards - one column layout on small screens */
|
|
@@ -48,10 +64,12 @@ ul.horizontal-list {
|
|
|
48
64
|
ul.horizontal-list li.card {
|
|
49
65
|
width: 100%;
|
|
50
66
|
display: block;
|
|
51
|
-
margin-bottom: 1em;
|
|
52
|
-
margin-left: 1em;
|
|
53
67
|
a, .header {
|
|
54
68
|
font-size: 1em;
|
|
55
69
|
}
|
|
56
70
|
}
|
|
71
|
+
.card:hover {
|
|
72
|
+
transform: none;
|
|
73
|
+
box-shadow: none;
|
|
74
|
+
}
|
|
57
75
|
}
|