PLW ContentFoundation 04
Palette
Type
Shape
Accent

Content · composition

Heading cluster & Eyebrow

The workhorse opener: an eyebrow label, a heading, and a lede, spaced as one unit so every section starts with the same rhythm. Left or centered. The eyebrow can carry an accent or a rule.

ALeft & centered

Established Counsel

Representation that reads the room

Mid-market firms expect their website to carry the same authority as the practice. The cluster sets that tone in the first three lines.

Now welcoming clients

A steady hand, on the record

Centered clusters anchor CTA bands and section openers. The lede caps its measure and centers with the heading.

Semantics & a11y

  • The heading is a real <h2> (or appropriate level); the eyebrow is a <p>, not a heading, so it never pollutes the document outline.
  • Decorative eyebrow rule is a CSS ::before, not announced.
  • Centered variant sets text-align and auto-margins the lede.

Token contract

--font-mono--font-display--font-body--text-xs--text-xl--color-muted--color-accent--space-3/4/8
// HeadingCluster.tsx
export function HeadingCluster({ eyebrow, title, lede, align = "start", level: H = "h2" }: ClusterProps) {
  return (
    <div data-align={align} className="flex flex-col gap-[var(--space-4)] data-[align=center]:items-center data-[align=center]:text-center">
      {eyebrow && <p className="font-[var(--font-mono)] text-[var(--text-xs)] uppercase tracking-[.16em] text-[var(--color-muted)]">{eyebrow}</p>}
      <H className="font-[var(--font-display)] text-[clamp(var(--text-3xl),4.5vw,var(--text-5xl))] leading-[var(--leading-tight)] text-[var(--color-fg)]">{title}</H>
      {lede && <p className="font-[var(--font-body)] text-[var(--text-xl)] leading-[var(--leading-snug)] text-[var(--color-muted)] max-w-[56ch]">{lede}</p>}
    </div>
  );
}

Content · type

Heading scale

Six levels in the display font. h1 and h2 are fluid (clamp); h3h5 step down the ramp; h6 switches to an uppercase body label. Each level re-tunes weight per type pairing so serifs and posters both read right.

Ah1 → h6
h1 · clamp(36 → 60px)

The verdict on craft

h2 · clamp(30 → 48px)

The verdict on craft

h3 · 30px

The verdict on craft

h4 · 24px

The verdict on craft

h5 · 20px
The verdict on craft
h6 · 16px uppercase label
The verdict on craft

Semantics & a11y

  • Use one <h1> per page; never skip levels for size, pick the level for meaning and the class for size.
  • text-wrap: balance keeps multi-line headings even.
  • h1/h2 clamp scales with viewport but is capped so it never overflows on mobile.

Token contract

--font-display--text-base…7xl--leading-tight--leading-snug--color-fg
// Heading.tsx — level (semantics) is independent of size (class).
type Lvl = 1|2|3|4|5|6;
const size: Record<Lvl, string> = {
  1: "font-[var(--font-display)] text-[clamp(var(--text-4xl),6vw,var(--text-6xl))] leading-[var(--leading-tight)]",
  2: "font-[var(--font-display)] text-[clamp(var(--text-3xl),4.5vw,var(--text-5xl))] leading-[var(--leading-tight)]",
  3: "font-[var(--font-display)] text-[var(--text-3xl)] leading-[var(--leading-snug)]",
  4: "font-[var(--font-display)] text-[var(--text-2xl)] leading-[var(--leading-snug)]",
  5: "font-[var(--font-display)] text-[var(--text-xl)]",
  6: "font-[var(--font-body)] text-[var(--text-base)] uppercase tracking-wide font-bold",
};
export function Heading({ level, as, className="", ...p }: { level: Lvl; as?: Lvl } & JSX.IntrinsicElements["h2"]) {
  const Tag = `h${as ?? level}` as keyof JSX.IntrinsicElements;
  return <Tag className={`text-[var(--color-fg)] ${size[level]} ${className}`} {...p} />;
}

Content · prose

Body & Lede

The reading scale. A lede opens at a larger size and tighter leading; body runs at relaxed leading with a capped measure for comfortable long-form reading, with inline links, bold, and sub-headings.

ALede + body

When a matter reaches our desk, the first thing we do is listen, because the facts a client thinks are minor are often the ones that decide the case.

Our practice was built on a simple idea: that careful preparation beats theatrics. We document everything, we rehearse every argument, and we never let a deadline set our strategy. The result is representation that feels calm even when the stakes are not.

How we work

Every engagement starts with a fixed-fee assessment so you know the road ahead before you commit. From there we build a plan, assign a lead, and give you a single point of contact who actually answers the phone.

That is the whole pitch. No jargon, no surprises on the invoice, no associate you have never met arguing your motion.

Semantics & a11y

  • Measure capped near 68ch (body) and 56ch (lede) for readability.
  • Relaxed leading on body, snug on lede; both read from --leading-* tokens.
  • Inline links keep an underline; bold uses real <strong>.

Token contract

--font-body--text-sm…xl--leading-snug--leading-relaxed--color-fg--color-accent--space-4/8
// Prose.tsx — wrap CMS/MDX output; one class styles the whole tree.
export const Lede = (p: JSX.IntrinsicElements["p"]) =>
  <p className="font-[var(--font-body)] text-[var(--text-xl)] leading-[var(--leading-snug)] text-[var(--color-muted)] max-w-[56ch]" {...p} />;

