From d919a967cfb826708cb066c2cbe0d31668ba266c Mon Sep 17 00:00:00 2001 From: Alex Dunmow Date: Sun, 5 Jul 2026 17:26:12 +0800 Subject: [PATCH] fix(lcars): remediate hero blank, empty-media balloon, CTA void, band padding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Layout/whitespace remediation (no redesign; LCARS persona intact): - hero: styled-text reads used `field.text|default:field`, which HARD-ERRORS in ninjatpl when the field is a bare string (resolveIdentifier errors on reflect.String, and nodeFilteredVariable returns before the default filter runs). The demo seed passes bare strings for eyebrow/headline/subheadline, so the hero aborted on its first {% set %} and rendered nothing — a dead band on the home page. Switch to `field|get:"text"|default:field` (the global jutsu `get` filter tolerates non-maps), which resolves both the {text,color} object and bare-string forms. Same defensive fix in navbar logoText. - hero split: guard the empty media frame so an image-less split hero drops to a single column instead of leaving a blank muted panel. - episode_console: empty cover rendered a full 1:1 square that ballooned to ~600px and, with align-items:stretch, stretched the text column to match, leaving a large void beside the copy. Switch to align-items:start and render a compact, capped, on-brand LCARS readout placeholder (.lcars-console-art) when no cover ships. - cta: band variant left a large empty region right of the button; use justify-content:space-between and trim the oversized 4rem band padding to 3rem. - manifest css: add .lcars-console-art (explicit CSS, semantic tokens) + cap .lcars-img-empty height. Mobile responsiveness audited from CSS/templates: all grids/rails collapse via explicit @media rules in manifest css.input_css_append (not Tailwind JIT-scanned theme classes); no horizontal overflow at 375-390px. Content is never gated by IntersectionObserver (canvas IO drives only the decorative hero background; .lcars-reveal is a load-time CSS animation with a reduced-motion opacity:1 fallback), so no reveal-hidden dead bands. Co-Authored-By: Claude Opus 4.8 --- blocks/episode_console.ninjatpl | 4 ++-- manifest.yaml | 12 +++++++++++- templates/overrides/lcars/cta.ninjatpl | 2 +- templates/overrides/lcars/hero.ninjatpl | 10 +++++----- templates/overrides/lcars/navbar.ninjatpl | 2 +- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/blocks/episode_console.ninjatpl b/blocks/episode_console.ninjatpl index ee45df2..96d20d9 100644 --- a/blocks/episode_console.ninjatpl +++ b/blocks/episode_console.ninjatpl @@ -1,7 +1,7 @@
-
-
{% if cover %}{% img cover alt=title|default:"Episode cover" %}{% else %}
{% endif %}
+
+{% if cover %}
{% img cover alt=title|default:"Episode cover" %}
{% else %}{% endif %}
{% if eyebrow %}{{ eyebrow }}{% else %}Now Broadcasting{% endif %}
{% if episodeNumber %}EP {{ episodeNumber }}{% endif %}{% if stardate %}Stardate {{ stardate }}{% endif %}{% if duration %}{{ duration }}{% endif %}
diff --git a/manifest.yaml b/manifest.yaml index 3b1c0fb..17a7f84 100644 --- a/manifest.yaml +++ b/manifest.yaml @@ -212,7 +212,17 @@ css: .lcars-surface-card { background-color: hsl(var(--card)); } .lcars-media-frame { display: block; width: 100%; overflow: hidden; background-color: hsl(var(--muted)); border-radius: 0.5rem; } .lcars-media-frame img { display: block; width: 100%; height: 100%; object-fit: cover; } - .lcars-img-empty { display: block; width: 100%; aspect-ratio: 16 / 9; background-color: hsl(var(--muted)); border-radius: 0.5rem; } + .lcars-img-empty { display: block; width: 100%; aspect-ratio: 16 / 9; max-height: 20rem; background-color: hsl(var(--muted)); border-radius: 0.5rem; } + /* Graceful empty-media state: an on-brand LCARS readout panel that stays + compact instead of ballooning into a blank square when no cover ships. */ + .lcars-console-art { display: flex; align-items: center; justify-content: center; align-self: start; width: 100%; aspect-ratio: 4 / 3; max-height: 15rem; padding: 1.5rem; background-color: hsl(var(--muted)); border-radius: 0.5rem; box-sizing: border-box; } + .lcars-console-art-scope { display: flex; flex-direction: column; gap: 0.5rem; width: 100%; max-width: 16rem; } + .lcars-console-art-scope i { display: block; height: 0.625rem; border-radius: 0.3125rem; opacity: 0.55; } + .lcars-console-art-scope i:nth-child(1) { width: 100%; background-color: hsl(var(--primary)); } + .lcars-console-art-scope i:nth-child(2) { width: 72%; background-color: hsl(var(--secondary)); } + .lcars-console-art-scope i:nth-child(3) { width: 88%; background-color: hsl(var(--accent)); } + .lcars-console-art-scope i:nth-child(4) { width: 60%; background-color: hsl(var(--secondary)); } + .lcars-console-art-scope i:nth-child(5) { width: 80%; background-color: hsl(var(--primary)); } /* --- Responsive grids --- */ .lcars-grid { display: grid; gap: 1.25rem; grid-template-columns: repeat(1, minmax(0, 1fr)); } diff --git a/templates/overrides/lcars/cta.ninjatpl b/templates/overrides/lcars/cta.ninjatpl index ed52675..56b51c6 100644 --- a/templates/overrides/lcars/cta.ninjatpl +++ b/templates/overrides/lcars/cta.ninjatpl @@ -1,5 +1,5 @@ {# cta override — full-width strip; band / card / split variants. #} -
+
{% if heading %}

{{ heading }}

{% endif %} {% if text %}

{{ text }}

{% endif %} diff --git a/templates/overrides/lcars/hero.ninjatpl b/templates/overrides/lcars/hero.ninjatpl index 39458cb..222349c 100644 --- a/templates/overrides/lcars/hero.ninjatpl +++ b/templates/overrides/lcars/hero.ninjatpl @@ -1,8 +1,8 @@ {# hero override — LCARS command-deck hero. GO BIG motion tier: one dependency-free canvas panel-sweep behind the content, lazy-inited, prefers-reduced-motion honored, with the fully-styled hero as the static no-JS fallback. All content fields preserved verbatim from the builtin. Styled-text fields accept {text,color} OR a bare string. #} -{% set eyebrowText = eyebrow.text|default:eyebrow %} -{% set headlineText = headline.text|default:headline %} -{% set subText = subheadline.text|default:subheadline %} -{% set descText = description.text|default:description %} +{% set eyebrowText = eyebrow|get:"text"|default:eyebrow %} +{% set headlineText = headline|get:"text"|default:headline %} +{% set subText = subheadline|get:"text"|default:subheadline %} +{% set descText = description|get:"text"|default:description %} {% set pText = ctaPrimary.text %} {% set pUrl = ctaPrimary.url %} {% set sText = ctaSecondary.text %} @@ -17,7 +17,7 @@ {% if trustLogos %}

Trusted by

{% for logo in trustLogos %}{% if logo.url %}{% img logo.image alt=logo.alt class="lcars-logo" %}{% else %}{% img logo.image alt=logo.alt class="lcars-logo" %}{% endif %}{% endfor %}
{% endif %} {% endmacro %} {% if variant == "split" %} -
{{ herobody() }}
{% if backgroundImage %}{% img backgroundImage alt=headlineText class="lcars-hero-media" %}{% endif %}
+
{% if backgroundImage %}
{{ herobody() }}
{% img backgroundImage alt=headlineText class="lcars-hero-media" %}
{% else %}
{{ herobody() }}
{% endif %}
{% else %}
{{ herobody() }}
{% endif %} diff --git a/templates/overrides/lcars/navbar.ninjatpl b/templates/overrides/lcars/navbar.ninjatpl index 48a71aa..9895039 100644 --- a/templates/overrides/lcars/navbar.ninjatpl +++ b/templates/overrides/lcars/navbar.ninjatpl @@ -1 +1 @@ - +