docs(badges): update print behavior docs + Zebra test day plan

- MODULE__AE_Events_Badge_Templates: rewrite Print Layout Architecture
  section with accurate cross-browser behavior table and Chrome margin
  guidance
- PROJECT__AE_Events_Badges_Review_Print: add TASK 4.1 print CSS
  centering history; correct Chrome squish root cause explanation
- PROJECT__AE_Events_Zebra_Hardware_Test_Day: new — comprehensive
  pre-test and day-of checklists for ZC10L hardware test ~2026-03-16
- TODO__Agents: add [Badges] Zebra ZC10L Hardware Testing section
This commit is contained in:
Scott Idem
2026-03-12 19:23:47 -04:00
parent cfa9e85d05
commit 90615ad5cc
4 changed files with 299 additions and 11 deletions

View File

@@ -261,14 +261,19 @@ in DB and may be needed:
### How the print CSS works
The print page (`print/+page.svelte`) injects `<style>` blocks into `<svelte:head>` that
take effect only in `@media print`. The strategy uses `display: contents` to dissolve
intermediate layout wrappers so `body` becomes the sole centering flex container.
take effect only in `@media print`. Multiple layers of the SvelteKit layout chain must
be neutered to get a clean print surface.
**Wrappers dissolved via `display: contents`:**
**`#ae_main_content` — cannot dissolve, must passthrough:**
`#ae_main_content` has `overflow: auto` (it is the events layout scroll container). CSS
spec prohibits `display: contents` from overriding elements with overflow clipping —
Firefox enforces this strictly, Chrome is lenient. Workaround: strip all its visual/layout
effects with explicit `display: block; overflow: visible; position: static; width: 100%`.
**Wrappers dissolved via `display: contents` (safe — no overflow constraints):**
| Selector | Source | Why dissolved |
|---|---|---|
| `#ae_main_content` | `events/+layout.svelte` | `overflow-auto`, `flex-col`, `max-w-7xl`, `bg-gray-50` |
| `.main_content` | `events/+layout.svelte` | `pb-48`, `pt-20+`, `grow`, `items-center`, `justify-start` |
| `.main_content` | `events/+layout.svelte` | `pb-48`, `pt-20+`, `grow` |
| `#badge_render_area` | `print/+page.svelte` | Screen-only right-padding offset for controls panel |
**App chrome hidden via `print:hidden`:**
@@ -280,12 +285,10 @@ intermediate layout wrappers so `body` becomes the sole centering flex container
- Debug info section (edit mode only)
- Root layout: offline banner, session expired banner, hydration overlay, sys/debug menus
**Result:** `body { display: flex; align-items: center; justify-content: center }` directly
centers `section.event_badge_wrapper` with no intermediate wrappers in the way.
**`@page` size:** Matched to badge stock per layout code. `margin: 0` fills the page.
For the PVC layout the page size equals the card exactly, so centering is redundant
but harmless. For layouts where stock ≠ page, centering positions the badge correctly.
**Badge centering — `position: fixed`:**
`.event_badge_wrapper` uses `position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%)`.
In print, `position: fixed` anchors relative to the `@page` content area, bypassing the entire
ancestor hierarchy (no containing-block height dependency, no overflow-clip interference).
**Future per-template margins:** `print_margin_cfg` is already parsed from `cfg_json`
in `print/+page.svelte`. A dynamic `@page { margin: ... }` injection can be built from
@@ -293,6 +296,50 @@ that value when a UI for it exists.
---
### Cross-browser print behavior — IMPORTANT
Verified 2026-03-12 by comparing print-to-PDF output from both browsers across multiple
print dialog settings.
#### `@page { size }` — paper size
| Browser | Save to PDF | Physical printer |
|---|---|---|
| **Firefox** | Paper size locked — cannot change in dialog; CSS `@page { size }` used ✅ | Can select paper size in dialog |
| **Chrome/Chromium** | Paper size locked — cannot change in dialog; uses system default (letter, A4, etc.) ❌ | Can select paper size under "More settings" |
Chrome intentionally does not honor `@page { size }` for Save as PDF. It uses the system
default paper size. This is a Chrome design decision, not a bug in our code.
For actual printing to Epson/Zebra hardware: the printer driver controls paper size from
the loaded badge stock. CSS `@page { size }` is advisory only. Real badge printing is
unaffected by Chrome's behavior.
Use Firefox for accurate print-to-PDF proofing — it produces a correctly-sized PDF that
matches the badge stock dimensions exactly.
#### Margins — Chrome "Default" causes layout problems
| Chrome margin setting | Result |
|---|---|
| **Default** | ❌ Adds URL, date, and page-number headers/footers into the printable area. These eat into the space that `position: fixed; top: 50%` references, making the badge appear off-center or clipped against the footer. |
| **None** | ✅ Correct — badge centered cleanly |
| **Minimum** | ✅ Correct — small margins, badge still centered |
| **Custom (reasonable values)** | ✅ Correct |
The badge content itself is **not** distorted. Verified: Chrome "None" margins on an A4
page produces the badge perfectly horizontally centered (page center 297.5 pts, badge
content center 297.5 pts). The CSS centering logic is correct.
**Staff guidance for Chrome:**
- Set **Margins → None** (or Minimum) in Chrome's print dialog.
- Optionally set paper size to match badge stock under "More settings" when printing to PDF.
- For physical printer: select correct paper size under "More settings".
Firefox users can use "Save to PDF" directly — it just works.
---
## Related Files
| File | Role |

