sitetile: give .st-faq a container, and let the cta's caption= be seen - #6
Merged
Conversation
Two defects found on a built site, both invisible to every gate this repo has.
.st-faq had NO rule. Thirty lines of the stylesheet style .st-faq-head, -list,
-item, -q and -a — every one a DESCENDANT — so the file reads like a package that
thought about the faq, while the container it all hangs from had no width and no
padding. probe_render on a built site showed `.st-faq` matching one rule:
`* { box-sizing }`. The FAQ ran edge to edge under a prose section inset 48px.
Third instance of the .st-notfound / .st-cta-arrow defect class: we emit a class
and never paint it, and the only detector is a person looking at the page.
The rule takes the SHARED wrapper's declarations (.st-prose, .st-grid, .st-cta,
.st-people) — no second opinion about page width — and sits in :where() so any
theme that names .st-faq wins. It is NOT gated on data-theme-custom, unlike the
faq PAINT below it: that gate is right for a look a hand-rolled theme already
chose, and wrong here, because it would exempt exactly the sites with the bug.
`caption=` on a cta was reported to authors as "read by nothing … the renderer
never looks at it", at save time, while it reordered the section's DOM. The list
of params each coral reads is derived from this package by scanning a section
component for `pm.<name>`; Cta.astro called `ctaCaptionFirst(pm)` — it handed the
whole bag to a helper that reached inside. Real code, real effect, nothing for the
derivation to find. A checker that is wrong is worse than none: it talks authors
out of markup that works. So ctaCaptionFirst now takes the VALUE and the read
happens at the call site, where a scan can see it.
Guards, both shown to go red with the fix reverted:
base-paint.test.mjs .st-faq is styled as a CONTAINER (its own selector, not a
descendant), ungated, and carries the shared wrapper's
declarations verbatim. Control: the faq paint IS still
gated, so the test can tell box model from look.
coral-params.test.mjs measures that caption= reorders the reference renderer,
then requires the scan to see it — a read param reported
inert fails here. Plus the general shape: no component may
hand `pm` to a helper. Controls for the detector, for the
comment stripper (this file's own prose says "pm"), and
for bracket reads.
The bracket half is not hypothetical. hero reads `pm['logo-pos']`, which cannot be
written `pm.logo-pos`, so a dot-only derivation calls that inert too — same defect,
a different door. Fixing the consumer's scan is the other repo's half; this one
asserts ours: every param this renderer reads is read where a scan can find it.
Refs tile-lab#7, tile-lab#8.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two renderer defects found on a built site. Neither failed anything: the build is green, the HTML is valid, and in both cases the detector was a person looking at the page.
1 —
.st-faqshipped no layout rule (tile-lab#7)Thirty lines of
site.cssstyle.st-faq-head,-list,-item,-qand-a. Every one of them is a descendant of.st-faq, which had no rule at all — so the stylesheet reads like a package that thought hard about the faq, while the container it all hangs from has no width and no padding.probe_renderon a built site showed.st-faqmatching exactly one rule:* { box-sizing }. The FAQ ran edge to edge, directly under a prose section inset 48px.A missing rule is invisible against a block of present ones. Same defect class as
.st-notfoundand.st-cta-arrow(2026-08-08): we emit a class and never paint it.The fix takes the shared wrapper declarations — the ones
.st-prose, .st-grid, .st-cta, .st-peoplealready use — so the faq joins the other sections rather than acquiring a second opinion about page width. It sits in:where()(zero specificity, a floor any theme overrides by naming the class) and is deliberately not gated ondata-theme-custom, unlike the faq paint below it. That gate is correct for a look a hand-rolled theme already chose; on the container it would exempt precisely the sites that have the bug.2 —
caption=on actawas reported inert while it reordered the DOM (tile-lab#8)save_page/verify_sitetold authors, at write time:Every clause was false. The real reader is
ctaCaptionFirst()insite-core.js, called fromCta.astro, and it moves the caption paragraph ahead of the button row in the real DOM (not a CSSorderillusion — the reading order is right for screen readers too).The checker was not making it up. The table of "which params each coral reads" is derived from this package, on purpose — a hand-kept list is wrong the day the renderer moves and nobody downstream can tell. The derivation scans a section component for
pm.<name>.Cta.astroread the param asctaCaptionFirst(pm): it handed the whole bag to a helper and the helper reached inside. Real code, real effect, and nopm.captionanywhere to find.So the fix is on this side of the seam.
ctaCaptionFirstnow takes the value, and the read happens at the call site in the component, where the thing deriving the table can see it. A checker that is wrong is worse than no checker — it does not merely fail to help, it talks authors out of markup that works.One more instance of the same defect, not fixed here:
heroreadspm['logo-pos'], which cannot be writtenpm.logo-pos— it is not an identifier. A dot-only derivation calls that one inert too. Making the downstream scan match the bracket form is the consumer's half; this PR asserts ours.Guards
Both were run with the fix reverted and both go red — a guard nobody has watched fail is a guard you only know is quiet.
base-paint.test.mjs—.st-faqis styled as a container (matched on its own selector, not on a descendant), is ungated, and carries the shared wrapper's declarations verbatim. Control: the faq paint is still gated, so the test can tell box model from look.coral-params.test.mjs(new) — the test this issue asked for. It first measures thatcaption=reorders the reference renderer (one variable between the two arms), then requires a scan ofCta.astroto see it: a param proved to be read, but reported inert, fails here. It also pins the general shape — no section component may handpmto a helper — with controls for the detector itself, for the comment stripper (this file's own prose contains the wordpm, and a scanner that reads its own explanation reports the fix as the bug), and for bracket reads.Verification
bash scripts/test.sh→ exit0,✅ ALL GREEN.packages/sitetile/astro/node_modules) and CI does not install them either, so the changed component would otherwise be exercised by nothing. Installed them and ran it:✅ sitetile-astro smoke PASS (59/59).faqsection and acta caption=before) and read the output back: the built CSS carries:where(.st-faq){max-width:var(--gd-maxw);margin-inline:auto;padding:2.5rem clamp(1rem,4vw,3rem)}, and in thecaption=beforesection the blurb precedesst-cta-btnswhile the page's other, plain cta keeps buttons-first. Fixture reverted.Refs tile-lab#7, tile-lab#8.