diff --git a/src/lib/ae_events/types/ae_badge_template_cfg.ts b/src/lib/ae_events/types/ae_badge_template_cfg.ts
index 14905488..0aca69e5 100644
--- a/src/lib/ae_events/types/ae_badge_template_cfg.ts
+++ b/src/lib/ae_events/types/ae_badge_template_cfg.ts
@@ -39,10 +39,19 @@ export interface BadgeTemplateCfg {
// Header image vertical offset. CSS length applied as margin-top on the badge_header div.
// Default (unset) = "2rem" (matches the prior hardcoded mt-8).
// Negative values shift the image toward the top edge; larger values push it down.
- // Useful when a background image's designed zone doesn't align with the default position.
// Any CSS length works: "-0.5in", "1rem", "8px".
header_margin_top?: string;
+ // Border drawn below the badge header image. Set header_border_color to enable.
+ // Unset = no border (default). Any valid CSS hex color.
+ header_border_color?: string;
+ // Thickness of the header bottom border. Any CSS length. Default "2px" when color is set.
+ header_border_width?: string;
+ // Padding below the header image (inside the badge_header div, above the border).
+ // Useful for creating visual space between the image and the body.
+ // Any CSS length: "0.5in", "1rem". Unset = no extra padding.
+ header_padding_bottom?: string;
+
// Allow arbitrary extra keys to preserve forward-compatibility.
[key: string]: any;
}
diff --git a/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_obj_view.svelte b/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_obj_view.svelte
index ae1aec53..81a5d268 100644
--- a/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_obj_view.svelte
+++ b/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_obj_view.svelte
@@ -326,6 +326,21 @@ let header_margin_top = $derived.by(() => {
return v && typeof v === 'string' && v.trim() ? v.trim() : '2rem';
});
+// Full inline style string for the badge_header div.
+// Combines margin-top, optional bottom border (color + width), and optional bottom padding.
+// Unset border_color = no border drawn.
+let header_div_style = $derived.by(() => {
+ const parts: string[] = [`margin-top: ${header_margin_top}`];
+ const color = (template_cfg?.header_border_color ?? '').trim();
+ if (color) {
+ const width = (template_cfg?.header_border_width ?? '').trim() || '2px';
+ parts.push(`border-bottom: ${width} solid ${color}`);
+ }
+ const pb = (template_cfg?.header_padding_bottom ?? '').trim();
+ if (pb) parts.push(`padding-bottom: ${pb}`);
+ return parts.join('; ');
+});
+
/**
* Layout-aware section heights for Element_fit_text.
*
@@ -676,7 +691,7 @@ const code_to_icon: {
p-2
hover:outline-2 hover:outline-gray-500/75 hover:outline-dashed
"
- style="margin-top: {header_margin_top};">
+ style={header_div_style}>
Header Bottom Border
+ + + +