Skip to content

T 159


uid: T-159 title: Invoice β€” discount label made layout-neutral + debug-overlay geometry accuracy (rename, box edges, px readouts) status: done area: invoice created: 2026-07-04 updated: 2026-07-05 related: T-153


Why (owner, 2026-07-04)

Five requests after reviewing the project-invoice render and its Grid & Flex Box debug overlay (flexDebug). Owner asked for a read-back before implementation; scope confirmed via Q&A:

"a) keep the line item discount unchanged, but b) also revert the line item heigh back to it's configuration before the adding of the line item discount because the adding of that shouldn't affect the general height of a line item" … "If an item has one line of item title, one line of fee type, adding the line item discount should've change nothing" (Q1 answer: the invoice document itself)

"Rename Branding to Header (or is it named header so to not get confused with the the Header in the second page of invoice version A?)" … (Q3 answer:) "we could do 'Branding' β†’ 'Header', while 'Header' β†’ 'Header (Cont.)' for header for continuation page"

"The bottom of the (currently) Branding flex box should align with the current position of the bottom of the subsidiary's Chinese name" Β· "Same with the Client flex box … The upper border of the flex box should align with the top of 'BILL TO' (with BILL TO:'s position unchanged)" (Q2 answer: Version A only)

"Line item (Item ), beforeTotal, Total Box … should display height in px like preItem and betweenItems" (Q4 answer: + the invoice-level discount block)*

Verified facts (before making the move)

  • The discount label (T-153) never changed the item's physical height. The label lives inside the line-total cell (column N), which is fixed-height (titleRowHeight + 24) with overflow: hidden. Replicated the exact grid in headless Chromium: an item measures 62px with or without the label (rows 38+24). What DID change: the total + label were centered as a pair, so the total sat ~1–9px higher than pre-discount (measured 1px in the minimal replica; scales with label height). The other two discount surfaces (status-panel sidebar cards; project-page table chip) DO grow β€” owner confirmed those are out of scope here.
  • Debug label "Header" was used only by the continuation-page header; "Branding" named the page-1 logo+subsidiary box in both composed headers (A + B). No same-page collision either way.
  • Version A geometry: subsidiary names = 42px cell (rows 5–6), top-aligned, text block measured 28.78px (16px English + 12.8px Chinese at line-height 1.2) β†’ ~13px tinted slack under the Chinese name. "BILL TO:" = 8pt Google Sans Mono, line box measured 13px, middle-aligned in a 42px cell β†’ 14.5px tinted headspace above the text.
  • Grid rows are auto-sized from cell heights (gridTemplateRows deliberately unset), and a grid item's margin counts toward track sizing β€” so trimming a cell with marginTop: m; height: Hβˆ’m keeps its row contribution at H while moving the tinted edge. This is what makes the box-edge fixes geometry-neutral.

What changed (all verified in headless Chromium before landing)

  1. ItemRow.tsx β€” discount label layout-neutral. The label now sits in a zero-height overflow: visible wrapper, so it no longer participates in the flex centering: the total renders at the exact pixel it had before line-item discounts existed (totalTop identical with/without label, SAME=true in the measurement run), and the label text overflows downward tucked beneath it, still inside the cell (bottom 61.1px < 62px cell). An item with one title line + one fee-type line is byte-identical in height and total-position to the pre-discount render.
  2. Renames. Branding β†’ Header (both InvoiceHeaderFullComposed*.tsx); continuation-page Header β†’ Header (Cont.) (InvoicePage.tsx). The name feeds only the overlay label text and a quoted CSS attribute value β€” parens/dots are safe.
  3. Version A Header box bottom = Chinese name bottom (HeaderBrandingVersionA.tsx). Names cell height 42 β†’ 31px (measured 28.78 + 2px padding); still spans rows 5–6 top-aligned so the text doesn't move; the A-I fillers keep holding the 21px rows but are excluded from the tint via a new debug-untinted escape hatch (higher-specificity CSS rule in both composed headers' wrapper); a debug-only A-I filler at 31px squares the box's bottom edge across the full width.
  4. Version A Client box top = "BILL TO:" top (ClientInfoSection.tsx, gated variant === 'A'; variant B byte-identical). BILL TO cell: marginTop: 14.5px, height βˆ’14.5, vAlign middleβ†’top with the FlexCell 2px padding zeroed β€” text pixels unchanged, tinted edge now starts at the text top. The E-N row-1 companion cell trimmed identically so the box top is straight across.
  5. px readouts (InvoicePage.tsx + new getItemRowTotalHeight() export from ItemRow.tsx): Item N: {h}px (title row + 24 + notes rows β€” same functions ItemRow renders with), beforeTotal: {21|42}px, Total Box: {sum}px, beforeDiscount: 21px, Discount: 21px β€” matching the existing preItem/betweenItems/afterTotal format.

