From 6af6950f23e0767f2963952cc3ad6f240ce47214 Mon Sep 17 00:00:00 2001 From: Alex Dunmow Date: Sun, 5 Jul 2026 17:27:27 +0800 Subject: [PATCH] fix(scifi-clean): repair blank hero + whitespace/layout + mobile responsiveness Layout / whitespace: - Root-cause blank hero: seed passed hero styled-text (eyebrow/headline/ subheadline) as bare strings, but the hero template does field.text|default:field and the ninjatpl engine throws a hard error on attribute-access-on-string, so the whole hero (and the builtin fallback) errored and rendered as an empty ~160px band. Seed now passes {text:...} objects (the builtin-sample / admin-editor format). - tech_spec table: value + unit were both right-aligned, leaving a cavernous mid-gap; label column now absorbs slack and value+unit group together on the right. Box narrowed (34rem) with tighter padding so the HUD corners frame a deliberate panel. - Tightened section rhythm (sc-section 4->3.5rem, sc-section-tight 2.5->2.75rem) and hero bottom padding to remove oversized inter-section gaps. - Defined sc-article-measure (was referenced but undefined -> unbounded line length). Empty-media graceful state (seed ships no images): - rich-section and hero (split) rendered an empty aspect-ratio muted box when media was absent; media frame is now guarded and the grid collapses to one column. Mobile responsiveness (explicit sc-* classes + @media, not JIT-scanned Tailwind): - sc-form-grid (global + contact-form scoped) collapses to 1 column <=640px. - gallery dropped inline grid-template-columns that overrode its responsive classes, so 3/4-col galleries now collapse on small screens. - nav toggle tap target bumped to 42x42px. Motion robustness: - Added a safety-net full-reveal timeout to the scroll-reveal script so below-fold [data-sc-reveal] content is guaranteed visible on no-scroll screenshot captures and IntersectionObserver edge cases. Reduced-motion / no-JS already render fully. Semantic tokens only; check-safety 32 checks 19 ok 13 skip -> OK; codeless build OK. No version bump. Co-Authored-By: Claude Opus 4.8 --- blocks/tech_spec.ninjatpl | 2 +- manifest.yaml | 14 ++++++++------ seed/seed.json | 2 +- .../overrides/scifi-clean/contact-form.ninjatpl | 2 +- templates/overrides/scifi-clean/gallery.ninjatpl | 2 +- templates/overrides/scifi-clean/hero.ninjatpl | 4 ++-- .../overrides/scifi-clean/rich-section.ninjatpl | 4 ++-- templates/scifi-clean/article.ninjatpl | 2 ++ templates/scifi-clean/auth.ninjatpl | 2 ++ templates/scifi-clean/blog-index.ninjatpl | 2 ++ templates/scifi-clean/contact.ninjatpl | 2 ++ templates/scifi-clean/default.ninjatpl | 2 ++ templates/scifi-clean/full-width.ninjatpl | 2 ++ templates/scifi-clean/landing.ninjatpl | 2 ++ 14 files changed, 30 insertions(+), 14 deletions(-) diff --git a/blocks/tech_spec.ninjatpl b/blocks/tech_spec.ninjatpl index 7e88827..0e7fe69 100644 --- a/blocks/tech_spec.ninjatpl +++ b/blocks/tech_spec.ninjatpl @@ -1 +1 @@ -
{% if caption %}{% endif %}{% if rows %}{% for row in rows %}{% endfor %}{% else %}{% endif %}
{{ caption }}
{{ row.label }}{{ row.value }}{{ row.unit }}
No spec rows yet--
+
{% if caption %}{% endif %}{% if rows %}{% for row in rows %}{% endfor %}{% else %}{% endif %}
{{ caption }}
{{ row.label }}{{ row.value }}{{ row.unit }}
No spec rows yet--
diff --git a/manifest.yaml b/manifest.yaml index a17f74c..93fc732 100644 --- a/manifest.yaml +++ b/manifest.yaml @@ -140,9 +140,10 @@ css: /* --- Layout primitives --- */ .sc-content-well { width: 100%; max-width: 1280px; margin-left: auto; margin-right: auto; padding-left: 1.5rem; padding-right: 1.5rem; box-sizing: border-box; } .sc-measure { max-width: 70ch; } + .sc-article-measure { max-width: 72ch; } .sc-swiss-12 { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: 1.5rem; row-gap: 1.5rem; } - .sc-section { padding-top: 4rem; padding-bottom: 4rem; } - .sc-section-tight { padding-top: 2.5rem; padding-bottom: 2.5rem; } + .sc-section { padding-top: 3.5rem; padding-bottom: 3.5rem; } + .sc-section-tight { padding-top: 2.75rem; padding-bottom: 2.75rem; } .sc-hairline { border: 1px solid hsl(var(--border)); } .sc-hairline-top { border-top: 1px solid hsl(var(--border)); } .sc-hairline-bottom { border-bottom: 1px solid hsl(var(--border)); } @@ -218,7 +219,7 @@ css: @media (min-width: 768px) { .sc-nav-links { display: flex; } } .sc-nav-link { font-family: var(--font-body, "Inter", system-ui, sans-serif); font-size: 0.9375rem; color: hsl(var(--foreground)); text-decoration: none; padding-bottom: 2px; border-bottom: 2px solid transparent; transition: border-color 150ms ease; } .sc-nav-link:hover { border-bottom-color: hsl(var(--accent)); } - .sc-nav-toggle { display: inline-flex; } + .sc-nav-toggle { display: inline-flex; align-items: center; justify-content: center; min-width: 42px; min-height: 42px; } @media (min-width: 768px) { .sc-nav-toggle { display: none; } } .sc-nav-drawer { display: none; flex-direction: column; gap: 0.25rem; padding: 0.5rem 0 1rem; border-top: 1px solid hsl(var(--border)); width: 100%; } @media (min-width: 768px) { .sc-nav-drawer { display: none !important; } } @@ -329,6 +330,7 @@ css: /* --- Forms --- */ .sc-form { display: grid; gap: 1.25rem; } .sc-form-grid { display: grid; gap: 1.25rem; grid-template-columns: repeat(2, minmax(0, 1fr)); } + @media (max-width: 640px) { .sc-form-grid { grid-template-columns: 1fr; } } .sc-field { display: flex; flex-direction: column; gap: 0.375rem; } .sc-field--full { grid-column: 1 / -1; } .sc-label { font-family: var(--font-heading, "Inter", system-ui, sans-serif); font-size: 0.8125rem; font-weight: 600; color: hsl(var(--foreground)); text-transform: uppercase; letter-spacing: 0.04em; } @@ -450,9 +452,9 @@ css: .sc-spec { width: 100%; border-collapse: collapse; font-family: var(--font-mono, ui-monospace, monospace); font-size: 0.875rem; } .sc-spec caption { font-family: var(--font-mono, ui-monospace, monospace); font-size: 0.75rem; letter-spacing: 0.12em; text-transform: uppercase; color: hsl(var(--muted-foreground)); text-align: left; padding-bottom: 0.75rem; } .sc-spec tr { border-bottom: 1px solid hsl(var(--border)); } - .sc-spec-label { text-align: left; padding: 0.625rem 0.5rem; color: hsl(var(--muted-foreground)); text-transform: uppercase; letter-spacing: 0.06em; font-size: 0.75rem; } - .sc-spec-value { text-align: right; padding: 0.625rem 0.5rem; color: hsl(var(--foreground)); font-variant-numeric: tabular-nums; font-weight: 500; } - .sc-spec-unit { text-align: right; padding: 0.625rem 0.5rem; color: hsl(var(--muted-foreground)); font-size: 0.75rem; } + .sc-spec-label { text-align: left; width: 100%; padding: 0.625rem 0.5rem; color: hsl(var(--muted-foreground)); text-transform: uppercase; letter-spacing: 0.06em; font-size: 0.75rem; } + .sc-spec-value { text-align: right; white-space: nowrap; padding: 0.625rem 0.375rem 0.625rem 1rem; color: hsl(var(--foreground)); font-variant-numeric: tabular-nums; font-weight: 500; } + .sc-spec-unit { text-align: left; white-space: nowrap; width: 1%; padding: 0.625rem 0.5rem 0.625rem 0; color: hsl(var(--muted-foreground)); font-size: 0.75rem; } .sc-bench-row { display: grid; grid-template-columns: 1fr auto; gap: 0.375rem 1rem; align-items: baseline; margin-bottom: 1rem; } .sc-bench-name { font-family: var(--font-body, "Inter", system-ui, sans-serif); font-size: 0.9375rem; color: hsl(var(--foreground)); } diff --git a/seed/seed.json b/seed/seed.json index 4c7b50a..8059281 100644 --- a/seed/seed.json +++ b/seed/seed.json @@ -27,7 +27,7 @@ "template_key": "full-width", "reconcile_blocks": true, "blocks": [ - { "block_key": "hero", "title": "Hero", "slot": "main", "sort_order": 1, "content": { "template": "left-aligned", "eyebrow": "Field autonomy", "headline": "Robots that hold their own position", "subheadline": "Halcyon builds the perception and control stack for machines that work where the map runs out. One runtime, from sensor to actuator.", "ctaPrimary": { "text": "Read the spec", "url": "/about" }, "ctaSecondary": { "text": "Book a briefing", "url": "/contact" } } }, + { "block_key": "hero", "title": "Hero", "slot": "main", "sort_order": 1, "content": { "template": "left-aligned", "eyebrow": { "text": "Field autonomy" }, "headline": { "text": "Robots that hold their own position" }, "subheadline": { "text": "Halcyon builds the perception and control stack for machines that work where the map runs out. One runtime, from sensor to actuator." }, "ctaPrimary": { "text": "Read the spec", "url": "/about" }, "ctaSecondary": { "text": "Book a briefing", "url": "/contact" } } }, { "block_key": "scifi-clean:telemetry_grid", "title": "Telemetry", "slot": "main", "sort_order": 2, "content": { "eyebrow": "Runtime", "heading": "What the stack holds", "columns": 4, "tiles": [ { "label": "Control loop", "value": "1000", "unit": "Hz", "delta": "deterministic" }, { "label": "Localisation drift", "value": "4", "unit": "cm", "delta": "over 1 km" }, { "label": "Onboard latency", "value": "18", "unit": "ms", "delta": "sensor to command" }, { "label": "Power draw", "value": "42", "unit": "W", "delta": "full autonomy" } ] } }, { "block_key": "scifi-clean:benchmark_table", "title": "Benchmarks", "slot": "main", "sort_order": 3, "content": { "eyebrow": "Perception", "heading": "Detection recall by surface", "rows": [ { "label": "Paved road", "value": "99.2", "unit": "%", "bar": 99, "highlight": false }, { "label": "Gravel and dirt", "value": "97.8", "unit": "%", "bar": 98, "highlight": false }, { "label": "Low light", "value": "94.1", "unit": "%", "bar": 94, "highlight": true }, { "label": "Heavy dust", "value": "91.6", "unit": "%", "bar": 92, "highlight": false } ], "note": "Measured on the internal Halcyon field set. Numbers are illustrative product data for this demo site." } }, { "block_key": "stats", "title": "Deployment", "slot": "main", "sort_order": 4, "content": { "heading": "Built for the field", "columns": 3, "countUp": false, "items": [ { "value": "40", "suffix": " C", "label": "Rated operating ceiling" }, { "value": "8", "suffix": " h", "label": "Continuous mission time" }, { "value": "IP67", "label": "Sealed enclosure rating" } ] } }, diff --git a/templates/overrides/scifi-clean/contact-form.ninjatpl b/templates/overrides/scifi-clean/contact-form.ninjatpl index 6190357..6deed57 100644 --- a/templates/overrides/scifi-clean/contact-form.ninjatpl +++ b/templates/overrides/scifi-clean/contact-form.ninjatpl @@ -30,5 +30,5 @@ {% endwith %} {% endif %} - + {% endwith %} diff --git a/templates/overrides/scifi-clean/gallery.ninjatpl b/templates/overrides/scifi-clean/gallery.ninjatpl index a059052..b0e682e 100644 --- a/templates/overrides/scifi-clean/gallery.ninjatpl +++ b/templates/overrides/scifi-clean/gallery.ninjatpl @@ -1,6 +1,6 @@ {# gallery override — HUD grid of hairline-framed images; carries data-bn-gallery / data-lightbox / data-bn-gallery-item so the host lightbox JS binds. #} {% if columns == 4 %}{% set gcols = "sc-gallery-4" %}{% set gn = 4 %}{% elif columns == 2 %}{% set gcols = "" %}{% set gn = 2 %}{% else %}{% set gcols = "sc-gallery-3" %}{% set gn = 3 %}{% endif %} {% if gap == "sm" %}{% set ggap = "0.5rem" %}{% elif gap == "lg" %}{% set ggap = "1.5rem" %}{% else %}{% set ggap = "1rem" %}{% endif %} -