* fix(dialogs): kill horizontal overflow in dialogs and cut the worst modal copy
Overflow hardening:
- DialogTitle/DialogDescription and SheetTitle/SheetDescription get
break-words at the primitive, so long unbroken interpolated strings
(emails, product names, org numbers) can no longer widen any dialog.
- AccountCombobox's non-flat dropdown is portaled to document.body with
viewport-clamped geometry (new pure helper account-combobox-position.ts,
unit-tested), the same fix info-tooltip.tsx applies to TooltipContent:
the 34rem panel inside a scrollable DialogContent was the root cause of
sideways-scrolling dialogs. Outside-click checks the portaled node,
position tracks scroll/resize (capture phase), wheel/touchmove stop at
the panel so react-remove-scroll's modal lock cannot block its scrolling,
and DialogContent/SheetContent treat data-dialog-companion nodes as
inside interactions so clicking the panel never dismisses the dialog.
The flat variant is unchanged.
- StrikeLinesDialog/CorrectionEntryDialog line rows switch bare 1fr grid
tracks to minmax(0,1fr) and wrap the sm:contents-promoted AccountCombobox
in a min-w-0 cell (SendInvoiceDialog's pattern).
- New dialog-overflow-risk ratchet in no-new-antipatterns.mjs: bare fr
tracks in dialog hosts, whitespace-nowrap inside DialogContent regions
outside an allowlist, and unportaled >=20rem overlays; baselined at the
post-fix 7 files.
Copy reduction (convention 7, MatchVoucherDialog precedent):
- New shared RattelseExplainer (HelpPopover) carries the "a posted
verifikat cannot be edited directly" framing once; CorrectionEntryDialog,
StrikeLinesDialog, RecordateEntryDialog and CorrectMetadataDialog drop
their permanent inline explainer boxes and keep at most one sentence
inline (hardcoded Swedish: verifikat surface).
- SendInvoiceDialog keeps the actual addresses inline and moves the fixed
CC/BCC framing plus the extra-address rules behind a HelpPopover
(recipient_additional_hint replaced by recipient_help_fixed and
recipient_help_additional in both messages files).
- HelpPopover panels gain pointer-events-auto and the companion marker so
they are actually interactive inside modal dialogs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(bookkeeping): mechanism-accurate rattelse copy and calmer dropdown repositioning
The shared RattelseExplainer claimed every rattelse is logged with who/when
in the verifikat's rattelsehistorik, which is only true for the inline
strike-and-replace track (StrikeLinesDialog, CorrectMetadataDialog). The
storno dialogs (CorrectionEntryDialog, RecordateEntryDialog) never write
that log: their BFL 5 kap 5 trail is the storno chain. The shared component
now keeps only the universally true framing sentence, and each dialog's
popover carries the trail sentence matching its own mechanism.
AccountCombobox's capture-phase scroll/resize handler now skips setState
when the recomputed position is shallow-equal to the current one
(isSameDropdownPosition in the pure position helper, unit-tested) and
ignores scroll events originating inside the portaled panel itself, so
scrolling the account list no longer churns re-renders.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix(analytics): mask session replays by default, chrome-only unmask
Invert PostHog session-replay masking from visible-by-default with pattern
masking to deny-by-default: every input value is masked wholesale (rrweb
maskAllInputs, no maskInputFn) and every text node is masked unless it sits
under data-ph-unmask chrome or a table column header (th). Chrome tags live
on the shared UI primitives (PageHeader, Label, Button except combobox
triggers, TabsTrigger, Badge, Card/Dialog/Sheet titles, tooltips, help
popovers, empty states, settings labels), and tagged chrome is still
pattern-scrubbed for amounts and person-/organisationsnummer. data-ph-mask
beats data-ph-unmask, so call sites that interpolate user data into chrome
stay masked; a very-thorough audit swept every unmasked primitive and each
found site got a call-site mask. Confirm-dialog wrappers and toasts stay
masked centrally: their copy describes user objects by design. Untagged new
UI over-masks instead of leaking. Privacy policy, RoPA and decision log
updated in the same change.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(analytics): tag detail-section chrome merged from main
The register-detail primitives landed on main after the replay-masking
audit ran: kickers and DefRow labels are static i18n chrome, values stay
masked.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(analytics): close skeptic and review findings on replay masking
Explicit data-ph tags now resolve before the th chrome fallback, so a th
nested inside a data-ph-mask container masks correctly (regression test
added). Seven missed text-leak sites get call-site masks: delete-invoice
and credit-page invoice numbers, IB-correction voucher reference, TIC
orgnr (served unnormalized, so the separator-based scrub cannot be relied
on), articles search-term empty state, dimension segment labels, and
activate-account buttons. The attribute channel is closed with rrweb's
blockClass: inputs whose placeholder carries an effective user value
(salary overrides, correction description, danger-zone confirms, credit
confirm) get ph-no-capture, removing the element from recordings while
the prefill UX stays intact; the pivot-th title attribute is dropped.
Privacy-policy effective date bumped to 2026-08-17.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix(design): stop synthesizing bold on Hedvig display headings
Hedvig Letters Serif ships weight 400 only, but the h1-h3 base rule
forced font-weight 500 and DialogTitle/SheetTitle stacked font-semibold
on top, so every display heading rendered browser-synthesized bold: the
smudged heavy look on dialog titles and page headings. Drop the base
rule to 400, remove the weight utilities from the title primitives, and
sweep the 41 files that hand-set font-medium/semibold/bold on serif
headings (a pattern design.md already forbids). Headings that opt into
font-sans keep their weight.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(design): drop empty className left by the weight sweep
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Fixed user issues
* feat: add personal_number column to customers for individual identification
* feat: add personal_number field to makeCustomer function for enhanced customer identification
* feat: add personal_number column with constraint check for customer identification