Decision log

2026-07-04 β€” opened, implemented, merged

  • βœ… Attestation (Document Rendering Fine-Tuning): read AGENTS.md; scope-scanned the board β€” the discount rendering is T-153 (done, other agent); this is new corrective/overlay work β†’ T-159.
  • Source: Document Rendering Fine-Tuning Β· https://claude.ai/code/session_01A2tdTGEeYDMDVhrceFpJ8D
  • Proposed by: the owner (5-item request). Approved by: the owner β€” read-back confirmed with Q1–Q4 answers quoted above before any code was touched.
  • Type-check gate: npm ci + unfiltered NODE_OPTIONS=--max-old-space-size=8192 npx tsc --noEmit β†’ clean (exit 0) β€” first change this session where the full gate could actually run.
  • Verification: headless-Chromium measurement harness (grid replica) proved the discount fix (SAME=true) and produced the 28.78px / 13px / 14.5px constants used in the geometry fixes.
  • Deploy: NOT deployed β€” merged only, per the 🟑🟑 manual-deploy policy and the owner's standing instruction that deploys happen only on their explicit "deploy".
  • Blast radius: invoice document render (lib/invoice) only β€” the N-column discount label's visual position (total restored to pre-discount pixel; label unmoved visually), debug-overlay labels/boxes (flexDebug-only), and Version A's BILL TO/subsidiary-name cell geometry (text pixels unchanged; margin+height trims keep grid-track contributions identical β€” verified reasoning documented above). Variant B and quotations byte-identical except the shared renames. Status-panel sidebar and project-page discount chips untouched (owner: out of scope). T-153's math/label content untouched.
  • Commits (append-only): 874e9171 (all five items) Β· 08ca4a17 (merge of PR #863 into main).

2026-07-05 β€” follow-up: true single-line item height + centered amount/discount pair

  • βœ… Attestation (Codex local session): read AGENTS.md; scope-scanned the board β€” this is a corrective follow-up to T-159/T-153, not a new task.
  • Owner report: a one-line title + one-line fee-type item with a line discount still rendered as 70px, while the expected normal height is 62px.
  • Diagnosis: the discount label was already not part of row-height calculation, but ItemRow.getTitleLayout() still added +8px / +12px for reduced-font single-line titles. The example title "Live Performed Lead Vocal Editing" crossed that threshold, so the title row became 46px and the item total became 70px (46 + 24). That made the symptom look discount-related because this was the discounted line.
  • What changed: single-line titles now keep the base 38px title row even when reduced to 17pt or 15.5pt; only genuinely wrapped titles increase height. rowHeightsCalculator.ts was aligned with ItemRow.tsx so debug/readout math matches render math.
  • Amount-cell alignment: reverted from centering only the amount with a zero-height discount label to centering the amount+discount stack as a pair inside the fixed 62px cell. This keeps the discount label from affecting item height while satisfying the owner preference that the amount plus discount sit height-wise in the middle of the line item box.
  • Design note: recommended future display for material discounts is smaller struck-through gross amount above the main discounted amount, with the discount label under it. Not implemented pending owner approval. Static comparison mockup: docs/eop-tasks/assets/t159-discount-display-demo.svg.
  • Source: Codex local session Β· /Users/gutchumi/dev/ArtifactoftheEstablisher.

2026-07-05 β€” follow-up: no browser word-wrap + gross/net discount display

  • βœ… Attestation (Codex local session): read AGENTS.md; scope-scanned the board β€” this remains the T-159 invoice-rendering follow-up.
  • Owner report: after the first follow-up was deployed, the row height was fixed at 62px, but the title still wrapped unnecessarily and discounted lines showed only the net amount in the normal line-amount style.
  • Diagnosis: getTitleLayout() classified the title as single-line, but the title span still used whiteSpace: normal, so the browser could wrap at word boundaries anyway. The amount cell also rendered only lineTotal, so the original gross amount was unavailable visually.
  • What changed: single-line titles now render with whiteSpace: nowrap; wrapping is enabled only when getTitleLayout() marks the title as wrapped. Discounted line amounts now render as a compact stack inside the fixed column-N cell: struck-through gross amount, net amount, and the discount label. The main net amount is slightly reduced only for discounted lines so the three-line stack fits inside the unchanged 62px row.
  • Source: Codex local session Β· /Users/gutchumi/dev/ArtifactoftheEstablisher.

2026-07-05 β€” follow-up: restore title shrink-before-wrap thresholds

  • βœ… Attestation (Codex local session): read AGENTS.md; scope-scanned the board β€” this remains the T-159 invoice-rendering follow-up.
  • Owner report: title wrapping should still be allowed, but only after the prior shrink-first rules have reduced title font size.
  • Diagnosis: the shrink-before-wrap rules still existed structurally, but the 2026-07-05 height fix raised the thresholds from the earlier A-H-safe 32 / 38 / 42 characters to 45 / 50 / 55. A 35-character title therefore stayed at 19pt and wrapped naturally before it ever reached the intended 17pt reduction. The later nowrap patch hid the symptom but also disabled the intended wrap path.
  • What changed: restored the conservative A-H thresholds (32 / 38 / 42) in both ItemRow.tsx and rowHeightsCalculator.ts, kept the 38px single-line title row for reduced-font titles, and restored natural wrapping in the title span. Result: medium titles shrink first; only titles beyond the 15.5pt threshold wrap and expand.
  • Source: Codex local session Β· /Users/gutchumi/dev/ArtifactoftheEstablisher.

2026-07-05 β€” follow-up: restore full 16pt font size for discounted totals

  • βœ… Attestation (Gemini CLI local session): read AGENTS.md; scope-scanned the board β€” this remains the T-159 invoice-rendering follow-up.
  • Owner report: requested that the discounted total amount (net amount) should remain at the full 16pt size (the same size as when rendered normally), rather than being reduced to 13pt.
  • What changed: modified ItemRow.tsx line-total font size so that the discounted net total always renders at the full 16pt font size. All other supporting rows (struck-through gross amount and italic discount label) fit perfectly within the unchanged 62px line-item box.
  • Source: Gemini CLI local session Β· /Users/gutchumi/.gemini/tmp/artifactoftheestablisher.

2026-07-05 β€” follow-up: style line-total components (centered net total, gross total and red discount label on row 2 grouped by ' // ')

  • βœ… Attestation (Gemini CLI local session): read AGENTS.md; scope-scanned the board β€” this remains the T-159 invoice-rendering follow-up.
  • Owner report: requested a highly optimized and compact centered double-row rendering for discounted lines: (1) discounted net total centered on top at normal 16pt size, (2) struck-through italic gross total on the left and red italic discount label on the right grouped together on the bottom line, separated by a " // " mark.
  • What changed: modified ItemRow.tsx so that:
  • Net total is rendered on top at the prominent 16pt font size.
  • Gross total (9px, italic, struck-through) and the discount label (9px, italic, red) are rendered side-by-side on the second row, separated cleanly by " // " with a 4px gap.
  • Both rows are perfectly centered horizontally and vertically inside column N's cell.
  • Source: Gemini CLI local session Β· /Users/gutchumi/.gemini/tmp/artifactoftheestablisher.

2026-07-05 β€” follow-up: TotalBox rightmost offset padding

  • βœ… Attestation (Gemini CLI local session): read AGENTS.md; scope-scanned the board β€” this remains the T-159 invoice-rendering follow-up.
  • Owner report: requested a rightwards border offset for right-aligned items inside the TotalBox (Chinese words, English words, and the numeric total) to prevent them from touching the border too closely (refined from 3px to 6px), and enquired whether the Chinese words are currently bold.
  • What changed:
  • Verified that the Chinese amount is indeed rendered bold (specifically styled with fontWeight: 700).
  • Added paddingRight: '6px' to all three rightmost flex cells (Chinese total row, numeric total row, and English total row) inside TotalBox.tsx to give them a visually balanced, safe 6px breathing margin from the solid black right border.
  • Source: Gemini CLI local session Β· /Users/gutchumi/.gemini/tmp/artifactoftheestablisher.