| Field | Value |
|---|
| ID | FRD-040 |
| Owner | David Holmes |
| Status | Complete ✅ |
| Last Updated | 2026-05-26 |
| Target Release | v2.1.0 |
| Type | Refactor |
| Complexity | S |
Document Summary
Five inline style={{}} declarations in legal-proposed-order.tsx and legal-section-cover-page.tsx violate ADR-030, which mandates that all legal-document presentational styles live in legal-document.css. This FRD defines the work to extract those inline styles into CSS class rules, eliminating the violations and restoring a single source of truth for legal-document appearance.
Introduction
Overview
ADR-030 establishes that legal-document.css is the single source of truth for all legal-document styling. No legal component may use inline style={{}} for visual mechanics. This rule exists so that screen rendering and print output stay identical, and so that legal style changes propagate from one file. Five call sites currently violate this rule.
Goals
- Remove all inline
style={{}} from legal-proposed-order.tsx and legal-section-cover-page.tsx.
- Add equivalent CSS class rules to
legal-document.css.
- Verify that screen and print rendering remain pixel-identical before and after the change.
Non-Goals
- Redesigning legal component layout or spacing.
- Changing any visual appearance of legal documents.
- Auditing other components for ADR-030 compliance (covered by broader compliance tracking).
Scope
In Scope
| Item | Description |
|---|
legal-proposed-order.tsx line 257 | Inline style={{ marginTop: '2.5em' }} on the signature block wrapper. |
legal-section-cover-page.tsx line 89 | Inline style={{ on the outer section wrapper. |
legal-section-cover-page.tsx line 165 | Inline style={{ margin: '0 auto' }} on CoverImage. |
legal-section-cover-page.tsx line 188 | Inline style={{ margin: '0 auto 16pt' }} on inline CoverImage. |
legal-section-cover-page.tsx line 231 | Inline style={{ margin: '0 auto' }} on bottom CoverImage. |
legal-document.css | New class rules for extracted styles. |
Out of Scope
| Item | Reason |
|---|
| Other legal components | This FRD targets only the identified violations. |
| Print stylesheet changes | ADR-030 ensures screen equals print; the CSS classes will inherit print behavior from the existing cascade. |
| Design token additions | The values being extracted are fixed spacing values, not new tokens. |
Users and Pain Points
| User | Pain Point |
|---|
| Legal component maintainer | Cannot reason about legal styles from legal-document.css alone because some styles are scattered as inline declarations. |
| Print/PDF author | Inline styles may not behave identically across print engines, risking screen/print divergence. |
| ADR compliance reviewer | Must flag these violations in every audit, creating recurring noise. |
Definitions
| Term | Definition |
|---|
| ADR-030 | Architecture Decision Record mandating that all legal-document styles live in legal-document.css with no inline style={{}}. |
| Inline style | A React style={{}} prop that applies CSS directly to an element, bypassing the stylesheet cascade. |
| legal-document.css | The canonical stylesheet for all legal-document rendering, located at src/components/patterns/myfreelawyer/components/legal-document.css. |
Current State
The following inline styles exist in violation of ADR-030:
legal-proposed-order.tsx:257 — style={{ marginTop: '2.5em' }} adds spacing above the proposed-order signature block.
legal-section-cover-page.tsx:89 — style={{ applies conditional layout to the section wrapper (flex direction, gap).
legal-section-cover-page.tsx:165 — style={{ margin: '0 auto' }} centers a CoverImage in the header area.
legal-section-cover-page.tsx:188 — style={{ margin: '0 auto 16pt' }} centers an inline CoverImage with bottom spacing.
legal-section-cover-page.tsx:231 — style={{ margin: '0 auto' }} centers a CoverImage in the footer area.
These violations were identified in the ADR compliance report and tracked as tech debt item #81.
Proposed Solution
For each violation:
- Define a descriptive CSS class in
legal-document.css (e.g., .legal-proposed-order__signature-spacer, .legal-cover-page__image--centered).
- Replace the inline
style={{}} prop with the new className.
- For the conditional layout in
legal-section-cover-page.tsx:89, use a modifier class (e.g., .legal-cover-page__section--inline-images) toggled via className rather than a conditional style prop.
All new classes follow the existing BEM-like naming convention in legal-document.css.
Requirements
| ID | Priority | Requirement |
|---|
| ADR023-01 | P0 | Remove inline style={{}} from legal-proposed-order.tsx line 257 and replace with a CSS class. |
| ADR023-02 | P0 | Remove inline style={{}} from legal-section-cover-page.tsx lines 89, 165, 188, 231 and replace with CSS classes. |
| ADR023-03 | P0 | New CSS classes added to legal-document.css produce identical rendering to the inline styles they replace. |
| ADR023-04 | P0 | No visual regression in legal document Storybook stories. |
Functional Requirements
- The proposed-order signature block retains its
2.5em top margin via the new class .legal-proposed-order__signature-spacer.
- Cover-page images remain horizontally centered via
.legal-cover-page__image--centered with margin: 0 auto.
- Inline cover-page images retain their
16pt bottom margin via .legal-cover-page__image--centered-spaced.
- The conditional flex layout on the cover-page section wrapper uses a
.legal-cover-page__section--inline-images modifier class that applies display: flex; align-items: center; gap: 32px.
- The conditional
flex: 1 on the title block uses .legal-cover-page__title-block--flex.
Non-Functional Requirements
| Category | Requirement |
|---|
| Zero visual change | Before-and-after screenshots of all affected stories must be pixel-identical. |
| CSS specificity | New classes use the same specificity level as existing legal-document.css rules. No !important. |
| Print parity | Screen and print rendering remain identical per ADR-030. |
API/Interface Requirements
No public API changes. The component props remain unchanged; only internal className usage changes.
Accessibility Requirements
No accessibility impact. This is a pure refactor of style application mechanism with zero DOM or semantic changes.
Content and Documentation Requirements
- Update the ADR compliance report to mark these violations as resolved.
- No new documentation needed; the class names are internal implementation details documented by their position in
legal-document.css.
Dependencies
| Dependency | Type | Notes |
|---|
legal-document.css | Internal | Target file for new class rules. |
legal-proposed-order.tsx | Internal | Source of violation #1. |
legal-section-cover-page.tsx | Internal | Source of violations #2 through #5. |
| ADR-030 | Governance | The rule being enforced. |
Risks and Tradeoffs
| Risk | Likelihood | Impact | Mitigation |
|---|
| CSS specificity conflict causes unintended override. | Low | Medium | New classes follow the existing BEM naming and sit at the same specificity tier. Visual regression test catches mismatches. |
Conditional class toggling is less readable than conditional style. | Low | Low | The modifier-class pattern is already used elsewhere in legal-document.css and is the established convention. |
Open Questions
- Should the cover-page image centering classes be consolidated into a single utility class with a spacing modifier, or kept as separate classes? Leaning toward separate classes for clarity.
Acceptance Criteria
LLM Handoff Instructions
When implementing this FRD:
- Open
src/components/patterns/myfreelawyer/components/legal-document.css and add the new classes at the end of the relevant section (proposed-order styles near other .legal-proposed-order__* rules, cover-page styles near other .legal-cover-page__* rules).
- In
legal-proposed-order.tsx at line 257, replace style={{ marginTop: '2.5em' }} with className="legal-proposed-order__signature-spacer".
- In
legal-section-cover-page.tsx, replace each inline style with the corresponding class. For the conditional layout at line 89, use a ternary or clsx to toggle the modifier class.
- Check that no other inline
style props exist in either file by searching for style={{.
- Run
pnpm typecheck and pnpm vitest run --project unit.
- Run
pnpm build-storybook to confirm no build regressions.
- Visually inspect the legal document stories in Storybook to confirm identical rendering.
Decision Log
| Date | Decision | Rationale |
|---|
| 2026-05-26 | Extract inline styles to CSS classes rather than CSS custom properties. | The values are fixed spacing, not design tokens. Classes match the existing pattern in legal-document.css. |
| 2026-05-26 | Use BEM modifier classes for conditional layout. | Consistent with existing cover-page class naming. Avoids runtime style computation. |
Document History
| Version | Date | Author | Changes |
|---|
| 0.1 | 2026-05-26 | David Holmes | Initial draft. |