feat: implement #4 — replace answer-revealing validation messages with pedagogical hints

Rewrite ~120 validation error messages across 17 English lesson modules
and their localized variants (ar, de, es, pl, uk) to use concept questions,
property hints, and directional nudges instead of revealing the exact
CSS property-value answers.

Priority modules (flexbox, box-model, colors, positioning) fully rewritten.
All remaining CSS modules updated. Only message strings changed — no
validation logic modifications.
This commit is contained in:
2026-03-28 19:40:28 +01:00
parent 782e87705c
commit c560676544
50 changed files with 434 additions and 403 deletions

View File

@@ -22,7 +22,7 @@
{
"type": "regex",
"value": "^input\\[type=\"text\"\\]\\s*{",
"message": "Use <kbd>input[type=\"text\"] { … }</kbd> as your attribute selector",
"message": "Which attribute selector syntax targets inputs with a specific type? Check the square-bracket notation from the description.",
"options": {
"caseSensitive": true
}
@@ -85,7 +85,7 @@
{
"type": "regex",
"value": "^a\\[href\\^=\"https\"\\]\\s*{",
"message": "Use <kbd>a[href^=\"https\"] { … }</kbd> as your attribute selector to target HTTPS links",
"message": "Which partial-match attribute selector targets values that <em>start with</em> a given string? Combine the element name with that selector.",
"options": {
"caseSensitive": true
}
@@ -145,7 +145,7 @@
{
"type": "regex",
"value": "^\\.main-nav\\s*>\\s*li\\s*{",
"message": "Use <kbd>.main-nav > li { … }</kbd> with the child combinator to target only direct children",
"message": "Which combinator selects only <em>direct</em> children, skipping deeper descendants? Place it between the parent and child selectors.",
"options": {
"caseSensitive": true
}
@@ -203,7 +203,7 @@
{
"type": "regex",
"value": "^nav\\s+a\\s*{",
"message": "Use <kbd>nav a</kbd> with a space between nav and a",
"message": "The descendant combinator is the simplest one — what character separates a parent selector from a descendant selector?",
"options": {
"caseSensitive": true
}
@@ -261,7 +261,7 @@
{
"type": "regex",
"value": "^h2\\s*\\+\\s*p\\s*{",
"message": "Use <kbd>h2 + p</kbd> with the adjacent sibling combinator (+)",
"message": "Which combinator targets the element <em>immediately</em> following a sibling? Place it between the two element selectors.",
"options": {
"caseSensitive": true
}
@@ -319,7 +319,7 @@
{
"type": "regex",
"value": "^h3\\s*~\\s*p\\s*{",
"message": "Use <kbd>h3 ~ p</kbd> with the general sibling combinator (~)",
"message": "Which combinator selects <em>all</em> later siblings, not just the one right next to it? Place it between the two element selectors.",
"options": {
"caseSensitive": true
}
@@ -377,7 +377,7 @@
{
"type": "regex",
"value": "^button:hover\\s*{",
"message": "Use <kbd>button:hover</kbd> to target buttons on hover",
"message": "Which pseudo-class activates when the cursor is over an element? Attach it to the button selector with a colon.",
"options": {
"caseSensitive": true
}
@@ -435,7 +435,7 @@
{
"type": "regex",
"value": "^li:first-child\\s*{",
"message": "Use <kbd>li:first-child</kbd> to target first list items",
"message": "Which pseudo-class selects an element only when it is the <em>first</em> child of its parent? Attach it to the <kbd>li</kbd> selector.",
"options": {
"caseSensitive": true
}