--- /** * docs/02: "Title, description, date, topic pills, reading time." * * ONE LINK, AND THE WHOLE CARD IS ITS HIT AREA — the `PracticeCard` pattern, * for the same measured reason: the link wraps only the headline, so its * accessible name is the headline rather than the card's four elements, and a * `::after` stretched over the positioned card carries the click. Three of these * on `/` would otherwise be three links each announcing a date, two pills, a * reading time and a 150-character description. * * THE PARENT MUST NOT TRY TO STYLE THIS ROOT. Astro does not pass a parent's * scope attribute to a child's root element, so a grid's `.card { block-size: * 100% }` compiles against the parent's cid and never matches — `CLAUDE.md` * records this costing twice, and names `ArticleCard` as one of the next places * it would happen. The card sizes itself below; a parent supplies only * `display: grid` and `gap` on its own element. * * `readingTime` IS RENDERED WITH ITS UNIT AND IS NOT A CLAIM ABOUT THE PRACTICE. * §4 Forbidden bars counts of matters, hours mediated and years in practice — * a number describing how long an article takes to read is not in that family, * and `check:claims`'s `counts-and-tenure` pattern is scoped to the practice. * Do not reach for a matter count, a settlement rate, or a case figure here. */ import Pill from './Pill.astro'; import { TOPIC_LABELS, formatArticleDate, isoDate } from '../data/insights'; import type { InsightTopic } from '../data/insights'; interface Props { href: string; title: string; description: string; date: Date; topics: readonly InsightTopic[]; /** Minutes. */ readingTime: number; /** Explicit: docs/02 forbids skipped heading levels. */ level: 2 | 3; } const { href, title, description, date, topics, readingTime, level } = Astro.props; const H = `h${level}` as 'h2' | 'h3'; ---
{readingTime} min read
{title}

{description}

{ topics.length > 0 && ( ) }