From 26fde2a5662d700a9f001149f9d43bf4f9a52cd7 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Fri, 15 May 2026 15:26:13 -0400 Subject: [PATCH] =?UTF-8?q?feat(badges):=20add=204=C3=976=20fanfold=20layo?= =?UTF-8?q?ut=20CSS=20for=20Epson=20single-sided=20stock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduces badge_layout_epson_4x6_fanfold.css (layout code badge_4x6_fanfold) for the Axonius Adapt 2026 June show. Wires @page size to 4in×6in in the print page and cleans up the stale 4in×12in default. Imports new CSS in badge component. Measured stock: 4in × 6in portrait with 5/8in lanyard hole 1/4in from top. Co-Authored-By: Claude Sonnet 4.6 --- .../MODULE__AE_Events_Badge_Templates.md | 5 +- .../css/badge_layout_epson_4x6_fanfold.css | 63 +++++++++++++++++++ .../[badge_id]/ae_comp__badge_obj_view.svelte | 1 + .../badges/[badge_id]/print/+page.svelte | 6 +- 4 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 src/lib/ae_events/badges/css/badge_layout_epson_4x6_fanfold.css diff --git a/documentation/MODULE__AE_Events_Badge_Templates.md b/documentation/MODULE__AE_Events_Badge_Templates.md index c362003a..6ffd2fb0 100644 --- a/documentation/MODULE__AE_Events_Badge_Templates.md +++ b/documentation/MODULE__AE_Events_Badge_Templates.md @@ -180,7 +180,7 @@ The `layout` field encodes physical badge stock dimensions. Standard codes to us | --- | --- | --- | --- | | `badge_4x5_fanfold` | 4" × 5" (101.6 × 127mm) | `badge_layout_epson_4x5_fanfold.css` | Epson ColorWorks C3500 / ExpoBadge fanfold — preferred for general conference use (ISHLT, demos) | | `badge_3.5x5.5_pvc` | 3.5" × 5.5" (88.9 × 139.7mm) | `badge_layout_zebra_zc10l_pvc.css` | PVC card, Zebra ZC10L — single-sided, set `duplex=0` | -| `badge_4x6_fanfold` | 4" × 6" (101.6 × 152.4mm) | *(none — Tailwind defaults)* | Generic fanfold fallback; dimensions match the hardcoded Tailwind values | +| `badge_4x6_fanfold` | 4" × 6" (101.6 × 152.4mm) | `badge_layout_epson_4x6_fanfold.css` | Single-sided fanfold; Axonius Adapt 2026 (June 2026). Lanyard hole: 5/8in × 1/8in, centered, 1/4in from top. | | `badge_4x6_fanfold_tickets` | 4" × 6" + tear-offs | *(pending)* | Fanfold with ticket stubs | Layout CSS files live in `src/lib/ae_events/badges/css/` and are imported by @@ -359,6 +359,7 @@ Firefox users can use "Save to PDF" directly — it just works. - [x] Wire `style_href` via `` in print page — done in `print/+page.svelte`; also in `properties_to_save`. (2026-03-18 verified) - [x] Add `duplex` to `properties_to_save` — done. (2026-03-18 verified) - [x] Add `duplex`-driven suppression to `badge_back` section — done in `ae_comp__badge_obj_view.svelte`; `show_badge_back` derived from `duplex` field. -- [ ] Make `layout` field drive actual card dimensions in the badge component — currently the Zebra ZC10L layout CSS (`badge_layout_zebra_zc10l_pvc.css`) sets dimensions correctly via `[data-layout="..."]` scoping, but fanfold layouts still use Tailwind defaults. Needs proper CSS for each layout code. +- [x] `badge_4x6_fanfold` layout CSS created (`badge_layout_epson_4x6_fanfold.css`), imported in badge component, `@page 4in 6in` wired in print page. (2026-05-15) +- [ ] `badge_4x5_fanfold` layout CSS exists but is stale (not used in 2+ years) — review against actual hardware before next use. - [ ] Remove dead `exhibitor_info` / `presenter_info` / `staff_info` / `vip_info` / `vote_info` `{#if}` blocks from `ae_comp__badge_obj_view.svelte` (if they were carried over from v1) - [ ] Improve `ae_comp__badge_template_form.svelte` to edit all relevant fields (currently minimal) diff --git a/src/lib/ae_events/badges/css/badge_layout_epson_4x6_fanfold.css b/src/lib/ae_events/badges/css/badge_layout_epson_4x6_fanfold.css new file mode 100644 index 00000000..502252e3 --- /dev/null +++ b/src/lib/ae_events/badges/css/badge_layout_epson_4x6_fanfold.css @@ -0,0 +1,63 @@ +/* ============================================================================= + Badge Layout: Epson ColorWorks — Fanfold 4" × 6" (Single-sided) + layout code: badge_4x6_fanfold + Badge stock: 4in wide × 6in per label, single-sided continuous fanfold + Used for: Axonius Adapt 2026 (June 2026) + + Physical notes (measured 2026-05-15): + Overall: 4.0in × 6.0in (portrait) + Lanyard hole: 5/8in wide × 1/8in tall, centered horizontally, + 1/4in from top edge, 3/8in from each side edge. + Keep decorative header content below the hole zone (~3/8in from top). + + Print behavior: + Single-sided only. Set duplex=0 on the template — the badge_back section + will not render at all. @page size (4in × 6in) is injected dynamically + by print/+page.svelte based on the layout field. + + CSS scope: + All rules scoped under [data-layout="badge_4x6_fanfold"] to avoid conflicts + with other layouts compiled into the same bundle. These override the + Tailwind utility classes (w-[4in], min-h-[6.0in], etc.) hardcoded on the + badge sections — attribute + class selectors win over single class selectors. + ============================================================================= */ + +/* --- Badge front --- */ + +[data-layout='badge_4x6_fanfold'] .badge_front { + min-width: 4in; + width: 4in; + min-height: 6in; + max-height: 6in; + + /* debug */ + /* outline: thick solid orange; */ +} + +/* Body area: 6in total − ~1in header − ~0.5in footer ≈ 4.5in for content */ +[data-layout='badge_4x6_fanfold'] .badge_body { + max-height: 4.5in; +} + +/* Outer wrapper: strip the default padding/gap so the outline hugs the badge. + badge_front above supplies the exact 4×6in card size. */ +[data-layout='badge_4x6_fanfold'].event_badge_wrapper { + padding: 0; + gap: 0; + min-height: 0; + min-width: 4in; + width: 4in; + max-width: 4in; +} + +@media print { + [data-layout='badge_4x6_fanfold'].event_badge_wrapper { + width: 4in !important; + height: 6in !important; + max-width: 4in !important; + max-height: 6in !important; + /* overflow: visible so any intentional bleed element is not clipped by the + wrapper — the Epson driver clips at the physical label edge. */ + overflow: visible !important; + } +} 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 a9f5abc3..642c5a28 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 @@ -72,6 +72,7 @@ let { // Each file scopes rules under [data-layout="..."] on the wrapper section. // @page rules (paper size) are injected per-template in print/+page.svelte. import '$lib/ae_events/badges/css/badge_layout_epson_4x5_fanfold.css'; +import '$lib/ae_events/badges/css/badge_layout_epson_4x6_fanfold.css'; import '$lib/ae_events/badges/css/badge_layout_zebra_zc10l_pvc.css'; import { untrack } from 'svelte'; diff --git a/src/routes/events/[event_id]/(badges)/badges/[badge_id]/print/+page.svelte b/src/routes/events/[event_id]/(badges)/badges/[badge_id]/print/+page.svelte index c49a171b..976d0fac 100644 --- a/src/routes/events/[event_id]/(badges)/badges/[badge_id]/print/+page.svelte +++ b/src/routes/events/[event_id]/(badges)/badges/[badge_id]/print/+page.svelte @@ -293,8 +293,10 @@ let page_size_css = $derived( $lq__event_badge_template_obj?.layout === 'badge_3.5x5.5_pvc' ? '3.5in 5.5in' : $lq__event_badge_template_obj?.layout === 'badge_4x5_fanfold' - ? '4in 10in' - : '4in 12in' // Default: badge_4x6_fanfold or layout not yet set + ? '4in 10in' // duplex fanfold: 5in front + 5in back = 10in strip + : $lq__event_badge_template_obj?.layout === 'badge_4x6_fanfold' + ? '4in 6in' // single-sided fanfold: front only + : '4in 6in' // fallback: unknown layout, assume single-sided 4×6 ); // @page size + optional per-template margin override from cfg_json.print_margin. // print_margin_cfg is parsed from the template's cfg_json field — allows per-event