From da430c65f7f077defb4a762f889ec81238571853 Mon Sep 17 00:00:00 2001
From: Larison Carvalho
Date: Wed, 2 Sep 2026 10:43:28 +0200
Subject: [PATCH 1/4] fix: clear Infima's default table styling from the
at-scale comparison
The comparison table is ruled horizontally only and its cells start at the
measure with no left padding, but Infima's defaults were still supplying a
1px border on all four sides of every cell plus zebra striping. The result
was a bordered grid the design never asked for, with the text jammed against
the vertical rules.
Reset the borders, row backgrounds and display so border-collapse applies.
---
documentation/src/pages/at-scale.module.css | 55 +++++++++++++++++++--
1 file changed, 52 insertions(+), 3 deletions(-)
diff --git a/documentation/src/pages/at-scale.module.css b/documentation/src/pages/at-scale.module.css
index 330dc0b1..5adcf5b6 100644
--- a/documentation/src/pages/at-scale.module.css
+++ b/documentation/src/pages/at-scale.module.css
@@ -289,21 +289,68 @@
/* ------------------------------------------------------------------ table ---- */
+/*
+ * Infima styles every table as a bordered, striped grid, and this one is ruled
+ * horizontally only. Its defaults are cleared here rather than worked around: the cells
+ * start at the measure with no left padding, which only reads as a column when there is
+ * no vertical rule for the text to sit against. display:table is part of the reset too,
+ * since Infima's display:block leaves border-collapse below with nothing to collapse.
+ *
+ * The layout is fixed so the widths below hold: a long answer wraps inside its column
+ * rather than widening it, which is what keeps the gaps between the three even.
+ */
.table {
+ display: table;
+ table-layout: fixed;
width: 100%;
- margin-top: 2rem;
+ margin: 2rem 0 0;
border-collapse: collapse;
font-size: 0.9rem;
}
+/*
+ * The middle column holds a word or two. Sizing itself, it took nearly a third of the
+ * table and left its answer stranded a long way short of the last column, so it is given
+ * the width its content needs and the slack goes to the column on the end, where there is
+ * nothing following it to open a gap against. Widths sit on the head row because the
+ * fixed layout above takes its columns from the first row.
+ */
+.table thead th:first-child {
+ width: 30%;
+}
+
+.table thead th:nth-child(2) {
+ width: 14rem;
+}
+
+.table thead,
+.table tr,
+.table tr:nth-child(2n) {
+ background: none;
+ border-top: none;
+}
+
+.table thead tr {
+ border-bottom: none;
+}
+
.table th,
.table td {
padding: 0.9rem var(--tp-gut) 0.9rem 0;
text-align: left;
vertical-align: top;
+ border: none;
border-bottom: 1px solid var(--tp-rule);
}
+/* The capability column's text runs to its full measure, so this padding is the entire gap
+ after it. It is wider than the shared gutter to match the space the middle column's
+ width leaves before the last one, which is set by that column's content, not by a
+ gutter. */
+.table tr > *:first-child {
+ padding-right: 3.5rem;
+}
+
.table thead th {
border-bottom: 1px solid var(--tp-ink);
color: var(--tp-faint);
@@ -315,7 +362,6 @@
}
.table tbody th {
- width: 30%;
font-family: var(--tp-display);
font-size: 0.88rem;
font-weight: 700;
@@ -1018,8 +1064,11 @@
border-bottom: none;
}
+ .table tr > *:first-child {
+ padding-right: 0;
+ }
+
.table tbody th {
- width: auto;
margin-bottom: 0.4rem;
}
From 8d50577aae6e81c18d12f2c3115143310f9757f5 Mon Sep 17 00:00:00 2001
From: Larison Carvalho
Date: Wed, 2 Sep 2026 11:31:01 +0200
Subject: [PATCH 2/4] fix: align the status tags in the home page roadmap strip
The tag trailed the title inline, so it landed wherever each title happened
to stop and the four sat at four different offsets. Give it its own column
so they line up down the strip, and fall back to the inline treatment on a
phone, where the rows go full width and there is nothing to line up against.
---
documentation/src/pages/index.module.css | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/documentation/src/pages/index.module.css b/documentation/src/pages/index.module.css
index ab3876ea..d20b53c5 100644
--- a/documentation/src/pages/index.module.css
+++ b/documentation/src/pages/index.module.css
@@ -1428,12 +1428,26 @@
border-bottom: 1px solid var(--tp-rule);
}
+/*
+ * The tag sits in its own column rather than trailing the title inline, so the four tags
+ * line up down the strip instead of landing wherever each title happens to stop. Each row
+ * is its own grid, so the tags only agree on a width if the column names one and they
+ * fill it; left to size themselves the shorter tag sits indented from the longer ones.
+ * It is a floor rather than a fixed width because the tags do not wrap: a status longer
+ * than today's two should push the column open, not spill across the gap into the body.
+ */
.aheadHead {
- display: flex;
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) minmax(4.6rem, auto);
align-items: baseline;
gap: 0.6rem;
}
+.aheadHead .betaTag,
+.aheadHead .tagPlanned {
+ text-align: center;
+}
+
.aheadTitle {
font-family: var(--tp-display);
font-size: 0.8rem;
@@ -1461,6 +1475,12 @@
.aheadStrip li {
grid-template-columns: minmax(0, 1fr);
}
+
+ /* Nothing to line up against once the rows are full width, and a tag held out at the
+ right edge of a phone reads as belonging to the row rather than to its title. */
+ .aheadHead {
+ display: flex;
+ }
}
/*
From 42cafc8d0a3e99f7ab9f6ad715c39ade67acdf4e Mon Sep 17 00:00:00 2001
From: Larison Carvalho
Date: Wed, 2 Sep 2026 18:21:18 +0200
Subject: [PATCH 3/4] style: lead the get involved block with contribution, not
the star
The block promoted four links as equally weighted buttons, so nothing in it
was ranked, and the loudest element was a star. Its own copy says a bug
report is worth more than a star, so the layout was arguing against the
text; starring is also not contributing.
Give it one button, the good-first-issue list, and drop the rest to plain
text running from the ask that takes real work down to the one that costs
nothing. Promote the label to a heading, and caption the contributor row,
which otherwise loses its label to that heading and reads as decoration.
---
documentation/src/pages/index.js | 83 ++++++++++++++++--------
documentation/src/pages/index.module.css | 39 +++++++++++
2 files changed, 96 insertions(+), 26 deletions(-)
diff --git a/documentation/src/pages/index.js b/documentation/src/pages/index.js
index 3af7b8a0..597b2295 100644
--- a/documentation/src/pages/index.js
+++ b/documentation/src/pages/index.js
@@ -49,8 +49,9 @@ const REPO = 'https://github.com/StackGuardian/tirith';
* told it does not exist yet. Influence is the offer, and the star is the cheap version of
* it rather than the point.
*
- * All three are ghost buttons. A secondary action that looks primary is not secondary, and
- * the accent on this page belongs to the copy button in the hero.
+ * Only the first is a ghost button and the rest are plain text. A secondary action that
+ * looks primary is not secondary, and the accent on this page belongs to the copy button
+ * in the hero.
*/
const involve = {
note:
@@ -68,11 +69,23 @@ const involve = {
'It is licensed under Apache 2.0 and governed publicly. Contributions do not need to ' +
'be large: a tested policy, a CI example for an underserved system, or a reproducible bug ' +
'report can be far more valuable than a star.',
- links: [
- {label: 'Star on GitHub', href: REPO},
- {label: 'Find a good first issue', href: `${REPO}/labels/good%20first%20issue`},
- {label: 'Watch for releases', href: `${REPO}/releases`},
+ /*
+ * One button, because four of them read as four equally weighted decisions at the point
+ * where the page should be asking for one thing.
+ *
+ * The button is the good-first-issue list and not the star. The paragraph above it says
+ * a bug report is worth more than a star, so giving the star the loudest element would
+ * have the layout contradicting the copy, and starring is not contributing. The rest run
+ * from the ask that takes real work down to the one that costs nothing.
+ */
+ primary: {
+ label: 'Find a good first issue',
+ href: `${REPO}/labels/good%20first%20issue`,
+ },
+ more: [
{label: 'Ask for a feature', href: `${REPO}/issues/new/choose`},
+ {label: 'Watch for releases', href: `${REPO}/releases`},
+ {label: 'Star on GitHub', href: REPO},
],
};
@@ -903,29 +916,47 @@ export default function Home() {
-
Built by the community
-
- {CONTRIBUTORS.map((c) => (
-
-
-
-
-
- ))}
-
+
+ Get involved
+
+ {/*
+ * Captioned rather than labelled from above, because the heading now names
+ * the section rather than the row: without a line of its own the faces are
+ * a group of strangers the reader has no way to place.
+ */}
+
+
+ {CONTRIBUTORS.map((c) => (
+
+
+
+
+
+ ))}
+
+
+ Built by the community.
+
+
{involve.community}
{involve.note}
+ {/* Wrapped, because a bare grid child would stretch the button full width. */}
diff --git a/documentation/src/pages/index.module.css b/documentation/src/pages/index.module.css
index d20b53c5..88fe4151 100644
--- a/documentation/src/pages/index.module.css
+++ b/documentation/src/pages/index.module.css
@@ -1541,6 +1541,45 @@
outline-offset: 2px;
}
+/*
+ * The figure holds the faces and their caption together. The row's own bottom margin is
+ * spacing for the block below it, which is too much between an image and its caption, so
+ * it is overridden here rather than pulled back with a negative margin on the caption.
+ */
+.contributors {
+ margin: 0;
+}
+
+.contributors .faces {
+ margin-bottom: 0.55rem;
+}
+
+.contributorsNote {
+ color: var(--tp-faint);
+ font-size: 0.8rem;
+}
+
+/*
+ * The references under the button. They are deliberately not buttons: the block asks for
+ * one thing, and a row of equally sized boxes turns that ask into a menu.
+ */
+.involveMore {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.35rem 1.2rem;
+ font-size: 0.85rem;
+}
+
+.involveMore a {
+ color: var(--tp-soft);
+ text-decoration: underline;
+ text-underline-offset: 0.2em;
+}
+
+.involveMore a:hover {
+ color: var(--tp-ink);
+}
+
.involveNote {
max-width: 62ch;
margin: 0;
From bad3b038e70224d23fbeae4875dc155020b7defb Mon Sep 17 00:00:00 2001
From: Larison Carvalho
Date: Wed, 2 Sep 2026 18:21:34 +0200
Subject: [PATCH 4/4] docs: cut the tirith ui banner to one line
Four clauses and forty-four words wrapped the announcement strip onto two
lines, which is more than a banner gets read for. Keep the two things the
tool is for and drop the rest, which the page it links to already covers.
---
documentation/src/pages/index.js | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/documentation/src/pages/index.js b/documentation/src/pages/index.js
index 597b2295..77dca10b 100644
--- a/documentation/src/pages/index.js
+++ b/documentation/src/pages/index.js
@@ -278,10 +278,12 @@ const announcement = {
// No backticks: this is JSX text, not markdown, so they would render literally.
// The renderer sets the command in .
command: 'tirith ui',
+ // A banner is read at a glance or not at all, so it carries the two things the tool is
+ // for and nothing else. Validation as you type and serving the playground to a team are
+ // the page it links to, not this line.
body:
- 'explores a failing evaluation down to the resource that caused it, builds policies ' +
- 'from a form, validates them as you type, and serves the playground on a port for ' +
- 'people who have installed nothing.',
+ 'explores a failing evaluation down to the resource that caused it, and builds ' +
+ 'policies from a form.',
to: '/docs/tirith-usage/interactive-interface/',
linkLabel: 'Read more',
};