Theme Counsel

Blocks & themesPreview
@wabbit/tome-theme-counselv0.1.2

Counsel, a Tome theme for law firms and other advisors whose credibility is their product: a well-set printed document, Source Serif 4 with small-caps meta and light numerals, ruled ledgers, margin notes and a compliance label on every proof block. Four palettes (Vellum, Chancery, Sage, Slate) plus dark, self-hosted OFL fonts, activated by data-tome-theme="counsel".

Install
  1. Get a registry token from your credentials page. You need a purchase that includes this package, or a Craft Library membership.

  2. Add the registry and your token to the .npmrc at the root of your project, with your token in place of YOUR_TOKEN:

    @wabbit:registry=https://npm.wabbit.com/
    //npm.wabbit.com/:_authToken=YOUR_TOKEN
  3. Then install:

    npm install @wabbit/tome-theme-counsel

Overview

@wabbit/tome-theme-counsel

Counsel is a Tome theme for law firms first, then accountants, financial and tax advisors, consultants and medical specialists: advisors whose credibility is their product. Its stance is "well-set, and nothing to prove". It borrows the authority of a well-made printed document rather than a corporate website: Source Serif 4 at a book weight, a small-caps meta voice, light numerals, ruled ledgers instead of cards, margin notes, and a compliance label on every proof block. It ships four palettes (Vellum, Chancery, Sage, Slate), each in light and a derived dark.

This package is a theme (a ThemeManifest of kind: 'theme'). It owns no blocks. It declares the whole token surface blocks read, self-hosts its two OFL font families, and restyles blocks and chrome through their public hooks.

Layer: ui · Family / tier: themes / addon · Versioning: independent.

Install

pnpm add @wabbit/tome-theme-counsel

| Peer | Range | Required | |---|---|---| | @wabbit/tome-ui | >=0.18.0 <1.0.0 | yes | | @wabbit/tome-core | >=1.21.1 <2.0.0 | no (optional) |

@wabbit/tome-ui is a CSS-contract peer. Its tokens.css re-declares the var()-aliased Layer 2 under [data-tome-theme] and defines the fixed-band ink family this theme sets, and 0.18.0 is the release that ships the platform scroll reveal Counsel turns on. @wabbit/tome-core is needed only for the ./register subpath and the ThemeManifest type. The package imports no React and no Payload.

Counsel's treatments style hooks that the same release adds to the blocks it uses: the split hero's call link, photo label and caption line; the stat strip's note; the phase-ledger index and panel variants; the dated-ledger year precision, density, note and per-entry labels; the team-roster people variant; the testimonial quotes-grid; the FAQ's openFirst and calloutStyle: 'line'; the shared header-group hooks (data-block-header, data-block-eyebrow, data-block-heading, data-block-subtext); the dated-ledger chipPlacement: 'dateline'; the testimonial eyebrow and starred stat unit; the contact aside and form slot; the info-panel person note, h1 and label tokens; the new annotated-page block; chrome's data-nav-scrolled and footer fine print (with its inset), text rows (with emphasis and row groups) and pairs; and the forms stepsDisplay: 'stacked' and optionalMarker options. On older block packs the theme still applies, and those parts render with the blocks' own look.

Usage

Import the stylesheet once at the app root, after tome-ui's tokens, and activate the theme on <html>:

// app/layout.tsx
import '@wabbit/tome-ui/tokens.css'
import '@wabbit/tome-theme-counsel/styles.css'
import '@wabbit/tome-theme-counsel/fonts.css'
<html data-tome-theme="counsel">                                <!-- Vellum, light -->
<html data-tome-theme="counsel" data-tome-palette="chancery">   <!-- Chancery -->
<html data-tome-theme="counsel" data-tome-palette="slate" data-theme="dark">

With no data-tome-palette the theme renders Vellum. Counsel is designed light: a page is light paper with one dark band, the matter intake. data-theme="dark" gives a full dark page, derived from each palette's band colour; it is allowed, contrast-checked, and not the default. The intake band is dark in both modes, and its fields and button stay light.

To have the admin ThemeSwitcher, createThemeConfig() and other registry readers list it, register it on the server before building the Payload config:

import '@wabbit/tome-theme-counsel/register'

Header: Navbar 7, navTheme: 'light', and the lockup

Counsel's hero is light paper, so it expects the tome-chrome Header global's `navTheme` set to `'light'` with Navbar 7 (design version '7'). The header sits transparent over the hero at rest. Once the page scrolls, chrome writes data-nav-scrolled="true" on the nav, and Counsel compacts the header from 92px to 62px through Navbar 7's --tome-header-pad-block, with the name a step smaller and the tagline faded out. Navbar 7's curtain paints the scrim; Counsel sets it to a 94% ground with an 8px blur (--tome-header-curtain-bg, --tome-header-curtain-blur), squares it (--tome-header-curtain-radius: 0) and swaps its drop shadow for a hairline (--tome-header-curtain-shadow). The current page (aria-current="page", set by chrome) is ink under a 1px accent rule. Set the Header global's `menuLabel` ("Menu") and the menu button becomes a bordered pill with that label ([data-menu-label]). The hero and the practice page head pad their tops to clear the header.