export const Prose = (p: JSX.IntrinsicElements["div"]) =>
  <div className={"max-w-[68ch] font-[var(--font-body)] text-[var(--text-base)] leading-[var(--leading-relaxed)] text-[var(--color-fg)]
    [&_p]:mb-[var(--space-4)] [&_a]:text-[var(--color-accent)] [&_a]:underline
    [&_h2]:font-[var(--font-display)] [&_h2]:text-[var(--text-2xl)] [&_h2]:mt-[var(--space-8)]"} {...p} />;

Content · emphasis

Blockquote

A pull quote in the display font with an accent rule, or centered for testimonial bands. The quote text inherits the display family so it bends with the type pairing; attribution sits quietly beneath.

ARuled & centered

They treated a stressful year like it was routine. That calm was worth more than any billboard promise.

Dana R. · Manufacturing client

The only firm that returned every call the same day.

Marcus L. · Real estate developer

Semantics & a11y

  • Real <blockquote> with attribution in <footer>.
  • Accent rule is a left border on the token, not an image; scales with --border-heavy.
  • Display-font quotes drop uppercase on poster pairings so long quotes stay readable.

Token contract

--font-display--text-2xl…4xl--color-fg--color-accent--color-muted--border-heavy--space-4/5
// Blockquote.tsx
export function Blockquote({ children, cite, center }: QuoteProps) {
  return (
    <blockquote className={center
      ? "text-center"
      : "border-l-[length:var(--border-heavy)] border-[var(--color-accent)] pl-[var(--space-5)]"}>
      <p className="font-[var(--font-display)] font-medium text-[var(--text-2xl)] leading-[var(--leading-snug)] text-[var(--color-fg)] mb-[var(--space-4)]">{children}</p>
      {cite && <footer className="text-[var(--text-sm)] text-[var(--color-muted)]">{cite}</footer>}
    </blockquote>
  );
}

Content · aside

Callout

A boxed aside for notes, tips, and warnings. Five tones drawn from the semantic tokens (neutral, accent, success, warning, danger), each tinted against the background so it reads on any palette.

ATones

Note

Neutral callout for general asides and footnotes within a page.

Tip

Accent callout to highlight a recommended path or a key benefit.

Filed successfully

Success confirms a completed action or a positive status.

Deadline approaching

Warning flags something time-sensitive that needs attention.

Action required

Danger marks an error or a blocking issue the user must resolve.

Semantics & a11y

  • Tone is paired with a title word and an icon, never color alone.
  • For live status, add role="status" (success/info) or role="alert" (danger) on the consuming element.
  • Tints use color-mix against --color-bg so contrast holds across palettes.

Token contract

--color-accent--color-success--color-warning--color-danger--color-surface--color-bg--color-border--radius-lg--space-4/5
// Callout.tsx
const tone = {
  neutral: "bg-[var(--color-surface)] border-[var(--color-border)] [&_svg]:text-[var(--color-accent)]",
  accent:  "bg-[color-mix(in_srgb,var(--color-accent)_12%,var(--color-bg))] border-[color-mix(in_srgb,var(--color-accent)_30%,var(--color-border))]",
  success: "bg-[color-mix(in_srgb,var(--color-success)_12%,var(--color-bg))] [&_svg]:text-[var(--color-success)]",
  warning: "bg-[color-mix(in_srgb,var(--color-warning)_14%,var(--color-bg))] [&_svg]:text-[var(--color-warning)]",
  danger:  "bg-[color-mix(in_srgb,var(--color-danger)_12%,var(--color-bg))] [&_svg]:text-[var(--color-danger)]",
};
export const Callout = ({ t="neutral", icon, title, children }) =>
  <div className={`flex gap-[var(--space-4)] p-[var(--space-5)] rounded-[var(--radius-lg)] border ${tone[t]}`}>
    <span aria-hidden className="shrink-0">{icon}</span>
    <div className="text-[var(--text-sm)] text-[var(--color-fg)]">{title && <p className="font-bold">{title}</p>}{children}</div>
  </div>;

Content · enumeration

Lists

Bulleted, check, numbered, and definition lists. Markers are drawn from tokens, so bullets are accent dots (square on brutalist), numbers sit in accent chips, and checks use the accent. Definition lists align term and detail in two columns.

AFour kinds

Bulleted

  • Fixed-fee initial assessment
  • A named lead on every matter
  • Same-day callbacks, in writing

Check

  • No associate you have never met
  • No surprises on the invoice

Numbered

  1. We listen, and document everythingA fixed-fee assessment of the facts.
  2. We build the plan and assign a lead
  3. We execute, and you always reach us

Definition

Retainer
An advance against future fees, replenished monthly.
Contingency
We are paid a share of the recovery, only if you win.

Semantics & a11y

  • Real <ul> / <ol> / <dl>; custom markers are CSS pseudo-elements, so the list semantics and count survive.
  • Numbered markers use counter(), not hardcoded digits, so reordering renumbers automatically.
  • Definition list stacks to one column on mobile.

Token contract

--color-accent--color-accent-fg--color-fg--color-muted--color-border--radius-pill--radius-sm--font-mono--space-3…9
// List.tsx — markers are pseudo-elements so list semantics survive.
const base = "font-[var(--font-body)] text-[var(--text-base)] leading-[var(--leading-normal)]
  text-[var(--color-fg)] flex flex-col gap-[var(--space-3)] max-w-[64ch] list-none p-0 m-0";

/* bullet: li::before is an accent dot (square under [data-shape=brutalist]) */
/* number: ol counter() in an accent chip; check: accent tick.            */
export const List = ({ variant="bullet", ...p }) =>
  variant === "number"
    ? <ol className={`${base} c-list--number`} {...p} />
    : <ul className={`${base} c-list--${variant}`} {...p} />;