View File

@@ -129,6 +129,28 @@ should be the reference. See Design Intent section above.
Pronouns field is now an attendee-level field (was trusted-only). Staff section labelled.
- Debug JSON blocks in v2 badge render hidden behind global edit_mode flag.
**Print page CSS centering work (also 2026-03-12) — ⚠️ Chromium PDF issue pending:**
Multiple iterations to center the badge on the printed page, working around SvelteKit layout
hierarchy issues. Current approach: `position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%)`
on `.event_badge_wrapper`. Key findings:
- `#ae_main_content` has `overflow: auto` — Firefox (spec-compliant) won't let `display: contents`
dissolve it. Workaround: explicit passthrough block (`display: block; overflow: visible; width: 100%`).
- `app.css` global `overflow: hidden` on `html, body` creates a BFC that collapses body to badge-width.
Override with `overflow: visible !important` in print CSS.
- **Chrome ignores `@page { size }` for Save as PDF** — verified 2026-03-12. Firefox honors it.
Chrome uses the system default paper size; Firefox locks to the CSS `@page { size }` value.
Neither browser lets you change paper size in "Save to PDF" mode — only when printing to a
physical printer. For actual Epson/Zebra printing, the driver controls paper size; unaffected.
- **Chrome "Default" margins cause the "squish"** — Chrome's Default margin setting inserts
URL/date/page-number headers and footers into the printable area. These eat into the space
that `position: fixed; top: 50%` references, making the badge off-center or clipped. Fix:
set **Margins → None** (or Minimum) in Chrome's print dialog. Content centering verified
correct: Chrome A4 + None margins produces badge center = 297.5 pts on a 297.5 pt wide page.
Use Firefox for accurate PDF proofing.
- See `documentation/MODULE__AE_Events_Badge_Templates.md` → "Print Layout Architecture" for full
technical details.
### ✅ TASK 3: Badge Print Controls Panel — COMPLETE (2026-03-02)
**Files created/modified:**

View File