The two-line brand ("Hollis & Marrow" over "Attorneys at law") is your LogoComponent, rendered in chrome's logo slot. Mark it up with the theme's lockup hooks:

<span data-counsel-lockup>
  <span data-counsel-lockup-name>
    Hollis <span data-counsel-mark>&amp;</span> Marrow
  </span>
  <span data-counsel-lockup-tagline>Attorneys at law</span>
</span>

The name is the serif at the book weight, the ampersand italic in the accent text colour, and the tagline the small-caps meta voice. The CTA is an ink pill that answers hover with a 3px accent underline; nav links are the UI face in muted ink.

Footer: footer 7 with backgroundColor: 'muted'

Set the Footer global to design version '7' and `backgroundColor: 'muted'`. Group labels are small caps; the text is the UI face. Use chrome's plain-text rows (data-footer-text-row) for offices and the telephone (mark an office name Bold, emphasis, and its address lines Continue the row above, groupWithPrevious, so each office reads as one tight group), a label/value pair (data-footer-pair) for hours, and `finePrint` for the attorney-advertising paragraphs. Their lead-ins (data-footer-fine-print-lead, "Attorney advertising.") are ink small caps. There is no footer CTA band: the intake is the page's close.

The intake

The matter intake is a contact block, variant estimate, with a tome-forms form in its form slot. Set the form's `stepsDisplay` to `'stacked'`: every step renders as a numbered fieldset (the number a light numeral in the band accent, the legend in small caps), with one submit and its submitNote beside it ("We reply within one business day"). Set the form's optionalMarker to (optional) for the muted marker. Put the confidentiality note in the contact block's aside. Fields are the light fixed surface with ink text; the submit is a light pill.

Scroll reveal

Counsel turns on tome-ui's opt-in platform scroll reveal (--tome-reveal: on) and maps its timing to its own, quieter values: --tome-reveal-rise 8px, --tome-reveal-duration 560ms, --tome-reveal-stagger 70ms, and --tome-reveal-ease the theme's ease-out. The reveal runs only where the site mounts the controller once in its root layout:

import { TomeReveal } from '@wabbit/tome-ui/reveal'

// inside <body>, once
<TomeReveal />

