fix(terminal): remediate layout/whitespace + mobile responsiveness
Layout/whitespace (home page): - feature-grid rendered as 3 full-width ballooning rows because the host Tailwind scan covers rendered block HTML, not theme override .ninjatpl files, so lg:grid-cols-* utilities in overrides are purge-fragile and collapsed to one column. Move multi-column layout to plain CSS in css.input_css_append (.tty-grid*, never purged) and apply to feature-grid, stats, pricing, contact-card + a .tty-form-grid for contact-form (col-span utilities were equally fragile). - code_console / boot_log persona blocks shipped no max-width wrapper and ran edge-to-edge on the full-width landing page while sibling sections were contained; wrap both in a centred .tty-console-shell with a mobile side gutter. - CTA heading read dark-on-green (fails contrast): .terminal-heading in assets/style.css hardcoded color:foreground, overriding the band's primary-foreground. Change to color:inherit so headings on inverted bands read correctly. - Trim oversized section padding (py-16 md:py-24 -> py-12 md:py-20; the window-nested contact sections -> py-8 md:py-12). Mobile: - All multi-column grids now collapse to 1 column via CSS media queries (minmax(0,1fr) prevents long/monospace content forcing horizontal overflow); console blocks keep overflow-x scroll inside their own box. - Pin hero min-heights to CSS (.tty-hero*) since min-h-screen / arbitrary min-h-[..] utilities are also purge-fragile. Persona (phosphor TTY, window chrome, man-page, canvas hero) unchanged. No version bump. make + check-safety both exit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
48d8b8ef45
commit
0e54864687
@ -23,7 +23,10 @@
|
|||||||
font-family: var(--font-heading, "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
font-family: var(--font-heading, "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.08em;
|
letter-spacing: 0.08em;
|
||||||
color: hsl(var(--foreground));
|
/* Inherit colour from context so headings placed on an inverted band
|
||||||
|
(e.g. a bg-primary CTA) read as primary-foreground, not a hardcoded
|
||||||
|
foreground that goes dark-on-bright and fails contrast. */
|
||||||
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.terminal-mono {
|
.terminal-mono {
|
||||||
@ -428,3 +431,45 @@
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
font-family: var(--font-body, ui-monospace, monospace);
|
font-family: var(--font-body, ui-monospace, monospace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- Reliable responsive grids (see manifest.yaml input_css_append:
|
||||||
|
the host scans rendered block HTML, not theme override templates, so
|
||||||
|
responsive Tailwind grid utilities in overrides are purge-fragile;
|
||||||
|
define multi-column layout in CSS instead). minmax(0,1fr) prevents
|
||||||
|
long content forcing horizontal overflow on mobile. --- */
|
||||||
|
.tty-grid,
|
||||||
|
.tty-grid-2,
|
||||||
|
.tty-grid-3,
|
||||||
|
.tty-grid-4 { display: grid; gap: 1.5rem; grid-template-columns: repeat(1, minmax(0, 1fr)); }
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.tty-grid-2,
|
||||||
|
.tty-grid-3,
|
||||||
|
.tty-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||||
|
}
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.tty-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||||
|
.tty-grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
||||||
|
}
|
||||||
|
.tty-grid-stats2,
|
||||||
|
.tty-grid-stats3,
|
||||||
|
.tty-grid-stats4 { display: grid; gap: 2rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.tty-grid-stats3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||||
|
.tty-grid-stats4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Two-column form grid (col-span utilities purge-fragile) --- */
|
||||||
|
.tty-form-grid { display: grid; gap: 1.25rem; grid-template-columns: repeat(1, minmax(0, 1fr)); }
|
||||||
|
.tty-form-grid > .tty-col-full { grid-column: 1 / -1; }
|
||||||
|
@media (min-width: 640px) { .tty-form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
|
||||||
|
|
||||||
|
/* --- Contained console shell for full-width landing pages --- */
|
||||||
|
.tty-console-shell { width: 100%; max-width: 56rem; margin: 1.5rem auto; padding-inline: 1rem; }
|
||||||
|
|
||||||
|
/* --- Hero heights (purge-fragile utilities pinned in CSS) --- */
|
||||||
|
.tty-hero { position: relative; }
|
||||||
|
.tty-hero-screen { min-height: 100vh; }
|
||||||
|
.tty-hero-tall { min-height: 75vh; }
|
||||||
|
.tty-hero-half { min-height: 50vh; }
|
||||||
|
.tty-hero-auto { min-height: 24rem; }
|
||||||
|
.tty-hero-media { min-height: 20rem; }
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
{% if lines %}<div class="boot-log" data-block="terminal:boot_log">{% for line in lines %}<span class="boot-line" data-line-index="{{ forloop.Counter0 }}" style="animation-delay: {{ forloop.Counter * 80 }}ms;">[ {{ forloop.Counter0 }} ] {{ line }}</span>{% endfor %}{% set cur = cursor|default:"block" %}{% if cur != "none" %}<span class="boot-cursor">{% if cur == "underscore" %}_{% elif cur == "pipe" %}|{% else %}█{% endif %}</span>{% endif %}</div>{% endif %}
|
{% if lines %}<div class="tty-console-shell"><div class="boot-log" data-block="terminal:boot_log">{% for line in lines %}<span class="boot-line" data-line-index="{{ forloop.Counter0 }}" style="animation-delay: {{ forloop.Counter * 80 }}ms;">[ {{ forloop.Counter0 }} ] {{ line }}</span>{% endfor %}{% set cur = cursor|default:"block" %}{% if cur != "none" %}<span class="boot-cursor">{% if cur == "underscore" %}_{% elif cur == "pipe" %}|{% else %}█{% endif %}</span>{% endif %}</div></div>{% endif %}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
{% if command or output %}<div class="code-console" data-block="terminal:code_console" data-language="{{ language|default:"shell" }}">{% if command %}<div class="cmd-line"><span class="cmd-prompt">{{ prompt|default:"$" }}</span><span class="cmd-text">{{ command }}</span></div>{% endif %}{% if output %}<pre>{{ output }}</pre>{% endif %}</div>{% endif %}
|
{% if command or output %}<div class="tty-console-shell"><div class="code-console" data-block="terminal:code_console" data-language="{{ language|default:"shell" }}">{% if command %}<div class="cmd-line"><span class="cmd-prompt">{{ prompt|default:"$" }}</span><span class="cmd-text">{{ command }}</span></div>{% endif %}{% if output %}<pre>{{ output }}</pre>{% endif %}</div></div>{% endif %}
|
||||||
|
|||||||
@ -458,6 +458,58 @@ css:
|
|||||||
}
|
}
|
||||||
@media (max-width: 768px) { .terminal-article-grid { grid-template-columns: 1fr; } }
|
@media (max-width: 768px) { .terminal-article-grid { grid-template-columns: 1fr; } }
|
||||||
|
|
||||||
|
/* --- Reliable responsive grids ----------------------------
|
||||||
|
The host scans rendered block HTML, not theme override
|
||||||
|
.ninjatpl files, so responsive Tailwind grid utilities used
|
||||||
|
only in overrides (lg:grid-cols-*, sm:grid-cols-2) are
|
||||||
|
purge-fragile and can silently collapse to one column on
|
||||||
|
desktop. Multi-column layout is therefore defined here as
|
||||||
|
plain CSS, which is compiled into the Tailwind input and can
|
||||||
|
never be purged. minmax(0,1fr) stops long/unbreakable content
|
||||||
|
from forcing horizontal overflow on mobile. */
|
||||||
|
.tty-grid,
|
||||||
|
.tty-grid-2,
|
||||||
|
.tty-grid-3,
|
||||||
|
.tty-grid-4 { display: grid; gap: 1.5rem; grid-template-columns: repeat(1, minmax(0, 1fr)); }
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
.tty-grid-2,
|
||||||
|
.tty-grid-3,
|
||||||
|
.tty-grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||||
|
}
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.tty-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||||
|
.tty-grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
||||||
|
}
|
||||||
|
.tty-grid-stats2,
|
||||||
|
.tty-grid-stats3,
|
||||||
|
.tty-grid-stats4 { display: grid; gap: 2rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.tty-grid-stats3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
||||||
|
.tty-grid-stats4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Two-column form grid (col-span utilities in overrides
|
||||||
|
are purge-fragile; pin the grid in CSS) ------------------- */
|
||||||
|
.tty-form-grid { display: grid; gap: 1.25rem; grid-template-columns: repeat(1, minmax(0, 1fr)); }
|
||||||
|
.tty-form-grid > .tty-col-full { grid-column: 1 / -1; }
|
||||||
|
@media (min-width: 640px) { .tty-form-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
|
||||||
|
|
||||||
|
/* --- Contained console shell ------------------------------
|
||||||
|
The persona code-console / boot-log blocks ship no max-width
|
||||||
|
wrapper, so on a full-width landing page they run edge-to-edge
|
||||||
|
while the neighbouring sections are contained. This shell
|
||||||
|
centres them and keeps a mobile side gutter. */
|
||||||
|
.tty-console-shell { width: 100%; max-width: 56rem; margin: 1.5rem auto; padding-inline: 1rem; }
|
||||||
|
|
||||||
|
/* --- Hero heights (min-h-screen / arbitrary min-h-[..] are
|
||||||
|
purge-fragile utilities; pin them in CSS) ----------------- */
|
||||||
|
.tty-hero { position: relative; }
|
||||||
|
.tty-hero-screen { min-height: 100vh; }
|
||||||
|
.tty-hero-tall { min-height: 75vh; }
|
||||||
|
.tty-hero-half { min-height: 50vh; }
|
||||||
|
.tty-hero-auto { min-height: 24rem; }
|
||||||
|
.tty-hero-media { min-height: 20rem; }
|
||||||
|
|
||||||
/* --- Reduced motion: kill all motion ---------------------- */
|
/* --- Reduced motion: kill all motion ---------------------- */
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
{# contact-card terminal override: neon channel panels. All field reads + control flow preserved. #}
|
{# contact-card terminal override: neon channel panels. All field reads + control flow preserved. #}
|
||||||
<section class="py-16 md:py-24 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
<section class="py-8 md:py-12 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||||
<div class="mx-auto max-w-4xl px-4">
|
<div class="mx-auto max-w-4xl px-4">
|
||||||
{% if heading %}<h2 class="terminal-heading text-3xl font-semibold tracking-tight md:text-4xl" data-text="{{ heading }}">{{ heading }}</h2>{% endif %}
|
{% if heading %}<h2 class="terminal-heading text-3xl font-semibold tracking-tight md:text-4xl" data-text="{{ heading }}">{{ heading }}</h2>{% endif %}
|
||||||
{% if description %}<p class="mt-3 max-w-2xl text-lg text-muted-foreground">{{ description }}</p>{% endif %}
|
{% if description %}<p class="mt-3 max-w-2xl text-lg text-muted-foreground">{{ description }}</p>{% endif %}
|
||||||
<div class="mt-10 grid grid-cols-1 gap-4 {% if columns == 3 %}sm:grid-cols-2 lg:grid-cols-3{% elif columns == 1 %}{% else %}sm:grid-cols-2{% endif %}">
|
<div class="mt-8 {% if columns == 3 %}tty-grid-3{% elif columns == 1 %}tty-grid{% else %}tty-grid-2{% endif %}">
|
||||||
{% for channel in channels %}
|
{% for channel in channels %}
|
||||||
<div class="tty-corners flex items-start gap-4 rounded-md border border-primary/40 bg-card p-5 text-card-foreground tty-frame">
|
<div class="tty-corners flex items-start gap-4 rounded-md border border-primary/40 bg-card p-5 text-card-foreground tty-frame">
|
||||||
{% if channel.icon %}<span class="inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-md bg-primary/10 text-primary"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/{{ channel.icon|split:":"|first }}.svg#{{ channel.icon|split:":"|last }}"></use></svg></span>{% endif %}
|
{% if channel.icon %}<span class="inline-flex h-10 w-10 shrink-0 items-center justify-center rounded-md bg-primary/10 text-primary"><svg class="h-5 w-5" aria-hidden="true"><use href="/icons/{{ channel.icon|split:":"|first }}.svg#{{ channel.icon|split:":"|last }}"></use></svg></span>{% endif %}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{# contact-form terminal override: terminal console chrome. The {% form %} block, honeypot, field loop, form.submitted/errors reads and _block_id/bid submit wiring are preserved byte-for-byte — only presentational classes change. #}
|
{# contact-form terminal override: terminal console chrome. The {% form %} block, honeypot, field loop, form.submitted/errors reads and _block_id/bid submit wiring are preserved byte-for-byte — only presentational classes change. #}
|
||||||
{% with bid=_block_id|default:context.blockId %}
|
{% with bid=_block_id|default:context.blockId %}
|
||||||
<section id="contact-form-{{ bid }}" class="py-16 md:py-24 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
<section id="contact-form-{{ bid }}" class="py-8 md:py-12 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||||
<div class="mx-auto max-w-2xl px-4">
|
<div class="mx-auto max-w-2xl px-4">
|
||||||
{% if form.submitted %}
|
{% if form.submitted %}
|
||||||
<div class="tty-corners rounded-md border border-primary/50 bg-card p-8 text-center text-card-foreground tty-frame">
|
<div class="tty-corners rounded-md border border-primary/50 bg-card p-8 text-center text-card-foreground tty-frame">
|
||||||
@ -12,9 +12,9 @@
|
|||||||
{% if description %}<p class="mt-3 text-lg text-muted-foreground">{{ description }}</p>{% endif %}
|
{% if description %}<p class="mt-3 text-lg text-muted-foreground">{{ description }}</p>{% endif %}
|
||||||
{% if form.errors._form %}<div class="mt-6 rounded-md border border-destructive/50 bg-destructive/10 px-4 py-3 text-sm text-destructive">{{ form.errors._form }}</div>{% endif %}
|
{% if form.errors._form %}<div class="mt-6 rounded-md border border-destructive/50 bg-destructive/10 px-4 py-3 text-sm text-destructive">{{ form.errors._form }}</div>{% endif %}
|
||||||
{% with formAction="/api/blocks/"|add:bid|add:"/submit" formTarget="#contact-form-"|add:bid %}
|
{% with formAction="/api/blocks/"|add:bid|add:"/submit" formTarget="#contact-form-"|add:bid %}
|
||||||
{% form action=formAction hx_target=formTarget hx_swap="outerHTML" class="mt-8 grid grid-cols-1 gap-5 sm:grid-cols-2" %}
|
{% form action=formAction hx_target=formTarget hx_swap="outerHTML" class="mt-8 tty-form-grid" %}
|
||||||
{% for field in fields %}
|
{% for field in fields %}
|
||||||
<div class="{% if field.width == "half" %}sm:col-span-1{% else %}sm:col-span-2{% endif %}">
|
<div class="{% if field.width == "half" %}tty-col-half{% else %}tty-col-full{% endif %}">
|
||||||
{% if field.label %}<label for="cf-{{ bid }}-{{ field.name }}" class="terminal-mono mb-1.5 block text-sm font-medium uppercase tracking-wide text-accent">{{ field.label }}{% if field.required %} <span class="text-destructive">*</span>{% endif %}</label>{% endif %}
|
{% if field.label %}<label for="cf-{{ bid }}-{{ field.name }}" class="terminal-mono mb-1.5 block text-sm font-medium uppercase tracking-wide text-accent">{{ field.label }}{% if field.required %} <span class="text-destructive">*</span>{% endif %}</label>{% endif %}
|
||||||
{% if field.type == "textarea" %}
|
{% if field.type == "textarea" %}
|
||||||
<textarea id="cf-{{ bid }}-{{ field.name }}" name="{{ field.name }}" rows="5"{% if field.required %} required{% endif %}{% if field.placeholder %} placeholder="{{ field.placeholder }}"{% endif %} class="w-full rounded-md border border-primary/40 bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"></textarea>
|
<textarea id="cf-{{ bid }}-{{ field.name }}" name="{{ field.name }}" rows="5"{% if field.required %} required{% endif %}{% if field.placeholder %} placeholder="{{ field.placeholder }}"{% endif %} class="w-full rounded-md border border-primary/40 bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"></textarea>
|
||||||
@ -29,7 +29,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<div class="hidden" aria-hidden="true"><label>Leave this field empty<input type="text" name="website" tabindex="-1" autocomplete="off"></label></div>
|
<div class="hidden" aria-hidden="true"><label>Leave this field empty<input type="text" name="website" tabindex="-1" autocomplete="off"></label></div>
|
||||||
<div class="sm:col-span-2">
|
<div class="tty-col-full">
|
||||||
<button type="submit" class="terminal-mono inline-flex items-center justify-center rounded-md bg-primary px-6 py-2.5 text-sm font-medium uppercase tracking-wider text-primary-foreground transition-colors hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2">{{ submitLabel|default:"Send message" }}</button>
|
<button type="submit" class="terminal-mono inline-flex items-center justify-center rounded-md bg-primary px-6 py-2.5 text-sm font-medium uppercase tracking-wider text-primary-foreground transition-colors hover:bg-primary/90 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2">{{ submitLabel|default:"Send message" }}</button>
|
||||||
</div>
|
</div>
|
||||||
{% endform %}
|
{% endform %}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{# cta terminal override: scanline overlay, heading, CTAs. All field reads preserved. #}
|
{# cta terminal override: scanline overlay, heading, CTAs. All field reads preserved. #}
|
||||||
<section class="relative overflow-hidden py-16 md:py-24 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
<section class="relative overflow-hidden py-12 md:py-20 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||||
<div aria-hidden="true" class="tty-scanlines pointer-events-none absolute inset-0"></div>
|
<div aria-hidden="true" class="tty-scanlines pointer-events-none absolute inset-0"></div>
|
||||||
<div class="relative z-10 mx-auto max-w-6xl px-4">
|
<div class="relative z-10 mx-auto max-w-6xl px-4">
|
||||||
<div class="tty-corners {% if background == "band" %}rounded-md bg-primary px-6 py-14 text-center text-primary-foreground md:px-12{% elif background == "card" %}rounded-md border border-primary/50 bg-card px-6 py-14 text-center text-card-foreground tty-frame md:px-12{% else %}flex flex-col items-center gap-8 rounded-md border border-primary/30 bg-muted px-6 py-12 text-foreground md:flex-row md:justify-between md:px-12 md:text-left{% endif %}">
|
<div class="tty-corners {% if background == "band" %}rounded-md bg-primary px-6 py-14 text-center text-primary-foreground md:px-12{% elif background == "card" %}rounded-md border border-primary/50 bg-card px-6 py-14 text-center text-card-foreground tty-frame md:px-12{% else %}flex flex-col items-center gap-8 rounded-md border border-primary/30 bg-muted px-6 py-12 text-foreground md:flex-row md:justify-between md:px-12 md:text-left{% endif %}">
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
{# feature_grid terminal override: scanline hero overlay, mono eyebrow, heading, neon HUD cards. All field reads + control flow preserved. #}
|
{# feature_grid terminal override: scanline hero overlay, mono eyebrow, heading, neon HUD cards. All field reads + control flow preserved. #}
|
||||||
<section class="relative overflow-hidden py-16 md:py-24 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
<section class="relative overflow-hidden py-12 md:py-20 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||||
<div aria-hidden="true" class="tty-scanlines pointer-events-none absolute inset-0"></div>
|
<div aria-hidden="true" class="tty-scanlines pointer-events-none absolute inset-0"></div>
|
||||||
<div class="relative z-10 mx-auto max-w-6xl px-4">
|
<div class="relative z-10 mx-auto max-w-6xl px-4">
|
||||||
{% if eyebrow %}<p class="terminal-mono text-center text-xs font-semibold uppercase tracking-widest text-accent">{{ eyebrow }}</p>{% endif %}
|
{% if eyebrow %}<p class="terminal-mono text-center text-xs font-semibold uppercase tracking-widest text-accent">{{ eyebrow }}</p>{% endif %}
|
||||||
{% if heading %}<h2 class="terminal-heading mt-2 text-center text-3xl font-semibold tracking-tight md:text-4xl" data-text="{{ heading }}">{{ heading }}</h2>{% endif %}
|
{% if heading %}<h2 class="terminal-heading mt-2 text-center text-3xl font-semibold tracking-tight md:text-4xl" data-text="{{ heading }}">{{ heading }}</h2>{% endif %}
|
||||||
{% if intro %}<p class="mx-auto mt-4 max-w-2xl text-center text-lg text-muted-foreground">{{ intro }}</p>{% endif %}
|
{% if intro %}<p class="mx-auto mt-4 max-w-2xl text-center text-lg text-muted-foreground">{{ intro }}</p>{% endif %}
|
||||||
<div class="mt-12 grid grid-cols-1 gap-6 sm:grid-cols-2 {% if columns == 2 %}lg:grid-cols-2{% elif columns == 4 %}lg:grid-cols-4{% else %}lg:grid-cols-3{% endif %}">
|
<div class="mt-10 tty-grid-{% if columns == 2 %}2{% elif columns == 4 %}4{% else %}3{% endif %}">
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
<div class="{% if layout == "card" %}tty-corners rounded-md border border-primary/40 bg-card p-6 text-card-foreground tty-frame transition-transform hover:-translate-y-0.5{% elif layout == "centered" %}text-center{% endif %}">
|
<div class="{% if layout == "card" %}tty-corners rounded-md border border-primary/40 bg-card p-6 text-card-foreground tty-frame transition-transform hover:-translate-y-0.5{% elif layout == "centered" %}text-center{% endif %}">
|
||||||
{% if item.icon %}<div class="mb-4 inline-flex h-11 w-11 items-center justify-center rounded-md bg-primary/10 text-primary{% if layout == "centered" %} mx-auto{% endif %}"><svg class="h-6 w-6" aria-hidden="true"><use href="/icons/{{ item.icon|split:":"|first }}.svg#{{ item.icon|split:":"|last }}"></use></svg></div>{% endif %}
|
{% if item.icon %}<div class="mb-4 inline-flex h-11 w-11 items-center justify-center rounded-md bg-primary/10 text-primary{% if layout == "centered" %} mx-auto{% endif %}"><svg class="h-6 w-6" aria-hidden="true"><use href="/icons/{{ item.icon|split:":"|first }}.svg#{{ item.icon|split:":"|last }}"></use></svg></div>{% endif %}
|
||||||
|
|||||||
@ -26,13 +26,13 @@
|
|||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
{% if variant == "split" %}
|
{% if variant == "split" %}
|
||||||
<section class="hero grid grid-cols-1 lg:grid-cols-2 overflow-hidden bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
<section class="hero grid grid-cols-1 lg:grid-cols-2 overflow-hidden bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||||
<div class="relative min-h-[320px] bg-muted {% if mediaPosition == "left" %}order-1 lg:order-1{% else %}order-1 lg:order-2{% endif %}">{% if hasImage %}{% img backgroundImage alt=headlineText class="absolute inset-0 h-full w-full object-cover" layout="hero" %}{% else %}<div class="tty-rain-wrap"><div class="tty-rain-fallback"></div><canvas class="tty-rain-canvas" aria-hidden="true"></canvas></div>{% endif %}<div aria-hidden="true" class="tty-scanlines pointer-events-none absolute inset-0"></div></div>
|
<div class="relative tty-hero-media bg-muted {% if mediaPosition == "left" %}order-1 lg:order-1{% else %}order-1 lg:order-2{% endif %}">{% if hasImage %}{% img backgroundImage alt=headlineText class="absolute inset-0 h-full w-full object-cover" layout="hero" %}{% else %}<div class="tty-rain-wrap"><div class="tty-rain-fallback"></div><canvas class="tty-rain-canvas" aria-hidden="true"></canvas></div>{% endif %}<div aria-hidden="true" class="tty-scanlines pointer-events-none absolute inset-0"></div></div>
|
||||||
<div class="flex flex-col justify-center px-6 py-16 lg:px-12 {% if mediaPosition == "left" %}order-2 lg:order-2{% else %}order-2 lg:order-1{% endif %}"><div class="max-w-lg text-left">{{ herocontent("left") }}</div></div>
|
<div class="flex flex-col justify-center px-6 py-16 lg:px-12 {% if mediaPosition == "left" %}order-2 lg:order-2{% else %}order-2 lg:order-1{% endif %}"><div class="max-w-lg text-left">{{ herocontent("left") }}</div></div>
|
||||||
</section>
|
</section>
|
||||||
{% else %}
|
{% else %}
|
||||||
{% set align = "center" %}
|
{% set align = "center" %}
|
||||||
{% if variant == "left-aligned" %}{% set align = "left" %}{% endif %}
|
{% if variant == "left-aligned" %}{% set align = "left" %}{% endif %}
|
||||||
<section class="hero relative flex flex-col overflow-hidden bg-background text-foreground {% if minHeight == "screen" %}min-h-screen{% elif minHeight == "50vh" %}min-h-[50vh]{% elif minHeight == "auto" %}min-h-[400px]{% else %}min-h-[75vh]{% endif %} {% if verticalAlign == "top" %}justify-start pt-20{% elif verticalAlign == "bottom" %}justify-end pb-20{% else %}justify-center{% endif %}{% if class %} {{ class }}{% endif %}">
|
<section class="hero tty-hero flex flex-col overflow-hidden bg-background text-foreground {% if minHeight == "screen" %}tty-hero-screen{% elif minHeight == "50vh" %}tty-hero-half{% elif minHeight == "auto" %}tty-hero-auto{% else %}tty-hero-tall{% endif %} {% if verticalAlign == "top" %}justify-start pt-20{% elif verticalAlign == "bottom" %}justify-end pb-20{% else %}justify-center{% endif %}{% if class %} {{ class }}{% endif %}">
|
||||||
{% if hasImage %}<div class="absolute inset-0 z-0">{% img backgroundImage alt=headlineText class="h-full w-full object-cover" layout="hero" %}{% if showOverlay %}<div class="absolute inset-0 {% if overlayColor == "light" %}bg-background/60{% elif overlayColor == "primary" %}bg-primary/50{% elif overlayOpacity <= 30 %}bg-black/30{% elif overlayOpacity <= 50 %}bg-black/50{% elif overlayOpacity <= 70 %}bg-black/70{% else %}bg-black/80{% endif %}"></div>{% endif %}</div>{% else %}<div class="tty-rain-wrap z-0"><div class="tty-rain-fallback"></div><canvas class="tty-rain-canvas" aria-hidden="true"></canvas></div>{% endif %}
|
{% if hasImage %}<div class="absolute inset-0 z-0">{% img backgroundImage alt=headlineText class="h-full w-full object-cover" layout="hero" %}{% if showOverlay %}<div class="absolute inset-0 {% if overlayColor == "light" %}bg-background/60{% elif overlayColor == "primary" %}bg-primary/50{% elif overlayOpacity <= 30 %}bg-black/30{% elif overlayOpacity <= 50 %}bg-black/50{% elif overlayOpacity <= 70 %}bg-black/70{% else %}bg-black/80{% endif %}"></div>{% endif %}</div>{% else %}<div class="tty-rain-wrap z-0"><div class="tty-rain-fallback"></div><canvas class="tty-rain-canvas" aria-hidden="true"></canvas></div>{% endif %}
|
||||||
<div aria-hidden="true" class="tty-scanlines pointer-events-none absolute inset-0 z-0"></div>
|
<div aria-hidden="true" class="tty-scanlines pointer-events-none absolute inset-0 z-0"></div>
|
||||||
<div class="relative z-10 mx-auto w-full max-w-4xl px-4 sm:px-6 lg:px-8 {% if variant == "left-aligned" %}text-left{% else %}text-center{% endif %}">{{ herocontent(align) }}</div>
|
<div class="relative z-10 mx-auto w-full max-w-4xl px-4 sm:px-6 lg:px-8 {% if variant == "left-aligned" %}text-left{% else %}text-center{% endif %}">{{ herocontent(align) }}</div>
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
{# pricing terminal override: scanline overlay, heading, HUD neon tier panels (magenta highlight / cyan standard), CTAs. Field reads + control flow preserved. #}
|
{# pricing terminal override: scanline overlay, heading, HUD neon tier panels (magenta highlight / cyan standard), CTAs. Field reads + control flow preserved. #}
|
||||||
<section class="relative overflow-hidden py-16 md:py-24 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
<section class="relative overflow-hidden py-12 md:py-20 bg-background text-foreground{% if class %} {{ class }}{% endif %}">
|
||||||
<div aria-hidden="true" class="tty-scanlines pointer-events-none absolute inset-0"></div>
|
<div aria-hidden="true" class="tty-scanlines pointer-events-none absolute inset-0"></div>
|
||||||
<div class="relative z-10 mx-auto max-w-6xl px-4">
|
<div class="relative z-10 mx-auto max-w-6xl px-4">
|
||||||
{% if heading %}<h2 class="terminal-heading text-center text-3xl font-semibold tracking-tight md:text-4xl" data-text="{{ heading }}">{{ heading }}</h2>{% endif %}
|
{% if heading %}<h2 class="terminal-heading text-center text-3xl font-semibold tracking-tight md:text-4xl" data-text="{{ heading }}">{{ heading }}</h2>{% endif %}
|
||||||
{% if intro %}<p class="mx-auto mt-4 max-w-2xl text-center text-lg text-muted-foreground">{{ intro }}</p>{% endif %}
|
{% if intro %}<p class="mx-auto mt-4 max-w-2xl text-center text-lg text-muted-foreground">{{ intro }}</p>{% endif %}
|
||||||
<div class="mt-12 grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
|
<div class="mt-10 tty-grid-3">
|
||||||
{% for tier in tiers %}
|
{% for tier in tiers %}
|
||||||
<div class="tty-corners relative flex flex-col rounded-md border p-6 {% if tier.highlighted %}border-primary bg-card text-card-foreground tty-frame ring-1 ring-primary{% else %}border-primary/40 bg-card text-card-foreground tty-frame{% endif %}">
|
<div class="tty-corners relative flex flex-col rounded-md border p-6 {% if tier.highlighted %}border-primary bg-card text-card-foreground tty-frame ring-1 ring-primary{% else %}border-primary/40 bg-card text-card-foreground tty-frame{% endif %}">
|
||||||
{% if tier.badge %}<span class="terminal-mono absolute -top-3 left-1/2 -translate-x-1/2 rounded-none bg-primary px-3 py-1 text-xs font-semibold uppercase tracking-widest text-primary-foreground">{{ tier.badge }}</span>{% endif %}
|
{% if tier.badge %}<span class="terminal-mono absolute -top-3 left-1/2 -translate-x-1/2 rounded-none bg-primary px-3 py-1 text-xs font-semibold uppercase tracking-widest text-primary-foreground">{{ tier.badge }}</span>{% endif %}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
{# stats terminal override: scanline overlay, heading, HUD stat tiles, mono labels. data-stats + countUp script/attrs preserved byte-for-byte. #}
|
{# stats terminal override: scanline overlay, heading, HUD stat tiles, mono labels. data-stats + countUp script/attrs preserved byte-for-byte. #}
|
||||||
<section class="relative overflow-hidden py-16 md:py-24 bg-background text-foreground{% if class %} {{ class }}{% endif %}"{% if countUp %} data-stats{% endif %}>
|
<section class="relative overflow-hidden py-12 md:py-20 bg-background text-foreground{% if class %} {{ class }}{% endif %}"{% if countUp %} data-stats{% endif %}>
|
||||||
<div aria-hidden="true" class="tty-scanlines pointer-events-none absolute inset-0"></div>
|
<div aria-hidden="true" class="tty-scanlines pointer-events-none absolute inset-0"></div>
|
||||||
<div class="relative z-10 mx-auto max-w-6xl px-4">
|
<div class="relative z-10 mx-auto max-w-6xl px-4">
|
||||||
{% if heading %}<h2 class="terminal-heading text-center text-3xl font-semibold tracking-tight md:text-4xl" data-text="{{ heading }}">{{ heading }}</h2>{% endif %}
|
{% if heading %}<h2 class="terminal-heading text-center text-3xl font-semibold tracking-tight md:text-4xl" data-text="{{ heading }}">{{ heading }}</h2>{% endif %}
|
||||||
{% if intro %}<p class="mx-auto mt-4 max-w-2xl text-center text-lg text-muted-foreground">{{ intro }}</p>{% endif %}
|
{% if intro %}<p class="mx-auto mt-4 max-w-2xl text-center text-lg text-muted-foreground">{{ intro }}</p>{% endif %}
|
||||||
<dl class="mt-12 grid grid-cols-2 gap-8 {% if columns == 2 %}md:grid-cols-2{% elif columns == 3 %}md:grid-cols-3{% else %}md:grid-cols-4{% endif %}">
|
<dl class="mt-10 tty-grid-stats{% if columns == 2 %}2{% elif columns == 3 %}3{% else %}4{% endif %}">
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
<div class="tty-corners text-center">
|
<div class="tty-corners text-center">
|
||||||
<dd class="terminal-heading text-4xl font-bold tracking-tight md:text-5xl" style="font-family:var(--font-heading)">{% if item.prefix %}{{ item.prefix }}{% endif %}<span{% if countUp %} data-countup-value="{{ item.value }}"{% endif %}>{{ item.value }}</span>{% if item.suffix %}{{ item.suffix }}{% endif %}</dd>
|
<dd class="terminal-heading text-4xl font-bold tracking-tight md:text-5xl" style="font-family:var(--font-heading)">{% if item.prefix %}{{ item.prefix }}{% endif %}<span{% if countUp %} data-countup-value="{{ item.value }}"{% endif %}>{{ item.value }}</span>{% if item.suffix %}{{ item.suffix }}{% endif %}</dd>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user