refactor: split concepts.page into 6 sections, fix dead highlighting (RD-24)

The page held six teaching sections and a 142-line `styles:` block, at 471
effective lines against a limit of 250. It is now 36 lines of composition.

Angular scopes a component's CSS to markup that component rendered, so the
split had to move each rule to its owner. `concept-card` owns the card
vocabulary and renders it. `.app-code`, `.app-lead`, `.app-cols` and
`.app-note` become globals, because their targets are projected or arrive
through `[innerHTML]`.

That constraint exposed a live bug. The syntax-highlighting rules compiled to
`pre[_ngcontent-%COMP%] .k[_ngcontent-%COMP%]`, but `highlight-ts` injects the
`.k`/`.s`/`.c` spans through `[innerHTML]`, so they carry no scope attribute
and the rule never matched. Keywords, strings and comments have always
rendered in the plain foreground colour. The rules are global now, on five new
`--app-code-*` tokens.

Widen the colour guard while here: it scanned only `*.component.ts`, so every
`*.page.ts`, `*.section.ts` and `*.step.ts` was invisible to it. That is how
this page collected 21 hardcoded colours. One other file needed a fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-09-04 23:44:01 +02:00
co-authored by Claude Sonnet 5
parent d5a7a25a78
commit 630d68045f
13 changed files with 908 additions and 488 deletions
+52
View File
@@ -113,6 +113,15 @@ body {
--app-devpanel-accent: #9cdcfe;
--app-devpanel-border: #444;
--app-devpanel-shadow: rgb(0 0 0 / 0.4);
/* Showcase code-block palette (concepts.page.ts, RD-24): the same "exempt file"
reasoning as --app-devpanel-* above. A dark code-editor palette, kept off the CIBG
design system, for the teaching page's highlighted TS snippets. */
--app-code-bg: #1e2430;
--app-code-fg: #e6e9ef;
--app-code-keyword: #c792ea;
--app-code-string: #c3e88d;
--app-code-comment: #7e8aa0;
}
/* App utility classes: centralise the repeated inline layout idioms so components stay
@@ -127,6 +136,49 @@ body {
.app-text-subtle {
color: var(--rhc-color-foreground-subtle);
}
/* Highlighted code block (concepts.page.ts, RD-24). Global because the `.k`/`.s`/`.c`
keyword/string/comment spans arrive through `[innerHTML]` — they never carry the
rendering component's `_ngcontent` attribute, so a component-scoped rule can never
match them. This is why the highlighting never rendered before RD-24. */
.app-code {
background: var(--app-code-bg);
color: var(--app-code-fg);
padding: 1rem;
border-radius: 8px;
overflow: auto;
font-size: 0.82rem;
line-height: 1.55;
margin: 0;
}
.app-code .k {
color: var(--app-code-keyword);
}
.app-code .s {
color: var(--app-code-string);
}
.app-code .c {
color: var(--app-code-comment);
font-style: italic;
}
/* Page-level typography idioms shared by every showcase section (concepts.page.ts). */
.app-lead {
color: var(--rhc-color-grijs-700);
max-width: 46rem;
margin: 0.25rem 0 1.25rem;
}
.app-cols {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
gap: 1.5rem;
align-items: start;
}
/* A note whose content includes markup (e.g. `<code>`) must be projected into its
card, so it keeps the DECLARING component's scope, not the card's — global it is. */
.app-note {
font-size: 0.9rem;
color: var(--rhc-color-grijs-700);
margin: 0.75rem 0 0;
}
/* Route transitions (withViewTransitions): cross-fade the routed CONTENT only.
The chrome gets its own stable view-transition-name so it's lifted out of the