stacks/news-digest: twice-daily LLM-curated briefing on ana-docker
The Miniflux inbox got noisy after a few subreddits + HN + Lobste.rs.
This stack distills a single static page twice a day — at 0800 and
2000 local — that surfaces only what cleared score + ratio filters,
each item tldr'd by qwen3.5-35-a3b on llama-swap.
Pipeline (digest.py, ~330 lines):
1. Discover subreddits from Miniflux feeds (any reddit.com/r/<sub>/
URL — single source of truth, no duplicated config).
2. Reddit JSON top-of-day per sub. Filter: score >= 50,
upvote_ratio >= 0.85. Cap 8 items per sub.
3. Miniflux /v1/entries for the 'Tech aggregators' category
(HN, Lobste.rs) — last 12 hours.
4. Batched per-source summarization via llama-swap
/v1/chat/completions. Each post gets a one-sentence tldr +
one-word tag (news / tutorial / release / discussion /
question / showcase / drama / meme).
5. Render Jinja2 template. Atomic write to /output/index.html
(.tmp + rename) so partial pages never get served. Per-edition
archive at /output/edition-YYYY-MM-DD-{am,pm}.html.
Two containers:
news-digest-worker python:3.12-alpine + busybox crond
news-digest-web nginx:alpine, port 8181, homepage card via
docker labels (group=News, fits next to Miniflux)
Both bind-mount /opt/docker/data/news-digest as /output and
/usr/share/nginx/html respectively.
Aesthetic — operations-center chrome (Australis cool-mono palette,
JetBrains Mono UPPERCASE eyebrows, mdi-glyph anchor) wrapping
editorial-serif news content (Fraunces variable serif w/ optical
sizes). Two type families that wouldn't normally meet, intentionally
combined: chrome says 'filed at 0800 from the bridge'; headlines say
'this is news, read it like news.' Sticky aurora-glow rule under the
masthead is the only sanctioned Australis gradient.
Edition stamp (AM/PM in big mono Australis-yellow) is the signature
piece — establishes the twice-daily rhythm at a glance.
All filtering + LLM + scheduling knobs in .env. Subreddit list is
implicit (read from Miniflux), so adding a sub = subscribing in
Miniflux, no config edit on this stack.
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>Daily Digest · {{ date_long }} · {{ edition_short }}</title>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
{# ────── header ────── #}
|
||||
<header class="masthead" role="banner">
|
||||
<div class="masthead-inner">
|
||||
<div class="masthead-brand">
|
||||
<span class="brand-glyph" aria-hidden="true">◢</span>
|
||||
<span class="brand-mark">DAILY DIGEST</span>
|
||||
</div>
|
||||
<div class="masthead-edition">
|
||||
<span class="edition-num">№ {{ generated_at.strftime("%j") }}</span>
|
||||
<span class="edition-stamp">{{ edition|upper }} EDITION</span>
|
||||
</div>
|
||||
<div class="masthead-meta">
|
||||
<div class="meta-row">
|
||||
<span class="meta-label">FILED</span>
|
||||
<span class="meta-value">{{ date_long|upper }} · {{ time_short }} {{ tz }}</span>
|
||||
</div>
|
||||
<div class="meta-row">
|
||||
<span class="meta-label">DESK</span>
|
||||
<span class="meta-value">SUBREDDITS · TECH FEEDS</span>
|
||||
</div>
|
||||
<div class="meta-row">
|
||||
<span class="meta-label">CURATED BY</span>
|
||||
<span class="meta-value">{{ model }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{# A thin aurora-glow rule under the masthead — the only sanctioned
|
||||
Australis gradient. #}
|
||||
<div class="aurora-rule" aria-hidden="true"></div>
|
||||
</header>
|
||||
|
||||
{# ────── nav strip ────── #}
|
||||
<nav class="jumpnav" aria-label="sections">
|
||||
<ol>
|
||||
{% if reddit_sources %}
|
||||
<li><a href="#reddit"><span class="jump-num">01</span> REDDIT</a></li>
|
||||
{% endif %}
|
||||
{% if tech_sources %}
|
||||
<li><a href="#tech"><span class="jump-num">02</span> TECH FEEDS</a></li>
|
||||
{% endif %}
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<main class="brief">
|
||||
|
||||
{# ────── REDDIT SECTION ────── #}
|
||||
{% if reddit_sources %}
|
||||
<section id="reddit" class="desk">
|
||||
<header class="desk-head">
|
||||
<span class="desk-num">01</span>
|
||||
<h2 class="desk-title">Reddit</h2>
|
||||
<span class="desk-sub">top of last {{ generated_at.hour < 14 and "12" or "12" }} hours · score-filtered</span>
|
||||
<span class="desk-count">{{ reddit_sources|sum(attribute='items')|length }} items</span>
|
||||
</header>
|
||||
|
||||
{% for src in reddit_sources %}
|
||||
<article class="source">
|
||||
<header class="source-head">
|
||||
<a class="source-name" href="{{ src.href }}" target="_blank" rel="noopener">
|
||||
{{ src.name }}
|
||||
</a>
|
||||
<span class="source-count">{{ src.items|length }}</span>
|
||||
</header>
|
||||
<ol class="items">
|
||||
{% for it in src.items %}
|
||||
<li class="item" data-tag="{{ it.tag }}">
|
||||
<div class="item-rail" aria-hidden="true">
|
||||
{% if it.score %}
|
||||
<span class="chip chip-score" title="upvotes">▲ {{ it.score }}</span>
|
||||
{% endif %}
|
||||
{% if it.comments %}
|
||||
<span class="chip chip-comments" title="comments">{{ it.comments }} ⌥</span>
|
||||
{% endif %}
|
||||
{% if it.tag and it.tag != 'other' %}
|
||||
<span class="chip chip-tag chip-tag-{{ it.tag }}">{{ it.tag }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="item-body">
|
||||
<h3 class="item-title">
|
||||
<a href="{{ it.url or it.permalink }}" target="_blank" rel="noopener">{{ it.title }}</a>
|
||||
</h3>
|
||||
{% if it.tldr %}
|
||||
<p class="item-tldr">{{ it.tldr }}</p>
|
||||
{% endif %}
|
||||
<footer class="item-foot">
|
||||
<a class="item-link" href="{{ it.permalink }}" target="_blank" rel="noopener">
|
||||
comments
|
||||
</a>
|
||||
{% if it.url and it.url != it.permalink %}
|
||||
<span class="sep">·</span>
|
||||
<a class="item-link" href="{{ it.url }}" target="_blank" rel="noopener">
|
||||
{{ it.url|domain }}
|
||||
</a>
|
||||
{% endif %}
|
||||
<span class="sep">·</span>
|
||||
<span class="item-meta">{{ it.posted_at|humanago }} ago</span>
|
||||
<span class="sep">·</span>
|
||||
<span class="item-meta">u/{{ it.author }}</span>
|
||||
</footer>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
{# ────── TECH FEEDS SECTION ────── #}
|
||||
{% if tech_sources %}
|
||||
<section id="tech" class="desk">
|
||||
<header class="desk-head">
|
||||
<span class="desk-num">02</span>
|
||||
<h2 class="desk-title">Tech Feeds</h2>
|
||||
<span class="desk-sub">non-reddit · last {{ generated_at.hour < 14 and "12" or "12" }} hours</span>
|
||||
<span class="desk-count">{{ tech_sources|sum(attribute='items')|length }} items</span>
|
||||
</header>
|
||||
|
||||
{% for src in tech_sources %}
|
||||
<article class="source">
|
||||
<header class="source-head">
|
||||
<a class="source-name" href="{{ src.href }}" target="_blank" rel="noopener">
|
||||
{{ src.name }}
|
||||
</a>
|
||||
<span class="source-count">{{ src.items|length }}</span>
|
||||
</header>
|
||||
<ol class="items">
|
||||
{% for it in src.items %}
|
||||
<li class="item" data-tag="{{ it.tag }}">
|
||||
<div class="item-rail" aria-hidden="true">
|
||||
{% if it.tag and it.tag != 'other' %}
|
||||
<span class="chip chip-tag chip-tag-{{ it.tag }}">{{ it.tag }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="item-body">
|
||||
<h3 class="item-title">
|
||||
<a href="{{ it.url }}" target="_blank" rel="noopener">{{ it.title }}</a>
|
||||
</h3>
|
||||
{% if it.tldr %}
|
||||
<p class="item-tldr">{{ it.tldr }}</p>
|
||||
{% endif %}
|
||||
<footer class="item-foot">
|
||||
{% if it.url %}
|
||||
<a class="item-link" href="{{ it.url }}" target="_blank" rel="noopener">
|
||||
{{ it.url|domain }}
|
||||
</a>
|
||||
<span class="sep">·</span>
|
||||
{% endif %}
|
||||
<span class="item-meta">{{ it.posted_at|humanago }} ago</span>
|
||||
{% if it.author %}
|
||||
<span class="sep">·</span>
|
||||
<span class="item-meta">{{ it.author }}</span>
|
||||
{% endif %}
|
||||
</footer>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
{% if not reddit_sources and not tech_sources %}
|
||||
<section class="desk empty">
|
||||
<p class="empty-msg">
|
||||
No items cleared the filters in the last window.<br>
|
||||
Lower <code>DIGEST_MIN_SCORE</code> or widen
|
||||
<code>DIGEST_REDDIT_HOURS</code> if this looks wrong.
|
||||
</p>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
</main>
|
||||
|
||||
<footer class="colophon">
|
||||
<div class="colophon-inner">
|
||||
<div class="colophon-block">
|
||||
<span class="meta-label">FILED</span>
|
||||
<span class="meta-value">{{ generated_at.isoformat(timespec="seconds") }}</span>
|
||||
</div>
|
||||
<div class="colophon-block">
|
||||
<span class="meta-label">NEXT EDITION</span>
|
||||
<span class="meta-value">{{ next_edition|upper }} · 12 H</span>
|
||||
</div>
|
||||
<div class="colophon-block">
|
||||
<span class="meta-label">PIPELINE</span>
|
||||
<span class="meta-value">REDDIT JSON + MINIFLUX → {{ model }} → JINJA2</span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,497 @@
|
||||
/* -------------------------------------------------------------------------
|
||||
news-digest — daily intel briefing.
|
||||
|
||||
Aesthetic: operations-center chrome (Australis cool-mono palette,
|
||||
JetBrains Mono UPPERCASE eyebrows, mdi-glyph anchor) wrapping
|
||||
editorial-serif news content (Fraunces). Two type families that
|
||||
wouldn't normally meet, intentionally combined: the chrome says
|
||||
"filed at 0800 from the bridge"; the headlines say "this is news,
|
||||
read it like news."
|
||||
|
||||
Type:
|
||||
Display (headlines): Fraunces — variable serif w/ optical sizes
|
||||
Body (summaries): Inter — same as Australis, optimized for screens
|
||||
Mono (chrome): JetBrains Mono — eyebrows / metadata / chips
|
||||
|
||||
Color: pure Australis Ice + Sea + Aurora. Score chips lean
|
||||
--aus-blue (info); release tags --aus-green; drama --aus-red
|
||||
(sparingly). No warm accents — Australis is cool-only by design.
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Inter:wght@400;500;600;700&family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600;9..144,700;9..144,800&display=swap');
|
||||
|
||||
:root {
|
||||
/* Australis palette — vendored subset */
|
||||
--aus-black: #222531;
|
||||
--aus-white: #a9bcc3;
|
||||
--aus-bright-white: #cce7ec;
|
||||
--aus-bright-black: #373b46;
|
||||
--aus-dark-30: #414751;
|
||||
--aus-dark-40: #565f69;
|
||||
--aus-dark-50: #6e7882;
|
||||
--aus-dark-60: #86929d;
|
||||
--aus-bright-70: #9daeb6;
|
||||
--aus-bright-80: #b3cbcf;
|
||||
--aus-blue: #6388d8;
|
||||
--aus-bright-blue: #a4c4ff;
|
||||
--aus-cyan: #00b1a8;
|
||||
--aus-bright-cyan: #42dcd1;
|
||||
--aus-green: #16b866;
|
||||
--aus-bright-green: #51e08a;
|
||||
--aus-yellow: #e1c631;
|
||||
--aus-bright-yellow:#ffe14e;
|
||||
--aus-red: #ff491a;
|
||||
--aus-magenta: #9d78ff;
|
||||
|
||||
--bg: var(--aus-black);
|
||||
--bg-elev: var(--aus-bright-black);
|
||||
--surface: #2a2e3a;
|
||||
--surface-hi: var(--aus-dark-30);
|
||||
--rule: var(--aus-dark-30);
|
||||
--rule-bright: var(--aus-dark-40);
|
||||
--fg: var(--aus-bright-white);
|
||||
--fg-dim: var(--aus-bright-70);
|
||||
--fg-faint: var(--aus-dark-50);
|
||||
--accent: var(--aus-bright-cyan);
|
||||
--accent-dim: var(--aus-cyan);
|
||||
|
||||
/* Type families */
|
||||
--font-display: "Fraunces", "Times New Roman", Georgia, serif;
|
||||
--font-sans: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
|
||||
--font-mono: "JetBrains Mono", ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
|
||||
|
||||
/* Scale + chrome */
|
||||
--pad-x: 24px;
|
||||
--content-w: 880px;
|
||||
}
|
||||
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
[hidden] { display: none !important; }
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
background: var(--bg);
|
||||
color: var(--fg);
|
||||
font: 16px/1.55 var(--font-sans);
|
||||
font-feature-settings: "ss01" 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
a { color: inherit; text-decoration: none; }
|
||||
a:hover { color: var(--accent); }
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
masthead — full-width banner; the "I am a news edition" statement
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
.masthead {
|
||||
border-bottom: 1px solid var(--rule);
|
||||
background: var(--bg-elev);
|
||||
}
|
||||
|
||||
.masthead-inner {
|
||||
max-width: var(--content-w);
|
||||
margin: 0 auto;
|
||||
padding: 36px var(--pad-x) 24px;
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
grid-template-rows: auto auto;
|
||||
column-gap: 32px;
|
||||
row-gap: 16px;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.masthead-brand {
|
||||
grid-column: 1 / 2;
|
||||
grid-row: 1 / 2;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 10px;
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
.brand-glyph {
|
||||
font-size: 32px;
|
||||
line-height: 1;
|
||||
color: var(--accent);
|
||||
text-shadow: 0 0 12px rgba(66, 220, 209, .35);
|
||||
}
|
||||
.brand-mark {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
letter-spacing: .18em;
|
||||
color: var(--fg);
|
||||
}
|
||||
|
||||
.masthead-edition {
|
||||
grid-column: 2 / 3;
|
||||
grid-row: 1 / 2;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: flex-end;
|
||||
gap: 18px;
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
.edition-num {
|
||||
color: var(--fg-faint);
|
||||
font-size: 11px;
|
||||
letter-spacing: .14em;
|
||||
}
|
||||
.edition-stamp {
|
||||
/* THE statement piece — large mono in Australis yellow.
|
||||
"This is the morning/evening brief, filed officially." */
|
||||
font-family: var(--font-mono);
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
letter-spacing: .14em;
|
||||
color: var(--aus-yellow);
|
||||
padding: 4px 10px;
|
||||
border: 1px solid var(--aus-yellow);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.masthead-meta {
|
||||
grid-column: 1 / 3;
|
||||
grid-row: 2 / 3;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, auto);
|
||||
gap: 4px 32px;
|
||||
align-items: baseline;
|
||||
font-family: var(--font-mono);
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid var(--rule);
|
||||
}
|
||||
.meta-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 10px;
|
||||
font-size: 11px;
|
||||
letter-spacing: .08em;
|
||||
}
|
||||
.meta-label {
|
||||
color: var(--fg-faint);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: .14em;
|
||||
}
|
||||
.meta-value {
|
||||
color: var(--fg);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
/* The aurora glow rule — sanctioned Australis gradient, used once. */
|
||||
.aurora-rule {
|
||||
height: 2px;
|
||||
background: linear-gradient(90deg,
|
||||
transparent 0%,
|
||||
var(--aus-bright-blue) 25%,
|
||||
var(--aus-bright-cyan) 50%,
|
||||
var(--aus-bright-green) 75%,
|
||||
transparent 100%);
|
||||
opacity: .65;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
jump nav
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
.jumpnav {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 5;
|
||||
background: rgba(34, 37, 49, 0.92);
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
border-bottom: 1px solid var(--rule);
|
||||
}
|
||||
.jumpnav ol {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 12px var(--pad-x);
|
||||
max-width: var(--content-w);
|
||||
margin-inline: auto;
|
||||
display: flex;
|
||||
gap: 28px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
letter-spacing: .14em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.jumpnav a {
|
||||
color: var(--fg-dim);
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
}
|
||||
.jumpnav a:hover { color: var(--fg); }
|
||||
.jump-num { color: var(--fg-faint); font-size: 10px; }
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
main brief
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
.brief {
|
||||
max-width: var(--content-w);
|
||||
margin: 0 auto;
|
||||
padding: 32px var(--pad-x) 64px;
|
||||
}
|
||||
|
||||
.desk + .desk { margin-top: 64px; }
|
||||
|
||||
.desk-head {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
align-items: baseline;
|
||||
column-gap: 16px;
|
||||
padding-bottom: 14px;
|
||||
margin-bottom: 24px;
|
||||
border-bottom: 1px solid var(--rule-bright);
|
||||
}
|
||||
.desk-num {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
letter-spacing: .14em;
|
||||
color: var(--aus-yellow);
|
||||
padding-top: 4px; /* aligns visually with the serif baseline */
|
||||
}
|
||||
.desk-title {
|
||||
font-family: var(--font-display);
|
||||
font-size: 38px;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.015em;
|
||||
margin: 0;
|
||||
color: var(--fg);
|
||||
font-variation-settings: "opsz" 144;
|
||||
}
|
||||
.desk-sub {
|
||||
/* Sub-line hugs the title baseline */
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
letter-spacing: .08em;
|
||||
color: var(--fg-faint);
|
||||
text-transform: uppercase;
|
||||
grid-column: 2 / 3;
|
||||
align-self: end;
|
||||
padding-bottom: 6px;
|
||||
padding-left: 12px;
|
||||
}
|
||||
.desk-count {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
letter-spacing: .08em;
|
||||
color: var(--fg-dim);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
per-source block
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
.source + .source { margin-top: 36px; }
|
||||
|
||||
.source-head {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 14px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.source-name {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: .12em;
|
||||
text-transform: uppercase;
|
||||
color: var(--accent);
|
||||
border-bottom: 1px dashed var(--accent-dim);
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
.source-name:hover { color: var(--aus-bright-cyan); }
|
||||
.source-count {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 10px;
|
||||
letter-spacing: .14em;
|
||||
color: var(--fg-faint);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
item — the news card
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
.items {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: grid;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: grid;
|
||||
grid-template-columns: 96px 1fr;
|
||||
column-gap: 24px;
|
||||
padding-bottom: 24px;
|
||||
border-bottom: 1px solid var(--rule);
|
||||
}
|
||||
.item:last-child {
|
||||
border-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.item-rail {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 6px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.chip {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 10.5px;
|
||||
font-weight: 600;
|
||||
letter-spacing: .06em;
|
||||
padding: 2px 8px;
|
||||
border: 1px solid currentColor;
|
||||
border-radius: 2px;
|
||||
white-space: nowrap;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.chip-score { color: var(--aus-blue); }
|
||||
.chip-comments { color: var(--fg-dim); border-color: var(--rule-bright); }
|
||||
.chip-tag {
|
||||
font-size: 9.5px;
|
||||
letter-spacing: .14em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.chip-tag-news { color: var(--aus-bright-blue); }
|
||||
.chip-tag-tutorial { color: var(--aus-bright-cyan); }
|
||||
.chip-tag-release { color: var(--aus-bright-green); }
|
||||
.chip-tag-discussion{ color: var(--fg-dim); }
|
||||
.chip-tag-question { color: var(--aus-yellow); }
|
||||
.chip-tag-showcase { color: var(--aus-magenta); }
|
||||
.chip-tag-drama { color: var(--aus-red); }
|
||||
.chip-tag-meme { color: var(--fg-faint); }
|
||||
|
||||
.item-body {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
margin: 0 0 8px;
|
||||
font-family: var(--font-display);
|
||||
font-size: 22px;
|
||||
line-height: 1.2;
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.01em;
|
||||
color: var(--fg);
|
||||
font-variation-settings: "opsz" 36;
|
||||
}
|
||||
.item-title a { color: inherit; }
|
||||
.item-title a:hover { color: var(--accent); }
|
||||
|
||||
.item-tldr {
|
||||
margin: 0 0 12px;
|
||||
font-size: 15px;
|
||||
line-height: 1.55;
|
||||
color: var(--fg-dim);
|
||||
}
|
||||
|
||||
.item-foot {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
gap: 8px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 10.5px;
|
||||
letter-spacing: .06em;
|
||||
color: var(--fg-faint);
|
||||
}
|
||||
.item-link {
|
||||
color: var(--fg-dim);
|
||||
border-bottom: 1px dotted var(--fg-faint);
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
.item-link:hover { color: var(--accent); border-color: var(--accent-dim); }
|
||||
.item-meta { font-variant-numeric: tabular-nums; }
|
||||
.sep { color: var(--rule-bright); }
|
||||
|
||||
/* Visual de-emphasize purely meme/skip items if any slip through. */
|
||||
.item[data-tag="meme"] { opacity: .58; }
|
||||
.item[data-tag="other"] { opacity: .85; }
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
empty state + colophon
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
.desk.empty {
|
||||
text-align: center;
|
||||
padding: 72px 24px;
|
||||
border: 1px dashed var(--rule);
|
||||
border-radius: 6px;
|
||||
}
|
||||
.empty-msg {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 13px;
|
||||
color: var(--fg-faint);
|
||||
line-height: 1.6;
|
||||
}
|
||||
.empty-msg code {
|
||||
color: var(--fg-dim);
|
||||
font-family: inherit;
|
||||
background: var(--surface);
|
||||
padding: 2px 6px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.colophon {
|
||||
border-top: 1px solid var(--rule);
|
||||
background: var(--bg-elev);
|
||||
padding: 24px var(--pad-x);
|
||||
margin-top: 64px;
|
||||
}
|
||||
.colophon-inner {
|
||||
max-width: var(--content-w);
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 20px;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 10.5px;
|
||||
letter-spacing: .08em;
|
||||
}
|
||||
.colophon-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
.colophon-block .meta-label { color: var(--fg-faint); font-size: 10px; }
|
||||
.colophon-block .meta-value { color: var(--fg-dim); font-size: 11px; }
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
responsive
|
||||
------------------------------------------------------------------------- */
|
||||
|
||||
@media (max-width: 720px) {
|
||||
:root { --pad-x: 16px; }
|
||||
.masthead-inner {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto auto auto;
|
||||
}
|
||||
.masthead-brand,
|
||||
.masthead-edition,
|
||||
.masthead-meta { grid-column: 1 / 2; }
|
||||
.masthead-edition { justify-content: flex-start; }
|
||||
.edition-stamp { font-size: 18px; }
|
||||
.masthead-meta { grid-template-columns: 1fr; gap: 6px; }
|
||||
.desk-title { font-size: 28px; }
|
||||
.desk-head { grid-template-columns: auto 1fr; row-gap: 6px; }
|
||||
.desk-sub { grid-column: 1 / 3; padding-left: 0; }
|
||||
.desk-count { display: none; }
|
||||
.item { grid-template-columns: 64px 1fr; column-gap: 14px; }
|
||||
.item-rail { padding-top: 4px; }
|
||||
.chip { font-size: 9.5px; padding: 1px 6px; }
|
||||
.item-title { font-size: 18px; }
|
||||
.item-tldr { font-size: 14px; }
|
||||
.colophon-inner { grid-template-columns: 1fr; }
|
||||
}
|
||||
Reference in New Issue
Block a user