@@ -0,0 +1,200 @@
# PROJECT: Zebra ZC10L Hardware Test Day
**Created:** 2026-03-12
**Planned date:** ~week of 2026-03-16 (printer rented for one day)
**Hardware:** Zebra ZC10L, 3.5" × 5.5" PVC card stock
**Goal:** Validate real-world badge printing before Axonius (NYC, mid-April 2026)
**Owner:** Scott Idem / One Sky IT
---
## Before the Printer Arrives — Pre-Test Checklist
These must be done before the printer is on-site so you're not burning rental time on setup.
- [ ] **Remove debug outlines** from `print/+page.svelte` print CSS.
The lime/blue/red/orange/purple/cyan debug outlines are still in the file. Remove the
entire `TEMPORARY DEBUG OUTLINES` block. Commit before the test day.
- [ ] **Zebra ZC10L Linux driver** — install CUPS driver ahead of time.
- Check Zebra's site for the Linux CUPS driver for ZC10L.
- Install, configure in CUPS (`http://localhost:631`), do a test page print with a spare card.
- Confirm the card feeds without jam and ink/dye-sub layer applies cleanly.
- Driver may need the printer set to the correct card stock size (3.5" × 5.5").
- [ ] **Wire `style_href`** — add `<link rel="stylesheet" href={...}>` to `<svelte:head>` in
`print/+page.svelte` when `$lq__event_badge_template_obj?.style_href` is set.
Without this, any client-specific external CSS won't load.
See `documentation/MODULE__AE_Events_Badge_Templates.md` → "External CSS Approach".
- [ ] **Confirm single-sided print (duplex=0)**`duplex` backend field doesn't exist yet.
For PVC cards, the badge back must NOT print. Verify this works by checking that
`.badge_back` is hidden in `@media print` when the layout is `badge_3.5x5.5_pvc`.
The PVC CSS (`badge_layout_zebra_zc10l_pvc.css`) may already handle this — confirm.
If not, add a print rule: `[data-layout="badge_3.5x5.5_pvc"] .badge_back { display: none !important; }`
- [ ] **Test event + template in dev DB** — create/confirm:
- Event with `mod_badges_json` configured
- PVC template: `layout: badge_3.5x5.5_pvc`, `duplex: 0` (once backend supports it),
`header_path` set to a real image URL, `badge_type_list` JSON populated
- Test badge records (see "Test Data Set" below)
- [ ] **Test data set** — create badge records covering:
- Short name: "Kim Lee"
- Long name: "Bartholomew Vandenberghe-Christopoulos"
- HTML in name: `<b>Dr.</b> Patricia Adams`
- HTML in affiliations: `University of Minnesota<br>Dept. of Surgery`
- Badge with no affiliations, no location
- Badge with all 8 ticket codes set
- Three different badge_type_codes (e.g. member, staff, guest) — to verify footer
stripe color for each
- [ ] **Browser setup on kiosk machine** — confirm Chrome and Firefox both installed.
Test print dialog settings once driver is working:
- Chrome: Margins → None (required), paper size set to 3.5×5.5 if available
- Firefox: should just work — `@page { size: 3.5in 5.5in }` is honored
---
## Test Day Checklist
### 1. Basic Print Path
- [ ] Card feeds and prints without jam
- [ ] Badge fills the card edge-to-edge (no white border, no clipping)
- [ ] Content horizontally centered on the card
- [ ] Content vertically centered on the card
- [ ] No debug outlines visible (confirm cleanup commit applied)
**Chrome:**
- [ ] Print → Margins: **None** → correct output
- [ ] Print → Margins: **Default** → bad (expected — documents the known issue)
- [ ] Print → Margins: **Minimum** → correct output
- [ ] "More settings" → paper size: does selecting 3.5×5.5 matter, or does Zebra driver override?
**Firefox:**
- [ ] Print → just works out of the box
### 2. Single-Sided PVC
- [ ] Only the front face prints — back does NOT print
- [ ] No second card ejected or blank card printed for the back
### 3. Visual Quality
- [ ] Font sizes readable at 3.5×5.5 physical scale (name, title, affiliations, location)
- [ ] Auto-scaling text (v2) — does it look natural, not crunched?
- [ ] Header image renders correctly (colors, resolution, no pixelation)
- [ ] Footer stripe color correct for each badge_type_code tested
- [ ] HTML in name/affiliations renders correctly (bold, line break, etc.)
- [ ] Badge with no affiliations — no awkward blank space
### 4. Edge Cases — Badge Content
- [ ] Long name auto-scales without overflow or clipping
- [ ] HTML markup in name field: `<b>Dr.</b>` renders bold on the physical card
- [ ] HTML line break in affiliations: two-line org renders cleanly
- [ ] Badge with no location — layout doesn't break
- [ ] Badge with all 8 ticket/option codes — back of badge (if applicable) lays out cleanly
### 5. Print Tracking
- [ ] `print_count` increments after printing via the **Print Badge** button
- [ ] `print_first_datetime` set on first print
- [ ] "Printed N×" amber chip appears in print page header after first print
- [ ] Reprint via Re-print shortcut (trusted + edit mode) does NOT increment count
- [ ] Second print via Print Badge button DOES increment count (to 2)
### 6. QR Code
- [ ] QR on printed card is scannable with a phone camera
- [ ] QR scans to the correct badge ID (test with `/events/[id]/badges` search by QR scan)
- [ ] QR on back (if `show_qr_back=1`) also scans correctly
- [ ] If `show_qr_back=0` — no QR code visible on back
### 7. Font Size Controls
- [ ] Manual font size override (+ / in controls panel) changes the badge render live
- [ ] Change is visible on the physical printed card
- [ ] Reset (↺) returns to auto-sizing
- [ ] Auto-sizing produces a reasonable default for all test names without manual adjustment
### 8. Edit Fields at Kiosk
- [ ] Badge info editable before printing: change full_name_override, verify change appears on card
- [ ] Save change → re-print → new value printed
- [ ] Cancel reverts to saved value
- [ ] Badge type dropdown changes footer stripe color on the rendered badge
---
## Known Limitations on Test Day
These are not bugs — just gaps that won't be addressed during the test day:
- **`style_href` external CSS**: Must be wired before test day (see pre-checklist). If not
done, client-specific CSS from the template won't load — fall back to default styles.
- **`duplex` backend field**: Not yet in the backend schema. Single-sided behavior depends
on the PVC CSS hiding `.badge_back` in print. Verify manually.
- **Per-template print margins (`print_margin_cfg`)**: UI doesn't exist yet. If the card
needs a physical offset for the Zebra's feed, apply a manual CSS tweak to the PVC layout
CSS file and revert after testing.
- **Kiosk attendee editing (TASK 4.0)**: Edit panel is currently trusted_access only.
Attendee self-edit at kiosk isn't finished — staff will need to do all edits on test day.
- **`@page { size }` in Chrome**: Chrome ignores the CSS page size for Save as PDF.
For physical Zebra printing the driver controls paper size — this is fine.
---
## Known Print Dialog Behavior (for reference)
| Browser | Save to PDF | Physical Printer |
|---|---|---|
| Firefox | Paper size locked to CSS `@page { size }` ✅ | Can select paper size in dialog |
| Chrome | Paper size = system default (letter/A4) ❌ | Can select paper size under "More settings" |
| Chrome Margin Setting | Result |
|---|---|
| Default | ❌ Inserts URL/date/page chrome, offsets badge centering |
| None | ✅ Badge centered correctly |
| Minimum | ✅ Badge centered correctly |
---
## Things to Note / Capture During Testing
Use this section to log observations on the day:
```
DATE: ___________
Driver version: ___________
Card stock type: ___________
CUPS printer name: ___________
Observations:
-
-
-
Font size adjustments needed:
Name default: was __px, adjusted to __px
Title default: was __px, adjusted to __px
Affiliations: was __px, adjusted to __px
Location: was __px, adjusted to __px
Physical offset needed (crop/margin): ___________
Bugs found:
-
-
```
---
## Follow-Up After Test Day
- [ ] Update font size defaults in `ae_comp__badge_print_controls.svelte` based on observations
- [ ] Note any physical margin/offset needed into `cfg_json: { print_margin: {...} }` once that UI exists
- [ ] Document driver version and CUPS config that worked in this file
- [ ] Commit any fixes, re-run `npx svelte-check`, commit clean

