Patterns
Prose links
Inline links inside flowing text are styled through the .prose class on the container element. This approach scopes the link style to reading contexts only; card layouts, nav elements, and list templates are deliberately excluded.
Visual appearance:
| State | Colour | Underline |
|---|---|---|
| Default | --color-mid (#366867) | Teal tint, 1.5px, offset 0.15em |
| Hover | --color-primary (#71b8b8) | Solid, 2px |
| Mobile | --color-mid | Always underlined (reinforced via responsive.css) |
The rule in docs.css:
.prose a:not(.btn):not(.agenda-program__link) { ... }
.prose a:not(.btn):not(.agenda-program__link):hover { ... }
Where .prose is applied
Add .prose only to containers that render flowing markdown. Card and list templates omit it intentionally; their <a> elements are structural, not inline text links.
| Template | Element |
|---|---|
layouts/docs/single.html | <article class="docs__body content prose"> |
layouts/blog/single.html | <article class="content prose"> |
layouts/_default/single.html | <article class="content prose"> |
layouts/contact/single.html | <article class="content prose"> |
layouts/user-day/single.html | <article class="content prose"> |
layouts/stream/single.html | <article class="content stream-content prose"> |
layouts/samm-identity/single.html | <article class="docs__body content prose"> |
layouts/internal/single.html | <article class="docs__body content prose"> |
layouts/practice/single.html | <div class="practice-description prose"> — scoped to description only |
Do not add .prose to: docs/list.html, business-function/single.html, or any template whose <article> contains card-style <a> elements.
.content a? The old pattern used .content a:not(… 8 exclusions …). Every new card component required a new exclusion. The .prose approach inverts the logic: opt in at the container level rather than opt out per component. Adding a new card layout inside a prose container is now the exceptional case, handled by adding to the :not() list.Adding a new exclusion
If a new card-style link appears inside a .prose container and picks up unwanted underlines, add it to both the base rule and the :hover variant in docs.css:
.prose a:not(.btn):not(.agenda-program__link):not(.your-new-class) { ... }
.prose a:not(.btn):not(.agenda-program__link):not(.your-new-class):hover { ... }
BF-colored links
Links on model pages inherit their color from the business function context rather than from .prose.
How it works:
- A wrapper element has
--bf-colorand--bf-color-lightset (via a.model-bf--*or.skills-bf-group--*class). - Links inside inherit:
color: var(--bf-color). - Hover shifts to:
color: var(--bf-color-light).
Override rules use deep descendant selectors (specificity 0-7-2+) to win over .prose a without !important or hacks:
/* Practice stream heading links — high specificity to beat .prose a */
.docs .docs__content .docs__body.content .practice-content
.practice-streams .practice-stream h3 a { ... }
!important. When a BF-coloured link needs to override the prose rule, increase specificity by adding more ancestor selectors that already exist in the DOM. This makes the override traceable and reversible. A comment in the CSS should explain which component triggered the override.Navigation links
Links in navigational contexts — header, footer, sidebar, pager — follow different rules than prose links.
| Context | Underline | Colour | Notes |
|---|---|---|---|
| Header nav | None | Offwhite / mid-teal on hover | Nav links are self-evidently interactive |
| Footer | None | Muted; mid-teal on hover | Navigation context sufficient |
| Docs sidebar | None (is-active: bold + teal) | --color-text-light; primary on hover | Active state uses font-weight + color |
| Pager cards | None | Dark; teal on hover | Card border + chevron = affordance |
Practice stream h3 a | None on desktop; underline on mobile | BF color | Mobile rule in responsive.css for tap affordance |
Mobile underline rule for stream h3:
@media (max-width: 48rem) {
.docs.model-docs .docs__content .content.practice-content
.practice-streams .practice-stream h3 a {
text-decoration: underline;
text-decoration-color: currentColor;
text-underline-offset: 0.15em;
}
}
This is a mobile-only override; desktop stream headings rely on their BF color and position as headings to signal interactivity. Mobile adds underlines because hover states don’t exist and the heading color alone may not be sufficient affordance on a small screen.