/** spec §16 — ONE card shell, three laws. * * Every consent/status card in the product is this shell with different * CONTENTS: eyebrow · one-size icon well · title · the mandatory plain-words * line · field rows or a list · actions · byline. Standing-access and the * resolved record are contents only, and every surface that shows one (thread, * waiting strip, activities, mobile sheet, voice, embeds) renders the SAME * shell. * * The SENTENCE family — the approval ask (M1), the connect row (C2) and the * automation rule (A1) — is headless: its first line IS the card (a question, * a toolkit name, a rule), with one quiet line under it carrying the rest. * Those three wear no eyebrow and no icon well (connect shows the toolkit's * raw mark, deliberately not a well: the well cropped the Gmail M). They are * still this shell, and law 3 lives across each pair of lines. * * 1. Ancestors may set width/max-width on `.fl-cardshell` — never undress it. * 2. ONE icon well (28px), ONE primary button (`.fl-btn-primary`), ONE * ceremony button (`.fl-btn-ceremony`). No card wears the ceremony register * today: the approval ask carries irreversibility in plain words instead. * 3. The plain-words line is mandatory: a card always says what it DOES. * * Geometry lives in the `.fl-card-*` CSS. Some elements also * carry their legacy `.fl-approval*` / `.fl-grant` class: three suites, the * corpus harness and the thread's morph start-rect lookup select on those * names. They are markers only — the `.fl-card-*` rules are declared later in * the one stylesheet, so the shell's geometry always wins. * * Deliberately NOT re-exported from `chrome/index.ts`: the shell is internal * vocabulary (the export-surface test pins the public list), so surfaces * import this module directly. */ import { type HTMLAttributes, type ReactNode } from "react"; import type { CardFieldRow } from "./field-rows.js"; /** The eyebrow strings, once (six were hardcoded across the card files). Each card that joined the sentence family took its entry with it: the approval ask, the connect row and the automation rule are their own first line, so only the kinds that still wear a head are left here. */ export declare const CARD_EYEBROWS: { readonly standingAccess: "Standing access"; readonly resolved: "Approval"; readonly waiting: "Waiting on you"; }; /** What separates the facts on the sentence family's one quiet line (`ul.fl-approval-sub` — the ask, the press modal, the connect row). It leads every item but the first, as REAL text inside the `
  • `, where a CSS `content` rule used to draw it between them. Generated content is not invisible to a screen reader — Chromium puts it in the accessibility tree, and the item reads "· Permanent: Yes" either way. It is invisible to the CLIPBOARD: copying the line gave back "This makes a change you can’t undo, as you.asked in an app", every fact run into the next. Inside the item is the only place that fixes the copy and keeps the list a list — a separator BETWEEN the items is a text node whose parent is the `