Without the controller nothing moves and nothing is hidden. Blocks that animate themselves (the process panel's scroll-follow) are skipped by the controller. data-tome-reveal="off" on <html>, a region or a block root turns it off there, and overrides the theme. Under reduced motion there is no reveal, no crossfade, no step-bar scale and no smooth scroll; the header still compacts, since that is a state change.

Fonts

Source Serif 4 (one variable face per style, roman and italic, carrying wght 200 to 900 and opsz 8 to 60) and Public Sans (400, 500) ship inside the package as latin-subset woff2 from fontsource 5.3.0, with their SIL OFL 1.1 licences (fonts/OFL-SourceSerif4.md, fonts/OFL-PublicSans.md). There is no third-party font request. Pick one delivery path:

  • import '@wabbit/tome-theme-counsel/fonts.css': the bundler resolves the files from this package.
  • Your own host: copy the files from @wabbit/tome-theme-counsel/fonts/* and inject getCounselFontStyles({ src }).
  • next/font/local, using the file list from getCounselFontFaces().
import { getCounselFontPreloads } from '@wabbit/tome-theme-counsel/fonts'

// in <head>: preload the serif roman and the 400 UI face
{getCounselFontPreloads({ src: '/fonts/counsel/' }).map((l) => <link key={l.href} {...l} />)}

The serif sets display, headings, running prose and the small caps; Public Sans is the UI face only (buttons, nav, form labels and fields, hints, compliance labels, margin notes, captions, the footer's small print). Every --font-* slot is declared with its paired --tome-type-* alias on the theme selector (amendment A4.1). The fontsource files carry no smcp feature, so the small caps are synthesized by the browser, exactly as in the approved design. The treatments already ask for all-small-caps and oldstyle-nums, so a font build with true small caps would show them with no CSS change.

The laid-paper effect

There is one opt-in effect: faint horizontal laid lines on the page ground, the texture of a writing paper. It is static, Vellum only (the other palettes and dark mode declare its ink transparent), and off on the intake band and the footer.

<html data-tome-theme="counsel" data-counsel-effect="laid-paper">
<section data-counsel-effect="laid-paper">…</section>

Sites can also make their own section the dark band with data-counsel-band="dark", mark a meta line with data-counsel-meta (small caps), and colour a section or paragraph mark with data-counsel-mark.

Public API

| Export | Subpath | Purpose | |---|---|---| | counselThemeManifest (ThemeManifest) | ., ./manifest | The theme's manifest: name counsel, kind: 'theme', tier addon, four palettes, fonts and one pairing, recommended blocks and chrome (Navbar 7, footer 7), styledBlocks, requires.tomeUi. | | COUNSEL_PALETTE_IDS, CounselPaletteId | ., ./manifest | ['vellum', 'chancery', 'sage', 'slate'], the data-tome-palette values. | | COUNSEL_STYLED_BLOCKS, COUNSEL_RECOMMENDED_BLOCKS | ., ./manifest | The block slugs the theme restyles, and the slugs its demo is composed from. | | ThemeManifest (type) | . | Re-exported from @wabbit/tome-core/registry/theme. | | getCounselFontFaces(), getCounselFontStyles({ src }), getCounselFontPreloads({ src }) | ., ./fonts | Font descriptors, @font-face CSS for a custom host, and preload links. | | COUNSEL_FONT_STACKS, COUNSEL_FONT_LICENSES, COUNSEL_LATIN_UNICODE_RANGE, COUNSEL_SERIF_WEIGHTS, COUNSEL_UI_WEIGHTS | ., ./fonts | The CSS stacks the tokens use, the licence file per family, the subset range, and the weights used. | | CounselFontFace, CounselFontPreloadDescriptor, CounselFontStylesOptions (types) | ., ./fonts | The descriptor shapes. | | side effect | ./register | Registers counselThemeManifest in tome-core's theme registry. | | stylesheet | ./styles.css | Tokens, treatments and the effect. The file that does everything visual. | | stylesheet | ./fonts.css | The four @font-face rules. Optional. | | font files | ./fonts/* | The woff2 files and their OFL licences, for self-hosting. |

import { counselThemeManifest } from '@wabbit/tome-theme-counsel/manifest'

counselThemeManifest.palettes.map((p) => p.label)
// ['Vellum', 'Chancery', 'Sage', 'Slate']

Tokens

The theme sets Layer 1 (the names tome-ui's tokens.css reads: --background, --foreground, --card, --primary, --accent, --muted, --border, --input, --ring, the feedback, chart and muted2 names) and lets tome-ui's generated re-resolution derive the aliased Layer 2. It sets these Layer-2 literals directly, because no Layer-1 input sits behind them:

  • --tome-color-accent-text and the feedback *-text weights, and --tome-color-surface-tint (a step lighter than tome-ui's alias to --muted)
  • the fixed-band inks: --tome-color-surface-solid-dark, --tome-color-on-solid-dark, --tome-color-on-solid-dark-muted, --tome-color-accent-on-solid-dark, --tome-color-primary-on-solid-dark, --tome-color-border-inverse, and the light fixed surface --tome-color-surface-inverse with --tome-color-on-inverse, --tome-color-on-inverse-muted, --tome-color-accent-on-inverse, --tome-color-primary-on-inverse
  • the four --tome-type-* families, each paired with its --font-* slot

The dark band (the intake) is each palette's band colour. The light fixed surface (the intake fields) is the palette's card and ink. tome-ui's "inverse" is the light fixed surface; the dark band is "solid-dark".

Selector ladder (specificity, never load order):

| Selector | Specificity | Holds | |---|---|---| | [data-tome-theme="counsel"] | 0,1,0 | Vellum light, type, radius, rhythm, motion | | [data-tome-theme="counsel"][data-theme="dark"] | 0,2,0 | Vellum dark | | [data-tome-theme="counsel"][data-tome-palette="p"] | 0,2,0 | palette light | | [data-tome-theme="counsel"][data-tome-palette="p"][data-theme="dark"] | 0,3,0 | palette dark |

Every palette rule, light and dark, declares the full set: Layer 1, the literals, the band inks and three private tokens: --counsel-rule-strong (the heavy ink rule; tome-ui has no such token), --counsel-placeholder (placeholder ink on a light field) and --counsel-grain-ink (the laid-paper ink, transparent outside Vellum light). Other private tokens use the --counsel-* prefix: prose and meta sizes, numeral sizes, the UI sizes, display tracking, the header heights, rule and row geometry, the portrait and photo filters, control heights, the reveal timing (mapped onto tome-ui's --tome-reveal-*), and the grain pitch.

Shape and rhythm. --radius 2px; --tome-radius-sm and md 2px, lg and xl 3px, full 999px for actions only. No shadows anywhere: rules do the work. One section rhythm (--tome-section-py, 64 to 108px), a 600px prose measure, and tome-ui's grid unchanged. tome-ui sets the root at 18px, so the approved mockups' 16px-root sizes are converted by 16/18: the body is 1rem here (18px) and running prose 1.056rem (19px).

Palettes

| Palette | Ground / card | Ink / muted | Accent / accent text | Band | |---|---|---|---|---| | Vellum (default) | #F4EFE4 / #FBF8F2 | #1C1915 / #564D42 | oxblood #7B1E2A / #7B1E2A | #231E19, band accent #D98C8F | | Chancery | #F8F9FB / #FFFFFF | navy #14213A / #4A5568 | gold #A88641 / #7D6127 | #14213A, band accent #D9BC78 | | Sage | #EDF0E8 / #F8F9F5 | #1B2D21 / #48584C | terracotta #A85634 / #94472B | #1B2D21, band accent #E4A589 | | Slate | #EEF0F2 / #F9FAFB | #1B2127 / #4D555C | teal #197C7C / #0C696B | #1C242A, band accent #80CAC5 |

The accent is punctuation: rules, the active step bar, hover underlines, the compliance label's 2px start rule, section and paragraph marks, quotation marks, units and the ampersand. It is never a large fill.

Contrast

All ratios are WCAG 2.x. Text must reach at least 4.5. Input outlines, accent marks and the focus ring must reach at least 3. The test suite re-measures these floors from the shipped values.

| Pair | Vellum | Chancery | Sage | Slate | |---|---|---|---|---| | body on ground / card | 15.27 / 16.52 | 15.24 / 16.05 | 12.63 / 13.75 | 14.21 / 15.54 | | muted on ground / card | 7.22 / 7.81 | 7.14 / 7.53 | 6.57 / 7.15 | 6.64 / 7.26 | | accent text on ground / card | 8.88 / 9.61 | 5.52 / 5.82 | 5.71 / 6.22 | 5.66 / 6.19 | | on-accent on an accent fill | 9.61 | 4.70 | 4.91 | 4.77 | | accent mark on ground | 8.88 | 3.24 | 4.51 | 4.36 | | input outline on card | 3.61 | 3.26 | 3.43 | 3.41 | | band ink / muted / accent | 13.80 / 7.89 / 6.37 | 14.18 / 8.39 / 8.72 | 12.81 / 7.44 / 6.95 | 13.77 / 8.00 / 8.37 | | placeholder on a light field | 5.65 | 5.46 | 5.19 | 5.26 | | dark mode: body on page / card | 13.80 / 12.47 | 14.18 / 12.69 | 12.81 / 11.32 | 13.77 / 12.27 |

Chancery's gold mark is the closest pass (3.24). It never carries meaning alone: the active step bar also inks the step's label.

What it styles

| Hook | Treatment | |---|---| | Chrome header (nav[data-nav-theme], nav[data-nav-scrolled="true"]) | The lockup hooks; nav links in the UI face (muted, ink on hover, [aria-current="page"] under a 1px accent rule); the ink-pill CTA through --tome-header-cta-*; the "Menu" pill ([data-menu-label]); the compact state through --tome-header-pad-block, the curtain's 94% scrim and 8px blur through --tome-header-curtain-bg and --tome-header-curtain-blur, a square curtain and a hairline through --tome-header-curtain-radius and --tome-header-curtain-shadow. | | high-impact-hero split | Small-caps kicker, the promise at the hero size (15ch), the lede, ink pills in the action row ([data-hero-actions]), the inline call ([data-hero-call], the number in ink over a hairline), the portrait plate (1:1, 4:5 from 768, the portrait filter) with its photo label, and the caption ([data-caption-meta] in small caps). | | proposal-stat-strip | The credibility numerals: headless ([data-stat-strip-headless]), each figure under a heavy ink rule, a light numeral with its unit at half size in the accent text colour, a UI-face caption, and the source note ([data-stat-note]) as a compliance label. | | phase-ledger index | The practice ledger ([data-phase-index], rows [data-phase-row]): hairline rules, the section numeral ([data-phase-num], sized through --tome-dossier-phase-index-num-size) with an accent section mark, the linked title, the muted line, and "Led by" and "Read section n" ([data-phase-outcome], [data-phase-link]) in small caps. | | phase-ledger panel | The process panel through the block's tokens (--tome-dossier-panel-top, -panel-media-height, -panel-fade 450ms, -panel-bar in the accent, -phase-panel-num-size): the photo filter on [data-phase-media], the step number in the accent text colour, the meta ([data-phase-meta]) in small caps; the step bar's tabs ([data-phase-tab]) as hairlines, "Step n" ([data-phase-tab] [data-phase-num]) in accent-text small caps over the serif title ([data-phase-title]), muted until active ([data-phase-active]). The crossfade starts only once the island is ready (data-panel-ready). | | dated-ledger rows | The matters ledger (photo, year numeral [data-ledger-year] sized through --tome-dossier-ledger-year-size, small-caps dateline with the matter type under "No. 1" in the same voice when the block sets chipPlacement: 'dateline' ([data-ledger-date] [data-ledger-chip], the gap through --tome-dossier-ledger-dateline-chip-gap), serif title, light figure, the per-entry compliance label in its own lane after the figure from 1024px through the block's label-lane tokens (--tome-dossier-ledger-label-cols / -areas, -label-media-cols / -areas), the note) and, with data-ledger-density="compact", the recognition ledger (smaller year, honour, issuer in the UI face, the person in small caps, tighter rows). | | team-roster people | The statement tile under a heavy rule; 4:5 portraits with the portrait filter and the photo label; the name ([data-person-name]) in the serif, the role ([data-person-role]) in small caps, admission line ([data-person-credential]) in the UI face, the fact ([data-person-fact]) in serif italic; empty cells ([data-roster-empty]) only from 1024px; four columns from 1024px (--tome-roster-people-cols); the header group ([data-block-header]) as a section opener: the label ([data-block-eyebrow]) in small caps, the heading ([data-block-heading]) at h2, the deck ([data-block-subtext]), on the page lanes from 1024px. | | testimonial quotes-grid | Quote cells ([data-testimonial-cell]) under heavy rules, serif quotes with accent-text curly marks, ink small-caps attribution, labels; the stat tile ([data-testimonial-stat]) on the tinted surface with an accent top rule, its value ([data-testimonial-stat-value]) a light numeral with its starred unit ([data-testimonial-stat-unit]) at 0.45em through --tome-testimonial-stat-unit-size; four columns from 1024px (--tome-testimonial-grid-cols); the eyebrow ([data-block-eyebrow]) as the small-caps label and the section title as the heading, on the page lanes from 1024px. | | faq | Hairline-ruled questions ([data-faq-item]), "Q. n" in accent-text small caps from a CSS counter on [data-faq-question], a light accent plus that turns 45 degrees, muted answers ([data-faq-answer]) indented to the question, the badge ([data-block-eyebrow]) as the small-caps label, and, with calloutStyle: 'line' ([data-faq-callout-style="line"]), the bridge as a plain serif line with an accent-text link ([data-faq-callout-link]); the box style keeps the block's own look. From 1024px the header group ([data-block-header]) sits on the page lanes and the list and callout ([data-faq-callout]) in the reading column. Set calloutStyle: 'line' on a Counsel site. | | contact estimate | The page's one dark band and its opener, the confidentiality aside ([data-contact-aside], its label in small caps, in the right margin lane from 1024px), and the stacked form in the form slot ([data-contact-form-slot]): numbered legends ([data-form-step-legend], [data-form-step-number]), UI-face labels, light 48px fields with the placeholder ink, the light submit pill with the promise beside it ([data-form-submit-note]), the muted (optional) marker ([data-field-optional], through --tome-forms-optional-color and -weight). | | info-panel | The practice page head: the crumb ([data-section-label], its link [data-section-label-link] and the rest [data-section-label-rest]) in serif small caps through --tome-info-panel-label-font, -case, -tracking and -caps, the page title, the deck, and the fact card under a heavy rule: 72px portrait or the initials tile ([data-panel-initials]), the photo-label line ([data-panel-person-note]), small-caps terms over UI-face values, an accent-text link ([data-panel-cta]). | | annotated-page | The Annotated Page: a heavy rule above; the paragraph mark ([data-para-mark]) in small caps; prose ([data-annotated-body]) at the prose size; sub-headings; notes ([data-note-kind]) under a 1px accent rule from 768, an inset on a 2px accent start rule below it; the person note's initials tile ([data-note-initials]); citation numbers and markers ([data-cite-marker]) in the accent text colour. | | zone-directory | Other practices: the board ([data-zone-board]) unframed, its cells ([data-zone-cell]) under heavy rules, light section numerals ([data-zone-num]), serif titles ([data-zone-title]), muted lines ([data-zone-description]), "Read section n" ([data-zone-link]) in ink small caps. | | [data-compliance-label] (every block) | The one compliance-label look: a small UI-face line on a 2px accent start rule. Inside a photo it is the overlay on a 94% surface scrim. | | Chrome footer 7 | Small-caps group labels, the UI face, text rows, label/value pairs, and the fine print with ink small-caps lead-ins, sized through --tome-footer-fine-print-size, --tome-footer-fine-print-measure and --tome-footer-pair-label-min, and indented to the reading column from 1024px through --tome-footer-fine-print-inset; from 1024px the brand sits in the left margin lane and the link columns ([data-footer-nav]) start on the reading column; a text row's emphasis ([data-footer-text-strong], an office name) in ink, and grouped rows ([data-footer-row-group], an office and its address) set tight through --tome-footer-row-group-gap. |

Treatments target only public hooks: data-block-type on the block wrapper, data-block-variant on the root, the blocks' documented data-* part attributes, and published component tokens. Element names are used only where a block publishes no part hook (a quote's blockquote, the form fields inside the intake's form slot). They never target class names or structural chains such as > div:last-child. data-block-type is matched in its catalog form (high-impact-hero, not the stored highImpactHero), and a test fails any other form.

Server / client posture

The package is pure CSS plus constants. It has no React components and no 'use client' files, so it is inert under React Server Components. It adds nothing to a client bundle beyond the stylesheets the consumer imports. ./register is a server-side import.

Tests

pnpm --filter @wabbit/tome-theme-counsel test

The vitest suites cover:

  • the theme conformance check in theme mode (Layer-1 surface, *-text literals, radius and font slots, the full dark redeclaration, palette coverage, scoping, no module class names, font pairing) and in platform mode
  • manifest validation, its agreement with package.json, and registration
  • every palette defining the full required set in both modes, and the contrast floors re-measured from the shipped values
  • the A4.1 font pairing, and the self-hosted faces with their licences
  • no colour literal outside src/tokens/, no comment that swallows a rule, no structural or class selector, no drop shadow, and every treatment rule scoped to the theme
  • the reveal switch and timing, and each section's contract hooks

Exports

  • @wabbit/tome-theme-counsel
  • @wabbit/tome-theme-counsel/manifest
  • @wabbit/tome-theme-counsel/register
  • @wabbit/tome-theme-counsel/fonts
  • @wabbit/tome-theme-counsel/styles.css
  • @wabbit/tome-theme-counsel/fonts.css
  • @wabbit/tome-theme-counsel/fonts/*

Changelog

v0.1.2patch

e8213a7: Counsel's intake, footer and section openers now sit where the mockups put them from 1024px. - **Intake.** The form no longer overlaps the heading and deck. The `estimate` variant places its form card on rows 1 and 2 (and its call, hours and areas on row 2) from 1024px; the theme now resets both to `auto`, so the opener holds the first row and the form follows it in the reading column, with the confidentiality aside beside it in the right margin lane. With a `promise`, the promise leads the reading column and the aside runs beside the promise and the form. - **Confidentiality aside.** The note is the small UI-face size again and its label is ink. The deck rule matched the aside's paragraphs (the aside renders inside the intro) and set them at the deck size in muted ink; it now leaves the aside out. - **Footer 7.** From 1024px the link columns start on the reading column, as the fine print does, with the brand in the left margin lane. The nav no longer shrinks to make room for the brand column's width cap (it started 227px late at 1440). - **FAQ and people openers.** From 1024px the heading starts exactly on the reading column. The blocks' header `gap` became a column gap when the theme made the header a subgrid and moved the heading 2px. - **Intake submit row.** The submit button starts the row at the reading column, with the response promise after it, as in the mockup (it sat right of centre, the forms default). The theme sets tome-forms' new `--tome-forms-submit-justify` and, for earlier forms releases, the row's alignment directly.

  • e8213a7: Counsel's intake, footer and section openers now sit where the mockups put them from 1024px. - **Intake.** The form no longer overlaps the heading and deck. The `estimate` variant places its form card on rows 1 and 2 (and its call, hours and areas on row 2) from 1024px; the theme now resets both to `auto`, so the opener holds the first row and the form follows it in the reading column, with the confidentiality aside beside it in the right margin lane. With a `promise`, the promise leads the reading column and the aside runs beside the promise and the form. - **Confidentiality aside.** The note is the small UI-face size again and its label is ink. The deck rule matched the aside's paragraphs (the aside renders inside the intro) and set them at the deck size in muted ink; it now leaves the aside out. - **Footer 7.** From 1024px the link columns start on the reading column, as the fine print does, with the brand in the left margin lane. The nav no longer shrinks to make room for the brand column's width cap (it started 227px late at 1440). - **FAQ and people openers.** From 1024px the heading starts exactly on the reading column. The blocks' header `gap` became a column gap when the theme made the header a subgrid and moved the heading 2px. - **Intake submit row.** The submit button starts the row at the reading column, with the response promise after it, as in the mockup (it sat right of centre, the forms default). The theme sets tome-forms' new `--tome-forms-submit-justify` and, for earlier forms releases, the row's alignment directly.
v0.1.1patch

6e0c217: Fixes from the Counsel starter demo, measured against the v2 mockups and written on the hooks and tokens the blocks, chrome and forms now publish. - **Compact header no longer turns pink in Chromium.** Every `color-mix()` toward `transparent` (the header scrim, the photo labels, the text selection) now mixes in oklab. In oklch, the missing hue of `transparent` carried into the result, and Chromium painted the near-neutral ground at hue 0. A test bans `color-mix(in oklch, … transparent)` anywhere in the theme. - **Section openers.** The FAQ, the people grid and the quotes-grid open like every other labelled section through the shared header-group hooks (`data-block-header`, `data-block-eyebrow`, `data-block-heading`, `data-block-subtext`): the label in small caps, the heading at the h2 size, the deck. From 1024px each header group is a subgrid of the page, so the label sits in the left margin lane and the heading runs from the reading column. - **FAQ.** With `calloutStyle: 'line'` (`data-faq-callout-style="line"`), the bridge is the mockup's plain line: a serif sentence and an accent-text link (`data-faq-callout-link`) with an arrow. Set it on a Counsel site; the box style keeps the block's own panel and button. From 1024px the list and the callout (`data-faq-callout`) sit in the reading column. - **Intake.** The confidentiality aside's label (the aside's own `<p>`) is set in serif small caps, and its body in small UI-face type. From 1024px the band draws the page's lanes: the label in the left margin, the heading and form in the reading column, the aside in the right margin lane, sticky. Form rules key on `data-contact-form-slot`. The band is padded once, on the section. The `(optional)` marker is muted and regular through `--tome-forms-optional-color` and `--tome-forms-optional-weight`. - **Matters ledger.** With `chipPlacement: 'dateline'`, the matter type sits under "No. 1" in the dateline's small caps (`[data-ledger-date] [data-ledger-chip]`), with no pill or bullet. - **Client voice.** Four columns from 1024px (`--tome-testimonial-grid-cols: 4`). The `eyebrow` is the small-caps label and the section title the heading. The starred stat unit is 0.45em through `--tome-testimonial-stat-unit-size`. - **People.** Four columns from 1024px (`--tome-roster-people-cols: 4`), on the variant's content lane. - **Footer 7.** A text row's emphasis (`data-footer-text-strong`, the office names) is ink at 500, and grouped rows (`data-footer-row-group`) sit tight (`--tome-footer-row-group-gap: 0`). From 1024px the columns and the fine print start on the reading column (`--tome-footer-fine-print-inset`), the fine print keeping its 600px text measure. - **Practice page head.** The crumb is the serif in small caps through `--tome-info-panel-label-font`, `-case`, `-tracking` and `-caps`, the linked part and the rest (`data-section-label-link`, `data-section-label-rest`) in the same voice. "Book a consultation" (`data-panel-cta`) is an accent-text link with an arrow, not a full-width filled button. - **Other practices.** Cells are reached by `data-zone-cell`. Column tokens are set only inside media queries, since the blocks apply them at every width.

  • 6e0c217: Fixes from the Counsel starter demo, measured against the v2 mockups and written on the hooks and tokens the blocks, chrome and forms now publish. - **Compact header no longer turns pink in Chromium.** Every `color-mix()` toward `transparent` (the header scrim, the photo labels, the text selection) now mixes in oklab. In oklch, the missing hue of `transparent` carried into the result, and Chromium painted the near-neutral ground at hue 0. A test bans `color-mix(in oklch, … transparent)` anywhere in the theme. - **Section openers.** The FAQ, the people grid and the quotes-grid open like every other labelled section through the shared header-group hooks (`data-block-header`, `data-block-eyebrow`, `data-block-heading`, `data-block-subtext`): the label in small caps, the heading at the h2 size, the deck. From 1024px each header group is a subgrid of the page, so the label sits in the left margin lane and the heading runs from the reading column. - **FAQ.** With `calloutStyle: 'line'` (`data-faq-callout-style="line"`), the bridge is the mockup's plain line: a serif sentence and an accent-text link (`data-faq-callout-link`) with an arrow. Set it on a Counsel site; the box style keeps the block's own panel and button. From 1024px the list and the callout (`data-faq-callout`) sit in the reading column. - **Intake.** The confidentiality aside's label (the aside's own `<p>`) is set in serif small caps, and its body in small UI-face type. From 1024px the band draws the page's lanes: the label in the left margin, the heading and form in the reading column, the aside in the right margin lane, sticky. Form rules key on `data-contact-form-slot`. The band is padded once, on the section. The `(optional)` marker is muted and regular through `--tome-forms-optional-color` and `--tome-forms-optional-weight`. - **Matters ledger.** With `chipPlacement: 'dateline'`, the matter type sits under "No. 1" in the dateline's small caps (`[data-ledger-date] [data-ledger-chip]`), with no pill or bullet. - **Client voice.** Four columns from 1024px (`--tome-testimonial-grid-cols: 4`). The `eyebrow` is the small-caps label and the section title the heading. The starred stat unit is 0.45em through `--tome-testimonial-stat-unit-size`. - **People.** Four columns from 1024px (`--tome-roster-people-cols: 4`), on the variant's content lane. - **Footer 7.** A text row's emphasis (`data-footer-text-strong`, the office names) is ink at 500, and grouped rows (`data-footer-row-group`) sit tight (`--tome-footer-row-group-gap: 0`). From 1024px the columns and the fine print start on the reading column (`--tome-footer-fine-print-inset`), the fine print keeping its 600px text measure. - **Practice page head.** The crumb is the serif in small caps through `--tome-info-panel-label-font`, `-case`, `-tracking` and `-caps`, the linked part and the rest (`data-section-label-link`, `data-section-label-rest`) in the same voice. "Book a consultation" (`data-panel-cta`) is an accent-text link with an arrow, not a full-width filled button. - **Other practices.** Cells are reached by `data-zone-cell`. Column tokens are set only inside media queries, since the blocks apply them at every width.
v0.1.0minor

d7d0a32: New theme: Counsel, for law firms and other advisors whose credibility is their product, activated with `data-tome-theme="counsel"`. - Four palettes (Vellum, the default; Chancery; Sage; Slate), each in light and a derived dark, selected with `data-tome-palette`. Every palette sets Layer 1, the `*-text` literals, the tinted surface and the fixed-band ink family, contrast-checked (text at least 4.5:1; input outlines, accent marks and the focus ring at least 3:1). - Self-hosted OFL fonts: Source Serif 4 (one variable face per style, roman and italic, with the optical-size axis) for headings, prose and the small-caps meta voice, and Public Sans (400, 500) for the UI only, latin-subset woff2 with their licences, via `./fonts.css`, the `./fonts` descriptors or `./fonts/*` for your own host. Each `--font-*` slot is paired with its `--tome-type-*` alias. - Treatments through public hooks only: the Navbar 7 lockup and its compact state on scroll, the `split` hero with its portrait plate, the credibility numerals, the `index` practice ledger with section marks, the matters and compact recognition ledgers, the `panel` process step bar, the `people` grid, the `quotes-grid` client voice, the numbered FAQ, the dark intake band with a stacked form, the practice page head, the Annotated Page, the other-practices directory, footer 7 with its fine print, and one look for every compliance label. The accent is used only as punctuation, and nothing casts a shadow. - The platform scroll reveal is on, with Counsel's quieter timing (8px rise, 560ms, 70ms stagger); it runs only where the site mounts `TomeReveal`. - One opt-in effect: a laid-paper texture on the Vellum page ground (`data-counsel-effect="laid-paper"`). - `./register` adds the theme to tome-core's theme registry. Requires `@wabbit/tome-ui` 0.18.0 or later; `@wabbit/tome-core` is an optional peer.

  • d7d0a32: New theme: Counsel, for law firms and other advisors whose credibility is their product, activated with `data-tome-theme="counsel"`. - Four palettes (Vellum, the default; Chancery; Sage; Slate), each in light and a derived dark, selected with `data-tome-palette`. Every palette sets Layer 1, the `*-text` literals, the tinted surface and the fixed-band ink family, contrast-checked (text at least 4.5:1; input outlines, accent marks and the focus ring at least 3:1). - Self-hosted OFL fonts: Source Serif 4 (one variable face per style, roman and italic, with the optical-size axis) for headings, prose and the small-caps meta voice, and Public Sans (400, 500) for the UI only, latin-subset woff2 with their licences, via `./fonts.css`, the `./fonts` descriptors or `./fonts/*` for your own host. Each `--font-*` slot is paired with its `--tome-type-*` alias. - Treatments through public hooks only: the Navbar 7 lockup and its compact state on scroll, the `split` hero with its portrait plate, the credibility numerals, the `index` practice ledger with section marks, the matters and compact recognition ledgers, the `panel` process step bar, the `people` grid, the `quotes-grid` client voice, the numbered FAQ, the dark intake band with a stacked form, the practice page head, the Annotated Page, the other-practices directory, footer 7 with its fine print, and one look for every compliance label. The accent is used only as punctuation, and nothing casts a shadow. - The platform scroll reveal is on, with Counsel's quieter timing (8px rise, 560ms, 70ms stagger); it runs only where the site mounts `TomeReveal`. - One opt-in effect: a laid-paper texture on the Vellum page ground (`data-counsel-effect="laid-paper"`). - `./register` adds the theme to tome-core's theme registry. Requires `@wabbit/tome-ui` 0.18.0 or later; `@wabbit/tome-core` is an optional peer.