View File

@@ -38,6 +38,25 @@ frontend pass the location directly in the Launcher URL without the extra lookup
- **Badge print controls UX polish:** Scott has improvements in mind — TBD next session.
File: `ae_comp__badge_print_controls.svelte`.
### [Badges] Zebra ZC10L Hardware Testing — ~week of 2026-03-16
Scott is renting a Zebra ZC10L for one day to do real-world badge printing tests before
Axonius (mid-April). See `documentation/PROJECT__AE_Events_Zebra_Hardware_Test_Day.md`
for the full checklist and prep plan.
**Pre-test work (do before printer arrives):**
- [ ] **Remove debug outlines** from `print/+page.svelte` print CSS (lime/blue/red/orange/purple/cyan)
- [ ] **Zebra ZC10L Linux driver** — install CUPS driver package ahead of time; verify card prints
before burning rental time on driver setup. Check Zebra's site for Linux/CUPS driver.
- [ ] **Wire `style_href`** via `<svelte:head>` in `print/+page.svelte` — needed so client-specific
CSS loads from the template's `style_href` field. Currently tracked as pending in MODULE doc.
- [ ] **Confirm `duplex=0` hides badge back in print**`duplex` field not yet on backend;
verify badge_back is suppressed for single-sided PVC. May need a manual print CSS rule until
the backend field lands and `properties_to_save` is updated.
- [ ] **Set up test event + PVC template** in dev DB with `layout: badge_3.5x5.5_pvc`,
a few badge records with varied name lengths, HTML in fields, different badge_type_codes.
- [ ] **Test data set:** include edge cases — very long name, HTML markup in name/affiliations,
badge with no affiliations, badge with all ticket/option codes set.
### [Leads] Exhibitor Lead Scanning — NEXT MAJOR FEATURE
QR code scan at exhibitor booth → capture attendee badge data. Gated by `allow_tracking` on
the badge. Check if `documentation/MODULE__AE_Events_Leads.md` exists for full spec.