Web dashboard v2 step 4: table-of-contents sidebar

Signed-in issue pages (issue, article, world, behind) get a chapter list
that marks where the reader is. One `issue_toc` helper builds it for all
four handlers: the picks in issue order numbered across sections, then
World Briefing, Behind the paper and a colophon anchor, with
position/total over the navigable chapters.

At `lg` and up it is a sticky left column with its own sticky header
(issue number, "Chapter N of M", a 2px progress bar); below `lg` the same
`<nav>` collapses behind a sticky hamburger bar and drops down as a
panel that closes on link tap, Escape and outside tap. Without JS the
panel is simply visible; `theme.js` marks the document scripted before
paint so it never flashes open. Article pages advance the progress bar
with scroll position through `requestAnimationFrame`, and the bar is a
`<progress>` element because a percentage width would need an inline
style the CSP forbids.

Also fixes the phone "ears" row from the step 2 review: the row no
longer wraps at 390px, the dateline has a short form below `sm:`, and
the toggle and account link stay on one line.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NHyYupFdBiR4VfoUM7NjSM
This commit is contained in:
2026-09-03 21:50:05 +00:00
co-authored by Claude Fable 5.1
parent 29c66da865
commit ca910d99e5
15 changed files with 610 additions and 19 deletions
+20
View File
@@ -0,0 +1,20 @@
<div class="sticky top-0 z-30 lg:static lg:z-auto">
<div class="relative flex min-h-12 items-center gap-3 border-b border-rule bg-paper px-4 sm:px-6 lg:hidden">
<button class="-ml-2 flex h-10 w-10 shrink-0 items-center justify-center border-0 bg-transparent p-0 text-ink hover:text-accent" type="button" data-toc-toggle aria-controls="toc" aria-expanded="false" aria-label="Contents">
<svg aria-hidden="true" viewBox="0 0 24 24" class="h-5 w-5 fill-none stroke-current" stroke-width="1.75"><path d="M4 7h16M4 12h16M4 17h16"/></svg>
</button>
<span class="min-w-0 flex-1 truncate font-sans text-sm leading-tight text-ink">{{ toc.current_label() }}</span>
{% if toc.position > 0 %}<span class="shrink-0 font-sans text-xs tabular-nums text-muted">{{ toc.position }} / {{ toc.total }}</span>{% endif %}
<progress class="toc-progress absolute inset-x-0 -bottom-px" data-toc-progress value="{{ toc.position }}" max="{{ toc.total }}" aria-hidden="true"></progress>
</div>
<nav id="toc" data-toc-panel class="absolute inset-x-0 top-full z-30 max-h-[72vh] overflow-y-auto border-b border-rule bg-paper px-4 pb-7 pt-2 shadow-[0_18px_32px_-26px_rgb(0_0_0_/_0.6)] sm:px-6 lg:sticky lg:inset-x-auto lg:top-6 lg:z-auto lg:mt-12 lg:max-h-[calc(100vh-3rem)] lg:border-0 lg:px-0 lg:pb-10 lg:pt-0 lg:shadow-none" aria-label="Contents">
<div class="hidden lg:sticky lg:top-0 lg:z-10 lg:block lg:bg-paper lg:pb-3">
<a class="block font-sans text-[0.68rem] font-semibold uppercase tracking-[0.12em] text-muted no-underline hover:text-ink" href="{{ toc.issue_href }}">No. {{ toc.issue_number }} <span class="text-rule" aria-hidden="true">·</span> {{ toc.short_date }}</a>
<p class="mt-2 font-sans text-[0.72rem] text-ink-2">{% if toc.position > 0 %}Chapter {{ toc.position }} of {{ toc.total }}{% else %}Front page{% endif %}</p>
<progress class="toc-progress mt-2.5" data-toc-progress value="{{ toc.position }}" max="{{ toc.total }}" aria-hidden="true"></progress>
</div>
<ul class="m-0 mt-1 list-none p-0 lg:mt-4">
{% for item in toc.items %}{% if item.is_section() %}<li class="mt-5 border-t border-rule pt-2 font-sans text-[0.66rem] font-semibold uppercase tracking-[0.12em] text-muted">{{ item.label }}</li>{% else %}<li{% if item.divider %} class="mt-4 border-t border-rule pt-3"{% endif %}><a class="flex items-baseline gap-2 border-l-2 py-2.5 pl-3 no-underline transition-colors duration-150 lg:py-1.5 {% if item.current %}border-accent font-semibold text-ink{% else %}border-transparent text-ink-2 hover:border-rule-strong hover:text-accent{% endif %}" href="{{ item.href }}"{% if item.current %} aria-current="page"{% endif %}>{% match item.number %}{% when Some with (number) %}<span class="w-4 shrink-0 font-sans text-[0.66rem] tabular-nums text-muted">{{ number }}</span>{% when None %}<span class="w-4 shrink-0" aria-hidden="true"></span>{% endmatch %}<span class="min-w-0 flex-1 font-serif text-[0.95rem] leading-snug">{{ item.label }}</span>{% match item.minutes %}{% when Some with (minutes) %}<span class="shrink-0 font-sans text-[0.66rem] tabular-nums text-muted">{{ minutes }} min</span>{% when None %}{% endmatch %}</a></li>{% endif %}{% endfor %}
</ul>
</nav>
</div>
+4 -2
View File
@@ -1,6 +1,8 @@
{% extends "layout.html" %}{% block ears %}<span>From this issue</span>{% endblock %}{% block content %}<article class="mx-auto mt-10 max-w-[68ch] px-4 sm:mt-14 sm:px-6">
{% extends "layout.html" %}{% block ears %}<span class="sm:hidden">{{ toc.short_date }}</span><span class="hidden sm:inline">{{ toc.display_date }} · No. {{ toc.issue_number }}</span>{% endblock %}{% block content %}<div class="mx-auto max-w-7xl lg:grid lg:grid-cols-[16rem_minmax(0,1fr)] lg:gap-x-10 lg:px-6 xl:grid-cols-[18rem_minmax(0,1fr)] xl:gap-x-14">{% include "_toc.html" %}
<article class="mx-auto mt-10 w-full max-w-[68ch] px-4 sm:px-6 lg:mt-12 lg:px-0" data-toc-scroll>
<header><p class="font-sans text-[0.72rem] uppercase tracking-[0.12em] text-muted">Article</p><h1 class="mt-3 text-4xl font-semibold leading-[1.1] tracking-[-0.01em] sm:text-5xl"><a class="text-ink no-underline hover:text-accent" href="{{ source_url }}">{{ title }}</a></h1>{% match byline %}{% when Some with (byline) %}<p class="mt-5 font-sans text-sm font-medium text-ink-2">{{ byline }}</p>{% when None %}{% endmatch %}<p class="mt-1 font-sans text-sm text-muted">{{ meta_line }}</p>{% match why %}{% when Some with (why) %}<p class="mt-6 border-l-2 border-accent pl-3 italic text-ink-2">Why it's here: {{ why }}</p>{% when None %}{% endmatch %}{% match social_line %}{% when Some with (social) %}<p class="mt-4 font-sans text-sm text-muted">{{ social }}</p>{% when None %}{% endmatch %}{% match summary %}{% when Some with (summary) %}<p class="mt-7 text-xl italic leading-relaxed text-ink-2">{{ summary }}</p>{% when None %}{% endmatch %}{% if excerpt_only %}<p class="notice mt-6">Excerpt only — continue reading at the original site.</p>{% endif %}</header>
<div class="prose-body mt-10 border-t border-rule pt-8">{{ body_html|safe }}</div>
{% match discussion_html %}{% when Some with (discussion) %}<section class="discussion prose-body mt-12 border-t border-rule pt-6 [&_.comment-meta]:font-sans [&_.comment-meta]:text-sm [&_.comment-meta]:text-muted [&_blockquote.reply]:ml-6"><h2 class="mb-6 border-0 pt-0 text-2xl">Discussion</h2>{{ discussion|safe }}</section>{% when None %}{% endmatch %}
<footer class="mt-12 border-t border-rule pt-6">{% match rating %}{% when Some with (widget) %}{% include "_rating_widget.html" %}{% when None %}{% endmatch %}<p class="mt-6"><a class="btn" href="{{ read_online_url }}">Read online ↗</a></p><nav class="mt-10 grid grid-cols-1 gap-3 font-sans sm:grid-cols-2" aria-label="Adjacent articles">{% match previous %}{% when Some with (previous) %}<a class="group min-h-24 border border-rule p-4 text-ink no-underline hover:border-accent" rel="prev" href="{{ previous.href }}"><span class="block text-[0.68rem] uppercase tracking-[0.12em] text-muted">Previous</span><span class="mt-2 block leading-snug group-hover:text-accent">← {{ previous.title }}</span></a>{% when None %}{% endmatch %}{% match next %}{% when Some with (next) %}<a class="group min-h-24 border border-rule p-4 text-right text-ink no-underline hover:border-accent sm:col-start-2" rel="next" href="{{ next.href }}"><span class="block text-[0.68rem] uppercase tracking-[0.12em] text-muted">Next</span><span class="mt-2 block leading-snug group-hover:text-accent">{{ next.title }} →</span></a>{% when None %}{% endmatch %}</nav><p class="mt-8 font-sans text-sm"><a href="{{ issue_href }}">← Back to this issue</a></p></footer>
</article>{% endblock %}
</article>
</div>{% endblock %}
+3 -1
View File
@@ -1 +1,3 @@
{% extends "layout.html" %}{% block ears %}<span>Edition notes</span>{% endblock %}{% block content %}<article class="mx-auto mt-10 max-w-[68ch] px-4 sm:mt-14 sm:px-6"><header class="mb-9"><p class="font-sans text-[0.72rem] uppercase tracking-[0.12em] text-muted">Edition notes</p><h1 class="mt-2 text-4xl font-semibold leading-[1.1] tracking-[-0.01em] sm:text-5xl">Behind the paper</h1></header><section class="border-y border-rule py-6"><p>{{ summary_line }}</p><p class="mt-3">{{ admitted_line }}</p><p class="mt-3">{{ learned_line }}</p></section><section class="mt-10"><h2 class="border-t border-rule pt-2 font-sans text-[0.72rem] font-semibold uppercase tracking-[0.12em] text-muted">Near misses</h2><p class="mt-5 italic text-ink-2">Highest utility not selected.</p>{% if near_misses.is_empty() %}<p class="mt-4 text-muted">None recorded for this run.</p>{% else %}<ol class="mt-5 list-decimal space-y-3 pl-6">{% for near_miss in near_misses %}<li>{% if page.is_admin() %}<a class="text-ink decoration-rule hover:decoration-accent" href="/dashboard/articles/{{ near_miss.article_id }}">{{ near_miss.line }}</a>{% else %}{{ near_miss.line }}{% endif %}</li>{% endfor %}</ol>{% endif %}</section><p class="mt-10 border-l-2 border-rule pl-4 italic text-ink-2">{{ models_line }}</p><p class="mt-10 border-t border-rule pt-5 font-sans text-sm"><a href="{{ issue_href }}">← Back to this issue</a></p></article>{% endblock %}
{% extends "layout.html" %}{% block ears %}<span class="sm:hidden">{{ toc.short_date }}</span><span class="hidden sm:inline">{{ toc.display_date }} · No. {{ toc.issue_number }}</span>{% endblock %}{% block content %}<div class="mx-auto max-w-7xl lg:grid lg:grid-cols-[16rem_minmax(0,1fr)] lg:gap-x-10 lg:px-6 xl:grid-cols-[18rem_minmax(0,1fr)] xl:gap-x-14">{% include "_toc.html" %}
<article class="mx-auto mt-10 w-full max-w-[68ch] px-4 sm:px-6 lg:mt-12 lg:px-0"><header class="mb-9"><p class="font-sans text-[0.72rem] uppercase tracking-[0.12em] text-muted">Edition notes</p><h1 class="mt-2 text-4xl font-semibold leading-[1.1] tracking-[-0.01em] sm:text-5xl">Behind the paper</h1></header><section class="border-y border-rule py-6"><p>{{ summary_line }}</p><p class="mt-3">{{ admitted_line }}</p><p class="mt-3">{{ learned_line }}</p></section><section class="mt-10"><h2 class="border-t border-rule pt-2 font-sans text-[0.72rem] font-semibold uppercase tracking-[0.12em] text-muted">Near misses</h2><p class="mt-5 italic text-ink-2">Highest utility not selected.</p>{% if near_misses.is_empty() %}<p class="mt-4 text-muted">None recorded for this run.</p>{% else %}<ol class="mt-5 list-decimal space-y-3 pl-6">{% for near_miss in near_misses %}<li>{% if page.is_admin() %}<a class="text-ink decoration-rule hover:decoration-accent" href="/dashboard/articles/{{ near_miss.article_id }}">{{ near_miss.line }}</a>{% else %}{{ near_miss.line }}{% endif %}</li>{% endfor %}</ol>{% endif %}</section><p class="mt-10 border-l-2 border-rule pl-4 italic text-ink-2">{{ models_line }}</p><p class="mt-10 border-t border-rule pt-5 font-sans text-sm"><a href="{{ issue_href }}">← Back to this issue</a></p></article>
</div>{% endblock %}
+6 -4
View File
@@ -1,5 +1,6 @@
{% extends "layout.html" %}{% block ears %}<span>{{ display_date }} <span class="hidden sm:inline">· No. {{ issue_number }}</span></span>{% endblock %}{% block content %}
<article class="mx-auto mt-8 max-w-[68ch] px-4 sm:mt-12 sm:px-6">
{% extends "layout.html" %}{% block ears %}<span class="sm:hidden">{{ toc.short_date }}</span><span class="hidden sm:inline">{{ toc.display_date }} · No. {{ toc.issue_number }}</span>{% endblock %}{% block content %}
<div class="mx-auto max-w-7xl lg:grid lg:grid-cols-[16rem_minmax(0,1fr)] lg:gap-x-10 lg:px-6 xl:grid-cols-[18rem_minmax(0,1fr)] xl:gap-x-14">{% include "_toc.html" %}
<article class="mx-auto mt-10 w-full max-w-[68ch] px-4 sm:px-6 lg:mt-12 lg:px-0">
<header class="mb-8 text-center"><p class="font-sans text-[0.72rem] uppercase tracking-[0.12em] text-muted">{{ display_date }} · No. {{ issue_number }}</p><p class="mt-2 font-sans text-sm text-muted">{{ stats_line }}</p></header>
<section aria-labelledby="brief-heading"><h1 id="brief-heading" class="border-t border-rule pt-2 font-sans text-[0.72rem] font-semibold uppercase tracking-[0.12em] text-muted">The Brief</h1><div class="editorial prose-body mt-5 [&>p:first-child]:first-letter:float-left [&>p:first-child]:first-letter:mr-2 [&>p:first-child]:first-letter:mt-1 [&>p:first-child]:first-letter:font-serif [&>p:first-child]:first-letter:text-[4.6rem] [&>p:first-child]:first-letter:font-semibold [&>p:first-child]:first-letter:leading-[0.72]">{{ front_page_html|safe }}</div></section>
{% if !downloads.is_empty() %}<div class="my-8 flex flex-wrap gap-2 border-y border-rule py-4">{% for download in downloads %}<a class="btn" href="{{ download.href }}">Download {{ download.label }} <span class="ml-1 text-muted">{{ download.size }}</span></a>{% endfor %}</div>{% endif %}
@@ -7,5 +8,6 @@
{% for section in sections %}<section class="mt-10"><h3 class="border-t border-rule pt-2 font-sans text-[0.72rem] font-semibold uppercase tracking-[0.12em] text-muted">{{ section.name }}</h3><ul class="m-0 list-none p-0">{% for entry in section.entries %}<li class="border-b border-rule py-6"><h4 class="font-serif font-semibold leading-[1.1] tracking-[-0.01em] {% if entry.is_lead %}text-3xl{% else %}text-2xl{% endif %}"><a class="text-ink no-underline hover:text-accent" href="{{ entry.href }}">{{ entry.title }}</a></h4><p class="mt-2 font-sans text-sm text-muted">{{ entry.source }} · {{ entry.reading_minutes }} min read</p>{% if !entry.summary.is_empty() %}<p class="mt-4">{{ entry.summary }}</p>{% endif %}{% match entry.why %}{% when Some with (why) %}<p class="mt-4 border-l-2 border-accent pl-3 italic text-ink-2">Why it's here: {{ why }}</p>{% when None %}{% endmatch %}{% match entry.rating %}{% when Some with (widget) %}{% include "_rating_widget.html" %}{% when None %}{% endmatch %}</li>{% endfor %}</ul></section>{% endfor %}
</section>
{% if has_world || has_behind %}<nav class="my-12 flex flex-wrap items-center justify-center gap-x-3 gap-y-1 border-y border-rule py-4 text-center font-sans text-sm uppercase tracking-[0.08em]" aria-label="Issue chapters">{% if has_world %}<a class="text-ink no-underline hover:text-accent" href="/issues/{{ date }}/world">World Briefing</a>{% endif %}{% if has_world && has_behind %}<span class="text-muted" aria-hidden="true">·</span>{% endif %}{% if has_behind %}<a class="text-ink no-underline hover:text-accent" href="/issues/{{ date }}/behind">Behind the paper</a>{% endif %}</nav>{% endif %}
<footer class="mt-12 border-t border-rule pt-2 font-sans text-sm leading-relaxed"><h2 class="text-[0.72rem] font-semibold uppercase tracking-[0.12em] text-muted">Colophon</h2><p class="my-4 text-ink-2"><em>The Daily EPUB</em> is assembled every morning from a personal feed reader.</p><dl class="kv border-y border-rule py-4 text-xs sm:text-sm"><dt>Generated</dt><dd>{{ colophon.generated_at }}</dd><dt>Bulk model</dt><dd>{{ colophon.bulk_model }}</dd><dt>Editor model</dt><dd>{{ colophon.editor_model }}</dd><dt>Summaries model</dt><dd>{{ colophon.summaries_model }}</dd><dt>Entries considered</dt><dd>{% match colophon.entries_fetched %}{% when Some with (entries) %}{{ entries }}{% match colophon.feeds_seen %}{% when Some with (feeds) %} from {{ feeds }} feeds{% when None %}{% endmatch %}{% when None %}n/a{% endmatch %}</dd><dt>Candidates scored</dt><dd>{% match colophon.candidates %}{% when Some with (candidates) %}{{ candidates }}{% when None %}n/a{% endmatch %}</dd><dt>Articles selected</dt><dd>{{ colophon.article_count }} across {{ colophon.section_count }} sections</dd><dt>Words</dt><dd>{{ colophon.total_words }} · ~{{ colophon.reading_minutes }} min read</dd>{% for cost in colophon.provider_costs %}<dt>{{ cost.provider }} cost</dt><dd>{{ cost.cost }}</dd>{% endfor %}<dt>Total token cost</dt><dd>{% match colophon.cost_usd %}{% when Some with (cost) %}{{ cost }}{% when None %}n/a{% endmatch %}</dd><dt>Generator</dt><dd>{{ colophon.generator_version }}</dd></dl></footer>
</article>{% endblock %}
<footer id="colophon" class="mt-12 scroll-mt-6 border-t border-rule pt-2 font-sans text-sm leading-relaxed"><h2 class="text-[0.72rem] font-semibold uppercase tracking-[0.12em] text-muted">Colophon</h2><p class="my-4 text-ink-2"><em>The Daily EPUB</em> is assembled every morning from a personal feed reader.</p><dl class="kv border-y border-rule py-4 text-xs sm:text-sm"><dt>Generated</dt><dd>{{ colophon.generated_at }}</dd><dt>Bulk model</dt><dd>{{ colophon.bulk_model }}</dd><dt>Editor model</dt><dd>{{ colophon.editor_model }}</dd><dt>Summaries model</dt><dd>{{ colophon.summaries_model }}</dd><dt>Entries considered</dt><dd>{% match colophon.entries_fetched %}{% when Some with (entries) %}{{ entries }}{% match colophon.feeds_seen %}{% when Some with (feeds) %} from {{ feeds }} feeds{% when None %}{% endmatch %}{% when None %}n/a{% endmatch %}</dd><dt>Candidates scored</dt><dd>{% match colophon.candidates %}{% when Some with (candidates) %}{{ candidates }}{% when None %}n/a{% endmatch %}</dd><dt>Articles selected</dt><dd>{{ colophon.article_count }} across {{ colophon.section_count }} sections</dd><dt>Words</dt><dd>{{ colophon.total_words }} · ~{{ colophon.reading_minutes }} min read</dd>{% for cost in colophon.provider_costs %}<dt>{{ cost.provider }} cost</dt><dd>{{ cost.cost }}</dd>{% endfor %}<dt>Total token cost</dt><dd>{% match colophon.cost_usd %}{% when Some with (cost) %}{{ cost }}{% when None %}n/a{% endmatch %}</dd><dt>Generator</dt><dd>{{ colophon.generator_version }}</dd></dl></footer>
</article>
</div>{% endblock %}
+1 -1
View File
@@ -1,4 +1,4 @@
{% extends "layout.html" %}{% block ears %}{% if empty %}<span>Morning edition</span>{% else %}<span>{{ issue.display_date }} <span class="hidden sm:inline">· No. {{ issue.issue_number }}</span></span>{% endif %}{% endblock %}{% block content %}
{% extends "layout.html" %}{% block ears %}{% if empty %}<span>Morning edition</span>{% else %}<span class="sm:hidden">{{ issue.short_date }}</span><span class="hidden sm:inline">{{ issue.display_date }} · No. {{ issue.issue_number }}</span>{% endif %}{% endblock %}{% block content %}
<article class="mx-auto mt-8 max-w-[68ch] px-4 sm:mt-12 sm:px-6">
{% if empty %}<div class="py-16 text-center"><p class="font-sans text-[0.72rem] uppercase tracking-[0.12em] text-muted">Morning edition</p><h1 class="mt-3 text-4xl font-semibold leading-[1.1] tracking-[-0.01em]">No issue yet</h1><p class="mt-4 text-ink-2">The first issue has not been published.</p></div>{% else %}
<header class="mb-10 text-center"><p class="font-sans text-[0.72rem] uppercase tracking-[0.12em] text-muted">{{ issue.display_date }} · No. {{ issue.issue_number }}</p><p class="mt-2 font-sans text-sm text-muted">{{ issue.stats_line }}</p><p class="mx-auto mt-5 max-w-[58ch] text-lg italic leading-relaxed text-ink-2">A personal morning paper, assembled daily; the selection is the reader's, the words are the authors'.</p></header>
+5 -5
View File
@@ -13,16 +13,16 @@
<body>
<a class="fixed left-3 top-3 z-50 -translate-y-20 bg-ink px-3 py-2 font-sans text-sm text-paper no-underline focus:translate-y-0" href="#content">Skip to content</a>
<header class="mx-auto max-w-7xl px-4 pt-4 sm:px-6 sm:pt-6">
<div class="mb-2 flex min-h-8 items-center justify-between gap-4 border-b border-rule pb-2 font-sans text-[0.72rem] uppercase tracking-[0.12em] text-muted">
<div>{% block ears %}<span>Morning edition</span>{% endblock %}</div>
<div class="flex items-center gap-3 normal-case tracking-normal">
<button class="flex min-h-10 items-center gap-1.5 border-0 bg-transparent px-1.5 py-1 text-xs text-muted hover:text-ink" type="button" data-theme-toggle aria-label="Theme: system">
<div class="mb-2 flex min-h-8 flex-nowrap items-center justify-between gap-2 border-b border-rule pb-2 font-sans text-[0.72rem] uppercase tracking-[0.12em] text-muted sm:gap-4">
<div class="min-w-0 truncate whitespace-nowrap">{% block ears %}<span>Morning edition</span>{% endblock %}</div>
<div class="flex shrink-0 items-center gap-2 whitespace-nowrap normal-case tracking-normal sm:gap-3">
<button class="flex min-h-10 shrink-0 items-center gap-1.5 whitespace-nowrap border-0 bg-transparent px-1.5 py-1 text-xs text-muted hover:text-ink" type="button" data-theme-toggle aria-label="Theme: system">
<svg data-theme-icon="system" aria-hidden="true" viewBox="0 0 24 24" class="h-4 w-4 fill-none stroke-current" stroke-width="1.75"><path d="M4 5.5h16v11H4zM9 20h6M12 16.5V20"/></svg>
<svg data-theme-icon="light" aria-hidden="true" viewBox="0 0 24 24" class="h-4 w-4 fill-none stroke-current" stroke-width="1.75" hidden><circle cx="12" cy="12" r="3.5"/><path d="M12 2v2.2M12 19.8V22M4.93 4.93l1.56 1.56M17.51 17.51l1.56 1.56M2 12h2.2M19.8 12H22M4.93 19.07l1.56-1.56M17.51 6.49l1.56-1.56"/></svg>
<svg data-theme-icon="dark" aria-hidden="true" viewBox="0 0 24 24" class="h-4 w-4 fill-none stroke-current" stroke-width="1.75" hidden><path d="M20 15.1A8.5 8.5 0 0 1 8.9 4a8.5 8.5 0 1 0 11.1 11.1Z"/></svg>
<span data-theme-label>System</span>
</button>
{% match page.viewer %}{% when Some with (viewer) %}<a class="text-ink no-underline hover:text-accent" href="/account">{{ viewer.username }}</a>{% when None %}<a class="text-ink no-underline hover:text-accent" href="/login">Sign in</a>{% endmatch %}
{% match page.viewer %}{% when Some with (viewer) %}<a class="max-w-32 shrink-0 truncate whitespace-nowrap text-ink no-underline hover:text-accent" href="/account">{{ viewer.username }}</a>{% when None %}<a class="shrink-0 whitespace-nowrap text-ink no-underline hover:text-accent" href="/login">Sign in</a>{% endmatch %}
</div>
</div>
<div class="border-b-[3px] border-double border-ink py-3 text-center sm:py-4"><a class="font-serif text-3xl font-semibold leading-none tracking-[-0.02em] text-ink no-underline hover:text-ink sm:text-5xl" href="/">The Daily EPUB</a></div>
+3 -1
View File
@@ -1 +1,3 @@
{% extends "layout.html" %}{% block ears %}{% match display_date %}{% when Some with (date) %}<span>{{ date }}</span>{% when None %}<span>World Briefing</span>{% endmatch %}{% endblock %}{% block content %}<article class="mx-auto mt-10 max-w-[68ch] px-4 sm:mt-14 sm:px-6"><header class="mb-9">{% match display_date %}{% when Some with (date) %}<p class="font-sans text-[0.72rem] uppercase tracking-[0.12em] text-muted">{{ date }}</p>{% when None %}{% endmatch %}<h1 class="mt-2 text-4xl font-semibold leading-[1.1] tracking-[-0.01em] sm:text-5xl">World Briefing</h1></header><div class="prose-body border-t border-rule pt-7">{{ body_html|safe }}</div><p class="mt-10 border-t border-rule pt-5 font-sans text-sm"><a href="{{ issue_href }}">← Back to this issue</a></p></article>{% endblock %}
{% extends "layout.html" %}{% block ears %}<span class="sm:hidden">{{ toc.short_date }}</span><span class="hidden sm:inline">{{ toc.display_date }} · No. {{ toc.issue_number }}</span>{% endblock %}{% block content %}<div class="mx-auto max-w-7xl lg:grid lg:grid-cols-[16rem_minmax(0,1fr)] lg:gap-x-10 lg:px-6 xl:grid-cols-[18rem_minmax(0,1fr)] xl:gap-x-14">{% include "_toc.html" %}
<article class="mx-auto mt-10 w-full max-w-[68ch] px-4 sm:px-6 lg:mt-12 lg:px-0"><header class="mb-9">{% match display_date %}{% when Some with (date) %}<p class="font-sans text-[0.72rem] uppercase tracking-[0.12em] text-muted">{{ date }}</p>{% when None %}{% endmatch %}<h1 class="mt-2 text-4xl font-semibold leading-[1.1] tracking-[-0.01em] sm:text-5xl">World Briefing</h1></header><div class="prose-body border-t border-rule pt-7">{{ body_html|safe }}</div><p class="mt-10 border-t border-rule pt-5 font-sans text-sm"><a href="{{ issue_href }}">← Back to this issue</a></p></article>
</div>{% endblock %}