Lock branch-meta-grid to a fixed 3-column layout
Intent: Replace the auto-fit grid with an explicit 3-column grid so the metadata blocks have consistent widths regardless of content, and cap the overall grid width at 1360px.
Affected files: crates/pika-news/templates/detail.html
Evidence
@@ -82,8 +82,9 @@
- grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
+ grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 0.85rem;
+ max-width: 1360px;
The .branch-meta-grid previously used repeat(auto-fit, minmax(180px, 1fr)), which allowed the browser to choose how many columns to render based on available space. This caused inconsistent layouts depending on viewport width.
The new rule repeat(3, minmax(0, 1fr)) forces exactly three equal-width columns. minmax(0, 1fr) ensures each column can shrink to zero rather than overflowing, which is important when content is long. A max-width: 1360px cap prevents the grid from stretching uncomfortably wide on very large displays.
Remove margin-top from summary-stack
Intent: Eliminate the top margin on the summary-stack container so that spacing is controlled by the parent grid gap instead of a hard-coded margin.
Affected files: crates/pika-news/templates/detail.html
Evidence
@@ -129,7 +130,7 @@
- .summary-stack { display: flex; flex-direction: column; gap: 1rem; margin-top: 1rem; }
+ .summary-stack { display: flex; flex-direction: column; gap: 1rem; }
The margin-top: 1rem on .summary-stack was previously needed when the CI summary card sat directly below the metadata section. Since the CI summary is now relocated inside the review-rail grid child, the vertical spacing is handled by the rail's own gap property, making the margin redundant.
Convert review-main into a two-column grid
Intent: Split the main review area into a fixed-width left rail (320–420px) and a fluid right tutorial column, with dedicated utility classes for each.
Affected files: crates/pika-news/templates/detail.html
Evidence
@@ -196,7 +197,24 @@
- .review-main { min-width: 0; }
+ .review-main {
+ min-width: 0;
+ display: grid;
+ grid-template-columns: minmax(320px, 420px) minmax(0, 1fr);
+ gap: 1.25rem;
+ }
+ .review-rail,
+ .tutorial-column {
+ min-width: 0;
+ }
+ .review-rail {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+ }
+ .tutorial-column .panel + .panel {
+ margin-top: 1rem;
+ }
This is the core layout change. .review-main becomes a CSS grid with two columns:
- Left column (
minmax(320px, 420px)): constrained width that holds the review rail.
- Right column (
minmax(0, 1fr)): takes all remaining space for the tutorial content.
Two new structural classes are introduced:
.review-rail — a flex column with gap: 1rem that stacks the CI summary, executive summary, and media links vertically.
.tutorial-column — uses an adjacent-sibling rule (.panel + .panel) to add margin-top: 1rem between consecutive panels, since it is not a flex container itself.
Both children get min-width: 0 to prevent grid blowout from long content like diff lines or pre-formatted code.
Add responsive breakpoints for tablet and mobile
Intent: Collapse the two-column layouts to single columns at appropriate viewport widths so the page remains usable on smaller screens.
Affected files: crates/pika-news/templates/detail.html
Evidence
@@ -248,8 +266,13 @@
@media (max-width: 1024px) {
+ .branch-meta-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.review-layout { grid-template-columns: 1fr; }
.file-list-sidebar { position: static; }
+ .review-main { grid-template-columns: 1fr; }
+ }
+ @media (max-width: 720px) {
+ .branch-meta-grid { grid-template-columns: 1fr; }
}
Two responsive tiers are defined:
≤ 1024px (tablet):
.branch-meta-grid drops from 3 columns to 2.
.review-main collapses to a single column, stacking the rail above the tutorial.
- The existing file-list sidebar collapse is preserved.
≤ 720px (mobile):
.branch-meta-grid drops to a single column.
This ensures the 3→2→1 column progression feels natural across breakpoints.
Relocate CI summary into the review-rail
Intent: Move the CI summary block from its previous position (between the metadata section and the review layout) into the left rail so it sits alongside the executive summary and media links.
Affected files: crates/pika-news/templates/detail.html
Evidence
@@ -309,8 +332,6 @@
- <div id="branch-ci-summary" class="summary-stack">{{ branch_ci_summary_html|safe }}</div>
-
@@ -321,22 +342,47 @@
+ <div class="review-rail">
+ <div id="branch-ci-summary" class="summary-stack">{{ branch_ci_summary_html|safe }}</div>
The #branch-ci-summary div was previously rendered between the metadata grid and the review layout, spanning the full page width. It is now the first child of .review-rail, placing it in the constrained left column. This groups all high-level branch status information (CI results, summary, media) in one scannable column.
Reorganize template blocks into rail and tutorial columns
Intent: Redistribute the executive summary, media links, error message, and tutorial steps into their respective column containers so the HTML structure matches the new CSS grid.
Affected files: crates/pika-news/templates/detail.html
Evidence
@@ -321,22 +342,47 @@
+ <div class="review-rail">
{% match executive_html %}
{% when Some with (summary_html) %}
<section class="panel">
<h2>Summary</h2>
<div>{{ summary_html|safe }}</div>
</section>
+ {% when None %}
+ <section class="panel">
+ <h2>Summary</h2>
+ {% if tutorial_status == "failed" %}
+ <p>This branch tutorial is unavailable because generation for this branch head failed.</p>
+ {% else %}
+ <p>Summary is not ready yet. Refresh shortly.</p>
+ {% endif %}
+ </section>
+ {% endmatch %}
+ {% if media_links.len() > 0 %}
+ <section class="panel">
+ <h2>Media Links</h2>
+ <ul>
+ {% for link in media_links %}
+ <li><a href="{{ link.href }}">{{ link.label }}</a></li>
+ {% endfor %}
+ </ul>
+ </section>
+ {% endif %}
+ </div>
+
+ <div class="tutorial-column">
@@ -364,28 +410,6 @@
- {% when None %}
- <section class="panel">
- <h2>Summary</h2>
- ...
- </section>
- {% endmatch %}
- {% if media_links.len() > 0 %}
- ...
- {% endif %}
The template previously interleaved the summary match arms with the tutorial steps inside a single summary-stack div. This change fully separates concerns:
review-rail (left column) now contains:
- CI summary (
branch_ci_summary_html)
- Executive summary panel (both
Some and None arms of the executive_html match)
- Media links panel (conditionally rendered)
tutorial-column (right column) now contains:
- Error message panel (conditionally rendered)
- Tutorial steps panel
The None arm of executive_html — which shows either a failure notice or a "not ready yet" message — was previously located after the tutorial steps at the bottom of the template. It is now placed inline inside the rail's match block, making the summary panel always visible in the left column regardless of generation state.